added gpx dialog

This commit is contained in:
Fedor Katurov 2020-01-24 16:53:47 +07:00
parent 947ec69e60
commit e995b46641
33 changed files with 11687 additions and 131 deletions

View file

@ -151,3 +151,18 @@ export const editorSetDirection = (drawing_direction: IEditorState['drawing_dire
type: EDITOR_ACTIONS.SET_DIRECTION,
drawing_direction,
});
export const editorSetGpx = (gpx: Partial<IEditorState['gpx']>) => ({
type: EDITOR_ACTIONS.SET_GPX,
gpx,
});
export const editorUploadGpx = (file: File) => ({
type: EDITOR_ACTIONS.UPLOAD_GPX,
file,
});
export const editorDropGpx = (index: number) => ({
type: EDITOR_ACTIONS.DROP_GPX,
index,
});

View file

@ -1,5 +1,12 @@
const P = 'EDITOR';
export const GPX_ROUTE_COLORS = [
'#ff3344',
'#3344ff',
'#33ff44',
'#33ffff',
];
export const DRAWING_DIRECTIONS: Record<'FORWARDS' | 'BACKWARDS', 'forward' | 'backward'> = {
FORWARDS: 'forward',
BACKWARDS: 'backward',
@ -61,4 +68,7 @@ export const EDITOR_ACTIONS = {
CAPTURE_HIPSTORY: `${P}-CAPTURE_HIPSTORY`,
SET_DIRECTION: `${P}-SET_DIRECTION`,
SET_GPX: `${P}-SET_GPX`,
UPLOAD_GPX: `${P}-UPLOAD_GPX`,
DROP_GPX: `${P}-DROP_GPX`,
};

View file

@ -187,6 +187,17 @@ const setDirection = (
drawing_direction,
});
const setGpx = (
state,
{ gpx }: ReturnType<typeof ACTIONS.editorSetGpx>
): IEditorState => ({
...state,
gpx: {
...state.gpx,
...gpx,
},
});
export const EDITOR_HANDLERS = {
[EDITOR_ACTIONS.SET_EDITING]: setEditing,
[EDITOR_ACTIONS.SET_CHANGED]: setChanged,
@ -219,4 +230,5 @@ export const EDITOR_HANDLERS = {
[EDITOR_ACTIONS.SET_HISTORY]: setHistory,
[EDITOR_ACTIONS.SET_DIRECTION]: setDirection,
[EDITOR_ACTIONS.SET_GPX]: setGpx,
};

View file

@ -2,10 +2,19 @@ import { createReducer } from '~/utils/reducer';
import { DIALOGS } from '~/constants/dialogs';
import { MODES } from '~/constants/modes';
import { EDITOR_HANDLERS } from './handlers';
import { ILatLng } from '../map/types';
// import { ILatLng } from '../map/types';
import { INominatimResult } from '~/redux/types';
import { IMapReducer } from '../map';
import { DRAWING_DIRECTIONS } from './constants';
import { LatLng } from 'leaflet';
export interface IGpxRoute {
latlngs: LatLng[],
enabled: boolean;
color: string;
name: string;
id: string;
}
export interface IEditorHistoryItem {
route: IMapReducer['route'];
@ -19,8 +28,8 @@ export interface IEditorState {
markers_shown: boolean;
router: {
points: ILatLng[];
waypoints: ILatLng[];
points: LatLng[];
waypoints: LatLng[];
};
mode: typeof MODES[keyof typeof MODES];
@ -70,6 +79,12 @@ export interface IEditorState {
records: IEditorHistoryItem[];
position: number;
};
gpx: {
enabled: boolean;
list: IGpxRoute[],
},
}
export const EDITOR_INITIAL_STATE = {
@ -130,6 +145,11 @@ export const EDITOR_INITIAL_STATE = {
records: [{ route: [], stickers: [] }],
position: 0,
},
gpx: {
enabled: true,
list: [],
},
};
export const editor = createReducer(EDITOR_INITIAL_STATE, EDITOR_HANDLERS);

View file

@ -8,7 +8,7 @@ import {
takeLeading,
delay,
} from 'redux-saga/effects';
import { selectEditor, selectEditorMode } from '~/redux/editor/selectors';
import { selectEditor, selectEditorMode, selectEditorGpx } from '~/redux/editor/selectors';
import { simplify } from '~/utils/simplify';
import {
editorHideRenderer,
@ -30,6 +30,8 @@ import {
editorSetHistory,
editorUndo,
editorRedo,
editorUploadGpx,
editorSetGpx,
} from '~/redux/editor/actions';
import { getUrlData, pushPath } from '~/utils/history';
import { MODES } from '~/constants/modes';
@ -38,7 +40,7 @@ import { LatLng } from 'leaflet';
import { searchSetTab } from '../user/actions';
import { TABS, DIALOGS } from '~/constants/dialogs';
import { EDITOR_ACTIONS, EDITOR_HISTORY_LENGTH } from './constants';
import { getGPXString, downloadGPXTrack } from '~/utils/gpx';
import { getGPXString, downloadGPXTrack, importGpxTrack } from '~/utils/gpx';
import {
getTilePlacement,
getPolyPlacement,
@ -62,6 +64,9 @@ import { OsrmRouter } from '~/utils/map/OsrmRouter';
import path from 'ramda/es/path';
import { MainMap } from '~/constants/map';
import { EDITOR_INITIAL_STATE } from '.';
import { Unwrap } from '~/utils/middleware';
import uuid from 'uuid';
import { getRandomColor } from '~/utils/dom';
const hideLoader = () => {
document.getElementById('loader').style.opacity = String(0);
@ -240,9 +245,9 @@ function* keyPressedSaga({ key, target }: ReturnType<typeof editorKeyPressed>) {
yield put(editorChangeMode(MODES.TRASH));
}
} else if (key === 'z') {
yield put(editorUndo())
yield put(editorUndo());
} else if (key === 'x') {
yield put(editorRedo())
yield put(editorRedo());
}
}
@ -368,6 +373,29 @@ function* redoHistory() {
yield put(editorSetHistory({ position: history.position + 1 }));
}
function* uploadGpx({ file }: ReturnType<typeof editorUploadGpx>) {
const gpx: Unwrap<typeof importGpxTrack> = yield importGpxTrack(file);
if (!gpx || !gpx.length) return;
const { list }: ReturnType<typeof selectEditorGpx> = yield select(selectEditorGpx);
yield put(
editorSetGpx({
list: [
...list,
...gpx.map(item => ({
enabled: true,
latlngs: item.latlngs,
color: getRandomColor(),
name: item.name || `Track #${list.length + 1}`,
id: uuid() as string,
})),
],
})
);
}
export function* editorSaga() {
yield takeEvery(EDITOR_ACTIONS.LOCATION_CHANGED, locationChangeSaga);
@ -397,4 +425,6 @@ export function* editorSaga() {
yield takeEvery(EDITOR_ACTIONS.UNDO, undoHistory);
yield takeEvery(EDITOR_ACTIONS.REDO, redoHistory);
yield takeEvery(EDITOR_ACTIONS.UPLOAD_GPX, uploadGpx);
}

View file

@ -10,3 +10,4 @@ export const selectEditorRouter = (state: IState) => state.editor.router;
export const selectEditorDistance = (state: IState) => state.editor.distance;
export const selectEditorNominatim = (state: IState) => state.editor.nominatim;
export const selectEditorDirection = (state: IState) => state.editor.drawing_direction;
export const selectEditorGpx = (state: IState) => state.editor.gpx;

View file

@ -1,7 +1,8 @@
import { MAP_ACTIONS } from './constants';
import { IMapReducer } from './';
import { IStickerDump } from '~/redux/map/types';
import { ILatLng } from './types';
import { LatLng } from 'leaflet';
// import { ILatLng } from './types';
export const mapSet = (map: Partial<IMapReducer>) => ({
type: MAP_ACTIONS.SET_MAP,
@ -39,7 +40,7 @@ export const mapDropSticker = (index: number) => ({
index,
});
export const mapClicked = (latlng: ILatLng) => ({
export const mapClicked = (latlng: LatLng) => ({
type: MAP_ACTIONS.MAP_CLICKED,
latlng,
});

View file

@ -4,4 +4,6 @@ export const selectMap = (state: IState) => state.map;
export const selectMapProvider = (state: IState) => state.map.provider;
export const selectMapLogo = (state: IState) => state.map.logo;
export const selectMapRoute= (state: IState) => state.map.route;
export const selectMapStickers = (state: IState) => state.map.stickers;
export const selectMapStickers = (state: IState) => state.map.stickers;
export const selectMapTitle= (state: IState) => state.map.title;
export const selectMapAddress = (state: IState) => state.map.address;

View file

@ -1,15 +1,9 @@
import { LatLng } from 'leaflet';
import { IRoutePoint } from '~/utils/gpx';
export type ILatLng = {
lat: number;
lng: number;
};
export type IMapRoute = ILatLng[];
export type IMapRoute = LatLng[];
export interface IStickerDump {
latlng: ILatLng;
latlng: LatLng;
set: string;
sticker: string;
angle?: number;
@ -18,10 +12,10 @@ export interface IStickerDump {
export interface IRoute {
version: number;
title: string;
title: string;
owner: number;
address: string;
route: IRoutePoint[];
route: LatLng[];
stickers: IStickerDump[];
provider: string;
is_public: boolean;

View file

@ -26,6 +26,12 @@ const userPersistConfig: PersistConfig = {
storage,
};
const editorPersistConfig: PersistConfig = {
key: 'editor',
whitelist: ['gpx'],
storage,
};
export interface IState {
user: IRootReducer;
map: IMapReducer;
@ -43,8 +49,8 @@ const composeEnhancers =
export const store = createStore(
combineReducers({
user: persistReducer(userPersistConfig, userReducer),
editor: persistReducer(editorPersistConfig, editor),
map,
editor,
}),
composeEnhancers(applyMiddleware(sagaMiddleware))
);

View file

@ -343,7 +343,7 @@ export function* updateUserRoutes() {
}
export function* userSaga() {
yield takeLatest(REHYDRATE, authCheckSaga);
yield takeEvery(REHYDRATE, authCheckSaga);
yield takeEvery(USER_ACTIONS.USER_LOGOUT, userLogoutSaga);
yield takeLatest(USER_ACTIONS.GOT_VK_USER, gotVkUserSaga);