Panels,some new stations,afix for missing cancellation data

This commit is contained in:
Martin Donnelly 2018-09-12 20:38:18 +01:00
parent 9fbda5665f
commit 0d99419797
17 changed files with 3517 additions and 2646 deletions

209
fonts/fujicons.css Normal file
View File

@ -0,0 +1,209 @@
@font-face {
font-family: 'Fujicons';
font-style: normal;
font-weight: 400;
src: url(fujicons.ttf) format('truetype');
unicode-range: U+0-10FFFF;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 Fujicons;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* makes the font 33% larger relative to the icon container */
.fa-lg {
font-size: 1.33333333em;
line-height: 0.75em;
vertical-align: -15%;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-fw {
width: 1.28571429em;
text-align: center;
}
.fa-ul {
padding-left: 0;
margin-left: 2.14285714em;
list-style-type: none;
}
.fa-ul > li {
position: relative;
}
.fa-li {
position: absolute;
left: -2.14285714em;
width: 2.14285714em;
top: 0.14285714em;
text-align: center;
}
.fa-li.fa-lg {
left: -1.85714286em;
}
.fa-border {
padding: .2em .25em .15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
}
.fa-pull-left {
float: left;
}
.fa-pull-right {
float: right;
}
.fa.fa-pull-left {
margin-right: .3em;
}
.fa.fa-pull-right {
margin-left: .3em;
}
/* Deprecated as of 4.4.0 */
.pull-right {
float: right;
}
.pull-left {
float: left;
}
.fa.pull-left {
margin-right: .3em;
}
.fa.pull-right {
margin-left: .3em;
}
.fa-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
.fa-pulse {
-webkit-animation: fa-spin 1s infinite steps(8);
animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
.fa-rotate-90 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
-webkit-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);
}
.fa-flip-vertical {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
-webkit-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
:root .fa-rotate-90,
:root .fa-rotate-180,
:root .fa-rotate-270,
:root .fa-flip-horizontal,
:root .fa-flip-vertical {
filter: none;
}
.fa-stack {
position: relative;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2em;
vertical-align: middle;
}
.fa-stack-1x,
.fa-stack-2x {
position: absolute;
left: 0;
width: 100%;
text-align: center;
}
.fa-stack-1x {
line-height: inherit;
}
.fa-stack-2x {
font-size: 2em;
}
.fa-inverse {
color: #ffffff;
}
.fa-back:before {
content: "";
}
.fa-forward:before {
content: "";
}
.fa-globe:before {
content: "\EA12"
}
.fa-up:before {
content: "\E925"
}
.fa-down:before {
content: "\E922"
}
.fa-work:before {
content: "\E998"
}
.fa-home:before {
content: "\EA1E"
}
.fa-refresh:before {
content: "\EA88"
}

BIN
fonts/fujicons.ttf Executable file

Binary file not shown.

View File

@ -25,7 +25,7 @@ gulp.task('bundleBackbone', function () {
.pipe(sourcemaps.init({ 'loadMaps': true }))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
// .pipe(uglify())
.on('error', gutil.log)
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./live/js'));

View File

@ -69,3 +69,9 @@ gulp.task('gotham', function() {
gulp.src(['fonts/gotham.css']).pipe(gulp.dest('live/fonts'));
gulp.src(['fonts/GothamSSm-Black.otf', 'fonts/GothamSSm-Bold.otf', 'fonts/GothamSSm-Book.otf', 'fonts/GothamSSm-Light.otf', 'fonts/GothamSSm-Medium.otf']).pipe(gulp.dest('live/fonts'));
});
gulp.task('fujicons', function() {
gulp.src(['fonts/fujicons.css']).pipe(gulp.dest('live/fonts'));
gulp.src(['fonts/fujicons.ttf']).pipe(gulp.dest('live/fonts'));
});

View File

@ -4,4 +4,4 @@ const requireDir = require('require-dir');
requireDir('./gulp');
gulp.task('default', ['bundleBackbone', 'styles', 'copy', 'customMUI', 'vendor', 'fonts', 'gotham']);
gulp.task('default', ['bundleBackbone', 'styles', 'copy', 'customMUI', 'vendor', 'fonts', 'gotham', 'fujicons']);

5246
package-lock.json generated

File diff suppressed because it is too large Load Diff

172
server/lib/logging.js Normal file
View File

@ -0,0 +1,172 @@
/**
* @fileOverview Utilities to simplify logging for the rest of the code.
*/
const winston = require('winston');
const _ = require('lodash');
const debug = require('debug')('logging:compliance');
/**
* Requiring `winston-mongodb` will expose
* `winston.transports.MongoDB`
*/
// eslint-disable-next-line import/no-unassigned-import
require('winston-mongodb');
module.exports = logging;
const MONGO_LOG_COLLECTION = 'ComplianceLog';
/**
* Initialise log transports
*/
const transports = [
new winston.transports.Console({
'name': 'console.info',
'format': winston.format.combine(
winston.format.timestamp(),
winston.format.simple()
),
'colorize': true,
'silent': false
})
];
let mongoTransport;
/**
* Create a very basic logger
*/
const logger = winston.createLogger({
'level': 'info',
transports
});
/**
* Trivially handle the 'error' event to prevent unhandled exception errors.
*/
logger.on('error', (error) => {
debug('Logger error:', error);
});
/**
* Initialisation functions
*/
module.exports.init = {
initMongoTransport
};
/**
* For test, also export a way to control the logger
*/
module.exports._test = {
'getLogger': () => logger,
'getTransports': () => transports
};
/**
* @typedef {function} BridgeLogFunction
* @param {Object} req - Express request object (to access IP, request ID, etc.)
* @param {string} [req.ip] - The IP address of the caller
* @param {string} [req.bridgeUniqueId] - The unique id of this request
* @param {string} [req.sessionData.User] - UserID for the user the request is for
* @param {string} msg - The basic message to log
* @param {Object} [opt] - Optional object containing additional values to log. These will be
* automatically prefixed with '_' and added to the logged object.
*/
/**
* @typedef {Object} BridgeLog
* @property {BridgeLogFunction} info - log at info level
* @property {BridgeLogFunction} error - log at error level
*/
/**
* Factory function for initialising logging for the specified calling file.
*
* It returns an object containing log functions such as `log.info()`, `log.error()`.
* The format of this functions is defined as @see BridgeLogFunction.
*
* @example
* const log = require('<path>/utils/logging.js')(__filename, 'utils:text:example');
* log.info(req, 'Some info text I want to log');
* log.error(req, 'Some error text I want to log', {customValue: 'Some custom value for this log'});
*
* @param {string} file - The filename. Usually just __filename
* @param {string} logID - A colon seperated id for this log group (e.g as used by debug())
* @returns {BridgeLog} - The logging object
*/
function logging(file, logID) {
return {
'info': doLog.bind(undefined, file, logID, 'info'),
'error': doLog.bind(undefined, file, logID, 'error')
};
}
/**
* Function to actually do the logging for any of the specific functions specified above.
*
* @param {string} file - the full filepath of the file that initialised this logger
* @param {string} logId - id of the log group
* @param {string} level - log level
* @param {Object} req - Express request object (to access IP, requestID etc.)
* @param {string} msg - The simple string to log
* @param {Object} opt - Additional options to log
*/
function doLog(file, logId, level, req, msg, opt) {
const toLog = {
level,
'message': msg,
'meta': {
logId,
'ip': req.ip,
'reqId': req.bridgeUniqueId,
'userId': _.get(req, 'session.data.user'),
file
}
};
const loggableOpt = _.mapKeys(opt, (value, key) => `_${ key}`);
//
// Update the base object with the loggable options (prefix with _ per GELF);
//
_.assign(toLog.meta, loggableOpt);
//
// Call the real logger and return the result
//
return logger.log(toLog);
}
/**
* The MongoDB `Db` class from the NodeJS driver
* @typedef {Object} Db
*/
/**
* Updates the logger to include a MongoDB transport that talks to the provided
* `db` instance.
* This also removes any prior MongoDB transport.
*
* @param {Db} db - the MongoDB `Db` instance to use for calling the DB.
*/
function initMongoTransport(db) {
// Remove any existing mongodb transport
if (mongoTransport)
logger.remove(mongoTransport);
//
// Create a new mongodb transport and register it with the logger
//
mongoTransport = new winston.transports.MongoDB({
'name': 'mongotransport',
'decolorize': true,
'storeHost': true,
db,
'collection': MONGO_LOG_COLLECTION,
'format': winston.format.combine(
winston.format.timestamp(),
winston.format.printf((info) => info.message)
)
});
logger.add(mongoTransport);
}

View File

@ -19,6 +19,7 @@ function getTrainTimes(req, res) {
Query(function (a, b) {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(a));
}, res, 'huxley.apphb.com', url);
}

View File

@ -14,7 +14,9 @@ $mui-base-font-family: 'Roboto', "Helvetica Neue", Helvetica, Arial, Verdana,"Tr
// import MUI SASS
@import "./node_modules/muicss/lib/sass/mui";
@import "./src/css/viewport";
@import "./src/css/horscroll";
@import "./src/css/spinner";
////
body {
@ -171,3 +173,115 @@ However, delay the fade out process for 2.5 seconds */
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
.stop-scrolling {
height: 100%;
overflow: hidden;
}
.fullscreen {
position: absolute;
z-index: 5000;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
background-color: mui-color('grey','300');
background-repeat: no-repeat;
background-position: center top;
}
.fillpanel {
width:100%;
height:100%;
background-color: mui-color('amber', '50');
}
.fullscreen .header {
/*position: fixed;
top: 0;
right: 0;
left: 0;
z-index: +1;
transition: left 0.2s;*/
position:sticky;
}
.box {
display: flex;
flex-flow: column;
height:100%;
// overflow:auto;
}
.box .headerSpacer {
flex: 0 1 66px;
}
.box .content {
flex: 1 1 auto;
background-color: mui-color('white');
overflow: auto;
margin-bottom: 15px;
}
.newsarticle img {
max-height:100%;
max-width:100%;
}
.tiny {
font-size:1rem;
}
.small {
font-size:2rem;
}
.medium {
font-size:4rem;
}
.large {
font-size:6rem;
}
.cardLink {
color: mui-color('blue', '500');
margin-top: 10px;
}
.endbumper {
height:66px;
}
.seemore {
font-size:14px;
font-weight: 500;
}
#connectionStatus {
margin-top:15px;
margin-bottom:15px;
}
.trafficHeavy {
color: #fa4a50;
}
.trafficLight {
color: #fdbd15;
}
.trafficMedium {
color: #fba010;
}
#map { height: 180px; }
#bymeImages {
margin-bottom: 3px;
}

52
src/css/horscroll.scss Normal file
View File

@ -0,0 +1,52 @@
.scrolling-wrapper-flexbox {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
.scrollCard, .scrollCardHalf, .imageCard, .hourlyCard {
flex: 0 0 auto;
margin-right: 11px;
}
}
.scrollCard, .scrollCardHalf, .hourlyCard {
width: 250px;
height: 175px;
overflow-y: hidden;
border-radius: 3px;
background-color: #f5f5f5;
padding: 5px;
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.05), 0 2px 1px -2px rgba(0,0,0,0.05), 0 1px 5px 0 rgba(0,0,0,0.05)
}
.scrollCardHalf {
height: 85px;
}
.hourlyCard {
width: 42px;
height:70px;
background: transparent;
}
.imageCard {
// width: 250px;
height: 175px;
overflow-y: hidden;
}
.imageCard img {
max-height:100%;
max-width:100%;
}
.scrolling-wrapper, .scrolling-wrapper-flexbox {
height: 75px;
width: 100%;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}

93
src/css/spinner.scss Normal file
View File

@ -0,0 +1,93 @@
$green: #008744;
$blue: #0fa3ef;
$red: #dc4f43;
$yellow: #ffbe39;
$white: #eee;
$black: #301010;
// scaling... any units
$width: 100px;
body {
background-color: $white;
}
// demo-specific
.showbox {
position: absolute;
top: 40vh;
bottom: 60vh;
left: 0;
right: 0;
padding: 5%;
}
// end demo-specific
.loader {
position: relative;
margin: 0 auto;
width: $width;
&:before {
content: '';
display: block;
padding-top: 100%;
}
}
.circular {
animation: rotate 2s linear infinite;
height: 100%;
transform-origin: center center;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.path {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;
stroke-linecap: round;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35px;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -124px;
}
}
@keyframes color {
100%,
0% {
stroke: $red;
}
40% {
stroke: $yellow;
}
66% {
stroke: $blue;
}
80%,
90% {
stroke: $black;
}
}

81
src/css/viewport.scss Normal file
View File

@ -0,0 +1,81 @@
.viewport {
width: 100%;
height: 100%;
margin: 0;
}
/* encapsulate the various syntax in helper clases */
/* inspired by http://infrequently.org/2009/08/css-3-progress/ */
/* items flex/expand vertically */
.vbox {
/* previous syntax */
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-ms-box-orient: vertical;
box-orient: vertical;
/* current syntax */
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: flex;
-webkit-flex-direction: column;
-moz-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.gradient {
/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ebf1f6+0,abd3ee+50,89c3eb+51,d5ebfb+100;Blue+Gloss+%234 */
background: #ebf1f6; /* Old browsers */
background: -moz-linear-gradient(top, #ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%); /* FF3.6-15 */
background: -webkit-linear-gradient(top, #ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #ebf1f6 0%, #abd3ee 50%, #89c3eb 51%, #d5ebfb 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ebf1f6', endColorstr='#d5ebfb', GradientType=0); /* IE6-9 */
}
.backgroundImage {
background-image: url(http://via.placeholder.com/411x823);
}
.appPanel {
/* previous syntax */
-webkit-box-flex: 1;
-moz-box-flex: 1;
-ms-box-flex: 1;
box-flex: 1;
/* current syntax */
-webkit-flex: 1;
-moz-flex: 1;
-ms-flex: 1;
flex: 1;
height: 100vh;
width: 100vw;
overflow-y: auto;
/* background-color: white;*/
}
[data-id~="main"] {
z-index: 0;
position: absolute;
top: 0;
left: 0;
}
[data-id~="routeP"] {
z-index: 1000;
position: absolute;
top: 0;
left: 0;
}

View File

@ -7,6 +7,7 @@
<title>Train Times</title>
<link href="fonts/fonts.css" rel="stylesheet">
<link href="fonts/gotham.css" rel="stylesheet">
<link href="fonts/fujicons.css" rel="stylesheet" type="text/css"/>
<link href="css/mui.custom.css" rel="stylesheet" type="text/css"/>
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
@ -22,21 +23,26 @@
</head>
<body>
<header id="header">
<div class="mui-appbar mui--appbar-line-height mui--z2">
<div class='mui-col-xs-8 mui-col-md-8 mui--appbar-height titleBar'>Train Times</div>
<div class='mui-col-xs-4 mui-col-md-4 mui--appbar-height'></div>
<div class="appPanel" data-id="main">
<header id="header">
<div class="mui-appbar mui--appbar-line-height mui--z2">
<div class='mui-col-xs-8 mui-col-md-8 mui--appbar-height titleBar'>Train Times</div>
<div class='mui-col-xs-4 mui-col-md-4 mui--appbar-height'></div>
</div>
</header>
<div class="mui--appbar-height"></div>
<div class="mui-container">
<div class="app"></div>
<div id="trains" ></div>
<!--<div id='trainResults' class="mui&#45;&#45;hide"></div>-->
</div>
</header>
<div class="mui--appbar-height"></div>
<div class="mui-container">
<div class="app"></div>
<div id="trains" class="unsliced"></div>
<div id='trainResults' class="mui--hide"></div>
</div>
<div id="snackbar">⚡ Offline, waiting to reconnect...</div>

View File

@ -82,12 +82,12 @@ const { RouteModel, RouteView } = require('./route');
}
};
if ('serviceWorker' in navigator)
/*if ('serviceWorker' in navigator)
navigator.serviceWorker
.register('./service-worker.js')
.then(function() {
console.log('Service Worker Registered');
});
});*/
app.createViews();
})();

102
src/js/libs/panel.js Normal file
View File

@ -0,0 +1,102 @@
const $ = require('jquery');
let panelCount = 0;
function createPanel(params) {
const { title, divId } = params;
const newPanel = `
<div class="appPanel" data-id="${divId}">
<div id="card_${divId}" class="fullscreen" style="display:;">
<header class="header">
<div class="mui-appbar mui--appbar-line-height mui--z1" style="vertical-align:middle;">
<span>
<button class="mui-btn mui-btn--large mui-btn--primary mui-btn--flat closebutton" id="close_${divId}">
<i class="fa-3x fa fa-back mui--align-middle" style="color:white;"></i>
</button>
</span>
<span class="mui--text-title mui--align-middle" id="title_${divId}">
${title}
</span>
</div>
</header>
<div class="box">
<div class="content mui-panel" id="${divId}">
<div class="showbox">
<div class="loader">
<svg class="circular" viewBox="25 25 50 50">
<circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/>
</svg>
</div>
</div>
</div>
</div>
<!-- end fullscreen-->
</div>
</div>
`;
const $newPanel = $(newPanel);
const $closeButton = $newPanel.find(`button#close_${divId}`);
$closeButton.on('click', () => {
doClose();
});
$newPanel.offset({ 'top': $(window).scrollTop(), 'left': 0 });
function doClose() {
const $body = $('body');
$newPanel.hide().remove();
console.log('panelCount', panelCount);
panelCount--;
if (panelCount === 0)
console.log('Removing panel stuff');
$body.removeClass('stop-scrolling').unbind('touchmove');
}
return $newPanel;
}
function addPanel($newPanel) {
const $body = $('body');
const $content = $newPanel.find('.content');
$body.append($newPanel);
if (panelCount === 0) {
$body.addClass('stop-scrolling');
$body.bind('touchmove', function(e) {
e.preventDefault();
});
}
panelCount++;
return $content;
}
module.exports = { createPanel, addPanel };
/*
class Template {
constructor(item) {
// "pubdate": "Tue, 06 Feb 2018 17:05:00 +0100",
const pubdateSrc = fecha.parse(item.pubdate, 'ddd, DD MMM YYYY HH:mm:SS ZZ');
const pubdate = fecha.format(pubdateSrc, 'dddd MMMM Do, YYYY');
const description = item.description.replace(/(<script(\s|\S)*?<\/script>)|(<style(\s|\S)*?<\/style>)|(<!--(\s|\S)*?-->)|(<\/?(\s|\S)*?>)/g, '');
this.data = `<article>
<header>
<a href="${item.guid.text}">${item.title}</a>
<time class="published">${pubdate}</time>
</header>
<p class="description">${description}</p>
</article>`;
}
toString() {
return this.data;
}
}
*/

View File

@ -1,6 +1,7 @@
const $ = require('jquery');
const _ = require('underscore');
const Backbone = require('backbone');
const { createPanel, addPanel } = require('./libs/panel');
const RouteModel = Backbone.Model.extend({
'initialize': function () {
@ -138,7 +139,7 @@ const RouteView = Backbone.View.extend({
console.log(this);
this.eventBus.on('showRoute', function(d) {
console.log('Showroute', d);
this.showPanel();
this.model.set('to', d.to);
this.model.set('from', d.from);
this.model.update();
@ -146,6 +147,16 @@ const RouteView = Backbone.View.extend({
this.initView();
},
'showPanel': function(guid) {
console.log('Showing panel', guid);
this.$newPanel = createPanel({ 'title':'Details', 'divId':'routeP' });
this.$el = addPanel(this.$newPanel);
// this.$el.empty();
this.$newPanel.show();
},
'events': {
'click a': 'news',
'click .station': 'stations'
@ -191,7 +202,9 @@ const RouteView = Backbone.View.extend({
const statusMode = (status.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
const delayReason = (item.delayReason !== null) ? `<tr><td colspan="4" class="mui--bg-danger mui--text-white" style="font-size:75%;">${item.delayReason}</td></tr>` : '';
services.push({ 'location':dest.locationName, 'time':time, 'status':status, 'platform':platform, 'cancel':item.cancelReason, 'type':'train' });
const cancelReason = (item.cancelReason !== null) ? item.cancelReason : 'No reason given 🤷';
services.push({ 'location':dest.locationName, 'time':time, 'status':status, 'platform':platform, 'cancel':cancelReason, 'type':'train' });
if (!item.isCancelled)
ws = `${ws }<tr><td data-id="${item.serviceIdUrlSafe}" class="station">${dest.locationName} ${via}</td>
<td class="mui--text-center time">${time}</td>
@ -200,7 +213,7 @@ const RouteView = Backbone.View.extend({
</tr>${delayReason}`;
else
ws = `${ws }<tr><td>${dest.locationName} ${via}</td><td>${time}</td>
<td colspan="2" class="delayed"> ${item.cancelReason}</td></tr>`;
<td colspan="2" class="delayed"> ${cancelReason}</td></tr>`;
}
if (typeof route.busServices === 'object' && route.busServices !== null)
@ -222,7 +235,7 @@ const RouteView = Backbone.View.extend({
for (const item of route.nrccMessages) {
const msg = item.value.replace('href=', 'data-url=').replace(' ">', '">');
nrMessages = `${nrMessages}<div class="mui--bg-danger mui--text-white" style="padding:2px;">${msg}</div>`;
nrMessages = `${nrMessages}<div class="mui--bg-danger mui--text-white nrccAlert" style="padding:2px;">${msg}</div>`;
}
const thead = `<div class="mui--text-center mui--text-accent">${route.locationName} TO ${route.filterLocationName}</div>
@ -234,15 +247,20 @@ ${nrMessages}
<th class="mui--text-center">Platform</th></tr></thead>`;
ws = `${thead}<tbody class="tableBody">${ws}</tbody></table>`;
// ws = `${thead}${ws}</table>`;
this.$traintext.empty().html(ws);
this.$traintext.removeClass('mui--hide').addClass('mui--show');
this.$el.empty().html(ws);
// this.$traintext.removeClass('mui--hide').addClass('mui--show');
/*
if (this.$trains.hasClass('unsliced'))
this.$trains.addClass('sliced').removeClass('unsliced');
*/
// this.$trains.css("background-color", "yellow");
// this.$trains.css("height", "300px");
this.$el.find('a').on('click', this.news);
},
'initView': function () {

View File

@ -11,6 +11,13 @@ const Backbone = require('backbone');
const { findStation } = require('./stations');
const TrainModel = Backbone.Model.extend({
'defaults': function (obj) {
// return a new object
return {
'update': 0,
'last': new Date().getTime()
};
},
'initialize': function () {
const fromStation = this.get('from');
const toStation = this.get('to');
@ -45,6 +52,7 @@ const TrainModel = Backbone.Model.extend({
setTimeout(trainUpdateFn.bind(this), mod + 10);
},
'getTrain': function () {
this.set('update', new Date().getTime());
const url = this.get('url');
const self = this;
const bus = this.get('bus');
@ -61,6 +69,8 @@ const TrainModel = Backbone.Model.extend({
},
'success': function (data) {
bus.trigger('online');
console.log('Data', data);
self.set('trainData', data);
},
'error': function (xhr, type) {
@ -76,8 +86,15 @@ const TrainView = Backbone.View.extend({
'tagName': 'div',
'initialize': function (options) {
_.bindAll(this, 'render');
this.eventBus = options.eventBus;
this.model.bind('change', this.render);
this.model.bind('change:trainData', this.render);
this.model.bind('change:update', function(){
console.log('Updating....');
});
this.model.bind('all', function(eventName) {
console.log(`${eventName } was triggered!`);
});
this.$trains = $('#trains');
this.$traininfo = $('#traininfo');
this.$traintext = $('#trainResults');
@ -125,7 +142,7 @@ const TrainView = Backbone.View.extend({
this.$button = $(`#${target}`);
const output = 'OFF';
const output = '<i class="fa fa-refresh mui--align-middle" ></i>';
const status = (output === 'on time') ? 'ontime' : 'delayed';
this.$button.html(output);