mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-24 18:46:40 +07:00
added map fitting
This commit is contained in:
parent
0314edd550
commit
bc34cf3876
12 changed files with 93 additions and 78 deletions
|
@ -10,7 +10,7 @@ const mapDispatchToProps = {
|
|||
editorStopEditing,
|
||||
};
|
||||
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width?: number };
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { };
|
||||
|
||||
export class CancelDialog extends React.Component<Props, void> {
|
||||
cancel = () => {
|
||||
|
@ -22,10 +22,8 @@ export class CancelDialog extends React.Component<Props, void> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { width } = this.props;
|
||||
|
||||
return (
|
||||
<div className="control-dialog bottom right" style={{ width }}>
|
||||
<div className="control-dialog bottom right">
|
||||
<div className="helper cancel-helper">
|
||||
<div className="helper__text danger">
|
||||
<Icon icon="icon-cancel-1" />
|
||||
|
|
|
@ -89,7 +89,7 @@ const mapDispatchToProps = {
|
|||
editorRouterSubmit: EDITOR_ACTIONS.editorRouterSubmit,
|
||||
};
|
||||
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width?: number };
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { };
|
||||
|
||||
const RouterDialogUnconnected: FC<Props> = ({
|
||||
editor: {
|
||||
|
@ -98,9 +98,8 @@ const RouterDialogUnconnected: FC<Props> = ({
|
|||
},
|
||||
editorRouterCancel,
|
||||
editorRouterSubmit,
|
||||
width,
|
||||
}) => (
|
||||
<div className="control-dialog bottom right" style={{ width }}>
|
||||
<div className="control-dialog bottom right">
|
||||
<div className={classnames('save-loader', { active: is_routing })} />
|
||||
|
||||
{!waypoints.length && noPoints({ editorRouterCancel })}
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||
import { copyToClipboard, getUrlData } from '~/utils/history';
|
||||
import { toTranslit, parseDesc } from '~/utils/format';
|
||||
import { TIPS } from '~/constants/tips';
|
||||
import { MODES } from '~/constants/modes';
|
||||
import { Icon } from '~/components/panels/Icon';
|
||||
import { Switch } from '~/components/Switch';
|
||||
|
||||
|
@ -12,6 +11,7 @@ import { connect } from 'react-redux';
|
|||
import { selectMap } from '~/redux/map/selectors';
|
||||
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||
import { selectEditorSave } from '~/redux/editor/selectors';
|
||||
import { MODES } from '~/constants/modes';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
map: selectMap(state),
|
||||
|
@ -19,11 +19,12 @@ const mapStateToProps = state => ({
|
|||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
editorCancelSave: EDITOR_ACTIONS.editorCancelSave,
|
||||
editorSetMode: EDITOR_ACTIONS.editorSetMode,
|
||||
editorSendSaveRequest: EDITOR_ACTIONS.editorSendSaveRequest,
|
||||
};
|
||||
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width: number };
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { };
|
||||
|
||||
interface State {
|
||||
address: string;
|
||||
|
@ -91,16 +92,19 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
|
|||
this.setState({ is_public: !this.state.is_public });
|
||||
};
|
||||
|
||||
componentWillUnmount = () => {
|
||||
this.props.editorCancelSave()
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, is_public, description } = this.state;
|
||||
const {
|
||||
save: { error, finished, overwriting, loading },
|
||||
width,
|
||||
} = this.props;
|
||||
const { host, protocol } = getUrlData();
|
||||
|
||||
return (
|
||||
<div className="control-dialog control-dialog-medium" style={{ width }}>
|
||||
<div className="control-dialog bottom right">
|
||||
<div className="helper save-helper">
|
||||
<div className={classnames('save-loader', { active: loading })} />
|
||||
|
||||
|
|
|
@ -25,21 +25,19 @@ const TrashDialogUnconnected: FC<Props> = ({
|
|||
<div className="control-dialog bottom right" style={{ width }}>
|
||||
<div className="helper trash-helper desktop-only">
|
||||
<div className="helper__text danger">
|
||||
<div className="big upper desktop-only">Удалить:</div>
|
||||
<div className="big upper desktop-only">Все изменения будут удалены!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="helper trash-helper">
|
||||
<div className="helper__buttons flex_1 trash-buttons">
|
||||
<div className="button-group">
|
||||
<div className="button router-helper__button" onClick={editorClearPoly}>
|
||||
Маршрут
|
||||
</div>
|
||||
<div className="button router-helper__button" onClick={editorClearStickers}>
|
||||
Стикеры
|
||||
</div>
|
||||
<div className="button router-helper__button" onClick={editorClearAll}>
|
||||
ВСЕ
|
||||
</div>
|
||||
<div className="button router-helper__button" onClick={editorClearPoly}>
|
||||
Маршрут
|
||||
</div>
|
||||
<div className="button router-helper__button" onClick={editorClearStickers}>
|
||||
Стикеры
|
||||
</div>
|
||||
<div className="button router-helper__button" onClick={editorClearAll}>
|
||||
ВСЕ
|
||||
</div>
|
||||
<div className="flex_1" />
|
||||
<div className="button primary router-helper__button" onClick={editorClearCancel}>
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import { Map } from 'leaflet';
|
||||
import { Map, LayerGroup, Layer, FeatureGroup } from 'leaflet';
|
||||
|
||||
export class MapContainer extends Map {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routeLayer.addTo(this);
|
||||
this.stickerLayer.addTo(this);
|
||||
}
|
||||
|
||||
disableClicks = () => {
|
||||
this.clickable = false;
|
||||
};
|
||||
|
@ -9,10 +15,23 @@ export class MapContainer extends Map {
|
|||
this.clickable = true;
|
||||
};
|
||||
|
||||
getVisibleBounds = () => {
|
||||
const layers = [this.routeLayer, this.stickerLayer];
|
||||
for (let i = 0; i < layers.length; i += 1) {
|
||||
const bounds = layers[i].getBounds();
|
||||
if (Object.keys(bounds).length == 2) return bounds;
|
||||
}
|
||||
};
|
||||
|
||||
public clickable = true;
|
||||
|
||||
public routeLayer = new FeatureGroup();
|
||||
public stickerLayer = new FeatureGroup();
|
||||
}
|
||||
|
||||
export const MainMap = new MapContainer(document.getElementById('canvas')).setView(
|
||||
[55.0153275, 82.9071235],
|
||||
13
|
||||
);
|
||||
|
||||
console.log('MAP', MainMap);
|
||||
|
|
|
@ -48,7 +48,7 @@ const RouteUnconnected: FC<Props> = memo(
|
|||
maxMarkers: isMobile() ? 50 : 150,
|
||||
smoothFactor: 3,
|
||||
})
|
||||
.addTo(MainMap)
|
||||
.addTo(MainMap.routeLayer)
|
||||
.on('distancechange', onDistanceChange)
|
||||
.on('vertexdragstart', MainMap.disableClicks)
|
||||
.on('vertexdragend', MainMap.enableClicks)
|
||||
|
@ -60,7 +60,7 @@ const RouteUnconnected: FC<Props> = memo(
|
|||
setLayer(interactive);
|
||||
|
||||
return () => {
|
||||
interactive.removeFrom(MainMap);
|
||||
MainMap.routeLayer.removeLayer(interactive);
|
||||
};
|
||||
}, [MainMap, onDistanceChange]);
|
||||
|
||||
|
|
|
@ -54,23 +54,26 @@ const Sticker: React.FC<IProps> = ({
|
|||
setDragging(true);
|
||||
}, [setDragging, layer, map]);
|
||||
|
||||
const onDragStop = React.useCallback(event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const onDragStop = React.useCallback(
|
||||
event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
if (!layer) return;
|
||||
if (!layer) return;
|
||||
|
||||
setDragging(false);
|
||||
onChange({
|
||||
...sticker,
|
||||
angle,
|
||||
});
|
||||
setDragging(false);
|
||||
onChange({
|
||||
...sticker,
|
||||
angle,
|
||||
});
|
||||
|
||||
layer.dragging.enable();
|
||||
map.dragging.enable();
|
||||
|
||||
setTimeout(map.enableClicks, 100);
|
||||
}, [setDragging, layer, map, sticker, angle]);
|
||||
layer.dragging.enable();
|
||||
map.dragging.enable();
|
||||
|
||||
setTimeout(map.enableClicks, 100);
|
||||
},
|
||||
[setDragging, layer, map, sticker, angle]
|
||||
);
|
||||
|
||||
const onMoveStarted = React.useCallback(() => {
|
||||
map.disableClicks();
|
||||
|
@ -159,8 +162,8 @@ const Sticker: React.FC<IProps> = ({
|
|||
className: 'sticker-container',
|
||||
});
|
||||
|
||||
const item = marker(sticker.latlng, { icon, draggable: true })
|
||||
|
||||
const item = marker(sticker.latlng, { icon, draggable: true });
|
||||
|
||||
setLayer(item);
|
||||
|
||||
return () => {
|
||||
|
@ -170,10 +173,10 @@ const Sticker: React.FC<IProps> = ({
|
|||
|
||||
useEffect(() => {
|
||||
if (!layer) return;
|
||||
|
||||
layer.addTo(MainMap);
|
||||
|
||||
return () => layer.removeFrom(MainMap)
|
||||
layer.addTo(MainMap.stickerLayer);
|
||||
|
||||
return () => MainMap.stickerLayer.removeLayer(layer);
|
||||
}, [layer]);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
|
@ -48,7 +48,11 @@ export const editorResetSaveDialog = () => ({ type: EDITOR_ACTIONS.RESET_SAVE_DI
|
|||
export const editorSetSave = (save: Partial<IEditorState['save']>) => ({
|
||||
type: EDITOR_ACTIONS.SET_SAVE,
|
||||
save,
|
||||
})
|
||||
});
|
||||
|
||||
export const editorCancelSave = () => ({
|
||||
type: EDITOR_ACTIONS.CANCEL_SAVE,
|
||||
});
|
||||
|
||||
export const editorHideRenderer = () => ({ type: EDITOR_ACTIONS.HIDE_RENDERER });
|
||||
export const editorSetRenderer = payload => ({ type: EDITOR_ACTIONS.SET_RENDERER, payload });
|
||||
|
|
|
@ -20,8 +20,8 @@ export const EDITOR_ACTIONS = {
|
|||
|
||||
SEND_SAVE_REQUEST: `${P}-SEND_SAVE_REQUEST`,
|
||||
SET_SAVE_LOADING: `${P}-SET_SAVE_LOADING`,
|
||||
CANCEL_SAVE_REQUEST: `${P}-CANCEL_SAVE_REQUEST`,
|
||||
RESET_SAVE_DIALOG: `${P}-RESET_SAVE_DIALOG`,
|
||||
CANCEL_SAVE: `${P}-CANCEL_SAVE`,
|
||||
|
||||
SET_SAVE: `${P}-SET_SAVE`,
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ export interface IEditorState {
|
|||
};
|
||||
}
|
||||
|
||||
const EDITOR_INITIAL_STATE = {
|
||||
export const EDITOR_INITIAL_STATE = {
|
||||
changed: false,
|
||||
editing: false,
|
||||
ready: false,
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
editorSetFeature,
|
||||
editorLocationChanged,
|
||||
editorKeyPressed,
|
||||
editorSetSave,
|
||||
} from '~/redux/editor/actions';
|
||||
import { getUrlData, pushPath } from '~/utils/history';
|
||||
import { MODES } from '~/constants/modes';
|
||||
|
@ -45,6 +46,7 @@ import { MAP_ACTIONS } from '../map/constants';
|
|||
import { OsrmRouter } from '~/utils/osrm';
|
||||
import path from 'ramda/es/path';
|
||||
import { MainMap } from '~/constants/map';
|
||||
import { EDITOR_INITIAL_STATE } from '.';
|
||||
|
||||
const hideLoader = () => {
|
||||
document.getElementById('loader').style.opacity = String(0);
|
||||
|
@ -181,6 +183,7 @@ function* locationChangeSaga({ location }: ReturnType<typeof editorLocationChang
|
|||
if (!ready) return;
|
||||
|
||||
yield call(loadMapFromPath);
|
||||
MainMap.fitBounds(MainMap.getVisibleBounds(), { animate: true });
|
||||
}
|
||||
|
||||
function* keyPressedSaga({ key, target }: ReturnType<typeof editorKeyPressed>) {
|
||||
|
@ -248,6 +251,14 @@ function* routerSubmit() {
|
|||
yield put(editorSetMode(MODES.NONE));
|
||||
}
|
||||
|
||||
function* cancelSave() {
|
||||
yield put(
|
||||
editorSetSave({
|
||||
...EDITOR_INITIAL_STATE.save,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export function* editorSaga() {
|
||||
yield takeEvery(EDITOR_ACTIONS.LOCATION_CHANGED, locationChangeSaga);
|
||||
|
||||
|
@ -259,4 +270,5 @@ export function* editorSaga() {
|
|||
yield takeLatest(EDITOR_ACTIONS.ROUTER_CANCEL, routerCancel);
|
||||
yield takeLatest(MAP_ACTIONS.MAP_CLICKED, mapClick);
|
||||
yield takeLatest(EDITOR_ACTIONS.ROUTER_SUBMIT, routerSubmit);
|
||||
yield takeLatest(EDITOR_ACTIONS.CANCEL_SAVE, cancelSave);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import { delay } from 'redux-saga';
|
|||
import { setReadySaga } from '../editor/sagas';
|
||||
import { selectEditor } from '../editor/selectors';
|
||||
import { EDITOR_ACTIONS } from '../editor/constants';
|
||||
import { MainMap } from '~/constants/map';
|
||||
|
||||
function* onMapClick({ latlng }: ReturnType<typeof mapClicked>) {
|
||||
const {
|
||||
|
@ -149,6 +150,7 @@ export function* mapInitSaga() {
|
|||
|
||||
yield call(loadMapFromPath);
|
||||
yield call(setReadySaga);
|
||||
MainMap.fitBounds(MainMap.getVisibleBounds(), { animate: false });
|
||||
pushLoaderState(100);
|
||||
}
|
||||
|
||||
|
@ -234,7 +236,7 @@ function* sendSaveRequestSaga({
|
|||
const { distance }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||
const { token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||
|
||||
yield put(editorSetSave({ loading: true }));
|
||||
yield put(editorSetSave({ loading: true, overwriting: false, finished: false, error: null }));
|
||||
|
||||
const {
|
||||
result,
|
||||
|
@ -268,6 +270,7 @@ function* sendSaveRequestSaga({
|
|||
|
||||
if (result && result.data.code === 'already_exist')
|
||||
return yield put(editorSetSave({ overwriting: true }));
|
||||
|
||||
if (result && result.data.code === 'conflict')
|
||||
return yield put(
|
||||
editorSetSave({
|
||||
|
@ -277,6 +280,7 @@ function* sendSaveRequestSaga({
|
|||
finished: false,
|
||||
})
|
||||
);
|
||||
|
||||
if (timeout || !result || !result.data.route || !result.data.route.address)
|
||||
return yield put(
|
||||
editorSetSave({
|
||||
|
@ -296,6 +300,10 @@ function* sendSaveRequestSaga({
|
|||
})
|
||||
);
|
||||
|
||||
yield put(editorSetReady(false));
|
||||
pushPath(`/${address}/edit`);
|
||||
yield put(editorSetReady(true));
|
||||
|
||||
yield put(
|
||||
editorSetSave({
|
||||
error: TIPS.SAVE_SUCCESS,
|
||||
|
@ -306,36 +314,6 @@ function* sendSaveRequestSaga({
|
|||
);
|
||||
}
|
||||
|
||||
// function* setSaveSuccessSaga({
|
||||
// address,
|
||||
// title,
|
||||
// is_public,
|
||||
// description,
|
||||
// }: ReturnType<typeof editorSetSaveSuccess>) {
|
||||
// const { id }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||
// const { dialog_active }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||
|
||||
// replacePath(`/${address}/edit`);
|
||||
|
||||
// yield put(
|
||||
// mapSet({
|
||||
// title,
|
||||
// address,
|
||||
// is_public,
|
||||
// description,
|
||||
// owner: { id },
|
||||
// })
|
||||
// );
|
||||
|
||||
// yield put(editorSetChanged(false));
|
||||
|
||||
// if (dialog_active) {
|
||||
// yield call(searchSetSagaWorker);
|
||||
// }
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
export function* mapSaga() {
|
||||
// TODO: setChanged on set route, logo, provider, stickers
|
||||
yield takeEvery(EDITOR_ACTIONS.START_EDITING, startEditingSaga);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue