From a2607b257dd737d5913cc7a95c2e94d67bd2f9d7 Mon Sep 17 00:00:00 2001 From: muerwre Date: Wed, 27 Feb 2019 15:08:53 +0700 Subject: [PATCH] dialog-editor: menu for items --- src/components/dialogs/MapListDialog.tsx | 39 +++-- src/components/maps/RouteRow.tsx | 86 ++++++----- src/sprites/icon.svg | 5 + src/styles/dialogs.less | 174 ++++++++++++++--------- 4 files changed, 189 insertions(+), 115 deletions(-) diff --git a/src/components/dialogs/MapListDialog.tsx b/src/components/dialogs/MapListDialog.tsx index cb0a2bf..5280bd2 100644 --- a/src/components/dialogs/MapListDialog.tsx +++ b/src/components/dialogs/MapListDialog.tsx @@ -18,7 +18,7 @@ import { Icon } from '$components/panels/Icon'; import { pushPath } from '$utils/history'; import { IRootState, IRouteListItem } from '$redux/user/reducer'; -interface Props extends IRootState { +export interface IMapListDialogProps extends IRootState { marks: { [x: number]: string }, routes_sorted: Array, @@ -29,17 +29,33 @@ interface Props extends IRootState { setDialogActive: typeof setDialogActive, } -interface State { - editing_item: IRouteListItem['_id'], +export interface IMapListDialogState { + selected_item: IRouteListItem['_id'], + selected_item_mode: 'menu' | 'edit' | 'drop' | null, } -class Component extends React.Component { +class Component extends React.Component { state = { - editing_item: null, + selected_item: null, + selected_item_mode: null, }; - startEditing = editing_item => this.setState({ editing_item }); - stopEditing = () => this.setState({ editing_item: null }); + startEditing = (selected_item: IRouteListItem['_id']): void => this.setState({ + selected_item: ((this.state.selected_item !== selected_item && selected_item) || null), + selected_item_mode: 'edit', + }); + + showMenu = (selected_item: IRouteListItem['_id']): void => this.setState({ + selected_item: ((this.state.selected_item !== selected_item && selected_item) || null), + selected_item_mode: 'menu', + }); + + showDropCard = (selected_item: IRouteListItem['_id']): void => this.setState({ + selected_item: ((this.state.selected_item !== selected_item && selected_item) || null), + selected_item_mode: 'drop', + }); + + stopEditing = (): void => this.setState({ selected_item: null }); setTitle = ({ target: { value } }: { target: { value: string }}): void => { this.props.searchSetTitle(value); @@ -79,9 +95,9 @@ class Component extends React.Component { } }, marks, - }: Props = this.props; + }: IMapListDialogProps = this.props; - const { editing_item } = this.state; + const { selected_item, selected_item_mode } = this.state; return (
@@ -156,10 +172,13 @@ class Component extends React.Component { _id={route._id} is_public={route.is_public} tab={tab} - is_editing={(editing_item === route._id)} + selected={(selected_item === route._id)} + mode={selected_item_mode} openRoute={this.openRoute} startEditing={this.startEditing} stopEditing={this.stopEditing} + showMenu={this.showMenu} + showDropCard={this.showDropCard} key={route._id} /> )) diff --git a/src/components/maps/RouteRow.tsx b/src/components/maps/RouteRow.tsx index 4f626c3..a5f07cd 100644 --- a/src/components/maps/RouteRow.tsx +++ b/src/components/maps/RouteRow.tsx @@ -2,60 +2,68 @@ 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, - is_editing: boolean, + selected: boolean, title: string, distance: number, is_public: boolean, + mode: IMapListDialogState['selected_item_mode'], - openRoute: (_id: string) => void, - startEditing: (_id: string) => void, - stopEditing: () => void, + 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, is_editing, startEditing + title, distance, _id, openRoute, tab, selected, startEditing, showMenu, showDropCard, mode }: Props) => ( -
- { - tab === 'mine' && -
startEditing(_id)}> - -
- } -
-
openRoute(_id)}> -
- {(title || _id)} -
-
- - - {_id} - - - - {(distance && `${distance} km`) || '0 km'} - -
+
+
+
openRoute(_id)}> +
+ {(title || _id)}
-
-
- - Удалить -
-
startEditing(_id)}> - - Правка -
+
+ + + {_id} + + + + {(distance && `${distance} km`) || '0 km'} +
- +
+
showMenu(_id)}> + +
+
showDropCard(_id)}> + Удалить + +
+
startEditing(_id)}> + Редактировать + +
+
+
); diff --git a/src/sprites/icon.svg b/src/sprites/icon.svg index be97664..96b9fa0 100644 --- a/src/sprites/icon.svg +++ b/src/sprites/icon.svg @@ -379,6 +379,11 @@ + + + + + diff --git a/src/styles/dialogs.less b/src/styles/dialogs.less index cf26949..7c60194 100644 --- a/src/styles/dialogs.less +++ b/src/styles/dialogs.less @@ -187,34 +187,35 @@ position: relative; margin-bottom: 10px; transition: all 500ms; + display: flex; - //&:hover { - // .route-row { transform: translateX(-58px); } - // .route-row-edit { transform: translateX(-58px); } - // - // &.is_editing { - // .route-row { transform: translateX(0); } - // .route-row-edit { transform: translateX(0); } - // } - //} - - &.is_editing { + &.has_edit { //transform: translateY(-2px); .route-row { background: rgba(255, 100, 100, 0.2); } } -} -.route-row-editor { - color: white; - padding: 20px 0 5px; -} + &.has_menu { + .route-row { + transform: translateX(-100px); + } -.route-row-buttons { - flex: 1; - flex-direction: row; - display: flex; - align-items: center; + .route-row-edit-menu { + width: 100px; + } + } } +// +//.route-row-editor { +// color: white; +// padding: 20px 0 5px; +//} +// +//.route-row-buttons { +// flex: 1; +// flex-direction: row; +// display: flex; +// align-items: center; +//} .route-row { background: rgba(255, 255, 255, 0.05); @@ -224,6 +225,7 @@ cursor: pointer; transition: background 250ms, transform 500ms; position: relative; + flex: 1; &:hover { background: rgba(255, 255, 255, 0.1); @@ -236,58 +238,98 @@ } } -.route-row-panel { - position: absolute; - top: 100%; - height: 32px; - width: 100%; - left: 0; - background: mix(@dialog_background, white, 80%); - border-radius: 0 0 @panel_radius @panel_radius; - z-index: 1; - transform: scaleY(0); - pointer-events: none; - touch-action: none; - transition: transform 250ms; - transform-origin: 0 0; - padding: 0 5px; - box-sizing: border-box; - // display: flex; - align-items: center; - fill: white; - - display: none; - - & > div { - display: flex; - align-items: center; - - svg { - margin-right: 2px; - } - } -} - -.route-row-edit { - fill: rgba(255, 255, 255, 0.3); - right: -48px; - padding-left: 0px; - stroke: none; - position: absolute; - top: 0; - width: 58px; - height: 100%; - transition: all 500ms; +.route-row-edit-button { + width: 32px; + background: rgba(255, 255, 255, 0.08); + fill: rgba(255, 255, 255, 0.5); display: flex; - align-items: center; justify-content: center; - cursor: pointer; + align-items: center; + transition: all 250ms; + position: relative; &:hover { - fill: @green_secondary; + background: rgba(255, 255, 255, 0.1); } } +.route-row-edit-menu { + width: 0; + height: 100%; + right: 100%; + bottom: 0; + position: absolute; + background: rgba(0, 0, 0, 0.1); + overflow: hidden; + transition: all 500ms; + display: flex; + + div { + width: 50px; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + + &:hover { + background: fade(@red_secondary, 30%); + } + } + +} + +//.route-row-panel { +// position: absolute; +// top: 100%; +// height: 32px; +// width: 100%; +// left: 0; +// background: mix(@dialog_background, white, 80%); +// border-radius: 0 0 @panel_radius @panel_radius; +// z-index: 1; +// transform: scaleY(0); +// pointer-events: none; +// touch-action: none; +// transition: transform 250ms; +// transform-origin: 0 0; +// padding: 0 5px; +// box-sizing: border-box; +// // display: flex; +// align-items: center; +// fill: white; +// +// display: none; +// +// & > div { +// display: flex; +// align-items: center; +// +// svg { +// margin-right: 2px; +// } +// } +//} +// +//.route-row-edit { +// fill: rgba(255, 255, 255, 0.3); +// right: -48px; +// padding-left: 0px; +// stroke: none; +// position: absolute; +// top: 0; +// width: 58px; +// height: 100%; +// transition: all 500ms; +// display: flex; +// align-items: center; +// justify-content: center; +// cursor: pointer; +// +// &:hover { +// fill: @green_secondary; +// } +//} + .route-title { margin-bottom: 5px; font-weight: bold;