Merge branch 'develop'

This commit is contained in:
muerwre 2018-09-04 10:55:23 +07:00
commit 9c97c2df34
34 changed files with 1262 additions and 295 deletions

10
package-lock.json generated
View file

@ -10130,6 +10130,11 @@
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
"optional": true
},
"pt-sans-cyrillic": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/pt-sans-cyrillic/-/pt-sans-cyrillic-0.0.4.tgz",
"integrity": "sha512-QbXgUHp5pbSbxbLdfpe5/MzuYPufqv36UMQUUI7QwceaaCJA8NQilysjlexjHLyK0GFv7NB5kl6ZAcIMBBBRXA=="
},
"public-encrypt": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
@ -10209,6 +10214,11 @@
"integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==",
"dev": true
},
"raleway-cyrillic": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/raleway-cyrillic/-/raleway-cyrillic-4.0.2.tgz",
"integrity": "sha1-HcKzrqYwKwhTbs7jGIyS0li4jOE="
},
"ramda": {
"version": "0.24.1",
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",

View file

@ -57,6 +57,8 @@
"leaflet-routing-machine": "muerwre/leaflet-routing-machine#no-osrm-text",
"less": "^3.8.1",
"lodash": "^4.17.10",
"pt-sans-cyrillic": "0.0.4",
"raleway-cyrillic": "^4.0.2",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-hot-loader": "^4.1.1",

View file

@ -5,15 +5,19 @@ import { RouterDialog } from '$components/router/RouterDialog';
import { StickersDialog } from '$components/stickers/StickersDialog';
import { TrashDialog } from '$components/trash/TrashDialog';
import { LogoDialog } from '$components/logo/LogoDialog';
import { SaveDialog } from '$components/save/SaveDialog';
import { CancelDialog } from '$components/save/CancelDialog';
export const EditorDialog = ({
mode, routerPoints, editor, activeSticker, logo
mode, routerPoints, editor, activeSticker, logo, user, title, address,
}) => {
const showDialog = (
mode === MODES.ROUTER
|| (mode === MODES.STICKERS && !activeSticker)
|| mode === MODES.TRASH
|| mode === MODES.LOGO
|| mode === MODES.SAVE
|| mode === MODES.CONFIRM_CANCEL
);
return (
@ -23,6 +27,8 @@ export const EditorDialog = ({
{ mode === MODES.STICKERS && <StickersDialog editor={editor} /> }
{ mode === MODES.TRASH && <TrashDialog editor={editor} /> }
{ mode === MODES.LOGO && <LogoDialog editor={editor} logo={logo} /> }
{ mode === MODES.SAVE && <SaveDialog editor={editor} user={user} title={title} address={address} /> }
{ mode === MODES.CONFIRM_CANCEL && <CancelDialog editor={editor} /> }
</div>
);
};

View file

@ -2,7 +2,7 @@ import React from 'react';
import { MODES } from '$constants/modes';
import classnames from 'classnames';
import { toHours } from '$utils/time';
import { toHours } from '$utils/format';
import { Icon } from '$components/panels/Icon';
import { EditorDialog } from '$components/panels/EditorDialog';
@ -21,9 +21,21 @@ export class EditorPanel extends React.PureComponent {
startLogoMode = () => this.props.editor.changeMode(MODES.LOGO);
startSaveMode = () => this.props.editor.changeMode(MODES.SAVE);
stopEditing = () => {
if (!this.props.changed){
this.props.editor.cancelEditing();
} else {
this.props.editor.changeMode(MODES.CONFIRM_CANCEL);
}
};
startEditing = () => this.props.editor.startEditing();
render() {
const {
mode, routerPoints, editor, totalDistance, estimateTime, activeSticker, logo,
mode, routerPoints, editor, totalDistance, estimateTime, activeSticker, logo, user, editing, title, address, changed,
} = this.props;
return (
@ -35,37 +47,41 @@ export class EditorPanel extends React.PureComponent {
activeSticker={activeSticker}
editor={editor}
logo={logo}
user={user}
title={title}
address={address}
/>
<LogoPreview logo={logo} />
<div className="panel right">
<div className="control-dist">
{totalDistance} км
<Icon icon="icon-cycle" size={32} />
{
<span>{toHours(estimateTime)}</span>
}
</div>
<div className="control-dist">
{changed && '(ch) '}
{totalDistance} км
<Icon icon="icon-cycle" size={32} />
{
<span>{toHours(estimateTime)}</span>
}
</div>
<div className={classnames('panel right', { active: editing })}>
<div className="control-bar">
<button
className={classnames({ active: mode === MODES.ROUTER })}
onClick={this.startRouterMode}
>
<Icon icon="icon-router" />
<Icon icon="icon-route-2" />
</button>
<button
className={classnames({ active: mode === MODES.POLY })}
onClick={this.startPolyMode}
>
<Icon icon="icon-poly" />
<Icon icon="icon-poly-2" />
</button>
<button
className={classnames({ active: mode === MODES.STICKERS })}
onClick={this.startStickerMode}
>
<Icon icon="icon-sticker" />
<Icon icon="icon-sticker-2" />
</button>
</div>
@ -77,31 +93,54 @@ export class EditorPanel extends React.PureComponent {
className={classnames({ active: mode === MODES.SHOTTER })}
onClick={this.startShotterMode}
>
<Icon icon="icon-shooter" />
<Icon icon="icon-shot-2" />
</button>
<button
className={classnames({ active: mode === MODES.TRASH })}
onClick={this.startTrashMode}
>
<Icon icon="icon-trash" />
<Icon icon="icon-trash-2" />
</button>
<button
className={classnames({ active: mode === MODES.LOGO })}
onClick={this.startLogoMode}
>
<Icon icon="icon-logo" />
</button>
<button
className="highlighted"
>
<span>СХОРОНИТЬ</span>
<Icon icon="icon-save" />
<Icon icon="icon-logo-2" />
</button>
</div>
<div className="control-sep" />
<div className="control-bar">
<button
className="highlighted cancel"
onClick={this.stopEditing}
>
<span>ОТМЕНА</span>
</button>
<button
className="primary"
onClick={this.startSaveMode}
>
<span>СХОРОНИТЬ</span>
<Icon icon="icon-save-2" />
</button>
</div>
</div>
<div className={classnames('panel right', { active: !editing })}>
<div className="control-bar">
<button className="primary single" onClick={this.startEditing}>
<Icon icon="icon-route-2" />
<span>
РЕДАКТИРОВАТЬ
</span>
</button>
</div>
</div>
</div>
);

View file

@ -56,13 +56,13 @@ export class UserPanel extends React.PureComponent {
render() {
const {
props: { user, userLogout },
props: { user, userLogout, editor, editing },
state: { menuOpened },
} = this;
return (
<div>
<div className="panel">
<div className="panel active">
<div className="user-panel">
{
!user || user.role === ROLES.guest

View file

@ -0,0 +1,39 @@
import React from 'react';
import { MODES } from '$constants/modes';
export class CancelDialog extends React.Component {
cancel = () => {
this.props.editor.stopEditing();
};
proceed = () => {
this.props.editor.changeMode(MODES.NONE);
};
save = () => {
this.props.editor.changeMode(MODES.SAVE);
};
render() {
return (
<div className="helper cancel-helper">
<div className="helper__text">
<div className="big white">Изменения не сохранены!</div>
<div className="small gray">Закрыть редактор?</div>
</div>
<div className="helper__buttons button-group">
<div className="button router-helper__button" onClick={this.cancel}>
Закрыть
</div>
<div className="button success router-helper__button" onClick={this.proceed}>
Продолжить
</div>
<div className="button primary router-helper__button" onClick={this.save}>
Сохранить
</div>
</div>
</div>
);
}
}

View file

@ -0,0 +1,139 @@
import React from 'react';
import { getUrlData, pushPath } from '$utils/history';
import { toTranslit } from '$utils/format';
import { TIPS } from '$constants/tips';
import { MODES } from '$constants/modes';
import { postMap } from '$utils/api';
import classnames from 'classnames';
export class SaveDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
address: props.address || '',
title: props.title || '',
error: '',
sending: false,
finished: false,
overwriting: false,
};
}
getAddress = () => {
const { path } = getUrlData();
const { title, address } = this.state;
return toTranslit(address.trim()) || toTranslit(title.trim()) || toTranslit(path.trim());
};
setTitle = ({ target: { value } }) => this.setState({ title: (value || '') });
setAddress = ({ target: { value } }) => this.setState({ address: (value || '') });
cancelSaving = () => this.props.editor.changeMode(MODES.NONE);
sendSaveRequest = (e, force = false) => {
const { route, stickers } = this.props.editor.dumpData();
const { title } = this.state;
const { id, token } = this.props.user;
postMap({
id,
token,
route,
stickers,
title,
force,
address: this.getAddress(),
}).then(this.parseResponse).catch(console.warn);
};
forceSaveRequest = e => this.sendSaveRequest(e, true);
parseResponse = data => {
if (data.success) return this.setSuccess(data);
if (data.mode === 'overwriting') return this.setOverwrite(data.description);
return this.setError(data.description);
};
setSuccess = ({ address, description }) => {
pushPath(`/${address}/edit`);
console.log('addr?', address);
this.props.editor.setAddress(address);
this.props.editor.owner = this.props.user.id;
this.props.editor.setInitialData();
this.setState({
error: description, finished: true, sending: true, overwriting: false
});
};
setOverwrite = error => this.setState({
error, finished: false, sending: true, overwriting: true
});
setError = error => this.setState({
error, finished: false, sending: true, overwriting: false
});
render() {
const {
title, error, finished, overwriting, sending
} = this.state;
const { host } = getUrlData();
return (
<div className="helper save-helper">
<div className="save-title">
<div className="save-title-input">
<label className="save-title-label">Название</label>
<input type="text" value={title} onChange={this.setTitle} autoFocus />
</div>
</div>
<div className="save-description">
<div className="save-address-input">
<label className="save-address-label">http://{host}/</label>
<input type="text" value={this.getAddress().substr(0, 32)} onChange={this.setAddress} />
</div>
<div className="save-text">
{
error || TIPS.SAVE_INFO
}
</div>
<div className="save-buttons">
<div className="save-buttons-text" />
<div className={classnames({ 'button-group': !finished })}>
{ !finished &&
<div className="button" onClick={this.cancelSaving}>Отмена</div>
}
{
(!sending || (sending && !overwriting && !finished)) &&
<div className="button primary" onClick={this.sendSaveRequest}>Сохранить</div>
}
{
sending && overwriting &&
<div className="button danger" onClick={this.forceSaveRequest}>Перезаписать</div>
}
{ finished &&
<div className="button success" onClick={this.cancelSaving}>Отлично, спасибо!</div>
}
</div>
</div>
</div>
</div>
);
}
}

View file

@ -1,5 +1,8 @@
export const SERVER = 'http://alpha-map.vault48.org';
export const API = {
COMPOSE: `${SERVER}/engine/composerOrchid.php`,
GET_GUEST: `${SERVER}/engine/auth.php`,
GET_GUEST: `${SERVER}/engine/authOrchid.php`,
CHECK_TOKEN: `${SERVER}/engine/authOrchid.php`,
GET_MAP: `${SERVER}/engine/authOrchid.php`,
POST_MAP: `${SERVER}/engine/authOrchid.php?action=store`,
};

View file

@ -10,6 +10,8 @@ export const DEFAULT_USER = {
role: ROLES.guest,
routes: [],
success: false,
id: null,
token: null,
userdata: {
name: '',
agent: '',

View file

@ -6,4 +6,6 @@ export const MODES = {
TRASH: 'TRASH',
NONE: 'NONE',
LOGO: 'LOGO',
SAVE: 'SAVE',
CONFIRM_CANCEL: 'CONFIRM_CANCEL'
};

3
src/constants/tips.js Normal file
View file

@ -0,0 +1,3 @@
export const TIPS = {
SAVE_INFO: 'Вы можете задать своё название маршрута и адрес, по которому он будет доступен.'
};

View file

@ -6,13 +6,15 @@ import { Fills } from '$components/Fills';
import { DEFAULT_LOGO } from '$constants/logos';
import { UserLocation } from '$components/UserLocation';
import { DEFAULT_USER } from '$constants/auth';
import { getGuestToken, checkUserToken } from '$utils/api';
import { getGuestToken, checkUserToken, getStoredMap } from '$utils/api';
import { storeData, getData } from '$utils/storage';
import { UserPanel } from '$components/panels/UserPanel';
import { getUrlData, pushPath } from '$utils/history';
export class App extends React.Component {
state = {
mode: 'none',
editing: false,
logo: DEFAULT_LOGO,
routerPoints: 0,
totalDistance: 0,
@ -21,12 +23,68 @@ export class App extends React.Component {
user: {
...DEFAULT_USER,
},
title: '',
address: '',
changed: false,
};
componentDidMount() {
this.authInit();
window.editor = this.editor;
}
mapInit = () => {
const { path, mode } = getUrlData();
if (path) {
getStoredMap({ name: path })
.then(this.setDataOnLoad)
.then(() => {
if (mode && mode === 'edit') {
this.editor.startEditing();
} else {
this.editor.stopEditing();
}
})
.catch(this.startEmptyEditor);
} else {
// this.hideLoader();
this.startEmptyEditor();
}
};
startEmptyEditor = () => {
const { user } = this.state;
if (!user || !user.random_url || !user.id) return;
pushPath(`/${user.random_url}/edit`);
this.editor.owner = user.id;
this.editor.startEditing();
this.hideLoader();
this.clearChanged();
};
setTitle = title => this.setState({ title });
setAddress = address => {
console.log('SAT', address);
this.setState({ address });
};
getTitle = () => this.state.title;
setDataOnLoad = data => {
this.clearChanged();
this.editor.setData(data);
this.hideLoader();
};
hideLoader = () => {
document.getElementById('loader').style.opacity = 0;
document.getElementById('loader').style.pointerEvents = 'none';
};
setMode = mode => {
this.setState({ mode });
};
@ -49,6 +107,23 @@ export class App extends React.Component {
this.setState({ logo });
};
setEditing = editing => {
this.setState({ editing });
};
getUser = () => this.state.user;
triggerOnChange = () => {
if (!this.state.editing) return;
console.log('CHANGED!');
this.setState({ changed: true });
};
clearChanged = () => {
console.log('clearing');
this.setState({ changed: false });
};
editor = new Editor({
container: 'map',
mode: this.state.mode,
@ -57,29 +132,41 @@ export class App extends React.Component {
setTotalDist: this.setTotalDist,
setActiveSticker: this.setActiveSticker,
setLogo: this.setLogo,
setEditing: this.setEditing,
setTitle: this.setTitle,
setAddress: this.setAddress,
getUser: this.getUser,
triggerOnChange: this.triggerOnChange,
clearChanged: this.clearChanged,
getTitle: this.getTitle,
});
authInit = () => {
const user = this.getUserData();
const { id, token } = (user || {});
const fallback = () => getGuestToken({ callback: this.setUser });
if (id && token) {
checkUserToken({
callback: this.setUser,
fallback,
id,
token
});
})
.then(this.setUser)
.then(this.mapInit);
} else {
getGuestToken({ callback: fallback });
getGuestToken()
.then(this.setUser)
.then(this.mapInit);
}
};
setUser = user => {
if (!user.token || !user.id) return;
if (this.state.user.id === this.editor.owner) {
this.editor.owner = user.id;
}
this.setState({
user: {
...DEFAULT_USER,
@ -94,25 +181,25 @@ export class App extends React.Component {
storeData('user', this.state.user);
};
getUserData = () => {
return getData('user') || null;
};
getUserData = () => getData('user') || null;
userLogout = () => {
if (this.state.user.id === this.editor.owner) {
this.editor.owner = null;
}
//
this.setState({
user: {
...DEFAULT_USER,
}
user: DEFAULT_USER,
});
this.storeUserData();
setTimeout(this.storeUserData, 0);
};
render() {
const {
editor,
state: {
mode, routerPoints, totalDistance, estimateTime, activeSticker, logo, user,
mode, routerPoints, totalDistance, estimateTime, activeSticker, logo, user, editing, title, address, changed,
},
} = this;
@ -124,6 +211,7 @@ export class App extends React.Component {
<UserLocation editor={editor} />
<UserPanel
editor={editor}
user={user}
setUser={this.setUser}
userLogout={this.userLogout}
@ -138,6 +226,10 @@ export class App extends React.Component {
activeSticker={activeSticker}
logo={logo}
user={user}
editing={editing}
title={title}
address={address}
changed={changed}
/>
</div>
);

View file

@ -9,9 +9,21 @@
<link rel="shortcut icon" href="/favicon.png?wd" type="image/png">
<meta property="og:image" content="/misc/vk_preview.png" />
<meta content="/misc/vk_preview.png">
<style>
#loader {
position: fixed;
background: #576066;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
transition: opacity 1s;
}
</style>
</head>
<body>
<section id="loader"></section>
<section id="index"></section>
<div id="map" />
<section id="map"></section>
</body>

View file

@ -5,6 +5,8 @@ import ReactDOM from 'react-dom';
import { App } from '$containers/App';
import '$styles/main.less';
import 'raleway-cyrillic';
// import { Provider } from 'react-redux';
// import { ConnectedRouter } from 'react-router-redux';
// import { PersistGate } from 'redux-persist/integration/react';

View file

@ -6,6 +6,9 @@ import { Router } from '$modules/Router';
import { Shotter } from '$modules/Shotter';
import { DEFAULT_LOGO } from '$constants/logos';
import { parseStickerAngle, parseStickerStyle } from '$utils/import';
import { getUrlData, pushPath } from '$utils/history';
export class Editor {
constructor({
container,
@ -15,19 +18,27 @@ export class Editor {
setTotalDist,
setActiveSticker,
setLogo,
setEditing,
setTitle,
setAddress,
getUser,
triggerOnChange,
clearChanged,
getTitle,
}) {
this.logo = DEFAULT_LOGO;
this.owner = null;
this.map = new Map({ container });
this.initialData = {};
const {
lockMapClicks, routerMoveStart, changeMode, pushPolyPoints, map: { map }
} = this;
this.poly = new Poly({
map, routerMoveStart, lockMapClicks, setTotalDist
map, routerMoveStart, lockMapClicks, setTotalDist, triggerOnChange
});
this.stickers = new Stickers({ map, lockMapClicks });
this.stickers = new Stickers({ map, lockMapClicks, triggerOnChange });
this.router = new Router({
map, lockMapClicks, setRouterPoints, changeMode, pushPolyPoints
});
@ -49,6 +60,9 @@ export class Editor {
},
[MODES.TRASH]: {
toggle: this.clearAll,
},
[MODES.CONFIRM_CANCEL]: {
toggle: this.cancelEditing,
}
};
@ -58,10 +72,16 @@ export class Editor {
};
this.activeSticker = null;
this.clearChanged = clearChanged;
this.setActiveSticker = setActiveSticker;
this.setLogo = setLogo;
this.setMode = setMode;
this.setEditing = setEditing;
this.setTitle = setTitle;
this.setAddress = setAddress;
this.getUser = getUser;
this.mode = mode;
this.getTitle = getTitle;
map.addEventListener('mouseup', this.onClick);
map.addEventListener('dragstart', () => lockMapClicks(true));
@ -158,11 +178,118 @@ export class Editor {
this.setSticker(null);
this.changeMode(MODES.NONE);
this.clearChanged();
};
changeLogo = logo => {
this.logo = logo;
this.setLogo(logo);
this.changeMode(MODES.NONE);
};
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 (stickers) {
stickers.map(sticker => this.stickers.createSticker({
latlng: sticker.latlng,
angle: parseStickerAngle({ sticker, version }),
sticker: parseStickerStyle({ sticker, version }),
}));
}
if (owner) {
this.owner = owner;
}
if (!route || route.length <= 1) return;
const bounds = this.poly.poly.getBounds();
if (Object.values(bounds)) this.map.map.fitBounds(bounds);
};
setInitialData = () => {
const { path } = getUrlData();
const { id } = this.getUser();
const { route, stickers } = this.dumpData();
this.initialData = {
version: 2,
title: this.getTitle(),
owner: this.owner,
address: this.owner === id ? path : null,
path: path,
route,
stickers,
};
};
startEditing = () => {
const { path } = getUrlData();
const { random_url, id } = this.getUser();
this.setInitialData();
const url = (this.owner && this.owner === id) ? path : random_url;
pushPath(`/${url}/edit`);
if (this.poly.latlngs && this.poly.latlngs.length > 1) this.poly.poly.enableEdit();
this.stickers.startEditing();
this.setEditing(true);
console.log(this.initialData);
};
stopEditing = () => {
const { path } = getUrlData();
pushPath(`/${(this.initialData && this.initialData.path) || path}`);
this.changeMode(MODES.NONE);
this.poly.poly.disableEdit();
this.stickers.stopEditing();
this.setEditing(false);
};
cancelEditing = () => {
this.stopEditing();
console.log('trying to set initial data');
if (this.hasEmptyHistory()) {
this.clearAll();
this.startEditing();
} else {
this.setData(this.initialData);
}
this.clearChanged();
};
dumpData = () => ({
route: this.poly.dumpData(),
stickers: this.stickers.dumpData(),
});
isEmpty = () => {
const { route, stickers } = this.dumpData();
return (route.length > 1 && stickers.length > 0);
};
hasEmptyHistory = () => {
const { route, stickers } = this.initialData;
return (!route || route.length < 1) && (!stickers || stickers.length <= 0);
}
}

View file

@ -12,7 +12,7 @@ const polyStyle = {
export class Poly {
constructor({
map, routerMoveStart, lockMapClicks, setTotalDist
map, routerMoveStart, lockMapClicks, setTotalDist, triggerOnChange,
}) {
this.poly = L.polyline([], polyStyle);
@ -23,6 +23,7 @@ export class Poly {
this.routerMoveStart = routerMoveStart;
this.setTotalDist = setTotalDist;
this.triggerOnChange = triggerOnChange;
this.lockMapClicks = lockMapClicks;
this.bindEvents();
@ -63,7 +64,10 @@ export class Poly {
this.setTotalDist(kilometers);
this.routerMoveStart();
this.drawArrows();
if (coords.length > 1) this.triggerOnChange();
};
bindEvents = () => {
@ -124,6 +128,13 @@ export class Poly {
this.lockMapClicks(true);
};
setPoints = latlngs => {
if (!latlngs || latlngs.length <= 1) return;
this.poly.setLatLngs(latlngs);
this.updateMarks();
};
pushPoints = latlngs => {
const { map } = this;
const simplified = simplify({ map, latlngs });
@ -141,8 +152,11 @@ export class Poly {
clearAll = () => {
this.poly.setLatLngs([]);
this.poly.disableEdit();
this.updateMarks();
};
clearArrows = () => this.arrows.clearLayers();
dumpData = () => this.latlngs;
}

View file

@ -7,11 +7,15 @@ import stickers from '$sprites/stickers.svg';
export class Sticker {
constructor({
latlng, deleteSticker, map, lockMapClicks, sticker
latlng, deleteSticker, map, lockMapClicks, sticker, triggerOnChange, angle = 2.2
}) {
this.angle = 2.2;
this.latlng = latlng;
this.angle = angle;
this.isDragging = false;
this.map = map;
this.sticker = sticker;
this.editable = true;
this.triggerOnChange = triggerOnChange;
this.deleteSticker = deleteSticker;
this.lockMapClicks = lockMapClicks;
@ -37,18 +41,23 @@ export class Sticker {
className: 'sticker-container',
});
this.sticker = marker(latlng, { icon: mark });
this.marker = marker(latlng, { icon: mark });
this.setAngle(this.angle);
this.setAngle(angle);
this.stickerImage.addEventListener('mousedown', this.onDragStart);
this.stickerImage.addEventListener('mouseup', this.onDragStop);
this.element.addEventListener('mouseup', this.preventPropagations);
this.stickerDelete.addEventListener('click', this.onDelete);
this.marker.addEventListener('dragend', this.triggerOnChange);
this.triggerOnChange();
}
onDelete = () => {
this.triggerOnChange();
if (!this.isDragging) this.deleteSticker(this);
};
@ -56,7 +65,7 @@ export class Sticker {
this.preventPropagations(e);
this.isDragging = true;
this.sticker.disableEdit();
this.marker.disableEdit();
this.lockMapClicks(true);
@ -74,8 +83,9 @@ export class Sticker {
onDragStop = e => {
this.preventPropagations(e);
this.triggerOnChange();
this.isDragging = false;
this.sticker.enableEdit();
this.marker.enableEdit();
window.removeEventListener('mousemove', this.onDrag);
window.removeEventListener('mouseup', this.onDragStop);
@ -89,6 +99,7 @@ export class Sticker {
};
estimateAngle = e => {
console.log('est');
const { x, y } = this.element.getBoundingClientRect();
const { pageX, pageY } = e;
this.angle = Math.atan2((y - pageY), (x - pageX));
@ -97,8 +108,6 @@ export class Sticker {
};
setAngle = angle => {
// $(active_sticker.container).css('left',6+x-parseInt(active_sticker.ctrl.css('left'))).css('top',6+y-parseInt(active_sticker.ctrl.css('top')));
//
const rad = 44;
const mrad = 76;
const x = ((Math.cos(angle + 3.14) * rad) - 30);
@ -114,7 +123,7 @@ export class Sticker {
this.stickerDelete.style.top = ay;
this.stickerArrow.style.transform = `rotate(${angle + 3.14}rad)`;
}
};
generateStickerSVG = sticker => (
`
@ -122,5 +131,19 @@ export class Sticker {
<use xlink:href="${stickers}#sticker-${sticker}" x="0" y="0" width="64" height="64" />
</svg>
`
)
);
dumpData = () => ({
angle: this.angle,
latlng: { ...this.marker.getLatLng() },
sticker: this.sticker,
});
stopEditing = () => {
this.element.className = 'sticker-container inactive';
};
startEditing = () => {
this.element.className = 'sticker-container';
};
}

View file

@ -2,9 +2,10 @@ import { layerGroup } from 'leaflet';
import { Sticker } from '$modules/Sticker';
export class Stickers {
constructor({ map, lockMapClicks }) {
constructor({ map, lockMapClicks, triggerOnChange }) {
this.map = map;
this.layer = layerGroup();
this.triggerOnChange = triggerOnChange;
this.lockMapClicks = lockMapClicks;
this.stickers = [];
@ -19,18 +20,20 @@ export class Stickers {
// this.createSticker({ latlng });
// };
createSticker = ({ latlng, sticker }) => {
createSticker = ({ latlng, sticker, angle = 2.2 }) => {
const marker = new Sticker({
latlng,
angle,
deleteSticker: this.deleteStickerByReference,
map: this.map,
lockMapClicks: this.lockMapClicks,
sticker,
triggerOnChange: this.triggerOnChange,
});
this.stickers.push(marker);
marker.sticker.addTo(this.map);
marker.sticker.enableEdit();
marker.marker.addTo(this.map);
marker.marker.enableEdit();
};
deleteStickerByReference = ref => {
@ -38,7 +41,7 @@ export class Stickers {
if (index < 0) return;
this.map.removeLayer(ref.sticker);
this.map.removeLayer(ref.marker);
this.stickers.splice(index, 1);
};
@ -48,5 +51,15 @@ export class Stickers {
this.deleteStickerByReference(sticker);
return true;
});
};
dumpData = () => this.stickers.map(sticker => sticker.dumpData());
startEditing = () => {
this.stickers.map(sticker => sticker.startEditing());
}
stopEditing = () => {
this.stickers.map(sticker => sticker.stopEditing());
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 B

After

Width:  |  Height:  |  Size: 707 B

Before After
Before After

View file

@ -138,6 +138,73 @@
<path id="path5845" fill="none" fill-rule="evenodd" stroke="#fff" stroke-width="2.5" d="M20.948 16.134h4.243"/>
<path id="path5847" fill="none" fill-rule="evenodd" stroke="#fff" stroke-width="2.5" d="M6.63 16.134h4.242"/>
</g>
<g id="icon-shot-2" stroke="none" transform="scale(1.1) translate(-2 -2)">
<path id="rect5819" stroke-opacity=".941" stroke-width=".265" d="M0 0h32v32H0z" fill="black"/>
<rect id="rect6617" width="21" height="13.89" x="6.25" y="9.833" fill="#fff" rx="2" ry="2"/>
<path id="rect6619" fill="#fff" stroke-width="1.979" d="M13.812 7.009h6.282c.45 0 .749.528 1.147 1.039l3.096 3.974c.398.51-3.793 6.989-4.243 6.989h-6.282c-.45 0-4.889-6.747-4.475-7.24l3.19-3.802c.415-.493.836-.96 1.285-.96z"/>
<circle id="path6621" cx="16.627" cy="16.311" r="6.158" fill="black"/>
<circle id="circle6628" cx="16.627" cy="16.311" r="3.533" fill="#fff" />
</g>
<g id="icon-trash-2" stroke="none">
<g transform="translate(0 -3) scale(3.82445) scale(1.1) rotate(45 4 4)">
<rect id="rect4966" width="3.125" height="2.893" x="2.671" y="3.751" fill="#fff" rx=".36" ry=".403"/>
<rect id="rect4968" width="3.663" height=".87" x="2.401" y="2.423" fill="#fff" rx=".435" ry=".435"/>
<rect id="rect4970" width="2.924" height="1.306" x="2.771" y="1.698" fill="#fff" rx=".653" ry=".653"/>
<rect id="rect4972" width="1.933" height=".523" x="3.266" y="2.114" fill="black" rx=".261" ry=".261"/>
<g id="g4918" stroke-width=".523" transform="matrix(1.3497 0 0 1.3497 -1.613 -1.674)">
<rect id="rect4912" width="2.059" height=".425" x="5.622" y=".289" rx=".237" ry=".21" transform="rotate(45)" fill="black"/>
<rect id="rect4914" width="2.047" height=".389" x="-.491" y="-6.803" rx=".237" ry=".195" transform="rotate(135)" fill="black"/>
</g>
</g>
</g>
<g id="icon-logo-2" transform="scale(1.1) translate(-1 -2)">
<path id="rect5611" stroke-opacity=".941" stroke-width=".265" d="M0 0h32v32H0z" fill="black" stroke="none"/>
<g id="g5792" fill="none" stroke="#fff" stroke-width="2.37" transform="matrix(.84382 0 0 .84382 4.366 1.93)">
<path id="path5774" fill-rule="evenodd" d="M22.399 10.08c-5.964-3.689-11.363-3.732-17.222 0 .155 4.418-.316 11.882 8.61 15.957 9.228-4.38 8.532-11.89 8.612-15.957z"/>
</g>
<g id="g8284" fill="#fff" stroke-width="3.052" transform="matrix(.40236 0 0 .40236 10.45 8.978)">
<path d="M22.399 10.08c-5.964-3.689-11.363-3.732-17.222 0 .155 4.418-.316 11.882 8.61 15.957 9.228-4.38 8.532-11.89 8.612-15.957z" stroke="none" />
</g>
</g>
<g id="icon-sticker-2" transform="scale(1.1) translate(-3 -2)" stroke="none">
<g id="g4867" transform="matrix(.94996 0 0 .94996 -.16 .083)">
<path id="path4859" fill="#fff" fill-rule="evenodd" stroke-width=".767" d="M13.47 22.847l3.045 5.275 3.12-5.405z"/>
<circle id="path4863" cx="16.552" cy="14.98" r="8.712" fill="#fff" stroke-width="1.851"/>
<circle id="circle4869" cx="16.552" cy="14.98" r="5" fill="black" />
</g>
</g>
<g id="icon-route-2" transform="scale(1.1) translate(32 -2)" stroke="none">
<g fill="white">
<circle id="path5642" cx="-24.357" cy="23.576" r="2.507" fill="#fff" stroke-width="4.363"/>
<path id="path5644" fill="none" fill-rule="evenodd" stroke="#fff" stroke-width="2.621" d="M-24.289 21.588V10.61c0-4.22 6.62-4.194 6.62 0V21.42c0 4.011 6.828 4.027 6.828 0v-10.98"/>
<circle id="circle5646" cx="-10.93" cy="8.462" r="2.507" fill="#fff" stroke-width="4.363"/>
</g>
</g>
<g id="icon-poly-2" transform="scale(1.1) translate(-3 -2)" stroke="none">
<g fill="white">
<path id="path6375" fill="none" fill-rule="evenodd" stroke="#fff" stroke-linejoin="round" stroke-width="2.387" d="M7.924 12.991l8.569-4.989-6.55 14.587 13.762-7.974-3.958 9.12"/>
<circle id="path6363" cx="14.711" cy="-4.523" r="2.387" fill="#fff" stroke-width="5.304" transform="rotate(75)"/>
<circle id="circle6367" cx="12.17" cy="-13.883" r="2.387" fill="#fff" stroke-width="5.304" transform="rotate(75)"/>
<circle id="circle6371" cx="20.342" cy="-19.194" r="2.387" fill="#fff" stroke-width="5.304" transform="rotate(75)"/>
<circle id="circle6373" cx="24.138" cy="-3.701" r="2.387" fill="#fff" stroke-width="5.304" transform="rotate(75)"/>
<circle id="circle6774" cx="27.918" cy="-13.025" r="2.387" fill="#fff" stroke-width="5.304" transform="rotate(75)"/>
</g>
</g>
<g id="icon-save-2" transform="scale(1.1) translate(-3 -2)" stroke="none">
<g fill="white">
<path id="rect4766" stroke-opacity=".941" stroke-width=".265" d="M0 0h32v32H0z" fill="black"/>
<path id="rect4986" fill="#fff" stroke-opacity=".941" stroke-width="2.477" d="M6.894 8.502v15.455h18.212V11.402H14.042v-2.9z"/>
<path id="path7854" fill="none" fill-rule="evenodd" stroke="#000" stroke-width="2.735" d="M10.923 16.586l4.19 4.19 6.606-6.607" transform="scale(0.9) translate(2 2)"/>
</g>
</g>
</svg>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before After
Before After

View file

@ -7,6 +7,7 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="600"
@ -17,7 +18,29 @@
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="icons_draft.svg">
<defs
id="defs2" />
id="defs2">
<linearGradient
inkscape:collect="always"
id="linearGradient8806">
<stop
style="stop-color:#2ad4ff;stop-opacity:1;"
offset="0"
id="stop8802" />
<stop
style="stop-color:#5a2ca0;stop-opacity:1"
offset="1"
id="stop8804" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient8806"
id="linearGradient8808"
x1="-60.605404"
y1="-51.468327"
x2="-51.154362"
y2="-34.093327"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#333333"
@ -25,9 +48,9 @@
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="-83.901329"
inkscape:cy="9.506994"
inkscape:zoom="5.6568542"
inkscape:cx="-59.116412"
inkscape:cy="72.422571"
inkscape:document-units="px"
inkscape:current-layer="svg8"
showgrid="false"
@ -38,7 +61,7 @@
inkscape:window-maximized="1"
units="px"
inkscape:showpageshadow="false"
inkscape:snap-global="false" />
inkscape:snap-global="true" />
<metadata
id="metadata5">
<rdf:RDF>
@ -47,7 +70,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -58,7 +81,7 @@
transform="translate(0,-288.53332)" />
<g
id="icon-save"
transform="translate(-64)">
transform="translate(-192)">
<rect
y="0"
x="0"
@ -67,170 +90,101 @@
id="rect4766"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.49093914;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
d="M 6.84375,8.458984 V 11.375 13.416016 24 h 18.3125 V 11.375 h -11.125 V 8.458984 Z"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.47715282;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
d="m 6.8944259,8.5019904 v 2.8998766 2.02972 10.525407 H 25.105575 V 11.401867 H 14.042146 V 8.5019904 Z"
id="rect4986"
inkscape:connector-curvature="0" />
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.60305977;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4991"
width="2.7400389"
height="5.038136"
x="14.629981"
y="14.410719"
rx="0"
ry="0" />
<path
sodipodi:type="star"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="path4993"
sodipodi:sides="3"
sodipodi:cx="12.551145"
sodipodi:cy="17.239145"
sodipodi:r1="4.9819989"
sodipodi:r2="2.4313235"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.865682,19.730145 -4.314537,-0.05968 -4.314538,0.05968 2.20895,-3.706661 2.105588,-3.766338 2.105588,3.766337 z"
transform="matrix(0.45902766,-0.40627691,0.79505923,0.23456409,-3.4674638,21.088123)" />
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.73455501;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 10.922683,16.585837 4.189515,4.189516 6.606544,-6.606544"
id="path7854"
inkscape:connector-curvature="0" />
</g>
<g
id="g4982"
transform="translate(-32)">
id="icon-trash-2"
transform="translate(-96)">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4964"
width="32"
height="32"
x="0"
x="-32"
y="0" />
<rect
y="6"
x="-26"
height="20"
width="20"
id="rect4892"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#ff5555;stroke-width:0.16536458;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
<g
transform="matrix(3.7795278,0,0,3.7795278,0.00170832,-0.00171071)"
transform="matrix(3.8244521,0,0,3.8244521,-32.188451,-0.33217385)"
id="g4980">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79375005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.84404761;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4966"
width="2.9232607"
height="2.9232607"
x="2.782944"
y="3.6257474" />
width="3.1245625"
height="3.0925183"
x="2.6705999"
y="3.7506495"
rx="0.35952863"
ry="0.40317342" />
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79375005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.87442839;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4968"
width="3.5079126"
height="0.74835467"
x="2.4789248"
y="2.5967598" />
width="3.6630149"
height="0.86975819"
x="2.4013736"
y="2.422653"
rx="0.43487909"
ry="0.43487909" />
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79375005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.1561358;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4970"
width="1.4733232"
height="0.8652851"
x="3.4377544"
y="1.9185632" />
width="2.9243309"
height="1.3062081"
x="2.7707155"
y="1.6977544"
rx="0.65310407"
ry="0.65310407" />
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.68426704;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.14137733;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4972"
width="0.63142425"
height="0.38621464"
x="3.8587039"
y="2.2499807" />
<rect
y="3.9063804"
x="3.1337352"
height="2.3152225"
width="0.46772167"
id="rect4974"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.44191849;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.40540838;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4976"
width="0.44433555"
height="2.3152225"
x="-4.5369005"
y="3.9063804"
transform="scale(-1,1)" />
<rect
y="3.9063804"
x="4.95785"
height="2.3152225"
width="0.44433564"
id="rect4978"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.4054085;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
width="1.9327896"
height="0.52264619"
x="3.2664864"
y="2.1137509"
rx="0.26132309"
ry="0.26132309" />
<g
id="g4918"
transform="matrix(1.3497059,0,0,1.3497059,-1.6126065,-1.4740344)">
<rect
transform="rotate(45)"
y="0.28946143"
x="5.6217303"
height="0.4254922"
width="2.0591187"
id="rect4912"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52295071;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
rx="0.23696205"
ry="0.20971909" />
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.52295071;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4914"
width="2.0470104"
height="0.38916832"
x="-0.49102783"
y="-6.8034959"
transform="rotate(135)"
rx="0.23696205"
ry="0.19458416" />
</g>
</g>
</g>
<g
id="g5188"
transform="translate(-96)">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect5180"
width="32"
height="32"
x="0"
y="0" />
<g
id="g5322"
transform="matrix(0.04494207,0,0,0.04494207,7.0655171,7.0654393)"
style="fill:#ffffff">
<path
id="path5267"
d="m 313.1,147.875 c -6.057,0 -11.962,0.654 -17.661,1.871 l -15.805,-53.435 37.842,-2.565 c 4.447,-0.301 8.487,2.613 9.602,6.932 0.689,2.671 0.161,5.488 -1.45,7.728 -1.611,2.24 -4.113,3.638 -6.865,3.834 l -9.126,0.652 c -3.581,0.256 -6.276,3.366 -6.02,6.947 0.256,3.581 3.361,6.289 6.947,6.02 l 9.126,-0.652 c 6.611,-0.472 12.623,-3.829 16.493,-9.21 3.87,-5.382 5.14,-12.148 3.484,-18.566 C 336.99,87.056 327.291,80.067 316.598,80.777 l -45.936,3.114 c -1.969,0.134 -3.77,1.154 -4.896,2.773 -1.127,1.62 -1.457,3.663 -0.897,5.556 l 6.405,21.656 H 145.477 l -6.316,-12 H 155.5 c 3.59,0 6.5,-2.91 6.5,-6.5 0,-3.59 -2.91,-6.5 -6.5,-6.5 h -47 c -3.59,0 -6.5,2.91 -6.5,6.5 0,3.59 2.91,6.5 6.5,6.5 h 16.086 l 9.542,18.349 -18.836,33.485 c -9.549,-3.751 -19.929,-5.834 -30.792,-5.834 -46.593,0 -84.5,37.906 -84.5,84.5 0,46.594 37.907,84.5 84.5,84.5 44.404,0 80.892,-34.436 84.225,-78 0,0 31.695,0 31.776,0 2.235,0 4.32,-1.15 5.511,-3.055 l 68.779,-110.047 8.185,27.672 c -31.758,12.162 -54.376,42.945 -54.376,78.93 0,46.594 37.907,84.5 84.5,84.5 46.593,0 84.5,-37.906 84.5,-84.5 0,-46.594 -37.907,-84.501 -84.5,-84.501 z m -228.6,156 c -39.425,0 -71.5,-32.075 -71.5,-71.5 0,-39.425 32.075,-71.5 71.5,-71.5 8.549,0 16.75,1.513 24.355,4.276 l -31.482,55.968 c -3.726,2.365 -6.206,6.516 -6.206,11.256 0,7.363 5.969,13.333 13.333,13.333 5.002,0 9.354,-2.759 11.636,-6.833 h 59.556 c -3.297,36.388 -33.959,65 -71.192,65 z m 11.636,-78 c -0.99,-1.769 -2.37,-3.285 -4.025,-4.439 l 28.528,-50.717 c 19.37,11.397 32.922,31.647 35.052,55.156 z m 72.589,0 C 166.555,197.51 150.332,173.03 127.01,159.393 l 14.327,-25.471 48.396,91.953 z m 32.258,-6.538 -48.665,-92.462 H 258.772 Z M 313.1,303.875 c -39.425,0 -71.5,-32.075 -71.5,-71.5 0,-30.093 18.697,-55.885 45.077,-66.418 l 16.89,57.105 c -2.348,2.403 -3.8,5.687 -3.8,9.313 0,7.363 5.969,13.333 13.333,13.333 7.364,0 13.333,-5.97 13.333,-13.333 0,-6.354 -4.449,-11.661 -10.399,-12.999 l -16.895,-57.123 c 4.518,-0.897 9.184,-1.378 13.962,-1.378 39.425,0 71.5,32.075 71.5,71.5 0,39.425 -32.076,71.5 -71.501,71.5 z"
inkscape:connector-curvature="0"
style="fill:#ffffff;stroke-width:445.01733398;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g5269"
style="fill:#ffffff" />
<g
id="g5271"
style="fill:#ffffff" />
<g
id="g5273"
style="fill:#ffffff" />
<g
id="g5275"
style="fill:#ffffff" />
<g
id="g5277"
style="fill:#ffffff" />
<g
id="g5279"
style="fill:#ffffff" />
<g
id="g5281"
style="fill:#ffffff" />
<g
id="g5283"
style="fill:#ffffff" />
<g
id="g5285"
style="fill:#ffffff" />
<g
id="g5287"
style="fill:#ffffff" />
<g
id="g5289"
style="fill:#ffffff" />
<g
id="g5291"
style="fill:#ffffff" />
<g
id="g5293"
style="fill:#ffffff" />
<g
id="g5295"
style="fill:#ffffff" />
<g
id="g5297"
style="fill:#ffffff" />
</g>
</g>
<g
id="g5360"
transform="translate(-128)">
id="icon-cycle"
transform="translate(-256)">
<rect
y="0"
x="0"
@ -375,52 +329,43 @@
</g>
<g
id="icon-logo"
transform="translate(-160)">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect5611"
width="32"
height="32"
x="0"
y="0" />
transform="translate(-224)">
<g
id="g5792"
transform="matrix(0.77498581,0,0,0.77498581,5.3156895,3.0643897)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path5774"
d="m 23.422912,9.2841946 c -6.673016,-4.1271355 -12.713117,-4.1751388 -19.2686597,0 C 4.3276468,14.227863 3.7999932,22.578308 13.788583,27.138641 24.112354,22.238283 23.334112,13.834188 23.422912,9.2841946 Z"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5776"
d="M 13.435029,5.9254374 V 26.961864 c 0,0 10.69499,-3.270369 9.987883,-17.6776694 0,0 -3.447145,-2.8284271 -9.987883,-3.3587572 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5778"
d="M 4.7729708,15.117826 13.700194,6.1906024"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5780"
d="M 6.2755727,20.332738 14.053747,12.554563"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5782"
d="m 8.5736697,23.691495 c 0.4419418,-0.53033 5.6126603,-5.61266 5.6126603,-5.61266"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5784"
d="m 11.932427,25.636039 2.342291,-2.342291"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
id="g8291">
<rect
y="0"
x="0"
height="32"
width="32"
id="rect5611"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
<g
style="fill:none;stroke:#ffffff;stroke-width:2.37017416;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.84381985,0,0,0.84381985,4.3658214,1.9308448)"
id="g5792">
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.37017416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 22.398559,10.079871 c -5.964023,-3.688637 -11.362377,-3.7315401 -17.2214088,0 0.1549718,4.418415 -0.3166199,11.881644 8.6107048,15.957452 9.226894,-4.379706 8.531339,-11.890885 8.610704,-15.957452 z"
id="path5774"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
<g
id="g8284"
transform="matrix(0.40235808,0,0,0.40235808,10.449533,8.9782152)"
style="fill:#ffffff;stroke:none;stroke-width:3.05170989;stroke-miterlimit:4;stroke-dasharray:none">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path8282"
d="m 22.398559,10.079871 c -5.964023,-3.688637 -11.362377,-3.7315401 -17.2214088,0 0.1549718,4.418415 -0.3166199,11.881644 8.6107048,15.957452 9.226894,-4.379706 8.531339,-11.890885 8.610704,-15.957452 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:3.05170989;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</g>
<g
id="g5817">
id="icon-arrow"
transform="translate(-96)">
<g
transform="translate(-192)"
id="g5812">
@ -441,7 +386,7 @@
</g>
<g
id="icon-locate"
transform="translate(-224)">
transform="translate(-320)">
<rect
y="0"
x="0"
@ -477,13 +422,244 @@
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g6048">
id="icon-sticker-2"
transform="translate(-160)">
<g
id="g4851">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect4849"
width="32"
height="32"
x="0"
y="0" />
</g>
<g
style="stroke:#ff5555"
transform="matrix(0.625,0,0,0.625,6,6)"
id="g4855">
<rect
y="0"
x="0"
height="32"
width="32"
id="rect4853"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#ff5555;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
</g>
<g
transform="matrix(0.94995908,0,0,0.94995908,-0.16007924,0.08338523)"
id="g4867">
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:0.7669366px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 13.469609,22.847288 3.04507,5.274218 3.120566,-5.404981 z"
id="path4859"
inkscape:connector-curvature="0" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.85096157;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4863"
cx="16.552427"
cy="14.979611"
r="8.7118835" />
<circle
r="4.867671"
cy="14.979611"
cx="16.552427"
id="circle4869"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03420484;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
<g
id="icon-route-2">
<g
id="g5626"
transform="translate(-96)">
<rect
y="0"
x="0"
height="32"
width="32"
id="rect5624"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
</g>
<g
id="g5630"
transform="matrix(0.625,0,0,0.625,-90,6)"
style="stroke:#ff5555" />
<g
id="g5651"
transform="translate(-62.434309)">
<circle
r="2.5065837"
cy="23.576099"
cx="-24.357349"
id="path5642"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4.36288548;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccccc"
inkscape:connector-curvature="0"
id="path5644"
d="M -24.288863,21.588224 V 10.609537 c 0,-4.2198358 6.620295,-4.1938278 6.620295,0 v 10.811701 c 0,4.010734 6.827489,4.0268 6.827489,0 V 10.440523"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.62126899;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4.36288548;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5646"
cx="-10.930283"
cy="8.4616919"
r="2.5065837" />
</g>
</g>
<g
id="icon-poly-2"
transform="translate(-64)">
<g
id="g6355">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect6353"
width="32"
height="32"
x="0"
y="0" />
</g>
<g
style="stroke:#ff5555"
transform="matrix(0.625,0,0,0.625,6,6)"
id="g6359" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.38667011;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 7.9242274,12.99117 16.492872,8.0023269 9.942466,22.589067 l 13.7628,-7.974199 -3.958059,9.120045"
id="path6375"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.30371094;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path6363"
cx="14.711287"
cy="-4.5232019"
r="2.3866701"
transform="rotate(75)" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.30371094;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle6367"
cx="12.170312"
cy="-13.883187"
r="2.3866701"
transform="rotate(75)" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.30371094;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle6371"
cx="20.342056"
cy="-19.193758"
r="2.3866701"
transform="rotate(75)" />
<circle
r="2.3866701"
cy="-3.7006412"
cx="24.137783"
id="circle6373"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.30371094;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="rotate(75)" />
<circle
r="2.3866701"
cy="-13.024511"
cx="27.917694"
id="circle6774"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.30371094;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="rotate(75)" />
</g>
<g
id="icon-shot-2"
transform="translate(-32)">
<g
id="g6599">
<rect
y="0"
x="0"
height="32"
width="32"
id="rect6597"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
</g>
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect6036"
width="32"
height="32"
x="0"
y="0" />
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.34301686;stroke-miterlimit:4;stroke-dasharray:6.6860338, 3.3430169;stroke-dashoffset:0;stroke-opacity:1"
id="rect6617"
width="19.5"
height="13.890411"
x="6.25"
y="9.8327999"
rx="1.0866628"
ry="1.0866628" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.97853923;stroke-miterlimit:4;stroke-dasharray:3.95707839, 1.97853919;stroke-dashoffset:0;stroke-opacity:1"
d="m 13.812434,7.0090218 h 6.281781 c 0.449743,0 0.748727,0.5278292 1.146518,1.0385106 l 3.096051,3.9746756 c 0.397794,0.510682 -3.792826,6.988378 -4.242569,6.988378 h -6.281781 c -0.449743,0 -4.8893508,-6.746784 -4.4750391,-7.24045 L 12.527274,7.9692938 c 0.414312,-0.4936656 0.835417,-0.960272 1.28516,-0.960272 z"
id="rect6619"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssss" />
<circle
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.4567318;stroke-miterlimit:4;stroke-dasharray:12.91346364, 6.45673181;stroke-dashoffset:0;stroke-opacity:1"
id="path6621"
cx="16.626713"
cy="16.310539"
r="6.158021" />
<circle
r="3.533021"
cy="16.310539"
cx="16.626713"
id="circle6628"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.70439935;stroke-miterlimit:4;stroke-dasharray:7.40879871, 3.70439934;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="g7720"
transform="translate(-224,-32)">
<g
id="g7706">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
id="rect7704"
width="32"
height="32"
x="0"
y="0" />
</g>
<g
style="fill:none;stroke:#ff5555"
transform="matrix(0.625,0,0,0.625,6,38)"
id="g7710">
<rect
y="0"
x="0"
height="32"
width="32"
id="rect7708"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff5555;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
</g>
</g>
<g
transform="matrix(0.5,0,0,0.5,-64,-49.407377)"
id="g8789"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<g
id="g8773"
style="fill:#1a1a1a">
<rect
y="0"
x="0"
height="32"
width="32"
id="rect8771"
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
rx="4"
ry="4" />
</g>
<g
id="g8775"
transform="matrix(0.625,0,0,0.625,6,6)"
style="stroke:#ff5555" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient8808);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.60278547;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M -55.560547 -48.251953 A 1.6027855 1.6027855 45 0 0 -56.037109 -48.197266 A 1.6027855 1.6027855 45 0 0 -57.216797 -46.783203 L -60.574219 -44.828125 A 1.6027855 1.6027855 45 0 0 -61.667969 -44.923828 A 1.6027855 1.6027855 45 0 0 -62.800781 -42.960938 A 1.6027855 1.6027855 45 0 0 -60.837891 -41.826172 A 1.6027855 1.6027855 45 0 0 -59.65625 -43.509766 L -57.421875 -44.810547 L -60.15625 -38.71875 A 1.6027855 1.6027855 45 0 0 -60.5625 -38.666016 A 1.6027855 1.6027855 45 0 0 -61.695312 -36.703125 A 1.6027855 1.6027855 45 0 0 -59.732422 -35.568359 A 1.6027855 1.6027855 45 0 0 -58.558594 -36.910156 L -52.527344 -40.404297 L -53.625 -37.875 A 1.6027855 1.6027855 45 0 0 -53.857422 -37.833984 A 1.6027855 1.6027855 45 0 0 -54.990234 -35.871094 A 1.6027855 1.6027855 45 0 0 -53.027344 -34.738281 A 1.6027855 1.6027855 45 0 0 -51.894531 -36.701172 A 1.6027855 1.6027855 45 0 0 -52.154297 -37.240234 L -50.664062 -40.671875 A 1.6027855 1.6027855 45 0 0 -50.341797 -40.724609 A 1.6027855 1.6027855 45 0 0 -49.208984 -42.6875 A 1.6027855 1.6027855 45 0 0 -51.171875 -43.820312 A 1.6027855 1.6027855 45 0 0 -52.357422 -42.355469 L -58.316406 -38.902344 L -55.556641 -45.050781 A 1.6027855 1.6027855 45 0 0 -55.207031 -45.101562 A 1.6027855 1.6027855 45 0 0 -54.074219 -47.064453 A 1.6027855 1.6027855 45 0 0 -55.560547 -48.251953 z "
transform="matrix(2,0,0,2,128,98.814754)"
id="path8777" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before After
Before After

View file

@ -20,6 +20,10 @@
&.danger {
background: #ed2f3b;
}
&.success {
background: #17bf6d;
}
}
.button-group {

View file

@ -8,3 +8,9 @@
@dialog_background: #222222;
@location_line: #ff3344;
@green_primary: #abc837;
@green_secondary: #009c80;
@red_primary: #ff7034;
@red_secondary: #ff3344;

View file

@ -7,9 +7,10 @@
@import 'button.less';
@import 'logo.less';
@import 'user-button.less';
@import 'save.less';
body {
font-family: sans-serif;
font-family: 'Raleway', sans-serif;
font-size: 14px;
}

View file

@ -64,9 +64,9 @@
width: 32px;
height: 32px;
position: fixed;
top: 80px;
top: 10px;
left: 10px;
border-radius: 2px;
border-radius: 2px 0 0 2px;
z-index: 3;
box-shadow: @bar_shadow;
cursor: pointer;
@ -110,3 +110,7 @@
position: absolute;
}
}
.leaflet-top {
top: 42px;
}

View file

@ -1,21 +1,25 @@
.control-bar {
background: @bar_background;
border-radius: 3px;
border-radius: 4px;
display: flex;
box-shadow: @bar_shadow;
}
.control-dist {
height: 44px;
background: #222222;
padding: 0 10px;
display: flex;
align-items: center;
border-radius: 3px 0 0 3px;
font-weight: 200;
color: #cccccc;
user-select: none;
box-shadow: @bar_shadow;
position: fixed;
top: 10px;
left: 42px;
z-index: 2;
height: 32px;
border-radius: 0 3px 3px 0;
svg {
fill: #cccccc;
@ -36,6 +40,12 @@
color: white;
display: flex;
align-items: center;
transform: translateY(100px);
transition: transform 500ms;
&.active {
transform: translateY(0);
}
&.right {
left: auto;
@ -54,6 +64,7 @@
transition: background-color 500ms;
height: 48px;
box-sizing: border-box;
user-select: none;
&:hover {
background: rgba(100, 100, 100, 0.2);
@ -66,6 +77,10 @@
margin-left: 8px;
}
&:first-child {
border-radius: 4px 0 0 4px;
}
&:last-child {
border-radius: 0 4px 4px 0;
}
@ -78,10 +93,27 @@
}
&.highlighted {
background: #555555;
}
&.cancel {
background: linear-gradient(270deg, #0f5871, #444444 60%);
}
&.primary {
background: linear-gradient(150deg, @blue_primary, @blue_secondary) 50% 50% no-repeat;
background-size: 100% 100%;
}
&.danger {
background: linear-gradient(150deg, @red_primary, @red_secondary) 50% 50% no-repeat;
background-size: 100% 100%;
}
&.single {
border-radius: 3px;
}
svg {
fill: white;
stroke: white;

84
src/styles/save.less Normal file
View file

@ -0,0 +1,84 @@
.save-helper {
width: 443px;
padding: 0;
flex-direction: column;
}
.save-title {
padding: 10px;
width: 100%;
background: linear-gradient(160deg, @green_primary, @green_secondary);
flex-direction: column;
border-radius: 3px 3px 0 0;
font-weight: 200;
box-sizing: border-box;
}
.save-description {
padding: 10px;
}
.save-title-input {
background: rgba(0, 0, 0, 0.2);
border-radius: 2px;
display: flex;
input {
width: 100%;
padding: 5px;
background: transparent;
border: none;
outline: none;
color: white;
font-family: inherit;
font-size: 14px;
font-weight: 200;
}
}
.save-title-label {
display: flex;
padding: 5px 10px;
background: rgba(0,0,0,0.1);
height: 100%;
}
.save-address-input {
background: rgba(0, 0, 0, 0.2);
border-radius: 2px;
display: flex;
input {
width: 100%;
padding: 5px 5px 5px 2px;
background: transparent;
border: none;
outline: none;
color: white;
font-family: inherit;
font-size: 14px;
font-weight: 200;
}
}
.save-address-label {
display: flex;
padding: 5px 0 5px 10px;
height: 100%;
opacity: 0.5;
}
.save-text {
padding: 10px;
}
.save-buttons {
display: flex;
padding: 10px;
}
.save-buttons-text {
flex: 1;
}

View file

@ -1,11 +1,16 @@
.sticker-container {
outline: none;
position: relative;
transition: transform 250ms;
cursor: pointer;
&.leaflet-drag-target {
transition: none !important;
}
&:before {
content: ' ';
box-shadow: 0 0 10px 1px #ff3344;
background: #ff334422;
background: @red_secondary;
width: 48px;
height: 48px;
left: -24px;
@ -13,8 +18,8 @@
position: absolute;
border-radius: 40px;
opacity: 0;
transform: scale(0.5);
transition: opacity 250ms, transform 500ms;
transform: scale(0);
}
&:hover, &:active {
@ -24,10 +29,18 @@
}
&:before {
opacity: 1;
opacity: 0.3;
transform: scale(1);
}
}
&.inactive {
pointer-events: none;
.sticker-delete {
display: none;
}
}
}
.sticker-label {

View file

@ -4,25 +4,19 @@ import { API } from '$constants/api';
const report = console.warn;
export const checkUserToken = ({
callback, fallback, id, token
}) => (
axios.get(API.GET_GUEST, {
params: { action: 'check_token', id, token }
})
.then(result => (result && result.data))
.then(data => ({ ...data, id, token }))
.then(callback)
.catch(fallback)
);
export const getGuestToken = ({ callback }) => (
axios.get(API.GET_GUEST, {
params: { action: 'gen_guest_token' }
})
.then(result => (result && result.data))
.then(callback)
.catch(report)
);
export const checkUserToken = ({ id, token }) => axios.get(API.CHECK_TOKEN, {
params: {
id,
token,
action: 'check_token',
}
}).then(result => (result && result.data && { ...result.data, id, token }))
export const getGuestToken = () => axios.get(API.GET_GUEST, {
params: {
action: 'gen_guest_token'
}
}).then(result => (result && result.data));
export const getMergedImage = ({ placement, callback }) => (
axios.get(API.COMPOSE, {
@ -31,3 +25,27 @@ export const getMergedImage = ({ placement, callback }) => (
.then(callback)
.catch(report)
);
export const getStoredMap = ({ name }) => axios.get(API.GET_MAP, {
params: {
name,
action: 'load'
}
}).then(result => (result && result.data && result.data.data && {
...result.data.data,
owner: (result.data.owner || null),
address: (result.data.name || name),
}));
export const postMap = ({
title, address, route, stickers, id, token, force,
}) => axios.post(API.POST_MAP, {
action: 'store',
title,
address,
route,
stickers,
id,
token,
force,
}).then(result => (result && result.data && result.data));

12
src/utils/format.js Normal file
View file

@ -0,0 +1,12 @@
const ru = [' ','\\.',',',':','\\?','#','Я','я','Ю','ю','Ч','ч','Ш','ш','Щ','щ','Ж','ж','А','а','Б','б','В','в','Г','г','Д','д','Е','е','Ё','ё','З','з','И','и','Й','й','К','к','Л','л','М','м','Н','н', 'О','о','П','п','Р','р','С','с','Т','т','У','у','Ф','ф','Х','х','Ц','ц','Ы','ы','Ь','ь','Ъ','ъ','Э','э'];
const en = ['_','','','','','','Ya','ya','Yu','yu','Ch','ch','Sh','sh','Sh','sh','Zh','zh','A','a','B','b','V','v','G','g','D','d','E','e','E','e','Z','z','I','i','J','j','K','k','L','l','M','m','N','n', 'O','o','P','p','R','r','S','s','T','t','U','u','F','f','H','h','C','c','Y','y','`','`','\'','\'','E', 'e'];
export const toHours = (info) => {
const hrs = parseInt(Number(info), 10);
const min = Math.round((Number(info) - hrs) * 60);
const lmin = min < 10 ? '0' + min : min;
return `${hrs}:${lmin}`;
};
export const toTranslit = string => ru.reduce((text, el, i) => (text.replace(new RegExp(ru[i], 'g'), en[i])), (String(string) || ''));

13
src/utils/history.js Normal file
View file

@ -0,0 +1,13 @@
export const getPath = () => (window.location && window.location.pathname &&
window.location.pathname.replace(/^\//, ''));
export const pushPath = url => window.history.pushState(url, 'Редактирование маршрута', url);
export const getUrlData = () => {
const url = getPath();
const [path, mode] = url.split('/');
const { host } = window.location;
return { path, mode, host };
};

15
src/utils/import.js Normal file
View file

@ -0,0 +1,15 @@
/*
functions to parse old maps data
*/
export const parseStickerAngle = ({ sticker, version }) => {
return sticker && version && parseInt(version, 10) === 2
? parseFloat(sticker.angle)
: parseFloat(sticker.ang - 3.14);
};
export const parseStickerStyle = ({ sticker, version }) => (
sticker && version && parseInt(version, 10) === 2
? sticker.sticker
: 'basic'
);

View file

@ -1,6 +0,0 @@
export const toHours = (info) => {
const hrs = parseInt(Number(info), 10);
const min = Math.round((Number(info) - hrs) * 60);
const lmin = min < 10 ? '0' + min : min;
return `${hrs}:${lmin}`;
};

View file

@ -105,10 +105,10 @@ module.exports = () => {
resolve,
plugins,
entry: {
// loader: './src/loader.js',
app: './src/index.js',
},
output: {
publicPath: '/',
filename: '[name].bundle.[githash].js',
},
optimization: {