mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 11:06:40 +07:00
fixed loading route and maps
This commit is contained in:
parent
1f774a8299
commit
62cb8d8e18
18 changed files with 715 additions and 369 deletions
|
@ -8,7 +8,7 @@ const iframe_vk = require('./auth/iframe/vk');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.get('/', check);
|
router.get('/', check);
|
||||||
router.get('/list', list);
|
// router.get('/list', list);
|
||||||
router.get('/guest', guest);
|
router.get('/guest', guest);
|
||||||
router.get('/social/vk', vk);
|
router.get('/social/vk', vk);
|
||||||
router.get('/iframe/vk', iframe_vk);
|
router.get('/iframe/vk', iframe_vk);
|
||||||
|
|
|
@ -5,14 +5,6 @@ module.exports = async (req, res) => {
|
||||||
const { id, token } = req.query;
|
const { id, token } = req.query;
|
||||||
|
|
||||||
const user = await User.findOne({ _id: id, token });
|
const user = await User.findOne({ _id: id, token });
|
||||||
// .populate({
|
|
||||||
// path: 'routes',
|
|
||||||
// select: '_id title distance owner updated_at',
|
|
||||||
// options: {
|
|
||||||
// limit: 200,
|
|
||||||
// sort: { updated_at: -1 },
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
const random_url = await generateRandomUrl();
|
const random_url = await generateRandomUrl();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ const fetchUserData = async (req, res) => {
|
||||||
client_id: CONFIG.SOCIAL.VK.APP_ID,
|
client_id: CONFIG.SOCIAL.VK.APP_ID,
|
||||||
client_secret: CONFIG.SOCIAL.VK.SECRET,
|
client_secret: CONFIG.SOCIAL.VK.SECRET,
|
||||||
code,
|
code,
|
||||||
redirect_uri: `${proto}://${host}/auth/social/vk`,
|
redirect_uri: `${proto}://${host}/api/auth/social/vk`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).catch(() => {
|
).catch(() => {
|
||||||
|
|
|
@ -40,8 +40,8 @@ export interface IMapListDialogProps extends IRootState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMapListDialogState {
|
export interface IMapListDialogState {
|
||||||
menu_target: IRouteListItem['_id'],
|
menu_target: IRouteListItem['address'],
|
||||||
editor_target: IRouteListItem['_id'],
|
editor_target: IRouteListItem['address'],
|
||||||
|
|
||||||
is_editing: boolean,
|
is_editing: boolean,
|
||||||
is_dropping: boolean,
|
is_dropping: boolean,
|
||||||
|
@ -56,14 +56,14 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
||||||
is_dropping: false,
|
is_dropping: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
startEditing = (editor_target: IRouteListItem['_id']): void => this.setState({
|
startEditing = (editor_target: IRouteListItem['address']): void => this.setState({
|
||||||
editor_target,
|
editor_target,
|
||||||
menu_target: null,
|
menu_target: null,
|
||||||
is_editing: true,
|
is_editing: true,
|
||||||
is_dropping: false,
|
is_dropping: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
showMenu = (menu_target: IRouteListItem['_id']): void => this.setState({
|
showMenu = (menu_target: IRouteListItem['address']): void => this.setState({
|
||||||
menu_target,
|
menu_target,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
||||||
menu_target: null,
|
menu_target: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
showDropCard = (editor_target: IRouteListItem['_id']): void => this.setState({
|
showDropCard = (editor_target: IRouteListItem['address']): void => this.setState({
|
||||||
editor_target,
|
editor_target,
|
||||||
menu_target: null,
|
menu_target: null,
|
||||||
is_editing: false,
|
is_editing: false,
|
||||||
|
@ -211,13 +211,13 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
||||||
<RouteRowWrapper
|
<RouteRowWrapper
|
||||||
title={route.title}
|
title={route.title}
|
||||||
distance={route.distance}
|
distance={route.distance}
|
||||||
_id={route._id}
|
_id={route.address}
|
||||||
is_public={route.is_public}
|
is_public={route.is_public}
|
||||||
is_starred={route.is_starred}
|
is_starred={route.is_starred}
|
||||||
tab={tab}
|
tab={tab}
|
||||||
is_editing_mode={is_dropping ? 'drop' : 'edit'}
|
is_editing_mode={is_dropping ? 'drop' : 'edit'}
|
||||||
is_editing_target={editor_target === route._id}
|
is_editing_target={editor_target === route.address}
|
||||||
is_menu_target={menu_target === route._id}
|
is_menu_target={menu_target === route.address}
|
||||||
openRoute={this.openRoute}
|
openRoute={this.openRoute}
|
||||||
startEditing={this.startEditing}
|
startEditing={this.startEditing}
|
||||||
stopEditing={this.stopEditing}
|
stopEditing={this.stopEditing}
|
||||||
|
@ -227,7 +227,7 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
||||||
dropRoute={this.dropRoute}
|
dropRoute={this.dropRoute}
|
||||||
modifyRoute={this.modifyRoute}
|
modifyRoute={this.modifyRoute}
|
||||||
toggleStarred={this.toggleStarred}
|
toggleStarred={this.toggleStarred}
|
||||||
key={route._id}
|
key={route.address}
|
||||||
is_admin={role === ROLES.admin}
|
is_admin={role === ROLES.admin}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const RouteRowView = ({
|
||||||
title, distance, _id, openRoute, tab, startEditing, showMenu, showDropCard, hideMenu, is_admin, is_starred, toggleStarred,
|
title, distance, _id, openRoute, tab, startEditing, showMenu, showDropCard, hideMenu, is_admin, is_starred, toggleStarred,
|
||||||
}: Props): ReactElement<Props, null> => (
|
}: Props): ReactElement<Props, null> => (
|
||||||
<div
|
<div
|
||||||
className={classnames('route-row-view', { has_menu: (tab === 'mine') })}
|
className={classnames('route-row-view', { has_menu: (tab === 'my') })}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
(tab === 'all' || tab === 'starred') && is_admin &&
|
(tab === 'all' || tab === 'starred') && is_admin &&
|
||||||
|
@ -48,7 +48,7 @@ export const RouteRowView = ({
|
||||||
>
|
>
|
||||||
<div className="route-title">
|
<div className="route-title">
|
||||||
{
|
{
|
||||||
(tab === 'mine' || !is_admin) && is_starred &&
|
(tab === 'my' || !is_admin) && is_starred &&
|
||||||
<div className="route-row-corner"><Icon icon="icon-star-fill" size={18} /></div>
|
<div className="route-row-corner"><Icon icon="icon-star-fill" size={18} /></div>
|
||||||
}
|
}
|
||||||
<span>
|
<span>
|
||||||
|
@ -68,7 +68,7 @@ export const RouteRowView = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
tab === 'mine' &&
|
tab === 'my' &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div
|
<div
|
||||||
className="route-row-edit-button pointer"
|
className="route-row-edit-button pointer"
|
||||||
|
|
|
@ -65,7 +65,7 @@ export class Component extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
setMenuOpened = () => this.setState({ menuOpened: !this.state.menuOpened });
|
setMenuOpened = () => this.setState({ menuOpened: !this.state.menuOpened });
|
||||||
openMapsDialog = () => {
|
openMapsDialog = () => {
|
||||||
this.props.openMapDialog('mine');
|
this.props.openMapDialog('my');
|
||||||
};
|
};
|
||||||
|
|
||||||
openAppInfoDialog = () => {
|
openAppInfoDialog = () => {
|
||||||
|
@ -81,7 +81,7 @@ export class Component extends React.PureComponent<Props, State> {
|
||||||
const left = (width - 700) / 2;
|
const left = (width - 700) / 2;
|
||||||
|
|
||||||
window.open(
|
window.open(
|
||||||
`https://oauth.vk.com/authorize?client_id=5987644&scope=&redirect_uri=${CLIENT.API_ADDR}/auth/social/vk`,
|
`https://oauth.vk.com/authorize?client_id=5987644&scope=&redirect_uri=${CLIENT.API_ADDR}/api/auth/vk`,
|
||||||
'socialPopupWindow',
|
'socialPopupWindow',
|
||||||
`location=no,width=700,height=370,scrollbars=no,top=${top},left=${left},resizable=no`
|
`location=no,width=700,height=370,scrollbars=no,top=${top},left=${left},resizable=no`
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,28 +1,24 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { UserPicture } from '$components/user/UserPicture';
|
import { UserPicture } from "$components/user/UserPicture";
|
||||||
import { IUser } from "$constants/auth";
|
import { IUser } from "$constants/auth";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: IUser,
|
user: IUser;
|
||||||
setMenuOpened: () => void,
|
setMenuOpened: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserButton = ({
|
export const UserButton = ({
|
||||||
setMenuOpened,
|
setMenuOpened,
|
||||||
user: {
|
user: { uid, photo, name }
|
||||||
id,
|
|
||||||
photo,
|
|
||||||
first_name,
|
|
||||||
}
|
|
||||||
}: Props) => (
|
}: Props) => (
|
||||||
<div className="control-bar user-bar">
|
<div className="control-bar user-bar">
|
||||||
<div className="user-button" onClick={setMenuOpened}>
|
<div className="user-button" onClick={setMenuOpened}>
|
||||||
<UserPicture photo={photo} />
|
<UserPicture photo={photo} />
|
||||||
|
|
||||||
<div className="user-button-fields">
|
<div className="user-button-fields">
|
||||||
<div className="user-button-name">{(first_name || id || '...')}</div>
|
<div className="user-button-name">{name || uid || "..."}</div>
|
||||||
<div className="user-button-text">{(id || 'пользователь')}</div>
|
<div className="user-button-text">{uid || "пользователь"}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { CLIENT } from '$config/frontend';
|
import { CLIENT } from '$config/frontend';
|
||||||
|
|
||||||
export const API: { [x: string]: string } = {
|
export const API: { [x: string]: string } = {
|
||||||
GET_GUEST: `${CLIENT.API_ADDR}/auth`,
|
GET_GUEST: `${CLIENT.API_ADDR}/api/auth/`,
|
||||||
CHECK_TOKEN: `${CLIENT.API_ADDR}/auth`,
|
CHECK_TOKEN: `${CLIENT.API_ADDR}/api/auth/`,
|
||||||
IFRAME_LOGIN_VK: `${CLIENT.API_ADDR}/auth/iframe/vk`,
|
IFRAME_LOGIN_VK: `${CLIENT.API_ADDR}/api/auth/vk/`,
|
||||||
GET_MAP: `${CLIENT.API_ADDR}/route`,
|
GET_MAP: `${CLIENT.API_ADDR}/api/route/`,
|
||||||
POST_MAP: `${CLIENT.API_ADDR}/route`,
|
POST_MAP: `${CLIENT.API_ADDR}/api/route/`,
|
||||||
GET_ROUTE_LIST: `${CLIENT.API_ADDR}/route/list`,
|
GET_ROUTE_LIST: `${CLIENT.API_ADDR}/api/route/list/`,
|
||||||
|
|
||||||
DROP_ROUTE: `${CLIENT.API_ADDR}/route`,
|
DROP_ROUTE: `${CLIENT.API_ADDR}/api/route/`,
|
||||||
MODIFY_ROUTE: `${CLIENT.API_ADDR}/route/modify`,
|
MODIFY_ROUTE: `${CLIENT.API_ADDR}/api/route/`,
|
||||||
SET_STARRED: `${CLIENT.API_ADDR}/route/star`,
|
SET_STARRED: `${CLIENT.API_ADDR}/api/route/publish/`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const API_RETRY_INTERVAL = 10;
|
export const API_RETRY_INTERVAL = 10;
|
||||||
|
|
|
@ -1,42 +1,39 @@
|
||||||
export interface IRoles {
|
export interface IRoles {
|
||||||
guest: string,
|
guest: string;
|
||||||
vk: string,
|
vk: string;
|
||||||
admin: string,
|
admin: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUser {
|
export interface IUser {
|
||||||
new_messages: number,
|
new_messages: number;
|
||||||
place_types: {},
|
place_types: {};
|
||||||
random_url: string,
|
random_url: string;
|
||||||
role: IRoles[keyof IRoles],
|
role: IRoles[keyof IRoles];
|
||||||
routes: {},
|
routes: {};
|
||||||
success: boolean,
|
success: boolean;
|
||||||
id?: string,
|
id?: number;
|
||||||
token?: string,
|
uid: string;
|
||||||
photo: string,
|
token?: string;
|
||||||
first_name: string,
|
photo: string;
|
||||||
// userdata: {
|
name: string;
|
||||||
// name: string,
|
|
||||||
// agent: string,
|
|
||||||
// ip: string,
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ROLES: IRoles = {
|
export const ROLES: IRoles = {
|
||||||
guest: 'guest',
|
guest: "guest",
|
||||||
vk: 'vk',
|
vk: "vk",
|
||||||
admin: 'admin',
|
admin: "admin"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_USER: IUser = {
|
export const DEFAULT_USER: IUser = {
|
||||||
new_messages: 0,
|
new_messages: 0,
|
||||||
place_types: {},
|
place_types: {},
|
||||||
random_url: '',
|
random_url: "",
|
||||||
role: ROLES.guest,
|
role: ROLES.guest,
|
||||||
routes: {},
|
routes: {},
|
||||||
success: false,
|
success: false,
|
||||||
id: null,
|
id: null,
|
||||||
token: null,
|
token: null,
|
||||||
photo: null,
|
photo: null,
|
||||||
first_name: null,
|
name: null,
|
||||||
|
uid: null,
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ export interface IDialogs {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMapTabs {
|
export interface IMapTabs {
|
||||||
mine: string,
|
my: string,
|
||||||
all: string,
|
all: string,
|
||||||
starred: string,
|
starred: string,
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export const DIALOGS: IDialogs = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const TABS: IMapTabs = ({
|
export const TABS: IMapTabs = ({
|
||||||
mine: 'Мои',
|
my: 'Мои',
|
||||||
all: 'Заявки',
|
all: 'Заявки',
|
||||||
starred: 'Каталог',
|
starred: 'Каталог',
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,6 +15,17 @@ export interface IStickerPack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISticker {
|
||||||
|
angle: number;
|
||||||
|
set: string;
|
||||||
|
sticker: string;
|
||||||
|
text: string;
|
||||||
|
latlngs: {
|
||||||
|
lat: number;
|
||||||
|
lng: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface IStickers {
|
export interface IStickers {
|
||||||
base: IStickerPack,
|
base: IStickerPack,
|
||||||
real: IStickerPack,
|
real: IStickerPack,
|
||||||
|
|
|
@ -34,11 +34,11 @@ interface IEditor {
|
||||||
router: Router;
|
router: Router;
|
||||||
|
|
||||||
logo: keyof ILogos;
|
logo: keyof ILogos;
|
||||||
owner: { id: string };
|
owner: number;
|
||||||
initialData: {
|
initialData: {
|
||||||
version: number,
|
version: number,
|
||||||
title: IRootState['title'],
|
title: IRootState['title'],
|
||||||
owner: { id: string },
|
owner: number,
|
||||||
address: IRootState['address'],
|
address: IRootState['address'],
|
||||||
path: any,
|
path: any,
|
||||||
route: any,
|
route: any,
|
||||||
|
@ -322,11 +322,11 @@ export class Editor {
|
||||||
is_public,
|
is_public,
|
||||||
is_starred,
|
is_starred,
|
||||||
description,
|
description,
|
||||||
}: IEditor['initialData']): void => {
|
}: Partial<IEditor['initialData']>): void => {
|
||||||
this.setTitle(title || '');
|
this.setTitle(title || '');
|
||||||
const { id } = this.getUser();
|
const { id } = this.getUser();
|
||||||
|
|
||||||
if (address && id && owner && id === owner.id) {
|
if (address && id && owner && id === owner) {
|
||||||
this.setAddress(address);
|
this.setAddress(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +389,7 @@ export class Editor {
|
||||||
version: 2,
|
version: 2,
|
||||||
title: this.getTitle(),
|
title: this.getTitle(),
|
||||||
owner: this.owner,
|
owner: this.owner,
|
||||||
address: (this.owner.id === id ? path : null),
|
address: (this.owner === id ? path : null),
|
||||||
path,
|
path,
|
||||||
route,
|
route,
|
||||||
stickers,
|
stickers,
|
||||||
|
@ -405,7 +405,7 @@ export class Editor {
|
||||||
const { id } = this.getUser();
|
const { id } = this.getUser();
|
||||||
|
|
||||||
this.setInitialData();
|
this.setInitialData();
|
||||||
this.owner = { id };
|
this.owner = id;
|
||||||
|
|
||||||
this.poly.enableEditor();
|
this.poly.enableEditor();
|
||||||
this.stickers.startEditing();
|
this.stickers.startEditing();
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { persistStore, persistReducer } from 'redux-persist';
|
||||||
import storage from 'redux-persist/lib/storage';
|
import storage from 'redux-persist/lib/storage';
|
||||||
import createSagaMiddleware from 'redux-saga';
|
import createSagaMiddleware from 'redux-saga';
|
||||||
|
|
||||||
import { userReducer } from '$redux/user/reducer';
|
import { userReducer, IRootReducer } from '$redux/user/reducer';
|
||||||
import { userSaga } from '$redux/user/sagas';
|
import { userSaga } from '$redux/user/sagas';
|
||||||
import { createBrowserHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
import { locationChanged } from '$redux/user/actions';
|
import { locationChanged } from '$redux/user/actions';
|
||||||
|
@ -16,6 +16,9 @@ const userPersistConfig: PersistConfig = {
|
||||||
storage,
|
storage,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface IState {
|
||||||
|
user: IRootReducer
|
||||||
|
}
|
||||||
// create the saga middleware
|
// create the saga middleware
|
||||||
export const sagaMiddleware = createSagaMiddleware();
|
export const sagaMiddleware = createSagaMiddleware();
|
||||||
|
|
||||||
|
|
|
@ -94,9 +94,9 @@ export const mapsSetShift = (shift: number) => ({ type: ACTIONS.MAPS_SET_SHIFT,
|
||||||
export const setFeature = (features: { [x: string]: boolean }) => ({ type: ACTIONS.SET_FEATURE, features });
|
export const setFeature = (features: { [x: string]: boolean }) => ({ type: ACTIONS.SET_FEATURE, features });
|
||||||
export const setIsRouting = (is_routing: boolean) => ({ type: ACTIONS.SET_IS_ROUTING, is_routing });
|
export const setIsRouting = (is_routing: boolean) => ({ type: ACTIONS.SET_IS_ROUTING, is_routing });
|
||||||
|
|
||||||
export const dropRoute = (_id: string) => ({ type: ACTIONS.DROP_ROUTE, _id });
|
export const dropRoute = (address: string) => ({ type: ACTIONS.DROP_ROUTE, address });
|
||||||
export const modifyRoute = (_id: string, { title, is_public }: { title: string, is_public: boolean }) => ({
|
export const modifyRoute = (address: string, { title, is_public }: { title: string, is_public: boolean }) => ({
|
||||||
type: ACTIONS.MODIFY_ROUTE, _id, title, is_public
|
type: ACTIONS.MODIFY_ROUTE, address, title, is_public
|
||||||
});
|
});
|
||||||
export const toggleRouteStarred = (_id: string) => ({ type: ACTIONS.TOGGLE_ROUTE_STARRED, _id });
|
export const toggleRouteStarred = (address: string) => ({ type: ACTIONS.TOGGLE_ROUTE_STARRED, address });
|
||||||
export const setRouteStarred = (_id: string, is_starred: boolean) => ({ type: ACTIONS.SET_ROUTE_STARRED, _id, is_starred });
|
export const setRouteStarred = (address: string, is_starred: boolean) => ({ type: ACTIONS.SET_ROUTE_STARRED, address, is_starred });
|
||||||
|
|
|
@ -7,10 +7,27 @@ import { TIPS } from '$constants/tips';
|
||||||
import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers';
|
import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers';
|
||||||
import { DIALOGS, IDialogs, TABS } from '$constants/dialogs';
|
import { DIALOGS, IDialogs, TABS } from '$constants/dialogs';
|
||||||
import * as ActionCreators from '$redux/user/actions';
|
import * as ActionCreators from '$redux/user/actions';
|
||||||
import { IStickers } from "$constants/stickers";
|
import { IStickers, ISticker } from "$constants/stickers";
|
||||||
|
import { IRoutePoint } from '$utils/gpx';
|
||||||
|
import { IStickerDump } from '$modules/Sticker';
|
||||||
|
|
||||||
|
export interface IRoute {
|
||||||
|
version: number,
|
||||||
|
title: IRootState['title'],
|
||||||
|
owner: number,
|
||||||
|
address: IRootState['address'],
|
||||||
|
route: IRoutePoint[],
|
||||||
|
stickers: IStickerDump[],
|
||||||
|
provider: IRootState['provider'],
|
||||||
|
is_public: IRootState['is_public'],
|
||||||
|
is_published: IRootState['is_starred'],
|
||||||
|
description: IRootState['description'],
|
||||||
|
logo: IRootState['logo'],
|
||||||
|
distance: IRootState['distance']
|
||||||
|
}
|
||||||
|
|
||||||
export interface IRouteListItem {
|
export interface IRouteListItem {
|
||||||
_id: string,
|
address: string,
|
||||||
title: string,
|
title: string,
|
||||||
distance: number,
|
distance: number,
|
||||||
is_public: boolean,
|
is_public: boolean,
|
||||||
|
@ -318,13 +335,13 @@ const setIsRouting: ActionHandler<typeof ActionCreators.setIsRouting> = (state,
|
||||||
is_routing,
|
is_routing,
|
||||||
});
|
});
|
||||||
|
|
||||||
const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (state, { _id, is_starred }) => ({
|
const setRouteStarred: ActionHandler<typeof ActionCreators.setRouteStarred> = (state, { address, is_starred }) => ({
|
||||||
...state,
|
...state,
|
||||||
routes: {
|
routes: {
|
||||||
...state.routes,
|
...state.routes,
|
||||||
list: (
|
list: (
|
||||||
state.routes.list
|
state.routes.list
|
||||||
.map(el => el._id === _id ? { ...el, is_starred } : el)
|
.map(el => el.address === address ? { ...el, is_starred } : el)
|
||||||
.filter(el => (
|
.filter(el => (
|
||||||
(state.routes.filter.tab === 'starred' && el.is_starred) ||
|
(state.routes.filter.tab === 'starred' && el.is_starred) ||
|
||||||
(state.routes.filter.tab === 'all' && !el.is_starred)
|
(state.routes.filter.tab === 'all' && !el.is_starred)
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
import { REHYDRATE } from 'redux-persist';
|
import { REHYDRATE } from "redux-persist";
|
||||||
import { delay, SagaIterator } from 'redux-saga';
|
import { delay, SagaIterator } from "redux-saga";
|
||||||
import { takeLatest, select, call, put, takeEvery, race, take } from 'redux-saga/effects';
|
|
||||||
import {
|
import {
|
||||||
checkIframeToken, checkOSRMService,
|
takeLatest,
|
||||||
checkUserToken, dropRoute,
|
select,
|
||||||
getGuestToken, getRouteList,
|
call,
|
||||||
getStoredMap, modifyRoute,
|
put,
|
||||||
postMap, sendRouteStarred
|
takeEvery,
|
||||||
} from '$utils/api';
|
race,
|
||||||
|
take,
|
||||||
|
TakeEffect
|
||||||
|
} from "redux-saga/effects";
|
||||||
|
import {
|
||||||
|
checkIframeToken,
|
||||||
|
checkOSRMService,
|
||||||
|
checkUserToken,
|
||||||
|
dropRoute,
|
||||||
|
getGuestToken,
|
||||||
|
getRouteList,
|
||||||
|
getStoredMap,
|
||||||
|
modifyRoute,
|
||||||
|
postMap,
|
||||||
|
sendRouteStarred
|
||||||
|
} from "$utils/api";
|
||||||
import {
|
import {
|
||||||
hideRenderer,
|
hideRenderer,
|
||||||
searchPutRoutes,
|
searchPutRoutes,
|
||||||
|
@ -32,54 +46,79 @@ import {
|
||||||
setProvider,
|
setProvider,
|
||||||
changeProvider,
|
changeProvider,
|
||||||
setSaveLoading,
|
setSaveLoading,
|
||||||
mapsSetShift, searchChangeDistance, clearAll, setFeature, searchSetTitle, setRouteStarred, setDescription,
|
mapsSetShift,
|
||||||
} from '$redux/user/actions';
|
searchChangeDistance,
|
||||||
import { getUrlData, parseQuery, pushLoaderState, pushNetworkInitError, pushPath, replacePath } from '$utils/history';
|
clearAll,
|
||||||
import { editor } from '$modules/Editor';
|
setFeature,
|
||||||
import { ACTIONS } from '$redux/user/constants';
|
searchSetTitle,
|
||||||
import { MODES } from '$constants/modes';
|
setRouteStarred,
|
||||||
import { DEFAULT_USER } from '$constants/auth';
|
setDescription
|
||||||
import { TIPS } from '$constants/tips';
|
} from "$redux/user/actions";
|
||||||
import {
|
import {
|
||||||
composeArrows, composeDistMark,
|
getUrlData,
|
||||||
|
parseQuery,
|
||||||
|
pushLoaderState,
|
||||||
|
pushNetworkInitError,
|
||||||
|
pushPath,
|
||||||
|
replacePath
|
||||||
|
} from "$utils/history";
|
||||||
|
import { editor } from "$modules/Editor";
|
||||||
|
import { ACTIONS } from "$redux/user/constants";
|
||||||
|
import { MODES } from "$constants/modes";
|
||||||
|
import { DEFAULT_USER, IUser } from "$constants/auth";
|
||||||
|
import { TIPS } from "$constants/tips";
|
||||||
|
import {
|
||||||
|
composeArrows,
|
||||||
|
composeDistMark,
|
||||||
composeImages,
|
composeImages,
|
||||||
composePoly, composeStickers, downloadCanvas,
|
composePoly,
|
||||||
|
composeStickers,
|
||||||
|
downloadCanvas,
|
||||||
fetchImages,
|
fetchImages,
|
||||||
getPolyPlacement, getStickersPlacement,
|
getPolyPlacement,
|
||||||
|
getStickersPlacement,
|
||||||
getTilePlacement,
|
getTilePlacement,
|
||||||
imageFetcher
|
imageFetcher
|
||||||
} from '$utils/renderer';
|
} from "$utils/renderer";
|
||||||
import { ILogos, LOGOS } from '$constants/logos';
|
import { LOGOS } from "$constants/logos";
|
||||||
import { DEFAULT_PROVIDER } from '$constants/providers';
|
import { DEFAULT_PROVIDER } from "$constants/providers";
|
||||||
import { DIALOGS, TABS } from '$constants/dialogs';
|
import { DIALOGS } from "$constants/dialogs";
|
||||||
|
|
||||||
import * as ActionCreators from '$redux/user/actions';
|
import * as ActionCreators from "$redux/user/actions";
|
||||||
import { IRootState } from "$redux/user/reducer";
|
import { IRootState } from "$redux/user/reducer";
|
||||||
import { downloadGPXTrack, getGPXString } from "$utils/gpx";
|
import { downloadGPXTrack, getGPXString } from "$utils/gpx";
|
||||||
|
import { Unwrap } from "$utils/middleware";
|
||||||
|
import { IState } from "$redux/store";
|
||||||
|
|
||||||
const getUser = state => (state.user.user);
|
const getUser = (state: IState) => state.user.user;
|
||||||
const getState = state => (state.user);
|
const getState = (state: IState) => state.user;
|
||||||
|
|
||||||
const hideLoader = () => {
|
const hideLoader = () => {
|
||||||
document.getElementById('loader').style.opacity = String(0);
|
document.getElementById("loader").style.opacity = String(0);
|
||||||
document.getElementById('loader').style.pointerEvents = 'none';
|
document.getElementById("loader").style.pointerEvents = "none";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
function* generateGuestSaga() {
|
function* generateGuestSaga() {
|
||||||
const user = yield call(getGuestToken);
|
const {
|
||||||
yield put(setUser(user));
|
data: { user, random_url }
|
||||||
|
}: Unwrap<typeof getGuestToken> = yield call(getGuestToken);
|
||||||
|
|
||||||
return user;
|
yield put(setUser({ ...user, random_url }));
|
||||||
|
|
||||||
|
return { ...user, random_url };
|
||||||
}
|
}
|
||||||
|
|
||||||
function* startEmptyEditorSaga() {
|
function* startEmptyEditorSaga() {
|
||||||
const { user: { id, random_url }, provider = DEFAULT_PROVIDER } = yield select(getState);
|
const {
|
||||||
|
user: { id, random_url },
|
||||||
|
provider = DEFAULT_PROVIDER
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
pushPath(`/${random_url}/edit`);
|
pushPath(`/${random_url}/edit`);
|
||||||
|
|
||||||
editor.owner = { id };
|
editor.owner = id;
|
||||||
editor.setProvider(provider);
|
editor.setProvider(provider);
|
||||||
editor.startEditing();
|
editor.startEditing();
|
||||||
|
|
||||||
|
@ -95,9 +134,7 @@ function* startEditingSaga() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function* stopEditingSaga() {
|
function* stopEditingSaga() {
|
||||||
const {
|
const { changed, editing, mode, address_origin } = yield select(getState);
|
||||||
changed, editing, mode, address_origin
|
|
||||||
} = yield select(getState);
|
|
||||||
const { path } = getUrlData();
|
const { path } = getUrlData();
|
||||||
|
|
||||||
if (!editing) return;
|
if (!editing) return;
|
||||||
|
@ -111,22 +148,24 @@ function* stopEditingSaga() {
|
||||||
yield put(setChanged(false));
|
yield put(setChanged(false));
|
||||||
yield put(setEditing(editor.hasEmptyHistory)); // don't close editor if no previous map
|
yield put(setEditing(editor.hasEmptyHistory)); // don't close editor if no previous map
|
||||||
|
|
||||||
yield pushPath(`/${(address_origin || path)}/`);
|
yield pushPath(`/${address_origin || path}/`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* loadMapSaga(path) {
|
function* loadMapSaga(path) {
|
||||||
const map = yield call(getStoredMap, { name: path });
|
const { data: { route, error, random_url } }: Unwrap<typeof getStoredMap> = yield call(getStoredMap, { name: path });
|
||||||
|
|
||||||
if (map) {
|
if (route && !error) {
|
||||||
yield editor.clearAll();
|
yield editor.clearAll();
|
||||||
yield editor.setData(map);
|
yield editor.setData(route);
|
||||||
yield editor.fitDrawing();
|
yield editor.fitDrawing();
|
||||||
yield editor.setInitialData();
|
yield editor.setInitialData();
|
||||||
|
|
||||||
yield put(setChanged(false));
|
yield put(setChanged(false));
|
||||||
|
|
||||||
|
return { route, random_url };
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function* replaceAddressIfItsBusy(destination, original) {
|
function* replaceAddressIfItsBusy(destination, original) {
|
||||||
|
@ -150,14 +189,17 @@ function* setReadySaga() {
|
||||||
hideLoader();
|
hideLoader();
|
||||||
|
|
||||||
yield call(checkOSRMServiceSaga);
|
yield call(checkOSRMServiceSaga);
|
||||||
yield put(searchSetTab('mine'));
|
yield put(searchSetTab("my"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* mapInitSaga() {
|
function* mapInitSaga() {
|
||||||
pushLoaderState(90);
|
pushLoaderState(90);
|
||||||
|
|
||||||
const { path, mode, hash } = getUrlData();
|
const { path, mode, hash } = getUrlData();
|
||||||
const { provider, user: { id } } = yield select(getState);
|
const {
|
||||||
|
provider,
|
||||||
|
user: { id }
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
editor.map.setProvider(provider);
|
editor.map.setProvider(provider);
|
||||||
yield put(changeProvider(provider));
|
yield put(changeProvider(provider));
|
||||||
|
@ -174,13 +216,13 @@ function* mapInitSaga() {
|
||||||
if (path) {
|
if (path) {
|
||||||
const map = yield call(loadMapSaga, path);
|
const map = yield call(loadMapSaga, path);
|
||||||
|
|
||||||
if (map) {
|
if (map && map.route) {
|
||||||
if (mode && mode === 'edit') {
|
if (mode && mode === "edit") {
|
||||||
if (map && map.owner && mode === 'edit' && map.owner.id !== id) {
|
if (map && map.route && map.route.owner && mode === "edit" && map.route.owner !== id) {
|
||||||
yield call(setReadySaga);
|
yield call(setReadySaga);
|
||||||
yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
||||||
} else {
|
} else {
|
||||||
yield put(setAddressOrigin(''));
|
yield put(setAddressOrigin(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(setEditing(true));
|
yield put(setEditing(true));
|
||||||
|
@ -226,10 +268,15 @@ function* authCheckSaga() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id && token) {
|
if (id && token) {
|
||||||
const user = yield call(checkUserToken, { id, token });
|
const {
|
||||||
|
data: { user, random_url }
|
||||||
|
}: Unwrap<typeof checkUserToken> = yield call(checkUserToken, {
|
||||||
|
id,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
yield put(setUser(user));
|
yield put(setUser({ ...user, random_url }));
|
||||||
|
|
||||||
pushLoaderState(99);
|
pushLoaderState(99);
|
||||||
|
|
||||||
|
@ -251,14 +298,19 @@ function* setModeSaga({ mode }: ReturnType<typeof ActionCreators.setMode>) {
|
||||||
// console.log('change', mode);
|
// console.log('change', mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setActiveStickerSaga({ activeSticker }: { type: string, activeSticker: IRootState['activeSticker'] }) {
|
function* setActiveStickerSaga({
|
||||||
yield editor.activeSticker = activeSticker;
|
activeSticker
|
||||||
|
}: {
|
||||||
|
type: string;
|
||||||
|
activeSticker: IRootState["activeSticker"];
|
||||||
|
}) {
|
||||||
|
yield (editor.activeSticker = activeSticker);
|
||||||
yield put(setMode(MODES.STICKERS));
|
yield put(setMode(MODES.STICKERS));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setLogoSaga({ logo }: { type: string, logo: string }) {
|
function* setLogoSaga({ logo }: { type: string; logo: string }) {
|
||||||
const { mode } = yield select(getState);
|
const { mode } = yield select(getState);
|
||||||
editor.logo = logo;
|
editor.logo = logo;
|
||||||
|
|
||||||
|
@ -299,7 +351,8 @@ function* clearSaga({ type }) {
|
||||||
yield put(setChanged(false));
|
yield put(setChanged(false));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(setActiveSticker(null));
|
yield put(setActiveSticker(null));
|
||||||
|
@ -307,48 +360,75 @@ function* clearSaga({ type }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function* sendSaveRequestSaga({
|
function* sendSaveRequestSaga({
|
||||||
title, address, force, is_public, description,
|
title,
|
||||||
|
address,
|
||||||
|
force,
|
||||||
|
is_public,
|
||||||
|
description
|
||||||
}: ReturnType<typeof ActionCreators.sendSaveRequest>) {
|
}: ReturnType<typeof ActionCreators.sendSaveRequest>) {
|
||||||
if (editor.isEmpty) return yield put(setSaveError(TIPS.SAVE_EMPTY));
|
if (editor.isEmpty) return yield put(setSaveError(TIPS.SAVE_EMPTY));
|
||||||
|
|
||||||
const { route, stickers, provider } = editor.dumpData();
|
const { route, stickers, provider } = editor.dumpData();
|
||||||
const { logo, distance } = yield select(getState);
|
const { logo, distance } = yield select(getState);
|
||||||
const { id, token } = yield select(getUser);
|
const { token } = yield select(getUser);
|
||||||
|
|
||||||
yield put(setSaveLoading(true));
|
yield put(setSaveLoading(true));
|
||||||
|
|
||||||
const { result, timeout, cancel } = yield race({
|
const {
|
||||||
|
result,
|
||||||
|
timeout,
|
||||||
|
cancel
|
||||||
|
}: {
|
||||||
|
result: Unwrap<typeof postMap>;
|
||||||
|
timeout: boolean;
|
||||||
|
cancel: TakeEffect;
|
||||||
|
} = yield race({
|
||||||
result: postMap({
|
result: postMap({
|
||||||
id, token, route, stickers, title, force, address, logo, distance, provider, is_public, description,
|
token,
|
||||||
|
route,
|
||||||
|
stickers,
|
||||||
|
title,
|
||||||
|
force,
|
||||||
|
address,
|
||||||
|
logo,
|
||||||
|
distance,
|
||||||
|
provider,
|
||||||
|
is_public,
|
||||||
|
description
|
||||||
}),
|
}),
|
||||||
timeout: delay(10000),
|
timeout: delay(10000),
|
||||||
cancel: take(ACTIONS.RESET_SAVE_DIALOG),
|
cancel: take(ACTIONS.RESET_SAVE_DIALOG)
|
||||||
});
|
});
|
||||||
|
|
||||||
yield put(setSaveLoading(false));
|
yield put(setSaveLoading(false));
|
||||||
|
|
||||||
if (cancel) return yield put(setMode(MODES.NONE));
|
if (cancel) return yield put(setMode(MODES.NONE));
|
||||||
if (result && result.mode === 'overwriting') return yield put(setSaveOverwrite());
|
if (result && result.mode === "overwriting")
|
||||||
if (result && result.mode === 'exists') return yield put(setSaveError(TIPS.SAVE_EXISTS));
|
return yield put(setSaveOverwrite());
|
||||||
if (timeout || !result || !result.success || !result.address) return yield put(setSaveError(TIPS.SAVE_TIMED_OUT));
|
if (result && result.mode === "exists")
|
||||||
|
return yield put(setSaveError(TIPS.SAVE_EXISTS));
|
||||||
|
if (timeout || !result || !result.success || !result.address)
|
||||||
|
return yield put(setSaveError(TIPS.SAVE_TIMED_OUT));
|
||||||
|
|
||||||
return yield put(setSaveSuccess({
|
return yield put(
|
||||||
address: result.address,
|
setSaveSuccess({
|
||||||
title: result.title,
|
address: result.address,
|
||||||
is_public: result.is_public,
|
title: result.title,
|
||||||
description: result.description,
|
is_public: result.is_public,
|
||||||
|
description: result.description,
|
||||||
|
|
||||||
save_error: TIPS.SAVE_SUCCESS,
|
save_error: TIPS.SAVE_SUCCESS
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* getRenderData() {
|
function* getRenderData() {
|
||||||
yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 }));
|
yield put(setRenderer({ info: "Загрузка тайлов", progress: 0.1 }));
|
||||||
|
|
||||||
const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
const canvas = <HTMLCanvasElement>document.getElementById("renderer");
|
||||||
canvas.width = window.innerWidth;
|
canvas.width = window.innerWidth;
|
||||||
canvas.height = window.innerHeight;
|
canvas.height = window.innerHeight;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
const geometry = getTilePlacement();
|
const geometry = getTilePlacement();
|
||||||
const points = getPolyPlacement();
|
const points = getPolyPlacement();
|
||||||
|
@ -359,7 +439,7 @@ function* getRenderData() {
|
||||||
|
|
||||||
const images = yield fetchImages(ctx, geometry);
|
const images = yield fetchImages(ctx, geometry);
|
||||||
|
|
||||||
yield put(setRenderer({ info: 'Отрисовка', progress: 0.5 }));
|
yield put(setRenderer({ info: "Отрисовка", progress: 0.5 }));
|
||||||
|
|
||||||
yield composeImages({ geometry, images, ctx });
|
yield composeImages({ geometry, images, ctx });
|
||||||
yield composePoly({ points, ctx });
|
yield composePoly({ points, ctx });
|
||||||
|
@ -367,9 +447,9 @@ function* getRenderData() {
|
||||||
yield composeDistMark({ ctx, points, distance });
|
yield composeDistMark({ ctx, points, distance });
|
||||||
yield composeStickers({ stickers, ctx });
|
yield composeStickers({ stickers, ctx });
|
||||||
|
|
||||||
yield put(setRenderer({ info: 'Готово', progress: 1 }));
|
yield put(setRenderer({ info: "Готово", progress: 1 }));
|
||||||
|
|
||||||
return yield canvas.toDataURL('image/jpeg');
|
return yield canvas.toDataURL("image/jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
function* takeAShotSaga() {
|
function* takeAShotSaga() {
|
||||||
|
@ -377,50 +457,62 @@ function* takeAShotSaga() {
|
||||||
|
|
||||||
const { result, timeout } = yield race({
|
const { result, timeout } = yield race({
|
||||||
result: worker,
|
result: worker,
|
||||||
timeout: delay(500),
|
timeout: delay(500)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (timeout) yield put(setMode(MODES.SHOT_PREFETCH));
|
if (timeout) yield put(setMode(MODES.SHOT_PREFETCH));
|
||||||
|
|
||||||
const data = yield (result || worker);
|
const data = yield result || worker;
|
||||||
|
|
||||||
yield put(setMode(MODES.NONE));
|
yield put(setMode(MODES.NONE));
|
||||||
yield put(setRenderer({
|
yield put(
|
||||||
data, renderer_active: true, width: window.innerWidth, height: window.innerHeight
|
setRenderer({
|
||||||
}));
|
data,
|
||||||
|
renderer_active: true,
|
||||||
|
width: window.innerWidth,
|
||||||
|
height: window.innerHeight
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* getCropData({
|
function* getCropData({ x, y, width, height }) {
|
||||||
x, y, width, height
|
const {
|
||||||
}) {
|
logo,
|
||||||
const { logo, renderer: { data } } = yield select(getState);
|
renderer: { data }
|
||||||
const canvas = <HTMLCanvasElement>document.getElementById('renderer');
|
} = yield select(getState);
|
||||||
|
const canvas = <HTMLCanvasElement>document.getElementById("renderer");
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext("2d");
|
||||||
const image = yield imageFetcher(data);
|
const image = yield imageFetcher(data);
|
||||||
|
|
||||||
ctx.drawImage(image, -x, -y);
|
ctx.drawImage(image, -x, -y);
|
||||||
|
|
||||||
if (logo && LOGOS[logo][1]) {
|
if (logo && LOGOS[logo][1]) {
|
||||||
const logoImage = yield imageFetcher(LOGOS[logo][1]);
|
const logoImage = yield imageFetcher(LOGOS[logo][1]);
|
||||||
ctx.drawImage(logoImage, width - logoImage.width, height - logoImage.height);
|
ctx.drawImage(
|
||||||
|
logoImage,
|
||||||
|
width - logoImage.width,
|
||||||
|
height - logoImage.height
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield canvas.toDataURL('image/jpeg');
|
return yield canvas.toDataURL("image/jpeg");
|
||||||
}
|
}
|
||||||
|
|
||||||
function* cropAShotSaga(params) {
|
function* cropAShotSaga(params) {
|
||||||
const { title, address } = yield select(getState);
|
const { title, address } = yield select(getState);
|
||||||
yield call(getCropData, params);
|
yield call(getCropData, params);
|
||||||
const canvas = document.getElementById('renderer') as HTMLCanvasElement;
|
const canvas = document.getElementById("renderer") as HTMLCanvasElement;
|
||||||
|
|
||||||
downloadCanvas(canvas, (title || address).replace(/\./ig, ' '));
|
downloadCanvas(canvas, (title || address).replace(/\./gi, " "));
|
||||||
|
|
||||||
return yield put(hideRenderer());
|
return yield put(hideRenderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
function* changeProviderSaga({ provider }: ReturnType<typeof ActionCreators.changeProvider>) {
|
function* changeProviderSaga({
|
||||||
|
provider
|
||||||
|
}: ReturnType<typeof ActionCreators.changeProvider>) {
|
||||||
const { provider: current_provider } = yield select(getState);
|
const { provider: current_provider } = yield select(getState);
|
||||||
|
|
||||||
yield put(setProvider(provider));
|
yield put(setProvider(provider));
|
||||||
|
@ -435,8 +527,15 @@ function* changeProviderSaga({ provider }: ReturnType<typeof ActionCreators.chan
|
||||||
return put(setMode(MODES.NONE));
|
return put(setMode(MODES.NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* locationChangeSaga({ location }: ReturnType<typeof ActionCreators.locationChanged>) {
|
function* locationChangeSaga({
|
||||||
const { address, ready, user: { id, random_url }, is_public } = yield select(getState);
|
location
|
||||||
|
}: ReturnType<typeof ActionCreators.locationChanged>) {
|
||||||
|
const {
|
||||||
|
address,
|
||||||
|
ready,
|
||||||
|
user: { id, random_url },
|
||||||
|
is_public
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
if (!ready) return;
|
if (!ready) return;
|
||||||
|
|
||||||
|
@ -445,16 +544,16 @@ function* locationChangeSaga({ location }: ReturnType<typeof ActionCreators.loca
|
||||||
if (address !== path) {
|
if (address !== path) {
|
||||||
const map = yield call(loadMapSaga, path);
|
const map = yield call(loadMapSaga, path);
|
||||||
|
|
||||||
if (map && map.owner && mode === 'edit' && map.owner.id !== id) {
|
if (map && map.route && map.route.owner && mode === "edit" && map.route.owner !== id) {
|
||||||
return yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
return yield call(replaceAddressIfItsBusy, map.random_url, map.address);
|
||||||
}
|
}
|
||||||
} else if (mode === 'edit' && editor.owner.id !== id) {
|
} else if (mode === "edit" && editor.owner !== id) {
|
||||||
return yield call(replaceAddressIfItsBusy, random_url, address);
|
return yield call(replaceAddressIfItsBusy, random_url, address);
|
||||||
} else {
|
} else {
|
||||||
yield put(setAddressOrigin(''));
|
yield put(setAddressOrigin(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode !== 'edit') {
|
if (mode !== "edit") {
|
||||||
yield put(setEditing(false));
|
yield put(setEditing(false));
|
||||||
editor.stopEditing();
|
editor.stopEditing();
|
||||||
} else {
|
} else {
|
||||||
|
@ -463,27 +562,38 @@ function* locationChangeSaga({ location }: ReturnType<typeof ActionCreators.loca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* gotVkUserSaga({ user }: ReturnType<typeof ActionCreators.gotVkUser>) {
|
function* gotVkUserSaga({
|
||||||
const data = yield call(checkUserToken, user);
|
user: u
|
||||||
yield put(setUser(data));
|
}: ReturnType<typeof ActionCreators.gotVkUser>) {
|
||||||
|
const {
|
||||||
|
data: { user, random_url }
|
||||||
|
}: Unwrap<typeof checkUserToken> = yield call(checkUserToken, u);
|
||||||
|
|
||||||
|
yield put(setUser({ ...user, random_url }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* keyPressedSaga({ key, target }: ReturnType<typeof ActionCreators.keyPressed>): any {
|
function* keyPressedSaga({
|
||||||
if (
|
key,
|
||||||
target === 'INPUT' ||
|
target
|
||||||
target === 'TEXTAREA'
|
}: ReturnType<typeof ActionCreators.keyPressed>): any {
|
||||||
) {
|
if (target === "INPUT" || target === "TEXTAREA") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'Escape') {
|
if (key === "Escape") {
|
||||||
const { dialog_active, mode, renderer: { renderer_active } } = yield select(getState);
|
const {
|
||||||
|
dialog_active,
|
||||||
|
mode,
|
||||||
|
renderer: { renderer_active }
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
if (renderer_active) return yield put(hideRenderer());
|
if (renderer_active) return yield put(hideRenderer());
|
||||||
if (dialog_active) return yield put(setDialogActive(false));
|
if (dialog_active) return yield put(setDialogActive(false));
|
||||||
if (mode !== MODES.NONE) return yield put(setMode(MODES.NONE));
|
if (mode !== MODES.NONE) return yield put(setMode(MODES.NONE));
|
||||||
} else if (key === 'Delete') {
|
} else if (key === "Delete") {
|
||||||
const { user: { editing } } = yield select();
|
const {
|
||||||
|
user: { editing }
|
||||||
|
} = yield select();
|
||||||
|
|
||||||
if (!editing) return;
|
if (!editing) return;
|
||||||
|
|
||||||
|
@ -494,47 +604,63 @@ function* keyPressedSaga({ key, target }: ReturnType<typeof ActionCreators.keyPr
|
||||||
} else {
|
} else {
|
||||||
yield put(setMode(MODES.TRASH));
|
yield put(setMode(MODES.TRASH));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* searchGetRoutes() {
|
function* searchGetRoutes() {
|
||||||
const { id, token } = yield select(getUser);
|
const { id, token } = yield select(getUser);
|
||||||
|
|
||||||
const { routes: { step, shift, filter: { title, distance, tab } } } = yield select(getState);
|
const {
|
||||||
|
routes: {
|
||||||
|
step,
|
||||||
|
shift,
|
||||||
|
filter: { title, distance, tab }
|
||||||
|
}
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
return yield call(getRouteList, {
|
const result: Unwrap<typeof getRouteList> = yield getRouteList({
|
||||||
id,
|
|
||||||
token,
|
token,
|
||||||
title,
|
search: title,
|
||||||
distance,
|
min: distance[0],
|
||||||
|
max: distance[1],
|
||||||
step,
|
step,
|
||||||
shift,
|
shift,
|
||||||
author: tab === 'mine' ? id : '',
|
tab
|
||||||
starred: tab === 'starred' ? 1 : 0,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* searchSetSagaWorker() {
|
function* searchSetSagaWorker() {
|
||||||
const { routes: { filter } } = yield select(getState);
|
const {
|
||||||
|
routes: { filter }
|
||||||
|
}: ReturnType<typeof getState> = yield select(getState);
|
||||||
|
|
||||||
const { list, min, max, limit, shift, step } = yield call(searchGetRoutes);
|
const {
|
||||||
|
data: {
|
||||||
|
routes,
|
||||||
|
limits: { min, max, count: limit },
|
||||||
|
filter: { shift, step }
|
||||||
|
}
|
||||||
|
}: Unwrap<typeof getRouteList> = yield call(searchGetRoutes);
|
||||||
|
|
||||||
yield put(searchPutRoutes({ list, min, max, limit, shift, step }));
|
yield put(searchPutRoutes({ list: routes, min, max, limit, shift, step }));
|
||||||
|
|
||||||
// change distange range if needed and load additional data
|
// change distange range if needed and load additional data
|
||||||
if (
|
if (
|
||||||
(filter.min > min && filter.distance[0] <= filter.min) ||
|
(filter.min > min && filter.distance[0] <= filter.min) ||
|
||||||
(filter.max < max && filter.distance[1] >= filter.max)
|
(filter.max < max && filter.distance[1] >= filter.max)
|
||||||
) {
|
) {
|
||||||
yield put(searchChangeDistance([
|
yield put(
|
||||||
(filter.min > min && filter.distance[0] <= filter.min)
|
searchChangeDistance([
|
||||||
? min
|
filter.min > min && filter.distance[0] <= filter.min
|
||||||
: filter.distance[0],
|
? min
|
||||||
(filter.max < max && filter.distance[1] >= filter.max)
|
: filter.distance[0],
|
||||||
? max
|
filter.max < max && filter.distance[1] >= filter.max
|
||||||
: filter.distance[1],
|
? max
|
||||||
]));
|
: filter.distance[1]
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield put(searchSetLoading(false));
|
return yield put(searchSetLoading(false));
|
||||||
|
@ -547,14 +673,22 @@ function* searchSetSaga() {
|
||||||
yield call(searchSetSagaWorker);
|
yield call(searchSetSagaWorker);
|
||||||
}
|
}
|
||||||
|
|
||||||
function* openMapDialogSaga({ tab }: ReturnType<typeof ActionCreators.openMapDialog>) {
|
function* openMapDialogSaga({
|
||||||
const { dialog_active, routes: { filter: { tab: current } } } = yield select(getState);
|
tab
|
||||||
|
}: ReturnType<typeof ActionCreators.openMapDialog>) {
|
||||||
|
const {
|
||||||
|
dialog_active,
|
||||||
|
routes: {
|
||||||
|
filter: { tab: current }
|
||||||
|
}
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
if (dialog_active && tab === current) {
|
if (dialog_active && tab === current) {
|
||||||
return yield put(setDialogActive(false));
|
return yield put(setDialogActive(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab !== current) { // if tab wasnt changed just update data
|
if (tab !== current) {
|
||||||
|
// if tab wasnt changed just update data
|
||||||
yield put(searchSetTab(tab));
|
yield put(searchSetTab(tab));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,13 +700,18 @@ function* openMapDialogSaga({ tab }: ReturnType<typeof ActionCreators.openMapDia
|
||||||
|
|
||||||
function* searchSetTabSaga() {
|
function* searchSetTabSaga() {
|
||||||
yield put(searchChangeDistance([0, 10000]));
|
yield put(searchChangeDistance([0, 10000]));
|
||||||
yield put(searchPutRoutes({ list: [], min: 0, max: 10000, step: 20, shift: 0 }));
|
yield put(
|
||||||
|
searchPutRoutes({ list: [], min: 0, max: 10000, step: 20, shift: 0 })
|
||||||
|
);
|
||||||
|
|
||||||
yield put(searchSetTitle(''));
|
yield put(searchSetTitle(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setSaveSuccessSaga({
|
function* setSaveSuccessSaga({
|
||||||
address, title, is_public, description,
|
address,
|
||||||
|
title,
|
||||||
|
is_public,
|
||||||
|
description
|
||||||
}: ReturnType<typeof ActionCreators.setSaveSuccess>) {
|
}: ReturnType<typeof ActionCreators.setSaveSuccess>) {
|
||||||
const { id } = yield select(getUser);
|
const { id } = yield select(getUser);
|
||||||
const { dialog_active } = yield select(getState);
|
const { dialog_active } = yield select(getState);
|
||||||
|
@ -585,7 +724,7 @@ function* setSaveSuccessSaga({
|
||||||
yield put(setDescription(description));
|
yield put(setDescription(description));
|
||||||
yield put(setChanged(false));
|
yield put(setChanged(false));
|
||||||
|
|
||||||
yield editor.owner = { id };
|
editor.owner = id;
|
||||||
|
|
||||||
if (dialog_active) {
|
if (dialog_active) {
|
||||||
yield call(searchSetSagaWorker);
|
yield call(searchSetSagaWorker);
|
||||||
|
@ -594,7 +733,7 @@ function* setSaveSuccessSaga({
|
||||||
return yield editor.setInitialData();
|
return yield editor.setInitialData();
|
||||||
}
|
}
|
||||||
|
|
||||||
function* userLogoutSaga():SagaIterator {
|
function* userLogoutSaga(): SagaIterator {
|
||||||
yield put(setUser(DEFAULT_USER));
|
yield put(setUser(DEFAULT_USER));
|
||||||
yield call(generateGuestSaga);
|
yield call(generateGuestSaga);
|
||||||
}
|
}
|
||||||
|
@ -607,8 +746,12 @@ function* setUserSaga() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* setTitleSaga({ title }: ReturnType<typeof ActionCreators.setTitle>):SagaIterator {
|
function* setTitleSaga({
|
||||||
if (title) { document.title = `${title} | Редактор маршрутов`; }
|
title
|
||||||
|
}: ReturnType<typeof ActionCreators.setTitle>): SagaIterator {
|
||||||
|
if (title) {
|
||||||
|
document.title = `${title} | Редактор маршрутов`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* getGPXTrackSaga(): SagaIterator {
|
function* getGPXTrackSaga(): SagaIterator {
|
||||||
|
@ -617,13 +760,15 @@ function* getGPXTrackSaga(): SagaIterator {
|
||||||
|
|
||||||
if (!route || route.length <= 0) return;
|
if (!route || route.length <= 0) return;
|
||||||
|
|
||||||
const track = getGPXString({ route, stickers, title: (title || address) });
|
const track = getGPXString({ route, stickers, title: title || address });
|
||||||
|
|
||||||
return downloadGPXTrack({ track, title });
|
return downloadGPXTrack({ track, title });
|
||||||
}
|
}
|
||||||
|
|
||||||
function* mapsLoadMoreSaga() {
|
function* mapsLoadMoreSaga() {
|
||||||
const { routes: { limit, list, shift, step, loading, filter } } = yield select(getState);
|
const {
|
||||||
|
routes: { limit, list, shift, step, loading, filter }
|
||||||
|
} = yield select(getState);
|
||||||
|
|
||||||
if (loading || list.length >= limit || limit === 0) return;
|
if (loading || list.length >= limit || limit === 0) return;
|
||||||
|
|
||||||
|
@ -638,73 +783,109 @@ function* mapsLoadMoreSaga() {
|
||||||
(filter.min > result.min && filter.distance[0] <= filter.min) ||
|
(filter.min > result.min && filter.distance[0] <= filter.min) ||
|
||||||
(filter.max < result.max && filter.distance[1] >= filter.max)
|
(filter.max < result.max && filter.distance[1] >= filter.max)
|
||||||
) {
|
) {
|
||||||
yield put(searchChangeDistance([
|
yield put(
|
||||||
(filter.min > result.min && filter.distance[0] <= filter.min)
|
searchChangeDistance([
|
||||||
? result.min
|
filter.min > result.min && filter.distance[0] <= filter.min
|
||||||
: filter.distance[0],
|
? result.min
|
||||||
(filter.max < result.max && filter.distance[1] >= filter.max)
|
: filter.distance[0],
|
||||||
? result.max
|
filter.max < result.max && filter.distance[1] >= filter.max
|
||||||
: filter.distance[1],
|
? result.max
|
||||||
]));
|
: filter.distance[1]
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(searchPutRoutes({ ...result, list: [...list, ...result.list] }));
|
yield put(searchPutRoutes({ ...result, list: [...list, ...result.list] }));
|
||||||
yield put(searchSetLoading(false));
|
yield put(searchSetLoading(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
function* dropRouteSaga({ _id }: ReturnType<typeof ActionCreators.dropRoute>): SagaIterator {
|
function* dropRouteSaga({
|
||||||
const { id, token } = yield select(getUser);
|
address
|
||||||
|
}: ReturnType<typeof ActionCreators.dropRoute>): SagaIterator {
|
||||||
|
const { token } = yield select(getUser);
|
||||||
const {
|
const {
|
||||||
routes: { list, step, shift, limit, filter: { min, max } }
|
routes: {
|
||||||
|
list,
|
||||||
|
step,
|
||||||
|
shift,
|
||||||
|
limit,
|
||||||
|
filter: { min, max }
|
||||||
|
}
|
||||||
} = yield select(getState);
|
} = yield select(getState);
|
||||||
|
|
||||||
const index = list.findIndex(el => el._id === _id);
|
const index = list.findIndex(el => el.address === address);
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
yield put(searchPutRoutes({
|
yield put(
|
||||||
list: list.filter(el => el._id !== _id),
|
searchPutRoutes({
|
||||||
min,
|
list: list.filter(el => el.address !== address),
|
||||||
max,
|
min,
|
||||||
step,
|
max,
|
||||||
shift: (shift > 0) ? shift - 1 : 0,
|
step,
|
||||||
limit: (limit > 0) ? limit - 1 : limit,
|
shift: shift > 0 ? shift - 1 : 0,
|
||||||
}));
|
limit: limit > 0 ? limit - 1 : limit
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield call(dropRoute, { address: _id, id, token });
|
return yield call(dropRoute, { address, token });
|
||||||
}
|
}
|
||||||
|
|
||||||
function* modifyRouteSaga({ _id, title, is_public }: ReturnType<typeof ActionCreators.modifyRoute>): SagaIterator {
|
function* modifyRouteSaga({
|
||||||
const { id, token } = yield select(getUser);
|
address,
|
||||||
|
title,
|
||||||
|
is_public
|
||||||
|
}: ReturnType<typeof ActionCreators.modifyRoute>): SagaIterator {
|
||||||
|
const { token } = yield select(getUser);
|
||||||
const {
|
const {
|
||||||
routes: { list, step, shift, limit, filter: { min, max } }
|
routes: {
|
||||||
} = yield select(getState);
|
list,
|
||||||
|
step,
|
||||||
|
shift,
|
||||||
|
limit,
|
||||||
|
filter: { min, max }
|
||||||
|
}
|
||||||
|
}: ReturnType<typeof getState> = yield select(getState);
|
||||||
|
|
||||||
const index = list.findIndex(el => el._id === _id);
|
const index = list.findIndex(el => el.address === address);
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
yield put(searchPutRoutes({
|
yield put(
|
||||||
list: list.map(el => (el._id !== _id ? el : { ...el, title, is_public })),
|
searchPutRoutes({
|
||||||
min,
|
list: list.map(el =>
|
||||||
max,
|
el.address !== address ? el : { ...el, title, is_public }
|
||||||
step,
|
),
|
||||||
shift: (shift > 0) ? shift - 1 : 0,
|
min,
|
||||||
limit: (limit > 0) ? limit - 1 : limit,
|
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 });
|
return yield call(modifyRoute, { address, token, title, is_public });
|
||||||
}
|
}
|
||||||
|
|
||||||
function* toggleRouteStarredSaga({ _id }: ReturnType<typeof ActionCreators.toggleRouteStarred>) {
|
function* toggleRouteStarredSaga({
|
||||||
const { routes: { list } } = yield select(getState);
|
address
|
||||||
const route = list.find(el => el._id === _id);
|
}: ReturnType<typeof ActionCreators.toggleRouteStarred>) {
|
||||||
|
const {
|
||||||
|
routes: { list }
|
||||||
|
}: IState["user"] = yield select(getState);
|
||||||
|
|
||||||
|
const route = list.find(el => el.address === address);
|
||||||
const { id, token } = yield select(getUser);
|
const { id, token } = yield select(getUser);
|
||||||
|
|
||||||
yield put(setRouteStarred(_id, !route.is_starred));
|
yield put(setRouteStarred(address, !route.is_starred));
|
||||||
const result = yield sendRouteStarred({ id, token, _id, is_starred: !route.is_starred });
|
const result = yield sendRouteStarred({
|
||||||
|
id,
|
||||||
|
token,
|
||||||
|
address,
|
||||||
|
is_starred: !route.is_starred
|
||||||
|
});
|
||||||
|
|
||||||
if (!result) return yield put(setRouteStarred(_id, route.is_starred));
|
if (!result) return yield put(setRouteStarred(address, route.is_starred));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* userSaga() {
|
export function* userSaga() {
|
||||||
|
@ -720,12 +901,15 @@ export function* userSaga() {
|
||||||
|
|
||||||
yield takeEvery(ACTIONS.ROUTER_CANCEL, routerCancelSaga);
|
yield takeEvery(ACTIONS.ROUTER_CANCEL, routerCancelSaga);
|
||||||
yield takeEvery(ACTIONS.ROUTER_SUBMIT, routerSubmitSaga);
|
yield takeEvery(ACTIONS.ROUTER_SUBMIT, routerSubmitSaga);
|
||||||
yield takeEvery([
|
yield takeEvery(
|
||||||
ACTIONS.CLEAR_POLY,
|
[
|
||||||
ACTIONS.CLEAR_STICKERS,
|
ACTIONS.CLEAR_POLY,
|
||||||
ACTIONS.CLEAR_ALL,
|
ACTIONS.CLEAR_STICKERS,
|
||||||
ACTIONS.CLEAR_CANCEL,
|
ACTIONS.CLEAR_ALL,
|
||||||
], clearSaga);
|
ACTIONS.CLEAR_CANCEL
|
||||||
|
],
|
||||||
|
clearSaga
|
||||||
|
);
|
||||||
|
|
||||||
yield takeLatest(ACTIONS.SEND_SAVE_REQUEST, sendSaveRequestSaga);
|
yield takeLatest(ACTIONS.SEND_SAVE_REQUEST, sendSaveRequestSaga);
|
||||||
yield takeLatest(ACTIONS.SET_SAVE_SUCCESS, setSaveSuccessSaga);
|
yield takeLatest(ACTIONS.SET_SAVE_SUCCESS, setSaveSuccessSaga);
|
||||||
|
@ -740,10 +924,10 @@ export function* userSaga() {
|
||||||
|
|
||||||
yield takeLatest(ACTIONS.SET_TITLE, setTitleSaga);
|
yield takeLatest(ACTIONS.SET_TITLE, setTitleSaga);
|
||||||
|
|
||||||
yield takeLatest([
|
yield takeLatest(
|
||||||
ACTIONS.SEARCH_SET_TITLE,
|
[ACTIONS.SEARCH_SET_TITLE, ACTIONS.SEARCH_SET_DISTANCE],
|
||||||
ACTIONS.SEARCH_SET_DISTANCE,
|
searchSetSaga
|
||||||
], searchSetSaga);
|
);
|
||||||
|
|
||||||
yield takeLatest(ACTIONS.OPEN_MAP_DIALOG, openMapDialogSaga);
|
yield takeLatest(ACTIONS.OPEN_MAP_DIALOG, openMapDialogSaga);
|
||||||
yield takeLatest(ACTIONS.SEARCH_SET_TAB, searchSetTabSaga);
|
yield takeLatest(ACTIONS.SEARCH_SET_TAB, searchSetTabSaga);
|
||||||
|
|
282
src/utils/api.ts
282
src/utils/api.ts
|
@ -1,126 +1,222 @@
|
||||||
import axios, { AxiosPromise } from 'axios/index';
|
import axios, { AxiosPromise } from "axios/index";
|
||||||
import { API } from '$constants/api';
|
import { API } from "$constants/api";
|
||||||
import { IRootState } from "$redux/user/reducer";
|
import { IRootState, IRouteListItem, IRoute } from "$redux/user/reducer";
|
||||||
import { IUser } from "$constants/auth";
|
import { IUser } from "$constants/auth";
|
||||||
import { ILatLng } from "$modules/Stickers";
|
import { ILatLng } from "$modules/Stickers";
|
||||||
import { IStickerDump } from "$modules/Sticker";
|
import { IStickerDump } from "$modules/Sticker";
|
||||||
import { CLIENT } from '$config/frontend';
|
import { CLIENT } from "$config/frontend";
|
||||||
import { LatLngLiteral } from "leaflet";
|
import { LatLngLiteral } from "leaflet";
|
||||||
|
import {
|
||||||
|
resultMiddleware,
|
||||||
|
errorMiddleware,
|
||||||
|
IResultWithStatus,
|
||||||
|
configWithToken
|
||||||
|
} from "./middleware";
|
||||||
|
|
||||||
const arrayToObject = (array: any[], key: string): {} => array.reduce((obj, el) => ({ ...obj, [el[key]]: el }), {});
|
const arrayToObject = (array: any[], key: string): {} =>
|
||||||
|
array.reduce((obj, el) => ({ ...obj, [el[key]]: el }), {});
|
||||||
interface IPostMap {
|
|
||||||
title: IRootState['title'],
|
|
||||||
address: IRootState['address'],
|
|
||||||
route: Array<ILatLng>,
|
|
||||||
stickers: Array<IStickerDump>,
|
|
||||||
id: IRootState['user']['id'],
|
|
||||||
token: IRootState['user']['token'],
|
|
||||||
force: boolean,
|
|
||||||
logo: IRootState['logo'],
|
|
||||||
distance: IRootState['distance'],
|
|
||||||
provider: IRootState['provider'],
|
|
||||||
is_public: IRootState['is_public'],
|
|
||||||
description: IRootState['description'],
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IGetRouteList {
|
interface IGetRouteList {
|
||||||
title: IRootState['title'],
|
min: number;
|
||||||
distance: IRootState['distance'],
|
max: number;
|
||||||
author: IRootState['routes']['filter']['author'],
|
tab: string;
|
||||||
step: IRootState['routes']['step'],
|
search: string;
|
||||||
shift: IRootState['routes']['step'],
|
step: IRootState["routes"]["step"];
|
||||||
starred: number,
|
shift: IRootState["routes"]["step"];
|
||||||
id: IRootState['user']['id'],
|
token: IRootState["user"]["token"];
|
||||||
token: IRootState['user']['token'],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IGetRouteListResult {
|
interface IGetRouteListResult {
|
||||||
min: IRootState['routes']['filter']['min'],
|
min: IRootState["routes"]["filter"]["min"];
|
||||||
max: IRootState['routes']['filter']['max'],
|
max: IRootState["routes"]["filter"]["max"];
|
||||||
limit: IRootState['routes']['limit'],
|
limit: IRootState["routes"]["limit"];
|
||||||
step: IRootState['routes']['step'],
|
step: IRootState["routes"]["step"];
|
||||||
shift: IRootState['routes']['shift'],
|
shift: IRootState["routes"]["shift"];
|
||||||
list: IRootState['routes']['list'],
|
list: IRootState["routes"]["list"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const checkUserToken = (
|
export const checkUserToken = ({
|
||||||
{ id, token }:
|
|
||||||
{ id: IRootState['user']['id'], token: IRootState['user']['token']}
|
|
||||||
):AxiosPromise<IUser> => axios.get(API.CHECK_TOKEN, {
|
|
||||||
params: { id, token }
|
|
||||||
}).then(result => (result && result.data && {
|
|
||||||
...result.data,
|
|
||||||
id,
|
id,
|
||||||
token,
|
token
|
||||||
routes: (result.data.routes && result.data.routes.length > 0 && arrayToObject(result.data.routes, '_id')) || {},
|
}: {
|
||||||
})).catch(() => null);
|
id: IRootState["user"]["id"];
|
||||||
|
token: IRootState["user"]["token"];
|
||||||
|
}): Promise<IResultWithStatus<{
|
||||||
|
user: IUser;
|
||||||
|
random_url: string;
|
||||||
|
routes: IRouteListItem[];
|
||||||
|
}>> =>
|
||||||
|
axios
|
||||||
|
.get(API.CHECK_TOKEN, {
|
||||||
|
params: { id, token }
|
||||||
|
})
|
||||||
|
.then(resultMiddleware)
|
||||||
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
export const getGuestToken = ():AxiosPromise<IUser> => axios.get(API.GET_GUEST).then(result => (result && result.data));
|
export const getGuestToken = (): Promise<IResultWithStatus<{
|
||||||
|
user: IUser;
|
||||||
|
random_url: string;
|
||||||
|
}>> =>
|
||||||
|
axios
|
||||||
|
.get(API.GET_GUEST)
|
||||||
|
.then(resultMiddleware)
|
||||||
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
export const getStoredMap = (
|
export const getStoredMap = ({
|
||||||
{ name }: { name: IRootState['address'] }
|
name
|
||||||
) => axios.get(API.GET_MAP, {
|
}: {
|
||||||
params: { name }
|
name: IRootState["address"];
|
||||||
})
|
}): Promise<IResultWithStatus<{
|
||||||
.then(result => (
|
route: IRoute;
|
||||||
result && result.data && result.data.success && result.data
|
error?: string;
|
||||||
));
|
random_url: string;
|
||||||
|
}>> =>
|
||||||
|
axios
|
||||||
|
.get(API.GET_MAP, {
|
||||||
|
params: { name }
|
||||||
|
})
|
||||||
|
.then(resultMiddleware)
|
||||||
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
export const postMap = ({
|
export const postMap = ({
|
||||||
title, address, route, stickers, id, token, force, logo, distance, provider, is_public, description,
|
|
||||||
}: IPostMap) => axios.post(API.POST_MAP, {
|
|
||||||
title,
|
title,
|
||||||
address,
|
address,
|
||||||
route,
|
route,
|
||||||
stickers,
|
stickers,
|
||||||
id,
|
|
||||||
token,
|
|
||||||
force,
|
force,
|
||||||
logo,
|
logo,
|
||||||
distance,
|
distance,
|
||||||
provider,
|
provider,
|
||||||
is_public,
|
is_public,
|
||||||
description,
|
description,
|
||||||
}).then(result => (result && result.data && result.data));
|
token
|
||||||
|
}: Partial<IRoute> & { force: boolean; token: string }) =>
|
||||||
|
axios
|
||||||
|
.post(
|
||||||
|
API.POST_MAP,
|
||||||
|
{
|
||||||
|
title,
|
||||||
|
address,
|
||||||
|
route,
|
||||||
|
stickers,
|
||||||
|
force,
|
||||||
|
logo,
|
||||||
|
distance,
|
||||||
|
provider,
|
||||||
|
is_public,
|
||||||
|
description
|
||||||
|
},
|
||||||
|
configWithToken(token)
|
||||||
|
)
|
||||||
|
.then(result => result && result.data && result.data);
|
||||||
|
|
||||||
export const checkIframeToken = (
|
export const checkIframeToken = ({
|
||||||
{ viewer_id, auth_key }:
|
viewer_id,
|
||||||
{ viewer_id: string, auth_key: string }
|
auth_key
|
||||||
) => axios.get(API.IFRAME_LOGIN_VK, {
|
}: {
|
||||||
params: { viewer_id, auth_key }
|
viewer_id: string;
|
||||||
}).then(result => (result && result.data && result.data.success && result.data.user)).catch(() => (false));
|
auth_key: string;
|
||||||
|
}) =>
|
||||||
|
axios
|
||||||
|
.get(API.IFRAME_LOGIN_VK, {
|
||||||
|
params: { viewer_id, auth_key }
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
result => result && result.data && result.data.success && result.data.user
|
||||||
|
)
|
||||||
|
.catch(() => false);
|
||||||
|
|
||||||
export const getRouteList = ({
|
export const getRouteList = ({
|
||||||
title, distance, author, starred, id, token, step, shift,
|
search,
|
||||||
}: IGetRouteList): AxiosPromise<IGetRouteListResult> => axios.get(API.GET_ROUTE_LIST, {
|
min,
|
||||||
params: {
|
max,
|
||||||
title, distance, author, starred, id, token, step, shift
|
tab,
|
||||||
}
|
token,
|
||||||
}).then(result => (result && result.data && result.data.success && result.data))
|
step,
|
||||||
.catch(() => ({ list: [], min: 0, max: 0, limit: 0, step: 20, shift: 20 }));
|
shift
|
||||||
|
}: IGetRouteList): Promise<IResultWithStatus<{
|
||||||
|
routes: IRoute[];
|
||||||
|
limits: {
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
filter: {
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
shift: number;
|
||||||
|
step: number;
|
||||||
|
};
|
||||||
|
}>> =>
|
||||||
|
axios
|
||||||
|
.get(
|
||||||
|
API.GET_ROUTE_LIST,
|
||||||
|
configWithToken(token, {
|
||||||
|
params: {
|
||||||
|
search,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
tab,
|
||||||
|
token,
|
||||||
|
step,
|
||||||
|
shift
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(resultMiddleware)
|
||||||
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
export const checkOSRMService = (bounds: LatLngLiteral[]): Promise<boolean> => (
|
export const checkOSRMService = (bounds: LatLngLiteral[]): Promise<boolean> =>
|
||||||
CLIENT && CLIENT.OSRM_URL && axios.get(CLIENT.OSRM_TEST_URL(bounds)).then(() => true).catch(() => false)
|
CLIENT &&
|
||||||
);
|
CLIENT.OSRM_URL &&
|
||||||
|
axios
|
||||||
export const dropRoute = ({ address, id, token }: { address: string, id: string, token: string }): AxiosPromise<any> => (
|
.get(CLIENT.OSRM_TEST_URL(bounds))
|
||||||
axios.delete(API.DROP_ROUTE, { data: { address, id, token } })
|
|
||||||
);
|
|
||||||
|
|
||||||
export const modifyRoute = (
|
|
||||||
{ address, id, token, title, is_public }:
|
|
||||||
{ address: string, id: string, token: string, title: string, is_public: boolean }
|
|
||||||
): AxiosPromise<any> => (
|
|
||||||
axios.patch(API.DROP_ROUTE, { address, id, token, title, is_public })
|
|
||||||
);
|
|
||||||
|
|
||||||
export const sendRouteStarred = (
|
|
||||||
{ id, token, _id, is_starred }:
|
|
||||||
{ id: string, token: string, _id: string, is_starred: boolean }
|
|
||||||
): Promise<boolean> => (
|
|
||||||
axios.post(API.SET_STARRED, { id, token, address: _id, is_starred })
|
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch(() => true)
|
.catch(() => false);
|
||||||
);
|
|
||||||
|
|
||||||
|
export const dropRoute = ({
|
||||||
|
address,
|
||||||
|
token
|
||||||
|
}: {
|
||||||
|
address: string;
|
||||||
|
token: string;
|
||||||
|
}): Promise<any> =>
|
||||||
|
axios
|
||||||
|
.delete(API.DROP_ROUTE, configWithToken(token, { data: { address } }))
|
||||||
|
.then(resultMiddleware)
|
||||||
|
.catch(errorMiddleware);
|
||||||
|
|
||||||
|
export const modifyRoute = ({
|
||||||
|
address,
|
||||||
|
token,
|
||||||
|
title,
|
||||||
|
is_public
|
||||||
|
}: {
|
||||||
|
address: string;
|
||||||
|
token: string;
|
||||||
|
title: string;
|
||||||
|
is_public: boolean;
|
||||||
|
}): Promise<IResultWithStatus<{
|
||||||
|
route: IRoute;
|
||||||
|
}>> =>
|
||||||
|
axios.patch(
|
||||||
|
API.MODIFY_ROUTE,
|
||||||
|
{ address, token, is_public, title },
|
||||||
|
configWithToken(token)
|
||||||
|
);
|
||||||
|
|
||||||
|
export const sendRouteStarred = ({
|
||||||
|
id,
|
||||||
|
token,
|
||||||
|
address,
|
||||||
|
is_starred
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
token: string;
|
||||||
|
address: string;
|
||||||
|
is_starred: boolean;
|
||||||
|
}): Promise<IResultWithStatus<{ route: IRoute }>> =>
|
||||||
|
axios
|
||||||
|
.post(API.SET_STARRED, { id, token, address, is_starred })
|
||||||
|
.then(resultMiddleware)
|
||||||
|
.catch(errorMiddleware);
|
||||||
|
|
50
src/utils/middleware.ts
Normal file
50
src/utils/middleware.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import { AxiosRequestConfig } from "axios";
|
||||||
|
|
||||||
|
export type Unwrap<T> = T extends (...args: any[]) => Promise<infer U> ? U : T;
|
||||||
|
|
||||||
|
export interface IApiErrorResult {
|
||||||
|
detail?: string;
|
||||||
|
code?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IResultWithStatus<T> {
|
||||||
|
status: any;
|
||||||
|
data?: Partial<T> & IApiErrorResult;
|
||||||
|
error?: string;
|
||||||
|
debug?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HTTP_RESPONSES = {
|
||||||
|
SUCCESS: 200,
|
||||||
|
CREATED: 201,
|
||||||
|
CONNECTION_REFUSED: 408,
|
||||||
|
BAD_REQUEST: 400,
|
||||||
|
UNAUTHORIZED: 401,
|
||||||
|
NOT_FOUND: 404,
|
||||||
|
TOO_MANY_REQUESTS: 429,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resultMiddleware = (<T extends {}>({
|
||||||
|
status,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
status: number;
|
||||||
|
data: T;
|
||||||
|
}): { status: number; data: T } => ({ status, data }));
|
||||||
|
|
||||||
|
export const errorMiddleware = <T extends any>(debug): IResultWithStatus<T> => (debug && debug.response
|
||||||
|
? debug.response
|
||||||
|
: {
|
||||||
|
status: HTTP_RESPONSES.CONNECTION_REFUSED,
|
||||||
|
data: {},
|
||||||
|
debug,
|
||||||
|
error: 'Ошибка сети',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const configWithToken = (
|
||||||
|
token: string,
|
||||||
|
config: AxiosRequestConfig = {},
|
||||||
|
): AxiosRequestConfig => ({
|
||||||
|
...config,
|
||||||
|
headers: { ...(config.headers || {}), Authorization: `${token}` },
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue