advanced address parsing

This commit is contained in:
muerwre 2019-03-20 14:15:08 +07:00
parent ea08ab8a5e
commit 89a13f1475
5 changed files with 82 additions and 19 deletions

View file

@ -1,6 +1,6 @@
const { User, Route } = require('../../models');
const { parseRoute, parseStickers, parseString, parseNumber } = require('../../utils/parse');
const { parseRoute, parseStickers, parseString, parseNumber, parseAddress } = require('../../utils/parse');
module.exports = async (req, res) => {
const { body, body: { id, token, force } } = req;
@ -9,7 +9,7 @@ module.exports = async (req, res) => {
if (!owner) return res.send({ success: false, reason: 'unauthorized', id, token });
const title = parseString(body.title, 64);
const address = parseString(body.address, 32);
const address = parseAddress(body.address, 32)
const route = parseRoute(body.route);
const stickers = parseStickers(body.stickers);
const logo = parseString(body.logo, 16);

View file

@ -21,5 +21,10 @@ module.exports.parseStickers = stickers => stickers.filter(el => (
));
// .map(el => ((el.text && String(el.text).substr(0, 100)) || ''));
module.exports.parseString = (value, size) => (value && String(value).substr(0, size)) || '';
const parseString = (value, size) => (value && String(value).substr(0, size)) || '';
module.exports.parseNumber = (value, min, max) => (value && Number(value) && Math.min(max, Math.max(min, value))) || 0;
module.exports.parseString = parseString;
module.exports.parseAddress = (value, size) => (
parseString(value, size).replace(/[^A-Za-z\-_0-9]/ig, '_').replace(/_{2,}/ig, '_')
);

View file

@ -2,19 +2,47 @@ import * as React from 'react';
import { bindActionCreators } from "redux";
import { connect } from 'react-redux';
import classnames from 'classnames';
interface ITitleDialogProps {
editing: boolean,
title?: string,
}
export const Component: React.FunctionComponent<ITitleDialogProps> = ({ editing, title }) => (
!editing && title &&
<div className="title-dialog">
<div className="title-dialog-pane title-dialog-name">
<h2>{title}</h2>
interface ITitleDialogState {
raised: boolean;
}
export class Component extends React.PureComponent<ITitleDialogProps, ITitleDialogState> {
state = {
raised: false,
};
onHover = () => this.setState({ raised: true });
onLeave = () => this.setState({ raised: false });
render() {
const { editing, title } = this.props;
return (
<div className="title-dialog-wrapper">
<div className="title-dialog-sizer" ref={el => { this.sizer = el; }}>
<div className={classnames('title-dialog', { active: title && !editing })}>
<div className="title-dialog-pane title-dialog-name">
<h2>{title}</h2>
</div>
<div className="title-dialog-pane title-dialog-text">
Давно выяснено, что при оценке дизайна и композиции читаемый текст мешает сосредоточиться. Lorem Ipsum используют потому, что тот обеспечивает более или менее стандартное заполнение шаблона, а также реальное распределение букв и пробелов в абзацах, которое не получается при простой дубликации "Здесь ваш текст.. Здесь ваш текст.. Здесь ваш текст.." Многие программы электронной вёрстки и редакторы HTML используют Lorem Ipsum в качестве текста по умолчанию, так что поиск по
</div>
</div>
</div>
</div>
</div>
);
)
}
text;
sizer;
}
const mapStateToProps = ({ user: { editing, title } }) => ({ editing, title });
const mapDispatchToProps = dispatch => bindActionCreators({ }, dispatch);

View file

@ -616,20 +616,48 @@
}
}
.title-dialog {
.title-dialog-wrapper {
position: fixed;
left: 10px;
bottom: 68px;
width: 340px;
bottom: 0;
left: 0;
width: 360px;
height: 100%;
background: transparent;
z-index: 2;
opacity: 0.5;
transition: opacity 500ms;
padding: 10px 10px 58px 10px;
box-sizing: border-box;
display: flex;
align-items: flex-end;
pointer-events: none;
touch-action: none;
}
&:hover {
opacity: 1;
.title-dialog-sizer {
height: 100%;
width: 100%;
display: flex;
align-items: flex-end;
}
.title-dialog {
z-index: 2;
opacity: 0;
transition: opacity 500ms, transform 1s;
transform: translate(0, 68px);
user-select: none;
pointer-events: all;
touch-action: auto;
&.active {
opacity: 0.5;
transform: translate(0, 0);
&:hover {
opacity: 1;
}
}
.title-dialog-pane {
margin-bottom: 10px;
padding: 10px;
background: #111111;
color: fade(white, 50%);

View file

@ -1,6 +1,8 @@
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 removeGarbage = (text: string): string => text.replace(/[^A-Za-z\-_0-9]/ig, '_').replace(/_{2,}/ig, '_');
export const toHours = (info: number): string => {
const hrs = parseInt(String(info), 10);
const min = Math.round((Number(info) - hrs) * 60);
@ -9,5 +11,5 @@ export const toHours = (info: number): string => {
};
export const toTranslit = (string: string): string => (
ru.reduce((text, el, i) => (text.replace(new RegExp(ru[i], 'g'), en[i])), (String(string) || ''))
removeGarbage(ru.reduce((text, el, i) => (text.replace(new RegExp(ru[i], 'g'), en[i])), (String(string) || '')))
);