current user location

This commit is contained in:
Fedor Katurov 2020-01-20 12:20:54 +07:00
parent 5e3aa587c7
commit a574b7393d
12 changed files with 205 additions and 77 deletions

View file

@ -4,11 +4,9 @@ import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import createSagaMiddleware from 'redux-saga';
import { createBrowserHistory } from 'history';
import { editorLocationChanged } from '~/redux/editor/actions';
import { PersistConfig, Persistor } from "redux-persist/es/types";
import { PersistConfig, Persistor } from 'redux-persist/es/types';
import { userReducer, IRootReducer } from '~/redux/user';
import { userSaga } from '~/redux/user/sagas';
@ -18,6 +16,9 @@ import { editorSaga } from '~/redux/editor/sagas';
import { map, IMapReducer } from '~/redux/map';
import { mapSaga } from '~/redux/map/sagas';
import { watchLocation, getLocation } from '~/utils/window';
import { LatLngLiteral } from 'leaflet';
import { setUserLocation } from './user/actions';
const userPersistConfig: PersistConfig = {
key: 'user',
@ -26,17 +27,16 @@ const userPersistConfig: PersistConfig = {
};
export interface IState {
user: IRootReducer
map: IMapReducer,
editor: IEditorState,
user: IRootReducer;
map: IMapReducer;
editor: IEditorState;
}
// create the saga middleware
export const sagaMiddleware = createSagaMiddleware();
// redux extension composer
const composeEnhancers =
typeof window === 'object' &&
(<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
typeof window === 'object' && (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose;
@ -49,7 +49,7 @@ export const store = createStore(
composeEnhancers(applyMiddleware(sagaMiddleware))
);
export function configureStore(): { store: Store<any>, persistor: Persistor } {
export function configureStore(): { store: Store<any>; persistor: Persistor } {
sagaMiddleware.run(userSaga);
sagaMiddleware.run(mapSaga);
sagaMiddleware.run(editorSaga);
@ -65,3 +65,5 @@ history.listen((location, action) => {
if (action === 'REPLACE') return;
store.dispatch(editorLocationChanged(location.pathname));
});
watchLocation((location: LatLngLiteral) => store.dispatch(setUserLocation(location)));

View file

@ -1,5 +1,6 @@
import { USER_ACTIONS } from '~/redux/user/constants';
import { IUser } from "~/constants/auth";
import { IRootReducer } from '.';
export const setUser = (user: IUser) => ({ type: USER_ACTIONS.SET_USER, user });
export const userLogout = () => ({ type: USER_ACTIONS.USER_LOGOUT });
@ -24,3 +25,5 @@ export const modifyRoute = (address: string, { title, is_public }: { title: stri
});
export const toggleRouteStarred = (address: string) => ({ type: USER_ACTIONS.TOGGLE_ROUTE_STARRED, address });
export const setRouteStarred = (address: string, is_published: boolean) => ({ type: USER_ACTIONS.SET_ROUTE_STARRED, address, is_published });
export const setUserLocation = (location: IRootReducer['location']) => ({ type: USER_ACTIONS.SET_USER_LOCATION, location });

View file

@ -5,7 +5,8 @@ export const USER_ACTIONS = {
GOT_VK_USER: 'GOT_VK_USER',
IFRAME_LOGIN_VK: 'IFRAME_LOGIN_VK',
SET_USER_LOCATION: 'SET_USER_LOCATION',
SEARCH_SET_TITLE: 'SEARCH_SET_TITLE',
SEARCH_SET_DISTANCE: 'SEARCH_SET_DISTANCE',
SEARCH_CHANGE_DISTANCE: 'SEARCH_CHANGE_DISTANCE',

View file

@ -1,7 +1,7 @@
import { IRootState } from ".";
import * as ActionCreators from './actions'
import { TABS } from "~/constants/dialogs";
import { USER_ACTIONS } from "./constants";
import { IRootState, IRootReducer } from '.';
import * as ActionCreators from './actions';
import { TABS } from '~/constants/dialogs';
import { USER_ACTIONS } from './constants';
type UnsafeReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
@ -17,7 +17,10 @@ const setUser: ActionHandler<typeof ActionCreators.setUser> = (state, { user })
},
});
const searchSetTitle: ActionHandler<typeof ActionCreators.searchSetTitle> = (state, { title = '' }) => ({
const searchSetTitle: ActionHandler<typeof ActionCreators.searchSetTitle> = (
state,
{ title = '' }
) => ({
...state,
routes: {
...state.routes,
@ -25,33 +28,42 @@ const searchSetTitle: ActionHandler<typeof ActionCreators.searchSetTitle> = (sta
...state.routes.filter,
title,
distance: [0, 10000],
}
}
},
},
});
const searchSetDistance: ActionHandler<typeof ActionCreators.searchSetDistance> = (state, { distance = [0, 9999] }) => ({
const searchSetDistance: ActionHandler<typeof ActionCreators.searchSetDistance> = (
state,
{ distance = [0, 9999] }
) => ({
...state,
routes: {
...state.routes,
filter: {
...state.routes.filter,
distance,
}
}
},
},
});
const searchSetTab: ActionHandler<typeof ActionCreators.searchSetTab> = (state, { tab = TABS[Object.keys(TABS)[0]] }) => ({
const searchSetTab: ActionHandler<typeof ActionCreators.searchSetTab> = (
state,
{ tab = TABS[Object.keys(TABS)[0]] }
) => ({
...state,
routes: {
...state.routes,
filter: {
...state.routes.filter,
tab: Object.values(TABS).indexOf(tab) >= 0 ? tab : TABS[Object.values(TABS)[0]],
}
}
},
},
});
const searchPutRoutes: ActionHandler<typeof ActionCreators.searchPutRoutes> = (state, { list = [], min, max, limit, step, shift }) => ({
const searchPutRoutes: ActionHandler<typeof ActionCreators.searchPutRoutes> = (
state,
{ list = [], min, max, limit, step, shift }
) => ({
...state,
routes: {
...state.routes,
@ -61,50 +73,68 @@ const searchPutRoutes: ActionHandler<typeof ActionCreators.searchPutRoutes> = (s
shift,
filter: {
...state.routes.filter,
distance: (state.routes.filter.min === state.routes.filter.max)
? [min, max]
: state.routes.filter.distance,
distance:
state.routes.filter.min === state.routes.filter.max
? [min, max]
: state.routes.filter.distance,
min,
max,
}
}
},
},
});
const searchSetLoading: ActionHandler<typeof ActionCreators.searchSetLoading> = (state, { loading = false }) => ({
const searchSetLoading: ActionHandler<typeof ActionCreators.searchSetLoading> = (
state,
{ loading = false }
) => ({
...state,
routes: {
...state.routes,
loading,
}
},
});
const setStarred: ActionHandler<typeof ActionCreators.setStarred> = (state, { is_published = false }) => ({ ...state, is_published });
const setStarred: ActionHandler<typeof ActionCreators.setStarred> = (
state,
{ is_published = false }
) => ({ ...state, is_published });
const mapsSetShift: ActionHandler<typeof ActionCreators.mapsSetShift> = (state, { shift = 0 }) => ({
...state,
routes: {
...state.routes,
shift,
}
},
});
const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (state, { address, is_published }) => ({
const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (
state,
{ address, is_published }
) => ({
...state,
routes: {
...state.routes,
list: (
state.routes.list
.map(el => el.address === address ? { ...el, is_published } : el)
.filter(el => (
list: state.routes.list
.map(el => (el.address === address ? { ...el, is_published } : el))
.filter(
el =>
(state.routes.filter.tab === TABS.STARRED && el.is_published) ||
(state.routes.filter.tab === TABS.PENDING && !el.is_published)
))
)
}
),
},
});
export const USER_HANDLERS = ({
const setLocation = (
state: IRootReducer,
{ location }: ReturnType<typeof ActionCreators.setUserLocation>
): IRootReducer => ({
...state,
location,
});
export const USER_HANDLERS = {
[USER_ACTIONS.SET_USER]: setUser,
[USER_ACTIONS.SET_USER_LOCATION]: setLocation,
[USER_ACTIONS.SEARCH_SET_TITLE]: searchSetTitle,
[USER_ACTIONS.SEARCH_SET_DISTANCE]: searchSetDistance,
@ -118,4 +148,4 @@ export const USER_HANDLERS = ({
[USER_ACTIONS.SET_STARRED]: setStarred,
[USER_ACTIONS.SET_ROUTE_STARRED]: setRouteStarred,
});
};

View file

@ -1,43 +1,44 @@
import { createReducer } from '~/utils/reducer';
import { DEFAULT_USER, IUser } from '~/constants/auth';
import { USER_HANDLERS } from './handlers';
import { LatLngLiteral } from 'leaflet';
export interface IRouteListItem {
address: string,
title: string,
distance: number,
is_public: boolean,
is_published: boolean,
updated_at: string,
address: string;
title: string;
distance: number;
is_public: boolean;
is_published: boolean;
updated_at: string;
}
export interface IRootReducer {
// ready: boolean,
user: IUser,
user: IUser;
location: LatLngLiteral;
routes: {
limit: 0,
loading: boolean,
list: Array<IRouteListItem>,
step: number,
shift: number,
limit: 0;
loading: boolean;
list: Array<IRouteListItem>;
step: number;
shift: number;
filter: {
title: string,
starred: boolean,
distance: [number, number],
author: string,
tab: string,
min: number,
max: number,
}
},
title: string;
starred: boolean;
distance: [number, number];
author: string;
tab: string;
min: number;
max: number;
};
};
}
export type IRootState = Readonly<IRootReducer>;
export const INITIAL_STATE: IRootReducer = {
user: { ...DEFAULT_USER },
location: null,
routes: {
limit: 0,
loading: false, // <-- maybe delete this
@ -52,7 +53,7 @@ export const INITIAL_STATE: IRootReducer = {
tab: '',
min: 0,
max: 10000,
}
},
},
};

View file

@ -34,6 +34,7 @@ import { selectUser, selectUserUser } from './selectors';
import { mapInitSaga } from '~/redux/map/sagas';
import { editorSetDialog, editorSetDialogActive } from '../editor/actions';
import { selectEditor } from '../editor/selectors';
import { getLocation, watchLocation } from '~/utils/window';
function* generateGuestSaga() {
const {
@ -343,8 +344,13 @@ export function* updateUserRoutes() {
yield put(searchSetTab(TABS.MY));
}
// function* getUserLocation() {
// yield call(watchLocation, ActionCreators.setUserLocation);
// }
export function* userSaga() {
yield takeLatest(REHYDRATE, authCheckSaga);
// yield takeLatest(REHYDRATE, getUserLocation);
yield takeEvery(USER_ACTIONS.USER_LOGOUT, userLogoutSaga);
yield takeLatest(USER_ACTIONS.GOT_VK_USER, gotVkUserSaga);

View file

@ -1,4 +1,5 @@
import { IState } from '~/redux/store'
export const selectUser = (state: IState) => state.user;
export const selectUserUser = (state: IState) => state.user.user;
export const selectUserUser = (state: IState) => state.user.user;
export const selectUserLocation = (state: IState) => state.user.location;