dialog-editor: menu for items

This commit is contained in:
muerwre 2019-02-27 15:08:53 +07:00
parent b8f4bace71
commit a2607b257d
4 changed files with 189 additions and 115 deletions

View file

@ -18,7 +18,7 @@ import { Icon } from '$components/panels/Icon';
import { pushPath } from '$utils/history'; import { pushPath } from '$utils/history';
import { IRootState, IRouteListItem } from '$redux/user/reducer'; import { IRootState, IRouteListItem } from '$redux/user/reducer';
interface Props extends IRootState { export interface IMapListDialogProps extends IRootState {
marks: { [x: number]: string }, marks: { [x: number]: string },
routes_sorted: Array<IRouteListItem>, routes_sorted: Array<IRouteListItem>,
@ -29,17 +29,33 @@ interface Props extends IRootState {
setDialogActive: typeof setDialogActive, setDialogActive: typeof setDialogActive,
} }
interface State { export interface IMapListDialogState {
editing_item: IRouteListItem['_id'], selected_item: IRouteListItem['_id'],
selected_item_mode: 'menu' | 'edit' | 'drop' | null,
} }
class Component extends React.Component<Props, State> { class Component extends React.Component<IMapListDialogProps, IMapListDialogState> {
state = { state = {
editing_item: null, selected_item: null,
selected_item_mode: null,
}; };
startEditing = editing_item => this.setState({ editing_item }); startEditing = (selected_item: IRouteListItem['_id']): void => this.setState({
stopEditing = () => this.setState({ editing_item: null }); 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 => { setTitle = ({ target: { value } }: { target: { value: string }}): void => {
this.props.searchSetTitle(value); this.props.searchSetTitle(value);
@ -79,9 +95,9 @@ class Component extends React.Component<Props, State> {
} }
}, },
marks, marks,
}: Props = this.props; }: IMapListDialogProps = this.props;
const { editing_item } = this.state; const { selected_item, selected_item_mode } = this.state;
return ( return (
<div className="dialog-content"> <div className="dialog-content">
@ -156,10 +172,13 @@ class Component extends React.Component<Props, State> {
_id={route._id} _id={route._id}
is_public={route.is_public} is_public={route.is_public}
tab={tab} tab={tab}
is_editing={(editing_item === route._id)} selected={(selected_item === route._id)}
mode={selected_item_mode}
openRoute={this.openRoute} openRoute={this.openRoute}
startEditing={this.startEditing} startEditing={this.startEditing}
stopEditing={this.stopEditing} stopEditing={this.stopEditing}
showMenu={this.showMenu}
showDropCard={this.showDropCard}
key={route._id} key={route._id}
/> />
)) ))

View file

@ -2,31 +2,37 @@
import * as React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import classnames from 'classnames'; import classnames from 'classnames';
import { IMapListDialogState, MapListDialog } from "$components/dialogs/MapListDialog";
import { Tooltip } from "$components/panels/Tooltip";
interface Props { interface Props {
_id: string, _id: string,
tab: string, tab: string,
is_editing: boolean, selected: boolean,
title: string, title: string,
distance: number, distance: number,
is_public: boolean, is_public: boolean,
mode: IMapListDialogState['selected_item_mode'],
openRoute: (_id: string) => void, openRoute: typeof MapListDialog.openRoute,
startEditing: (_id: string) => void, startEditing: typeof MapListDialog.startEditing,
stopEditing: () => void, stopEditing: typeof MapListDialog.stopEditing,
showMenu: typeof MapListDialog.showMenu,
showDropCard: typeof MapListDialog.showDropCard,
key: string, key: string,
} }
export const RouteRow = ({ export const RouteRow = ({
title, distance, _id, openRoute, tab, is_editing, startEditing title, distance, _id, openRoute, tab, selected, startEditing, showMenu, showDropCard, mode
}: Props) => ( }: Props) => (
<div className={classnames('route-row-wrapper', { is_editing })}> <div
{ className={classnames('route-row-wrapper', {
tab === 'mine' && selected,
<div className="route-row-edit" onClick={() => startEditing(_id)}> has_menu: selected && mode === 'menu',
<Icon icon="icon-edit-1" /> has_drop: selected && mode === 'drop',
</div> has_edit: selected && mode === 'edit',
} })}
>
<div <div
className="route-row" className="route-row"
> >
@ -45,17 +51,19 @@ export const RouteRow = ({
</span> </span>
</div> </div>
</div> </div>
<div className="route-row-panel">
<div className="">
<Icon icon="icon-trash-4" size={24} />
Удалить
</div> </div>
<div className="flex_1 justify-end" onClick={() => startEditing(_id)}> <div className="route-row-edit-button pointer" onClick={() => showMenu(_id)}>
<Icon icon="icon-edit-1" size={24} /> <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>
</div> </div>
</div> </div>
); );

View file

@ -379,6 +379,11 @@
<circle cx="16" cy="16" fill="white" r="4" /> <circle cx="16" cy="16" fill="white" r="4" />
</g> </g>
<g id="icon-more-vert" stroke="none">
<path stroke="none" fill="black"/>
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" fill="white" stroke="none" stroke-width="0" transform="translate(4 4)"/>
</g>
<g id="icon-cluster-1" stroke="none"> <g id="icon-cluster-1" stroke="none">
<rect x="0" y="0" width="32" height="32" fill="black" stroke="none" /> <rect x="0" y="0" width="32" height="32" fill="black" stroke="none" />
<circle cx="10" cy="21" fill="white" r="4" /> <circle cx="10" cy="21" fill="white" r="4" />

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Before After
Before After

View file

@ -187,34 +187,35 @@
position: relative; position: relative;
margin-bottom: 10px; margin-bottom: 10px;
transition: all 500ms; transition: all 500ms;
display: flex;
//&:hover { &.has_edit {
// .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 {
//transform: translateY(-2px); //transform: translateY(-2px);
.route-row { background: rgba(255, 100, 100, 0.2); } .route-row { background: rgba(255, 100, 100, 0.2); }
} }
}
.route-row-editor { &.has_menu {
color: white; .route-row {
padding: 20px 0 5px; transform: translateX(-100px);
} }
.route-row-buttons { .route-row-edit-menu {
flex: 1; width: 100px;
flex-direction: row; }
display: flex; }
align-items: center;
} }
//
//.route-row-editor {
// color: white;
// padding: 20px 0 5px;
//}
//
//.route-row-buttons {
// flex: 1;
// flex-direction: row;
// display: flex;
// align-items: center;
//}
.route-row { .route-row {
background: rgba(255, 255, 255, 0.05); background: rgba(255, 255, 255, 0.05);
@ -224,6 +225,7 @@
cursor: pointer; cursor: pointer;
transition: background 250ms, transform 500ms; transition: background 250ms, transform 500ms;
position: relative; position: relative;
flex: 1;
&:hover { &:hover {
background: rgba(255, 255, 255, 0.1); background: rgba(255, 255, 255, 0.1);
@ -236,58 +238,98 @@
} }
} }
.route-row-panel { .route-row-edit-button {
position: absolute; width: 32px;
top: 100%; background: rgba(255, 255, 255, 0.08);
height: 32px; fill: rgba(255, 255, 255, 0.5);
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; 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; justify-content: center;
cursor: pointer; align-items: center;
transition: all 250ms;
position: relative;
&:hover { &: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 { .route-title {
margin-bottom: 5px; margin-bottom: 5px;
font-weight: bold; font-weight: bold;