mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 11:06:40 +07:00
dialog-editor: menu for items
This commit is contained in:
parent
b8f4bace71
commit
a2607b257d
4 changed files with 189 additions and 115 deletions
|
@ -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}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
|
|
@ -2,60 +2,68 @@
|
||||||
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
|
>
|
||||||
className="route-row"
|
<div
|
||||||
>
|
className="route-row"
|
||||||
<div onClick={() => openRoute(_id)}>
|
>
|
||||||
<div className="route-title">
|
<div onClick={() => openRoute(_id)}>
|
||||||
<span>{(title || _id)}</span>
|
<div className="route-title">
|
||||||
</div>
|
<span>{(title || _id)}</span>
|
||||||
<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-panel">
|
<div className="route-description">
|
||||||
<div className="">
|
<span>
|
||||||
<Icon icon="icon-trash-4" size={24} />
|
<Icon icon="icon-link-1" />
|
||||||
Удалить
|
{_id}
|
||||||
</div>
|
</span>
|
||||||
<div className="flex_1 justify-end" onClick={() => startEditing(_id)}>
|
<span>
|
||||||
<Icon icon="icon-edit-1" size={24} />
|
<Icon icon="icon-cycle-1" />
|
||||||
Правка
|
{(distance && `${distance} km`) || '0 km'}
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 |
|
@ -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;
|
|
||||||
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;
|
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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue