moved components to TypeScript

This commit is contained in:
muerwre 2019-02-12 16:20:31 +07:00
parent 85b8860862
commit 0a01c91271
54 changed files with 2771 additions and 5134 deletions

4
custom.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
declare module "*.svg" {
const content: any;
export default content;
}

7020
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -45,16 +45,16 @@
"style-loader": "^0.21.0", "style-loader": "^0.21.0",
"uglifyjs-webpack-plugin": "^1.3.0", "uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^4.6.0", "webpack": "^4.6.0",
"webpack-cli": "^2.0.15", "webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.11", "webpack-dev-server": "^3.1.14",
"ts-node": "^8.0.1", "ts-node": "^8.0.1",
"typescript": "^3.2.4" "typescript": "^3.2.4"
}, },
"dependencies": { "dependencies": {
"@types/classnames": "^2.2.7", "@types/classnames": "^2.2.7",
"@types/leaflet": "^1.4.1",
"@types/node": "^11.9.0", "@types/node": "^11.9.0",
"@types/react": "^16.7.20", "@types/react": "16.8.1",
"@types/react-dom": "^16.0.11",
"axios": "^0.18.0", "axios": "^0.18.0",
"babel-runtime": "^6.26.0", "babel-runtime": "^6.26.0",
"bluebird": "^3.5.3", "bluebird": "^3.5.3",
@ -84,8 +84,8 @@
"pug": "2.0.0-beta11", "pug": "2.0.0-beta11",
"raleway-cyrillic": "^4.0.2", "raleway-cyrillic": "^4.0.2",
"rc-slider": "8.5.0", "rc-slider": "8.5.0",
"react": "^16.3.2", "react": "16.8.1",
"react-dom": "^16.3.2", "react-dom": "16.8.1",
"react-hot-loader": "^4.1.1", "react-hot-loader": "^4.1.1",
"react-infinite-scroller": "^1.2.2", "react-infinite-scroller": "^1.2.2",
"react-rangeslider": "^2.2.0", "react-rangeslider": "^2.2.0",

View file

@ -1,16 +1,16 @@
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { MODES } from '$constants/modes'; import { IModes, MODES } from '$constants/modes';
import { STICKERS } from '$constants/stickers'; import { IStickerPack, STICKERS } from '$constants/stickers';
import { StickerIcon } from '$components/StickerIcon'; import { StickerIcon } from '$components/StickerIcon';
type Props = { interface Props {
mode: String, mode: keyof IModes,
sticker: String, sticker: string,
set: String, set: keyof IStickerPack,
} }
export class Cursor extends React.PureComponent<Props, void> { export class Cursor extends React.PureComponent<Props, {}> {
componentDidMount() { componentDidMount() {
window.addEventListener('mousemove', this.moveCursor); window.addEventListener('mousemove', this.moveCursor);
} }
@ -23,6 +23,8 @@ export class Cursor extends React.PureComponent<Props, void> {
this.cursor.style.transform = `translate3d(${clientX}px, ${clientY}px, 0)`; this.cursor.style.transform = `translate3d(${clientX}px, ${clientY}px, 0)`;
}; };
cursor: HTMLElement = null;
render() { render() {
const { mode, set, sticker } = this.props; const { mode, set, sticker } = this.props;
const activeSticker = (sticker && set && STICKERS[set] && STICKERS[set].layers[sticker]); const activeSticker = (sticker && set && STICKERS[set] && STICKERS[set].layers[sticker]);

View file

@ -1,4 +1,4 @@
import React from 'react'; import * as React from 'react';
export const Fills = () => ( export const Fills = () => (
<svg> <svg>
@ -24,7 +24,7 @@ export const Fills = () => (
orient="auto" orient="auto"
> >
<path d="M0,5a5,5 0 1,0 10,0a5,5 0 1,0 -10,0" fill="#ff3344" /> <path d="M0,5a5,5 0 1,0 10,0a5,5 0 1,0 -10,0" fill="#ff3344" />
<path d="M2.5 2L7.5 5L2.5 8z" fill="#ffffff" fillRule="even-odd" /> <path d="M2.5 2L7.5 5L2.5 8z" fill="#ffffff" fillRule="evenodd" />
</marker> </marker>
<marker <marker
@ -36,7 +36,7 @@ export const Fills = () => (
markerHeight="5" markerHeight="5"
orient="auto" orient="auto"
> >
<path d="m 2.625,3.375 h 7.5 L 10.28125,1.609375 13.5,4.25 10.484375,6.921875 10.171875,5.15625 2.625,5.125 Z" fill="#ff3344" fillRule="even-odd" /> <path d="m 2.625,3.375 h 7.5 L 10.28125,1.609375 13.5,4.25 10.484375,6.921875 10.171875,5.15625 2.625,5.125 Z" fill="#ff3344" fillRule="evenodd" />
</marker> </marker>
</defs> </defs>
<image xlinkHref={require('$sprites/stickers/stickers-base.svg')} width={0} height={0} /> <image xlinkHref={require('$sprites/stickers/stickers-base.svg')} width={0} height={0} />

View file

@ -1,8 +1,7 @@
import React from 'react'; import * as React from 'react';
import { Scrollbars } from 'tt-react-custom-scrollbars'; import { Scrollbars } from 'tt-react-custom-scrollbars';
export const Scroll = props => ( export const Scroll = props => (
// renderTrackVertical={props => <div {...props} className="track-vertical"/>}
<Scrollbars <Scrollbars
renderTrackHorizontal={prop => <div {...prop} className="track-horizontal" />} renderTrackHorizontal={prop => <div {...prop} className="track-horizontal" />}
renderTrackVertical={prop => <div {...prop} className="track-vertical" />} renderTrackVertical={prop => <div {...prop} className="track-vertical" />}

View file

@ -1,11 +1,16 @@
import React from 'react'; import * as React from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
type State = { interface Props {
text: String, value: string;
onChange: EventHandlerNonNull;
} }
export class StickerDesc extends React.PureComponent<void, State> { type State = {
text: String;
}
export class StickerDesc extends React.PureComponent<Props, State> {
state = { state = {
text: this.props.value, text: this.props.value,
}; };

View file

@ -1,9 +1,9 @@
import React from 'react'; import * as React from 'react';
import { STICKERS } from '$constants/stickers'; import { ISticker, STICKERS } from '$constants/stickers';
type Props = { type Props = {
set: String, set: string,
sticker: String, sticker: string,
}; };
export const StickerIcon = ({ set, sticker }: Props) => ( export const StickerIcon = ({ set, sticker }: Props) => (

View file

@ -1,10 +1,10 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
type Props = { type Props = {
active: Boolean, active: boolean,
onPress: Function, onPress?: () => void,
} }
export const Switch = ({ active, onPress = () => {} }: Props) => ( export const Switch = ({ active, onPress = () => {} }: Props) => (
<div <div

View file

@ -1,22 +1,29 @@
import React from 'react'; import * as React from 'react';
import { marker } from 'leaflet'; import { marker } from 'leaflet';
import { DomMarker } from '$utils/DomMarker'; import { DomMarker } from '$utils/DomMarker';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { editor } from '$modules/Editor'; import { editor } from '$modules/Editor';
export class UserLocation extends React.Component { interface Props {
}
export class UserLocation extends React.Component<Props, {}> {
constructor(props) { constructor(props) {
super(props); super(props);
const element = document.createElement('div'); const element = document.createElement('div');
this.icon = new DomMarker({ element, className: 'location-marker' }); this.icon = new DomMarker({ element, className: 'location-marker' });
this.mark = null;
this.map = editor.map.map; this.map = editor.map.map;
this.location = []; this.location = [];
} }
icon;
mark = null;
map;
location;
componentDidMount() { componentDidMount() {
this.getUserLocation(this.updateLocationMark); this.getUserLocation(this.updateLocationMark);
} }

View file

@ -1,5 +1,5 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import { Scroll } from '$components/Scroll'; import { Scroll } from '$components/Scroll';
import { APP_INFO } from '$constants/app_info'; import { APP_INFO } from '$constants/app_info';

View file

@ -1,12 +1,13 @@
import React from 'react'; import * as React from 'react';
import { MODES } from '$constants/modes'; import { MODES } from '$constants/modes';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { setMode, stopEditing } from "$redux/user/actions";
type Props = { type Props = {
stopEditing: Function, stopEditing: typeof stopEditing,
setMode: Function, setMode: typeof setMode,
width: Number, width: number,
}; };
export class CancelDialog extends React.Component<Props, void> { export class CancelDialog extends React.Component<Props, void> {

View file

@ -1,11 +1,12 @@
import React from 'react'; import * as React from 'react';
import { LOGOS } from '$constants/logos'; import { LOGOS } from '$constants/logos';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import classnames from 'classnames'; import classnames from 'classnames';
import { setLogo as setLogoAction } from "$redux/user/actions";
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
logo: String, setLogo: typeof setLogoAction,
setLogo: Function,
} }
export const LogoDialog = ({ logo, setLogo }: Props) => ( export const LogoDialog = ({ logo, setLogo }: Props) => (

View file

@ -1,5 +1,4 @@
// @flow import * as React from 'react';
import React from 'react';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { RouteRow } from '$components/maps/RouteRow'; import { RouteRow } from '$components/maps/RouteRow';
@ -16,34 +15,20 @@ import { Range } from 'rc-slider';
import { TABS } from '$constants/dialogs'; import { TABS } from '$constants/dialogs';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { pushPath } from '$utils/history'; import { pushPath } from '$utils/history';
import { IRootState } from '$redux/user/reducer';
type Props = { interface Props extends IRootState {
ready: Boolean,
routes: {
limit: Number,
loading: Boolean, // <-- maybe delete this
list: Array<Object>,
filter: {
title: String,
author: String,
distance: Array<Number>,
tab: Array<string>,
min: number,
max: number,
},
},
marks: { [x: number]: string }, marks: { [x: number]: string },
editing: Boolean,
routes_sorted: Array<string>, routes_sorted: Array<string>,
searchSetDistance: Function, searchSetDistance: typeof searchSetDistance,
searchSetTitle: Function, searchSetTitle: typeof searchSetTitle,
searchSetTab: Function, searchSetTab: typeof searchSetTab,
setDialogActive: Function, setDialogActive: typeof setDialogActive,
}; }
type State = { interface State {
editing_item: ?string, editing_item: string,
} }
class Component extends React.Component<Props, State> { class Component extends React.Component<Props, State> {
@ -54,13 +39,12 @@ class Component extends React.Component<Props, State> {
startEditing = editing_item => this.setState({ editing_item }); startEditing = editing_item => this.setState({ editing_item });
stopEditing = () => this.setState({ editing_item: null }); stopEditing = () => this.setState({ editing_item: null });
setTitle = ({ target: { value } }) => { setTitle = ({ target: { value } }: { target: { value: string }}): void => {
this.props.searchSetTitle(value); this.props.searchSetTitle(value);
}; };
openRoute = _id => { openRoute = (_id: string): void => {
pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`); pushPath(`/${_id}/${this.props.editing ? 'edit' : ''}`);
// this.props.setDialogActive(false);
}; };
render() { render() {
@ -150,9 +134,9 @@ class Component extends React.Component<Props, State> {
<RouteRow <RouteRow
editing={editing} editing={editing}
{...route} {...route}
openRoute={this.openRoute}
tab={tab} tab={tab}
is_editing={(editing_item === route._id)} is_editing={(editing_item === route._id)}
openRoute={this.openRoute}
startEditing={this.startEditing} startEditing={this.startEditing}
stopEditing={this.stopEditing} stopEditing={this.stopEditing}
key={route._id} key={route._id}

View file

@ -1,12 +1,13 @@
import React from 'react'; import * as React from 'react';
import { PROVIDERS, replaceProviderUrl } from '$constants/providers'; import { PROVIDERS, replaceProviderUrl } from '$constants/providers';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import classnames from 'classnames'; import classnames from 'classnames';
import { changeProvider as changeProviderAction } from "$redux/user/actions";
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
changeProvider: Function, changeProvider: typeof changeProviderAction,
provider: String, }
};
export const ProviderDialog = ({ provider, changeProvider }: Props) => ( export const ProviderDialog = ({ provider, changeProvider }: Props) => (
<div className="control-dialog top right control-dialog-provider"> <div className="control-dialog top right control-dialog-provider">

View file

@ -1,14 +1,19 @@
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import {
routerCancel as routerCancelAction,
routerSubmit as routerSubmitAction,
} from "$redux/user/actions";
type Props = { type Props = {
routerCancel: Function, routerPoints: number,
routerSubmit: Function, width: number,
routerPoints: Number,
width: Number, routerCancel: typeof routerCancelAction,
routerSubmit: typeof routerSubmitAction,
} }
const noPoints = ({ routerCancel }: Props) => ( const noPoints = ({ routerCancel }: { routerCancel: typeof routerCancelAction }) => (
<React.Fragment> <React.Fragment>
<div className="helper router-helper"> <div className="helper router-helper">
<div className="helper__text"> <div className="helper__text">
@ -29,7 +34,7 @@ const noPoints = ({ routerCancel }: Props) => (
</React.Fragment> </React.Fragment>
); );
const firstPoint = ({ routerCancel }: Props) => ( const firstPoint = ({ routerCancel }: { routerCancel: typeof routerCancelAction }) => (
<React.Fragment> <React.Fragment>
<div className="helper router-helper"> <div className="helper router-helper">
<div className="helper__text"> <div className="helper__text">
@ -48,7 +53,12 @@ const firstPoint = ({ routerCancel }: Props) => (
</React.Fragment> </React.Fragment>
); );
const draggablePoints = ({ routerCancel, routerSubmit }: Props) => ( const draggablePoints = ({
routerCancel, routerSubmit
}: {
routerCancel: typeof routerCancelAction,
routerSubmit: typeof routerSubmitAction,
}) => (
<React.Fragment> <React.Fragment>
<div className="helper"> <div className="helper">
<div className="helper__text success"> <div className="helper__text success">

View file

@ -1,4 +1,4 @@
import React from 'react'; import * as React from 'react';
import { copyToClipboard, getUrlData } from '$utils/history'; import { copyToClipboard, getUrlData } from '$utils/history';
import { toTranslit } from '$utils/format'; import { toTranslit } from '$utils/format';
import { TIPS } from '$constants/tips'; import { TIPS } from '$constants/tips';
@ -7,27 +7,20 @@ import { Icon } from '$components/panels/Icon';
import { Switch } from '$components/Switch'; import { Switch } from '$components/Switch';
import classnames from 'classnames'; import classnames from 'classnames';
import { IRootState } from "$redux/user/reducer";
import { sendSaveRequest, setMode } from "$redux/user/actions";
type Props = { interface Props extends IRootState {
address: String, // initial? width: number,
title: String, // initial? setMode: typeof setMode,
is_public: Boolean, sendSaveRequest: typeof sendSaveRequest,
}
save_error: String, interface State {
save_finished: Boolean, address: string,
save_overwriting: Boolean, title: string,
is_public: boolean,
width: Number, }
setMode: Function,
sendSaveRequest: Function,
};
type State = {
address: String,
title: String,
is_public: Boolean,
};
export class SaveDialog extends React.Component<Props, State> { export class SaveDialog extends React.Component<Props, State> {
constructor(props) { constructor(props) {

View file

@ -1,9 +1,9 @@
import React from 'react'; import * as React from 'react';
type Props = { interface Props {
renderer: { renderer: {
info: String, info: string,
progress: Number, progress: number,
} }
} }

View file

@ -1,12 +1,13 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import { STICKERS } from '$constants/stickers'; import { STICKERS } from '$constants/stickers';
import { setActiveSticker as setActiveStickerAction } from "$redux/user/actions";
type Props = { interface Props {
setActiveSticker: Function, setActiveSticker: typeof setActiveStickerAction,
width: Number, width: number,
}; }
export const StickersDialog = ({ setActiveSticker, width }: Props) => ( export const StickersDialog = ({ setActiveSticker, width }: Props) => (
<div className="control-dialog control-dialog-big" style={{ width }}> <div className="control-dialog control-dialog-big" style={{ width }}>

View file

@ -1,13 +1,13 @@
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
type Props = { type Props = {
clearPoly: Function, clearPoly: () => void,
clearStickers: Function, clearStickers: () => void,
clearAll: Function, clearAll: () => void,
clearCancel: Function, clearCancel: () => void,
width: Number, width: number,
} }
export const TrashDialog = ({ export const TrashDialog = ({

View file

@ -1,10 +1,9 @@
import React from 'react'; import * as React from 'react';
import { LOGOS } from '$constants/logos'; import { LOGOS } from '$constants/logos';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {}
logo: string
};
const Component = ({ logo }: Props) => ( const Component = ({ logo }: Props) => (
<div <div
@ -17,9 +16,6 @@ const Component = ({ logo }: Props) => (
/> />
); );
function mapStateToProps(state) { const mapStateToProps = ({ user: { logo } }) => ({ logo });
const { user: { logo } } = state;
return { logo };
}
export const LogoPreview = connect(mapStateToProps)(Component); export const LogoPreview = connect(mapStateToProps)(Component);

View file

@ -1,67 +0,0 @@
// @flow
import React from 'react';
import { Icon } from '$components/panels/Icon';
import classnames from 'classnames';
import { RouteRowEditor } from '$components/maps/RouteRowEditor';
type Props = {
_id: string,
title: string,
distance: number,
tab: string,
is_editing: boolean,
is_public: boolean,
openRoute: (_id: string) => {},
startEditing: (_id: string) => {},
stopEditing: () => {},
};
export const RouteRow = ({
title, distance, _id, openRoute, tab, is_editing, startEditing, stopEditing, is_public
}: Props) => (
<div className={classnames('route-row-wrapper', { is_editing })}>
{
tab === 'mine' &&
<div className="route-row-edit" onClick={() => startEditing(_id)}>
<Icon icon="icon-edit-1" />
</div>
}
{
!is_editing
?
<div
className="route-row"
>
<div onClick={() => openRoute(_id)}>
<div className="route-title">
<span>{(title || _id)}</span>
</div>
<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 className="route-row-panel">
<div className="">
<Icon icon="icon-trash-4" size={24} />
Удалить
</div>
<div className="flex_1 justify-end" onClick={() => startEditing(_id)}>
<Icon icon="icon-edit-1" size={24} />
Правка
</div>
</div>
</div>
: <RouteRowEditor title={title} is_public={is_public} distance={distance} _id={_id} />
}
</div>
);

View file

@ -0,0 +1,59 @@
// @flow
import * as React from 'react';
import { Icon } from '$components/panels/Icon';
import classnames from 'classnames';
interface Props {
_id: string,
tab: string,
is_editing: boolean,
title: string,
distance: number,
is_public: boolean,
openRoute: (_id: string) => void,
startEditing: (_id: string) => void,
stopEditing: () => void,
key: string,
}
export const RouteRow = ({ title, distance, _id, openRoute, tab, is_editing, startEditing }: any) => (
<div className={classnames('route-row-wrapper', { is_editing })}>
{
tab === 'mine' &&
<div className="route-row-edit" onClick={() => startEditing(_id)}>
<Icon icon="icon-edit-1" />
</div>
}
<div
className="route-row"
>
<div onClick={() => openRoute(_id)}>
<div className="route-title">
<span>{(title || _id)}</span>
</div>
<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 className="route-row-panel">
<div className="">
<Icon icon="icon-trash-4" size={24} />
Удалить
</div>
<div className="flex_1 justify-end" onClick={() => startEditing(_id)}>
<Icon icon="icon-edit-1" size={24} />
Правка
</div>
</div>
</div>
</div>
);

View file

@ -1,21 +1,21 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { Switch } from '$components/Switch'; import { Switch } from '$components/Switch';
type Props = { interface Props {
title: string;
is_editing: boolean;
distance: number;
_id: string;
}
interface State {
title: string, title: string,
is_public: boolean, is_public: boolean,
distance: number, }
_id: string,
};
type State = { export class RouteRowEditor extends React.Component<Props, State> {
title: string,
is_public: boolean,
};
export class RouteRowEditor extends React.PureComponent<Props, State> {
constructor(props) { constructor(props) {
super(props); super(props);

View file

@ -1,39 +1,38 @@
// flow // flow
import React from 'react'; import * as React from 'react';
import { toHours } from '$utils/format'; import { toHours } from '$utils/format';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Slider from 'rc-slider'; import Slider from 'rc-slider';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { setSpeed } from '$redux/user/actions'; import { setSpeed } from '$redux/user/actions';
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
distance: number, setSpeed: typeof setSpeed,
estimated: number, }
speed: number,
setSpeed: Function,
};
type State = { interface State {
dialogOpened: boolean, dialogOpened: boolean,
} }
class Component extends React.PureComponent<Props, State> { class Component extends React.PureComponent<Props, State> {
constructor(props) { constructor(props) {
super(props); super(props);
this.step = 5;
this.min = 5;
this.max = 30;
this.marks = [...Array((Math.floor(this.max - this.min) / this.step) + 1)].reduce((obj, el, index) => ({
...obj,
[this.min + (index * this.step)]: String(this.min + (index * this.step)),
}), { });
this.state = { this.state = {
dialogOpened: false, dialogOpened: false,
}; };
} }
step: number = 5;
min: number = 5;
max: number = 30;
marks: { [x: number]: string } = [...Array((Math.floor(this.max - this.min) / this.step) + 1)].reduce((obj, el, index) => ({
...obj,
[this.min + (index * this.step)]: String(this.min + (index * this.step)),
}), { });
toggleDialog = () => this.setState({ dialogOpened: !this.state.dialogOpened }); toggleDialog = () => this.setState({ dialogOpened: !this.state.dialogOpened });
render() { render() {

View file

@ -1,5 +1,5 @@
import React from 'react'; import * as React from 'react';
import { MODES } from '$constants/modes'; import { IModes, MODES } from '$constants/modes';
import { RouterDialog } from '$components/dialogs/RouterDialog'; import { RouterDialog } from '$components/dialogs/RouterDialog';
import { StickersDialog } from '$components/dialogs/StickersDialog'; import { StickersDialog } from '$components/dialogs/StickersDialog';
@ -28,14 +28,13 @@ import {
} from '$redux/user/actions'; } from '$redux/user/actions';
import { ProviderDialog } from '$components/dialogs/ProviderDialog'; import { ProviderDialog } from '$components/dialogs/ProviderDialog';
import { ShotPrefetchDialog } from '$components/dialogs/ShotPrefetchDialog'; import { ShotPrefetchDialog } from '$components/dialogs/ShotPrefetchDialog';
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
mode: String, width: number,
activeSticker: String,
width: Number,
} }
const DIALOG_CONTENTS = { const DIALOG_CONTENTS: { [x: string]: any } = {
[MODES.ROUTER]: RouterDialog, [MODES.ROUTER]: RouterDialog,
[MODES.STICKERS_SELECT]: StickersDialog, [MODES.STICKERS_SELECT]: StickersDialog,
[MODES.TRASH]: TrashDialog, [MODES.TRASH]: TrashDialog,
@ -46,14 +45,11 @@ const DIALOG_CONTENTS = {
[MODES.SHOT_PREFETCH]: ShotPrefetchDialog, [MODES.SHOT_PREFETCH]: ShotPrefetchDialog,
}; };
export const Component = (props: Props) => { export const Component = (props: Props) => (
const { mode } = props; props.mode && DIALOG_CONTENTS[props.mode]
? React.createElement(DIALOG_CONTENTS[props.mode], { ...props })
return ( : null
(mode && DIALOG_CONTENTS[mode] && React.createElement(DIALOG_CONTENTS[mode], { ...props })) );
|| <div>null</div>
);
};
const mapStateToProps = ({ user }) => ({ ...user }); const mapStateToProps = ({ user }) => ({ ...user });

View file

@ -1,4 +1,4 @@
import React from 'react'; import * as React from 'react';
import { MODES } from '$constants/modes'; import { MODES } from '$constants/modes';
import classnames from 'classnames'; import classnames from 'classnames';
@ -7,15 +7,13 @@ import { EditorDialog } from '$components/panels/EditorDialog';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { setMode, startEditing, stopEditing, setLogo, takeAShot, keyPressed } from '$redux/user/actions'; import { setMode, startEditing, stopEditing, setLogo, takeAShot, keyPressed } from '$redux/user/actions';
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
editing: false, setMode: typeof setMode,
mode: String, startEditing: typeof startEditing,
changed: Boolean, stopEditing: typeof stopEditing,
setMode: Function, keyPressed: EventListenerOrEventListenerObject,
startEditing: Function,
stopEditing: Function,
keyPressed: Function,
} }
class Component extends React.PureComponent<Props, void> { class Component extends React.PureComponent<Props, void> {
@ -27,9 +25,11 @@ class Component extends React.PureComponent<Props, void> {
if (!this.panel || !obj) return; if (!this.panel || !obj) return;
obj.style.width = width; obj.style.width = String(width);
} }
panel: HTMLElement = null;
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener('keydown', this.props.keyPressed); window.removeEventListener('keydown', this.props.keyPressed);
} }

View file

@ -1,11 +1,10 @@
import React from 'react'; import * as React from 'react';
import sprite from '$sprites/icon.svg';
export const Icon = ({ icon, size = 32 }) => ( export const Icon = ({ icon, size = 32 }: { icon: string, size?: number }) => (
<svg width={size} height={size} viewBox="0 0 32 32"> <svg width={size} height={size} viewBox="0 0 32 32">
<defs> <defs>
<mask id={`icon-mask-${icon}`}> <mask id={`icon-mask-${icon}`}>
<use xlinkHref={`${sprite}#${icon}`} x={0} y={0} /> <use xlinkHref={`${require('$sprites/icon.svg')}#${icon}`} x={0} y={0} />
</mask> </mask>
</defs> </defs>
<rect x="0" y="0" width="32" height="32" stroke="none" mask={`url(#icon-mask-${icon})`} /> <rect x="0" y="0" width="32" height="32" stroke="none" mask={`url(#icon-mask-${icon})`} />

View file

@ -1,9 +1,9 @@
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
type Props = { type Props = {
onCancel: Function, onCancel: () => void,
onSubmit: Function, onSubmit: () => void,
}; };
export const RendererPanel = ({ onCancel, onSubmit }: Props) => ( export const RendererPanel = ({ onCancel, onSubmit }: Props) => (
@ -32,11 +32,3 @@ export const RendererPanel = ({ onCancel, onSubmit }: Props) => (
</div> </div>
</div> </div>
); );
/*
<div className="control-bar control-bar-padded">
<button>
<Icon icon="icon-logo-3" />
</button>
</div>
*/

View file

@ -1,5 +1,5 @@
// flow // flow
import React from 'react'; import * as React from 'react';
import { UserLocation } from '$components/UserLocation'; import { UserLocation } from '$components/UserLocation';
import { DistanceBar } from '$components/panels/DistanceBar'; import { DistanceBar } from '$components/panels/DistanceBar';

View file

@ -1,21 +1,18 @@
// flow // flow
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import { PROVIDERS } from '$constants/providers'; import { PROVIDERS } from '$constants/providers';
import { LOGOS } from '$constants/logos'; import { LOGOS } from '$constants/logos';
import { setMode } from '$redux/user/actions'; import { setMode } from '$redux/user/actions';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { MODES } from '$constants/modes'; import { MODES } from '$constants/modes';
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
provider: string, startProviderMode: () => void,
logo: string, startLogoMode: () => void,
markers_shown: boolean, clearMode: () => void,
editing: boolean, }
startProviderMode: Function,
startLogoMode: Function,
clearMode: Function,
};
const Component = ({ const Component = ({
provider, logo, startProviderMode, startLogoMode, clearMode, editing, markers_shown, provider, logo, startProviderMode, startLogoMode, clearMode, editing, markers_shown,

View file

@ -1,33 +1,33 @@
import React from 'react'; import * as React from 'react';
import { GuestButton } from '$components/user/GuestButton'; import { GuestButton } from '$components/user/GuestButton';
import { DEFAULT_USER, ROLES } from '$constants/auth'; import { DEFAULT_USER, IUser, ROLES } from '$constants/auth';
import { UserButton } from '$components/user/UserButton'; import { UserButton } from '$components/user/UserButton';
import { UserMenu } from '$components/user/UserMenu'; import { UserMenu } from '$components/user/UserMenu';
import { setUser, userLogout, takeAShot, setDialog, gotVkUser, setDialogActive, openMapDialog } from '$redux/user/actions'; import { setUser, userLogout, takeAShot, setDialog, gotVkUser, setDialogActive, openMapDialog } from '$redux/user/actions';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import type { UserType } from '$constants/types';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
import classnames from 'classnames'; import classnames from 'classnames';
import { CLIENT } from '$config/frontend'; import { CLIENT } from '$config/frontend';
import { DIALOGS } from '$constants/dialogs'; import { DIALOGS } from '$constants/dialogs';
import { IRootState } from "$redux/user/reducer";
type Props = { interface Props extends IRootState {
user: UserType, userLogout: typeof userLogout,
dialog_active: Boolean, setDialog: typeof setDialog,
dialog: String, setDialogActive: typeof setDialogActive,
gotVkUser: typeof gotVkUser,
userLogout: Function, takeAShot: typeof takeAShot,
setDialog: Function, openMapDialog: typeof openMapDialog,
setDialogActive: Function,
gotVkUser: Function,
takeAShot: Function,
openMapDialog: Function,
}; };
export class Component extends React.PureComponent<Props, void> { interface State {
menuOpened: boolean
}
export class Component extends React.PureComponent<Props, State> {
state = { state = {
menuOpened: false, menuOpened: false,
}; };
@ -74,8 +74,8 @@ export class Component extends React.PureComponent<Props, void> {
}; };
openOauthFrame = () => { openOauthFrame = () => {
const width = parseInt(window.innerWidth, 10); const width = parseInt(String(window.innerWidth), 10);
const height = parseInt(window.innerHeight, 10); const height = parseInt(String(window.innerHeight), 10);
const top = (height - 370) / 2; const top = (height - 370) / 2;
const left = (width - 700) / 2; const left = (width - 700) / 2;

View file

@ -1,23 +1,23 @@
import React from 'react'; import * as React from 'react';
import { hideRenderer, cropAShot } from '$redux/user/actions'; import { hideRenderer, cropAShot } from '$redux/user/actions';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Croppr from 'croppr'; import Croppr from 'croppr';
import 'croppr/dist/croppr.css'; import 'croppr/dist/croppr.css';
import { Icon } from '$components/panels/Icon';
import { LOGOS } from '$constants/logos'; import { LOGOS } from '$constants/logos';
import { RendererPanel } from '$components/panels/RendererPanel'; import { RendererPanel } from '$components/panels/RendererPanel';
import { IRootState } from "$redux/user/reducer";
type Props = { type Props = {
data: String, data: IRootState['renderer']['data'],
logo: String, logo: IRootState['logo'],
hideRenderer: Function, hideRenderer: typeof hideRenderer,
cropAShot: Function, cropAShot: typeof cropAShot,
}; };
type State = { type State = {
opacity: Number, opacity: number,
}; };
class Component extends React.Component<Props, State> { class Component extends React.Component<Props, State> {
@ -52,7 +52,10 @@ class Component extends React.Component<Props, State> {
regionEl.append(this.logo); regionEl.append(this.logo);
}; };
croppr; croppr: Croppr;
logo: HTMLDivElement;
image: HTMLImageElement;
logoImg: HTMLImageElement;
getImage = () => this.props.cropAShot(this.croppr.getValue()); getImage = () => this.props.cropAShot(this.croppr.getValue());

View file

@ -1,5 +1,5 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import { Icon } from '$components/panels/Icon'; import { Icon } from '$components/panels/Icon';
type Props = { type Props = {

View file

@ -1,10 +1,10 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import { UserPicture } from '$components/user/UserPicture'; import { UserPicture } from '$components/user/UserPicture';
import type { UserType } from '$constants/types'; import { IUser } from '$constants/auth';
type Props = { type Props = {
user: UserType, user: IUser,
setMenuOpened: Function, setMenuOpened: Function,
}; };

View file

@ -1,4 +1,4 @@
import React from 'react'; import * as React from 'react';
import { APP_INFO } from '$constants/app_info'; import { APP_INFO } from '$constants/app_info';
type Props = { type Props = {

View file

@ -1,4 +1,4 @@
import React from 'react'; import * as React from 'react';
export const UserPicture = ({ photo }) => ( export const UserPicture = ({ photo }) => (
<div <div

View file

@ -1,11 +1,10 @@
import { CLIENT } from '$config/frontend'; import { CLIENT } from '$config/frontend';
export const API = { export const API: { [x: string]: string } = {
GET_GUEST: `${CLIENT.API_ADDR}/auth`, GET_GUEST: `${CLIENT.API_ADDR}/auth`,
CHECK_TOKEN: `${CLIENT.API_ADDR}/auth`, CHECK_TOKEN: `${CLIENT.API_ADDR}/auth`,
IFRAME_LOGIN_VK: `${CLIENT.API_ADDR}/auth/iframe/vk`, IFRAME_LOGIN_VK: `${CLIENT.API_ADDR}/auth/iframe/vk`,
GET_MAP: `${CLIENT.API_ADDR}/route`, GET_MAP: `${CLIENT.API_ADDR}/route`,
POST_MAP: `${CLIENT.API_ADDR}/route`, POST_MAP: `${CLIENT.API_ADDR}/route`,
GET_ROUTE_LIST: `${CLIENT.API_ADDR}/route/list`, GET_ROUTE_LIST: `${CLIENT.API_ADDR}/route/list`,
}; };

View file

@ -1,7 +1,6 @@
export const APP_INFO = { export const APP_INFO = {
VERSION: 2, VERSION: 2,
RELEASE: 1, RELEASE: 1,
CHANGELOG: { CHANGELOG: {
2: [ 2: [
[ [

View file

@ -1,5 +1,3 @@
type valueof<T> = T[keyof T]
export interface IRoles { export interface IRoles {
guest: string, guest: string,
vk: string, vk: string,

View file

@ -1,19 +1,19 @@
export interface IPRovider { export interface IProvider {
name: string, name: string,
url: string, url: string,
range: Array<string | number>, range: Array<string | number>,
} }
export interface ITileMaps { export interface ITileMaps {
WATERCOLOR: IPRovider, WATERCOLOR: IProvider,
DGIS: IPRovider, DGIS: IProvider,
DEFAULT: IPRovider, DEFAULT: IProvider,
DARQ: IPRovider, DARQ: IProvider,
BLANK: IPRovider, BLANK: IProvider,
HOT: IPRovider, HOT: IProvider,
YSAT: IPRovider, YSAT: IProvider,
YMAP: IPRovider, YMAP: IProvider,
SAT: IPRovider, SAT: IProvider,
} }

View file

@ -1,4 +1,4 @@
export const TIPS = { export const TIPS: { [x: string]: string } = {
SAVE_INFO: 'Никто, кроме вас не сможет изменить маршрут - только создать его копию и сохранить по другому адресу', SAVE_INFO: 'Никто, кроме вас не сможет изменить маршрут - только создать его копию и сохранить по другому адресу',
SAVE_TIMED_OUT: 'Сервер не ответил на запрос, попробуйте еще раз', SAVE_TIMED_OUT: 'Сервер не ответил на запрос, попробуйте еще раз',
SAVE_EMPTY: 'Этот маршрут пуст, нарисуйте что-нибудь для начала', SAVE_EMPTY: 'Этот маршрут пуст, нарисуйте что-нибудь для начала',

View file

@ -1,31 +0,0 @@
export type UserType = {
new_messages: Number,
place_types: Object,
random_url: String,
role: String,
routes: Array<Object>,
success: Boolean,
id: String,
token: String,
userdata: {
name: String,
agent: String,
ip: String,
photo: String,
}
};
type Path = Array<{ lat: Number, lng: Number }>;
type Stickers = Array<Object>;
export type Route = {
_id: String,
title: String,
version: Number,
stickers: Array<Stickers>,
route: Array<Path>,
logo: String,
distance: Number,
created_at: String,
updated_at: String,
}

View file

@ -1,5 +1,5 @@
// @flow // @flow
import React from 'react'; import * as React from 'react';
import { EditorPanel } from '$components/panels/EditorPanel'; import { EditorPanel } from '$components/panels/EditorPanel';
import { Fills } from '$components/Fills'; import { Fills } from '$components/Fills';
@ -15,15 +15,20 @@ import { LeftDialog } from '$containers/LeftDialog';
import { TopLeftPanel } from '$components/panels/TopLeftPanel'; import { TopLeftPanel } from '$components/panels/TopLeftPanel';
import { TopRightPanel } from '$components/panels/TopRightPanel'; import { TopRightPanel } from '$components/panels/TopRightPanel';
import { LogoPreview } from '$components/logo/LogoPreview'; import { LogoPreview } from '$components/logo/LogoPreview';
import { IStickerPack } from "$constants/stickers";
import { IDialogs } from "$constants/dialogs";
import { IModes } from "$constants/modes";
type Props = { type Props = {
renderer_active: Boolean, sticker: string,
hideRenderer: Function, renderer_active: boolean,
mode: String,
dialog: String, mode: keyof IModes,
dialog_active: Boolean, dialog: keyof IDialogs,
sticker: String, dialog_active: boolean,
set: String, set: keyof IStickerPack,
hideRenderer: typeof hideRenderer,
setDialogActive: typeof setDialogActive,
} }
const Component = (props: Props) => ( const Component = (props: Props) => (
@ -37,7 +42,12 @@ const Component = (props: Props) => (
<LogoPreview /> <LogoPreview />
<Cursor mode={props.mode} sticker={props.sticker} set={props.set} /> <Cursor mode={props.mode} sticker={props.sticker} set={props.set} />
<LeftDialog dialog={props.dialog} dialog_active={props.dialog_active} setDialogActive={props.setDialogActive} />
<LeftDialog
dialog={props.dialog}
dialog_active={props.dialog_active}
setDialogActive={props.setDialogActive}
/>
{ props.renderer_active && { props.renderer_active &&
<Renderer onClick={props.hideRenderer} /> <Renderer onClick={props.hideRenderer} />

View file

@ -1,30 +0,0 @@
// @flow
import React from 'react';
import { DIALOGS } from '$constants/dialogs';
import classnames from 'classnames';
import { AppInfoDialog } from '$components/dialogs/AppInfoDialog';
import { Icon } from '$components/panels/Icon';
import { MapListDialog } from '$components/dialogs/MapListDialog';
type Props = {
dialog: String,
dialog_active: Boolean,
setDialogActive: Function,
}
const LEFT_DIALOGS = {
[DIALOGS.MAP_LIST]: MapListDialog,
[DIALOGS.APP_INFO]: AppInfoDialog,
};
export const LeftDialog = ({ dialog, dialog_active, setDialogActive }: Props) => (
Object.keys(LEFT_DIALOGS).map(item => (
<div className={classnames('dialog', { active: dialog_active && (dialog === item) })} key={item}>
{ dialog && LEFT_DIALOGS[item] && React.createElement(LEFT_DIALOGS[item]) }
<div className="dialog-close-button" onClick={() => setDialogActive(false)}>
<Icon icon="icon-cancel-1" />
</div>
</div>
))
);

View file

@ -0,0 +1,36 @@
// @flow
import * as React from 'react';
import { DIALOGS, IDialogs } from '$constants/dialogs';
import * as classnames from 'classnames';
import { AppInfoDialog } from '$components/dialogs/AppInfoDialog';
import { Icon } from '$components/panels/Icon';
import { MapListDialog } from '$components/dialogs/MapListDialog';
import * as ActionCreators from "$redux/user/actions";
import { StatelessComponent } from "react";
interface Props {
dialog: keyof IDialogs,
dialog_active: Boolean,
setDialogActive: typeof ActionCreators.setDialogActive,
}
const LEFT_DIALOGS = {
[DIALOGS.MAP_LIST]: MapListDialog,
[DIALOGS.APP_INFO]: AppInfoDialog,
};
export const LeftDialog = ({ dialog, dialog_active, setDialogActive }: Props) => (
<React.Fragment>
{
Object.keys(LEFT_DIALOGS).map(item => (
<div className={classnames('dialog', { active: dialog_active && (dialog === item) })} key={item}>
{ dialog && LEFT_DIALOGS[item] && React.createElement(LEFT_DIALOGS[item]) }
<div className="dialog-close-button" onClick={() => setDialogActive(false)}>
<Icon icon="icon-cancel-1" />
</div>
</div>
))
}
</React.Fragment>
);

View file

@ -1,6 +1,5 @@
import { Map } from '$modules/Map'; import { Map } from '$modules/Map';
import { NewPoly } from '$modules/NewPoly'; import { NewPoly } from '$modules/NewPoly';
// import { Poly } from '$modules/Poly';
import { MODES } from '$constants/modes'; import { MODES } from '$constants/modes';
import { Stickers } from '$modules/Stickers'; import { Stickers } from '$modules/Stickers';
import { Router } from '$modules/Router'; import { Router } from '$modules/Router';
@ -21,8 +20,10 @@ import {
setRouterPoints, setRouterPoints,
setTitle, setTitle,
} from '$redux/user/actions'; } from '$redux/user/actions';
import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers'; import { DEFAULT_PROVIDER, IProvider, PROVIDERS } from '$constants/providers';
import { STICKERS } from '$constants/stickers'; import { STICKERS } from '$constants/stickers';
import { IRootState } from "$redux/user/reducer";
import { DEFAULT_USER } from "$constants/auth";
export class Editor { export class Editor {
constructor() { constructor() {
@ -30,7 +31,7 @@ export class Editor {
this.owner = null; this.owner = null;
this.map = new Map({ container: 'map' }); this.map = new Map({ container: 'map' });
this.initialData = {}; this.initialData = {};
this.activeSticker = null; this.activeSticker = {};
this.mode = MODES.NONE; this.mode = MODES.NONE;
this.provider = PROVIDERS[DEFAULT_PROVIDER]; this.provider = PROVIDERS[DEFAULT_PROVIDER];
@ -70,7 +71,6 @@ export class Editor {
toggle: this.clearSticker, toggle: this.clearSticker,
}, },
[MODES.TRASH]: { [MODES.TRASH]: {
// toggle: this.clearAll,
toggle: this.clearMode, toggle: this.clearMode,
}, },
[MODES.CONFIRM_CANCEL]: { [MODES.CONFIRM_CANCEL]: {
@ -98,25 +98,42 @@ export class Editor {
map.addEventListener('dragstop', () => lockMapClicks(false)); map.addEventListener('dragstop', () => lockMapClicks(false));
} }
getUser = () => store.getState().user.user; map; // todo typecheck
getMode = () => store.getState().user.mode; poly; // todo typecheck
getProvider = () => store.getState().user.provider; stickers;
getTitle = () => store.getState().user.title; router;
getEditing = () => store.getState().user.editing;
getChanged = () => store.getState().user.changed;
getRouterPoints = () => store.getState().user.routerPoints;
getDistance = () => store.getState().user.distance;
setLogo = logo => store.dispatch(setLogo(logo)); logo: string | number = DEFAULT_LOGO;
setMode = value => store.dispatch(setMode(value)); owner = null;
setRouterPoints = value => store.dispatch(setRouterPoints(value)); initialData;
setActiveSticker = value => store.dispatch(setActiveSticker(value)); activeSticker: IRootState['activeSticker'];
setTitle = value => store.dispatch(setTitle(value)); mode: IRootState['mode'];
setAddress = value => store.dispatch(setAddress(value)); provider: IProvider;
setPublic = value => store.dispatch(setPublic(value)); switches;
clickHandlers;
user = DEFAULT_USER;
getState = (): IRootState => <any>store.getState().user;
getUser = () => this.getState().user;
getMode = () => this.getState().mode;
getProvider = () => this.getState().provider;
getTitle = () => this.getState().title;
getEditing = () => this.getState().editing;
getChanged = () => this.getState().changed;
getRouterPoints = () => this.getState().routerPoints;
getDistance = () => this.getState().distance;
setLogo: typeof setLogo = logo => store.dispatch(setLogo(logo));
setMode: typeof setMode = value => store.dispatch(setMode(value));
setRouterPoints: typeof setRouterPoints = value => store.dispatch(setRouterPoints(value));
setActiveSticker: typeof setActiveSticker = value => store.dispatch(setActiveSticker(value));
setTitle: typeof setTitle = value => store.dispatch(setTitle(value));
setAddress: typeof setAddress = value => store.dispatch(setAddress(value));
setPublic: typeof setPublic = value => store.dispatch(setPublic(value));
setMarkersShown = value => { setMarkersShown = value => {
if (store.getState().user.markers_shown !== value) store.dispatch(setMarkersShown(value)); if (this.getState().markers_shown !== value) store.dispatch(setMarkersShown(value));
}; };
resetSaveDialog = () => store.dispatch(resetSaveDialog()); resetSaveDialog = () => store.dispatch(resetSaveDialog());
@ -340,6 +357,4 @@ export class Editor {
}; };
} }
export const editor = new Editor({}); export const editor = new Editor();
window.editor = editor;

View file

@ -1,11 +1,18 @@
import { map, tileLayer } from 'leaflet'; import {
Map as MapInterface,
map,
tileLayer,
TileLayer,
} from 'leaflet';
import 'leaflet/dist/leaflet.css'; import 'leaflet/dist/leaflet.css';
import { PROVIDER } from '$config/frontend'; import { PROVIDER } from '$config/frontend';
import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers'; import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers';
export class Map { export class Map {
constructor({ container }) { constructor({ container }) {
this.map = map(container, { editable: true }).setView([55.0153275, 82.9071235], 13); this.map = map(container).setView([55.0153275, 82.9071235], 13);
// todo: change coords?
this.tileLayer = tileLayer(PROVIDER.url, { this.tileLayer = tileLayer(PROVIDER.url, {
attribution: 'Независимое Велосообщество', attribution: 'Независимое Велосообщество',
@ -16,7 +23,10 @@ export class Map {
this.tileLayer.addTo(this.map); this.tileLayer.addTo(this.map);
} }
setProvider = provider => { map: MapInterface;
tileLayer: TileLayer;
setProvider = (provider: string): void => {
const { url } = (provider && PROVIDERS[provider] && PROVIDERS[provider]) || PROVIDERS[DEFAULT_PROVIDER]; const { url } = (provider && PROVIDERS[provider] && PROVIDERS[provider]) || PROVIDERS[DEFAULT_PROVIDER];
this.tileLayer.setUrl(url); this.tileLayer.setUrl(url);

View file

@ -1,5 +1,5 @@
import { marker } from 'leaflet'; import { marker } from 'leaflet';
import React from 'react'; import * as React from 'react';
import { DomMarker } from '$utils/DomMarker'; import { DomMarker } from '$utils/DomMarker';
import { STICKERS } from '$constants/stickers'; import { STICKERS } from '$constants/stickers';

View file

@ -12,13 +12,6 @@ export class Stickers {
this.layer.addTo(this.map); this.layer.addTo(this.map);
} }
//
// createOnClick = e => {
// if (!e || !e.latlng) return;
//
// const { latlng } = e;
// this.createSticker({ latlng });
// };
createSticker = ({ latlng, sticker, angle = 2.2, text = '', set }) => { createSticker = ({ latlng, sticker, angle = 2.2, text = '', set }) => {
const marker = new Sticker({ const marker = new Sticker({

View file

@ -43,7 +43,7 @@ export function configureStore(): { store: Store<any>, persistor: Persistor } {
} }
export const history = createBrowserHistory(); export const history = createBrowserHistory();
export const historyListener = history.listen((location, action) => { // export const historyListener = history.listen((location, action) => {
if (action === 'REPLACE') return; // if (action === 'REPLACE') return;
store.dispatch(locationChanged(location.pathname)); // store.dispatch(locationChanged(location.pathname));
}); // });

View file

@ -10,6 +10,12 @@ 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 } from "$constants/stickers";
interface IRoute {
lat: number,
lng: number,
_id: string,
}
interface IRootReducer { interface IRootReducer {
ready: boolean, ready: boolean,
user: IUser, user: IUser,
@ -49,7 +55,7 @@ interface IRootReducer {
routes: { routes: {
limit: 0, limit: 0,
loading: boolean, loading: boolean,
list: [], list: Array<IRoute>,
filter: { filter: {
title: '', title: '',
starred: boolean, starred: boolean,

View file

@ -22,7 +22,7 @@ import {
import { getUrlData, parseQuery, pushLoaderState, pushNetworkInitError, pushPath, replacePath } from '$utils/history'; import { getUrlData, parseQuery, pushLoaderState, pushNetworkInitError, pushPath, replacePath } from '$utils/history';
import { editor } from '$modules/Editor'; import { editor } from '$modules/Editor';
import { ACTIONS } from '$redux/user/constants'; import { ACTIONS } from '$redux/user/constants';
import { MODES } from '$constants/modes'; import { IModes, MODES } from '$constants/modes';
import { DEFAULT_USER } from '$constants/auth'; import { DEFAULT_USER } from '$constants/auth';
import { TIPS } from '$constants/tips'; import { TIPS } from '$constants/tips';
import { import {
@ -33,15 +33,18 @@ import {
getTilePlacement, getTilePlacement,
imageFetcher imageFetcher
} from '$utils/renderer'; } from '$utils/renderer';
import { LOGOS } from '$constants/logos'; import { ILogos, LOGOS } from '$constants/logos';
import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers'; import { DEFAULT_PROVIDER, PROVIDERS } from '$constants/providers';
import { DIALOGS } from '$constants/dialogs'; import { DIALOGS } from '$constants/dialogs';
import * as ActionCreators from '$redux/user/actions';
import { IRootState } from "$redux/user/reducer";
const getUser = state => (state.user.user); const getUser = state => (state.user.user);
const getState = state => (state.user); const getState = state => (state.user);
const hideLoader = () => { const hideLoader = () => {
document.getElementById('loader').style.opacity = 0; document.getElementById('loader').style.opacity = String(0);
document.getElementById('loader').style.pointerEvents = 'none'; document.getElementById('loader').style.pointerEvents = 'none';
return true; return true;
@ -213,19 +216,19 @@ function* authCheckSaga() {
return yield call(mapInitSaga); return yield call(mapInitSaga);
} }
function* setModeSaga({ mode }) { function* setModeSaga({ mode }: ReturnType<typeof ActionCreators.setMode>) {
return yield editor.changeMode(mode); return yield editor.changeMode(mode);
// console.log('change', mode); // console.log('change', mode);
} }
function* setActiveStickerSaga({ activeSticker }) { function* setActiveStickerSaga({ activeSticker }: { type: string, activeSticker: IRootState['activeSticker'] }) {
yield editor.activeSticker = activeSticker; yield editor.activeSticker = activeSticker;
yield put(setMode(MODES.STICKERS)); yield put(setMode(MODES.STICKERS));
return true; return true;
} }
function* setLogoSaga({ logo }) { function* setLogoSaga({ logo }: { type: string, logo: keyof ILogos }) {
const { mode } = yield select(getState); const { mode } = yield select(getState);
editor.logo = logo; editor.logo = logo;
@ -275,7 +278,7 @@ function* clearSaga({ type }) {
function* sendSaveRequestSaga({ function* sendSaveRequestSaga({
title, address, force, is_public title, address, force, is_public
}) { }: 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();
@ -310,7 +313,7 @@ function* sendSaveRequestSaga({
function* getRenderData() { function* getRenderData() {
yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 })); yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 }));
const canvas = 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');
@ -355,7 +358,7 @@ function* getCropData({
x, y, width, height x, y, width, height
}) { }) {
const { logo, renderer: { data } } = yield select(getState); const { logo, renderer: { data } } = yield select(getState);
const canvas = document.getElementById('renderer'); 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');
@ -381,7 +384,7 @@ function* cropAShotSaga(params) {
return yield put(hideRenderer()); return yield put(hideRenderer());
} }
function* changeProviderSaga({ provider }) { 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));
@ -396,7 +399,7 @@ function* changeProviderSaga({ provider }) {
return put(setMode(MODES.NONE)); return put(setMode(MODES.NONE));
} }
function* locationChangeSaga({ location }) { function* locationChangeSaga({ location }: ReturnType<typeof ActionCreators.locationChanged>) {
const { address, ready, user: { id, random_url } } = yield select(getState); const { address, ready, user: { id, random_url } } = yield select(getState);
if (!ready) return; if (!ready) return;
@ -426,12 +429,12 @@ function* locationChangeSaga({ location }) {
} }
} }
function* gotVkUserSaga({ user }) { function* gotVkUserSaga({ user }: ReturnType<typeof ActionCreators.gotVkUser>) {
const data = yield call(checkUserToken, user); const data = yield call(checkUserToken, user);
yield put(setUser(data)); yield put(setUser(data));
} }
function* keyPressedSaga({ key, target }): any { function* keyPressedSaga({ key, target }: ReturnType<typeof ActionCreators.keyPressed>): any {
if ( if (
target === 'INPUT' || target === 'INPUT' ||
target === 'TEXTAREA' target === 'TEXTAREA'
@ -490,7 +493,7 @@ function* searchSetSaga() {
yield call(searchSetSagaWorker); yield call(searchSetSagaWorker);
} }
function* openMapDialogSaga({ tab }) { function* openMapDialogSaga({ tab }: ReturnType<typeof ActionCreators.openMapDialog>) {
const { dialog_active, routes: { filter: { tab: current } } } = yield select(getState); const { dialog_active, routes: { filter: { tab: current } } } = yield select(getState);
if (dialog_active && tab === current) { if (dialog_active && tab === current) {
@ -514,7 +517,7 @@ function* searchSetTabSaga() {
yield call(searchSetSaga); yield call(searchSetSaga);
} }
function* setSaveSuccessSaga({ address, title, is_public }) { function* setSaveSuccessSaga({ address, title, is_public }: 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);

View file

@ -6,9 +6,9 @@
"noImplicitAny": false, "noImplicitAny": false,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"module": "commonjs", "module": "commonjs",
"target": "es5", "target": "es6",
"jsx": "react", "jsx": "react",
"lib": [ "es2015", "DOM" ], "lib": [ "es2015", "DOM", "es6" ],
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"$components/*": [ "src/components/*" ], "$components/*": [ "src/components/*" ],
@ -28,5 +28,6 @@
"include": [ "include": [
"./src/**/*", "./src/**/*",
"./backend/**/*", "./backend/**/*",
"./custom.d.ts",
] ]
} }