mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 11:06:40 +07:00
complete item editing
This commit is contained in:
parent
7513f79b93
commit
0cbbc0ce8a
12 changed files with 94 additions and 34 deletions
|
@ -13,6 +13,7 @@ const RouteSchema = new Schema(
|
||||||
owner: { type: Schema.Types.ObjectId, ref: 'User' },
|
owner: { type: Schema.Types.ObjectId, ref: 'User' },
|
||||||
distance: { type: Number, default: 0 },
|
distance: { type: Number, default: 0 },
|
||||||
is_public: { type: Boolean, default: false },
|
is_public: { type: Boolean, default: false },
|
||||||
|
is_deleted: { type: Boolean, default: false },
|
||||||
created_at: { type: Date, default: Date.now() },
|
created_at: { type: Date, default: Date.now() },
|
||||||
updated_at: { type: Date, default: Date.now() },
|
updated_at: { type: Date, default: Date.now() },
|
||||||
logo: { type: String, default: 'DEFAULT' },
|
logo: { type: String, default: 'DEFAULT' },
|
||||||
|
|
|
@ -12,7 +12,7 @@ module.exports = async (req, res) => {
|
||||||
if (!exists) return res.send({ success: false, mode: 'not_exists' });
|
if (!exists) return res.send({ success: false, mode: 'not_exists' });
|
||||||
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'not_yours' });
|
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'not_yours' });
|
||||||
|
|
||||||
exists.delete();
|
await exists.set({ is_deleted: true }).save();
|
||||||
|
|
||||||
return res.send({ success: true, address });
|
return res.send({ success: true, address });
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = async (req, res) => {
|
||||||
|
|
||||||
if (!name) return res.send({ success: false, mode: 'not_found_1' });
|
if (!name) return res.send({ success: false, mode: 'not_found_1' });
|
||||||
|
|
||||||
const exists = await Route.findOne({ _id: name }).populate('owner', '_id');
|
const exists = await Route.findOne({ _id: name, is_deleted: false }).populate('owner', '_id');
|
||||||
|
|
||||||
if (!exists) return res.send({ success: false, mode: 'not_found_2' });
|
if (!exists) return res.send({ success: false, mode: 'not_found_2' });
|
||||||
const data = exists.toObject();
|
const data = exists.toObject();
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports = async (req, res) => {
|
||||||
|
|
||||||
const user = await User.findOne({ _id: id, token });
|
const user = await User.findOne({ _id: id, token });
|
||||||
|
|
||||||
let criteria = {};
|
let criteria = { is_deleted: false };
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
criteria = {
|
criteria = {
|
||||||
|
@ -32,16 +32,14 @@ module.exports = async (req, res) => {
|
||||||
{
|
{
|
||||||
...criteria,
|
...criteria,
|
||||||
},
|
},
|
||||||
'_id title distance owner updated_at is_public',
|
'_id title distance owner updated_at is_public is_deleted',
|
||||||
{
|
{
|
||||||
limit: 9000,
|
limit: 9000,
|
||||||
sort: { updated_at: -1 },
|
sort: { updated_at: -1 },
|
||||||
}
|
}
|
||||||
).populate('owner', '_id');
|
).populate('owner', '_id');
|
||||||
|
|
||||||
list = list.filter(item => (
|
list = list.filter(item => !author || (item.owner && item.owner._id === author));
|
||||||
!author || item.owner._id === author
|
|
||||||
));
|
|
||||||
|
|
||||||
let limits = list.reduce(({ min, max }, { distance: dist }) => ({
|
let limits = list.reduce(({ min, max }, { distance: dist }) => ({
|
||||||
min: Math.ceil(Math.min(dist, min) / 25) * 25,
|
min: Math.ceil(Math.min(dist, min) / 25) * 25,
|
||||||
|
|
|
@ -12,7 +12,7 @@ module.exports = async (req, res) => {
|
||||||
const title = parseString(body.title, 32);
|
const title = parseString(body.title, 32);
|
||||||
const is_public = !!body.is_public;
|
const is_public = !!body.is_public;
|
||||||
|
|
||||||
const exists = await Route.findOne({ _id: address }).populate('owner', '_id');
|
const exists = await Route.findOne({ _id: address, is_deleted: false }).populate('owner', '_id');
|
||||||
|
|
||||||
if (!exists) return res.send({ success: false, mode: 'not_exists' });
|
if (!exists) return res.send({ success: false, mode: 'not_exists' });
|
||||||
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'not_yours' });
|
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'not_yours' });
|
||||||
|
|
|
@ -21,7 +21,7 @@ module.exports = async (req, res) => {
|
||||||
return res.send({ success: false, mode: 'empty' });
|
return res.send({ success: false, mode: 'empty' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const exists = await Route.findOne({ _id: address }).populate('owner', '_id');
|
const exists = await Route.findOne({ _id: address, is_deleted: false }).populate('owner', '_id');
|
||||||
|
|
||||||
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'exists' });
|
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'exists' });
|
||||||
if (exists && !force) return res.send({ success: false, mode: 'overwriting' });
|
if (exists && !force) return res.send({ success: false, mode: 'overwriting' });
|
||||||
|
|
|
@ -64,6 +64,10 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
||||||
menu_target,
|
menu_target,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
hideMenu = (): void => this.setState({
|
||||||
|
menu_target: null,
|
||||||
|
});
|
||||||
|
|
||||||
showDropCard = (editor_target: IRouteListItem['_id']): void => this.setState({
|
showDropCard = (editor_target: IRouteListItem['_id']): void => this.setState({
|
||||||
editor_target,
|
editor_target,
|
||||||
menu_target: null,
|
menu_target: null,
|
||||||
|
@ -211,6 +215,7 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
||||||
startEditing={this.startEditing}
|
startEditing={this.startEditing}
|
||||||
stopEditing={this.stopEditing}
|
stopEditing={this.stopEditing}
|
||||||
showMenu={this.showMenu}
|
showMenu={this.showMenu}
|
||||||
|
hideMenu={this.hideMenu}
|
||||||
showDropCard={this.showDropCard}
|
showDropCard={this.showDropCard}
|
||||||
dropRoute={this.dropRoute}
|
dropRoute={this.dropRoute}
|
||||||
modifyRoute={this.modifyRoute}
|
modifyRoute={this.modifyRoute}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Icon } from '$components/panels/Icon';
|
||||||
import { MapListDialog } from "$components/dialogs/MapListDialog";
|
import { MapListDialog } from "$components/dialogs/MapListDialog";
|
||||||
import { Tooltip } from "$components/panels/Tooltip";
|
import { Tooltip } from "$components/panels/Tooltip";
|
||||||
import { ReactElement } from "react";
|
import { ReactElement } from "react";
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
_id: string,
|
_id: string,
|
||||||
|
@ -16,14 +17,15 @@ interface Props {
|
||||||
startEditing: typeof MapListDialog.startEditing,
|
startEditing: typeof MapListDialog.startEditing,
|
||||||
stopEditing: typeof MapListDialog.stopEditing,
|
stopEditing: typeof MapListDialog.stopEditing,
|
||||||
showMenu: typeof MapListDialog.showMenu,
|
showMenu: typeof MapListDialog.showMenu,
|
||||||
|
hideMenu: typeof MapListDialog.hideMenu,
|
||||||
showDropCard: typeof MapListDialog.showDropCard,
|
showDropCard: typeof MapListDialog.showDropCard,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RouteRowView = ({
|
export const RouteRowView = ({
|
||||||
title, distance, _id, openRoute, tab, startEditing, showMenu, showDropCard
|
title, distance, _id, openRoute, tab, startEditing, showMenu, showDropCard, hideMenu,
|
||||||
}: Props): ReactElement<Props, null> => (
|
}: Props): ReactElement<Props, null> => (
|
||||||
<div
|
<div
|
||||||
className="route-row-view"
|
className={classnames('route-row-view', { has_menu: (tab === 'mine') })}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="route-row"
|
className="route-row"
|
||||||
|
@ -44,18 +46,27 @@ export const RouteRowView = ({
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="route-row-edit-button pointer" onClick={() => showMenu(_id)}>
|
{
|
||||||
<Icon icon="icon-more-vert" />
|
tab === 'mine' &&
|
||||||
</div>
|
<React.Fragment>
|
||||||
<div className="route-row-edit-menu pointer">
|
<div
|
||||||
<div onMouseDown={() => showDropCard(_id)}>
|
className="route-row-edit-button pointer"
|
||||||
<Tooltip>Удалить</Tooltip>
|
onMouseOver={showMenu.bind(null, _id)}
|
||||||
<Icon icon="icon-trash-3" size={32} />
|
onMouseOut={hideMenu}
|
||||||
</div>
|
>
|
||||||
<div onMouseDown={() => startEditing(_id)}>
|
<Icon icon="icon-more-vert" />
|
||||||
<Tooltip>Редактировать</Tooltip>
|
<div className="route-row-edit-menu pointer">
|
||||||
<Icon icon="icon-edit-1" size={32} />
|
<div onMouseDown={showDropCard.bind(null, _id)}>
|
||||||
</div>
|
<Tooltip>Удалить</Tooltip>
|
||||||
</div>
|
<Icon icon="icon-trash-3" size={32} />
|
||||||
|
</div>
|
||||||
|
<div onMouseDown={startEditing.bind(null, _id)} className="modify-button">
|
||||||
|
<Tooltip>Редактировать</Tooltip>
|
||||||
|
<Icon icon="icon-edit-1" size={32} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,6 +20,7 @@ interface Props {
|
||||||
startEditing: typeof MapListDialog.startEditing,
|
startEditing: typeof MapListDialog.startEditing,
|
||||||
stopEditing: typeof MapListDialog.stopEditing,
|
stopEditing: typeof MapListDialog.stopEditing,
|
||||||
showMenu: typeof MapListDialog.showMenu,
|
showMenu: typeof MapListDialog.showMenu,
|
||||||
|
hideMenu: typeof MapListDialog.hideMenu,
|
||||||
showDropCard: typeof MapListDialog.showDropCard,
|
showDropCard: typeof MapListDialog.showDropCard,
|
||||||
dropRoute: typeof MapListDialog.dropRoute,
|
dropRoute: typeof MapListDialog.dropRoute,
|
||||||
modifyRoute: typeof MapListDialog.modifyRoute,
|
modifyRoute: typeof MapListDialog.modifyRoute,
|
||||||
|
@ -30,7 +31,7 @@ interface Props {
|
||||||
export const RouteRowWrapper = ({
|
export const RouteRowWrapper = ({
|
||||||
title, distance, _id, openRoute, tab, startEditing, showMenu,
|
title, distance, _id, openRoute, tab, startEditing, showMenu,
|
||||||
showDropCard, is_public, is_editing_target, is_menu_target, is_editing_mode,
|
showDropCard, is_public, is_editing_target, is_menu_target, is_editing_mode,
|
||||||
dropRoute, stopEditing, modifyRoute,
|
dropRoute, stopEditing, modifyRoute, hideMenu,
|
||||||
}: Props): ReactElement<Props, null> => (
|
}: Props): ReactElement<Props, null> => (
|
||||||
<div
|
<div
|
||||||
className={classnames('route-row-wrapper', {
|
className={classnames('route-row-wrapper', {
|
||||||
|
@ -67,6 +68,7 @@ export const RouteRowWrapper = ({
|
||||||
startEditing={startEditing}
|
startEditing={startEditing}
|
||||||
stopEditing={stopEditing}
|
stopEditing={stopEditing}
|
||||||
showMenu={showMenu}
|
showMenu={showMenu}
|
||||||
|
hideMenu={hideMenu}
|
||||||
showDropCard={showDropCard}
|
showDropCard={showDropCard}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
|
@ -649,16 +649,46 @@ function* mapsLoadMoreSaga() {
|
||||||
|
|
||||||
function* dropRouteSaga({ _id }: ReturnType<typeof ActionCreators.dropRoute>): SagaIterator {
|
function* dropRouteSaga({ _id }: ReturnType<typeof ActionCreators.dropRoute>): SagaIterator {
|
||||||
const { id, token } = yield select(getUser);
|
const { id, token } = yield select(getUser);
|
||||||
const result = yield call(dropRoute, { address: _id, id, token });
|
const {
|
||||||
|
routes: { list, step, shift, limit, filter: { min, max } }
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
console.log('result', result);
|
const index = list.findIndex(el => el._id === _id);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
yield put(searchPutRoutes({
|
||||||
|
list: list.filter(el => el._id !== _id),
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
step,
|
||||||
|
shift: (shift > 0) ? shift - 1 : 0,
|
||||||
|
limit: (limit > 0) ? limit - 1 : limit,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return yield call(dropRoute, { address: _id, id, token });
|
||||||
}
|
}
|
||||||
|
|
||||||
function* modifyRouteSaga({ _id, title, is_public }: ReturnType<typeof ActionCreators.modifyRoute>): SagaIterator {
|
function* modifyRouteSaga({ _id, title, is_public }: ReturnType<typeof ActionCreators.modifyRoute>): SagaIterator {
|
||||||
const { id, token } = yield select(getUser);
|
const { id, token } = yield select(getUser);
|
||||||
const result = yield call(modifyRoute, { address: _id, id, token, title, is_public });
|
const {
|
||||||
|
routes: { list, step, shift, limit, filter: { min, max } }
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
console.log('result', result);
|
const index = list.findIndex(el => el._id === _id);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
yield put(searchPutRoutes({
|
||||||
|
list: list.map(el => (el._id !== _id ? el : { ...el, title, is_public })),
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
step,
|
||||||
|
shift: (shift > 0) ? shift - 1 : 0,
|
||||||
|
limit: (limit > 0) ? limit - 1 : limit,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return yield call(modifyRoute, { address: _id, id, token, title, is_public });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* userSaga() {
|
export function* userSaga() {
|
||||||
|
|
|
@ -197,11 +197,11 @@
|
||||||
|
|
||||||
&.is_menu_target {
|
&.is_menu_target {
|
||||||
.route-row {
|
.route-row {
|
||||||
transform: translateX(-100px);
|
transform: translateX(-120px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.route-row-edit-menu {
|
.route-row-edit-menu {
|
||||||
width: 100px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,8 +221,11 @@
|
||||||
.route-row-view {
|
.route-row-view {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: height 500ms;
|
transition: height 500ms;
|
||||||
padding-right: 32px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&.has_menu {
|
||||||
|
padding-right: 32px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.route-row-edit {
|
.route-row-edit {
|
||||||
|
@ -295,15 +298,25 @@
|
||||||
fill: fade(white, 30%);
|
fill: fade(white, 30%);
|
||||||
|
|
||||||
div {
|
div {
|
||||||
width: 50px;
|
width: 60px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
box-shadow: fade(black, 30%) 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: fade(@red_secondary, 30%);
|
background: fade(@red_secondary, 30%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.modify-button {
|
||||||
|
&:hover {
|
||||||
|
background: fade(@green_secondary, 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ export const checkOSRMService = (bounds: LatLngLiteral[]): Promise<boolean> => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export const dropRoute = ({ address, id, token }: { address: string, id: string, token: string }): AxiosPromise<any> => (
|
export const dropRoute = ({ address, id, token }: { address: string, id: string, token: string }): AxiosPromise<any> => (
|
||||||
axios.delete(API.DROP_ROUTE, { data: { address: '1123123123123', id, token } })
|
axios.delete(API.DROP_ROUTE, { data: { address, id, token } })
|
||||||
);
|
);
|
||||||
|
|
||||||
export const modifyRoute = (
|
export const modifyRoute = (
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue