commiting while gfx ar enot working right
4
copy.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# rm -rf /home/martin/dev/menuserver/dist/*
|
||||||
|
cp -r /home/martin/dev/svelte-traintimes/public/* /home/martin/dev/traintimesPWA/live
|
26
package-lock.json
generated
@ -1640,6 +1640,11 @@
|
|||||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
|
||||||
@ -2221,6 +2226,14 @@
|
|||||||
"type-check": "~0.3.2"
|
"type-check": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
|
||||||
|
"requires": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"livereload": {
|
"livereload": {
|
||||||
"version": "0.9.1",
|
"version": "0.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.1.tgz",
|
||||||
@ -2257,6 +2270,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/local-access/-/local-access-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/local-access/-/local-access-1.0.1.tgz",
|
||||||
"integrity": "sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA=="
|
"integrity": "sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA=="
|
||||||
},
|
},
|
||||||
|
"localforage": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ==",
|
||||||
|
"requires": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"locate-path": {
|
"locate-path": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||||
@ -3119,6 +3140,11 @@
|
|||||||
"picomatch": "^2.0.7"
|
"picomatch": "^2.0.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redaxios": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redaxios/-/redaxios-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-lrDld2bVWIBrW+S1HPMyP8OvEtpHPIfmXyW7T7xTox1SM4/M3aC5X55xa2vRR3LZHwCvpMQAgCye8IyICzkKpA=="
|
||||||
|
},
|
||||||
"redent": {
|
"redent": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
|
||||||
|
@ -24,7 +24,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
|
"localforage": "^1.7.3",
|
||||||
"muicss": "^0.10.1",
|
"muicss": "^0.10.1",
|
||||||
|
"redaxios": "^0.2.0",
|
||||||
"rollup-plugin-replace": "^2.2.0",
|
"rollup-plugin-replace": "^2.2.0",
|
||||||
"sirv-cli": "^0.4.4",
|
"sirv-cli": "^0.4.4",
|
||||||
"spectre.css": "^0.5.8",
|
"spectre.css": "^0.5.8",
|
||||||
|
9
public/browserconfig.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="/img/mstile-150x150.png"/>
|
||||||
|
<TileColor>#2b5797</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 49 KiB |
BIN
public/img/Icon-144.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
public/img/Icon-192.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
public/img/Icon-36.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/img/Icon-48.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
public/img/Icon-512.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
public/img/Icon-72.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
public/img/Icon-96.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
public/img/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
public/img/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
public/img/favicon-16x16.png
Normal file
After Width: | Height: | Size: 984 B |
BIN
public/img/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/img/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/img/mstile-150x150.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
public/img/photothumb.db
Normal file
33
public/img/safari-pinned-tab.svg
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="192.000000pt" height="192.000000pt" viewBox="0 0 192.000000 192.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,192.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M440 1789 c-80 -4 -104 -10 -149 -35 -63 -34 -117 -94 -145 -162 -19
|
||||||
|
-45 -20 -74 -20 -637 l0 -590 25 -56 c32 -67 91 -128 156 -160 l48 -23 605 -1
|
||||||
|
605 0 53 28 c69 35 118 86 151 156 l26 56 0 585 c-1 534 -2 590 -18 637 -33
|
||||||
|
94 -133 180 -231 199 -47 8 -969 11 -1106 3z m389 -79 c21 0 51 -44 51 -74 l0
|
||||||
|
-34 80 -1 c79 -1 80 -1 80 23 0 40 21 74 51 85 57 20 112 -21 112 -83 0 -17 5
|
||||||
|
-26 16 -26 68 0 143 -50 172 -115 17 -37 19 -74 19 -455 0 -265 -4 -429 -11
|
||||||
|
-454 -6 -23 -28 -55 -55 -81 l-44 -43 85 -89 c91 -94 101 -118 63 -153 -41
|
||||||
|
-38 -61 -28 -194 105 l-125 125 -168 0 -167 0 -128 -125 c-136 -134 -157 -145
|
||||||
|
-196 -103 -35 38 -26 60 65 155 l85 88 -35 30 c-19 16 -44 48 -55 70 -18 38
|
||||||
|
-19 65 -19 468 -1 404 1 431 19 467 32 63 105 110 171 110 11 0 16 8 14 23 -3
|
||||||
|
48 53 104 93 91 8 -2 17 -4 21 -4z"/>
|
||||||
|
<path d="M819 1532 c-48 -15 -65 -75 -31 -106 16 -14 43 -16 172 -17 169 0
|
||||||
|
190 7 190 62 0 25 -21 57 -38 60 -22 4 -282 4 -293 1z"/>
|
||||||
|
<path d="M735 1342 c-93 -5 -94 -6 -94 -192 0 -143 2 -160 19 -175 18 -16 48
|
||||||
|
-18 301 -18 l282 -1 18 23 c17 20 19 42 19 176 0 133 -2 154 -18 168 -15 14
|
||||||
|
-52 17 -242 19 -124 2 -252 2 -285 0z"/>
|
||||||
|
<path d="M685 741 c-35 -22 -50 -67 -35 -107 12 -32 55 -57 93 -56 44 1 88 50
|
||||||
|
81 89 -9 52 -15 63 -43 78 -34 17 -63 16 -96 -4z"/>
|
||||||
|
<path d="M1138 745 c-49 -27 -58 -97 -18 -137 55 -54 139 -31 154 43 7 38 -9
|
||||||
|
71 -44 92 -34 21 -56 21 -92 2z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -4,10 +4,22 @@
|
|||||||
<meta charset='utf-8'>
|
<meta charset='utf-8'>
|
||||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||||
|
|
||||||
<title>Svelte app</title>
|
<title>Traintimes</title>
|
||||||
|
|
||||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||||
<!--<link rel='stylesheet' href='/global.css'>-->
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/manifest.json">
|
||||||
|
<link rel="mask-icon" href="/img/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Train Times">
|
||||||
|
<meta name="application-name" content="Train Times">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
|
||||||
|
<!--<link rel='stylesheet' href='/global.c
|
||||||
|
ss'>-->
|
||||||
<link rel='stylesheet' href='/build/bundle.css'>
|
<link rel='stylesheet' href='/build/bundle.css'>
|
||||||
|
|
||||||
<script defer src='/build/bundle.js'></script>
|
<script defer src='/build/bundle.js'></script>
|
||||||
|
46
public/manifest.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "Train Times",
|
||||||
|
"short_name": "Train Times",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"start_url": ".",
|
||||||
|
"imgdisplay": "standalone",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
110
public/service-worker.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2016 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
const CACHE_VERSION = 8;
|
||||||
|
const dataCacheName = `traintimesData-v${CACHE_VERSION}`;
|
||||||
|
const cacheName = `traintimePWA-final-${CACHE_VERSION}`;
|
||||||
|
const filesToCache = [
|
||||||
|
'/',
|
||||||
|
'/index.html',
|
||||||
|
'/service-worker.js',
|
||||||
|
'/manifest.json',
|
||||||
|
'/favicon.png',
|
||||||
|
'/browserconfig.xml',
|
||||||
|
'/build/bundle.css',
|
||||||
|
'/build/bundle.js',
|
||||||
|
'/build/fonts/fujicons.css',
|
||||||
|
'/build/fonts/fujicons.ttf',
|
||||||
|
'/img/Icon-36.png',
|
||||||
|
'/img/Icon-48.png',
|
||||||
|
'/img/Icon-72.png',
|
||||||
|
'/img/Icon-96.png',
|
||||||
|
'/img/Icon-144.png',
|
||||||
|
'/img/Icon-192.png',
|
||||||
|
'/img/Icon-512.png'
|
||||||
|
];
|
||||||
|
|
||||||
|
self.addEventListener('install', function(e) {
|
||||||
|
console.log('[ServiceWorker] Install');
|
||||||
|
e.waitUntil(
|
||||||
|
caches.open(cacheName).then(function(cache) {
|
||||||
|
console.log('[ServiceWorker] Caching app shell');
|
||||||
|
|
||||||
|
return cache.addAll(filesToCache);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', function(e) {
|
||||||
|
console.log('[ServiceWorker] Activate');
|
||||||
|
e.waitUntil(
|
||||||
|
caches.keys().then(function(keyList) {
|
||||||
|
return Promise.all(keyList.map(function(key) {
|
||||||
|
if (key !== cacheName && key !== dataCacheName) {
|
||||||
|
console.log('[ServiceWorker] Removing old cache', key);
|
||||||
|
|
||||||
|
return caches.delete(key);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixes a corner case in which the app wasn't returning the latest data.
|
||||||
|
* You can reproduce the corner case by commenting out the line below and
|
||||||
|
* then doing the following steps: 1) load app for first time so that the
|
||||||
|
* initial New York City data is shown 2) press the refresh button on the
|
||||||
|
* app 3) go offline 4) reload the app. You expect to see the newer NYC
|
||||||
|
* data, but you actually see the initial data. This happens because the
|
||||||
|
* service worker is not yet activated. The code below essentially lets
|
||||||
|
* you activate the service worker faster.
|
||||||
|
*/
|
||||||
|
return self.clients.claim();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('fetch', function(e) {
|
||||||
|
console.warn('[Service Worker] Fetch', e.request.url);
|
||||||
|
const dataUrl = '/getnexttraintimes?';
|
||||||
|
if (e.request.url.indexOf(dataUrl) > -1) {
|
||||||
|
console.log('!');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the request URL contains dataUrl, the app is asking for fresh
|
||||||
|
* weather data. In this case, the service worker always goes to the
|
||||||
|
* network and then caches the response. This is called the "Cache then
|
||||||
|
* network" strategy:
|
||||||
|
* https://jakearchibald.com/2014/offline-cookbook/#cache-then-network
|
||||||
|
*/
|
||||||
|
e.respondWith(
|
||||||
|
caches.open(dataCacheName).then(function(cache) {
|
||||||
|
return fetch(e.request).then(function(response) {
|
||||||
|
cache.put(e.request.url, response.clone());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The app is asking for app shell files. In this scenario the app uses the
|
||||||
|
* "Cache, falling back to the network" offline strategy:
|
||||||
|
* https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network
|
||||||
|
*/
|
||||||
|
e.respondWith(
|
||||||
|
caches.match(e.request).then(function(response) {
|
||||||
|
return response || fetch(e.request);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
@ -30,10 +30,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<style lang="scss" global>
|
<style lang="scss" global>
|
||||||
@import "node_modules/spectre.css/src/spectre.scss";
|
@import "./css/global.scss";
|
||||||
/* @import "./css/custom.scss";*/
|
|
||||||
/*@import './fonts/fonts.css';
|
|
||||||
@import './fonts/gotham.css';*/
|
|
||||||
@import './fonts/fujicons.css';
|
@import './fonts/fujicons.css';
|
||||||
|
|
||||||
.up,
|
.up,
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
import {pop} from 'svelte-spa-router';
|
import {pop} from 'svelte-spa-router';
|
||||||
|
|
||||||
export let page;
|
export let page;
|
||||||
|
let showFav = false;
|
||||||
|
|
||||||
let titleText = 'Traintimes';
|
let titleText = 'Traintimes';
|
||||||
$: currentMode = (page === 'Home') ? 0 : 1;
|
$: currentMode = (page === 'Home') ? 0 : 1;
|
||||||
|
|
||||||
@ -9,42 +11,49 @@
|
|||||||
pop();
|
pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goHome() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/*#appbar-more-vert {
|
/*#appbar-more-vert {
|
||||||
width: 31px;
|
width: 31px;
|
||||||
height: 31px;
|
height: 31px;
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
#appbar-more-vert {
|
#appbar-more-vert {
|
||||||
line-height: 31px;
|
line-height: 31px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}*/
|
}*/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<header class="navbar bg-primary">
|
<header class="navbar bg-primary">
|
||||||
|
|
||||||
<section class="navbar-section">
|
|
||||||
{#if currentMode === 1}
|
|
||||||
<span on:click={goBack} class="" >
|
|
||||||
<i class="fa-2x fa fa-back" style="color:white;"></i>
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
|
|
||||||
<span class="text-bold navbar-brand mx-2 text-uppercase">{titleText}</span>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section class="navbar-section">
|
<section class="navbar-section">
|
||||||
<a href="/#/settings" class="btn btn-link text-secondary">Settings</a>
|
{#if currentMode === 1}
|
||||||
<a href="/#/favourites" class="btn btn-link text-secondary">Favourites</a>
|
<span on:click={goBack} class="">
|
||||||
|
<i class="fa-2x fa fa-back-chevron" style="color:white;"></i>
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
<span class="text-bold navbar-brand mx-1 text-uppercase">{titleText}</span>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<section class="navbar-section text-right">
|
||||||
|
<a href="/#/tweets" class="btn bg-primary ">Tweets</a>
|
||||||
|
<a href="/#/settings" class="btn bg-primary ">Settings</a>
|
||||||
|
{#if showFav}
|
||||||
|
<a href="/#/favourites" class="btn bg-primary">Favourites</a>
|
||||||
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,21 +1,40 @@
|
|||||||
<script>
|
<script>
|
||||||
import SettingsInput from "./SettingsInput.svelte";
|
import SettingsInput from "./SettingsInput.svelte";
|
||||||
|
import {state} from '../store/store';
|
||||||
|
|
||||||
|
let editorVisible = false;
|
||||||
|
let itemId;
|
||||||
let startStation;
|
let startStation;
|
||||||
let destStation;
|
let destStation;
|
||||||
let deleteEnabled = false;
|
let deleteEnabled = !(typeof startStation === 'string');
|
||||||
|
let canSave;
|
||||||
|
|
||||||
function deleteItem(){
|
$: {
|
||||||
|
console.log('typeof startStation', typeof startStation);
|
||||||
|
canSave = (typeof startStation === 'object') && (typeof destStation === 'object');
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem() {
|
||||||
console.log('>> Delete item');
|
console.log('>> Delete item');
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeEditor() {
|
function closeEditor() {
|
||||||
console.log('>> Close item');
|
// console.log('>> Close item');
|
||||||
|
|
||||||
|
startStation = '';
|
||||||
|
destStation = '';
|
||||||
|
editorVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveEditor() {
|
async function saveEditor() {
|
||||||
console.log('>> Save editor');
|
// console.log('>> Save editor');
|
||||||
|
await state.saveRoute({startStation, destStation});
|
||||||
|
|
||||||
|
closeEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
function newEditor() {
|
||||||
|
editorVisible = true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -23,38 +42,42 @@
|
|||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<span>SettingsEditor</span>
|
{#if editorVisible}
|
||||||
<div class="mui-container ">
|
<div class="container ">
|
||||||
<div class="mui-row card">
|
<div class="mui-row card">
|
||||||
<div class="mui--text-headline">New Route</div>
|
<div class="text-subhead">New Route</div>
|
||||||
<div class="mui--align-middle">
|
<div class="grid-3">
|
||||||
<div class='mui-col-xs-12 mui-col-md-5'>
|
<div class=''>
|
||||||
<SettingsInput bind:returnValue={startStation} label="Departure Station" name="startStation"/>
|
<SettingsInput bind:returnValue={startStation} label="Departure Station" name="startStation"/>
|
||||||
|
</div>
|
||||||
|
<div class='text-center'>
|
||||||
|
<i class="fa fa-thick-arrow fa-2x mui--align-middle"></i>
|
||||||
|
</div>
|
||||||
|
<div class=''>
|
||||||
|
<SettingsInput bind:returnValue={destStation} label="Destination Station" name="destStation"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class='mui-col-xs-12 mui-col-md-2'>
|
|
||||||
<i class="fa fa-thick-arrow fa-2x mui--align-middle">
|
<div class="my text-right">
|
||||||
</div>
|
|
||||||
<div class='mui-col-xs-12 mui-col-md-5'>
|
<button class="btn btn-sm" type="button" on:click={closeEditor}>
|
||||||
<SettingsInput bind:returnValue={destStation} label="Destination Station" name="destStation"/>
|
Close
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary btn-sm" id="save" type="button" on:click={saveEditor} disabled={!canSave}>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="my text-right">
|
{:else}
|
||||||
<button class="btn btn-danger btn-sm" id="delete" type="button" disabled={deleteEnabled} on:click={deleteItem}>
|
<div>
|
||||||
Delete
|
<button class="btn btn-primary" id="new" type="button" on:click={newEditor}>
|
||||||
</button>
|
Add a new route
|
||||||
<button class="btn btn-sm" type="button" on:click={closeEditor}>
|
</button>
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-primary btn-sm" id="save" type="button" on:click={saveEditor}>
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
|
||||||
</div>
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
import {onMount} from 'svelte';
|
import {onMount} from 'svelte';
|
||||||
import {searchStation} from '../libs/stations';
|
import {searchStation} from '../libs/stations';
|
||||||
|
|
||||||
export let returnValue;
|
export let returnValue = '';
|
||||||
export let value;
|
let value = '';
|
||||||
|
|
||||||
export let name;
|
export let name;
|
||||||
export let label;
|
export let label;
|
||||||
@ -12,22 +12,32 @@
|
|||||||
let debouncedDoSearch;
|
let debouncedDoSearch;
|
||||||
let searchResults = [];
|
let searchResults = [];
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (returnValue === '') {
|
||||||
|
value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// $: visible = (searchResults.length > 0) ?
|
// $: visible = (searchResults.length > 0) ?
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
debouncedDoSearch = debounce(doSearch, 500);
|
debouncedDoSearch = debounce(doSearch, 750);
|
||||||
});
|
});
|
||||||
|
|
||||||
function doSearch() {
|
function doSearch() {
|
||||||
returnValue = '';
|
returnValue = '';
|
||||||
|
// console.log(`doSearch ${name}`, value)
|
||||||
if (value.length >= 2)
|
if (value.length >= 2)
|
||||||
searchResults = searchStation(value);
|
searchResults = searchStation(value);
|
||||||
|
else
|
||||||
|
searchResults = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectItem(e) {
|
function selectItem(e) {
|
||||||
|
// console.log('>> selectItem', e);
|
||||||
let [id, name] = e.target.dataset.content.split(',');
|
let [id, name] = e.target.dataset.content.split(',');
|
||||||
|
|
||||||
returnValue = id;
|
returnValue = {id,name};
|
||||||
value = name;
|
value = name;
|
||||||
|
|
||||||
searchResults = [];
|
searchResults = [];
|
||||||
@ -41,7 +51,7 @@
|
|||||||
|
|
||||||
<span class="mui-dropdown--right">
|
<span class="mui-dropdown--right">
|
||||||
<label for={name}>{label}</label>
|
<label for={name}>{label}</label>
|
||||||
<input {name} on:keyup={debouncedDoSearch} bind:value />
|
<input autocomplete="off" {name} on:keyup={debouncedDoSearch} bind:value />
|
||||||
{#if searchResults.length > 0}
|
{#if searchResults.length > 0}
|
||||||
<ul class="mui-dropdown__menu mui--is-open">
|
<ul class="mui-dropdown__menu mui--is-open">
|
||||||
{#each searchResults as item, index}
|
{#each searchResults as item, index}
|
||||||
|
@ -1,12 +1,20 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import {state} from '../store/store';
|
||||||
|
import SettingsListItem from "./SettingsListItem.svelte";
|
||||||
|
|
||||||
|
let _routes = [];
|
||||||
|
|
||||||
|
state.routes.subscribe(async (v) => {
|
||||||
|
_routes = v;
|
||||||
|
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
* {
|
|
||||||
background: #f55a4e;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<span>SettingsList</span>
|
{#each _routes as item, i (item.id)}
|
||||||
|
<SettingsListItem item={item} id={i}/>
|
||||||
|
|
||||||
|
{/each}
|
||||||
|
60
src/components/SettingsListItem.svelte
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<script>
|
||||||
|
import { longpress } from '../libs/longpress.js';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
import {state} from '../store/store.js';
|
||||||
|
|
||||||
|
export let item;
|
||||||
|
export let id;
|
||||||
|
let buttonsVisible = false;
|
||||||
|
let duration = 1000;
|
||||||
|
|
||||||
|
function deleteItem() {
|
||||||
|
console.log(`delete: ${id}`);
|
||||||
|
buttonsVisible = false;
|
||||||
|
state.deleteRoute(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeEditor() {
|
||||||
|
buttonsVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveEditor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.grid-3 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-gap: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div out:slide|local>
|
||||||
|
<div class="grid card ">
|
||||||
|
<div class="col-5">{item.startStation.name}</div>
|
||||||
|
<div class="col-1"><i class="fa fa-thick-arrow fa-1x mui--align-middle"></i></div>
|
||||||
|
<div class="col-5">{item.destStation.name}</div>
|
||||||
|
<div class="col-1"><button class="btn btn-sm" on:click="{() => buttonsVisible = !buttonsVisible}"><i class="fa fa-menu"></i></button></div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if buttonsVisible}
|
||||||
|
<div class="my grid-3" transition:slide>
|
||||||
|
<button class="btn btn-danger btn-sm" id="delete" type="button" on:click={deleteItem}>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary btn-sm" id="save" type="button" on:click={saveEditor}>
|
||||||
|
Edit
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-sm" type="button" on:click={closeEditor}>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
@ -1,8 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import {onMount, onDestroy} from 'svelte';
|
import {onMount, onDestroy} from 'svelte';
|
||||||
import axios from 'axios';
|
import { fade } from 'svelte/transition';
|
||||||
|
import axios from 'redaxios';
|
||||||
import {push} from 'svelte-spa-router';
|
import {push} from 'svelte-spa-router';
|
||||||
|
|
||||||
|
import {state} from '../store/store';
|
||||||
import reducer from '../libs/reducer';
|
import reducer from '../libs/reducer';
|
||||||
|
|
||||||
export let fromStation;
|
export let fromStation;
|
||||||
@ -10,11 +12,23 @@
|
|||||||
|
|
||||||
let list = []
|
let list = []
|
||||||
let otherDetails = {};
|
let otherDetails = {};
|
||||||
let baseUrl = 'http://localhost:8100';
|
let baseUrl = state.getBaseUrl();
|
||||||
let doUpdate = true;
|
let doUpdate = true;
|
||||||
|
|
||||||
|
let fetchInterval;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
|
||||||
await fetchData();
|
await fetchData();
|
||||||
|
|
||||||
|
fetchInterval = setInterval(async () => {
|
||||||
|
console.log('Timetable update')
|
||||||
|
await fetchData();
|
||||||
|
}, 120000);
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(async () => {
|
||||||
|
clearInterval(fetchInterval);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
@ -23,8 +37,9 @@
|
|||||||
const url = baseUrl.concat(routeUrl)
|
const url = baseUrl.concat(routeUrl)
|
||||||
await axios.get(url)
|
await axios.get(url)
|
||||||
.then((d) => {
|
.then((d) => {
|
||||||
list = reducer.reduceTrainTimetable(d.data)
|
const data = JSON.parse(d.data);
|
||||||
otherDetails = reducer.reduceOtherDetails(d.data)
|
list = reducer.reduceTrainTimetable(data)
|
||||||
|
otherDetails = reducer.reduceOtherDetails(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,10 +57,10 @@
|
|||||||
<div>
|
<div>
|
||||||
<section>
|
<section>
|
||||||
{#if otherDetails.nrMessagesExist === true}
|
{#if otherDetails.nrMessagesExist === true}
|
||||||
<div class="mui--bg-danger mui--text-white nrccAlert" style="padding:2px;">
|
<div class="nrccAlert" style="padding:2px;">
|
||||||
<ul>
|
<ul>
|
||||||
{#each otherDetails.nrMessages as item}
|
{#each otherDetails.nrMessages as item}
|
||||||
<li><i class="fa fa-info mui--align-middle"></i> {item.msg}
|
<li class="alert bg-danger"><i class="fa fa-info mui--align-middle"></i> {item.msg}
|
||||||
{#if item.link}
|
{#if item.link}
|
||||||
<a href={item.link}>{item.linkText}</a>
|
<a href={item.link}>{item.linkText}</a>
|
||||||
{/if}
|
{/if}
|
||||||
@ -59,9 +74,9 @@
|
|||||||
|
|
||||||
{#if list.length > 0}
|
{#if list.length > 0}
|
||||||
|
|
||||||
{#each list as item}
|
{#each list as item, i (item.serviceIdUrlSafe)}
|
||||||
<div class="mui-row card mui--align-bottom">
|
<div class="grid card mui--align-bottom" transition:fade|local>
|
||||||
<div class="mui-col-xs-5 mui-col-md-4 mui--align-middle">
|
<div class="col-5 mui--align-middle">
|
||||||
<span on:click={viewService(item.serviceIdUrlSafe)}>{item.location}</span>
|
<span on:click={viewService(item.serviceIdUrlSafe)}>{item.location}</span>
|
||||||
<span class="mui--text-accent">{item.carriageCount}</span>
|
<span class="mui--text-accent">{item.carriageCount}</span>
|
||||||
<div>
|
<div>
|
||||||
@ -70,13 +85,13 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mui-col-xs-2 mui-col-md-3 mui--text-center mui--align-middle time">{item.time}</div>
|
<div class="col-2 text-center mui--align-middle time">{item.time}</div>
|
||||||
|
|
||||||
{#if item.isCancelled}
|
{#if item.isCancelled}
|
||||||
<div class="mui-col-xs-5 mui-col-md-5 mui--text-center mui--align-middle delayed"><i class="fa fa-alert fa-1x mui--align-middle"></i>{item.cancel}</div>
|
<div class="col-5 text-center mui--align-middle delayed"><i class="fa fa-alert fa-1x mui--align-middle"></i>{item.cancel}</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--text-center mui--align-middle {item.statusMode}">{item.status}</div>
|
<div class="col-3 text-center mui--align-middle {item.statusMode}">{item.status}</div>
|
||||||
<div class="mui-col-xs-2 mui-col-md-2 mui--text-center mui--align-middle">{item.platform}</div>
|
<div class="col-2 text-center mui--align-middle">{item.platform}</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
import {findStation} from '../libs/stations'
|
import {findStation} from '../libs/stations'
|
||||||
import {minuteFloor, LocalStorage} from '../libs/utils'
|
import {minuteFloor, LocalStorage} from '../libs/utils'
|
||||||
import {push} from 'svelte-spa-router';
|
import {push} from 'svelte-spa-router';
|
||||||
import axios from 'axios';
|
import axios from 'redaxios';
|
||||||
|
|
||||||
|
import {state} from '../store/store';
|
||||||
|
|
||||||
import {onMount, onDestroy} from 'svelte';
|
import {onMount, onDestroy} from 'svelte';
|
||||||
|
|
||||||
@ -12,7 +15,7 @@
|
|||||||
let startStationName;
|
let startStationName;
|
||||||
let destStationName;
|
let destStationName;
|
||||||
let url;
|
let url;
|
||||||
let baseUrl = 'http://localhost:8100';
|
let baseUrl = state.getBaseUrl();
|
||||||
let displayTime;
|
let displayTime;
|
||||||
let trainData = {eta: 'OFF', sta: 'OFF'};
|
let trainData = {eta: 'OFF', sta: 'OFF'};
|
||||||
let status;
|
let status;
|
||||||
@ -81,20 +84,51 @@
|
|||||||
const workingUrl = url.concat(`&mh=${minuteHash}`)
|
const workingUrl = url.concat(`&mh=${minuteHash}`)
|
||||||
axios.get(workingUrl)
|
axios.get(workingUrl)
|
||||||
.then((d) => {
|
.then((d) => {
|
||||||
trainData = {...d.data}
|
trainData = {...JSON.parse(d.data)};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.entry {
|
.TRcard {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.7rem 0rem;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
opacity: 0.9;
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
border-bottom-color: #666666;
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
|
||||||
|
0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.TRcard .entry {
|
||||||
|
align-items: left;
|
||||||
|
display: flex;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
/* -ms-flex: 1 0 0;
|
||||||
|
flex: 1 0 0;*/
|
||||||
|
-ms-flex-align: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.TRcard .entry:not(:first-child):last-child {
|
||||||
|
-ms-flex-pack: end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
align-items: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entryOld {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
margin: 6px 0;
|
margin: 6px 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.TRcard {
|
.TRcardOld {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
@ -111,11 +145,11 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="columns TRcard">
|
<div class="columns TRcard">
|
||||||
<div class='column col-7 entry'>
|
<div class='entry ml-1'>
|
||||||
<div>{startStationName}</div>
|
<div>{startStationName}</div>
|
||||||
<div>{destStationName}</div>
|
<div>{destStationName}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='column col-5 text-right entry'>
|
<div class='entry text-right'>
|
||||||
<span class="btn {status}" on:click={onClick}>{displayTime}</span>
|
<span class="btn {status}" on:click={onClick}>{displayTime}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
<script>
|
<script>
|
||||||
import {onMount, onDestroy} from 'svelte';
|
import {onMount, onDestroy} from 'svelte';
|
||||||
import {minuteFloor, LocalStorage} from '../libs/utils'
|
import axios from 'redaxios';
|
||||||
import axios from 'axios';
|
|
||||||
|
import {state} from '../store/store';
|
||||||
import reducer from '../libs/reducer';
|
import reducer from '../libs/reducer';
|
||||||
|
|
||||||
export let serviceId;
|
export let serviceId;
|
||||||
|
|
||||||
let list = [];
|
let list = [];
|
||||||
let baseUrl = 'http://localhost:8100';
|
let baseUrl = state.getBaseUrl();
|
||||||
let doUpdate = true;
|
let doUpdate = true;
|
||||||
let serviceInterval;
|
let serviceInterval;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
fetchServiceData();
|
await fetchServiceData();
|
||||||
|
|
||||||
serviceInterval = setInterval(() => {
|
serviceInterval = setInterval(async () => {
|
||||||
console.log('Do service update')
|
console.log('Service update')
|
||||||
fetchServiceData()
|
await fetchServiceData()
|
||||||
}, 120000);
|
}, 120000);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -24,17 +25,14 @@
|
|||||||
clearInterval(serviceInterval);
|
clearInterval(serviceInterval);
|
||||||
});
|
});
|
||||||
|
|
||||||
function fetchServiceData() {
|
async function fetchServiceData() {
|
||||||
console.log('>> TrainService: fetchServiceData');
|
|
||||||
// http://localhost:8100/getservice?serviceid=TDKWvQdeuviRyNYP7lk7gA
|
|
||||||
if (doUpdate === true) {
|
if (doUpdate === true) {
|
||||||
const routeUrl = `/getservice?serviceid=${serviceId}`
|
const routeUrl = `/getservice?serviceid=${serviceId}`
|
||||||
const url = baseUrl.concat(routeUrl)
|
const url = baseUrl.concat(routeUrl)
|
||||||
axios.get(url)
|
await axios.get(url)
|
||||||
.then((d) => {
|
.then((d) => {
|
||||||
console.log(d);
|
const data = JSON.parse(d.data);
|
||||||
list = reducer.reduceTrainService(d.data);
|
list = reducer.reduceTrainService(data);
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,19 +43,19 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="mui-row card mui--align-bottom">
|
<div class="grid card text-subhead">
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Station</div>
|
<div class="col-3 text-center">Station</div>
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Due</div>
|
<div class="col-3 text-center">Due</div>
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Estimated</div>
|
<div class="col-3 text-center">Estimated</div>
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Arrived</div>
|
<div class="col-3 text-center">Arrived</div>
|
||||||
</div>
|
</div>
|
||||||
{#if list.length > 0}
|
{#if list.length > 0}
|
||||||
{#each list as item}
|
{#each list as item}
|
||||||
<div class="mui-row card mui--align-bottom {item.classCancel}">
|
<div class="grid card {item.classCancel}">
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">{item.locationName}</div>
|
<div class="col-3 text-center">{item.locationName}</div>
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">{item.st}</div>
|
<div class="col-3 text-center">{item.st}</div>
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle {item.etMode}">{item.et}</div>
|
<div class="col-3 text-center {item.etMode}">{item.et}</div>
|
||||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle {item.atMode}">{item.at}</div>
|
<div class="col-3 text-center {item.atMode}">{item.at}</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
64
src/components/Twitter.svelte
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<script>
|
||||||
|
import {onMount, onDestroy} from 'svelte';
|
||||||
|
import {state} from '../store/store';
|
||||||
|
|
||||||
|
export let id;
|
||||||
|
|
||||||
|
let tweetData;
|
||||||
|
let tweet;
|
||||||
|
let inReply = false;
|
||||||
|
let tweetBody = ''
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (tweet) {
|
||||||
|
inReply = (tweet && tweet.in_reply_to_status_id !== null);
|
||||||
|
tweetBody = (tweet && tweet.truncated) ? tweet.extended_tweet.full_text : tweet.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
tweetData = state.getTweetByID(id);
|
||||||
|
tweet = JSON.parse(tweetData.tweet);
|
||||||
|
});
|
||||||
|
|
||||||
|
function viaImgCache(url) {
|
||||||
|
const cache = (true) ? 'https://image.silvrtree.co.uk/48,fit,q80/' : '';
|
||||||
|
return `${cache}${url}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.avatar {
|
||||||
|
max-width: 48px;
|
||||||
|
max-height: 48px;
|
||||||
|
border-radius: 0.1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{#if tweet}
|
||||||
|
<div class="card">
|
||||||
|
<blockquote>
|
||||||
|
<div class="tweet-header">
|
||||||
|
<div class="grid">
|
||||||
|
<img class='avatar col-2' src={viaImgCache(tweet.user.profile_image_url_https)} alt="@{tweet.user.screen_name}"/>
|
||||||
|
<div class="col-10 ml-2">
|
||||||
|
<div class="text-subhead">{tweet.user.name}</div>
|
||||||
|
<div>@{tweet.user.screen_name}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if inReply}
|
||||||
|
<div>
|
||||||
|
Replying to @{tweet.in_reply_to_screen_name}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="tweetBody">
|
||||||
|
{tweetBody}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<small class="text-highlight2">{tweet.created_at}</small>
|
||||||
|
</div>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
{/if}
|
199
src/components/TwitterSettings.svelte
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
<script>
|
||||||
|
import {state} from '../store/store';
|
||||||
|
import {onMount, onDestroy} from 'svelte';
|
||||||
|
|
||||||
|
let _following;
|
||||||
|
let mounted = false;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
_following = state.getTwitterFollowing();
|
||||||
|
mounted=(Object.keys(_following).length > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(async () => {
|
||||||
|
state.saveTwitterFollowing(_following);
|
||||||
|
});
|
||||||
|
|
||||||
|
state.twitterFollowing.subscribe(async (v) => {
|
||||||
|
_following = v;
|
||||||
|
mounted=(Object.keys(_following).length > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
label {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container ">
|
||||||
|
<div class="text-dark text-subhead">Twitter</div>
|
||||||
|
{#if mounted}
|
||||||
|
<div class="grid-1">
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.nationalrailenq.follow}>
|
||||||
|
@nationalrailenq
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.networkrail.follow}>
|
||||||
|
@networkrail
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailSCOT.follow}>
|
||||||
|
@NetworkRailSCOT
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.AvantiWestCoast.follow}>
|
||||||
|
@AvantiWestCoast
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.CalSleeper.follow}>
|
||||||
|
@CalSleeper
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.CrossCountryUK.follow}>
|
||||||
|
@CrossCountryUK
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.Eurostar.follow}>
|
||||||
|
@Eurostar
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.EurostarUK.follow}>
|
||||||
|
@EurostarUK
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.GatwickExpress.follow}>
|
||||||
|
@GatwickExpress
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.GlasgowSubway.follow}>
|
||||||
|
@GlasgowSubway
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.GWRHelp.follow}>
|
||||||
|
@GWRHelp
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.HeathrowExpress.follow}>
|
||||||
|
@HeathrowExpress
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.LNER.follow}>
|
||||||
|
@LNER
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.LNRailway.follow}>
|
||||||
|
@LNRailway
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.northernassist.follow}>
|
||||||
|
@northernassist
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.ScotRail.follow}>
|
||||||
|
@ScotRail
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.Stansted_Exp.follow}>
|
||||||
|
@Stansted_Exp
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.TfL.follow}>
|
||||||
|
@TfL
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailBHM.follow}>
|
||||||
|
@NetworkRailBHM
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailEDB.follow}>
|
||||||
|
@NetworkRailEDB
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailEUS.follow}>
|
||||||
|
@NetworkRailEUS
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailGLC.follow}>
|
||||||
|
@NetworkRailGLC
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailKGX.follow}>
|
||||||
|
@NetworkRailKGX
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailLST.follow}>
|
||||||
|
@NetworkRailLST
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailMAN.follow}>
|
||||||
|
@NetworkRailMAN
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.NetworkRailVIC.follow}>
|
||||||
|
@NetworkRailVIC
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-body">
|
||||||
|
<input type="checkbox" bind:checked={_following.BTPScotland.follow}>
|
||||||
|
@BTPScotland
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</div>
|
277
src/css/entireframework.min.css
vendored
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/* Copyright 2014 Owen Versteeg; MIT licensed */
|
||||||
|
body, textarea, input, select {
|
||||||
|
background: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
font: 16px sans-serif;
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.smooth {
|
||||||
|
transition: all .2s
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn, .nav a {
|
||||||
|
text-decoration: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin: 0 20px;
|
||||||
|
width: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
label > * {
|
||||||
|
display: inline
|
||||||
|
}
|
||||||
|
|
||||||
|
form > * {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
background: #999;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 0;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 2px 0;
|
||||||
|
padding: 12px 30px 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background: #888
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:active, .btn:focus {
|
||||||
|
background: #777
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-a {
|
||||||
|
background: #0ae
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-a:hover {
|
||||||
|
background: #09d
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-a:active, .btn-a:focus {
|
||||||
|
background: #08b
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-b {
|
||||||
|
background: #3c5
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-b:hover {
|
||||||
|
background: #2b4
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-b:active, .btn-b:focus {
|
||||||
|
background: #2a4
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-c {
|
||||||
|
background: #d33
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-c:hover {
|
||||||
|
background: #c22
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-c:active, .btn-c:focus {
|
||||||
|
background: #b22
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sm {
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px 14px 11px
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
margin: 1% 0;
|
||||||
|
overflow: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
float: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.table, .c12 {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c11 {
|
||||||
|
width: 91.66%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c10 {
|
||||||
|
width: 83.33%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c9 {
|
||||||
|
width: 75%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c8 {
|
||||||
|
width: 66.66%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c7 {
|
||||||
|
width: 58.33%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c6 {
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c5 {
|
||||||
|
width: 41.66%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c4 {
|
||||||
|
width: 33.33%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c3 {
|
||||||
|
width: 25%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c2 {
|
||||||
|
width: 16.66%
|
||||||
|
}
|
||||||
|
|
||||||
|
.c1 {
|
||||||
|
width: 8.33%
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3em
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn, h2 {
|
||||||
|
font-size: 2em
|
||||||
|
}
|
||||||
|
|
||||||
|
.ico {
|
||||||
|
font: 33px Arial Unicode MS, Lucida Sans Unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
.addon, .btn-sm, .nav, textarea, input, select {
|
||||||
|
outline: 0;
|
||||||
|
font-size: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea, input, select {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ccc
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus, input:focus, select:focus {
|
||||||
|
border-color: #5ab
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea, input[type=text] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 13em
|
||||||
|
}
|
||||||
|
|
||||||
|
.addon {
|
||||||
|
padding: 8px 12px;
|
||||||
|
box-shadow: 0 0 0 1px #ccc
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav, .nav .current, .nav a:hover {
|
||||||
|
background: #000;
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
height: 24px;
|
||||||
|
padding: 11px 0 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a {
|
||||||
|
color: #aaa;
|
||||||
|
padding-right: 1em;
|
||||||
|
position: relative;
|
||||||
|
top: -1px
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav .pagename {
|
||||||
|
font-size: 22px;
|
||||||
|
top: 1px
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-close {
|
||||||
|
background: #000;
|
||||||
|
float: right;
|
||||||
|
font-size: 25px;
|
||||||
|
margin: -54px 7px;
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1310px) {
|
||||||
|
.container {
|
||||||
|
margin: auto;
|
||||||
|
width: 1270px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 870px) {
|
||||||
|
.row .col {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
.btn.btn-close {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagename {
|
||||||
|
margin-top: -11px
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav:active, .nav:focus {
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav div:before {
|
||||||
|
background: #000;
|
||||||
|
border-bottom: 10px double;
|
||||||
|
border-top: 3px solid;
|
||||||
|
content: '';
|
||||||
|
float: right;
|
||||||
|
height: 4px;
|
||||||
|
position: relative;
|
||||||
|
right: 3px;
|
||||||
|
top: 14px;
|
||||||
|
width: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a {
|
||||||
|
padding: .5em 0;
|
||||||
|
display: block;
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table th, .table td {
|
||||||
|
padding: .5em;
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody > :nth-child(2n-1) {
|
||||||
|
background: #ddd
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg {
|
||||||
|
padding: 1.5em;
|
||||||
|
background: #def;
|
||||||
|
border-left: 5px solid #59d
|
||||||
|
}
|
896
src/css/global.scss
Normal file
@ -0,0 +1,896 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css?family=Roboto+Condensed');
|
||||||
|
|
||||||
|
/* Global Styles */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--primary-color: #607D8B;
|
||||||
|
--dark-color: #294c5d;
|
||||||
|
--light-color: #CFD8DC;
|
||||||
|
--danger-color: #dc3545;
|
||||||
|
--success-color: #28a745;
|
||||||
|
--highlight-color: #dcc894;
|
||||||
|
--highlight-color2: #dca394;
|
||||||
|
|
||||||
|
--navbar-height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Roboto Condensed', sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.active{
|
||||||
|
color: var(--highlight-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataRow {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utilities */
|
||||||
|
.container {
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text Styles*/
|
||||||
|
.x-large {
|
||||||
|
font-size: 4rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.large {
|
||||||
|
font-size: 3rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-primary {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-dark {
|
||||||
|
color: var(--dark-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-success {
|
||||||
|
color: var(--success-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-danger {
|
||||||
|
color: var(--danger-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-highlight {
|
||||||
|
color: var(--highlight-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-highlight2 {
|
||||||
|
color: var(--highlight-color2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-lowercase {
|
||||||
|
text-transform: lowercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-uppercase {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-capitalize {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-title, h3 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-subhead, h4 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-body2, h5 {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-body1 {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-caption {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Center All */
|
||||||
|
.all-center {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cards */
|
||||||
|
.card {
|
||||||
|
padding: 1rem;
|
||||||
|
border: #ccc 1px dotted;
|
||||||
|
margin: 0.7rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List */
|
||||||
|
.list {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list li {
|
||||||
|
padding-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
.p {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
.p-1 {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.p-2 {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
.p-3 {
|
||||||
|
padding: 3rem;
|
||||||
|
}
|
||||||
|
.py {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
.py-1 {
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
.py-2 {
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
.py-3 {
|
||||||
|
padding: 3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Margin */
|
||||||
|
.m {
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
.m-1 {
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-1 {
|
||||||
|
margin-bottom: .2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-1 {
|
||||||
|
margin-left: .2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-1 {
|
||||||
|
margin-right: .2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-1 {
|
||||||
|
margin-top: .2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-1 {
|
||||||
|
margin-left: 1rem !important;
|
||||||
|
margin-right: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-2 {
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: .4rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-2 {
|
||||||
|
margin-left: .4rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-2 {
|
||||||
|
margin-right: .4rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: .4rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-2 {
|
||||||
|
margin-left: 2rem !important;
|
||||||
|
margin-right: 2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-3 {
|
||||||
|
margin: 3rem;
|
||||||
|
}
|
||||||
|
.my {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
.my-1 {
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
.my-2 {
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
.my-3 {
|
||||||
|
margin: 3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: flex;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
-ms-flex-wrap: wrap;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-left: -.4rem;
|
||||||
|
margin-right: -.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid */
|
||||||
|
.grid-1 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(1, 1fr);
|
||||||
|
grid-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-2 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
grid-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-3 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-4 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
grid-gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.column,
|
||||||
|
/*.columns {
|
||||||
|
margin-left: 4%; }
|
||||||
|
.column:first-child,
|
||||||
|
.columns:first-child {
|
||||||
|
margin-left: 0; }*/
|
||||||
|
|
||||||
|
.col-1 {
|
||||||
|
width: 8.33333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-2 {
|
||||||
|
width: 16.66667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-3 {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-4 {
|
||||||
|
width: 33.33333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-5 {
|
||||||
|
width: 41.66667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-6 {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-7 {
|
||||||
|
width: 58.33333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-8 {
|
||||||
|
width: 66.66667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-9 {
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-10 {
|
||||||
|
width: 83.33333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-11 {
|
||||||
|
width: 91.66667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-12 {
|
||||||
|
width: 100%;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-1-3rd {
|
||||||
|
width: 30.6666666667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-2-3rd {
|
||||||
|
width: 65.3333333333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-half {
|
||||||
|
width: 48%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Offsets */
|
||||||
|
.offset-1-col {
|
||||||
|
margin-left: 8.66666666667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-2-col {
|
||||||
|
margin-left: 17.3333333333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-3-col {
|
||||||
|
margin-left: 26%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-4-col {
|
||||||
|
margin-left: 34.6666666667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-5-col {
|
||||||
|
margin-left: 43.3333333333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-6-col {
|
||||||
|
margin-left: 52%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-7-col {
|
||||||
|
margin-left: 60.6666666667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-8-col {
|
||||||
|
margin-left: 69.3333333333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-9-col {
|
||||||
|
margin-left: 78.0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-10-col {
|
||||||
|
margin-left: 86.6666666667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-11-col {
|
||||||
|
margin-left: 95.3333333333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-1-3rd-col {
|
||||||
|
margin-left: 34.6666666667%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-2-3rd-col {
|
||||||
|
margin-left: 69.3333333333%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offset-half-col {
|
||||||
|
margin-left: 52%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--light-color);
|
||||||
|
color: #333;
|
||||||
|
padding: 0.4rem 1.3rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
transition: opacity 0.2s ease-in;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-link {
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-block {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sm {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 0.3rem 1rem;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 0.6rem;
|
||||||
|
padding: 0.1rem 0.4rem;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0.3rem;
|
||||||
|
background: var(--light-color);
|
||||||
|
color: #333;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
padding: 0.7rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
background: var(--light-color);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary,
|
||||||
|
.bg-primary,
|
||||||
|
.badge-primary,
|
||||||
|
.alert-primary {
|
||||||
|
background: var(--primary-color);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn-light,
|
||||||
|
.bg-light,
|
||||||
|
.badge-light,
|
||||||
|
.alert-light {
|
||||||
|
background: var(--light-color);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-dark,
|
||||||
|
.bg-dark,
|
||||||
|
.badge-dark,
|
||||||
|
.alert-dark {
|
||||||
|
background: var(--dark-color);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger,
|
||||||
|
.bg-danger,
|
||||||
|
.badge-danger,
|
||||||
|
.alert-danger {
|
||||||
|
background: var(--danger-color);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success,
|
||||||
|
.bg-success,
|
||||||
|
.badge-success,
|
||||||
|
.alert-success {
|
||||||
|
background: var(--success-color);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-white,
|
||||||
|
.bg-white,
|
||||||
|
.badge-white,
|
||||||
|
.alert-white {
|
||||||
|
background: #fff;
|
||||||
|
color: #333;
|
||||||
|
border: #ccc solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.60;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn:enabled:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-light,
|
||||||
|
.badge-light {
|
||||||
|
border: #ccc solid 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.round-img {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms */
|
||||||
|
input {
|
||||||
|
margin: .2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-text {
|
||||||
|
display: block;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='text'],
|
||||||
|
input[type='email'],
|
||||||
|
input[type='password'],
|
||||||
|
input[type='date'],
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.1rem;
|
||||||
|
/*font-size: 1.2rem;*/
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='submit'],
|
||||||
|
button {
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
label,
|
||||||
|
legend {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: .1rem;
|
||||||
|
font-weight: 600; }
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
display: inline; }
|
||||||
|
label > .label-body {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: .5rem;
|
||||||
|
font-weight: normal;
|
||||||
|
background-color: #dcc894;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table th,
|
||||||
|
table td {
|
||||||
|
padding: 1rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
background: var(--light-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navbar */
|
||||||
|
.navbar {
|
||||||
|
position:fixed;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.7rem 0rem;
|
||||||
|
z-index: 2;
|
||||||
|
width: 100%;
|
||||||
|
opacity: 0.9;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
min-height: var(--navbar-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.navbar ul {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar a {
|
||||||
|
color: #fff;
|
||||||
|
padding: 0.45rem;
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar a:hover {
|
||||||
|
color: var(--light-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .welcome span {
|
||||||
|
margin-right: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .navbar-section {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
-ms-flex: 1 0 0;
|
||||||
|
flex: 1 0 0;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .navbar-section:not(:first-child):last-child {
|
||||||
|
-ms-flex-pack: end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .navbar-brand {
|
||||||
|
font-size: 125%;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Mobile Styles */
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.hide-sm {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-2,
|
||||||
|
.grid-3,
|
||||||
|
.grid-4 {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text Styles */
|
||||||
|
.x-large {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.large {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navbar */
|
||||||
|
.navbar {
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar ul {
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*:root {
|
||||||
|
--primary-color: #64B5F6;
|
||||||
|
--dark-color: #333333;
|
||||||
|
--light-color: #f4f4f4;
|
||||||
|
--danger-color: #dc3545;
|
||||||
|
--success-color: #28a745;
|
||||||
|
--medium-color: #999999;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
.table-responsive {
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardV2 {
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 4px 0 rgba(0,0,0,.14), 0 3px 4px 0 rgba(0,0,0,.12), 0 1px 5px 0 rgba(0,0,0,.2);
|
||||||
|
/*display: flex;
|
||||||
|
flex-direction: column;*/
|
||||||
|
min-width: 0;
|
||||||
|
/*position: relative;
|
||||||
|
word-wrap: break-word;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-of-type(odd){
|
||||||
|
background-color: rgba(0,0,0,0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody td {
|
||||||
|
border-top: 1px solid #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin-top: 2.2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
border-width: 0;
|
||||||
|
border-top: 1px solid var(--dark-color); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.modalWindow {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
background: rgba(0,0,0,0.2);
|
||||||
|
z-index: 99999;
|
||||||
|
opacity:0;
|
||||||
|
pointer-events: none;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
.modalWindow:target {
|
||||||
|
opacity:1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.modalWindow > div {
|
||||||
|
width: 500px;
|
||||||
|
position: relative;
|
||||||
|
margin: 10% auto;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
header + div.container {
|
||||||
|
position: relative;
|
||||||
|
top:var(--navbar-height);
|
||||||
|
min-height: calc(100vh - var(--navbar-height));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MUI Dropdown module
|
||||||
|
*/
|
||||||
|
.mui-dropdown {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-mui-toggle="dropdown"] {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
min-width: 160px;
|
||||||
|
padding: 5px 3px;
|
||||||
|
margin: 2px 0 0;
|
||||||
|
list-style: none;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #FFF;
|
||||||
|
border-radius: 2px;
|
||||||
|
z-index: 1;
|
||||||
|
background-clip: padding-box;
|
||||||
|
border: 1px solid var(--light-color);
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
|
||||||
|
0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
||||||
|
.mui-dropdown__menu {
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
border-left: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (-ms-ime-align: auto) {
|
||||||
|
.mui-dropdown__menu {
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
border-left: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu.mui--is-open {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu > li > a {
|
||||||
|
display: block;
|
||||||
|
padding: 3px 20px;
|
||||||
|
clear: both;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 1.429;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu > li > a:hover, .mui-dropdown__menu > li > a:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu > .mui--is-disabled > a, .mui-dropdown__menu > .mui--is-disabled > a:hover, .mui-dropdown__menu > .mui--is-disabled > a:focus {
|
||||||
|
color: #EEEEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu > .mui--is-disabled > a:hover, .mui-dropdown__menu > .mui--is-disabled > a:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: none;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown__menu--right {
|
||||||
|
left: auto;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown--up > .mui-dropdown__menu {
|
||||||
|
margin: 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown--right > .mui-dropdown__menu {
|
||||||
|
margin: 0 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mui-dropdown--left > .mui-dropdown__menu {
|
||||||
|
margin: 0 2px 0 0;
|
||||||
|
}
|
29
src/libs/longpress.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export function longpress(node, duration) {
|
||||||
|
let timer;
|
||||||
|
|
||||||
|
const handleMousedown = () => {
|
||||||
|
console.log('>> handleMousedown');
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
node.dispatchEvent(
|
||||||
|
new CustomEvent('longpress')
|
||||||
|
);
|
||||||
|
}, duration);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseup = () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
};
|
||||||
|
|
||||||
|
node.addEventListener('mousedown', handleMousedown);
|
||||||
|
node.addEventListener('mouseup', handleMouseup);
|
||||||
|
|
||||||
|
return {
|
||||||
|
update(newDuration) {
|
||||||
|
duration = newDuration;
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
node.removeEventListener('mousedown', handleMousedown);
|
||||||
|
node.removeEventListener('mouseup', handleMouseup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -41,7 +41,7 @@ const reducer = {
|
|||||||
const symbol = ['💠', '🚉'];
|
const symbol = ['💠', '🚉'];
|
||||||
if (typeof data === 'object' && data !== null) {
|
if (typeof data === 'object' && data !== null) {
|
||||||
console.log('>> reduceTrainService');
|
console.log('>> reduceTrainService');
|
||||||
console.log(data);
|
// console.log(data);
|
||||||
if (typeof data.trainServices === 'object' && data.trainServices !== null)
|
if (typeof data.trainServices === 'object' && data.trainServices !== null)
|
||||||
for (const item of data.trainServices) {
|
for (const item of data.trainServices) {
|
||||||
// console.log(item)
|
// console.log(item)
|
||||||
@ -86,7 +86,7 @@ const reducer = {
|
|||||||
services.push({ 'location': dest.locationName, 'time': time, 'status': status, 'platform': platform, 'cancel': item.cancelReason, 'type': 'bus', 'via': via });
|
services.push({ 'location': dest.locationName, 'time': time, 'status': status, 'platform': platform, 'cancel': item.cancelReason, 'type': 'bus', 'via': via });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(services);
|
console.log(services);
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
},
|
},
|
||||||
|
24
src/main.js
@ -1,5 +1,7 @@
|
|||||||
import App from './App.svelte';
|
import App from './App.svelte';
|
||||||
|
|
||||||
|
import { state } from './store/store';
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
'target': document.body,
|
'target': document.body,
|
||||||
'props': {
|
'props': {
|
||||||
@ -7,4 +9,26 @@ const app = new App({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
//
|
||||||
|
navigator.serviceWorker.ready.then(function(reg) {
|
||||||
|
console.warn('Ready??', reg);
|
||||||
|
// main();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register('./service-worker.js')
|
||||||
|
.then((r) => {
|
||||||
|
console.warn('Service Worker Registered', r.scope);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// registration failed
|
||||||
|
console.error(`Registration failed with ${ error}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
25
src/pages/Favourites.svelte
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<script>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
background: #f55a4e;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1>Favourites</h1>
|
||||||
|
|
||||||
|
<div class="grid-2">
|
||||||
|
<div>a</div>
|
||||||
|
<div>b</div>
|
||||||
|
<div>c</div>
|
||||||
|
<div>d</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,10 +1,24 @@
|
|||||||
<script>
|
<script>
|
||||||
import TrainRoute from "../components/TrainRoute.svelte";
|
import TrainRoute from "../components/TrainRoute.svelte";
|
||||||
|
import {state} from '../store/store';
|
||||||
|
|
||||||
|
let _routes = [];
|
||||||
|
|
||||||
|
state.routes.subscribe(async (v) => {
|
||||||
|
_routes = v;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<TrainRoute destStation="glq" startStation="dbe"/>
|
{#each _routes as item}
|
||||||
|
<TrainRoute destStation={item.destStation.id} startStation={item.startStation.id}/>
|
||||||
|
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <TrainRoute destStation="glq" startStation="dbe"/>
|
||||||
<TrainRoute destStation="dbe" startStation="glq"/>
|
<TrainRoute destStation="dbe" startStation="glq"/>
|
||||||
<TrainRoute destStation="glc" startStation="ptk"/>
|
<TrainRoute destStation="glc" startStation="ptk"/>
|
||||||
<TrainRoute destStation="ptk" startStation="dbe"/>
|
<TrainRoute destStation="ptk" startStation="dbe"/>
|
||||||
@ -14,7 +28,7 @@
|
|||||||
<TrainRoute destStation="glc" startStation="bhi"/>
|
<TrainRoute destStation="glc" startStation="bhi"/>
|
||||||
<TrainRoute destStation="bhi" startStation="glc"/>
|
<TrainRoute destStation="bhi" startStation="glc"/>
|
||||||
<TrainRoute destStation="dbe" startStation="dmr"/>
|
<TrainRoute destStation="dbe" startStation="dmr"/>
|
||||||
<TrainRoute destStation="dmr" startStation="glc"/>
|
<TrainRoute destStation="dmr" startStation="glc"/>-->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="mui--appbar-height"></div>
|
<div class="container">
|
||||||
<div class="mui-container">
|
|
||||||
<TrainService {serviceId}/>
|
<TrainService {serviceId}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import SettingsEditor from "../components/SettingsEditor.svelte";
|
import SettingsEditor from "../components/SettingsEditor.svelte";
|
||||||
import SettingsList from "../components/SettingsList.svelte";
|
import SettingsList from "../components/SettingsList.svelte";
|
||||||
|
import TwitterSettings from "../components/TwitterSettings.svelte";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -9,8 +10,10 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<span>Settings</span>
|
<div class="text-dark text-subhead">Settings</div>
|
||||||
|
|
||||||
<SettingsEditor/>
|
<SettingsEditor/>
|
||||||
<SettingsList/>
|
<SettingsList/>
|
||||||
|
<hr/>
|
||||||
|
<TwitterSettings/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div>
|
<div>
|
||||||
<div class="mui--text-center mui--text-accent">{fromStationName} TO {destStationName}</div>
|
<div class="text-center text-dark text-subhead">{fromStationName} TO {destStationName}</div>
|
||||||
<TimetableList {fromStation} {destStation}/>
|
<TimetableList {fromStation} {destStation}/>
|
||||||
|
|
||||||
<!--<timetable-list :fromStation="$route.params.fromStation" :destStation="$route.params.destStation"/>-->
|
<!--<timetable-list :fromStation="$route.params.fromStation" :destStation="$route.params.destStation"/>-->
|
||||||
|
39
src/pages/Twitter.svelte
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script>
|
||||||
|
import {onMount, onDestroy} from 'svelte';
|
||||||
|
import {state} from '../store/store';
|
||||||
|
import Twitter from "../components/Twitter.svelte";
|
||||||
|
|
||||||
|
let _tweets = [];
|
||||||
|
|
||||||
|
let serviceInterval;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
await state.getTweets();
|
||||||
|
|
||||||
|
serviceInterval = setInterval(async () => {
|
||||||
|
console.log('Twitter update')
|
||||||
|
await state.getTweets();
|
||||||
|
}, 300000);
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(async () => {
|
||||||
|
clearInterval(serviceInterval);
|
||||||
|
});
|
||||||
|
|
||||||
|
state.tweetList.subscribe(async (v) => {
|
||||||
|
_tweets = v;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="text-subhead">Twitter</div>
|
||||||
|
{#each _tweets as item, i (item)}
|
||||||
|
<Twitter id={item}/>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
</div>
|
@ -11,6 +11,8 @@ import Home from './pages/Home.svelte';
|
|||||||
import Service from './pages/Service.svelte';
|
import Service from './pages/Service.svelte';
|
||||||
import Timetable from './pages/Timetable.svelte';
|
import Timetable from './pages/Timetable.svelte';
|
||||||
import Settings from './pages/Settings.svelte';
|
import Settings from './pages/Settings.svelte';
|
||||||
|
import Favourites from './pages/Favourites.svelte';
|
||||||
|
import Twitter from './pages/Twitter.svelte';
|
||||||
import NotFound from './pages/NotFound.svelte';
|
import NotFound from './pages/NotFound.svelte';
|
||||||
|
|
||||||
const routes = new Map();
|
const routes = new Map();
|
||||||
@ -18,6 +20,8 @@ routes.set('/', Home);
|
|||||||
routes.set('/timetable/:fromStation/:destStation', Timetable);
|
routes.set('/timetable/:fromStation/:destStation', Timetable);
|
||||||
routes.set('/service/:serviceId', Service);
|
routes.set('/service/:serviceId', Service);
|
||||||
routes.set('/settings', Settings);
|
routes.set('/settings', Settings);
|
||||||
|
routes.set('/favourites', Favourites);
|
||||||
|
routes.set('/tweets', Twitter);
|
||||||
routes.set('*', NotFound);
|
routes.set('*', NotFound);
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
|
281
src/store/store.js
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
/**
|
||||||
|
* Created by WebStorm.
|
||||||
|
* User: martin
|
||||||
|
* Date: 28/04/2020
|
||||||
|
* Time: 11:28
|
||||||
|
|
||||||
|
*/
|
||||||
|
import axios from 'redaxios';
|
||||||
|
|
||||||
|
import { writable, get } from 'svelte/store';
|
||||||
|
import localforage from 'localforage';
|
||||||
|
const baseUrl = (ENV === 'production') ? (`${location.protocol }//${ location.hostname}`) : 'http://localhost:8100';
|
||||||
|
|
||||||
|
let started = false;
|
||||||
|
const twitterAccounts = {
|
||||||
|
'nationalrailenq': {
|
||||||
|
'id': 33546465,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'networkrail': {
|
||||||
|
'id': 365344176,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailSCOT': {
|
||||||
|
'id': 402687948,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'AvantiWestCoast': {
|
||||||
|
'id': 1143560758476906497,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'CalSleeper': {
|
||||||
|
'id': 2870293725,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'CrossCountryUK': {
|
||||||
|
'id': 153368708,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'Eurostar': {
|
||||||
|
'id': 98412169,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'EurostarUK': {
|
||||||
|
'id': 59742254,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'GatwickExpress': {
|
||||||
|
'id': 163816182,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'GlasgowSubway': {
|
||||||
|
'id': 224607925,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'GWRHelp': {
|
||||||
|
'id': 15589815,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'HeathrowExpress': {
|
||||||
|
'id': 20240678,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'LNER': {
|
||||||
|
'id': 313306238,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'LNRailway': {
|
||||||
|
'id': 910487328627535872,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'northernassist': {
|
||||||
|
'id': 194512268,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'ScotRail': {
|
||||||
|
'id': 61569136,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'Stansted_Exp': {
|
||||||
|
'id': 257511611,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'TfL': {
|
||||||
|
'id': 47319664,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailBHM': {
|
||||||
|
'id': 583910976,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailEDB': {
|
||||||
|
'id': 586614081,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailEUS': {
|
||||||
|
'id': 581807264,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailGLC': {
|
||||||
|
'id': 421061171,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailKGX': {
|
||||||
|
'id': 459192871,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailLST': {
|
||||||
|
'id': 581826097,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailMAN': {
|
||||||
|
'id': 583895871,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'NetworkRailVIC': {
|
||||||
|
'id': 587354752,
|
||||||
|
'follow': false
|
||||||
|
},
|
||||||
|
'BTPScotland': {
|
||||||
|
'id': 957256160,
|
||||||
|
'follow': false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
'twitterFollowing': writable({}),
|
||||||
|
'twitterFollowingList' : writable([]),
|
||||||
|
'tweetList' : writable([]),
|
||||||
|
'tweets' : writable([]),
|
||||||
|
'favourites' : writable([]),
|
||||||
|
'routes' : writable([]),
|
||||||
|
'routeIndex' : writable(0),
|
||||||
|
incrementRouteIndex() {
|
||||||
|
this.routeIndex.update(v => v + 1);
|
||||||
|
},
|
||||||
|
async saveRoute(newRoute) {
|
||||||
|
// console.log('Newroute', newRoute);
|
||||||
|
const _newRoute = { ...newRoute };
|
||||||
|
_newRoute.id = get(this.routeIndex);
|
||||||
|
|
||||||
|
this.routes.update((v) => {
|
||||||
|
// console.log('update', [...v, _newRoute]);
|
||||||
|
|
||||||
|
return [...v, _newRoute];
|
||||||
|
});
|
||||||
|
this.incrementRouteIndex();
|
||||||
|
},
|
||||||
|
deleteRoute(id) {
|
||||||
|
const pre = get(this.routes).slice(0, id);
|
||||||
|
|
||||||
|
const post = get(this.routes).slice(id + 1);
|
||||||
|
|
||||||
|
this.routes.set([...pre, ...post]);
|
||||||
|
},
|
||||||
|
async getTweets() {
|
||||||
|
// console.log('>> getTweets');
|
||||||
|
// console.log('>> state.twitterFollowingList', get(state.twitterFollowingList));
|
||||||
|
const list = get(state.twitterFollowingList).map((item) => {
|
||||||
|
return item[1].id;
|
||||||
|
})/* .join(',')*/;
|
||||||
|
// console.log('>> actual ids', list);
|
||||||
|
// const routeUrl = `/twitter?t=${list}`;
|
||||||
|
const routeUrl = '/twitter';
|
||||||
|
const twitterUrl = baseUrl.concat(routeUrl);
|
||||||
|
const postReq = {
|
||||||
|
'method':'post',
|
||||||
|
'url': twitterUrl,
|
||||||
|
'data' : {
|
||||||
|
list
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// console.log(postReq);
|
||||||
|
await axios(postReq)
|
||||||
|
.then((d) => {
|
||||||
|
// console.log('>> retrieved', d);
|
||||||
|
const data = JSON.parse(d.data);
|
||||||
|
const list = data.map((item) => {
|
||||||
|
return item.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tMap = data.map((item) => {
|
||||||
|
return [item.id, item];
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tweetList.set(list);
|
||||||
|
this.tweets.set(new Map(tMap));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getTweetByID(id) {
|
||||||
|
return get(this.tweets).get(id);
|
||||||
|
},
|
||||||
|
getTwitterFollowing() {
|
||||||
|
return get(this.twitterFollowing);
|
||||||
|
},
|
||||||
|
saveTwitterFollowing(newVals) {
|
||||||
|
this.twitterFollowing.set(newVals);
|
||||||
|
},
|
||||||
|
|
||||||
|
getBaseUrl() {
|
||||||
|
return baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
localforage.getItem('twitterFollowing').then((value) => {
|
||||||
|
if (value !== null) state.twitterFollowing.set(value);
|
||||||
|
else {
|
||||||
|
state.twitterFollowing.set(twitterAccounts);
|
||||||
|
localforage.setItem('twitterFollowing', twitterAccounts).catch((err) => {
|
||||||
|
// This code runs if there were any errors
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('twitterFollowing', get(state.twitterFollowing));
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
localforage.getItem('favourites').then((value) => {
|
||||||
|
if (value !== null) state.favourites.set(value);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
localforage.getItem('routes').then((value) => {
|
||||||
|
if (value !== null) state.routes.set(value);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
localforage.getItem('routeIndex').then((value) => {
|
||||||
|
if (value !== null) state.routeIndex.set(value);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
state.favourites.subscribe((v) => {
|
||||||
|
console.log('>> Store.state.favourites', v);
|
||||||
|
});
|
||||||
|
|
||||||
|
state.routes.subscribe((v) => {
|
||||||
|
if (started)
|
||||||
|
// console.log('>> Store.state.routes', v);
|
||||||
|
localforage.setItem('routes', v).catch((err) => {
|
||||||
|
// This code runs if there were any errors
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
state.routeIndex.subscribe((v) => {
|
||||||
|
if (started)
|
||||||
|
// console.log('>> Store.state.routeIndex', v);
|
||||||
|
localforage.setItem('routeIndex', v).catch((err) => {
|
||||||
|
// This code runs if there were any errors
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
state.twitterFollowing.subscribe((v) => {
|
||||||
|
if (started)
|
||||||
|
// console.log('>> Store.state.twitterFollowing', v);
|
||||||
|
localforage.setItem('twitterFollowing', v).catch((err) => {
|
||||||
|
// This code runs if there were any errors
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
const list = Object.entries(get(state.twitterFollowing)).filter((item) => {
|
||||||
|
if (item[1].follow) return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
state.twitterFollowingList.set(list);
|
||||||
|
});
|
||||||
|
|
||||||
|
// started = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
started = true;
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
export { state };
|
21
test.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html ⚡>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>amp-twitter - Example 1</title>
|
||||||
|
<script async src="https://cdn.ampproject.org/v0.js"></script>
|
||||||
|
<script custom-element="amp-twitter" src="https://cdn.ampproject.org/v0/amp-twitter-0.1.js" async></script>
|
||||||
|
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
||||||
|
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<amp-twitter
|
||||||
|
width="375"
|
||||||
|
height="472"
|
||||||
|
layout="responsive"
|
||||||
|
data-tweetid="1255922296860090400"
|
||||||
|
>
|
||||||
|
</amp-twitter>
|
||||||
|
</body>
|
||||||
|
</html>
|