diff --git a/src/components/logo/LogoDialog.jsx b/src/components/logo/LogoDialog.jsx index 4b7bdf6..d54c3f4 100644 --- a/src/components/logo/LogoDialog.jsx +++ b/src/components/logo/LogoDialog.jsx @@ -3,29 +3,26 @@ import { LOGOS } from '$constants/logos'; import { Icon } from '$components/panels/Icon'; import classnames from 'classnames'; -export class LogoDialog extends React.Component { - changeLogo = logo => { - this.props.editor.changeLogo(logo); - }; - - render() { - return ( -
-
- -
- { - Object.keys(LOGOS).map(logo => ( -
this.changeLogo(logo)} - key={logo} - > - {LOGOS[logo][0]} -
- )) - } -
- ); - } +type Props = { + logo: String, + setLogo: Function, } + +export const LogoDialog = ({ logo, setLogo }: Props) => ( +
+
+ +
+ { + Object.keys(LOGOS).map(item => ( +
setLogo(item)} + key={item} + > + {LOGOS[item][0]} +
+ )) + } +
+); diff --git a/src/components/panels/EditorDialog.jsx b/src/components/panels/EditorDialog.jsx index 60a54ce..ba40897 100644 --- a/src/components/panels/EditorDialog.jsx +++ b/src/components/panels/EditorDialog.jsx @@ -7,10 +7,23 @@ import { TrashDialog } from '$components/trash/TrashDialog'; import { LogoDialog } from '$components/logo/LogoDialog'; import { SaveDialog } from '$components/save/SaveDialog'; import { CancelDialog } from '$components/save/CancelDialog'; +import type { UserType } from '$constants/types'; +type Props = { + mode: String, + routerPoints: Number, + editor: Object, + activeSticker: String, + logo: String, + user: UserType, + title: String, + address: String, + + setLogo: Function, +} export const EditorDialog = ({ - mode, routerPoints, editor, activeSticker, logo, user, title, address, -}) => { + mode, routerPoints, editor, activeSticker, logo, user, title, address, setLogo +}: Props) => { const showDialog = ( mode === MODES.ROUTER || (mode === MODES.STICKERS && !activeSticker) @@ -26,7 +39,7 @@ export const EditorDialog = ({ { mode === MODES.ROUTER && } { mode === MODES.STICKERS && } { mode === MODES.TRASH && } - { mode === MODES.LOGO && } + { mode === MODES.LOGO && } { mode === MODES.SAVE && } { mode === MODES.CONFIRM_CANCEL && } diff --git a/src/components/panels/EditorPanel.jsx b/src/components/panels/EditorPanel.jsx index 8f86f73..dd3f64a 100644 --- a/src/components/panels/EditorPanel.jsx +++ b/src/components/panels/EditorPanel.jsx @@ -9,7 +9,7 @@ import { EditorDialog } from '$components/panels/EditorDialog'; import { LogoPreview } from '$components/logo/LogoPreview'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import { setMode, startEditing, stopEditing } from '$redux/user/actions'; +import { setMode, startEditing, stopEditing, setLogo } from '$redux/user/actions'; import type { UserType } from '$constants/types'; import { editor } from '$modules/Editor'; @@ -29,7 +29,7 @@ type Props = { setMode: Function, startEditing: Function, stopEditing: Function, - + setLogo: Function, } class Component extends React.PureComponent { @@ -76,6 +76,7 @@ class Component extends React.PureComponent { user={user} title={title} address={address} + setLogo={this.props.setLogo} /> @@ -209,6 +210,7 @@ function mapStateToProps(state) { const mapDispatchToProps = dispatch => bindActionCreators({ setMode, + setLogo, startEditing, stopEditing, }, dispatch); diff --git a/src/components/panels/UserPanel.jsx b/src/components/panels/UserPanel.jsx index 1bb564c..a3e2e92 100644 --- a/src/components/panels/UserPanel.jsx +++ b/src/components/panels/UserPanel.jsx @@ -5,8 +5,18 @@ import { SERVER } from '$constants/api'; import { DEFAULT_USER, ROLES } from '$constants/auth'; import { UserButton } from '$components/user/UserButton'; import { UserMenu } from '$components/user/UserMenu'; +import { setUser, userLogout } from '$redux/user/actions'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import type { UserType } from '$constants/types'; -export class UserPanel extends React.PureComponent { +type Props = { + user: UserType, + userLogout: Function, + setUser: Function, +}; + +export class Component extends React.PureComponent { state = { menuOpened: false, }; @@ -56,7 +66,7 @@ export class UserPanel extends React.PureComponent { render() { const { - props: { user, userLogout, editor, editing }, + props: { user }, state: { menuOpened }, } = this; @@ -71,7 +81,7 @@ export class UserPanel extends React.PureComponent { } { (user && user.role && user.role !== 'guest' && menuOpened) && - + } @@ -79,3 +89,20 @@ export class UserPanel extends React.PureComponent { ); } } + + +function mapStateToProps(state) { + const { user: { user } } = state; + + return { user }; +} + +const mapDispatchToProps = dispatch => bindActionCreators({ + setUser, + userLogout, +}, dispatch); + +export const UserPanel = connect( + mapStateToProps, + mapDispatchToProps +)(Component); diff --git a/src/components/user/GuestButton.jsx b/src/components/user/GuestButton.jsx index 51989eb..51cfd96 100644 --- a/src/components/user/GuestButton.jsx +++ b/src/components/user/GuestButton.jsx @@ -1,8 +1,14 @@ +// @flow import React from 'react'; -export const GuestButton = ({ onClick }) => ( +type Props = { + onClick: Function, +} + +export const GuestButton = ({ onClick }: Props) => (
); + +/* +
+
Мы храним следующие данные о вас:
+ { id &&
ID: {id}
} + { agent &&
Браузер: {agent}
} + { ip &&
Адрес: {ip}
} +
Мы используем их для авторизации и исправления ошибок.
+
+ */ diff --git a/src/config.js b/src/config.js index e1b5973..88e2302 100644 --- a/src/config.js +++ b/src/config.js @@ -1,3 +1,7 @@ +import { providers } from '$constants/providers'; + export const CONFIG = { OSRM_URL: 'http://vault48.org:5000/route/v1', }; + +export const PROVIDER = providers.blank; diff --git a/src/containers/App.jsx b/src/containers/App.jsx index 11b1c64..14fd877 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -4,12 +4,8 @@ import React from 'react'; import { editor } from '$modules/Editor'; import { EditorPanel } from '$components/panels/EditorPanel'; import { Fills } from '$components/Fills'; -import { DEFAULT_LOGO } from '$constants/logos'; import { UserLocation } from '$components/UserLocation'; -import { DEFAULT_USER } from '$constants/auth'; -import { storeData, getData } from '$utils/storage'; import { UserPanel } from '$components/panels/UserPanel'; -import { pushPath } from '$utils/history'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; @@ -17,44 +13,26 @@ import { hot } from 'react-hot-loader'; import type { UserType } from '$constants/types'; type Props = { - // todo: clean this! user: UserType, - editing: false, - mode: String, - changed: Boolean, - distance: Number, - title: String, - address: String, - mode: String, - editing: Boolean, - logo: String, - routerPoints: Number, - estimateTime: Number, - activeSticker: String, - title: String, - address: String, } -type State = { -} - -class Component extends React.Component { - state = { - // mode: 'none', - // editing: false, - logo: DEFAULT_LOGO, - routerPoints: 0, - totalDistance: 0, - estimateTime: 0, - activeSticker: null, - // user: { - // ...DEFAULT_USER, - // }, - // title: '', - // address: '', - // changed: false, - }; +class Component extends React.Component { + // state = { + // // mode: 'none', + // // editing: false, + // logo: DEFAULT_LOGO, + // routerPoints: 0, + // totalDistance: 0, + // estimateTime: 0, + // activeSticker: null, + // // user: { + // // ...DEFAULT_USER, + // // }, + // // title: '', + // // address: '', + // // changed: false, + // }; componentDidMount() { // this.authInit(); @@ -79,76 +57,76 @@ class Component extends React.Component { // this.startEmptyEditor(); // } // }; - - startEmptyEditor = () => { - const { user } = this.state; - if (!user || !user.random_url || !user.id) return; - - pushPath(`/${user.random_url}/edit`); - - editor.owner = user.id; - editor.startEditing(); - - this.hideLoader(); - - this.clearChanged(); - }; - - setTitle = title => this.setState({ title }); - setAddress = address => { - this.setState({ address }); - }; - - getTitle = () => this.state.title; - - setDataOnLoad = data => { - this.clearChanged(); - editor.setData(data); - this.hideLoader(); - }; - - hideLoader = () => { - document.getElementById('loader').style.opacity = 0; - document.getElementById('loader').style.pointerEvents = 'none'; - }; - - setMode = mode => { - this.setState({ mode }); - }; - - setRouterPoints = routerPoints => { - this.setState({ routerPoints }); - }; - - setTotalDist = totalDistance => { - const time = (totalDistance && (totalDistance / 15)) || 0; - const estimateTime = (time && parseFloat(time.toFixed(1))); - this.setState({ totalDistance, estimateTime }); - }; - - setActiveSticker = activeSticker => { - this.setState({ activeSticker }); - }; - - setLogo = logo => { - this.setState({ logo }); - }; - - setEditing = editing => { - this.setState({ editing }); - }; - - getUser = () => this.state.user; // - // triggerOnChange = () => { - // if (!this.state.editing) return; + // startEmptyEditor = () => { + // const { user } = this.state; + // if (!user || !user.random_url || !user.id) return; // - // this.setState({ changed: true }); + // pushPath(`/${user.random_url}/edit`); + // + // editor.owner = user.id; + // editor.startEditing(); + // + // this.hideLoader(); + // + // this.clearChanged(); + // }; + // + // setTitle = title => this.setState({ title }); + // setAddress = address => { + // this.setState({ address }); + // }; + // + // getTitle = () => this.state.title; + // + // setDataOnLoad = data => { + // this.clearChanged(); + // editor.setData(data); + // this.hideLoader(); + // }; + // + // hideLoader = () => { + // document.getElementById('loader').style.opacity = 0; + // document.getElementById('loader').style.pointerEvents = 'none'; + // }; + // + // setMode = mode => { + // this.setState({ mode }); + // }; + // + // setRouterPoints = routerPoints => { + // this.setState({ routerPoints }); + // }; + // + // setTotalDist = totalDistance => { + // const time = (totalDistance && (totalDistance / 15)) || 0; + // const estimateTime = (time && parseFloat(time.toFixed(1))); + // this.setState({ totalDistance, estimateTime }); + // }; + // + // setActiveSticker = activeSticker => { + // this.setState({ activeSticker }); + // }; + // + // setLogo = logo => { + // this.setState({ logo }); + // }; + // + // setEditing = editing => { + // this.setState({ editing }); + // }; + // + // getUser = () => this.state.user; + // // + // // triggerOnChange = () => { + // // if (!this.state.editing) return; + // // + // // this.setState({ changed: true }); + // // }; + // + // clearChanged = () => { + // this.setState({ changed: false }); // }; - - clearChanged = () => { - this.setState({ changed: false }); - }; // editor = new Editor({ // container: 'map', @@ -186,45 +164,43 @@ class Component extends React.Component { // } // }; - setUser = user => { - if (!user.token || !user.id) return; + // setUser = user => { + // if (!user.token || !user.id) return; + // + // if (this.state.user.id === editor.owner) { + // editor.owner = user.id; + // } + // + // this.setState({ + // user: { + // ...DEFAULT_USER, + // ...user, + // } + // }); + // + // this.storeUserData(); + // }; - if (this.state.user.id === editor.owner) { - editor.owner = user.id; - } + // storeUserData = () => { + // storeData('user', this.state.user); + // }; - this.setState({ - user: { - ...DEFAULT_USER, - ...user, - } - }); - - this.storeUserData(); - }; - - storeUserData = () => { - storeData('user', this.state.user); - }; - - getUserData = () => getData('user') || null; - - userLogout = () => { - if (this.state.user.id === editor.owner) { - editor.owner = null; - } - // - this.setState({ - user: DEFAULT_USER, - }); - - setTimeout(this.storeUserData, 0); - }; + // getUserData = () => getData('user') || null; + // + // userLogout = () => { + // if (this.state.user.id === editor.owner) { + // editor.owner = null; + // } + // // + // this.setState({ + // user: DEFAULT_USER, + // }); + // + // setTimeout(this.storeUserData, 0); + // }; render() { - const { - props: { user } - } = this; + const { props: { user } } = this; return (
@@ -235,8 +211,8 @@ class Component extends React.Component { diff --git a/src/modules/Editor.js b/src/modules/Editor.js index 044476f..35a58d6 100644 --- a/src/modules/Editor.js +++ b/src/modules/Editor.js @@ -14,31 +14,19 @@ import { setChanged, setDistance, setEditing, - setLogo, + setLogo, setMode, setRouterPoints, setTitle } from '$redux/user/actions'; export class Editor { - constructor({ - // container, - // mode, - // setMode, - // setRouterPoints, - // setTotalDist, - // setEditing, - // triggerOnChange, - // getTitle, - // clearChanged, - // setActiveSticker, - // setLogo, - // setTitle, - // setAddress, - }) { + constructor() { this.logo = DEFAULT_LOGO; this.owner = null; this.map = new Map({ container: 'map' }); this.initialData = {}; + this.activeSticker = null; + this.mode = MODES.NONE; const { triggerOnChange, lockMapClicks, routerMoveStart, changeMode, pushPolyPoints, @@ -81,8 +69,6 @@ export class Editor { [MODES.ROUTER]: this.router.pushWaypointOnClick, }; - this.activeSticker = null; - this.mode = MODES.NONE; // this.clearChanged = clearChanged; // this.setActiveSticker = setActiveSticker; // this.setLogo = setLogo; @@ -104,6 +90,7 @@ export class Editor { getChanged = () => store.getState().user.changed; setEditing = value => store.dispatch(setEditing(value)); + setMode = value => store.dispatch(setMode(value)); setDistance = value => store.dispatch(setDistance(value)); setChanged = value => store.dispatch(setChanged(value)); setRouterPoints = value => store.dispatch(setRouterPoints(value)); @@ -121,17 +108,20 @@ export class Editor { }; createStickerOnClick = (e) => { + // todo: move to sagas? if (!e || !e.latlng || !this.activeSticker) return; const { latlng } = e; this.stickers.createSticker({ latlng, sticker: this.activeSticker }); - this.setSticker(null); + this.setActiveSticker(null); }; changeMode = mode => { + // todo: check if TOGGLING works (we changing MODE from the sagas now) if (this.mode === mode) { if (this.switches[mode] && this.switches[mode].toggle) { - this.switches[mode].toggle(); // if we have special function on mode when it toggles + // if we have special function on mode when it clicked again + this.switches[mode].toggle(); } else { this.disableMode(mode); // this.setMode(MODES.NONE); @@ -154,7 +144,7 @@ export class Editor { }; onClick = e => { - if (e.originalEvent.which === 3) return; // skip right click + if (e.originalEvent.which === 3) return; // skip right / middle click if (this.clickHandlers[this.mode]) this.clickHandlers[this.mode](e); }; @@ -190,45 +180,47 @@ export class Editor { this.poly.pushPoints(latlngs); }; - setSticker = sticker => { - this.activeSticker = sticker; - this.setActiveSticker(sticker); - }; + // setSticker = sticker => { + // this.activeSticker = sticker; + // this.setActiveSticker(sticker); + // }; clearSticker = () => { if (this.activeSticker) { - this.setSticker(null); + this.setActiveSticker(null); } else { - this.changeMode(MODES.NONE); + this.setMode(MODES.NONE); } }; clearAll = () => { + // todo: move to sagas this.poly.clearAll(); this.router.clearAll(); this.stickers.clearAll(); - this.setSticker(null); - this.changeMode(MODES.NONE); + this.setActiveSticker(null); + this.setMode(MODES.NONE); this.clearChanged(); }; changeLogo = logo => { + // todo: move to sagas this.logo = logo; this.setLogo(logo); this.changeMode(MODES.NONE); }; - setData = ({ route, stickers, version = 1, owner, title, address }) => { + setData = ({ + route, stickers, version = 1, owner, title, address + }) => { this.setTitle(title || ''); const { id } = this.getUser(); if (address && id && owner && id === owner) this.setAddress(address); - if (route) { - this.poly.setPoints(route); - } + if (route) this.poly.setPoints(route); if (stickers) { stickers.map(sticker => this.stickers.createSticker({ @@ -238,9 +230,7 @@ export class Editor { })); } - if (owner) { - this.owner = owner; - } + if (owner) this.owner = owner; if (!route || route.length <= 1) return; @@ -258,7 +248,7 @@ export class Editor { version: 2, title: this.getTitle(), owner: this.owner, - address: this.owner === id ? path : null, + address: (this.owner === id ? path : null), path, route, stickers, @@ -278,19 +268,19 @@ export class Editor { if (this.poly.latlngs && this.poly.latlngs.length > 1) this.poly.poly.enableEdit(); this.stickers.startEditing(); - // this.setEditing(true); - console.log(this.initialData); + // this.setEditing(true); + // console.log(this.initialData); }; stopEditing = () => { const { path } = getUrlData(); pushPath(`/${(this.initialData && this.initialData.path) || path}`); - this.changeMode(MODES.NONE); + // this.changeMode(MODES.NONE); this.poly.poly.disableEdit(); this.stickers.stopEditing(); - this.setEditing(false); + // this.setEditing(false); }; cancelEditing = () => { @@ -313,11 +303,11 @@ export class Editor { stickers: this.stickers.dumpData(), }); - isEmpty = () => { - const { route, stickers } = this.dumpData(); - - return (route.length > 1 && stickers.length > 0); - }; + // isEmpty = () => { + // const { route, stickers } = this.dumpData(); + // + // return (route.length > 1 && stickers.length > 0); + // }; hasEmptyHistory = () => { const { route, stickers } = this.initialData; @@ -326,18 +316,4 @@ export class Editor { } } -export const editor = new Editor({ - // setMode: this.setMode, - // setTotalDist: this.setTotalDist, - // setEditing: this.setEditing, - // getUser: this.getUser, - // triggerOnChange: this.triggerOnChange, - // getTitle: this.getTitle, - - // setRouterPoints: this.setRouterPoints, - // setActiveSticker: this.setActiveSticker, - // setLogo: this.setLogo, - // setTitle: this.setTitle, - // setAddress: this.setAddress, - // clearChanged: this.clearChanged, -}); +export const editor = new Editor({}); diff --git a/src/modules/Map.js b/src/modules/Map.js index ce5e935..38b5349 100644 --- a/src/modules/Map.js +++ b/src/modules/Map.js @@ -1,14 +1,14 @@ import { map, tileLayer } from 'leaflet'; -import { providers } from '$constants/providers'; import 'leaflet/dist/leaflet.css'; import 'leaflet-editable'; +import { PROVIDER } from '$config'; export class Map { constructor({ container }) { this.map = map(container, { editable: true }).setView([55.0153275, 82.9071235], 13); - this.tileLayer = tileLayer(providers.default, { + this.tileLayer = tileLayer(PROVIDER, { attribution: 'Независимое Велосообщество', maxNativeZoom: 18, maxZoom: 18, diff --git a/src/redux/user/actions.js b/src/redux/user/actions.js index 5c4d87e..6b946f1 100644 --- a/src/redux/user/actions.js +++ b/src/redux/user/actions.js @@ -1,6 +1,9 @@ import { ACTIONS } from '$redux/user/constants'; export const setUser = user => ({ type: ACTIONS.SET_USER, user }); +export const userLogout = user => ({ type: ACTIONS.USER_LOGOUT }); + + export const setEditing = editing => ({ type: ACTIONS.SET_EDITING, editing }); export const setMode = mode => ({ type: ACTIONS.SET_MODE, mode }); export const setDistance = distance => ({ type: ACTIONS.SET_DISTANCE, distance }); diff --git a/src/redux/user/constants.js b/src/redux/user/constants.js index e069f33..031fdc7 100644 --- a/src/redux/user/constants.js +++ b/src/redux/user/constants.js @@ -1,7 +1,8 @@ export const ACTIONS = { SET_USER: 'SET_USER', - SET_EDITING: 'SET_EDITING', + USER_LOGOUT: 'USER_LOGOUT', + SET_EDITING: 'SET_EDITING', SET_MODE: 'SET_MODE', SET_DISTANCE: 'SET_DISTANCE', SET_CHANGED: 'SET_CHANGED', diff --git a/src/redux/user/sagas.js b/src/redux/user/sagas.js index 556dd51..dbed7f6 100644 --- a/src/redux/user/sagas.js +++ b/src/redux/user/sagas.js @@ -6,6 +6,7 @@ import { getUrlData, pushPath } from '$utils/history'; import { editor } from '$modules/Editor'; import { ACTIONS } from '$redux/user/constants'; import { MODES } from '$constants/modes'; +import { DEFAULT_USER } from '$constants/auth'; const getUser = state => (state.user.user); const getState = state => (state.user); @@ -101,12 +102,40 @@ function* stopEditingSaga() { } } +function* userLogoutSaga() { + const { id } = yield select(getUser); + + if (id === editor.owner) { + editor.owner = null; + } + + yield put(setUser(DEFAULT_USER)); + yield call(generateGuestSaga); +} + +function* setActiveStickerSaga({ activeSticker }) { + yield editor.activeSticker = activeSticker; + return true; +} + +function* setLogoSaga({ logo }) { + const { mode } = yield select(getState); + editor.logo = logo; + + if (mode === MODES.LOGO) { + yield put(setMode(MODES.NONE)); + } +} export function* userSaga() { - // Login - // yield takeLatest(AUTH_ACTIONS.SEND_LOGIN_REQUEST, sendLoginRequestSaga); + // ASYNCHRONOUS!!! :-) + yield takeLatest(REHYDRATE, authChechSaga); yield takeEvery(ACTIONS.SET_MODE, setModeSaga); yield takeEvery(ACTIONS.START_EDITING, startEditingSaga); yield takeEvery(ACTIONS.STOP_EDITING, stopEditingSaga); + + yield takeEvery(ACTIONS.USER_LOGOUT, userLogoutSaga); + yield takeEvery(ACTIONS.SET_ACTIVE_STICKER, setActiveStickerSaga); + yield takeEvery(ACTIONS.SET_LOGO, setLogoSaga); } diff --git a/src/styles/user-button.less b/src/styles/user-button.less index 2c4bfe5..ca74703 100644 --- a/src/styles/user-button.less +++ b/src/styles/user-button.less @@ -1,13 +1,17 @@ .user-bar { - width: 240px; + // width: 160px; .button { width: 100%; } } +.user-bar-guest { + width: 168px; +} .user-button { - width: 100%; + width: 120px; + padding-left: 48px; height: 48px; display: flex; @@ -22,6 +26,9 @@ background-position: 50% 50%; background: rgba(0,0,0,0.3); border-radius: 3px 0 0 3px; + position: absolute; + left: 0; + top: 0; } .user-button-fields {