mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
moved editor to separate reducer
This commit is contained in:
parent
e950d98b73
commit
87670770b0
38 changed files with 1425 additions and 1069 deletions
|
@ -1,17 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import { MODES } from '~/constants/modes';
|
import { MODES } from '~/constants/modes';
|
||||||
import { IStickerPack, STICKERS } from '~/constants/stickers';
|
import { STICKERS } from '~/constants/stickers';
|
||||||
import { StickerIcon } from '~/components/StickerIcon';
|
import { StickerIcon } from '~/components/StickerIcon';
|
||||||
import { IRootReducer } from '~/redux/user';
|
import { connect } from 'react-redux';
|
||||||
|
import { selectEditor } from '~/redux/editor/selectors'
|
||||||
|
|
||||||
interface Props {
|
const mapStateToProps = state => ({
|
||||||
mode: IRootReducer['mode'],
|
editor: selectEditor
|
||||||
sticker: string,
|
});
|
||||||
set: keyof IStickerPack,
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Cursor extends React.PureComponent<Props, {}> {
|
const mapDispatchToProps = {};
|
||||||
|
|
||||||
|
class CursorUnconnected extends React.PureComponent<Props, {}> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.addEventListener('mousemove', this.moveCursor);
|
window.addEventListener('mousemove', this.moveCursor);
|
||||||
}
|
}
|
||||||
|
@ -27,15 +28,27 @@ export class Cursor extends React.PureComponent<Props, {}> {
|
||||||
cursor: HTMLElement = null;
|
cursor: HTMLElement = null;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { mode, set, sticker } = this.props;
|
const {
|
||||||
const activeSticker = (sticker && set && STICKERS[set] && STICKERS[set].layers[sticker]);
|
editor: { mode, set, sticker },
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const activeSticker = sticker && set && STICKERS[set] && STICKERS[set].layers[sticker];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="cursor-tooltip desktop-only" ref={el => { this.cursor = el; }}>
|
<div
|
||||||
{ mode === MODES.ROUTER && <Icon icon="icon-router" />}
|
className="cursor-tooltip desktop-only"
|
||||||
{ mode === MODES.POLY && <Icon icon="icon-poly" />}
|
ref={el => {
|
||||||
{ mode === MODES.STICKERS && activeSticker && <StickerIcon sticker={sticker} set={set} /> }
|
this.cursor = el;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{mode === MODES.ROUTER && <Icon icon="icon-router" />}
|
||||||
|
{mode === MODES.POLY && <Icon icon="icon-poly" />}
|
||||||
|
{mode === MODES.STICKERS && activeSticker && <StickerIcon sticker={sticker} set={set} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const Cursor = connect()(CursorUnconnected);
|
||||||
|
|
||||||
|
export { Cursor }
|
|
@ -2,21 +2,23 @@ import React from 'react';
|
||||||
|
|
||||||
import { MODES } from '~/constants/modes';
|
import { MODES } from '~/constants/modes';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import { setMode, stopEditing } from "~/redux/user/actions";
|
import { editorSetMode, editorStopEditing } from '~/redux/editor/actions';
|
||||||
|
|
||||||
type Props = {
|
const mapStateToProps = () => ({});
|
||||||
stopEditing: typeof stopEditing,
|
const mapDispatchToProps = {
|
||||||
setMode: typeof setMode,
|
editorSetMode,
|
||||||
width: number,
|
editorStopEditing,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width?: number };
|
||||||
|
|
||||||
export class CancelDialog extends React.Component<Props, void> {
|
export class CancelDialog extends React.Component<Props, void> {
|
||||||
cancel = () => {
|
cancel = () => {
|
||||||
this.props.stopEditing();
|
this.props.editorStopEditing();
|
||||||
};
|
};
|
||||||
|
|
||||||
proceed = () => {
|
proceed = () => {
|
||||||
this.props.setMode(MODES.NONE);
|
this.props.editorSetMode(MODES.NONE);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -6,12 +6,14 @@ import {
|
||||||
searchSetDistance,
|
searchSetDistance,
|
||||||
searchSetTitle,
|
searchSetTitle,
|
||||||
searchSetTab,
|
searchSetTab,
|
||||||
setDialogActive,
|
|
||||||
mapsLoadMore,
|
mapsLoadMore,
|
||||||
dropRoute,
|
dropRoute,
|
||||||
modifyRoute,
|
modifyRoute,
|
||||||
toggleRouteStarred,
|
toggleRouteStarred,
|
||||||
} from '~/redux/user/actions';
|
} from '~/redux/user/actions';
|
||||||
|
|
||||||
|
import { editorSetDialogActive } from '~/redux/editor/actions';
|
||||||
|
|
||||||
import { isMobile } from '~/utils/window';
|
import { isMobile } from '~/utils/window';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
@ -19,28 +21,60 @@ import Range from 'rc-slider/lib/Range';
|
||||||
import { TABS, TABS_TITLES } from '~/constants/dialogs';
|
import { TABS, TABS_TITLES } from '~/constants/dialogs';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import { pushPath } from '~/utils/history';
|
import { pushPath } from '~/utils/history';
|
||||||
import { IRootState, IRouteListItem } from '~/redux/user';
|
import { IRouteListItem } from '~/redux/user';
|
||||||
import { ROLES } from '~/constants/auth';
|
import { ROLES } from '~/constants/auth';
|
||||||
import { IState } from '~/redux/store';
|
import { IState } from '~/redux/store';
|
||||||
|
|
||||||
export interface IMapListDialogProps extends IRootState {
|
|
||||||
marks: { [x: number]: string };
|
|
||||||
routes_sorted: Array<IRouteListItem>;
|
|
||||||
routes: IRootState['routes'];
|
|
||||||
ready: IRootState['ready'];
|
|
||||||
role: IRootState['user']['role'];
|
|
||||||
|
|
||||||
mapsLoadMore: typeof mapsLoadMore;
|
const mapStateToProps = ({
|
||||||
searchSetDistance: typeof searchSetDistance;
|
editor: { editing },
|
||||||
searchSetTitle: typeof searchSetTitle;
|
user: {
|
||||||
searchSetTab: typeof searchSetTab;
|
routes,
|
||||||
setDialogActive: typeof setDialogActive;
|
user: { role },
|
||||||
dropRoute: typeof dropRoute;
|
},
|
||||||
modifyRoute: typeof modifyRoute;
|
}: IState) => {
|
||||||
toggleRouteStarred: typeof toggleRouteStarred;
|
if (routes.filter.max >= 9999) {
|
||||||
}
|
return {
|
||||||
|
routes,
|
||||||
|
editing,
|
||||||
|
marks: {},
|
||||||
|
ready: false,
|
||||||
|
role,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface IMapListDialogState {
|
return {
|
||||||
|
role,
|
||||||
|
routes,
|
||||||
|
editing,
|
||||||
|
ready: true,
|
||||||
|
marks: [...new Array(Math.floor((routes.filter.max - routes.filter.min) / 25) + 1)].reduce(
|
||||||
|
(obj, el, i) => ({
|
||||||
|
...obj,
|
||||||
|
[routes.filter.min + i * 25]: ` ${routes.filter.min + i * 25}${
|
||||||
|
routes.filter.min + i * 25 >= 200 ? '+' : ''
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
searchSetDistance,
|
||||||
|
searchSetTitle,
|
||||||
|
searchSetTab,
|
||||||
|
editorSetDialogActive,
|
||||||
|
mapsLoadMore,
|
||||||
|
dropRoute,
|
||||||
|
modifyRoute,
|
||||||
|
toggleRouteStarred,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {}
|
||||||
|
|
||||||
|
export interface State {
|
||||||
menu_target: IRouteListItem['address'];
|
menu_target: IRouteListItem['address'];
|
||||||
editor_target: IRouteListItem['address'];
|
editor_target: IRouteListItem['address'];
|
||||||
|
|
||||||
|
@ -48,7 +82,7 @@ export interface IMapListDialogState {
|
||||||
is_dropping: boolean;
|
is_dropping: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMapListDialogState> {
|
class MapListDialogUnconnected extends React.Component<Props, State> {
|
||||||
state = {
|
state = {
|
||||||
menu_target: null,
|
menu_target: null,
|
||||||
editor_target: null,
|
editor_target: null,
|
||||||
|
@ -92,14 +126,11 @@ class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMap
|
||||||
};
|
};
|
||||||
|
|
||||||
openRoute = (_id: string): void => {
|
openRoute = (_id: string): void => {
|
||||||
if (isMobile()) this.props.setDialogActive(false);
|
if (isMobile()) this.props.editorSetDialogActive(false);
|
||||||
|
|
||||||
// pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`);
|
|
||||||
this.stopEditing();
|
this.stopEditing();
|
||||||
|
|
||||||
pushPath(`/${_id}`);
|
pushPath(`/${_id}`);
|
||||||
|
|
||||||
// pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onScroll = (e: {
|
onScroll = (e: {
|
||||||
|
@ -148,7 +179,7 @@ class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMap
|
||||||
filter: { min, max, title, distance, tab },
|
filter: { min, max, title, distance, tab },
|
||||||
},
|
},
|
||||||
marks,
|
marks,
|
||||||
}: IMapListDialogProps = this.props;
|
}: Props = this.props;
|
||||||
|
|
||||||
const { editor_target, menu_target, is_editing, is_dropping } = this.state;
|
const { editor_target, menu_target, is_editing, is_dropping } = this.state;
|
||||||
|
|
||||||
|
@ -245,51 +276,6 @@ class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({
|
|
||||||
user: {
|
|
||||||
editing,
|
|
||||||
routes,
|
|
||||||
user: { role },
|
|
||||||
},
|
|
||||||
}: IState) => {
|
|
||||||
if (routes.filter.max >= 9999) {
|
|
||||||
return {
|
|
||||||
routes,
|
|
||||||
editing,
|
|
||||||
marks: {},
|
|
||||||
ready: false,
|
|
||||||
role,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
role,
|
|
||||||
routes,
|
|
||||||
editing,
|
|
||||||
ready: true,
|
|
||||||
marks: [...new Array(Math.floor((routes.filter.max - routes.filter.min) / 25) + 1)].reduce(
|
|
||||||
(obj, el, i) => ({
|
|
||||||
...obj,
|
|
||||||
[routes.filter.min + i * 25]: ` ${routes.filter.min + i * 25}${
|
|
||||||
routes.filter.min + i * 25 >= 200 ? '+' : ''
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
}),
|
|
||||||
{}
|
|
||||||
),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
|
||||||
searchSetDistance,
|
|
||||||
searchSetTitle,
|
|
||||||
searchSetTab,
|
|
||||||
setDialogActive,
|
|
||||||
mapsLoadMore,
|
|
||||||
dropRoute,
|
|
||||||
modifyRoute,
|
|
||||||
toggleRouteStarred,
|
|
||||||
};
|
|
||||||
|
|
||||||
const MapListDialog = connect(mapStateToProps, mapDispatchToProps)(MapListDialogUnconnected);
|
const MapListDialog = connect(mapStateToProps, mapDispatchToProps)(MapListDialogUnconnected);
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import {
|
import * as EDITOR_ACTIONS from '~/redux/editor/actions'
|
||||||
routerCancel as routerCancelAction,
|
|
||||||
routerSubmit as routerSubmitAction,
|
|
||||||
} from "~/redux/user/actions";
|
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -11,11 +8,11 @@ type Props = {
|
||||||
width: number,
|
width: number,
|
||||||
is_routing: boolean,
|
is_routing: boolean,
|
||||||
|
|
||||||
routerCancel: typeof routerCancelAction,
|
editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel,
|
||||||
routerSubmit: typeof routerSubmitAction,
|
editorRouterSubmit: typeof EDITOR_ACTIONS.editorRouterSubmit,
|
||||||
}
|
}
|
||||||
|
|
||||||
const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction }) => (
|
const noPoints = ({ editorRouterCancel }: { editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel }) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="helper router-helper">
|
<div className="helper router-helper">
|
||||||
<div className="helper__text">
|
<div className="helper__text">
|
||||||
|
@ -28,7 +25,7 @@ const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction })
|
||||||
<div className="helper router-helper">
|
<div className="helper router-helper">
|
||||||
<div className="helper__buttons flex_1">
|
<div className="helper__buttons flex_1">
|
||||||
<div className="flex_1" />
|
<div className="flex_1" />
|
||||||
<div className="button router-helper__button" onClick={routerCancel}>
|
<div className="button router-helper__button" onClick={editorRouterCancel}>
|
||||||
Отмена
|
Отмена
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +33,7 @@ const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction })
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction }) => (
|
const firstPoint = ({ editorRouterCancel }: { editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel }) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="helper router-helper">
|
<div className="helper router-helper">
|
||||||
<div className="helper__text">
|
<div className="helper__text">
|
||||||
|
@ -47,7 +44,7 @@ const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction
|
||||||
<div className="helper router-helper">
|
<div className="helper router-helper">
|
||||||
<div className="helper__buttons flex_1">
|
<div className="helper__buttons flex_1">
|
||||||
<div className="flex_1" />
|
<div className="flex_1" />
|
||||||
<div className="button router-helper__button" onClick={routerCancel}>
|
<div className="button router-helper__button" onClick={editorRouterCancel}>
|
||||||
Отмена
|
Отмена
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -56,10 +53,10 @@ const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction
|
||||||
);
|
);
|
||||||
|
|
||||||
const draggablePoints = ({
|
const draggablePoints = ({
|
||||||
routerCancel, routerSubmit
|
editorRouterCancel, editorRouterSubmit
|
||||||
}: {
|
}: {
|
||||||
routerCancel: typeof routerCancelAction,
|
editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel,
|
||||||
routerSubmit: typeof routerSubmitAction,
|
editorRouterSubmit: typeof EDITOR_ACTIONS.editorRouterSubmit,
|
||||||
}) => (
|
}) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="helper">
|
<div className="helper">
|
||||||
|
@ -71,10 +68,10 @@ const draggablePoints = ({
|
||||||
<div className="helper router-helper">
|
<div className="helper router-helper">
|
||||||
<div className="helper__buttons button-group flex_1">
|
<div className="helper__buttons button-group flex_1">
|
||||||
<div className="flex_1" />
|
<div className="flex_1" />
|
||||||
<div className="button button_red router-helper__button" onClick={routerCancel}>
|
<div className="button button_red router-helper__button" onClick={editorRouterCancel}>
|
||||||
Отмена
|
Отмена
|
||||||
</div>
|
</div>
|
||||||
<div className="button primary router-helper__button" onClick={routerSubmit}>
|
<div className="button primary router-helper__button" onClick={editorRouterSubmit}>
|
||||||
Применить
|
Применить
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,13 +80,13 @@ const draggablePoints = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
export const RouterDialog = ({
|
export const RouterDialog = ({
|
||||||
routerPoints, routerCancel, routerSubmit, width, is_routing,
|
routerPoints, editorRouterCancel, editorRouterSubmit, width, is_routing,
|
||||||
}: Props) => (
|
}: Props) => (
|
||||||
<div className="control-dialog" style={{ width }}>
|
<div className="control-dialog" style={{ width }}>
|
||||||
<div className={classnames('save-loader', { active: is_routing })} />
|
<div className={classnames('save-loader', { active: is_routing })} />
|
||||||
|
|
||||||
{!routerPoints && noPoints({ routerCancel })}
|
{!routerPoints && noPoints({ editorRouterCancel })}
|
||||||
{routerPoints === 1 && firstPoint({ routerCancel })}
|
{routerPoints === 1 && firstPoint({ editorRouterCancel })}
|
||||||
{routerPoints >= 2 && draggablePoints({ routerCancel, routerSubmit })}
|
{routerPoints >= 2 && draggablePoints({ editorRouterCancel, editorRouterSubmit })}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,17 +10,17 @@ import classnames from 'classnames';
|
||||||
import ExpandableTextarea from 'react-expandable-textarea';
|
import ExpandableTextarea from 'react-expandable-textarea';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectMap } from '~/redux/map/selectors';
|
import { selectMap } from '~/redux/map/selectors';
|
||||||
import { selectUser } from '~/redux/user/selectors';
|
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||||
import * as USER_ACTIONS from '~/redux/user/actions';
|
import { selectEditor } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
map: selectMap(state),
|
map: selectMap(state),
|
||||||
user: selectUser(state),
|
editor: selectEditor(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
setMode: USER_ACTIONS.setMode,
|
editorSetMode: EDITOR_ACTIONS.editorSetMode,
|
||||||
sendSaveRequest: USER_ACTIONS.sendSaveRequest,
|
editorSendSaveRequest: EDITOR_ACTIONS.editorSendSaveRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width: number };
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width: number };
|
||||||
|
@ -33,14 +33,14 @@ interface State {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SaveDialogUnconnected extends React.Component<Props, State> {
|
class SaveDialogUnconnected extends React.Component<Props, State> {
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
address: props.address || '',
|
address: props.map.address || '',
|
||||||
title: props.title || '',
|
title: props.map.title || '',
|
||||||
is_public: props.is_public || false,
|
is_public: props.map.is_public || false,
|
||||||
description: props.description || '',
|
description: props.map.description || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,16 +57,18 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
|
||||||
|
|
||||||
setTitle = ({ target: { value } }) =>
|
setTitle = ({ target: { value } }) =>
|
||||||
this.setState({ title: (value && value.substr(0, 64)) || '' });
|
this.setState({ title: (value && value.substr(0, 64)) || '' });
|
||||||
|
|
||||||
setAddress = ({ target: { value } }) =>
|
setAddress = ({ target: { value } }) =>
|
||||||
this.setState({ address: (value && value.substr(0, 32)) || '' });
|
this.setState({ address: (value && value.substr(0, 32)) || '' });
|
||||||
|
|
||||||
setDescription = ({ target: { value } }) =>
|
setDescription = ({ target: { value } }) =>
|
||||||
this.setState({ description: (value && value.substr(0, 256)) || '' });
|
this.setState({ description: (value && value.substr(0, 256)) || '' });
|
||||||
|
|
||||||
sendSaveRequest = (e, force = false) => {
|
editorSendSaveRequest = (e, force = false) => {
|
||||||
const { title, is_public, description } = this.state;
|
const { title, is_public, description } = this.state;
|
||||||
const address = this.getAddress();
|
const address = this.getAddress();
|
||||||
|
|
||||||
this.props.sendSaveRequest({
|
this.props.editorSendSaveRequest({
|
||||||
title,
|
title,
|
||||||
address,
|
address,
|
||||||
force,
|
force,
|
||||||
|
@ -74,9 +76,10 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
|
||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
forceSaveRequest = e => this.sendSaveRequest(e, true);
|
|
||||||
|
|
||||||
cancelSaving = () => this.props.setMode(MODES.NONE);
|
forceSaveRequest = e => this.editorSendSaveRequest(e, true);
|
||||||
|
|
||||||
|
cancelSaving = () => this.props.editorSetMode(MODES.NONE);
|
||||||
|
|
||||||
onCopy = e => {
|
onCopy = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -91,7 +94,7 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
const { title, is_public, description } = this.state;
|
const { title, is_public, description } = this.state;
|
||||||
const {
|
const {
|
||||||
user: { save_error, save_finished, save_overwriting, save_loading },
|
editor: { save_error, save_finished, save_overwriting, save_loading },
|
||||||
width,
|
width,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { host, protocol } = getUrlData();
|
const { host, protocol } = getUrlData();
|
||||||
|
@ -157,7 +160,7 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!save_finished && !save_overwriting && (
|
{!save_finished && !save_overwriting && (
|
||||||
<div className="button primary" onClick={this.sendSaveRequest}>
|
<div className="button primary" onClick={this.editorSendSaveRequest}>
|
||||||
Сохранить
|
Сохранить
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectUserRenderer } from '~/redux/user/selectors';
|
import { selectEditorRenderer } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
renderer: selectUserRenderer(state),
|
renderer: selectEditorRenderer(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
type Props = ReturnType<typeof mapStateToProps> & {};
|
type Props = ReturnType<typeof mapStateToProps> & {};
|
||||||
|
|
|
@ -1,39 +1,44 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { STICKERS } from '~/constants/stickers';
|
import { STICKERS } from '~/constants/stickers';
|
||||||
import { setActiveSticker as setActiveStickerAction } from "~/redux/user/actions";
|
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
interface Props {
|
const mapStateToProps = () => ({});
|
||||||
setActiveSticker: typeof setActiveStickerAction,
|
const mapDispatchToProps = {
|
||||||
width: number,
|
editorSetActiveSticker: EDITOR_ACTIONS.editorSetActiveSticker,
|
||||||
}
|
};
|
||||||
|
|
||||||
export const StickersDialog = ({ setActiveSticker, width }: Props) => (
|
type Props = ReturnType<typeof mapStateToProps> &
|
||||||
|
typeof mapDispatchToProps & {
|
||||||
|
width: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StickersDialogUnconnected = ({ editorSetActiveSticker, width }: Props) => (
|
||||||
<div className="control-dialog control-dialog-big" style={{ width }}>
|
<div className="control-dialog control-dialog-big" style={{ width }}>
|
||||||
<div className="helper stickers-helper">
|
<div className="helper stickers-helper">
|
||||||
{
|
{Object.keys(STICKERS).map(set => (
|
||||||
Object.keys(STICKERS).map(set => (
|
<div key={set}>
|
||||||
<div key={set}>
|
<div className="stickers-set-title">{STICKERS[set].title || null}</div>
|
||||||
<div className="stickers-set-title">{STICKERS[set].title || null}</div>
|
<div className="stickers-grid">
|
||||||
<div className="stickers-grid">
|
{Object.keys(STICKERS[set].layers).map(sticker => (
|
||||||
{
|
<div
|
||||||
Object.keys(STICKERS[set].layers).map(sticker => (
|
style={{
|
||||||
<div
|
backgroundImage: `url(${STICKERS[set].url})`,
|
||||||
style={{
|
backgroundPosition: `${-STICKERS[set].layers[sticker].off * 48}px 50%`,
|
||||||
backgroundImage: `url(${STICKERS[set].url})`,
|
}}
|
||||||
backgroundPosition: `${-STICKERS[set].layers[sticker].off * 48}px 50%`,
|
className="sticker-preview"
|
||||||
}}
|
key={`${set}-${sticker}`}
|
||||||
className="sticker-preview"
|
onClick={() => editorSetActiveSticker({ set, sticker })}
|
||||||
key={`${set}-${sticker}`}
|
/>
|
||||||
onClick={() => setActiveSticker({ set, sticker })}
|
))}
|
||||||
/>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
))
|
</div>
|
||||||
}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const StickersDialog = connect(mapStateToProps, mapDispatchToProps)(StickersDialogUnconnected);
|
||||||
|
|
||||||
|
export { StickersDialog };
|
|
@ -5,11 +5,11 @@ import classnames from 'classnames';
|
||||||
import { getStyle } from '~/utils/dom';
|
import { getStyle } from '~/utils/dom';
|
||||||
import { nearestInt } from '~/utils/geom';
|
import { nearestInt } from '~/utils/geom';
|
||||||
import { parseDesc } from '~/utils/format';
|
import { parseDesc } from '~/utils/format';
|
||||||
import { selectUser } from '~/redux/user/selectors';
|
|
||||||
import { selectMap } from '~/redux/map/selectors';
|
import { selectMap } from '~/redux/map/selectors';
|
||||||
|
import { selectEditor } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
user: selectUser(state),
|
editor: selectEditor(state),
|
||||||
map: selectMap(state),
|
map: selectMap(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ export class TitleDialogUnconnected extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
user: { editing },
|
editor: { editing },
|
||||||
map: { title, description },
|
map: { title, description },
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { raised, height, height_raised } = this.state;
|
const { raised, height, height_raised } = this.state;
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
// flow
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { toHours } from '~/utils/format';
|
import { toHours } from '~/utils/format';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
// import Slider from 'rc-slider';
|
|
||||||
import Slider from 'rc-slider/lib/Slider';
|
import Slider from 'rc-slider/lib/Slider';
|
||||||
import { bindActionCreators } from 'redux';
|
import { editorSetSpeed } from '~/redux/editor/actions';
|
||||||
import { setSpeed } from '~/redux/user/actions';
|
|
||||||
import { IRootState } from "~/redux/user";
|
|
||||||
import { Tooltip } from "~/components/panels/Tooltip";
|
import { Tooltip } from "~/components/panels/Tooltip";
|
||||||
import { isMobile } from "~/utils/window";
|
import { isMobile } from "~/utils/window";
|
||||||
|
import { IState } from '~/redux/store';
|
||||||
|
|
||||||
interface Props extends IRootState {
|
function mapStateToProps(state) {
|
||||||
setSpeed: typeof setSpeed,
|
const {
|
||||||
|
editor: { distance, estimated, speed },
|
||||||
|
}: IState = state;
|
||||||
|
|
||||||
|
return { distance, estimated, speed };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = { editorSetSpeed };
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
dialogOpened: boolean,
|
dialogOpened: boolean,
|
||||||
}
|
}
|
||||||
|
@ -68,7 +73,7 @@ class Component extends React.PureComponent<Props, State> {
|
||||||
min={min}
|
min={min}
|
||||||
max={max}
|
max={max}
|
||||||
step={step}
|
step={step}
|
||||||
onChange={this.props.setSpeed}
|
onChange={this.props.editorSetSpeed}
|
||||||
defaultValue={15}
|
defaultValue={15}
|
||||||
value={speed}
|
value={speed}
|
||||||
marks={marks}
|
marks={marks}
|
||||||
|
@ -81,18 +86,6 @@ class Component extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
|
||||||
const {
|
|
||||||
user: { distance, estimated, speed },
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
return { distance, estimated, speed };
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => bindActionCreators({
|
|
||||||
setSpeed,
|
|
||||||
}, dispatch);
|
|
||||||
|
|
||||||
export const DistanceBar = connect(
|
export const DistanceBar = connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
|
|
|
@ -12,29 +12,13 @@ import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { ProviderDialog } from '~/components/dialogs/ProviderDialog';
|
import { ProviderDialog } from '~/components/dialogs/ProviderDialog';
|
||||||
import { ShotPrefetchDialog } from '~/components/dialogs/ShotPrefetchDialog';
|
import { ShotPrefetchDialog } from '~/components/dialogs/ShotPrefetchDialog';
|
||||||
import { selectUserMode } from '~/redux/user/selectors';
|
import { selectEditorMode } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
const mapStateToProps = state => ({ mode: selectUserMode(state) });
|
const mapStateToProps = state => ({ mode: selectEditorMode(state) });
|
||||||
|
|
||||||
// const mapDispatchToProps = dispatch => bindActionCreators({
|
|
||||||
// routerCancel: USER_ACTIONS.routerCancel,
|
|
||||||
// routerSubmit: USER_ACTIONS.routerSubmit,
|
|
||||||
// setActiveSticker: USER_ACTIONS.setActiveSticker,
|
|
||||||
// clearStickers: USER_ACTIONS.clearStickers,
|
|
||||||
// clearPoly: USER_ACTIONS.clearPoly,
|
|
||||||
// clearAll: USER_ACTIONS.clearAll,
|
|
||||||
// clearCancel: USER_ACTIONS.clearCancel,
|
|
||||||
// stopEditing: USER_ACTIONS.stopEditing,
|
|
||||||
// setEditing: USER_ACTIONS.setEditing,
|
|
||||||
// setMode: USER_ACTIONS.setMode,
|
|
||||||
// sendSaveRequest: USER_ACTIONS.sendSaveRequest,
|
|
||||||
// changeProvider: USER_ACTIONS.changeProvider,
|
|
||||||
// mapSetLogo: MAP_ACTIONS.mapSetLogo,
|
|
||||||
// }, dispatch);
|
|
||||||
|
|
||||||
type Props = ReturnType<typeof mapStateToProps> & {
|
type Props = ReturnType<typeof mapStateToProps> & {
|
||||||
width: number;
|
width: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DIALOG_CONTENTS: { [x: string]: any } = {
|
const DIALOG_CONTENTS: { [x: string]: any } = {
|
||||||
[MODES.ROUTER]: RouterDialog,
|
[MODES.ROUTER]: RouterDialog,
|
||||||
|
@ -47,12 +31,9 @@ const DIALOG_CONTENTS: { [x: string]: any } = {
|
||||||
[MODES.SHOT_PREFETCH]: ShotPrefetchDialog,
|
[MODES.SHOT_PREFETCH]: ShotPrefetchDialog,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Component = (props: Props) =>
|
const EditorDialogUnconnected = (props: Props) =>
|
||||||
props.mode && DIALOG_CONTENTS[props.mode]
|
props.mode && DIALOG_CONTENTS[props.mode] ? createElement(DIALOG_CONTENTS[props.mode]) : null;
|
||||||
? createElement(DIALOG_CONTENTS[props.mode])
|
|
||||||
: null;
|
|
||||||
|
|
||||||
export const EditorDialog = connect(
|
const EditorDialog = connect(mapStateToProps)(EditorDialogUnconnected);
|
||||||
mapStateToProps
|
|
||||||
// mapDispatchToProps
|
export { EditorDialog };
|
||||||
)(Component);
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { MODES } from '~/constants/modes';
|
import { MODES } from '~/constants/modes';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
@ -6,21 +6,34 @@ import { Icon } from '~/components/panels/Icon';
|
||||||
import { EditorDialog } from '~/components/panels/EditorDialog';
|
import { EditorDialog } from '~/components/panels/EditorDialog';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { setMode, startEditing, stopEditing, takeAShot, keyPressed } from '~/redux/user/actions';
|
import {
|
||||||
import { IRootState } from "~/redux/user";
|
editorSetMode,
|
||||||
import { Tooltip } from "~/components/panels/Tooltip";
|
editorStartEditing,
|
||||||
|
editorStopEditing,
|
||||||
|
editorTakeAShot,
|
||||||
|
editorKeyPressed,
|
||||||
|
} from '~/redux/editor/actions';
|
||||||
|
import { Tooltip } from '~/components/panels/Tooltip';
|
||||||
|
import { IState } from '~/redux/store';
|
||||||
|
import { selectEditor } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
interface Props extends IRootState {
|
const mapStateToProps = (state: IState) => ({
|
||||||
routing: IRootState['features']['routing'],
|
editor: selectEditor(state),
|
||||||
setMode: typeof setMode,
|
});
|
||||||
startEditing: typeof startEditing,
|
|
||||||
stopEditing: typeof stopEditing,
|
|
||||||
keyPressed: EventListenerOrEventListenerObject,
|
|
||||||
}
|
|
||||||
|
|
||||||
class Component extends React.PureComponent<Props, void> {
|
const mapDispatchToProps = {
|
||||||
|
editorSetMode,
|
||||||
|
editorStartEditing,
|
||||||
|
editorStopEditing,
|
||||||
|
editorTakeAShot,
|
||||||
|
editorKeyPressed,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||||
|
|
||||||
|
class EditorPanelUnconnected extends PureComponent<Props, void> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.addEventListener('keydown', this.props.keyPressed);
|
window.addEventListener('keydown', this.props.editorKeyPressed as any);
|
||||||
|
|
||||||
const obj = document.getElementById('control-dialog');
|
const obj = document.getElementById('control-dialog');
|
||||||
const { width } = this.panel.getBoundingClientRect();
|
const { width } = this.panel.getBoundingClientRect();
|
||||||
|
@ -33,29 +46,38 @@ class Component extends React.PureComponent<Props, void> {
|
||||||
panel: HTMLElement = null;
|
panel: HTMLElement = null;
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
window.removeEventListener('keydown', this.props.keyPressed);
|
window.removeEventListener('keydown', this.props.editorKeyPressed as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
startPolyMode = () => this.props.setMode(MODES.POLY);
|
startPolyMode = () => this.props.editorSetMode(MODES.POLY);
|
||||||
startStickerMode = () => this.props.setMode(MODES.STICKERS_SELECT);
|
startStickerMode = () => this.props.editorSetMode(MODES.STICKERS_SELECT);
|
||||||
startRouterMode = () => this.props.setMode(MODES.ROUTER);
|
startRouterMode = () => this.props.editorSetMode(MODES.ROUTER);
|
||||||
startTrashMode = () => this.props.setMode(MODES.TRASH);
|
startTrashMode = () => this.props.editorSetMode(MODES.TRASH);
|
||||||
startSaveMode = () => {
|
startSaveMode = () => {
|
||||||
// if (!this.props.changed) return;
|
// if (!this.props.changed) return;
|
||||||
this.props.setMode(MODES.SAVE);
|
this.props.editorSetMode(MODES.SAVE);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
mode, changed, editing, routing,
|
editor: {
|
||||||
|
mode,
|
||||||
|
changed,
|
||||||
|
editing,
|
||||||
|
features: { routing },
|
||||||
|
},
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classnames('panel right', { active: editing })} ref={el => { this.panel = el; }}>
|
<div
|
||||||
|
className={classnames('panel right', { active: editing })}
|
||||||
|
ref={el => {
|
||||||
|
this.panel = el;
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="control-bar control-bar-padded">
|
<div className="control-bar control-bar-padded">
|
||||||
{
|
{routing && (
|
||||||
routing &&
|
|
||||||
<button
|
<button
|
||||||
className={classnames({ active: mode === MODES.ROUTER })}
|
className={classnames({ active: mode === MODES.ROUTER })}
|
||||||
onClick={this.startRouterMode}
|
onClick={this.startRouterMode}
|
||||||
|
@ -63,8 +85,7 @@ class Component extends React.PureComponent<Props, void> {
|
||||||
<Tooltip>Автоматический маршрут</Tooltip>
|
<Tooltip>Автоматический маршрут</Tooltip>
|
||||||
<Icon icon="icon-route-2" />
|
<Icon icon="icon-route-2" />
|
||||||
</button>
|
</button>
|
||||||
}
|
)}
|
||||||
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={classnames({ active: mode === MODES.POLY })}
|
className={classnames({ active: mode === MODES.POLY })}
|
||||||
|
@ -75,13 +96,14 @@ class Component extends React.PureComponent<Props, void> {
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={classnames({ active: (mode === MODES.STICKERS || mode === MODES.STICKERS_SELECT) })}
|
className={classnames({
|
||||||
|
active: mode === MODES.STICKERS || mode === MODES.STICKERS_SELECT,
|
||||||
|
})}
|
||||||
onClick={this.startStickerMode}
|
onClick={this.startStickerMode}
|
||||||
>
|
>
|
||||||
<Tooltip>Точки маршрута</Tooltip>
|
<Tooltip>Точки маршрута</Tooltip>
|
||||||
<Icon icon="icon-sticker-3" />
|
<Icon icon="icon-sticker-3" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="control-sep" />
|
<div className="control-sep" />
|
||||||
|
@ -99,10 +121,7 @@ class Component extends React.PureComponent<Props, void> {
|
||||||
<div className="control-sep" />
|
<div className="control-sep" />
|
||||||
|
|
||||||
<div className="control-bar">
|
<div className="control-bar">
|
||||||
<button
|
<button className="highlighted cancel" onClick={this.props.editorStopEditing}>
|
||||||
className="highlighted cancel"
|
|
||||||
onClick={this.props.stopEditing}
|
|
||||||
>
|
|
||||||
<Icon icon="icon-cancel-1" />
|
<Icon icon="icon-cancel-1" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -114,59 +133,21 @@ class Component extends React.PureComponent<Props, void> {
|
||||||
<Icon icon="icon-check-1" />
|
<Icon icon="icon-check-1" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classnames('panel right', { active: !editing })}>
|
<div className={classnames('panel right', { active: !editing })}>
|
||||||
<div className="control-bar">
|
<div className="control-bar">
|
||||||
<button className="primary single" onClick={this.props.startEditing}>
|
<button className="primary single" onClick={this.props.editorStartEditing}>
|
||||||
<Icon icon="icon-route-2" />
|
<Icon icon="icon-route-2" />
|
||||||
<span>
|
<span>РЕДАКТИРОВАТЬ</span>
|
||||||
РЕДАКТИРОВАТЬ
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<EditorDialog
|
<EditorDialog width={(this.panel && this.panel.getBoundingClientRect().width) || 0} />
|
||||||
width={((this.panel && this.panel.getBoundingClientRect().width) || 0)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
export const EditorPanel = connect(mapStateToProps, mapDispatchToProps)(EditorPanelUnconnected);
|
||||||
const {
|
|
||||||
user: {
|
|
||||||
editing,
|
|
||||||
mode,
|
|
||||||
changed,
|
|
||||||
features: {
|
|
||||||
routing,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
return {
|
|
||||||
editing,
|
|
||||||
mode,
|
|
||||||
changed,
|
|
||||||
routing,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => bindActionCreators({
|
|
||||||
setMode,
|
|
||||||
// setLogo,
|
|
||||||
startEditing,
|
|
||||||
stopEditing,
|
|
||||||
takeAShot,
|
|
||||||
keyPressed,
|
|
||||||
}, dispatch);
|
|
||||||
|
|
||||||
export const EditorPanel = connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(Component);
|
|
||||||
|
|
|
@ -1,36 +1,34 @@
|
||||||
// flow
|
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import { PROVIDERS } from '~/constants/providers';
|
import { PROVIDERS } from '~/constants/providers';
|
||||||
import { LOGOS } from '~/constants/logos';
|
import { LOGOS } from '~/constants/logos';
|
||||||
import * as USER_ACTIONS from '~/redux/user/actions';
|
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { MODES } from '~/constants/modes';
|
import { MODES } from '~/constants/modes';
|
||||||
import { IRootState } from '~/redux/user';
|
|
||||||
|
|
||||||
import { Tooltip } from '~/components/panels/Tooltip';
|
import { Tooltip } from '~/components/panels/Tooltip';
|
||||||
import { selectMap } from '~/redux/map/selectors';
|
import { selectMap } from '~/redux/map/selectors';
|
||||||
import { selectUser } from '~/redux/user/selectors';
|
import { selectEditor } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
map: selectMap(state),
|
map: selectMap(state),
|
||||||
user: selectUser(state),
|
editor: selectEditor(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
setMode: USER_ACTIONS.setMode,
|
editorSetMode: EDITOR_ACTIONS.editorSetMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||||
|
|
||||||
const TopRightPanelUnconnected = ({
|
const TopRightPanelUnconnected = ({
|
||||||
map: { provider, logo },
|
map: { provider, logo },
|
||||||
user: { markers_shown, editing },
|
editor: { markers_shown, editing },
|
||||||
setMode,
|
editorSetMode,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const startProviderMode = useCallback(() => setMode(MODES.PROVIDER), [setMode]);
|
const startProviderMode = useCallback(() => editorSetMode(MODES.PROVIDER), [editorSetMode]);
|
||||||
const startLogoMode = useCallback(() => setMode(MODES.LOGO), [setMode]);
|
const startLogoMode = useCallback(() => editorSetMode(MODES.LOGO), [editorSetMode]);
|
||||||
const clearMode = useCallback(() => setMode(MODES.NONE), [setMode]);
|
const clearMode = useCallback(() => editorSetMode(MODES.NONE), [editorSetMode]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="status-panel top right">
|
<div className="status-panel top right">
|
||||||
|
|
|
@ -4,35 +4,41 @@ import { GuestButton } from '~/components/user/GuestButton';
|
||||||
import { DEFAULT_USER, ROLES } from '~/constants/auth';
|
import { DEFAULT_USER, ROLES } from '~/constants/auth';
|
||||||
import { UserButton } from '~/components/user/UserButton';
|
import { UserButton } from '~/components/user/UserButton';
|
||||||
import { UserMenu } from '~/components/user/UserMenu';
|
import { UserMenu } from '~/components/user/UserMenu';
|
||||||
|
import { setUser, userLogout, gotVkUser, openMapDialog } from '~/redux/user/actions';
|
||||||
import {
|
import {
|
||||||
setUser,
|
editorTakeAShot,
|
||||||
userLogout,
|
editorSetDialog,
|
||||||
takeAShot,
|
editorSetDialogActive,
|
||||||
setDialog,
|
editorGetGPXTrack,
|
||||||
gotVkUser,
|
} from '~/redux/editor/actions';
|
||||||
setDialogActive,
|
|
||||||
openMapDialog,
|
|
||||||
getGPXTrack,
|
|
||||||
} from '~/redux/user/actions';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { CLIENT } from '~/config/frontend';
|
import { CLIENT } from '~/config/frontend';
|
||||||
import { DIALOGS, TABS } from '~/constants/dialogs';
|
import { DIALOGS, TABS } from '~/constants/dialogs';
|
||||||
import { IRootState } from '~/redux/user';
|
|
||||||
import { Tooltip } from '~/components/panels/Tooltip';
|
import { Tooltip } from '~/components/panels/Tooltip';
|
||||||
import { TitleDialog } from '~/components/dialogs/TitleDialog';
|
import { TitleDialog } from '~/components/dialogs/TitleDialog';
|
||||||
|
|
||||||
interface Props extends IRootState {
|
const mapStateToProps = ({ user: { user }, editor: { dialog, dialog_active, is_empty } }) => ({
|
||||||
userLogout: typeof userLogout;
|
dialog,
|
||||||
setDialog: typeof setDialog;
|
dialog_active,
|
||||||
setDialogActive: typeof setDialogActive;
|
user,
|
||||||
gotVkUser: typeof gotVkUser;
|
is_empty,
|
||||||
takeAShot: typeof takeAShot;
|
});
|
||||||
openMapDialog: typeof openMapDialog;
|
|
||||||
getGPXTrack: typeof getGPXTrack;
|
const mapDispatchToProps = {
|
||||||
}
|
setUser,
|
||||||
|
userLogout,
|
||||||
|
editorTakeAShot,
|
||||||
|
editorSetDialog,
|
||||||
|
gotVkUser,
|
||||||
|
editorSetDialogActive,
|
||||||
|
openMapDialog,
|
||||||
|
editorGetGPXTrack,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
menuOpened: boolean;
|
menuOpened: boolean;
|
||||||
|
@ -84,8 +90,8 @@ export class UserPanelUnconnected extends PureComponent<Props, State> {
|
||||||
|
|
||||||
openAppInfoDialog = () => {
|
openAppInfoDialog = () => {
|
||||||
this.setMenuOpened();
|
this.setMenuOpened();
|
||||||
this.props.setDialog(DIALOGS.APP_INFO);
|
this.props.editorSetDialog(DIALOGS.APP_INFO);
|
||||||
this.props.setDialogActive(this.props.dialog !== DIALOGS.APP_INFO);
|
this.props.editorSetDialogActive(this.props.dialog !== DIALOGS.APP_INFO);
|
||||||
};
|
};
|
||||||
|
|
||||||
openOauthFrame = () => {
|
openOauthFrame = () => {
|
||||||
|
@ -143,7 +149,7 @@ export class UserPanelUnconnected extends PureComponent<Props, State> {
|
||||||
<div className="control-sep" />
|
<div className="control-sep" />
|
||||||
|
|
||||||
<div className="control-bar">
|
<div className="control-bar">
|
||||||
<button className={classnames({ active: false })} onClick={this.props.takeAShot}>
|
<button className={classnames({ active: false })} onClick={this.props.editorTakeAShot}>
|
||||||
<Tooltip>Снимок карты</Tooltip>
|
<Tooltip>Снимок карты</Tooltip>
|
||||||
<Icon icon="icon-shot-4" />
|
<Icon icon="icon-shot-4" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -153,7 +159,10 @@ export class UserPanelUnconnected extends PureComponent<Props, State> {
|
||||||
<div className="control-sep" />
|
<div className="control-sep" />
|
||||||
|
|
||||||
<div className="control-bar">
|
<div className="control-bar">
|
||||||
<button className={classnames({ active: false })} onClick={this.props.getGPXTrack}>
|
<button
|
||||||
|
className={classnames({ active: false })}
|
||||||
|
onClick={this.props.editorGetGPXTrack}
|
||||||
|
>
|
||||||
<Tooltip>Экспорт GPX</Tooltip>
|
<Tooltip>Экспорт GPX</Tooltip>
|
||||||
<Icon icon="icon-gpx-1" />
|
<Icon icon="icon-gpx-1" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -166,24 +175,6 @@ export class UserPanelUnconnected extends PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({ user: { dialog, dialog_active, user, is_empty } }) => ({
|
|
||||||
dialog,
|
|
||||||
dialog_active,
|
|
||||||
user,
|
|
||||||
is_empty,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
|
||||||
setUser,
|
|
||||||
userLogout,
|
|
||||||
takeAShot,
|
|
||||||
setDialog,
|
|
||||||
gotVkUser,
|
|
||||||
setDialogActive,
|
|
||||||
openMapDialog,
|
|
||||||
getGPXTrack,
|
|
||||||
};
|
|
||||||
|
|
||||||
const UserPanel = connect(mapStateToProps, mapDispatchToProps)(UserPanelUnconnected);
|
const UserPanel = connect(mapStateToProps, mapDispatchToProps)(UserPanelUnconnected);
|
||||||
|
|
||||||
export { UserPanel };
|
export { UserPanel };
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { hideRenderer, cropAShot } from '~/redux/user/actions';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Croppr from 'croppr';
|
import Croppr from 'croppr';
|
||||||
import 'croppr/dist/croppr.css';
|
import 'croppr/dist/croppr.css';
|
||||||
import { LOGOS } from '~/constants/logos';
|
import { LOGOS } from '~/constants/logos';
|
||||||
import { RendererPanel } from '~/components/panels/RendererPanel';
|
import { RendererPanel } from '~/components/panels/RendererPanel';
|
||||||
import { IRootState } from "~/redux/user";
|
import { selectEditor } from '~/redux/editor/selectors';
|
||||||
import { IRoute } from '~/redux/map/types';
|
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||||
|
import { selectMap } from '~/redux/map/selectors';
|
||||||
|
|
||||||
type Props = {
|
const mapStateToProps = state => ({
|
||||||
data: IRootState['renderer']['data'],
|
editor: selectEditor(state),
|
||||||
logo: IRoute['logo'],
|
map: selectMap(state),
|
||||||
hideRenderer: typeof hideRenderer,
|
});
|
||||||
cropAShot: typeof cropAShot,
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
editorHideRenderer: EDITOR_ACTIONS.editorHideRenderer,
|
||||||
|
editorCropAShot: EDITOR_ACTIONS.editorCropAShot,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
opacity: number,
|
opacity: number,
|
||||||
};
|
};
|
||||||
|
@ -47,7 +51,7 @@ class Component extends React.Component<Props, State> {
|
||||||
this.logo.style.transform = `scale(${scale})`;
|
this.logo.style.transform = `scale(${scale})`;
|
||||||
|
|
||||||
this.logoImg = document.createElement('img');
|
this.logoImg = document.createElement('img');
|
||||||
if (this.props.logo && LOGOS[this.props.logo][1]) this.logoImg.src = LOGOS[this.props.logo][1];
|
if (this.props.map.logo && LOGOS[this.props.map.logo][1]) this.logoImg.src = LOGOS[this.props.map.logo][1];
|
||||||
|
|
||||||
this.logo.append(this.logoImg);
|
this.logo.append(this.logoImg);
|
||||||
regionEl.append(this.logo);
|
regionEl.append(this.logo);
|
||||||
|
@ -58,10 +62,10 @@ class Component extends React.Component<Props, State> {
|
||||||
image: HTMLImageElement;
|
image: HTMLImageElement;
|
||||||
logoImg: HTMLImageElement;
|
logoImg: HTMLImageElement;
|
||||||
|
|
||||||
getImage = () => this.props.cropAShot(this.croppr.getValue());
|
getImage = () => this.props.editorCropAShot(this.croppr.getValue());
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { data } = this.props;
|
const { data } = this.props.editor.renderer;
|
||||||
const { opacity } = this.state;
|
const { opacity } = this.state;
|
||||||
const { innerWidth, innerHeight } = window;
|
const { innerWidth, innerHeight } = window;
|
||||||
const padding = 30;
|
const padding = 30;
|
||||||
|
@ -95,7 +99,7 @@ class Component extends React.Component<Props, State> {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RendererPanel
|
<RendererPanel
|
||||||
onCancel={this.props.hideRenderer}
|
onCancel={this.props.editorHideRenderer}
|
||||||
onSubmit={this.getImage}
|
onSubmit={this.getImage}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -103,12 +107,4 @@ class Component extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({ ...state.user.renderer, logo: state.user.logo });
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => bindActionCreators({
|
|
||||||
hideRenderer,
|
|
||||||
cropAShot,
|
|
||||||
}, dispatch);
|
|
||||||
|
|
||||||
export const Renderer = connect(mapStateToProps, mapDispatchToProps)(Component);
|
export const Renderer = connect(mapStateToProps, mapDispatchToProps)(Component);
|
||||||
|
|
|
@ -11,7 +11,7 @@ export interface IUser {
|
||||||
role: IRoles[keyof IRoles];
|
role: IRoles[keyof IRoles];
|
||||||
routes: {};
|
routes: {};
|
||||||
success: boolean;
|
success: boolean;
|
||||||
id?: number;
|
id?: string;
|
||||||
uid: string;
|
uid: string;
|
||||||
token?: string;
|
token?: string;
|
||||||
photo: string;
|
photo: string;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { EditorPanel } from '~/components/panels/EditorPanel';
|
import { EditorPanel } from '~/components/panels/EditorPanel';
|
||||||
|
@ -9,8 +8,7 @@ import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { Renderer } from '~/components/renderer/Renderer';
|
import { Renderer } from '~/components/renderer/Renderer';
|
||||||
import { hideRenderer, setDialogActive } from '~/redux/user/actions';
|
import { editorHideRenderer, editorSetDialogActive } from '~/redux/editor/actions';
|
||||||
import { Cursor } from '~/components/Cursor';
|
|
||||||
import { LeftDialog } from '~/containers/LeftDialog';
|
import { LeftDialog } from '~/containers/LeftDialog';
|
||||||
import { TopLeftPanel } from '~/components/panels/TopLeftPanel';
|
import { TopLeftPanel } from '~/components/panels/TopLeftPanel';
|
||||||
import { TopRightPanel } from '~/components/panels/TopRightPanel';
|
import { TopRightPanel } from '~/components/panels/TopRightPanel';
|
||||||
|
@ -19,18 +17,19 @@ import { IStickerPack } from '~/constants/stickers';
|
||||||
import { IDialogs } from '~/constants/dialogs';
|
import { IDialogs } from '~/constants/dialogs';
|
||||||
|
|
||||||
import { Map } from '~/containers/map/Map';
|
import { Map } from '~/containers/map/Map';
|
||||||
import { IRootReducer } from '~/redux/user';
|
import { IEditorState } from '~/redux/editor';
|
||||||
|
import { IState } from '~/redux/store';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
sticker: string;
|
sticker: string;
|
||||||
renderer_active: boolean;
|
renderer_active: boolean;
|
||||||
|
|
||||||
mode: IRootReducer['mode'];
|
mode: IEditorState['mode'];
|
||||||
dialog: keyof IDialogs;
|
dialog: keyof IDialogs;
|
||||||
dialog_active: boolean;
|
dialog_active: boolean;
|
||||||
set: keyof IStickerPack;
|
set: keyof IStickerPack;
|
||||||
hideRenderer: typeof hideRenderer;
|
editorHideRenderer: typeof editorHideRenderer;
|
||||||
setDialogActive: typeof setDialogActive;
|
editorSetDialogActive: typeof editorSetDialogActive;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Component = (props: Props) => (
|
const Component = (props: Props) => (
|
||||||
|
@ -45,26 +44,26 @@ const Component = (props: Props) => (
|
||||||
<LeftDialog
|
<LeftDialog
|
||||||
dialog={props.dialog}
|
dialog={props.dialog}
|
||||||
dialog_active={props.dialog_active}
|
dialog_active={props.dialog_active}
|
||||||
setDialogActive={props.setDialogActive}
|
editorSetDialogActive={props.editorSetDialogActive}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<LogoPreview />
|
<LogoPreview />
|
||||||
|
|
||||||
<Map />
|
<Map />
|
||||||
|
|
||||||
{props.renderer_active && <Renderer onClick={props.hideRenderer} />}
|
{props.renderer_active && <Renderer onClick={props.editorHideRenderer} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const mapStateToProps = ({
|
const mapStateToProps = ({
|
||||||
user: {
|
editor: {
|
||||||
mode,
|
mode,
|
||||||
dialog,
|
dialog,
|
||||||
dialog_active,
|
dialog_active,
|
||||||
renderer,
|
renderer,
|
||||||
activeSticker: { sticker = null, set = null },
|
activeSticker: { sticker = null, set = null },
|
||||||
},
|
},
|
||||||
}) => ({
|
}: IState) => ({
|
||||||
renderer_active: renderer.renderer_active,
|
renderer_active: renderer.renderer_active,
|
||||||
mode,
|
mode,
|
||||||
dialog,
|
dialog,
|
||||||
|
@ -74,5 +73,5 @@ const mapStateToProps = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch =>
|
const mapDispatchToProps = dispatch =>
|
||||||
bindActionCreators({ hideRenderer, setDialogActive }, dispatch);
|
bindActionCreators({ editorHideRenderer, editorSetDialogActive }, dispatch);
|
||||||
export const App = connect(mapStateToProps, mapDispatchToProps)(hot(module)(Component));
|
export const App = connect(mapStateToProps, mapDispatchToProps)(hot(module)(Component));
|
||||||
|
|
|
@ -4,12 +4,12 @@ import classnames from 'classnames';
|
||||||
import { AppInfoDialog } from '~/components/dialogs/AppInfoDialog';
|
import { AppInfoDialog } from '~/components/dialogs/AppInfoDialog';
|
||||||
import { Icon } from '~/components/panels/Icon';
|
import { Icon } from '~/components/panels/Icon';
|
||||||
import { MapListDialog } from '~/components/dialogs/MapListDialog';
|
import { MapListDialog } from '~/components/dialogs/MapListDialog';
|
||||||
import * as USER_ACTIONS from '~/redux/user/actions';
|
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
dialog: keyof IDialogs;
|
dialog: keyof IDialogs;
|
||||||
dialog_active: Boolean;
|
dialog_active: Boolean;
|
||||||
setDialogActive: typeof USER_ACTIONS.setDialogActive;
|
editorSetDialogActive: typeof EDITOR_ACTIONS.editorSetDialogActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LEFT_DIALOGS = {
|
const LEFT_DIALOGS = {
|
||||||
|
@ -17,7 +17,7 @@ const LEFT_DIALOGS = {
|
||||||
[DIALOGS.APP_INFO]: AppInfoDialog,
|
[DIALOGS.APP_INFO]: AppInfoDialog,
|
||||||
};
|
};
|
||||||
|
|
||||||
const LeftDialog = ({ dialog, dialog_active, setDialogActive }: Props) => (
|
const LeftDialog = ({ dialog, dialog_active, editorSetDialogActive }: Props) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{Object.keys(LEFT_DIALOGS).map(item => (
|
{Object.keys(LEFT_DIALOGS).map(item => (
|
||||||
<div
|
<div
|
||||||
|
@ -26,11 +26,11 @@ const LeftDialog = ({ dialog, dialog_active, setDialogActive }: Props) => (
|
||||||
>
|
>
|
||||||
{dialog && LEFT_DIALOGS[item] && createElement(LEFT_DIALOGS[item], {})}
|
{dialog && LEFT_DIALOGS[item] && createElement(LEFT_DIALOGS[item], {})}
|
||||||
|
|
||||||
<div className="dialog-close-button desktop-only" onClick={() => setDialogActive(false)}>
|
<div className="dialog-close-button desktop-only" onClick={() => editorSetDialogActive(false)}>
|
||||||
<Icon icon="icon-cancel-1" />
|
<Icon icon="icon-cancel-1" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="dialog-close-button mobile-only" onClick={() => setDialogActive(false)}>
|
<div className="dialog-close-button mobile-only" onClick={() => editorSetDialogActive(false)}>
|
||||||
<Icon icon="icon-chevron-down" />
|
<Icon icon="icon-chevron-down" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,15 +12,15 @@ import * as MAP_ACTIONS from "~/redux/map/actions";
|
||||||
import { Route } from "~/containers/map/Route";
|
import { Route } from "~/containers/map/Route";
|
||||||
import { TileLayer } from "~/containers/map/TileLayer";
|
import { TileLayer } from "~/containers/map/TileLayer";
|
||||||
import { Stickers } from "~/containers/map/Stickers";
|
import { Stickers } from "~/containers/map/Stickers";
|
||||||
import { selectUserEditing } from '~/redux/user/selectors'
|
|
||||||
|
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
|
import { selectEditorEditing } from "~/redux/editor/selectors";
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
provider: selectMapProvider(state),
|
provider: selectMapProvider(state),
|
||||||
route: selectMapRoute(state),
|
route: selectMapRoute(state),
|
||||||
stickers: selectMapStickers(state),
|
stickers: selectMapStickers(state),
|
||||||
editing: selectUserEditing(state),
|
editing: selectEditorEditing(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
|
|
120
src/redux/editor/actions.ts
Normal file
120
src/redux/editor/actions.ts
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
import { EDITOR_ACTIONS } from './constants';
|
||||||
|
import { IEditorState } from '.';
|
||||||
|
import { IRoute } from '../map/types';
|
||||||
|
import { KeyboardEvent } from 'react';
|
||||||
|
|
||||||
|
export const editorSetEditing = (editing: IEditorState['editing']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_EDITING,
|
||||||
|
editing,
|
||||||
|
});
|
||||||
|
export const editorSetMode = (mode: IEditorState['mode']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_MODE,
|
||||||
|
mode,
|
||||||
|
});
|
||||||
|
export const editorSetDistance = (distance: IEditorState['distance']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_DISTANCE,
|
||||||
|
distance,
|
||||||
|
});
|
||||||
|
export const editorSetChanged = (changed: IEditorState['changed']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_CHANGED,
|
||||||
|
changed,
|
||||||
|
});
|
||||||
|
export const editorSetSpeed = speed => ({ type: EDITOR_ACTIONS.SET_SPEED, speed });
|
||||||
|
|
||||||
|
export const editorStartEditing = () => ({ type: EDITOR_ACTIONS.START_EDITING });
|
||||||
|
export const editorStopEditing = () => ({ type: EDITOR_ACTIONS.STOP_EDITING });
|
||||||
|
|
||||||
|
export const editorRouterCancel = () => ({ type: EDITOR_ACTIONS.ROUTER_CANCEL });
|
||||||
|
export const editorRouterSubmit = () => ({ type: EDITOR_ACTIONS.ROUTER_SUBMIT });
|
||||||
|
|
||||||
|
export const editorClearPoly = () => ({ type: EDITOR_ACTIONS.CLEAR_POLY });
|
||||||
|
export const editorClearStickers = () => ({ type: EDITOR_ACTIONS.CLEAR_STICKERS });
|
||||||
|
export const editorClearAll = () => ({ type: EDITOR_ACTIONS.CLEAR_ALL });
|
||||||
|
export const editorClearCancel = () => ({ type: EDITOR_ACTIONS.CLEAR_CANCEL });
|
||||||
|
|
||||||
|
export const editorSendSaveRequest = (payload: {
|
||||||
|
title: IRoute['title'];
|
||||||
|
address: IRoute['address'];
|
||||||
|
is_public: IRoute['is_public'];
|
||||||
|
description: IRoute['description'];
|
||||||
|
force: boolean;
|
||||||
|
}) => ({
|
||||||
|
type: EDITOR_ACTIONS.SEND_SAVE_REQUEST,
|
||||||
|
...payload,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorResetSaveDialog = () => ({ type: EDITOR_ACTIONS.RESET_SAVE_DIALOG });
|
||||||
|
|
||||||
|
export const editorSetSaveLoading = (save_loading: IEditorState['save_loading']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_SAVE_LOADING,
|
||||||
|
save_loading,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorSetSaveSuccess = (payload: {
|
||||||
|
address: IRoute['address'];
|
||||||
|
title: IRoute['address'];
|
||||||
|
is_public: IRoute['is_public'];
|
||||||
|
description: IRoute['description'];
|
||||||
|
|
||||||
|
save_error: string;
|
||||||
|
}) => ({ type: EDITOR_ACTIONS.SET_SAVE_SUCCESS, ...payload });
|
||||||
|
|
||||||
|
export const editorSetSaveError = (save_error: IEditorState['save_error']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_SAVE_ERROR,
|
||||||
|
save_error,
|
||||||
|
});
|
||||||
|
export const editorSetSaveOverwrite = () => ({ type: EDITOR_ACTIONS.SET_SAVE_OVERWRITE });
|
||||||
|
|
||||||
|
export const editorHideRenderer = () => ({ type: EDITOR_ACTIONS.HIDE_RENDERER });
|
||||||
|
export const editorSetRenderer = payload => ({ type: EDITOR_ACTIONS.SET_RENDERER, payload });
|
||||||
|
export const editorTakeAShot = () => ({ type: EDITOR_ACTIONS.TAKE_A_SHOT });
|
||||||
|
export const editorCropAShot = payload => ({ type: EDITOR_ACTIONS.CROP_A_SHOT, ...payload });
|
||||||
|
export const editorSetDialog = dialog => ({ type: EDITOR_ACTIONS.SET_DIALOG, dialog });
|
||||||
|
export const editorSetDialogActive = dialog_active => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_DIALOG_ACTIVE,
|
||||||
|
dialog_active,
|
||||||
|
});
|
||||||
|
export const editorSetReady = ready => ({ type: EDITOR_ACTIONS.SET_READY, ready });
|
||||||
|
|
||||||
|
export const editorGetGPXTrack = () => ({ type: EDITOR_ACTIONS.GET_GPX_TRACK });
|
||||||
|
export const editorSetMarkersShown = markers_shown => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_MARKERS_SHOWN,
|
||||||
|
markers_shown,
|
||||||
|
});
|
||||||
|
export const editorSetIsEmpty = is_empty => ({ type: EDITOR_ACTIONS.SET_IS_EMPTY, is_empty });
|
||||||
|
export const editorSetFeature = (features: { [x: string]: boolean }) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_FEATURE,
|
||||||
|
features,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorSetIsRouting = (is_routing: boolean) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_IS_ROUTING,
|
||||||
|
is_routing,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorSetRouterPoints = (routerPoints: IEditorState['routerPoints']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_ROUTER_POINTS,
|
||||||
|
routerPoints,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorSetActiveSticker = (activeSticker: IEditorState['activeSticker']) => ({
|
||||||
|
type: EDITOR_ACTIONS.SET_ACTIVE_STICKER,
|
||||||
|
activeSticker,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorLocationChanged = location => ({
|
||||||
|
type: EDITOR_ACTIONS.LOCATION_CHANGED,
|
||||||
|
location,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const editorKeyPressed = ({
|
||||||
|
key,
|
||||||
|
target: { tagName },
|
||||||
|
}: {
|
||||||
|
key: string;
|
||||||
|
target: { tagName: string };
|
||||||
|
}) => ({
|
||||||
|
type: EDITOR_ACTIONS.KEY_PRESSED,
|
||||||
|
key,
|
||||||
|
target: tagName,
|
||||||
|
});
|
47
src/redux/editor/constants.ts
Normal file
47
src/redux/editor/constants.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
const P = 'EDITOR';
|
||||||
|
|
||||||
|
export const EDITOR_ACTIONS = {
|
||||||
|
SET_EDITING: `${P}-SET_EDITING`,
|
||||||
|
SET_MODE: `${P}-SET_MODE`,
|
||||||
|
SET_DISTANCE: `${P}-SET_DISTANCE`,
|
||||||
|
SET_CHANGED: `${P}-SET_CHANGED`,
|
||||||
|
SET_SPEED: `${P}-SET_SPEED`,
|
||||||
|
SET_ROUTER_POINTS: `${P}-SET_ROUTER_POINTS`,
|
||||||
|
SET_ACTIVE_STICKER: `${P}-SET_ACTIVE_STICKER`,
|
||||||
|
START_EDITING: `${P}-START_EDITING`,
|
||||||
|
STOP_EDITING: `${P}-STOP_EDITING`,
|
||||||
|
ROUTER_CANCEL: `${P}-ROUTER_CANCEL`,
|
||||||
|
ROUTER_SUBMIT: `${P}-ROUTER_SUBMIT`,
|
||||||
|
|
||||||
|
CLEAR_POLY: `${P}-CLEAR_POLY`,
|
||||||
|
CLEAR_STICKERS: `${P}-CLEAR_STICKERS`,
|
||||||
|
CLEAR_ALL: `${P}-CLEAR_ALL`,
|
||||||
|
CLEAR_CANCEL: `${P}-CLEAR_CANCEL`,
|
||||||
|
|
||||||
|
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`,
|
||||||
|
|
||||||
|
SET_SAVE_SUCCESS: `${P}-SET_SAVE_SUCCESS`,
|
||||||
|
SET_SAVE_ERROR: `${P}-SET_SAVE_ERROR`,
|
||||||
|
SET_SAVE_OVERWRITE: `${P}-SET_SAVE_OVERWRITE`,
|
||||||
|
|
||||||
|
SHOW_RENDERER: `${P}-SHOW_RENDERER`,
|
||||||
|
HIDE_RENDERER: `${P}-HIDE_RENDERER`,
|
||||||
|
SET_RENDERER: `${P}-SET_RENDERER`,
|
||||||
|
TAKE_A_SHOT: `${P}-TAKE_A_SHOT`,
|
||||||
|
CROP_A_SHOT: `${P}-CROP_A_SHOT`,
|
||||||
|
|
||||||
|
SET_DIALOG: `${P}-SET_DIALOG`,
|
||||||
|
SET_DIALOG_ACTIVE: `${P}-SET_DIALOG_ACTIVE`,
|
||||||
|
LOCATION_CHANGED: `${P}-LOCATION_CHANGED`,
|
||||||
|
SET_READY: `${P}-SET_READY`,
|
||||||
|
|
||||||
|
SET_MARKERS_SHOWN: `${P}-SET_MARKERS_SHOWN`,
|
||||||
|
GET_GPX_TRACK: `${P}-GET_GPX_TRACK`,
|
||||||
|
SET_IS_EMPTY: `${P}-SET_IS_EMPTY`,
|
||||||
|
SET_FEATURE: `${P}-SET_FEATURE`,
|
||||||
|
SET_IS_ROUTING: `${P}-SET_IS_ROUTING`,
|
||||||
|
KEY_PRESSED: `${P}-KEY_PRESSED`,
|
||||||
|
};
|
200
src/redux/editor/handlers.ts
Normal file
200
src/redux/editor/handlers.ts
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
import { getEstimated } from '~/utils/format';
|
||||||
|
import * as ACTIONS from '~/redux/editor/actions';
|
||||||
|
import { EDITOR_ACTIONS } from '~/redux/editor/constants';
|
||||||
|
import { IEditorState } from '~/redux/editor';
|
||||||
|
import { TIPS } from '~/constants/tips';
|
||||||
|
|
||||||
|
const setEditing = (
|
||||||
|
state,
|
||||||
|
{ editing }: ReturnType<typeof ACTIONS.editorSetEditing>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
editing,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setChanged = (
|
||||||
|
state,
|
||||||
|
{ changed }: ReturnType<typeof ACTIONS.editorSetChanged>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
changed,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setMode = (state, { mode }: ReturnType<typeof ACTIONS.editorSetMode>): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
mode,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setDistance = (
|
||||||
|
state,
|
||||||
|
{ distance }: ReturnType<typeof ACTIONS.editorSetDistance>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
distance,
|
||||||
|
estimated: getEstimated(distance, state.speed),
|
||||||
|
});
|
||||||
|
|
||||||
|
const setRouterPoints = (
|
||||||
|
state,
|
||||||
|
{ routerPoints }: ReturnType<typeof ACTIONS.editorSetRouterPoints>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
routerPoints,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setActiveSticker = (
|
||||||
|
state,
|
||||||
|
{ activeSticker }: ReturnType<typeof ACTIONS.editorSetActiveSticker>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
activeSticker: activeSticker || { set: null, sticker: null },
|
||||||
|
});
|
||||||
|
|
||||||
|
const hideRenderer = (state): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
renderer: { ...state.renderer, renderer_active: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
const setRenderer = (
|
||||||
|
state,
|
||||||
|
{ payload }: ReturnType<typeof ACTIONS.editorSetRenderer>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
renderer: { ...state.renderer, ...payload },
|
||||||
|
});
|
||||||
|
|
||||||
|
const sendSaveRequest = (state): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
save_processing: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setSaveError = (
|
||||||
|
state,
|
||||||
|
{ save_error }: ReturnType<typeof ACTIONS.editorSetSaveError>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
save_error,
|
||||||
|
save_finished: false,
|
||||||
|
save_processing: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setSaveLoading = (
|
||||||
|
state,
|
||||||
|
{ save_loading }: ReturnType<typeof ACTIONS.editorSetSaveLoading>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
save_loading,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setSaveOverwrite = (state): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
save_overwriting: true,
|
||||||
|
save_finished: false,
|
||||||
|
save_processing: false,
|
||||||
|
save_error: TIPS.SAVE_OVERWRITE,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setSaveSuccess = (
|
||||||
|
state,
|
||||||
|
{ save_error }: ReturnType<typeof ACTIONS.editorSetSaveSuccess>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
save_overwriting: false,
|
||||||
|
save_finished: true,
|
||||||
|
save_processing: false,
|
||||||
|
save_error,
|
||||||
|
});
|
||||||
|
|
||||||
|
const resetSaveDialog = (state): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
save_overwriting: false,
|
||||||
|
save_finished: false,
|
||||||
|
save_processing: false,
|
||||||
|
save_error: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const setDialog = (state, { dialog }: ReturnType<typeof ACTIONS.editorSetDialog>): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
dialog,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setDialogActive = (
|
||||||
|
state,
|
||||||
|
{ dialog_active }: ReturnType<typeof ACTIONS.editorSetDialogActive>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
dialog_active: dialog_active || !state.dialog_active,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setReady = (state, { ready = true }: ReturnType<typeof ACTIONS.editorSetReady>): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
ready,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setSpeed = (
|
||||||
|
state,
|
||||||
|
{ speed = 15 }: ReturnType<typeof ACTIONS.editorSetSpeed>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
speed,
|
||||||
|
estimated: getEstimated(state.distance, speed),
|
||||||
|
});
|
||||||
|
|
||||||
|
const setMarkersShown = (
|
||||||
|
state,
|
||||||
|
{ markers_shown = true }: ReturnType<typeof ACTIONS.editorSetMarkersShown>
|
||||||
|
): IEditorState => ({ ...state, markers_shown });
|
||||||
|
|
||||||
|
const setIsEmpty = (
|
||||||
|
state,
|
||||||
|
{ is_empty = true }: ReturnType<typeof ACTIONS.editorSetIsEmpty>
|
||||||
|
): IEditorState => ({ ...state, is_empty });
|
||||||
|
|
||||||
|
const setFeature = (
|
||||||
|
state,
|
||||||
|
{ features }: ReturnType<typeof ACTIONS.editorSetFeature>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
features: {
|
||||||
|
...state.features,
|
||||||
|
...features,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const setIsRouting = (
|
||||||
|
state,
|
||||||
|
{ is_routing }: ReturnType<typeof ACTIONS.editorSetIsRouting>
|
||||||
|
): IEditorState => ({
|
||||||
|
...state,
|
||||||
|
is_routing,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const EDITOR_HANDLERS = {
|
||||||
|
[EDITOR_ACTIONS.SET_EDITING]: setEditing,
|
||||||
|
[EDITOR_ACTIONS.SET_CHANGED]: setChanged,
|
||||||
|
[EDITOR_ACTIONS.SET_MODE]: setMode,
|
||||||
|
[EDITOR_ACTIONS.SET_DISTANCE]: setDistance,
|
||||||
|
[EDITOR_ACTIONS.SET_ROUTER_POINTS]: setRouterPoints,
|
||||||
|
[EDITOR_ACTIONS.SET_ACTIVE_STICKER]: setActiveSticker,
|
||||||
|
|
||||||
|
[EDITOR_ACTIONS.SET_SAVE_ERROR]: setSaveError,
|
||||||
|
[EDITOR_ACTIONS.SET_SAVE_LOADING]: setSaveLoading,
|
||||||
|
[EDITOR_ACTIONS.SET_SAVE_OVERWRITE]: setSaveOverwrite,
|
||||||
|
[EDITOR_ACTIONS.SET_SAVE_SUCCESS]: setSaveSuccess,
|
||||||
|
[EDITOR_ACTIONS.SEND_SAVE_REQUEST]: sendSaveRequest,
|
||||||
|
[EDITOR_ACTIONS.RESET_SAVE_DIALOG]: resetSaveDialog,
|
||||||
|
|
||||||
|
[EDITOR_ACTIONS.HIDE_RENDERER]: hideRenderer,
|
||||||
|
[EDITOR_ACTIONS.SET_RENDERER]: setRenderer,
|
||||||
|
|
||||||
|
[EDITOR_ACTIONS.SET_DIALOG]: setDialog,
|
||||||
|
[EDITOR_ACTIONS.SET_DIALOG_ACTIVE]: setDialogActive,
|
||||||
|
[EDITOR_ACTIONS.SET_READY]: setReady,
|
||||||
|
|
||||||
|
[EDITOR_ACTIONS.SET_SPEED]: setSpeed,
|
||||||
|
[EDITOR_ACTIONS.SET_MARKERS_SHOWN]: setMarkersShown,
|
||||||
|
[EDITOR_ACTIONS.SET_IS_EMPTY]: setIsEmpty,
|
||||||
|
|
||||||
|
[EDITOR_ACTIONS.SET_FEATURE]: setFeature,
|
||||||
|
[EDITOR_ACTIONS.SET_IS_ROUTING]: setIsRouting,
|
||||||
|
};
|
85
src/redux/editor/index.ts
Normal file
85
src/redux/editor/index.ts
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import { IDialogs } from '~/constants/dialogs';
|
||||||
|
import { MODES } from '~/constants/modes';
|
||||||
|
import { createReducer } from 'reduxsauce';
|
||||||
|
import { EDITOR_HANDLERS } from './handlers';
|
||||||
|
|
||||||
|
export interface IEditorState {
|
||||||
|
changed: boolean,
|
||||||
|
editing: boolean,
|
||||||
|
ready: boolean,
|
||||||
|
markers_shown: boolean;
|
||||||
|
|
||||||
|
mode: typeof MODES[keyof typeof MODES],
|
||||||
|
|
||||||
|
dialog: IDialogs[keyof IDialogs],
|
||||||
|
dialog_active: boolean,
|
||||||
|
|
||||||
|
routerPoints: number,
|
||||||
|
distance: number,
|
||||||
|
estimated: number,
|
||||||
|
speed: number,
|
||||||
|
activeSticker: { set?: string, sticker?: string },
|
||||||
|
is_empty: boolean,
|
||||||
|
is_published: boolean,
|
||||||
|
is_routing: boolean,
|
||||||
|
save_error: string,
|
||||||
|
save_finished: boolean,
|
||||||
|
save_overwriting: boolean,
|
||||||
|
save_processing: boolean,
|
||||||
|
save_loading: boolean,
|
||||||
|
|
||||||
|
features: {
|
||||||
|
routing: boolean,
|
||||||
|
},
|
||||||
|
|
||||||
|
renderer: {
|
||||||
|
data: string,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
renderer_active: boolean,
|
||||||
|
info: string,
|
||||||
|
progress: number,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const EDITOR_INITIAL_STATE = {
|
||||||
|
changed: false,
|
||||||
|
editing: false,
|
||||||
|
ready: false,
|
||||||
|
markers_shown: false,
|
||||||
|
|
||||||
|
mode: MODES.NONE,
|
||||||
|
dialog: null,
|
||||||
|
dialog_active: false,
|
||||||
|
|
||||||
|
routerPoints: 0,
|
||||||
|
distance: 0,
|
||||||
|
estimated: 0,
|
||||||
|
speed: 15,
|
||||||
|
activeSticker: { set: null, sticker: null },
|
||||||
|
|
||||||
|
is_published: false,
|
||||||
|
is_empty: true,
|
||||||
|
is_routing: false,
|
||||||
|
|
||||||
|
save_error: '',
|
||||||
|
save_finished: false,
|
||||||
|
save_overwriting: false,
|
||||||
|
save_processing: false,
|
||||||
|
save_loading: false,
|
||||||
|
|
||||||
|
features: {
|
||||||
|
routing: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
renderer: {
|
||||||
|
data: '',
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
renderer_active: false,
|
||||||
|
info: '',
|
||||||
|
progress: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const editor = createReducer(EDITOR_INITIAL_STATE, EDITOR_HANDLERS);
|
256
src/redux/editor/sagas.ts
Normal file
256
src/redux/editor/sagas.ts
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
import { call, put, takeEvery, takeLatest, select, race } from 'redux-saga/effects';
|
||||||
|
import { delay, SagaIterator } from 'redux-saga';
|
||||||
|
import { selectEditor } from '~/redux/editor/selectors';
|
||||||
|
|
||||||
|
import {
|
||||||
|
editorHideRenderer,
|
||||||
|
editorSetChanged,
|
||||||
|
editorSetEditing,
|
||||||
|
editorSetMode,
|
||||||
|
editorSetReady,
|
||||||
|
editorSetRenderer,
|
||||||
|
editorSetDialog,
|
||||||
|
editorSetDialogActive,
|
||||||
|
editorClearAll,
|
||||||
|
editorSetFeature,
|
||||||
|
editorLocationChanged,
|
||||||
|
editorKeyPressed,
|
||||||
|
} from '~/redux/editor/actions';
|
||||||
|
import { getUrlData, pushPath } from '~/utils/history';
|
||||||
|
import { MODES } from '~/constants/modes';
|
||||||
|
import { checkOSRMService } from '~/utils/api';
|
||||||
|
import { LatLng } from 'leaflet';
|
||||||
|
import { searchSetTab } from '../user/actions';
|
||||||
|
import { TABS } from '~/constants/dialogs';
|
||||||
|
import { EDITOR_ACTIONS } from './constants';
|
||||||
|
import { getGPXString, downloadGPXTrack } from '~/utils/gpx';
|
||||||
|
import {
|
||||||
|
getTilePlacement,
|
||||||
|
getPolyPlacement,
|
||||||
|
getStickersPlacement,
|
||||||
|
fetchImages,
|
||||||
|
composeArrows,
|
||||||
|
composeDistMark,
|
||||||
|
composeImages,
|
||||||
|
composePoly,
|
||||||
|
composeStickers,
|
||||||
|
imageFetcher,
|
||||||
|
downloadCanvas,
|
||||||
|
} from '~/utils/renderer';
|
||||||
|
import { selectMap } from '../map/selectors';
|
||||||
|
import { selectUser } from '../user/selectors';
|
||||||
|
import { LOGOS } from '~/constants/logos';
|
||||||
|
import { loadMapSaga, replaceAddressIfItsBusy } from '../map/sagas';
|
||||||
|
import { mapSetAddressOrigin } from '../map/actions';
|
||||||
|
|
||||||
|
const hideLoader = () => {
|
||||||
|
document.getElementById('loader').style.opacity = String(0);
|
||||||
|
document.getElementById('loader').style.pointerEvents = 'none';
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
function* stopEditingSaga() {
|
||||||
|
const { changed, editing, mode }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
const { address_origin }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
const { path } = getUrlData();
|
||||||
|
|
||||||
|
if (!editing) return;
|
||||||
|
if (changed && mode !== MODES.CONFIRM_CANCEL) {
|
||||||
|
yield put(editorSetMode(MODES.CONFIRM_CANCEL));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(editorSetMode(MODES.NONE));
|
||||||
|
yield put(editorSetChanged(false));
|
||||||
|
|
||||||
|
yield pushPath(`/${address_origin || path}/`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function* checkOSRMServiceSaga() {
|
||||||
|
const routing = yield call(checkOSRMService, [new LatLng(1, 1), new LatLng(2, 2)]);
|
||||||
|
|
||||||
|
yield put(editorSetFeature({ routing }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* setReadySaga() {
|
||||||
|
yield put(editorSetReady(true));
|
||||||
|
hideLoader();
|
||||||
|
|
||||||
|
yield call(checkOSRMServiceSaga);
|
||||||
|
yield put(searchSetTab(TABS.MY));
|
||||||
|
}
|
||||||
|
|
||||||
|
function* getRenderData() {
|
||||||
|
yield put(editorSetRenderer({ info: 'Загрузка тайлов', progress: 0.1 }));
|
||||||
|
|
||||||
|
const { route, stickers, provider }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
|
||||||
|
const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
const geometry = getTilePlacement();
|
||||||
|
const points = getPolyPlacement(route);
|
||||||
|
const sticker_points = getStickersPlacement(stickers);
|
||||||
|
// TODO: get distance:
|
||||||
|
const distance = 0;
|
||||||
|
// const distance = editor.poly.poly.distance;
|
||||||
|
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const images = yield fetchImages(ctx, geometry, provider);
|
||||||
|
|
||||||
|
yield put(editorSetRenderer({ info: 'Отрисовка', progress: 0.5 }));
|
||||||
|
|
||||||
|
yield composeImages({ geometry, images, ctx });
|
||||||
|
yield composePoly({ points, ctx });
|
||||||
|
yield composeArrows({ points, ctx });
|
||||||
|
yield composeDistMark({ ctx, points, distance });
|
||||||
|
yield composeStickers({ stickers: sticker_points, ctx });
|
||||||
|
|
||||||
|
yield put(editorSetRenderer({ info: 'Готово', progress: 1 }));
|
||||||
|
|
||||||
|
return yield canvas.toDataURL('image/jpeg');
|
||||||
|
}
|
||||||
|
|
||||||
|
function* takeAShotSaga() {
|
||||||
|
const worker = call(getRenderData);
|
||||||
|
|
||||||
|
const { result, timeout } = yield race({
|
||||||
|
result: worker,
|
||||||
|
timeout: delay(500),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (timeout) yield put(editorSetMode(MODES.SHOT_PREFETCH));
|
||||||
|
|
||||||
|
const data = yield result || worker;
|
||||||
|
|
||||||
|
yield put(editorSetMode(MODES.NONE));
|
||||||
|
yield put(
|
||||||
|
editorSetRenderer({
|
||||||
|
data,
|
||||||
|
renderer_active: true,
|
||||||
|
width: window.innerWidth,
|
||||||
|
height: window.innerHeight,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function* getCropData({ x, y, width, height }) {
|
||||||
|
const { logo }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
const {
|
||||||
|
renderer: { data },
|
||||||
|
}: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
|
const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const image = yield imageFetcher(data);
|
||||||
|
|
||||||
|
ctx.drawImage(image, -x, -y);
|
||||||
|
|
||||||
|
if (logo && LOGOS[logo][1]) {
|
||||||
|
const logoImage = yield imageFetcher(LOGOS[logo][1]);
|
||||||
|
ctx.drawImage(logoImage, width - logoImage.width, height - logoImage.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return yield canvas.toDataURL('image/jpeg');
|
||||||
|
}
|
||||||
|
|
||||||
|
function* cropAShotSaga(params) {
|
||||||
|
const { title, address }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
|
||||||
|
yield call(getCropData, params);
|
||||||
|
const canvas = document.getElementById('renderer') as HTMLCanvasElement;
|
||||||
|
|
||||||
|
downloadCanvas(canvas, (title || address).replace(/\./gi, ' '));
|
||||||
|
|
||||||
|
return yield put(editorHideRenderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
function* locationChangeSaga({ location }: ReturnType<typeof editorLocationChanged>) {
|
||||||
|
const {
|
||||||
|
user: { id, random_url },
|
||||||
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
|
||||||
|
const { ready }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
|
const { owner, address }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
|
||||||
|
if (!ready) return;
|
||||||
|
|
||||||
|
const { path, mode } = getUrlData(location);
|
||||||
|
|
||||||
|
if (address !== path) {
|
||||||
|
const map = yield call(loadMapSaga, path);
|
||||||
|
|
||||||
|
if (map && map.route && map.route.owner && mode === 'edit' && map.route.owner !== id) {
|
||||||
|
return yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
||||||
|
}
|
||||||
|
} else if (mode === 'edit' && owner.id !== id) {
|
||||||
|
return yield call(replaceAddressIfItsBusy, random_url, address);
|
||||||
|
} else {
|
||||||
|
yield put(mapSetAddressOrigin(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode !== 'edit') {
|
||||||
|
yield put(editorSetEditing(false));
|
||||||
|
// editor.stopEditing();
|
||||||
|
} else {
|
||||||
|
yield put(editorSetEditing(true));
|
||||||
|
// editor.startEditing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function* keyPressedSaga({ key, target }: ReturnType<typeof editorKeyPressed>): any {
|
||||||
|
if (target === 'INPUT' || target === 'TEXTAREA') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === 'Escape') {
|
||||||
|
const {
|
||||||
|
dialog_active,
|
||||||
|
mode,
|
||||||
|
renderer: { renderer_active },
|
||||||
|
}: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
|
if (renderer_active) return yield put(editorHideRenderer());
|
||||||
|
if (dialog_active) return yield put(editorSetDialogActive(false));
|
||||||
|
if (mode !== MODES.NONE) return yield put(editorSetMode(MODES.NONE));
|
||||||
|
} else if (key === 'Delete') {
|
||||||
|
const { editing } = yield select(selectEditor);
|
||||||
|
|
||||||
|
if (!editing) return;
|
||||||
|
|
||||||
|
const { mode } = yield select(selectUser);
|
||||||
|
|
||||||
|
if (mode === MODES.TRASH) {
|
||||||
|
yield put(editorClearAll());
|
||||||
|
} else {
|
||||||
|
yield put(editorSetMode(MODES.TRASH));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function* getGPXTrackSaga(): SagaIterator {
|
||||||
|
const { route, stickers, title, address }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
// const { title, address }: = yield select(selectUser);
|
||||||
|
|
||||||
|
if (!route || route.length <= 0) return;
|
||||||
|
|
||||||
|
const track = getGPXString({ route, stickers, title: title || address });
|
||||||
|
|
||||||
|
return downloadGPXTrack({ track, title });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* editorSaga() {
|
||||||
|
yield takeEvery(EDITOR_ACTIONS.STOP_EDITING, stopEditingSaga);
|
||||||
|
yield takeLatest(EDITOR_ACTIONS.TAKE_A_SHOT, takeAShotSaga);
|
||||||
|
yield takeLatest(EDITOR_ACTIONS.CROP_A_SHOT, cropAShotSaga);
|
||||||
|
yield takeLatest(EDITOR_ACTIONS.LOCATION_CHANGED, locationChangeSaga);
|
||||||
|
yield takeLatest(EDITOR_ACTIONS.KEY_PRESSED, keyPressedSaga);
|
||||||
|
yield takeLatest(EDITOR_ACTIONS.GET_GPX_TRACK, getGPXTrackSaga);
|
||||||
|
}
|
7
src/redux/editor/selectors.ts
Normal file
7
src/redux/editor/selectors.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { IState } from "../store";
|
||||||
|
|
||||||
|
export const selectEditor = (state: IState) => state.editor;
|
||||||
|
export const selectEditorEditing = (state: IState) => state.editor.editing;
|
||||||
|
export const selectEditorMode = (state: IState) => state.editor.mode;
|
||||||
|
export const selectEditorActiveSticker = (state: IState) => state.editor.activeSticker;
|
||||||
|
export const selectEditorRenderer = (state: IState) => state.editor.renderer;
|
|
@ -68,3 +68,8 @@ export const mapSetLogo = (logo: IMapReducer['logo']) => ({
|
||||||
type: MAP_ACTIONS.SET_LOGO,
|
type: MAP_ACTIONS.SET_LOGO,
|
||||||
logo,
|
logo,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const mapSetAddressOrigin = (address_origin: IMapReducer['address_origin']) => ({
|
||||||
|
type: MAP_ACTIONS.SET_ADDRESS_ORIGIN,
|
||||||
|
address_origin,
|
||||||
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ export const MAP_ACTIONS = {
|
||||||
SET_TITLE: `${P}-SET_TILE`,
|
SET_TITLE: `${P}-SET_TILE`,
|
||||||
SET_DESCRIPTION: `${P}-SETDESCRIPTION`,
|
SET_DESCRIPTION: `${P}-SETDESCRIPTION`,
|
||||||
SET_ADDRESS: `${P}-SET_ADDRESS`,
|
SET_ADDRESS: `${P}-SET_ADDRESS`,
|
||||||
|
SET_ADDRESS_ORIGIN: `${P}-SET_ADDRESS_ORIGIN`,
|
||||||
SET_OWNER: `${P}-SET_OWNER`,
|
SET_OWNER: `${P}-SET_OWNER`,
|
||||||
SET_PUBLIC: `${P}-SET_PUBLIC`,
|
SET_PUBLIC: `${P}-SET_PUBLIC`,
|
||||||
SET_LOGO: `${P}-SET_LOGO`,
|
SET_LOGO: `${P}-SET_LOGO`,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
mapSetOwner,
|
mapSetOwner,
|
||||||
mapSetPublic,
|
mapSetPublic,
|
||||||
mapSetLogo,
|
mapSetLogo,
|
||||||
|
mapSetAddressOrigin,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
const setMap = (state: IMapReducer, { map }: ReturnType<typeof mapSet>): IMapReducer => ({
|
const setMap = (state: IMapReducer, { map }: ReturnType<typeof mapSet>): IMapReducer => ({
|
||||||
|
@ -86,6 +87,11 @@ const setLogo = (state: IMapReducer, { logo }: ReturnType<typeof mapSetLogo>): I
|
||||||
logo,
|
logo,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const setAddressOrigin = (state, { address_origin }: ReturnType<typeof mapSetAddressOrigin>): IMapReducer => ({
|
||||||
|
...state,
|
||||||
|
address_origin
|
||||||
|
});
|
||||||
|
|
||||||
export const MAP_HANDLERS = {
|
export const MAP_HANDLERS = {
|
||||||
[MAP_ACTIONS.SET_MAP]: setMap,
|
[MAP_ACTIONS.SET_MAP]: setMap,
|
||||||
[MAP_ACTIONS.SET_PROVIDER]: setProvider,
|
[MAP_ACTIONS.SET_PROVIDER]: setProvider,
|
||||||
|
@ -99,4 +105,5 @@ export const MAP_HANDLERS = {
|
||||||
[MAP_ACTIONS.SET_OWNER]: setOwner,
|
[MAP_ACTIONS.SET_OWNER]: setOwner,
|
||||||
[MAP_ACTIONS.SET_PUBLIC]: setPublic,
|
[MAP_ACTIONS.SET_PUBLIC]: setPublic,
|
||||||
[MAP_ACTIONS.SET_LOGO]: setLogo,
|
[MAP_ACTIONS.SET_LOGO]: setLogo,
|
||||||
|
[MAP_ACTIONS.SET_ADDRESS_ORIGIN]: setAddressOrigin,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@ export interface IMapReducer {
|
||||||
title: string;
|
title: string;
|
||||||
logo: string;
|
logo: string;
|
||||||
address: string;
|
address: string;
|
||||||
|
address_origin: string;
|
||||||
description: string;
|
description: string;
|
||||||
owner: { id: string };
|
owner: { id: string };
|
||||||
is_public: boolean;
|
is_public: boolean;
|
||||||
|
@ -24,6 +25,7 @@ export const MAP_INITIAL_STATE: IMapReducer = {
|
||||||
stickers: [],
|
stickers: [],
|
||||||
title: '',
|
title: '',
|
||||||
address: '',
|
address: '',
|
||||||
|
address_origin: '',
|
||||||
description: '',
|
description: '',
|
||||||
owner: { id: null },
|
owner: { id: null },
|
||||||
is_public: false,
|
is_public: false,
|
||||||
|
|
|
@ -1,39 +1,58 @@
|
||||||
import { takeEvery, select, put, call, TakeEffect, race, take, takeLatest } from 'redux-saga/effects';
|
import {
|
||||||
|
takeEvery,
|
||||||
|
select,
|
||||||
|
put,
|
||||||
|
call,
|
||||||
|
TakeEffect,
|
||||||
|
race,
|
||||||
|
take,
|
||||||
|
takeLatest,
|
||||||
|
} from 'redux-saga/effects';
|
||||||
import { MAP_ACTIONS } from './constants';
|
import { MAP_ACTIONS } from './constants';
|
||||||
import { mapClicked, mapAddSticker, mapSetProvider, mapSet, mapSetTitle, mapSetAddress, mapSetDescription, mapSetOwner, mapSetPublic } from './actions';
|
import {
|
||||||
import { selectUserMode, selectUserActiveSticker, selectUser, selectUserUser } from '~/redux/user/selectors';
|
mapClicked,
|
||||||
|
mapAddSticker,
|
||||||
|
mapSetProvider,
|
||||||
|
mapSet,
|
||||||
|
mapSetTitle,
|
||||||
|
mapSetAddressOrigin,
|
||||||
|
} from './actions';
|
||||||
|
import { selectUser, selectUserUser } from '~/redux/user/selectors';
|
||||||
import { MODES } from '~/constants/modes';
|
import { MODES } from '~/constants/modes';
|
||||||
import {
|
import {
|
||||||
setMode,
|
editorSetMode,
|
||||||
setChanged,
|
editorSetChanged,
|
||||||
setAddressOrigin,
|
editorSetEditing,
|
||||||
setEditing,
|
editorSetReady,
|
||||||
setReady,
|
editorSetActiveSticker,
|
||||||
setActiveSticker,
|
editorSetSaveError,
|
||||||
setSaveError,
|
editorSetSaveLoading,
|
||||||
setSaveLoading,
|
editorSendSaveRequest,
|
||||||
sendSaveRequest,
|
editorSetSaveSuccess,
|
||||||
setSaveSuccess,
|
editorSetSaveOverwrite,
|
||||||
setSaveOverwrite,
|
} from '~/redux/editor/actions';
|
||||||
} from '~/redux/user/actions';
|
|
||||||
import { pushLoaderState, getUrlData, pushPath, replacePath } from '~/utils/history';
|
import { pushLoaderState, getUrlData, pushPath, replacePath } from '~/utils/history';
|
||||||
import { setReadySaga, searchSetSagaWorker } from '~/redux/user/sagas';
|
import { searchSetSagaWorker } from '~/redux/user/sagas';
|
||||||
import { getStoredMap, postMap } from '~/utils/api';
|
import { getStoredMap, postMap } from '~/utils/api';
|
||||||
import { Unwrap } from '~/utils/middleware';
|
import { Unwrap } from '~/utils/middleware';
|
||||||
import { DEFAULT_PROVIDER } from '~/constants/providers';
|
|
||||||
import { USER_ACTIONS } from '~/redux/user/constants';
|
import { USER_ACTIONS } from '~/redux/user/constants';
|
||||||
import { selectMap } from './selectors';
|
import { selectMap, selectMapProvider } from './selectors';
|
||||||
import { TIPS } from '~/constants/tips';
|
import { TIPS } from '~/constants/tips';
|
||||||
import { delay } from 'redux-saga';
|
import { delay } from 'redux-saga';
|
||||||
|
import { setReadySaga } from '../editor/sagas';
|
||||||
|
import { selectEditor } from '../editor/selectors';
|
||||||
|
import { EDITOR_ACTIONS } from '../editor/constants';
|
||||||
|
|
||||||
function* onMapClick({ latlng }: ReturnType<typeof mapClicked>) {
|
function* onMapClick({ latlng }: ReturnType<typeof mapClicked>) {
|
||||||
const mode = yield select(selectUserMode);
|
const {
|
||||||
const { set, sticker } = yield select(selectUserActiveSticker);
|
mode,
|
||||||
|
activeSticker: { set, sticker },
|
||||||
|
}: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case MODES.STICKERS:
|
case MODES.STICKERS:
|
||||||
yield put(mapAddSticker({ latlng, set, sticker, text: '', angle: 0 }));
|
yield put(mapAddSticker({ latlng, set, sticker, text: '', angle: 0 }));
|
||||||
yield put(setMode(MODES.NONE));
|
yield put(editorSetMode(MODES.NONE));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -64,7 +83,7 @@ function* onMapClick({ latlng }: ReturnType<typeof mapClicked>) {
|
||||||
|
|
||||||
export function* replaceAddressIfItsBusy(destination, original) {
|
export function* replaceAddressIfItsBusy(destination, original) {
|
||||||
if (original) {
|
if (original) {
|
||||||
yield put(setAddressOrigin(original));
|
yield put(mapSetAddressOrigin(original));
|
||||||
}
|
}
|
||||||
|
|
||||||
pushPath(`/${destination}/edit`);
|
pushPath(`/${destination}/edit`);
|
||||||
|
@ -97,14 +116,15 @@ export function* loadMapSaga(path) {
|
||||||
function* startEmptyEditorSaga() {
|
function* startEmptyEditorSaga() {
|
||||||
const {
|
const {
|
||||||
user: { id, random_url },
|
user: { id, random_url },
|
||||||
provider = DEFAULT_PROVIDER,
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
} = yield select(selectUser);
|
|
||||||
|
const provider: ReturnType<typeof selectMapProvider> = yield select(selectMapProvider);
|
||||||
|
|
||||||
// TODO: set owner { id }
|
// TODO: set owner { id }
|
||||||
pushPath(`/${random_url}/edit`);
|
pushPath(`/${random_url}/edit`);
|
||||||
|
|
||||||
yield put(setChanged(false));
|
yield put(editorSetChanged(false));
|
||||||
yield put(setEditing(true));
|
yield put(editorSetEditing(true));
|
||||||
|
|
||||||
return yield call(setReadySaga);
|
return yield call(setReadySaga);
|
||||||
}
|
}
|
||||||
|
@ -114,9 +134,9 @@ export function* mapInitSaga() {
|
||||||
|
|
||||||
const { path, mode, hash } = getUrlData();
|
const { path, mode, hash } = getUrlData();
|
||||||
const {
|
const {
|
||||||
provider,
|
|
||||||
user: { id },
|
user: { id },
|
||||||
} = yield select(selectUser);
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
const provider: ReturnType<typeof selectMapProvider> = yield select(selectMapProvider);
|
||||||
|
|
||||||
yield put(mapSetProvider(provider));
|
yield put(mapSetProvider(provider));
|
||||||
|
|
||||||
|
@ -139,14 +159,12 @@ export function* mapInitSaga() {
|
||||||
yield call(setReadySaga);
|
yield call(setReadySaga);
|
||||||
yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
||||||
} else {
|
} else {
|
||||||
yield put(setAddressOrigin(''));
|
yield put(mapSetAddressOrigin(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(setEditing(true));
|
yield put(editorSetEditing(true));
|
||||||
// TODO: start editing
|
|
||||||
} else {
|
} else {
|
||||||
yield put(setEditing(false));
|
yield put(editorSetEditing(false));
|
||||||
// TODO: stop editing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yield call(setReadySaga);
|
yield call(setReadySaga);
|
||||||
|
@ -155,7 +173,7 @@ export function* mapInitSaga() {
|
||||||
}
|
}
|
||||||
|
|
||||||
yield call(startEmptyEditorSaga);
|
yield call(startEmptyEditorSaga);
|
||||||
yield put(setReady(true));
|
yield put(editorSetReady(true));
|
||||||
|
|
||||||
pushLoaderState(100);
|
pushLoaderState(100);
|
||||||
|
|
||||||
|
@ -163,7 +181,7 @@ export function* mapInitSaga() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setActiveStickerSaga() {
|
function* setActiveStickerSaga() {
|
||||||
yield put(setMode(MODES.STICKERS));
|
yield put(editorSetMode(MODES.STICKERS));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setTitleSaga({ title }: ReturnType<typeof mapSetTitle>) {
|
function* setTitleSaga({ title }: ReturnType<typeof mapSetTitle>) {
|
||||||
|
@ -172,10 +190,14 @@ function* setTitleSaga({ title }: ReturnType<typeof mapSetTitle>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* startEditingSaga() {
|
||||||
|
const { path } = getUrlData();
|
||||||
|
yield pushPath(`/${path}/edit`);
|
||||||
|
}
|
||||||
|
|
||||||
function* clearSaga({ type }) {
|
function* clearSaga({ type }) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case USER_ACTIONS.CLEAR_POLY:
|
case EDITOR_ACTIONS.CLEAR_POLY:
|
||||||
// TODO: clear router waypoints
|
|
||||||
yield put(
|
yield put(
|
||||||
mapSet({
|
mapSet({
|
||||||
route: [],
|
route: [],
|
||||||
|
@ -183,7 +205,7 @@ function* clearSaga({ type }) {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USER_ACTIONS.CLEAR_STICKERS:
|
case EDITOR_ACTIONS.CLEAR_STICKERS:
|
||||||
yield put(
|
yield put(
|
||||||
mapSet({
|
mapSet({
|
||||||
stickers: [],
|
stickers: [],
|
||||||
|
@ -191,8 +213,8 @@ function* clearSaga({ type }) {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USER_ACTIONS.CLEAR_ALL:
|
case EDITOR_ACTIONS.CLEAR_ALL:
|
||||||
yield put(setChanged(false));
|
yield put(editorSetChanged(false));
|
||||||
yield put(
|
yield put(
|
||||||
mapSet({
|
mapSet({
|
||||||
route: [],
|
route: [],
|
||||||
|
@ -205,8 +227,8 @@ function* clearSaga({ type }) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(setActiveSticker(null)); // TODO: move to maps
|
yield put(editorSetActiveSticker(null));
|
||||||
yield put(setMode(MODES.NONE));
|
yield put(editorSetMode(MODES.NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* sendSaveRequestSaga({
|
function* sendSaveRequestSaga({
|
||||||
|
@ -215,17 +237,18 @@ function* sendSaveRequestSaga({
|
||||||
force,
|
force,
|
||||||
is_public,
|
is_public,
|
||||||
description,
|
description,
|
||||||
}: ReturnType<typeof sendSaveRequest>) {
|
}: ReturnType<typeof editorSendSaveRequest>) {
|
||||||
const { route, stickers, provider } = yield select(selectMap);
|
const { route, stickers, provider }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
|
|
||||||
if (!route.length && !stickers.length) {
|
if (!route.length && !stickers.length) {
|
||||||
return yield put(setSaveError(TIPS.SAVE_EMPTY)); // TODO: move setSaveError to editor
|
return yield put(editorSetSaveError(TIPS.SAVE_EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
const { logo, distance } = yield select(selectUser);
|
const { logo }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
const { token } = yield select(selectUserUser);
|
const { distance }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
const { token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
|
|
||||||
yield put(setSaveLoading(true)); // TODO: move setSaveLoading to maps
|
yield put(editorSetSaveLoading(true));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
result,
|
result,
|
||||||
|
@ -250,20 +273,21 @@ function* sendSaveRequestSaga({
|
||||||
description,
|
description,
|
||||||
}),
|
}),
|
||||||
timeout: delay(10000),
|
timeout: delay(10000),
|
||||||
cancel: take(USER_ACTIONS.RESET_SAVE_DIALOG),
|
cancel: take(EDITOR_ACTIONS.RESET_SAVE_DIALOG),
|
||||||
});
|
});
|
||||||
|
|
||||||
yield put(setSaveLoading(false));
|
yield put(editorSetSaveLoading(false));
|
||||||
|
|
||||||
if (cancel) return yield put(setMode(MODES.NONE));
|
if (cancel) return yield put(editorSetMode(MODES.NONE));
|
||||||
|
|
||||||
if (result && result.data.code === 'already_exist') return yield put(setSaveOverwrite()); // TODO: move setSaveOverwrite to editor
|
if (result && result.data.code === 'already_exist') return yield put(editorSetSaveOverwrite());
|
||||||
if (result && result.data.code === 'conflict') return yield put(setSaveError(TIPS.SAVE_EXISTS));
|
if (result && result.data.code === 'conflict')
|
||||||
|
return yield put(editorSetSaveError(TIPS.SAVE_EXISTS));
|
||||||
if (timeout || !result || !result.data.route || !result.data.route.address)
|
if (timeout || !result || !result.data.route || !result.data.route.address)
|
||||||
return yield put(setSaveError(TIPS.SAVE_TIMED_OUT));
|
return yield put(editorSetSaveError(TIPS.SAVE_TIMED_OUT));
|
||||||
|
|
||||||
return yield put( // TODO: move setSaveSuccess to editor
|
return yield put(
|
||||||
setSaveSuccess({
|
editorSetSaveSuccess({
|
||||||
address: result.data.route.address,
|
address: result.data.route.address,
|
||||||
title: result.data.route.title,
|
title: result.data.route.title,
|
||||||
is_public: result.data.route.is_public,
|
is_public: result.data.route.is_public,
|
||||||
|
@ -279,18 +303,23 @@ function* setSaveSuccessSaga({
|
||||||
title,
|
title,
|
||||||
is_public,
|
is_public,
|
||||||
description,
|
description,
|
||||||
}: ReturnType<typeof setSaveSuccess>) {
|
}: ReturnType<typeof editorSetSaveSuccess>) {
|
||||||
const { id } = yield select(selectUser);
|
const { id }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
const { dialog_active } = yield select(selectUser);
|
const { dialog_active }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
replacePath(`/${address}/edit`);
|
replacePath(`/${address}/edit`);
|
||||||
|
|
||||||
yield put(mapSetTitle(title));
|
yield put(
|
||||||
yield put(mapSetAddress(address));
|
mapSet({
|
||||||
yield put(mapSetPublic(is_public));
|
title,
|
||||||
yield put(mapSetDescription(description));
|
address,
|
||||||
yield put(setChanged(false));
|
is_public,
|
||||||
yield put(mapSetOwner({ id }));
|
description,
|
||||||
|
owner: { id },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
yield put(editorSetChanged(false));
|
||||||
|
|
||||||
if (dialog_active) {
|
if (dialog_active) {
|
||||||
yield call(searchSetSagaWorker);
|
yield call(searchSetSagaWorker);
|
||||||
|
@ -298,27 +327,25 @@ function* setSaveSuccessSaga({
|
||||||
|
|
||||||
// yield editor.setInitialData();
|
// yield editor.setInitialData();
|
||||||
// TODO: set initial data here
|
// TODO: set initial data here
|
||||||
|
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* mapSaga() {
|
export function* mapSaga() {
|
||||||
// TODO: setChanged on set route, logo, provider, stickers
|
// TODO: setChanged on set route, logo, provider, stickers
|
||||||
|
yield takeEvery(EDITOR_ACTIONS.START_EDITING, startEditingSaga);
|
||||||
yield takeEvery(USER_ACTIONS.SET_ACTIVE_STICKER, setActiveStickerSaga); // TODO: move active sticker to maps
|
yield takeEvery(EDITOR_ACTIONS.SET_ACTIVE_STICKER, setActiveStickerSaga);
|
||||||
yield takeEvery(MAP_ACTIONS.MAP_CLICKED, onMapClick);
|
yield takeEvery(MAP_ACTIONS.MAP_CLICKED, onMapClick);
|
||||||
yield takeEvery(MAP_ACTIONS.SET_TITLE, setTitleSaga);
|
yield takeEvery(MAP_ACTIONS.SET_TITLE, setTitleSaga);
|
||||||
// yield takeEvery(USER_ACTIONS.SET_LOGO, setLogoSaga);
|
yield takeLatest(EDITOR_ACTIONS.SEND_SAVE_REQUEST, sendSaveRequestSaga);
|
||||||
yield takeLatest(USER_ACTIONS.SEND_SAVE_REQUEST, sendSaveRequestSaga);
|
yield takeLatest(EDITOR_ACTIONS.SET_SAVE_SUCCESS, setSaveSuccessSaga);
|
||||||
yield takeLatest(USER_ACTIONS.SET_SAVE_SUCCESS, setSaveSuccessSaga);
|
|
||||||
|
|
||||||
yield takeEvery(
|
yield takeEvery(
|
||||||
// TODO: move all actions to MAP
|
|
||||||
[
|
[
|
||||||
USER_ACTIONS.CLEAR_POLY,
|
EDITOR_ACTIONS.CLEAR_POLY,
|
||||||
USER_ACTIONS.CLEAR_STICKERS,
|
EDITOR_ACTIONS.CLEAR_STICKERS,
|
||||||
USER_ACTIONS.CLEAR_ALL,
|
EDITOR_ACTIONS.CLEAR_ALL,
|
||||||
USER_ACTIONS.CLEAR_CANCEL,
|
EDITOR_ACTIONS.CLEAR_CANCEL,
|
||||||
],
|
],
|
||||||
clearSaga
|
clearSaga
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,13 +4,20 @@ import { persistStore, persistReducer } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import createSagaMiddleware from 'redux-saga';
|
import createSagaMiddleware from 'redux-saga';
|
||||||
|
|
||||||
|
|
||||||
|
import { createBrowserHistory } from 'history';
|
||||||
|
import { editorLocationChanged } from '~/redux/editor/actions';
|
||||||
|
import { PersistConfig, Persistor } from "redux-persist/es/types";
|
||||||
|
|
||||||
|
|
||||||
import { userReducer, IRootReducer } from '~/redux/user';
|
import { userReducer, IRootReducer } from '~/redux/user';
|
||||||
import { userSaga } from '~/redux/user/sagas';
|
import { userSaga } from '~/redux/user/sagas';
|
||||||
import { mapSaga } from '~/redux/map/sagas';
|
|
||||||
import { createBrowserHistory } from 'history';
|
import { editor, IEditorState } from '~/redux/editor';
|
||||||
import { locationChanged } from '~/redux/user/actions';
|
import { editorSaga } from '~/redux/editor/sagas';
|
||||||
import { PersistConfig, Persistor } from "redux-persist/es/types";
|
|
||||||
import { map, IMapReducer } from '~/redux/map';
|
import { map, IMapReducer } from '~/redux/map';
|
||||||
|
import { mapSaga } from '~/redux/map/sagas';
|
||||||
|
|
||||||
const userPersistConfig: PersistConfig = {
|
const userPersistConfig: PersistConfig = {
|
||||||
key: 'user',
|
key: 'user',
|
||||||
|
@ -21,6 +28,7 @@ const userPersistConfig: PersistConfig = {
|
||||||
export interface IState {
|
export interface IState {
|
||||||
user: IRootReducer
|
user: IRootReducer
|
||||||
map: IMapReducer,
|
map: IMapReducer,
|
||||||
|
editor: IEditorState,
|
||||||
}
|
}
|
||||||
// create the saga middleware
|
// create the saga middleware
|
||||||
export const sagaMiddleware = createSagaMiddleware();
|
export const sagaMiddleware = createSagaMiddleware();
|
||||||
|
@ -36,14 +44,15 @@ export const store = createStore(
|
||||||
combineReducers({
|
combineReducers({
|
||||||
user: persistReducer(userPersistConfig, userReducer),
|
user: persistReducer(userPersistConfig, userReducer),
|
||||||
map,
|
map,
|
||||||
// routing: routerReducer
|
editor,
|
||||||
}),
|
}),
|
||||||
composeEnhancers(applyMiddleware(/* routerMiddleware(history), */ sagaMiddleware))
|
composeEnhancers(applyMiddleware(sagaMiddleware))
|
||||||
);
|
);
|
||||||
|
|
||||||
export function configureStore(): { store: Store<any>, persistor: Persistor } {
|
export function configureStore(): { store: Store<any>, persistor: Persistor } {
|
||||||
sagaMiddleware.run(userSaga);
|
sagaMiddleware.run(userSaga);
|
||||||
sagaMiddleware.run(mapSaga);
|
sagaMiddleware.run(mapSaga);
|
||||||
|
sagaMiddleware.run(editorSaga);
|
||||||
|
|
||||||
const persistor = persistStore(store);
|
const persistor = persistStore(store);
|
||||||
|
|
||||||
|
@ -54,5 +63,5 @@ export const history = createBrowserHistory();
|
||||||
|
|
||||||
history.listen((location, action) => {
|
history.listen((location, action) => {
|
||||||
if (action === 'REPLACE') return;
|
if (action === 'REPLACE') return;
|
||||||
store.dispatch(locationChanged(location.pathname));
|
store.dispatch(editorLocationChanged(location.pathname));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,81 +1,81 @@
|
||||||
import { USER_ACTIONS } from '~/redux/user/constants';
|
import { USER_ACTIONS } from '~/redux/user/constants';
|
||||||
import { IUser } from "~/constants/auth";
|
import { IUser } from "~/constants/auth";
|
||||||
import { IRootState } from "~/redux/user";
|
// import { IRootState } from "~/redux/user";
|
||||||
import { IRoute } from '~/redux/map/types';
|
// import { IRoute } from '~/redux/map/types';
|
||||||
|
|
||||||
export const setUser = (user: IUser) => ({ type: USER_ACTIONS.SET_USER, user });
|
export const setUser = (user: IUser) => ({ type: USER_ACTIONS.SET_USER, user });
|
||||||
export const userLogout = () => ({ type: USER_ACTIONS.USER_LOGOUT });
|
export const userLogout = () => ({ type: USER_ACTIONS.USER_LOGOUT });
|
||||||
|
|
||||||
export const setEditing = (editing: IRootState['editing']) => ({ type: USER_ACTIONS.SET_EDITING, editing });
|
// export const setEditing = (editing: IRootState['editing']) => ({ type: USER_ACTIONS.SET_EDITING, editing });
|
||||||
export const setMode = (mode: IRootState['mode']) => ({ type: USER_ACTIONS.SET_MODE, mode });
|
// export const setMode = (mode: IRootState['mode']) => ({ type: USER_ACTIONS.SET_MODE, mode });
|
||||||
export const setDistance = (distance: IRootState['distance']) => ({ type: USER_ACTIONS.SET_DISTANCE, distance });
|
// export const setDistance = (distance: IRootState['distance']) => ({ type: USER_ACTIONS.SET_DISTANCE, distance });
|
||||||
export const setChanged = (changed: IRootState['changed']) => ({ type: USER_ACTIONS.SET_CHANGED, changed });
|
// export const setChanged = (changed: IRootState['changed']) => ({ type: USER_ACTIONS.SET_CHANGED, changed });
|
||||||
export const setRouterPoints = routerPoints => ({ type: USER_ACTIONS.SET_ROUTER_POINTS, routerPoints });
|
// export const setRouterPoints = routerPoints => ({ type: USER_ACTIONS.SET_ROUTER_POINTS, routerPoints });
|
||||||
export const setActiveSticker = activeSticker => ({ type: USER_ACTIONS.SET_ACTIVE_STICKER, activeSticker });
|
// export const setActiveSticker = activeSticker => ({ type: USER_ACTIONS.SET_ACTIVE_STICKER, activeSticker });
|
||||||
// export const setLogo = logo => ({ type: USER_ACTIONS.SET_LOGO, logo });
|
// export const setLogo = logo => ({ type: USER_ACTIONS.SET_LOGO, logo });
|
||||||
// export const setTitle = title => ({ type: USER_ACTIONS.SET_TITLE, title });
|
// export const setTitle = title => ({ type: USER_ACTIONS.SET_TITLE, title });
|
||||||
// export const setDescription = description => ({ type: USER_ACTIONS.SET_DESCRIPTION, description });
|
// export const setDescription = description => ({ type: USER_ACTIONS.SET_DESCRIPTION, description });
|
||||||
// export const setAddress = address => ({ type: USER_ACTIONS.SET_ADDRESS, address });
|
// export const setAddress = address => ({ type: USER_ACTIONS.SET_ADDRESS, address });
|
||||||
export const setAddressOrigin = address_origin => ({ type: USER_ACTIONS.SET_ADDRESS_ORIGIN, address_origin });
|
// export const setAddressOrigin = address_origin => ({ type: USER_ACTIONS.SET_ADDRESS_ORIGIN, address_origin });
|
||||||
// export const setPublic = is_public => ({ type: USER_ACTIONS.SET_PUBLIC, is_public });
|
// export const setPublic = is_public => ({ type: USER_ACTIONS.SET_PUBLIC, is_public });
|
||||||
export const setStarred = is_published => ({ type: USER_ACTIONS.SET_STARRED, is_published });
|
export const setStarred = is_published => ({ type: USER_ACTIONS.SET_STARRED, is_published });
|
||||||
export const setSpeed = speed => ({ type: USER_ACTIONS.SET_SPEED, speed });
|
// export const setSpeed = speed => ({ type: USER_ACTIONS.SET_SPEED, speed });
|
||||||
|
|
||||||
export const startEditing = () => ({ type: USER_ACTIONS.START_EDITING });
|
// export const startEditing = () => ({ type: USER_ACTIONS.START_EDITING });
|
||||||
export const stopEditing = () => ({ type: USER_ACTIONS.STOP_EDITING });
|
// export const stopEditing = () => ({ type: USER_ACTIONS.STOP_EDITING });
|
||||||
|
|
||||||
export const routerCancel = () => ({ type: USER_ACTIONS.ROUTER_CANCEL });
|
// export const routerCancel = () => ({ type: USER_ACTIONS.ROUTER_CANCEL });
|
||||||
export const routerSubmit = () => ({ type: USER_ACTIONS.ROUTER_SUBMIT });
|
// export const routerSubmit = () => ({ type: USER_ACTIONS.ROUTER_SUBMIT });
|
||||||
|
|
||||||
export const clearPoly = () => ({ type: USER_ACTIONS.CLEAR_POLY });
|
// export const clearPoly = () => ({ type: USER_ACTIONS.CLEAR_POLY });
|
||||||
export const clearStickers = () => ({ type: USER_ACTIONS.CLEAR_STICKERS });
|
// export const clearStickers = () => ({ type: USER_ACTIONS.CLEAR_STICKERS });
|
||||||
export const clearAll = () => ({ type: USER_ACTIONS.CLEAR_ALL });
|
// export const clearAll = () => ({ type: USER_ACTIONS.CLEAR_ALL });
|
||||||
export const clearCancel = () => ({ type: USER_ACTIONS.CLEAR_CANCEL });
|
// export const clearCancel = () => ({ type: USER_ACTIONS.CLEAR_CANCEL });
|
||||||
|
|
||||||
export const sendSaveRequest = (payload: {
|
// export const sendSaveRequest = (payload: {
|
||||||
title: IRoute['title'],
|
// title: IRoute['title'],
|
||||||
address: IRoute['address'],
|
// address: IRoute['address'],
|
||||||
is_public: IRoute['is_public'],
|
// is_public: IRoute['is_public'],
|
||||||
description: IRoute['description'],
|
// description: IRoute['description'],
|
||||||
force: boolean,
|
// force: boolean,
|
||||||
}) => ({
|
// }) => ({
|
||||||
type: USER_ACTIONS.SEND_SAVE_REQUEST,
|
// type: USER_ACTIONS.SEND_SAVE_REQUEST,
|
||||||
...payload,
|
// ...payload,
|
||||||
});
|
// });
|
||||||
|
|
||||||
export const resetSaveDialog = () => ({ type: USER_ACTIONS.RESET_SAVE_DIALOG });
|
// export const resetSaveDialog = () => ({ type: USER_ACTIONS.RESET_SAVE_DIALOG });
|
||||||
|
|
||||||
export const setSaveLoading = (save_loading: IRootState['save_loading']) => ({ type: USER_ACTIONS.SET_SAVE_LOADING, save_loading });
|
// export const setSaveLoading = (save_loading: IRootState['save_loading']) => ({ type: USER_ACTIONS.SET_SAVE_LOADING, save_loading });
|
||||||
|
|
||||||
export const setSaveSuccess = (payload: {
|
// export const setSaveSuccess = (payload: {
|
||||||
address: IRoute['address'],
|
// address: IRoute['address'],
|
||||||
title: IRoute['address'],
|
// title: IRoute['address'],
|
||||||
is_public: IRoute['is_public'],
|
// is_public: IRoute['is_public'],
|
||||||
description: IRoute['description'],
|
// description: IRoute['description'],
|
||||||
|
|
||||||
save_error: string,
|
// save_error: string,
|
||||||
}) => ({ type: USER_ACTIONS.SET_SAVE_SUCCESS, ...payload });
|
// }) => ({ type: USER_ACTIONS.SET_SAVE_SUCCESS, ...payload });
|
||||||
|
|
||||||
export const setSaveError = (save_error: IRootState['save_error']) => ({ type: USER_ACTIONS.SET_SAVE_ERROR, save_error });
|
// export const setSaveError = (save_error: IRootState['save_error']) => ({ type: USER_ACTIONS.SET_SAVE_ERROR, save_error });
|
||||||
export const setSaveOverwrite = () => ({ type: USER_ACTIONS.SET_SAVE_OVERWRITE });
|
// export const setSaveOverwrite = () => ({ type: USER_ACTIONS.SET_SAVE_OVERWRITE });
|
||||||
|
|
||||||
export const hideRenderer = () => ({ type: USER_ACTIONS.HIDE_RENDERER });
|
// export const hideRenderer = () => ({ type: USER_ACTIONS.HIDE_RENDERER });
|
||||||
export const setRenderer = payload => ({ type: USER_ACTIONS.SET_RENDERER, payload });
|
// export const setRenderer = payload => ({ type: USER_ACTIONS.SET_RENDERER, payload });
|
||||||
export const takeAShot = () => ({ type: USER_ACTIONS.TAKE_A_SHOT });
|
// export const takeAShot = () => ({ type: USER_ACTIONS.TAKE_A_SHOT });
|
||||||
export const cropAShot = payload => ({ type: USER_ACTIONS.CROP_A_SHOT, ...payload });
|
// export const cropAShot = payload => ({ type: USER_ACTIONS.CROP_A_SHOT, ...payload });
|
||||||
|
|
||||||
// export const setProvider = provider => ({ type: USER_ACTIONS.SET_PROVIDER, provider });
|
// export const setProvider = provider => ({ type: USER_ACTIONS.SET_PROVIDER, provider });
|
||||||
// export const changeProvider = provider => ({ type: USER_ACTIONS.CHANGE_PROVIDER, provider });
|
// export const changeProvider = provider => ({ type: USER_ACTIONS.CHANGE_PROVIDER, provider });
|
||||||
|
|
||||||
export const setDialog = dialog => ({ type: USER_ACTIONS.SET_DIALOG, dialog });
|
// export const setDialog = dialog => ({ type: USER_ACTIONS.SET_DIALOG, dialog });
|
||||||
export const setDialogActive = dialog_active => ({ type: USER_ACTIONS.SET_DIALOG_ACTIVE, dialog_active });
|
// export const setDialogActive = dialog_active => ({ type: USER_ACTIONS.SET_DIALOG_ACTIVE, dialog_active });
|
||||||
export const openMapDialog = tab => ({ type: USER_ACTIONS.OPEN_MAP_DIALOG, tab });
|
export const openMapDialog = tab => ({ type: USER_ACTIONS.OPEN_MAP_DIALOG, tab });
|
||||||
|
|
||||||
export const locationChanged = location => ({ type: USER_ACTIONS.LOCATION_CHANGED, location });
|
// export const locationChanged = location => ({ type: USER_ACTIONS.LOCATION_CHANGED, location });
|
||||||
export const setReady = ready => ({ type: USER_ACTIONS.SET_READY, ready });
|
// export const setReady = ready => ({ type: USER_ACTIONS.SET_READY, ready });
|
||||||
|
|
||||||
export const gotVkUser = user => ({ type: USER_ACTIONS.GOT_VK_USER, user });
|
export const gotVkUser = user => ({ type: USER_ACTIONS.GOT_VK_USER, user });
|
||||||
export const keyPressed = ({ key, target: { tagName } }) => ({ type: USER_ACTIONS.KEY_PRESSED, key, target: tagName });
|
// export const keyPressed = ({ key, target: { tagName } }) => ({ type: USER_ACTIONS.KEY_PRESSED, key, target: tagName });
|
||||||
|
|
||||||
export const searchSetTitle = title => ({ type: USER_ACTIONS.SEARCH_SET_TITLE, title });
|
export const searchSetTitle = title => ({ type: USER_ACTIONS.SEARCH_SET_TITLE, title });
|
||||||
export const searchSetDistance = distance => ({ type: USER_ACTIONS.SEARCH_SET_DISTANCE, distance });
|
export const searchSetDistance = distance => ({ type: USER_ACTIONS.SEARCH_SET_DISTANCE, distance });
|
||||||
|
@ -85,15 +85,15 @@ export const searchSetLoading = loading => ({ type: USER_ACTIONS.SEARCH_SET_LOAD
|
||||||
|
|
||||||
export const searchPutRoutes = payload => ({ type: USER_ACTIONS.SEARCH_PUT_ROUTES, ...payload });
|
export const searchPutRoutes = payload => ({ type: USER_ACTIONS.SEARCH_PUT_ROUTES, ...payload });
|
||||||
|
|
||||||
export const setMarkersShown = markers_shown => ({ type: USER_ACTIONS.SET_MARKERS_SHOWN, markers_shown });
|
// export const getGPXTrack = () => ({ type: USER_ACTIONS.GET_GPX_TRACK });
|
||||||
export const getGPXTrack = () => ({ type: USER_ACTIONS.GET_GPX_TRACK });
|
// export const setMarkersShown = markers_shown => ({ type: USER_ACTIONS.SET_MARKERS_SHOWN, markers_shown });
|
||||||
export const setIsEmpty = is_empty => ({ type: USER_ACTIONS.SET_IS_EMPTY, is_empty });
|
// export const setIsEmpty = is_empty => ({ type: USER_ACTIONS.SET_IS_EMPTY, is_empty });
|
||||||
|
|
||||||
export const mapsLoadMore = () => ({ type: USER_ACTIONS.MAPS_LOAD_MORE });
|
export const mapsLoadMore = () => ({ type: USER_ACTIONS.MAPS_LOAD_MORE });
|
||||||
export const mapsSetShift = (shift: number) => ({ type: USER_ACTIONS.MAPS_SET_SHIFT, shift });
|
export const mapsSetShift = (shift: number) => ({ type: USER_ACTIONS.MAPS_SET_SHIFT, shift });
|
||||||
|
|
||||||
export const setFeature = (features: { [x: string]: boolean }) => ({ type: USER_ACTIONS.SET_FEATURE, features });
|
// export const setFeature = (features: { [x: string]: boolean }) => ({ type: USER_ACTIONS.SET_FEATURE, features });
|
||||||
export const setIsRouting = (is_routing: boolean) => ({ type: USER_ACTIONS.SET_IS_ROUTING, is_routing });
|
// export const setIsRouting = (is_routing: boolean) => ({ type: USER_ACTIONS.SET_IS_ROUTING, is_routing });
|
||||||
|
|
||||||
export const dropRoute = (address: string) => ({ type: USER_ACTIONS.DROP_ROUTE, address });
|
export const dropRoute = (address: string) => ({ type: USER_ACTIONS.DROP_ROUTE, address });
|
||||||
export const modifyRoute = (address: string, { title, is_public }: { title: string, is_public: boolean }) => ({
|
export const modifyRoute = (address: string, { title, is_public }: { title: string, is_public: boolean }) => ({
|
||||||
|
|
|
@ -1,61 +1,7 @@
|
||||||
export interface IActions {
|
export const USER_ACTIONS = {
|
||||||
[x: string]: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const USER_ACTIONS: IActions = {
|
|
||||||
SET_USER: 'SET_USER',
|
SET_USER: 'SET_USER',
|
||||||
USER_LOGOUT: 'USER_LOGOUT',
|
USER_LOGOUT: 'USER_LOGOUT',
|
||||||
|
|
||||||
SET_EDITING: 'SET_EDITING',
|
|
||||||
SET_MODE: 'SET_MODE',
|
|
||||||
SET_DISTANCE: 'SET_DISTANCE',
|
|
||||||
SET_CHANGED: 'SET_CHANGED',
|
|
||||||
SET_ROUTER_POINTS: 'SET_ROUTER_POINTS',
|
|
||||||
SET_ACTIVE_STICKER: 'SET_ACTIVE_STICKER',
|
|
||||||
SET_LOGO: 'SET_LOGO',
|
|
||||||
SET_TITLE: 'SET_TITLE',
|
|
||||||
SET_ADDRESS: 'SET_ADDRESS',
|
|
||||||
SET_ADDRESS_ORIGIN: 'SET_ADDRESS_ORIGIN',
|
|
||||||
SET_PUBLIC: 'SET_PUBLIC',
|
|
||||||
SET_STARRED: 'SET_STARRED',
|
|
||||||
SET_DESCRIPTION: 'SET_DESCRIPTION',
|
|
||||||
|
|
||||||
START_EDITING: 'START_EDITING',
|
|
||||||
STOP_EDITING: 'STOP_EDITING',
|
|
||||||
|
|
||||||
ROUTER_CANCEL: 'ROUTER_CANCEL',
|
|
||||||
ROUTER_SUBMIT: 'ROUTER_SUBMIT',
|
|
||||||
|
|
||||||
CLEAR_POLY: 'CLEAR_POLY',
|
|
||||||
CLEAR_STICKERS: 'CLEAR_STICKERS',
|
|
||||||
CLEAR_ALL: 'CLEAR_ALL',
|
|
||||||
CLEAR_CANCEL: 'CLEAR_CANCEL',
|
|
||||||
|
|
||||||
SEND_SAVE_REQUEST: 'SEND_SAVE_REQUEST',
|
|
||||||
SET_SAVE_LOADING: 'SET_SAVE_LOADING',
|
|
||||||
CANCEL_SAVE_REQUEST: 'CANCEL_SAVE_REQUEST',
|
|
||||||
RESET_SAVE_DIALOG: 'RESET_SAVE_DIALOG',
|
|
||||||
|
|
||||||
SET_SAVE_SUCCESS: 'SET_SAVE_SUCCESS',
|
|
||||||
SET_SAVE_ERROR: 'SET_SAVE_ERROR',
|
|
||||||
SET_SAVE_OVERWRITE: 'SET_SAVE_OVERWRITE',
|
|
||||||
|
|
||||||
SHOW_RENDERER: 'SHOW_RENDERER',
|
|
||||||
HIDE_RENDERER: 'HIDE_RENDERER',
|
|
||||||
SET_RENDERER: 'SET_RENDERER',
|
|
||||||
TAKE_A_SHOT: 'TAKE_A_SHOT',
|
|
||||||
CROP_A_SHOT: 'CROP_A_SHOT',
|
|
||||||
|
|
||||||
SET_PROVIDER: 'SET_PROVIDER',
|
|
||||||
CHANGE_PROVIDER: 'CHANGE_PROVIDER',
|
|
||||||
|
|
||||||
SET_DIALOG: 'SET_DIALOG',
|
|
||||||
SET_DIALOG_ACTIVE: 'SET_DIALOG_ACTIVE',
|
|
||||||
LOCATION_CHANGED: 'LOCATION_CHANGED',
|
|
||||||
SET_READY: 'SET_READY',
|
|
||||||
|
|
||||||
GOT_VK_USER: 'GOT_VK_USER',
|
GOT_VK_USER: 'GOT_VK_USER',
|
||||||
KEY_PRESSED: 'KEY_PRESSED',
|
|
||||||
|
|
||||||
IFRAME_LOGIN_VK: 'IFRAME_LOGIN_VK',
|
IFRAME_LOGIN_VK: 'IFRAME_LOGIN_VK',
|
||||||
|
|
||||||
|
@ -68,21 +14,13 @@ export const USER_ACTIONS: IActions = {
|
||||||
SEARCH_SET_LOADING: 'SEARCH_SET_LOADING',
|
SEARCH_SET_LOADING: 'SEARCH_SET_LOADING',
|
||||||
|
|
||||||
OPEN_MAP_DIALOG: 'OPEN_MAP_DIALOG',
|
OPEN_MAP_DIALOG: 'OPEN_MAP_DIALOG',
|
||||||
SET_SPEED: 'SET_SPEED',
|
|
||||||
|
|
||||||
SET_MARKERS_SHOWN: 'SET_MARKERS_SHOWN',
|
|
||||||
|
|
||||||
GET_GPX_TRACK: 'GET_GPX_TRACK',
|
|
||||||
SET_IS_EMPTY: 'SET_IS_EMPTY',
|
|
||||||
|
|
||||||
MAPS_LOAD_MORE: 'MAPS_LOAD_MORE',
|
MAPS_LOAD_MORE: 'MAPS_LOAD_MORE',
|
||||||
MAPS_SET_SHIFT: 'MAPS_SET_SHIFT',
|
MAPS_SET_SHIFT: 'MAPS_SET_SHIFT',
|
||||||
|
|
||||||
SET_FEATURE: 'SET_FEATURE',
|
|
||||||
SET_IS_ROUTING: 'SET_IS_ROUTING',
|
|
||||||
|
|
||||||
DROP_ROUTE: 'DROP_ROUTE',
|
DROP_ROUTE: 'DROP_ROUTE',
|
||||||
|
SET_STARRED: 'SET_STARRED',
|
||||||
MODIFY_ROUTE: 'MODIFY_ROUTE',
|
MODIFY_ROUTE: 'MODIFY_ROUTE',
|
||||||
|
|
||||||
SET_ROUTE_STARRED: 'SET_ROUTE_STARRED',
|
SET_ROUTE_STARRED: 'SET_ROUTE_STARRED',
|
||||||
TOGGLE_ROUTE_STARRED: 'TOGGLE_ROUTE_STARRED',
|
TOGGLE_ROUTE_STARRED: 'TOGGLE_ROUTE_STARRED',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { IRootState } from ".";
|
import { IRootState } from ".";
|
||||||
import * as ActionCreators from './actions'
|
import * as ActionCreators from './actions'
|
||||||
import { TIPS } from "~/constants/tips";
|
|
||||||
import { TABS } from "~/constants/dialogs";
|
import { TABS } from "~/constants/dialogs";
|
||||||
import { USER_ACTIONS } from "./constants";
|
import { USER_ACTIONS } from "./constants";
|
||||||
|
|
||||||
|
@ -10,11 +9,6 @@ export interface ActionHandler<T> {
|
||||||
(state: IRootState, payload: UnsafeReturnType<T>): IRootState;
|
(state: IRootState, payload: UnsafeReturnType<T>): IRootState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getEstimated = (distance: number, speed: number = 15): number => {
|
|
||||||
const time = (distance && (distance / speed)) || 0;
|
|
||||||
return (time && parseFloat(time.toFixed(1)));
|
|
||||||
};
|
|
||||||
|
|
||||||
const setUser: ActionHandler<typeof ActionCreators.setUser> = (state, { user }) => ({
|
const setUser: ActionHandler<typeof ActionCreators.setUser> = (state, { user }) => ({
|
||||||
...state,
|
...state,
|
||||||
user: {
|
user: {
|
||||||
|
@ -23,121 +17,6 @@ const setUser: ActionHandler<typeof ActionCreators.setUser> = (state, { user })
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const setEditing: ActionHandler<typeof ActionCreators.setEditing> = (state, { editing }) => ({
|
|
||||||
...state, editing
|
|
||||||
});
|
|
||||||
|
|
||||||
const setChanged: ActionHandler<typeof ActionCreators.setChanged> = (state, { changed }) => ({
|
|
||||||
...state,
|
|
||||||
changed
|
|
||||||
});
|
|
||||||
|
|
||||||
const setMode: ActionHandler<typeof ActionCreators.setMode> = (state, { mode }) => ({
|
|
||||||
...state,
|
|
||||||
mode
|
|
||||||
});
|
|
||||||
|
|
||||||
const setDistance: ActionHandler<typeof ActionCreators.setDistance> = (state, { distance }) => ({
|
|
||||||
...state,
|
|
||||||
distance,
|
|
||||||
estimated: getEstimated(distance, state.speed),
|
|
||||||
});
|
|
||||||
|
|
||||||
const setRouterPoints: ActionHandler<typeof ActionCreators.setRouterPoints> = (state, { routerPoints }) => ({
|
|
||||||
...state,
|
|
||||||
routerPoints,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setActiveSticker: ActionHandler<typeof ActionCreators.setActiveSticker> = (state, { activeSticker }) => ({
|
|
||||||
...state,
|
|
||||||
activeSticker: activeSticker || { set: null, sticker: null }
|
|
||||||
});
|
|
||||||
|
|
||||||
// const setLogo: ActionHandler<typeof ActionCreators.setLogo> = (state, { logo }) => ({
|
|
||||||
// ...state,
|
|
||||||
// logo
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const setTitle: ActionHandler<typeof ActionCreators.setTitle> = (state, { title }) => ({
|
|
||||||
// ...state,
|
|
||||||
// title
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const setDescription: ActionHandler<typeof ActionCreators.setDescription> = (state, { description }) => ({
|
|
||||||
// ...state,
|
|
||||||
// description
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const setAddress: ActionHandler<typeof ActionCreators.setAddress> = (state, { address }) => ({
|
|
||||||
// ...state,
|
|
||||||
// address
|
|
||||||
// });
|
|
||||||
|
|
||||||
const setAddressOrigin: ActionHandler<typeof ActionCreators.setAddressOrigin> = (state, { address_origin }) => ({
|
|
||||||
...state,
|
|
||||||
address_origin
|
|
||||||
});
|
|
||||||
|
|
||||||
const sendSaveRequest: ActionHandler<typeof ActionCreators.sendSaveRequest> = (state) => ({
|
|
||||||
...state,
|
|
||||||
save_processing: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setSaveError: ActionHandler<typeof ActionCreators.setSaveError> = (state, { save_error }) => ({
|
|
||||||
...state, save_error, save_finished: false, save_processing: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const setSaveLoading: ActionHandler<typeof ActionCreators.setSaveLoading> = (state, { save_loading }) => ({
|
|
||||||
...state, save_loading
|
|
||||||
});
|
|
||||||
|
|
||||||
const setSaveOverwrite: ActionHandler<typeof ActionCreators.setSaveOverwrite> = (state) => ({
|
|
||||||
...state,
|
|
||||||
save_overwriting: true,
|
|
||||||
save_finished: false,
|
|
||||||
save_processing: false,
|
|
||||||
save_error: TIPS.SAVE_OVERWRITE,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setSaveSuccess: ActionHandler<typeof ActionCreators.setSaveSuccess> = (state, { save_error }) => ({
|
|
||||||
...state,
|
|
||||||
save_overwriting: false,
|
|
||||||
save_finished: true,
|
|
||||||
save_processing: false,
|
|
||||||
save_error,
|
|
||||||
});
|
|
||||||
|
|
||||||
const resetSaveDialog: ActionHandler<typeof ActionCreators.resetSaveDialog> = (state) => ({
|
|
||||||
...state, save_overwriting: false, save_finished: false, save_processing: false, save_error: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const hideRenderer: ActionHandler<typeof ActionCreators.hideRenderer> = (state) => ({
|
|
||||||
...state,
|
|
||||||
renderer: { ...state.renderer, renderer_active: false }
|
|
||||||
});
|
|
||||||
|
|
||||||
const setRenderer: ActionHandler<typeof ActionCreators.setRenderer> = (state, { payload }) => ({
|
|
||||||
...state,
|
|
||||||
renderer: { ...state.renderer, ...payload }
|
|
||||||
});
|
|
||||||
|
|
||||||
// const setProvider: ActionHandler<typeof ActionCreators.setProvider> = (state, { provider }) => ({ ...state, provider });
|
|
||||||
|
|
||||||
const setDialog: ActionHandler<typeof ActionCreators.setDialog> = (state, { dialog }) => ({
|
|
||||||
...state,
|
|
||||||
dialog,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setDialogActive: ActionHandler<typeof ActionCreators.setDialogActive> = (state, { dialog_active }) => ({
|
|
||||||
...state,
|
|
||||||
dialog_active: dialog_active || !state.dialog_active,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setReady: ActionHandler<typeof ActionCreators.setReady> = (state, { ready = true }) => ({
|
|
||||||
...state,
|
|
||||||
ready,
|
|
||||||
});
|
|
||||||
|
|
||||||
const searchSetTitle: ActionHandler<typeof ActionCreators.searchSetTitle> = (state, { title = '' }) => ({
|
const searchSetTitle: ActionHandler<typeof ActionCreators.searchSetTitle> = (state, { title = '' }) => ({
|
||||||
...state,
|
...state,
|
||||||
routes: {
|
routes: {
|
||||||
|
@ -199,17 +78,8 @@ const searchSetLoading: ActionHandler<typeof ActionCreators.searchSetLoading> =
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// const setPublic: ActionHandler<typeof ActionCreators.setPublic> = (state, { is_public = false }) => ({ ...state, is_public });
|
|
||||||
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 setSpeed: ActionHandler<typeof ActionCreators.setSpeed> = (state, { speed = 15 }) => ({
|
|
||||||
...state,
|
|
||||||
speed,
|
|
||||||
estimated: getEstimated(state.distance, speed),
|
|
||||||
});
|
|
||||||
|
|
||||||
const setMarkersShown: ActionHandler<typeof ActionCreators.setMarkersShown> = (state, { markers_shown = true }) => ({ ...state, markers_shown });
|
|
||||||
const setIsEmpty: ActionHandler<typeof ActionCreators.setIsEmpty> = (state, { is_empty = true }) => ({ ...state, is_empty });
|
|
||||||
const mapsSetShift: ActionHandler<typeof ActionCreators.mapsSetShift> = (state, { shift = 0 }) => ({
|
const mapsSetShift: ActionHandler<typeof ActionCreators.mapsSetShift> = (state, { shift = 0 }) => ({
|
||||||
...state,
|
...state,
|
||||||
routes: {
|
routes: {
|
||||||
|
@ -218,19 +88,6 @@ const mapsSetShift: ActionHandler<typeof ActionCreators.mapsSetShift> = (state,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const setFeature: ActionHandler<typeof ActionCreators.setFeature> = (state, { features }) => ({
|
|
||||||
...state,
|
|
||||||
features: {
|
|
||||||
...state.features,
|
|
||||||
...features,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const setIsRouting: ActionHandler<typeof ActionCreators.setIsRouting> = (state, { is_routing }) => ({
|
|
||||||
...state,
|
|
||||||
is_routing,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (state, { address, is_published }) => ({
|
const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (state, { address, is_published }) => ({
|
||||||
...state,
|
...state,
|
||||||
routes: {
|
routes: {
|
||||||
|
@ -248,33 +105,6 @@ const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (s
|
||||||
|
|
||||||
export const USER_HANDLERS = ({
|
export const USER_HANDLERS = ({
|
||||||
[USER_ACTIONS.SET_USER]: setUser,
|
[USER_ACTIONS.SET_USER]: setUser,
|
||||||
[USER_ACTIONS.SET_EDITING]: setEditing,
|
|
||||||
[USER_ACTIONS.SET_CHANGED]: setChanged,
|
|
||||||
[USER_ACTIONS.SET_MODE]: setMode,
|
|
||||||
[USER_ACTIONS.SET_DISTANCE]: setDistance,
|
|
||||||
[USER_ACTIONS.SET_ROUTER_POINTS]: setRouterPoints,
|
|
||||||
[USER_ACTIONS.SET_ACTIVE_STICKER]: setActiveSticker,
|
|
||||||
// [USER_ACTIONS.SET_LOGO]: setLogo,
|
|
||||||
// [USER_ACTIONS.SET_TITLE]: setTitle,
|
|
||||||
// [USER_ACTIONS.SET_DESCRIPTION]: setDescription,
|
|
||||||
// [USER_ACTIONS.SET_ADDRESS]: setAddress,
|
|
||||||
[USER_ACTIONS.SET_ADDRESS_ORIGIN]: setAddressOrigin,
|
|
||||||
|
|
||||||
[USER_ACTIONS.SET_SAVE_ERROR]: setSaveError,
|
|
||||||
[USER_ACTIONS.SET_SAVE_LOADING]: setSaveLoading,
|
|
||||||
[USER_ACTIONS.SET_SAVE_OVERWRITE]: setSaveOverwrite,
|
|
||||||
[USER_ACTIONS.SET_SAVE_SUCCESS]: setSaveSuccess,
|
|
||||||
[USER_ACTIONS.SEND_SAVE_REQUEST]: sendSaveRequest,
|
|
||||||
[USER_ACTIONS.RESET_SAVE_DIALOG]: resetSaveDialog,
|
|
||||||
|
|
||||||
[USER_ACTIONS.HIDE_RENDERER]: hideRenderer,
|
|
||||||
[USER_ACTIONS.SET_RENDERER]: setRenderer,
|
|
||||||
|
|
||||||
// [USER_ACTIONS.SET_PROVIDER]: setProvider,
|
|
||||||
|
|
||||||
[USER_ACTIONS.SET_DIALOG]: setDialog,
|
|
||||||
[USER_ACTIONS.SET_DIALOG_ACTIVE]: setDialogActive,
|
|
||||||
[USER_ACTIONS.SET_READY]: setReady,
|
|
||||||
|
|
||||||
[USER_ACTIONS.SEARCH_SET_TITLE]: searchSetTitle,
|
[USER_ACTIONS.SEARCH_SET_TITLE]: searchSetTitle,
|
||||||
[USER_ACTIONS.SEARCH_SET_DISTANCE]: searchSetDistance,
|
[USER_ACTIONS.SEARCH_SET_DISTANCE]: searchSetDistance,
|
||||||
|
@ -282,16 +112,10 @@ export const USER_HANDLERS = ({
|
||||||
[USER_ACTIONS.SEARCH_SET_TAB]: searchSetTab,
|
[USER_ACTIONS.SEARCH_SET_TAB]: searchSetTab,
|
||||||
[USER_ACTIONS.SEARCH_PUT_ROUTES]: searchPutRoutes,
|
[USER_ACTIONS.SEARCH_PUT_ROUTES]: searchPutRoutes,
|
||||||
[USER_ACTIONS.SEARCH_SET_LOADING]: searchSetLoading,
|
[USER_ACTIONS.SEARCH_SET_LOADING]: searchSetLoading,
|
||||||
// [USER_ACTIONS.SET_PUBLIC]: setPublic,
|
|
||||||
[USER_ACTIONS.SET_STARRED]: setStarred,
|
|
||||||
[USER_ACTIONS.SET_SPEED]: setSpeed,
|
|
||||||
|
|
||||||
[USER_ACTIONS.SET_MARKERS_SHOWN]: setMarkersShown,
|
|
||||||
[USER_ACTIONS.SET_IS_EMPTY]: setIsEmpty,
|
|
||||||
[USER_ACTIONS.MAPS_SET_SHIFT]: mapsSetShift,
|
[USER_ACTIONS.MAPS_SET_SHIFT]: mapsSetShift,
|
||||||
|
|
||||||
[USER_ACTIONS.SET_FEATURE]: setFeature,
|
[USER_ACTIONS.SET_STARRED]: setStarred,
|
||||||
[USER_ACTIONS.SET_IS_ROUTING]: setIsRouting,
|
|
||||||
|
|
||||||
[USER_ACTIONS.SET_ROUTE_STARRED]: setRouteStarred,
|
[USER_ACTIONS.SET_ROUTE_STARRED]: setRouteStarred,
|
||||||
});
|
});
|
|
@ -1,8 +1,5 @@
|
||||||
import { createReducer } from 'reduxsauce';
|
import { createReducer } from 'reduxsauce';
|
||||||
import { DEFAULT_USER, IUser } from '~/constants/auth';
|
import { DEFAULT_USER, IUser } from '~/constants/auth';
|
||||||
import { MODES } from '~/constants/modes';
|
|
||||||
import { DIALOGS, IDialogs } from '~/constants/dialogs';
|
|
||||||
import { IStickers } from "~/constants/stickers";
|
|
||||||
import { USER_HANDLERS } from './handlers';
|
import { USER_HANDLERS } from './handlers';
|
||||||
|
|
||||||
export interface IRouteListItem {
|
export interface IRouteListItem {
|
||||||
|
@ -15,50 +12,8 @@ export interface IRouteListItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRootReducer {
|
export interface IRootReducer {
|
||||||
ready: boolean,
|
// ready: boolean,
|
||||||
user: IUser,
|
user: IUser,
|
||||||
editing: boolean,
|
|
||||||
mode: typeof MODES[keyof typeof MODES],
|
|
||||||
// logo: keyof typeof LOGOS,
|
|
||||||
routerPoints: number,
|
|
||||||
distance: number,
|
|
||||||
// description: string,
|
|
||||||
estimated: number,
|
|
||||||
speed: number,
|
|
||||||
activeSticker: { set?: keyof IStickers, sticker?: string },
|
|
||||||
// title: string,
|
|
||||||
// address: string,
|
|
||||||
// address_origin: string,
|
|
||||||
changed: boolean,
|
|
||||||
// provider: keyof typeof PROVIDERS,
|
|
||||||
markers_shown: boolean,
|
|
||||||
|
|
||||||
is_published: boolean,
|
|
||||||
// is_public: boolean,
|
|
||||||
is_empty: boolean,
|
|
||||||
is_routing: boolean,
|
|
||||||
|
|
||||||
save_error: string,
|
|
||||||
save_finished: boolean,
|
|
||||||
save_overwriting: boolean,
|
|
||||||
save_processing: boolean,
|
|
||||||
save_loading: boolean,
|
|
||||||
|
|
||||||
dialog: IDialogs[keyof IDialogs],
|
|
||||||
dialog_active: boolean,
|
|
||||||
|
|
||||||
features: {
|
|
||||||
routing: boolean,
|
|
||||||
},
|
|
||||||
|
|
||||||
renderer: {
|
|
||||||
data: string,
|
|
||||||
width: number,
|
|
||||||
height: number
|
|
||||||
renderer_active: boolean,
|
|
||||||
info: string,
|
|
||||||
progress: number,
|
|
||||||
},
|
|
||||||
|
|
||||||
routes: {
|
routes: {
|
||||||
limit: 0,
|
limit: 0,
|
||||||
|
@ -81,53 +36,8 @@ export interface IRootReducer {
|
||||||
export type IRootState = Readonly<IRootReducer>;
|
export type IRootState = Readonly<IRootReducer>;
|
||||||
|
|
||||||
export const INITIAL_STATE: IRootReducer = {
|
export const INITIAL_STATE: IRootReducer = {
|
||||||
ready: false,
|
|
||||||
user: { ...DEFAULT_USER },
|
user: { ...DEFAULT_USER },
|
||||||
|
|
||||||
mode: MODES.NONE,
|
|
||||||
// logo: DEFAULT_LOGO,
|
|
||||||
routerPoints: 0,
|
|
||||||
distance: 0,
|
|
||||||
// description: '',
|
|
||||||
estimated: 0,
|
|
||||||
speed: 15,
|
|
||||||
activeSticker: { set: null, sticker: null },
|
|
||||||
// title: '',
|
|
||||||
// address: '',
|
|
||||||
// address_origin: '',
|
|
||||||
// provider: DEFAULT_PROVIDER,
|
|
||||||
|
|
||||||
markers_shown: true,
|
|
||||||
changed: false,
|
|
||||||
editing: false,
|
|
||||||
|
|
||||||
is_published: false,
|
|
||||||
// is_public: false,
|
|
||||||
is_empty: true,
|
|
||||||
is_routing: false,
|
|
||||||
|
|
||||||
save_error: '',
|
|
||||||
save_finished: false,
|
|
||||||
save_overwriting: false,
|
|
||||||
save_processing: false,
|
|
||||||
save_loading: false,
|
|
||||||
|
|
||||||
dialog: DIALOGS.NONE,
|
|
||||||
dialog_active: false,
|
|
||||||
|
|
||||||
features: {
|
|
||||||
routing: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
renderer: {
|
|
||||||
data: '',
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
renderer_active: false,
|
|
||||||
info: '',
|
|
||||||
progress: 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
routes: {
|
routes: {
|
||||||
limit: 0,
|
limit: 0,
|
||||||
loading: false, // <-- maybe delete this
|
loading: false, // <-- maybe delete this
|
||||||
|
|
|
@ -19,23 +19,23 @@ import {
|
||||||
sendRouteStarred,
|
sendRouteStarred,
|
||||||
} from '~/utils/api';
|
} from '~/utils/api';
|
||||||
import {
|
import {
|
||||||
hideRenderer,
|
// hideRenderer,
|
||||||
searchPutRoutes,
|
// setChanged,
|
||||||
searchSetLoading,
|
// setDialogActive,
|
||||||
setChanged,
|
// setEditing,
|
||||||
setDialogActive,
|
// setMode,
|
||||||
setEditing,
|
// setReady,
|
||||||
setMode,
|
// setRenderer,
|
||||||
setReady,
|
// setDialog,
|
||||||
setRenderer,
|
// setAddressOrigin,
|
||||||
|
// clearAll,
|
||||||
|
// setFeature,
|
||||||
searchSetTab,
|
searchSetTab,
|
||||||
setUser,
|
setUser,
|
||||||
setDialog,
|
|
||||||
setAddressOrigin,
|
|
||||||
mapsSetShift,
|
mapsSetShift,
|
||||||
searchChangeDistance,
|
searchChangeDistance,
|
||||||
clearAll,
|
searchPutRoutes,
|
||||||
setFeature,
|
searchSetLoading,
|
||||||
searchSetTitle,
|
searchSetTitle,
|
||||||
setRouteStarred,
|
setRouteStarred,
|
||||||
} from '~/redux/user/actions';
|
} from '~/redux/user/actions';
|
||||||
|
@ -48,43 +48,22 @@ import {
|
||||||
pushPath,
|
pushPath,
|
||||||
} from '~/utils/history';
|
} from '~/utils/history';
|
||||||
import { USER_ACTIONS } from '~/redux/user/constants';
|
import { USER_ACTIONS } from '~/redux/user/constants';
|
||||||
import { MODES } from '~/constants/modes';
|
|
||||||
import { DEFAULT_USER } from '~/constants/auth';
|
import { DEFAULT_USER } from '~/constants/auth';
|
||||||
import {
|
|
||||||
composeArrows,
|
|
||||||
composeDistMark,
|
|
||||||
composeImages,
|
|
||||||
composePoly,
|
|
||||||
composeStickers,
|
|
||||||
downloadCanvas,
|
|
||||||
fetchImages,
|
|
||||||
getPolyPlacement,
|
|
||||||
getStickersPlacement,
|
|
||||||
getTilePlacement,
|
|
||||||
imageFetcher,
|
|
||||||
} from '~/utils/renderer';
|
|
||||||
import { LOGOS } from '~/constants/logos';
|
|
||||||
import { DIALOGS, TABS } from '~/constants/dialogs';
|
import { DIALOGS, TABS } from '~/constants/dialogs';
|
||||||
|
|
||||||
import * as ActionCreators from '~/redux/user/actions';
|
import * as ActionCreators from '~/redux/user/actions';
|
||||||
import { downloadGPXTrack, getGPXString } from '~/utils/gpx';
|
|
||||||
import { Unwrap } from '~/utils/middleware';
|
import { Unwrap } from '~/utils/middleware';
|
||||||
import { IState } from '~/redux/store';
|
import { IState } from '~/redux/store';
|
||||||
import { selectUser, selectUserUser } from './selectors';
|
import { selectUser, selectUserUser } from './selectors';
|
||||||
import { mapInitSaga, loadMapSaga, replaceAddressIfItsBusy } from '~/redux/map/sagas';
|
import { mapInitSaga, loadMapSaga, replaceAddressIfItsBusy } from '~/redux/map/sagas';
|
||||||
import { LatLng } from 'leaflet';
|
import { editorSetDialog, editorSetDialogActive } from '../editor/actions';
|
||||||
import { selectMap } from '~/redux/map/selectors';
|
import { selectEditor } from '../editor/selectors';
|
||||||
|
import { EDITOR_ACTIONS } from '../editor/constants';
|
||||||
|
|
||||||
// const getUser = (state: IState) => state.user.user;
|
// const getUser = (state: IState) => state.user.user;
|
||||||
// const selectUser = (state: IState) => state.user;
|
// const selectUser = (state: IState) => state.user;
|
||||||
|
|
||||||
const hideLoader = () => {
|
|
||||||
document.getElementById('loader').style.opacity = String(0);
|
|
||||||
document.getElementById('loader').style.pointerEvents = 'none';
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
function* generateGuestSaga() {
|
function* generateGuestSaga() {
|
||||||
const {
|
const {
|
||||||
data: { user, random_url },
|
data: { user, random_url },
|
||||||
|
@ -95,52 +74,43 @@ function* generateGuestSaga() {
|
||||||
return { ...user, random_url };
|
return { ...user, random_url };
|
||||||
}
|
}
|
||||||
|
|
||||||
function* startEditingSaga() {
|
// function* stopEditingSaga() {
|
||||||
const { path } = getUrlData();
|
// const { changed, editing, mode, address_origin } = yield select(selectUser);
|
||||||
yield pushPath(`/${path}/edit`);
|
// const { path } = getUrlData();
|
||||||
}
|
|
||||||
|
|
||||||
function* stopEditingSaga() {
|
// if (!editing) return;
|
||||||
const { changed, editing, mode, address_origin } = yield select(selectUser);
|
// if (changed && mode !== MODES.CONFIRM_CANCEL) {
|
||||||
const { path } = getUrlData();
|
// yield put(setMode(MODES.CONFIRM_CANCEL));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
if (!editing) return;
|
// yield put(setMode(MODES.NONE));
|
||||||
if (changed && mode !== MODES.CONFIRM_CANCEL) {
|
// yield put(setChanged(false));
|
||||||
yield put(setMode(MODES.CONFIRM_CANCEL));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: cancel editing?
|
// yield pushPath(`/${address_origin || path}/`);
|
||||||
// yield editor.cancelEditing();
|
// }
|
||||||
yield put(setMode(MODES.NONE));
|
|
||||||
yield put(setChanged(false));
|
|
||||||
// TODO: dont close editor if theres no initial data
|
|
||||||
// yield put(setEditing(editor.hasEmptyHistory)); // don't close editor if no previous map
|
|
||||||
|
|
||||||
yield pushPath(`/${address_origin || path}/`);
|
// function* checkOSRMServiceSaga() {
|
||||||
}
|
// const routing = yield call(checkOSRMService, [new LatLng(1,1), new LatLng(2,2)]);
|
||||||
|
|
||||||
function* checkOSRMServiceSaga() {
|
// yield put(setFeature({ routing }));
|
||||||
const routing = yield call(checkOSRMService, [new LatLng(1,1), new LatLng(2,2)]);
|
// }
|
||||||
|
|
||||||
yield put(setFeature({ routing }));
|
// export function* setReadySaga() {
|
||||||
}
|
// yield put(setReady(true));
|
||||||
|
// hideLoader();
|
||||||
|
|
||||||
export function* setReadySaga() {
|
// yield call(checkOSRMServiceSaga);
|
||||||
yield put(setReady(true));
|
// yield put(searchSetTab(TABS.MY));
|
||||||
hideLoader();
|
// }
|
||||||
|
|
||||||
yield call(checkOSRMServiceSaga);
|
|
||||||
yield put(searchSetTab(TABS.MY));
|
|
||||||
}
|
|
||||||
|
|
||||||
function* authCheckSaga({ key }: RehydrateAction) {
|
function* authCheckSaga({ key }: RehydrateAction) {
|
||||||
if (key !== 'user') return;
|
if (key !== 'user') return;
|
||||||
|
|
||||||
pushLoaderState(70);
|
pushLoaderState(70);
|
||||||
|
|
||||||
const { id, token } = yield select(selectUserUser);
|
const { id, token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
const { ready } = yield select(selectUser);
|
const { ready }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
if (window.location.search || true) {
|
if (window.location.search || true) {
|
||||||
const { viewer_id, auth_key } = yield parseQuery(window.location.search);
|
const { viewer_id, auth_key } = yield parseQuery(window.location.search);
|
||||||
|
@ -215,128 +185,127 @@ function* authCheckSaga({ key }: RehydrateAction) {
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// function* getRenderData() {
|
||||||
|
// yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 }));
|
||||||
|
|
||||||
function* getRenderData() {
|
// const { route, stickers, provider }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 }));
|
|
||||||
|
|
||||||
const { route, stickers, provider }: ReturnType<typeof selectMap> = yield select(selectMap);
|
// const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
||||||
|
// canvas.width = window.innerWidth;
|
||||||
|
// canvas.height = window.innerHeight;
|
||||||
|
// const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
// const geometry = getTilePlacement();
|
||||||
canvas.width = window.innerWidth;
|
// const points = getPolyPlacement(route);
|
||||||
canvas.height = window.innerHeight;
|
// const sticker_points = getStickersPlacement(stickers);
|
||||||
const ctx = canvas.getContext('2d');
|
// // TODO: get distance:
|
||||||
|
// const distance = 0;
|
||||||
|
// // const distance = editor.poly.poly.distance;
|
||||||
|
|
||||||
const geometry = getTilePlacement();
|
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
const points = getPolyPlacement(route);
|
|
||||||
const sticker_points = getStickersPlacement(stickers);
|
|
||||||
// TODO: get distance:
|
|
||||||
const distance = 0;
|
|
||||||
// const distance = editor.poly.poly.distance;
|
|
||||||
|
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
// const images = yield fetchImages(ctx, geometry, provider);
|
||||||
|
|
||||||
const images = yield fetchImages(ctx, geometry, provider);
|
// yield put(setRenderer({ info: 'Отрисовка', progress: 0.5 }));
|
||||||
|
|
||||||
yield put(setRenderer({ info: 'Отрисовка', progress: 0.5 }));
|
// yield composeImages({ geometry, images, ctx });
|
||||||
|
// yield composePoly({ points, ctx });
|
||||||
|
// yield composeArrows({ points, ctx });
|
||||||
|
// yield composeDistMark({ ctx, points, distance });
|
||||||
|
// yield composeStickers({ stickers: sticker_points, ctx });
|
||||||
|
|
||||||
yield composeImages({ geometry, images, ctx });
|
// yield put(setRenderer({ info: 'Готово', progress: 1 }));
|
||||||
yield composePoly({ points, ctx });
|
|
||||||
yield composeArrows({ points, ctx });
|
|
||||||
yield composeDistMark({ ctx, points, distance });
|
|
||||||
yield composeStickers({ stickers: sticker_points, ctx });
|
|
||||||
|
|
||||||
yield put(setRenderer({ info: 'Готово', progress: 1 }));
|
// return yield canvas.toDataURL('image/jpeg');
|
||||||
|
// }
|
||||||
|
|
||||||
return yield canvas.toDataURL('image/jpeg');
|
// function* takeAShotSaga() {
|
||||||
}
|
// const worker = call(getRenderData);
|
||||||
|
|
||||||
function* takeAShotSaga() {
|
// const { result, timeout } = yield race({
|
||||||
const worker = call(getRenderData);
|
// result: worker,
|
||||||
|
// timeout: delay(500),
|
||||||
|
// });
|
||||||
|
|
||||||
const { result, timeout } = yield race({
|
// if (timeout) yield put(setMode(MODES.SHOT_PREFETCH));
|
||||||
result: worker,
|
|
||||||
timeout: delay(500),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (timeout) yield put(setMode(MODES.SHOT_PREFETCH));
|
// const data = yield result || worker;
|
||||||
|
|
||||||
const data = yield result || worker;
|
// yield put(setMode(MODES.NONE));
|
||||||
|
// yield put(
|
||||||
|
// setRenderer({
|
||||||
|
// data,
|
||||||
|
// renderer_active: true,
|
||||||
|
// width: window.innerWidth,
|
||||||
|
// height: window.innerHeight,
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
yield put(setMode(MODES.NONE));
|
// function* getCropData({ x, y, width, height }) {
|
||||||
yield put(
|
// const {
|
||||||
setRenderer({
|
// logo,
|
||||||
data,
|
// renderer: { data },
|
||||||
renderer_active: true,
|
// } = yield select(selectUser);
|
||||||
width: window.innerWidth,
|
// const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
||||||
height: window.innerHeight,
|
// canvas.width = width;
|
||||||
})
|
// canvas.height = height;
|
||||||
);
|
// const ctx = canvas.getContext('2d');
|
||||||
}
|
// const image = yield imageFetcher(data);
|
||||||
|
|
||||||
function* getCropData({ x, y, width, height }) {
|
// ctx.drawImage(image, -x, -y);
|
||||||
const {
|
|
||||||
logo,
|
|
||||||
renderer: { data },
|
|
||||||
} = yield select(selectUser);
|
|
||||||
const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const image = yield imageFetcher(data);
|
|
||||||
|
|
||||||
ctx.drawImage(image, -x, -y);
|
// if (logo && LOGOS[logo][1]) {
|
||||||
|
// const logoImage = yield imageFetcher(LOGOS[logo][1]);
|
||||||
|
// ctx.drawImage(logoImage, width - logoImage.width, height - logoImage.height);
|
||||||
|
// }
|
||||||
|
|
||||||
if (logo && LOGOS[logo][1]) {
|
// return yield canvas.toDataURL('image/jpeg');
|
||||||
const logoImage = yield imageFetcher(LOGOS[logo][1]);
|
// }
|
||||||
ctx.drawImage(logoImage, width - logoImage.width, height - logoImage.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return yield canvas.toDataURL('image/jpeg');
|
// function* cropAShotSaga(params) {
|
||||||
}
|
// const { title, address } = yield select(selectUser);
|
||||||
|
// yield call(getCropData, params);
|
||||||
|
// const canvas = document.getElementById('renderer') as HTMLCanvasElement;
|
||||||
|
|
||||||
function* cropAShotSaga(params) {
|
// downloadCanvas(canvas, (title || address).replace(/\./gi, ' '));
|
||||||
const { title, address } = yield select(selectUser);
|
|
||||||
yield call(getCropData, params);
|
|
||||||
const canvas = document.getElementById('renderer') as HTMLCanvasElement;
|
|
||||||
|
|
||||||
downloadCanvas(canvas, (title || address).replace(/\./gi, ' '));
|
// return yield put(hideRenderer());
|
||||||
|
// }
|
||||||
|
|
||||||
return yield put(hideRenderer());
|
// function* locationChangeSaga({ location }: ReturnType<typeof ActionCreators.locationChanged>) {
|
||||||
}
|
// const {
|
||||||
|
// address,
|
||||||
|
// ready,
|
||||||
|
// user: { id, random_url },
|
||||||
|
// } = yield select(selectUser);
|
||||||
|
|
||||||
function* locationChangeSaga({ location }: ReturnType<typeof ActionCreators.locationChanged>) {
|
// const { owner }: ReturnType<typeof selectMap> = yield select(selectMap)
|
||||||
const {
|
|
||||||
address,
|
|
||||||
ready,
|
|
||||||
user: { id, random_url },
|
|
||||||
} = yield select(selectUser);
|
|
||||||
|
|
||||||
const { owner }: ReturnType<typeof selectMap> = yield select(selectMap)
|
// if (!ready) return;
|
||||||
|
|
||||||
if (!ready) return;
|
// const { path, mode } = getUrlData(location);
|
||||||
|
|
||||||
const { path, mode } = getUrlData(location);
|
// if (address !== path) {
|
||||||
|
// const map = yield call(loadMapSaga, path);
|
||||||
|
|
||||||
if (address !== path) {
|
// if (map && map.route && map.route.owner && mode === 'edit' && map.route.owner !== id) {
|
||||||
const map = yield call(loadMapSaga, path);
|
// return yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
||||||
|
// }
|
||||||
|
// } else if (mode === 'edit' && owner.id !== id) {
|
||||||
|
// return yield call(replaceAddressIfItsBusy, random_url, address);
|
||||||
|
// } else {
|
||||||
|
// yield put(setAddressOrigin(''));
|
||||||
|
// }
|
||||||
|
|
||||||
if (map && map.route && map.route.owner && mode === 'edit' && map.route.owner !== id) {
|
// if (mode !== 'edit') {
|
||||||
return yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
// yield put(setEditing(false));
|
||||||
}
|
// // editor.stopEditing();
|
||||||
} else if (mode === 'edit' && owner.id !== id) {
|
// } else {
|
||||||
return yield call(replaceAddressIfItsBusy, random_url, address);
|
// yield put(setEditing(true));
|
||||||
} else {
|
// // editor.startEditing();
|
||||||
yield put(setAddressOrigin(''));
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (mode !== 'edit') {
|
|
||||||
yield put(setEditing(false));
|
|
||||||
// editor.stopEditing();
|
|
||||||
} else {
|
|
||||||
yield put(setEditing(true));
|
|
||||||
// editor.startEditing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function* gotVkUserSaga({ user: u }: ReturnType<typeof ActionCreators.gotVkUser>) {
|
function* gotVkUserSaga({ user: u }: ReturnType<typeof ActionCreators.gotVkUser>) {
|
||||||
const {
|
const {
|
||||||
|
@ -346,40 +315,40 @@ function* gotVkUserSaga({ user: u }: ReturnType<typeof ActionCreators.gotVkUser>
|
||||||
yield put(setUser({ ...user, random_url }));
|
yield put(setUser({ ...user, random_url }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* keyPressedSaga({ key, target }: ReturnType<typeof ActionCreators.keyPressed>): any {
|
// function* keyPressedSaga({ key, target }: ReturnType<typeof ActionCreators.keyPressed>): any {
|
||||||
if (target === 'INPUT' || target === 'TEXTAREA') {
|
// if (target === 'INPUT' || target === 'TEXTAREA') {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (key === 'Escape') {
|
// if (key === 'Escape') {
|
||||||
const {
|
// const {
|
||||||
dialog_active,
|
// dialog_active,
|
||||||
mode,
|
// mode,
|
||||||
renderer: { renderer_active },
|
// renderer: { renderer_active },
|
||||||
} = yield select(selectUser);
|
// } = yield select(selectUser);
|
||||||
|
|
||||||
if (renderer_active) return yield put(hideRenderer());
|
// if (renderer_active) return yield put(hideRenderer());
|
||||||
if (dialog_active) return yield put(setDialogActive(false));
|
// if (dialog_active) return yield put(setDialogActive(false));
|
||||||
if (mode !== MODES.NONE) return yield put(setMode(MODES.NONE));
|
// if (mode !== MODES.NONE) return yield put(setMode(MODES.NONE));
|
||||||
} else if (key === 'Delete') {
|
// } else if (key === 'Delete') {
|
||||||
const {
|
// const {
|
||||||
user: { editing },
|
// user: { editing },
|
||||||
} = yield select();
|
// } = yield select();
|
||||||
|
|
||||||
if (!editing) return;
|
// if (!editing) return;
|
||||||
|
|
||||||
const { mode } = yield select(selectUser);
|
// const { mode } = yield select(selectUser);
|
||||||
|
|
||||||
if (mode === MODES.TRASH) {
|
// if (mode === MODES.TRASH) {
|
||||||
yield put(clearAll());
|
// yield put(clearAll());
|
||||||
} else {
|
// } else {
|
||||||
yield put(setMode(MODES.TRASH));
|
// yield put(setMode(MODES.TRASH));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
function* searchGetRoutes() {
|
function* searchGetRoutes() {
|
||||||
const { token } = yield select(selectUserUser);
|
const { token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
routes: {
|
routes: {
|
||||||
|
@ -387,7 +356,7 @@ function* searchGetRoutes() {
|
||||||
shift,
|
shift,
|
||||||
filter: { title, distance, tab },
|
filter: { title, distance, tab },
|
||||||
},
|
},
|
||||||
} = yield select(selectUser);
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
|
||||||
const result: Unwrap<typeof getRouteList> = yield getRouteList({
|
const result: Unwrap<typeof getRouteList> = yield getRouteList({
|
||||||
token,
|
token,
|
||||||
|
@ -442,14 +411,17 @@ function* searchSetSaga() {
|
||||||
|
|
||||||
function* openMapDialogSaga({ tab }: ReturnType<typeof ActionCreators.openMapDialog>) {
|
function* openMapDialogSaga({ tab }: ReturnType<typeof ActionCreators.openMapDialog>) {
|
||||||
const {
|
const {
|
||||||
dialog_active,
|
|
||||||
routes: {
|
routes: {
|
||||||
filter: { tab: current },
|
filter: { tab: current },
|
||||||
},
|
},
|
||||||
} = yield select(selectUser);
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
|
||||||
|
const {
|
||||||
|
dialog_active,
|
||||||
|
}: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
if (dialog_active && tab === current) {
|
if (dialog_active && tab === current) {
|
||||||
return yield put(setDialogActive(false));
|
return yield put(editorSetDialogActive(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab !== current) {
|
if (tab !== current) {
|
||||||
|
@ -457,8 +429,8 @@ function* openMapDialogSaga({ tab }: ReturnType<typeof ActionCreators.openMapDia
|
||||||
yield put(searchSetTab(tab));
|
yield put(searchSetTab(tab));
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(setDialog(DIALOGS.MAP_LIST));
|
yield put(editorSetDialog(DIALOGS.MAP_LIST));
|
||||||
yield put(setDialogActive(true));
|
yield put(editorSetDialogActive(true));
|
||||||
|
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
@ -476,28 +448,28 @@ function* userLogoutSaga(): SagaIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setUserSaga() {
|
function* setUserSaga() {
|
||||||
const { dialog_active } = yield select(selectUser);
|
const { dialog_active }: ReturnType<typeof selectEditor> = yield select(selectEditor);
|
||||||
|
|
||||||
if (dialog_active) yield call(searchSetSagaWorker);
|
if (dialog_active) yield call(searchSetSagaWorker);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* getGPXTrackSaga(): SagaIterator {
|
// function* getGPXTrackSaga(): SagaIterator {
|
||||||
const { route, stickers }: ReturnType<typeof selectMap> = yield select(selectMap);
|
// const { route, stickers }: ReturnType<typeof selectMap> = yield select(selectMap);
|
||||||
const { title, address } = yield select(selectUser);
|
// const { title, address } = yield select(selectUser);
|
||||||
|
|
||||||
if (!route || route.length <= 0) return;
|
// if (!route || route.length <= 0) return;
|
||||||
|
|
||||||
const track = getGPXString({ route, stickers, title: title || address });
|
// const track = getGPXString({ route, stickers, title: title || address });
|
||||||
|
|
||||||
return downloadGPXTrack({ track, title });
|
// return downloadGPXTrack({ track, title });
|
||||||
}
|
// }
|
||||||
|
|
||||||
function* mapsLoadMoreSaga() {
|
function* mapsLoadMoreSaga() {
|
||||||
const {
|
const {
|
||||||
routes: { limit, list, shift, step, loading, filter },
|
routes: { limit, list, shift, step, loading, filter },
|
||||||
} = yield select(selectUser);
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
|
||||||
if (loading || list.length >= limit || limit === 0) return;
|
if (loading || list.length >= limit || limit === 0) return;
|
||||||
|
|
||||||
|
@ -540,7 +512,7 @@ function* mapsLoadMoreSaga() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function* dropRouteSaga({ address }: ReturnType<typeof ActionCreators.dropRoute>): SagaIterator {
|
function* dropRouteSaga({ address }: ReturnType<typeof ActionCreators.dropRoute>): SagaIterator {
|
||||||
const { token } = yield select(selectUserUser);
|
const { token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
const {
|
const {
|
||||||
routes: {
|
routes: {
|
||||||
list,
|
list,
|
||||||
|
@ -549,7 +521,7 @@ function* dropRouteSaga({ address }: ReturnType<typeof ActionCreators.dropRoute>
|
||||||
limit,
|
limit,
|
||||||
filter: { min, max },
|
filter: { min, max },
|
||||||
},
|
},
|
||||||
} = yield select(selectUser);
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
|
||||||
const index = list.findIndex(el => el.address === address);
|
const index = list.findIndex(el => el.address === address);
|
||||||
|
|
||||||
|
@ -574,7 +546,7 @@ function* modifyRouteSaga({
|
||||||
title,
|
title,
|
||||||
is_public,
|
is_public,
|
||||||
}: ReturnType<typeof ActionCreators.modifyRoute>): SagaIterator {
|
}: ReturnType<typeof ActionCreators.modifyRoute>): SagaIterator {
|
||||||
const { token } = yield select(selectUserUser);
|
const { token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
const {
|
const {
|
||||||
routes: {
|
routes: {
|
||||||
list,
|
list,
|
||||||
|
@ -606,12 +578,12 @@ function* modifyRouteSaga({
|
||||||
function* toggleRouteStarredSaga({
|
function* toggleRouteStarredSaga({
|
||||||
address,
|
address,
|
||||||
}: ReturnType<typeof ActionCreators.toggleRouteStarred>) {
|
}: ReturnType<typeof ActionCreators.toggleRouteStarred>) {
|
||||||
|
const { token }: ReturnType<typeof selectUserUser> = yield select(selectUserUser);
|
||||||
const {
|
const {
|
||||||
routes: { list },
|
routes: { list },
|
||||||
}: IState['user'] = yield select(selectUser);
|
}: ReturnType<typeof selectUser> = yield select(selectUser);
|
||||||
|
|
||||||
const route = list.find(el => el.address === address);
|
const route = list.find(el => el.address === address);
|
||||||
const { token } = yield select(selectUserUser);
|
|
||||||
|
|
||||||
yield put(setRouteStarred(address, !route.is_published));
|
yield put(setRouteStarred(address, !route.is_published));
|
||||||
const result = yield sendRouteStarred({
|
const result = yield sendRouteStarred({
|
||||||
|
@ -624,24 +596,24 @@ function* toggleRouteStarredSaga({
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* userSaga() {
|
export function* userSaga() {
|
||||||
|
// yield takeEvery(USER_ACTIONS.STOP_EDITING, stopEditingSaga);
|
||||||
|
// yield takeLatest(USER_ACTIONS.TAKE_A_SHOT, takeAShotSaga);
|
||||||
|
// yield takeLatest(USER_ACTIONS.CROP_A_SHOT, cropAShotSaga);
|
||||||
|
// yield takeLatest(USER_ACTIONS.LOCATION_CHANGED, locationChangeSaga);
|
||||||
|
// yield takeLatest(USER_ACTIONS.KEY_PRESSED, keyPressedSaga);
|
||||||
|
// yield takeLatest(USER_ACTIONS.GET_GPX_TRACK, getGPXTrackSaga);
|
||||||
|
|
||||||
yield takeLatest(REHYDRATE, authCheckSaga);
|
yield takeLatest(REHYDRATE, authCheckSaga);
|
||||||
|
|
||||||
yield takeEvery(USER_ACTIONS.START_EDITING, startEditingSaga);
|
|
||||||
yield takeEvery(USER_ACTIONS.STOP_EDITING, stopEditingSaga);
|
|
||||||
|
|
||||||
yield takeEvery(USER_ACTIONS.USER_LOGOUT, userLogoutSaga);
|
yield takeEvery(USER_ACTIONS.USER_LOGOUT, userLogoutSaga);
|
||||||
|
|
||||||
// yield takeEvery(USER_ACTIONS.ROUTER_CANCEL, routerCancelSaga);
|
// yield takeEvery(USER_ACTIONS.ROUTER_CANCEL, routerCancelSaga);
|
||||||
// yield takeEvery(USER_ACTIONS.ROUTER_SUBMIT, routerSubmitSaga);
|
// yield takeEvery(USER_ACTIONS.ROUTER_SUBMIT, routerSubmitSaga);
|
||||||
|
|
||||||
yield takeLatest(USER_ACTIONS.TAKE_A_SHOT, takeAShotSaga);
|
|
||||||
yield takeLatest(USER_ACTIONS.CROP_A_SHOT, cropAShotSaga);
|
|
||||||
|
|
||||||
// yield takeEvery(USER_ACTIONS.CHANGE_PROVIDER, changeProviderSaga);
|
// yield takeEvery(USER_ACTIONS.CHANGE_PROVIDER, changeProviderSaga);
|
||||||
yield takeLatest(USER_ACTIONS.LOCATION_CHANGED, locationChangeSaga);
|
|
||||||
|
|
||||||
yield takeLatest(USER_ACTIONS.GOT_VK_USER, gotVkUserSaga);
|
yield takeLatest(USER_ACTIONS.GOT_VK_USER, gotVkUserSaga);
|
||||||
yield takeLatest(USER_ACTIONS.KEY_PRESSED, keyPressedSaga);
|
|
||||||
|
|
||||||
// yield takeLatest(USER_ACTIONS.SET_TITLE, setTitleSaga);
|
// yield takeLatest(USER_ACTIONS.SET_TITLE, setTitleSaga);
|
||||||
|
|
||||||
|
@ -654,7 +626,6 @@ export function* userSaga() {
|
||||||
yield takeLatest(USER_ACTIONS.SEARCH_SET_TAB, searchSetTabSaga);
|
yield takeLatest(USER_ACTIONS.SEARCH_SET_TAB, searchSetTabSaga);
|
||||||
yield takeLatest(USER_ACTIONS.SET_USER, setUserSaga);
|
yield takeLatest(USER_ACTIONS.SET_USER, setUserSaga);
|
||||||
|
|
||||||
yield takeLatest(USER_ACTIONS.GET_GPX_TRACK, getGPXTrackSaga);
|
|
||||||
yield takeLatest(USER_ACTIONS.MAPS_LOAD_MORE, mapsLoadMoreSaga);
|
yield takeLatest(USER_ACTIONS.MAPS_LOAD_MORE, mapsLoadMoreSaga);
|
||||||
|
|
||||||
yield takeLatest(USER_ACTIONS.DROP_ROUTE, dropRouteSaga);
|
yield takeLatest(USER_ACTIONS.DROP_ROUTE, dropRouteSaga);
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
import { IState } from '~/redux/store'
|
import { IState } from '~/redux/store'
|
||||||
|
|
||||||
export const selectUser = (state: IState) => state.user;
|
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 selectUserEditing = (state: IState) => state.user.editing;
|
|
||||||
export const selectUserMode = (state: IState) => state.user.mode;
|
|
||||||
export const selectUserActiveSticker = (state: IState) => state.user.activeSticker;
|
|
||||||
export const selectUserRenderer = (state: IState) => state.user.renderer;
|
|
|
@ -164,4 +164,7 @@ export const toTranslit = (string: string = ''): string =>
|
||||||
|
|
||||||
export const parseDesc = (text: string = ''): string => text.replace(/(\n{2,})/gi, '\n\n');
|
export const parseDesc = (text: string = ''): string => text.replace(/(\n{2,})/gi, '\n\n');
|
||||||
|
|
||||||
// export const colorizeTitle = (text: string): string => text.replace(/(\[[^\]^]+\])/, ``)
|
export const getEstimated = (distance: number, speed: number = 15): number => {
|
||||||
|
const time = (distance && (distance / speed)) || 0;
|
||||||
|
return (time && parseFloat(time.toFixed(1)));
|
||||||
|
};
|
|
@ -23,5 +23,8 @@
|
||||||
"./src/index.tsx",
|
"./src/index.tsx",
|
||||||
"./backend/**/*",
|
"./backend/**/*",
|
||||||
"./custom.d.ts"
|
"./custom.d.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"./src/_modules/**/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue