Commit 2a07b202 by Иван Кубота

Favicon

Routing url => page page => url url => page.match Add routes to all pages Serve index.html on all requests
parent f8126071
......@@ -371,11 +371,7 @@ app.use(function(req, res, next) {
next();
});
app.use(transformServe('src'));
var lives = [];
app.use('/', function(req, res, next){
//console.log( req.originalUrl )
if( req.originalUrl === '/' ){
var serveMain = function(res) {
fs.readFile( dir( pack.src, pack.entry.html ), function( err, data ){
if( err ){
res.end( JSON.stringify( err, null, 2 ) );
......@@ -384,6 +380,14 @@ app.use('/', function(req, res, next){
}
} );
};
app.use(transformServe('src'));
var lives = [];
app.use('/', function(req, res, next){
//console.log( req.originalUrl )
if( req.originalUrl === '/' ){
serveMain(res);
}else if( req.originalUrl === '/[live]' ){
lives.push( res );
......@@ -404,6 +408,8 @@ app.use(transformServe('src', true));
app.use(function(req, res, next) {
res._log('!Not serving', req.url);
serveMain(res);
});
const util = require('util');
......
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
......@@ -8,12 +8,21 @@ Action.prototype = {
}
};
const ACTION = {
NAVIGATE: new Action((where, data)=>{
NAVIGATE: new Action((where, data, silent)=>{
store.set({
'navigation.current': where,
'navigation.data': data || {}
});
if(!silent){
Model.history.push( { current: where, data: data || {} } );
history.pushState( { place: where, data: data || {} }, '', Page[ where ].route.generate( data || {} ) );
}
}),
NAVIGATE_BACK: new Action(()=>{
store.set('navigation', Model.history.pop());
}),
CARD: {
LEARN_MORE: new Action((item)=>{
ACTION.NAVIGATE.execute('InfoPage', {id: item.id, category: item.category_id});
......@@ -47,4 +56,31 @@ const ACTION = {
export default ACTION
export {ACTION};
typeof window !== 'undefined' && (window.ACTION = ACTION);
if(typeof window !== 'undefined'){
window.ACTION = ACTION;
window.onpopstate = function(event) {
store.set({
'navigation.current': event.state.place,
'navigation.data': event.state.data || {}
});
};
const path = document.location.pathname;
tmpStore.valEqualOnly('loaded', true)(function() {
//debugger
let bestMatch = Object.values(Page)
.map((page)=>({page, match: page.route.match(path)}))
.sort((a,b)=>b.match - a.match)
[0];
console.log('ROUTE:', bestMatch.page.route.pageName)
if(bestMatch.match<0.1){
// 404
store.set({
'navigation.current': '404',
'navigation.data': {url: path}
});
}else{
bestMatch.page.route.load(path)
}
});
}
var Route = function(url) {
if(!(this instanceof Route))
return new Route(url);
//url.replace(/(:[a-zA-Z0-9\-_]+)(?=\/|$)/g)
var list = this.list = [];
var rand = Math.random().toString(36).substr(2);
this.splitted = url.replace(/(:([^\/]+))(?=\/|$)/g, function(str, full, token) {
list.push(token);
return rand;
}).split(rand);
var splitted = this.splitted,
out = [];
for( var i = 0, _i = splitted.length; i < _i; i++ ){
out.push(splitted[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
i<_i-1 && out.push('([^\\/]+)');
}
this.RegExp = new RegExp('^'+out.join('')+'$', 'i');
};
Route.prototype = {
generate: function(data) {
var list = this.list,
splitted = this.splitted,
out = [];
for( var i = 0, _i = list.length; i < _i; i++ ){
out.push(splitted[i]);
out.push(data[list[i]] || '');
}
return out.join('');
},
load: function(url) {
var matched = url.match(this.RegExp),
data = {}, list = this.list,
silent = true;
var state = history.state || {},
stateData = state.data || {},
dataNotMatched = false;
for( var i = 0, _i = list.length; i < _i; i++ ){
var listElement = list[ i ];
data[listElement] = matched[i+1];
if(stateData[listElement] !== matched[i+1])
dataNotMatched = true;
}
for(i in stateData){
if(!(i in data)){
dataNotMatched = true;
}
}
if(state.place === this.pageName || dataNotMatched){
silent = false;
}
ACTION.NAVIGATE.execute(this.pageName, data, silent);
/*
store.set({
'navigation.current': event.state.place,
'navigation.data': event.state.data || {}
});
*/
},
match: function(url) {
return (url.match(this.RegExp) !== null? 1 : 0)*url.length;
}
};
if(typeof window !== 'undefined'){
window.Route = Route;
}
<!DOCTYPE html>
<html>
<head>
<title>Category mapper</title>
<base href="/"/>
<title>ВкусВилл education</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script src="core/Path.js"></script>
......@@ -12,9 +13,14 @@
<script src="core/DOM.js"></script>
<script src="core/Random.Seeded.js"></script>
<script src="core/data/store/Store.js"></script>
<script src="core/Route.js"></script>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<script src="core/data/store/Store.js"></script>
$COMMIT$
$BUNDLE$
</head>
......
import '/model/Store';
import {ACTION} from "/controller/Action";
import './view/page/login/Login.jsx';
import './view/page/account/WelcomePage.jsx';
import './view/page/account/Account.jsx';
import './view/page/account/Profile.jsx';
import './view/page/tmp/Fields.jsx';
import Header from './view/block/header/Header.jsx';
import Header from '/view/block/header/Header.jsx';
import "/global-styles/base.scss";
import { Switch } from "./view/cmp/switch/Switch";
......@@ -18,7 +11,7 @@ export default function() {
let tagField, exportEl;
let dom = <div renderTo={document.body} cls="page-content">
<view.block.Header/>
<Header/>
{Switch({
cls: 'page-content__inner',
key: 'navigation.current',
......
......@@ -79,9 +79,51 @@ const createSavableStore = function(name) {
const cards = createSavableStore('cards');
//const products = createSavableStore('products');
const categories = createSavableStore('categories');
const SavableArray = function(name, length) {
this.name = name;
this.items = [];
this.maxLength = length;
};
SavableArray.prototype = Object.assign({
length: 0,
push: function(item) {
this.items.push(item);
this.save();
this.length++;
},
pop: function() {
try{
return this.items.pop();
}finally{
this.save();
}
},
save: function() {
localStorage.setItem(this.name, JSON.stringify({_VERSION_: STORE_VERSION, items: this.items}));
},
load: function(){
try{
var data = localStorage.getItem(this.name), parsed;
parsed = JSON.parse(data);
if(parsed._VERSION_ === STORE_VERSION){
this.items = data.items;
this.length = this.items.length;
}
}catch( e ){}
}
});
const history = new SavableArray('history', 50);
const Model = {
cards: cards,
categories: categories
categories: categories,
history: history
};
categories.loading = {};
......
......@@ -5,6 +5,7 @@ import PaginationSlider from '../paginationSlider/PaginationSlider.jsx';
import Back from '/svg/arr-back.svg';
import Arr from '/svg/arr.svg';
import {ACTION} from '/controller/Action';
const InfoCard = D.declare('view.cmp.InfoCard', ({item, category}) => {
console.log({item, category})
......@@ -22,10 +23,10 @@ const InfoCard = D.declare('view.cmp.InfoCard', ({item, category}) => {
let next = function(){
if( forwardHidden )
return false;
//debugger
for( let i = 0, _i = sorted.length; i < _i; i++ ){
if( sorted[ i ].id === item.id ){
store.set( 'navigation.data.id', sorted[ i + 1 ].id );
ACTION.NAVIGATE.execute('InfoPage', {id: sorted[ i + 1 ].id, category: category.type})
break;
}
}
......@@ -36,7 +37,8 @@ const InfoCard = D.declare('view.cmp.InfoCard', ({item, category}) => {
for( let i = 0, _i = sorted.length; i < _i; i++ ){
if( sorted[ i ].id === item.id ){
store.set( 'navigation.data.id', sorted[ i - 1 ].id );
ACTION.NAVIGATE.execute('InfoPage', {id: sorted[ i - 1 ].id, category: category.type})
break;
}
}
......
import * as Pages from './index';
if(typeof window !== 'undefined'){
window.Page = Pages;
for(let name in Pages){
let page = Pages[name];
if('route' in page){
page.route.pageCtor = page;
page.route.pageName = name;
}
}
}
export {Pages as Page};
\ No newline at end of file
......@@ -119,6 +119,7 @@ const Account = D.declare('view.page.Account', () => {
return dom;
});
Account.route = new Route('/');
export default Account;
export {Account};
......@@ -13,5 +13,7 @@ const Profile = D.declare('view.page.Profile', () => {
</div>
});
Profile.route = new Route('/profile');
export default Profile;
export {Profile};
......@@ -200,7 +200,7 @@ const WelcomePage = D.declare('view.page.WelcomePage', () =>
</div>
</div>
);
WelcomePage.route = new Route('/welcome');
export default WelcomePage;
export {WelcomePage};
......@@ -2,7 +2,6 @@ import '../../cmp/field/LabeledField.jsx';
import Button from '../../cmp/button/Button.jsx';
import Logo from '../../../svg/logo_vkusvill.svg';
import './loginPage.scss';
import Arr from '../../../svg/arr.svg';
import LoginHelp from './LoginHelp.jsx';
import LoginPhone from './LoginPhone.jsx';
......@@ -74,6 +73,6 @@ const Login = D.declare('view.page.Login', () => {
</IF>
</div>
});
Login.route = new Route('/login');
export default Login;
export {Login};
......@@ -2,7 +2,6 @@ import Button from "/view/cmp/button/Button.jsx";
import { AsyncAjax } from "/core/Ajax.jsx";
import { API } from "/dict/Consts.jsx";
import Arr from '/svg/arr.svg';
import { AsyncAuthAjax } from "../../../controller/Ajax";
const {AND, OR, IF} = Store;
const LoginCode = D.declare('view.page.LoginCode', ({loginStore}) => {
......
import './infoPage.scss';
import ArrActive from '/svg/arrow_active.svg';
import InfoCard from "../../cmp/infoCard/InfoCard.jsx";
import { AsyncAuthAjax } from "../../../controller/Ajax";
import { API } from "../../../dict/Consts";
const InfoPage = D.declare('view.page.InfoPage', () => {
......@@ -41,6 +39,7 @@ const InfoPage = D.declare('view.page.InfoPage', () => {
</div>
</div>
});
InfoPage.route = new Route('/category/:category/id/:id');
export default InfoPage;
export {InfoPage};
......@@ -18,7 +18,8 @@ const QuizPage = D.declare('view.page.QuizPage', () => {
</div>
</div>
</div>
})
});
QuizPage.route = new Route('/quiz');
export default QuizPage;
export {QuizPage};
......@@ -7,6 +7,6 @@ const ChooseType = D.declare( 'view.page.ChooseType', () => {
<button onClick={ACTION.TEST.DEMO.LIMITLESS.execute}>Бесконечная генерация вопросов</button>
</div>
} );
ChooseType.route = new Route('/demo/choose');
export default ChooseType;
export { ChooseType };
\ No newline at end of file
......@@ -26,6 +26,6 @@ const WelcomeDemoFinal = D.declare( 'view.page.WelcomeDemoFinal', () => {
</div>
</Info>
} );
WelcomeDemoFinal.route = new Route('/demo/final');
export default WelcomeDemoFinal;
export { WelcomeDemoFinal };
\ No newline at end of file
......@@ -26,6 +26,7 @@ const WelcomeDemoFinalLastNotification = D.declare( 'view.page.WelcomeDemoFinalL
</div>
</Info>
} );
WelcomeDemoFinalLastNotification.route = new Route('/demo/final/notify');
export default WelcomeDemoFinalLastNotification;
export { WelcomeDemoFinalLastNotification };
\ No newline at end of file
import Button from "/view/cmp/button/Button.jsx";
import LabeledField from "../../cmp/field/LabeledField.jsx";
import PhoneInput from "../../cmp/field/PhoneInput.jsx";
import Input from "../../cmp/field/Input";
......@@ -51,6 +50,6 @@ const Fields = D.declare('view.page.tmp.Fields', () => {
</div>
</div>
});
Fields.route = new Route('/fields');
export default Fields;
export {Fields};
\ No newline at end of file
import Button from "/view/cmp/button/Button.jsx";
import LabeledField from "../../cmp/field/LabeledField.jsx";
import PhoneInput from "../../cmp/field/PhoneInput.jsx";
import Input from "../../cmp/field/Input";
import { AsyncAuthAjax } from "../../../controller/Ajax";
import {API} from "../../../dict/Consts";
const TestRequests = D.declare('view.page.tmp.TestRequests', () => {
......@@ -40,5 +37,6 @@ const TestRequests = D.declare('view.page.tmp.TestRequests', () => {
</div>
});
TestRequests.route = new Route('/testRequests');
export default TestRequests;
export {TestRequests};
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment