moved editor to separate reducer

This commit is contained in:
Fedor Katurov 2020-01-09 10:59:26 +07:00
parent e950d98b73
commit 87670770b0
38 changed files with 1425 additions and 1069 deletions

View file

@ -2,21 +2,23 @@ import React from 'react';
import { MODES } from '~/constants/modes';
import { Icon } from '~/components/panels/Icon';
import { setMode, stopEditing } from "~/redux/user/actions";
import { editorSetMode, editorStopEditing } from '~/redux/editor/actions';
type Props = {
stopEditing: typeof stopEditing,
setMode: typeof setMode,
width: number,
const mapStateToProps = () => ({});
const mapDispatchToProps = {
editorSetMode,
editorStopEditing,
};
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width?: number };
export class CancelDialog extends React.Component<Props, void> {
cancel = () => {
this.props.stopEditing();
this.props.editorStopEditing();
};
proceed = () => {
this.props.setMode(MODES.NONE);
this.props.editorSetMode(MODES.NONE);
};
render() {

View file

@ -6,12 +6,14 @@ import {
searchSetDistance,
searchSetTitle,
searchSetTab,
setDialogActive,
mapsLoadMore,
dropRoute,
modifyRoute,
toggleRouteStarred,
} from '~/redux/user/actions';
import { editorSetDialogActive } from '~/redux/editor/actions';
import { isMobile } from '~/utils/window';
import classnames from 'classnames';
@ -19,28 +21,60 @@ import Range from 'rc-slider/lib/Range';
import { TABS, TABS_TITLES } from '~/constants/dialogs';
import { Icon } from '~/components/panels/Icon';
import { pushPath } from '~/utils/history';
import { IRootState, IRouteListItem } from '~/redux/user';
import { IRouteListItem } from '~/redux/user';
import { ROLES } from '~/constants/auth';
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;
searchSetDistance: typeof searchSetDistance;
searchSetTitle: typeof searchSetTitle;
searchSetTab: typeof searchSetTab;
setDialogActive: typeof setDialogActive;
dropRoute: typeof dropRoute;
modifyRoute: typeof modifyRoute;
toggleRouteStarred: typeof toggleRouteStarred;
}
const mapStateToProps = ({
editor: { editing },
user: {
routes,
user: { role },
},
}: IState) => {
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'];
editor_target: IRouteListItem['address'];
@ -48,7 +82,7 @@ export interface IMapListDialogState {
is_dropping: boolean;
}
class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMapListDialogState> {
class MapListDialogUnconnected extends React.Component<Props, State> {
state = {
menu_target: null,
editor_target: null,
@ -92,14 +126,11 @@ class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMap
};
openRoute = (_id: string): void => {
if (isMobile()) this.props.setDialogActive(false);
if (isMobile()) this.props.editorSetDialogActive(false);
// pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`);
this.stopEditing();
pushPath(`/${_id}`);
// pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`);
};
onScroll = (e: {
@ -148,7 +179,7 @@ class MapListDialogUnconnected extends React.Component<IMapListDialogProps, IMap
filter: { min, max, title, distance, tab },
},
marks,
}: IMapListDialogProps = this.props;
}: Props = this.props;
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);

View file

@ -1,9 +1,6 @@
import React from 'react';
import { Icon } from '~/components/panels/Icon';
import {
routerCancel as routerCancelAction,
routerSubmit as routerSubmitAction,
} from "~/redux/user/actions";
import * as EDITOR_ACTIONS from '~/redux/editor/actions'
import classnames from "classnames";
type Props = {
@ -11,11 +8,11 @@ type Props = {
width: number,
is_routing: boolean,
routerCancel: typeof routerCancelAction,
routerSubmit: typeof routerSubmitAction,
editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel,
editorRouterSubmit: typeof EDITOR_ACTIONS.editorRouterSubmit,
}
const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction }) => (
const noPoints = ({ editorRouterCancel }: { editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel }) => (
<React.Fragment>
<div className="helper router-helper">
<div className="helper__text">
@ -28,7 +25,7 @@ const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction })
<div className="helper router-helper">
<div className="helper__buttons flex_1">
<div className="flex_1" />
<div className="button router-helper__button" onClick={routerCancel}>
<div className="button router-helper__button" onClick={editorRouterCancel}>
Отмена
</div>
</div>
@ -36,7 +33,7 @@ const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction })
</React.Fragment>
);
const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction }) => (
const firstPoint = ({ editorRouterCancel }: { editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel }) => (
<React.Fragment>
<div className="helper router-helper">
<div className="helper__text">
@ -47,7 +44,7 @@ const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction
<div className="helper router-helper">
<div className="helper__buttons flex_1">
<div className="flex_1" />
<div className="button router-helper__button" onClick={routerCancel}>
<div className="button router-helper__button" onClick={editorRouterCancel}>
Отмена
</div>
</div>
@ -56,10 +53,10 @@ const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction
);
const draggablePoints = ({
routerCancel, routerSubmit
editorRouterCancel, editorRouterSubmit
}: {
routerCancel: typeof routerCancelAction,
routerSubmit: typeof routerSubmitAction,
editorRouterCancel: typeof EDITOR_ACTIONS.editorRouterCancel,
editorRouterSubmit: typeof EDITOR_ACTIONS.editorRouterSubmit,
}) => (
<React.Fragment>
<div className="helper">
@ -71,10 +68,10 @@ const draggablePoints = ({
<div className="helper router-helper">
<div className="helper__buttons button-group 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 className="button primary router-helper__button" onClick={routerSubmit}>
<div className="button primary router-helper__button" onClick={editorRouterSubmit}>
Применить
</div>
</div>
@ -83,13 +80,13 @@ const draggablePoints = ({
);
export const RouterDialog = ({
routerPoints, routerCancel, routerSubmit, width, is_routing,
routerPoints, editorRouterCancel, editorRouterSubmit, width, is_routing,
}: Props) => (
<div className="control-dialog" style={{ width }}>
<div className={classnames('save-loader', { active: is_routing })} />
{!routerPoints && noPoints({ routerCancel })}
{routerPoints === 1 && firstPoint({ routerCancel })}
{routerPoints >= 2 && draggablePoints({ routerCancel, routerSubmit })}
{!routerPoints && noPoints({ editorRouterCancel })}
{routerPoints === 1 && firstPoint({ editorRouterCancel })}
{routerPoints >= 2 && draggablePoints({ editorRouterCancel, editorRouterSubmit })}
</div>
);

View file

@ -10,17 +10,17 @@ import classnames from 'classnames';
import ExpandableTextarea from 'react-expandable-textarea';
import { connect } from 'react-redux';
import { selectMap } from '~/redux/map/selectors';
import { selectUser } from '~/redux/user/selectors';
import * as USER_ACTIONS from '~/redux/user/actions';
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
import { selectEditor } from '~/redux/editor/selectors';
const mapStateToProps = state => ({
map: selectMap(state),
user: selectUser(state),
editor: selectEditor(state),
});
const mapDispatchToProps = {
setMode: USER_ACTIONS.setMode,
sendSaveRequest: USER_ACTIONS.sendSaveRequest,
editorSetMode: EDITOR_ACTIONS.editorSetMode,
editorSendSaveRequest: EDITOR_ACTIONS.editorSendSaveRequest,
};
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & { width: number };
@ -33,14 +33,14 @@ interface State {
}
class SaveDialogUnconnected extends React.Component<Props, State> {
constructor(props) {
constructor(props: Props) {
super(props);
this.state = {
address: props.address || '',
title: props.title || '',
is_public: props.is_public || false,
description: props.description || '',
address: props.map.address || '',
title: props.map.title || '',
is_public: props.map.is_public || false,
description: props.map.description || '',
};
}
@ -57,16 +57,18 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
setTitle = ({ target: { value } }) =>
this.setState({ title: (value && value.substr(0, 64)) || '' });
setAddress = ({ target: { value } }) =>
this.setState({ address: (value && value.substr(0, 32)) || '' });
setDescription = ({ target: { value } }) =>
this.setState({ description: (value && value.substr(0, 256)) || '' });
sendSaveRequest = (e, force = false) => {
editorSendSaveRequest = (e, force = false) => {
const { title, is_public, description } = this.state;
const address = this.getAddress();
this.props.sendSaveRequest({
this.props.editorSendSaveRequest({
title,
address,
force,
@ -74,9 +76,10 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
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 => {
e.preventDefault();
@ -91,7 +94,7 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
render() {
const { title, is_public, description } = this.state;
const {
user: { save_error, save_finished, save_overwriting, save_loading },
editor: { save_error, save_finished, save_overwriting, save_loading },
width,
} = this.props;
const { host, protocol } = getUrlData();
@ -157,7 +160,7 @@ class SaveDialogUnconnected extends React.Component<Props, State> {
</div>
)}
{!save_finished && !save_overwriting && (
<div className="button primary" onClick={this.sendSaveRequest}>
<div className="button primary" onClick={this.editorSendSaveRequest}>
Сохранить
</div>
)}

View file

@ -1,9 +1,9 @@
import React from 'react';
import { connect } from 'react-redux';
import { selectUserRenderer } from '~/redux/user/selectors';
import { selectEditorRenderer } from '~/redux/editor/selectors';
const mapStateToProps = state => ({
renderer: selectUserRenderer(state),
renderer: selectEditorRenderer(state),
});
type Props = ReturnType<typeof mapStateToProps> & {};

View file

@ -1,39 +1,44 @@
// @flow
import React from 'react';
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 {
setActiveSticker: typeof setActiveStickerAction,
width: number,
}
const mapStateToProps = () => ({});
const mapDispatchToProps = {
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="helper stickers-helper">
{
Object.keys(STICKERS).map(set => (
<div key={set}>
<div className="stickers-set-title">{STICKERS[set].title || null}</div>
<div className="stickers-grid">
{
Object.keys(STICKERS[set].layers).map(sticker => (
<div
style={{
backgroundImage: `url(${STICKERS[set].url})`,
backgroundPosition: `${-STICKERS[set].layers[sticker].off * 48}px 50%`,
}}
className="sticker-preview"
key={`${set}-${sticker}`}
onClick={() => setActiveSticker({ set, sticker })}
/>
))
}
</div>
{Object.keys(STICKERS).map(set => (
<div key={set}>
<div className="stickers-set-title">{STICKERS[set].title || null}</div>
<div className="stickers-grid">
{Object.keys(STICKERS[set].layers).map(sticker => (
<div
style={{
backgroundImage: `url(${STICKERS[set].url})`,
backgroundPosition: `${-STICKERS[set].layers[sticker].off * 48}px 50%`,
}}
className="sticker-preview"
key={`${set}-${sticker}`}
onClick={() => editorSetActiveSticker({ set, sticker })}
/>
))}
</div>
))
}
</div>
))}
</div>
</div>
);
const StickersDialog = connect(mapStateToProps, mapDispatchToProps)(StickersDialogUnconnected);
export { StickersDialog };

View file

@ -5,11 +5,11 @@ import classnames from 'classnames';
import { getStyle } from '~/utils/dom';
import { nearestInt } from '~/utils/geom';
import { parseDesc } from '~/utils/format';
import { selectUser } from '~/redux/user/selectors';
import { selectMap } from '~/redux/map/selectors';
import { selectEditor } from '~/redux/editor/selectors';
const mapStateToProps = state => ({
user: selectUser(state),
editor: selectEditor(state),
map: selectMap(state),
});
@ -80,7 +80,7 @@ export class TitleDialogUnconnected extends React.PureComponent<Props, State> {
render() {
const {
user: { editing },
editor: { editing },
map: { title, description },
} = this.props;
const { raised, height, height_raised } = this.state;