From d2707da076d87364fe69dac2c7d2db75738ecf82 Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 13:45:01 +0100 Subject: [PATCH 1/7] Initial server setup --- package.json | 3 +++ server/index.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 server/index.js diff --git a/package.json b/package.json index e3a3974..5c200cb 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,9 @@ "color-interpolate": "^1.0.2", "d3": "^4.12.0", "dateformat": "^3.0.2", + "koa": "^2.6.2", + "koa-router": "^7.4.0", + "koa-static": "^5.0.0", "msgflo-browser": "^0.2.0", "plotly.js": "^1.31.2", "skatejs": "^5.0.0-beta.4" diff --git a/server/index.js b/server/index.js new file mode 100644 index 0000000..7730ae6 --- /dev/null +++ b/server/index.js @@ -0,0 +1,17 @@ +const Koa = require('koa'); +const Router = require('koa-router'); +const Static = require('koa-static'); +const path = require('path'); + +const app = new Koa(); +const router = new Router(); + +app + .use(router.routes()) + .use(router.allowedMethods()) + .use(Static(path.resolve(__dirname, '../dist'), {})); + +module.exports = app; +if (!module.parent) { + app.listen(8080); +} From 2395af36d97300d40506d9e0291dcdd3170e6998 Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 14:01:05 +0100 Subject: [PATCH 2/7] Update Dockerfile to run the server --- Dockerfile | 23 +++++++++++++++++++++-- package.json | 3 ++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 576b054..48b2e91 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,2 +1,21 @@ -FROM nginx -COPY dist /usr/share/nginx/html +FROM node:10-alpine + +# Reduce npm install verbosity, overflows Travis CI log view +ENV NPM_CONFIG_LOGLEVEL warn +ENV NODE_ENV production + +EXPOSE 8080 + +RUN mkdir -p /var/infoscreens +WORKDIR /var/infoscreens +COPY package.json /var/infoscreens +COPY server /var/infoscreens/server +COPY dist /var/infoscreens/dist + +# Install NoFlo and dependencies +RUN npm install --only=production + +# Map the volumes +VOLUME /var/infoscreens/dist + +CMD npm start diff --git a/package.json b/package.json index 5c200cb..63b0d8d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "build": "webpack", "pretest": "eslint index.js lib/*.js elements/*.js infodisplay/*.js events/*.js", - "start": "webpack-dev-server", + "dev": "webpack-dev-server", + "start": "node server", "test": "npm run build" }, "author": "Henri Bergius ", From a9c10851d6942b8a7af8c0f9799c926fd8380486 Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 14:03:05 +0100 Subject: [PATCH 3/7] Update docker-compose --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 466c083..3d21590 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,8 +8,8 @@ services: infoscreens: image: cbase/infoscreens ports: - - '8080:80' + - '8080:8080' links: - mqtt-infoscreens volumes: - - .:/usr/share/nginx/html + - ./dist:/var/infoscreens/dist From e5245d82a03583c2fe4795592aea7d73b07aaa69 Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 14:08:36 +0100 Subject: [PATCH 4/7] Enable CORS --- package.json | 2 ++ server/index.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/package.json b/package.json index 63b0d8d..dd0e259 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "color-interpolate": "^1.0.2", "d3": "^4.12.0", "dateformat": "^3.0.2", + "isomorphic-fetch": "^2.2.1", "koa": "^2.6.2", + "koa-cors": "0.0.16", "koa-router": "^7.4.0", "koa-static": "^5.0.0", "msgflo-browser": "^0.2.0", diff --git a/server/index.js b/server/index.js index 7730ae6..8714466 100644 --- a/server/index.js +++ b/server/index.js @@ -1,12 +1,14 @@ const Koa = require('koa'); const Router = require('koa-router'); const Static = require('koa-static'); +const Cors = require('koa-cors'); const path = require('path'); const app = new Koa(); const router = new Router(); app + .use(Cors()) .use(router.routes()) .use(router.allowedMethods()) .use(Static(path.resolve(__dirname, '../dist'), {})); From 0978d1df8de20caf1e858d74281ea538998ac46c Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 14:23:22 +0100 Subject: [PATCH 5/7] Proxy the fahrplan --- server/index.js | 4 ++++ server/route/35c3.js | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 server/route/35c3.js diff --git a/server/index.js b/server/index.js index 8714466..e66281e 100644 --- a/server/index.js +++ b/server/index.js @@ -4,9 +4,13 @@ const Static = require('koa-static'); const Cors = require('koa-cors'); const path = require('path'); +const route35c3 = require('./route/35c3'); + const app = new Koa(); const router = new Router(); +route35c3(router); + app .use(Cors()) .use(router.routes()) diff --git a/server/route/35c3.js b/server/route/35c3.js new file mode 100644 index 0000000..288bcef --- /dev/null +++ b/server/route/35c3.js @@ -0,0 +1,10 @@ +require('isomorphic-fetch'); + +module.exports = (router) => { + router.get('/35c3/fahrplan', async (ctx) => { + const res = await fetch('https://fahrplan.events.ccc.de/congress/2018/Fahrplan/schedule.json'); + ctx.assert((res.status === 200), res.status); + const body = await res.json(); + ctx.body = body; + }); +}; From d5c85c1c78b0c3fe22c050c59f71e8cdbe83038f Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 15:18:35 +0100 Subject: [PATCH 6/7] Implement 35c3 event calendar --- 35c3-events/calendar.js | 157 ++++++++++++++++++++++++++++++++++++++++ 35c3-events/index.html | 118 ++++++++++++++++++++++++++++++ webpack.config.js | 1 + 3 files changed, 276 insertions(+) create mode 100644 35c3-events/calendar.js create mode 100644 35c3-events/index.html diff --git a/35c3-events/calendar.js b/35c3-events/calendar.js new file mode 100644 index 0000000..9878254 --- /dev/null +++ b/35c3-events/calendar.js @@ -0,0 +1,157 @@ +import dateformat from 'dateformat'; +import '../elements/time'; + +function sortEvents(a, b) { + if (a.start < b.start) { + return -1; + } + if (a.start > b.start) { + return 1; + } + return 0; +} + +function getEvents(number) { + const now = new Date(); + return fetch('//airdrone.bergie.today:8080/35c3/fahrplan') + .then(res => res.json()) + .then((res) => { + // res.schedule.conference.days[0].rooms.Adams[0] + const talks = []; + res.schedule.conference.days.forEach((day) => { + const dayEnd = new Date(day.day_end); + if (dayEnd < now) { + // Already done with this day + return; + } + Object.keys(day.rooms).forEach((room) => { + day.rooms[room].forEach((slot) => { + const start = new Date(slot.date); + const [durationH, durationM] = slot.duration.split(':').map(val => parseInt(val, 10)); + const end = new Date(slot.date); + end.setHours(end.getHours() + durationH); + end.setMinutes(end.getMinutes() + durationM); + if (end < now) { + // This event is already over + return; + } + talks.push({ + allDay: false, + start: start.toISOString(), + end: end.toISOString(), + title: slot.title, + id: room, + }); + }); + }); + }); + return talks; + }) + .then(talks => fetch('https://launchlibrary.net/1.3/launch/next/2') + .then(res => res.json()) + .then((res) => { + const launches = res.launches.map((launch) => { + const start = new Date(launch.windowstart); + const end = new Date(launch.windowend); + return { + allDay: false, + start: start.toISOString(), + end: end.toISOString(), + title: launch.name, + id: launch.lsp.abbrev, + type: 'launch', + }; + }); + return launches; + }) + .then((launches) => { + console.log(launches, talks); + const allEvents = talks.concat(launches); + allEvents.sort(sortEvents); + return allEvents.slice(0, number); + })); +} + +let prevDate = new Date(); +function renderEvent(event, container) { + const now = new Date(); + const row = document.createElement('tr'); + const time = document.createElement('td'); + time.className = 'time'; + const destination = document.createElement('td'); + destination.className = 'destination'; + const code = document.createElement('td'); + code.className = 'code'; + const status = document.createElement('td'); + status.className = 'status'; + const startDate = new Date(event.start); + const pad = (t) => { + let val = `${t}`; + if (val.length === 1) { + val = `0${val}`; + } + if (val.length === 2) { + val = `0${val}`; + } + return val; + }; + const cleanTitle = (title) => { + let cleaned = title.replace(/\sBerlin$/, ''); + cleaned = cleaned.replace(/\sUser Group/, ' UG'); + return cleaned; + }; + const timeFormat = 'HH:MM'; + if (event.allDay) { + time.innerHTML = '--:--'; + } else { + time.innerHTML = dateformat(startDate, timeFormat); + } + + if (typeof event.id === 'number') { + code.innerHTML = `C${pad(event.id)}`; + } else { + code.innerHTML = event.id; + } + destination.innerHTML = cleanTitle(event.title); + if (event.type === 'launch') { + destination.classList.add('launch'); + } + + if (startDate.toDateString() !== prevDate.toDateString()) { + status.innerHTML = dateformat(startDate, 'dd.mm.'); + } + if (startDate.toDateString() === now.toDateString()) { + row.classList.add('today'); + if (startDate < now) { + status.innerHTML = 'Ongoing'; + status.classList.add('ongoing'); + } else { + status.innerHTML = 'Today'; + } + } + + row.appendChild(status); + row.appendChild(time); + row.appendChild(destination); + row.appendChild(code); + container.appendChild(row); + prevDate = startDate; +} + +function render() { + const table = document.getElementById('events'); + getEvents(17) + .then((events) => { + while (table.firstChild) { + table.removeChild(table.firstChild); + } + events.forEach(event => renderEvent(event, table)); + }); +} + +function onPageReady() { + window.removeEventListener('load', onPageReady, false); + render(); + setInterval(render, 30000); +} +window.addEventListener('load', onPageReady, false); diff --git a/35c3-events/index.html b/35c3-events/index.html new file mode 100644 index 0000000..583a108 --- /dev/null +++ b/35c3-events/index.html @@ -0,0 +1,118 @@ + + + + + 35c3 event calendar + + + + + + + +

c-base @ 35C3

+ +
+ + + + diff --git a/webpack.config.js b/webpack.config.js index b85d691..0800df0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,6 +6,7 @@ module.exports = { infoscreens: './index.js', infodisplay: './infodisplay/infodisplay.js', calendar: './events/calendar.js', + '35c3-calendar': './35c3-events/calendar.js', }, output: { path: path.resolve(__dirname, 'dist'), From e88ff347e9a3e81e669b9435baf882b395b42f64 Mon Sep 17 00:00:00 2001 From: Henri Bergius Date: Mon, 24 Dec 2018 15:19:45 +0100 Subject: [PATCH 7/7] Fix calendar URL --- 35c3-events/calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/35c3-events/calendar.js b/35c3-events/calendar.js index 9878254..b1b8af7 100644 --- a/35c3-events/calendar.js +++ b/35c3-events/calendar.js @@ -13,7 +13,7 @@ function sortEvents(a, b) { function getEvents(number) { const now = new Date(); - return fetch('//airdrone.bergie.today:8080/35c3/fahrplan') + return fetch('http://c-flo.cbrp3.c-base.org/35c3/fahrplan') .then(res => res.json()) .then((res) => { // res.schedule.conference.days[0].rooms.Adams[0]