mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 19:16:41 +07:00
dialog-editor: drop and edit items
This commit is contained in:
parent
a2607b257d
commit
970d0967c8
10 changed files with 279 additions and 150 deletions
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { RouteRow } from '$components/maps/RouteRow';
|
||||
import { RouteRowWrapper } from '$components/maps/RouteRowWrapper';
|
||||
import { Scroll } from '$components/Scroll';
|
||||
import {
|
||||
searchSetDistance,
|
||||
|
@ -21,6 +21,8 @@ import { IRootState, IRouteListItem } from '$redux/user/reducer';
|
|||
export interface IMapListDialogProps extends IRootState {
|
||||
marks: { [x: number]: string },
|
||||
routes_sorted: Array<IRouteListItem>,
|
||||
routes: IRootState['routes'],
|
||||
ready: IRootState['ready'],
|
||||
|
||||
mapsLoadMore: typeof mapsLoadMore,
|
||||
searchSetDistance: typeof searchSetDistance,
|
||||
|
@ -30,32 +32,44 @@ export interface IMapListDialogProps extends IRootState {
|
|||
}
|
||||
|
||||
export interface IMapListDialogState {
|
||||
selected_item: IRouteListItem['_id'],
|
||||
selected_item_mode: 'menu' | 'edit' | 'drop' | null,
|
||||
menu_target: IRouteListItem['_id'],
|
||||
editor_target: IRouteListItem['_id'],
|
||||
|
||||
is_editing: boolean,
|
||||
is_dropping: boolean,
|
||||
}
|
||||
|
||||
class Component extends React.Component<IMapListDialogProps, IMapListDialogState> {
|
||||
state = {
|
||||
selected_item: null,
|
||||
selected_item_mode: null,
|
||||
menu_target: null,
|
||||
editor_target: null,
|
||||
|
||||
is_editing: false,
|
||||
is_dropping: false,
|
||||
};
|
||||
|
||||
startEditing = (selected_item: IRouteListItem['_id']): void => this.setState({
|
||||
selected_item: ((this.state.selected_item !== selected_item && selected_item) || null),
|
||||
selected_item_mode: 'edit',
|
||||
startEditing = (editor_target: IRouteListItem['_id']): void => this.setState({
|
||||
editor_target,
|
||||
menu_target: null,
|
||||
is_editing: true,
|
||||
is_dropping: false,
|
||||
});
|
||||
|
||||
showMenu = (selected_item: IRouteListItem['_id']): void => this.setState({
|
||||
selected_item: ((this.state.selected_item !== selected_item && selected_item) || null),
|
||||
selected_item_mode: 'menu',
|
||||
showMenu = (menu_target: IRouteListItem['_id']): void => this.setState({
|
||||
menu_target,
|
||||
});
|
||||
|
||||
showDropCard = (selected_item: IRouteListItem['_id']): void => this.setState({
|
||||
selected_item: ((this.state.selected_item !== selected_item && selected_item) || null),
|
||||
selected_item_mode: 'drop',
|
||||
showDropCard = (editor_target: IRouteListItem['_id']): void => this.setState({
|
||||
editor_target,
|
||||
menu_target: null,
|
||||
is_editing: false,
|
||||
is_dropping: true,
|
||||
});
|
||||
|
||||
stopEditing = (): void => this.setState({ selected_item: null });
|
||||
stopEditing = (): void => {
|
||||
console.log('stop it!');
|
||||
this.setState({ editor_target: null });
|
||||
};
|
||||
|
||||
setTitle = ({ target: { value } }: { target: { value: string }}): void => {
|
||||
this.props.searchSetTitle(value);
|
||||
|
@ -64,6 +78,8 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
|||
openRoute = (_id: string): void => {
|
||||
if (isMobile()) this.props.setDialogActive(false);
|
||||
|
||||
this.stopEditing();
|
||||
|
||||
pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`);
|
||||
};
|
||||
|
||||
|
@ -80,6 +96,8 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
|||
}
|
||||
};
|
||||
|
||||
dropRoute = (): void => null;
|
||||
|
||||
render() {
|
||||
const {
|
||||
ready,
|
||||
|
@ -97,7 +115,7 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
|||
marks,
|
||||
}: IMapListDialogProps = this.props;
|
||||
|
||||
const { selected_item, selected_item_mode } = this.state;
|
||||
const { editor_target, menu_target, is_editing, is_dropping } = this.state;
|
||||
|
||||
return (
|
||||
<div className="dialog-content">
|
||||
|
@ -166,19 +184,21 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
|||
<div className="dialog-maplist">
|
||||
{
|
||||
list.map(route => (
|
||||
<RouteRow
|
||||
<RouteRowWrapper
|
||||
title={route.title}
|
||||
distance={route.distance}
|
||||
_id={route._id}
|
||||
is_public={route.is_public}
|
||||
tab={tab}
|
||||
selected={(selected_item === route._id)}
|
||||
mode={selected_item_mode}
|
||||
is_editing_mode={is_dropping ? 'drop' : 'edit'}
|
||||
is_editing_target={editor_target === route._id}
|
||||
is_menu_target={menu_target === route._id}
|
||||
openRoute={this.openRoute}
|
||||
startEditing={this.startEditing}
|
||||
stopEditing={this.stopEditing}
|
||||
showMenu={this.showMenu}
|
||||
showDropCard={this.showDropCard}
|
||||
dropRoute={this.dropRoute}
|
||||
key={route._id}
|
||||
/>
|
||||
))
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import { Icon } from '$components/panels/Icon';
|
||||
import classnames from 'classnames';
|
||||
import { IMapListDialogState, MapListDialog } from "$components/dialogs/MapListDialog";
|
||||
import { Tooltip } from "$components/panels/Tooltip";
|
||||
|
||||
interface Props {
|
||||
_id: string,
|
||||
tab: string,
|
||||
selected: boolean,
|
||||
title: string,
|
||||
distance: number,
|
||||
is_public: boolean,
|
||||
mode: IMapListDialogState['selected_item_mode'],
|
||||
|
||||
openRoute: typeof MapListDialog.openRoute,
|
||||
startEditing: typeof MapListDialog.startEditing,
|
||||
stopEditing: typeof MapListDialog.stopEditing,
|
||||
showMenu: typeof MapListDialog.showMenu,
|
||||
showDropCard: typeof MapListDialog.showDropCard,
|
||||
key: string,
|
||||
}
|
||||
|
||||
export const RouteRow = ({
|
||||
title, distance, _id, openRoute, tab, selected, startEditing, showMenu, showDropCard, mode
|
||||
}: Props) => (
|
||||
<div
|
||||
className={classnames('route-row-wrapper', {
|
||||
selected,
|
||||
has_menu: selected && mode === 'menu',
|
||||
has_drop: selected && mode === 'drop',
|
||||
has_edit: selected && mode === 'edit',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className="route-row"
|
||||
>
|
||||
<div onClick={() => openRoute(_id)}>
|
||||
<div className="route-title">
|
||||
<span>{(title || _id)}</span>
|
||||
</div>
|
||||
<div className="route-description">
|
||||
<span>
|
||||
<Icon icon="icon-link-1" />
|
||||
{_id}
|
||||
</span>
|
||||
<span>
|
||||
<Icon icon="icon-cycle-1" />
|
||||
{(distance && `${distance} km`) || '0 km'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="route-row-edit-button pointer" onClick={() => showMenu(_id)}>
|
||||
<Icon icon="icon-more-vert" />
|
||||
<div className="route-row-edit-menu">
|
||||
<div onClick={() => showDropCard(_id)}>
|
||||
<Tooltip>Удалить</Tooltip>
|
||||
<Icon icon="icon-trash-3" size={32} />
|
||||
</div>
|
||||
<div onClick={() => startEditing(_id)}>
|
||||
<Tooltip>Редактировать</Tooltip>
|
||||
<Icon icon="icon-edit-1" size={32} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
29
src/components/maps/RouteRowDrop.tsx
Normal file
29
src/components/maps/RouteRowDrop.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import { Icon } from '$components/panels/Icon';
|
||||
import { MapListDialog } from "$components/dialogs/MapListDialog";
|
||||
import { Tooltip } from "$components/panels/Tooltip";
|
||||
import { ReactElement } from "react";
|
||||
|
||||
interface Props {
|
||||
_id: string,
|
||||
stopEditing: typeof MapListDialog.stopEditing,
|
||||
dropRoute: typeof MapListDialog.dropRoute,
|
||||
}
|
||||
|
||||
export const RouteRowDrop = ({
|
||||
_id, stopEditing, dropRoute,
|
||||
}: Props): ReactElement<Props, null> => (
|
||||
<div
|
||||
className="route-row-drop"
|
||||
>
|
||||
<div
|
||||
className="route-row"
|
||||
>
|
||||
<div className="button-group">
|
||||
<div className="button" onClick={() => dropRoute(_id)}>Удалить</div>
|
||||
<div className="button primary" onClick={stopEditing}>Отмена</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
|
@ -5,9 +5,8 @@ import { Switch } from '$components/Switch';
|
|||
|
||||
interface Props {
|
||||
title: string;
|
||||
is_editing: boolean;
|
||||
distance: number;
|
||||
_id: string;
|
||||
is_public: boolean,
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -32,46 +31,34 @@ export class RouteRowEditor extends React.Component<Props, State> {
|
|||
render() {
|
||||
const {
|
||||
state: { title, is_public },
|
||||
props: { distance, _id }
|
||||
props: { _id }
|
||||
} = this;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="route-row"
|
||||
>
|
||||
<div className="route-title">
|
||||
<input
|
||||
type="text"
|
||||
value={title}
|
||||
onChange={this.setTitle}
|
||||
placeholder="Введите название"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
<div className="route-description">
|
||||
<span>
|
||||
<Icon icon="icon-link-1" />
|
||||
{_id}
|
||||
</span>
|
||||
<span>
|
||||
<Icon icon="icon-cycle-1" />
|
||||
{(distance && `${distance} km`) || '0 km'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="route-row-editor">
|
||||
<div className="route-row-buttons">
|
||||
<div className="flex_1" onClick={this.setPublic}>
|
||||
<Switch
|
||||
active={is_public}
|
||||
/>
|
||||
{
|
||||
is_public
|
||||
? ' В каталоге карт'
|
||||
: ' Только по ссылке'
|
||||
}
|
||||
</div>
|
||||
<div className="button primary" onClick={this.stopEditing}>
|
||||
OK
|
||||
<div className="route-row-edit">
|
||||
<div className="route-row">
|
||||
<div className="route-title">
|
||||
<input
|
||||
type="text"
|
||||
value={title}
|
||||
onChange={this.setTitle}
|
||||
placeholder="Введите название"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
<div className="route-row-editor">
|
||||
<div className="route-row-buttons">
|
||||
<div className="flex_1" onClick={this.setPublic}>
|
||||
<Switch active={is_public} />
|
||||
{
|
||||
is_public
|
||||
? ' В каталоге карт'
|
||||
: ' Только по ссылке'
|
||||
}
|
||||
</div>
|
||||
<div className="button primary" onClick={this.stopEditing}>
|
||||
OK
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
61
src/components/maps/RouteRowView.tsx
Normal file
61
src/components/maps/RouteRowView.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import { Icon } from '$components/panels/Icon';
|
||||
import { MapListDialog } from "$components/dialogs/MapListDialog";
|
||||
import { Tooltip } from "$components/panels/Tooltip";
|
||||
import { ReactElement } from "react";
|
||||
|
||||
interface Props {
|
||||
_id: string,
|
||||
tab: string,
|
||||
title: string,
|
||||
distance: number,
|
||||
is_public: boolean,
|
||||
|
||||
openRoute: typeof MapListDialog.openRoute,
|
||||
startEditing: typeof MapListDialog.startEditing,
|
||||
stopEditing: typeof MapListDialog.stopEditing,
|
||||
showMenu: typeof MapListDialog.showMenu,
|
||||
showDropCard: typeof MapListDialog.showDropCard,
|
||||
}
|
||||
|
||||
export const RouteRowView = ({
|
||||
title, distance, _id, openRoute, tab, startEditing, showMenu, showDropCard
|
||||
}: Props): ReactElement<Props, null> => (
|
||||
<div
|
||||
className="route-row-view"
|
||||
>
|
||||
<div
|
||||
className="route-row"
|
||||
onClick={() => openRoute(_id)}
|
||||
>
|
||||
<div className="route-title">
|
||||
<span>{(title || _id)}</span>
|
||||
</div>
|
||||
|
||||
<div className="route-description">
|
||||
<span>
|
||||
<Icon icon="icon-link-1" />
|
||||
{_id}
|
||||
</span>
|
||||
<span>
|
||||
<Icon icon="icon-cycle-1" />
|
||||
{(distance && `${distance} km`) || '0 km'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="route-row-edit-button pointer" onClick={() => showMenu(_id)}>
|
||||
<Icon icon="icon-more-vert" />
|
||||
</div>
|
||||
<div className="route-row-edit-menu pointer">
|
||||
<div onMouseDown={() => showDropCard(_id)}>
|
||||
<Tooltip>Удалить</Tooltip>
|
||||
<Icon icon="icon-trash-3" size={32} />
|
||||
</div>
|
||||
<div onMouseDown={() => startEditing(_id)}>
|
||||
<Tooltip>Редактировать</Tooltip>
|
||||
<Icon icon="icon-edit-1" size={32} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
72
src/components/maps/RouteRowWrapper.tsx
Normal file
72
src/components/maps/RouteRowWrapper.tsx
Normal file
|
@ -0,0 +1,72 @@
|
|||
import * as React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { MapListDialog } from "$components/dialogs/MapListDialog";
|
||||
import { RouteRowView } from "$components/maps/RouteRowView";
|
||||
import { RouteRowEditor } from "$components/maps/RouteRowEditor";
|
||||
import { RouteRowDrop } from "$components/maps/RouteRowDrop";
|
||||
import { ReactElement } from "react";
|
||||
|
||||
interface Props {
|
||||
_id: string,
|
||||
tab: string,
|
||||
title: string,
|
||||
distance: number,
|
||||
is_public: boolean,
|
||||
|
||||
is_editing_target: boolean,
|
||||
is_menu_target: boolean,
|
||||
|
||||
openRoute: typeof MapListDialog.openRoute,
|
||||
startEditing: typeof MapListDialog.startEditing,
|
||||
stopEditing: typeof MapListDialog.stopEditing,
|
||||
showMenu: typeof MapListDialog.showMenu,
|
||||
showDropCard: typeof MapListDialog.showDropCard,
|
||||
dropRoute: typeof MapListDialog.dropRoute,
|
||||
|
||||
is_editing_mode: 'edit' | 'drop',
|
||||
}
|
||||
|
||||
export const RouteRowWrapper = ({
|
||||
title, distance, _id, openRoute, tab, startEditing, showMenu,
|
||||
showDropCard, is_public, is_editing_target, is_menu_target, is_editing_mode,
|
||||
dropRoute, stopEditing,
|
||||
}: Props): ReactElement<Props, null> => (
|
||||
<div
|
||||
className={classnames('route-row-wrapper', {
|
||||
is_menu_target,
|
||||
is_editing_target,
|
||||
})}
|
||||
>
|
||||
{
|
||||
is_editing_target && is_editing_mode === 'edit' &&
|
||||
<RouteRowEditor
|
||||
title={title}
|
||||
_id={_id}
|
||||
is_public={is_public}
|
||||
/>
|
||||
}
|
||||
{
|
||||
is_editing_target && is_editing_mode === 'drop' &&
|
||||
<RouteRowDrop
|
||||
_id={_id}
|
||||
dropRoute={dropRoute}
|
||||
stopEditing={stopEditing}
|
||||
/>
|
||||
}
|
||||
{
|
||||
!is_editing_target &&
|
||||
<RouteRowView
|
||||
_id={_id}
|
||||
tab={tab}
|
||||
title={title}
|
||||
distance={distance}
|
||||
is_public={is_public}
|
||||
openRoute={openRoute}
|
||||
startEditing={startEditing}
|
||||
stopEditing={stopEditing}
|
||||
showMenu={showMenu}
|
||||
showDropCard={showDropCard}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
Loading…
Add table
Add a link
Reference in a new issue