Merge pull request #1 from nfp-projects/dev

Dev
master
Jonatan Nilsson 2020-04-07 11:17:20 +00:00 committed by GitHub
commit 19baa706fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 70 additions and 3042 deletions

2
.gitignore vendored
View File

@ -33,6 +33,8 @@ node_modules
.node_repl_history
db.sqlite
db.json
package-lock.json
public/client.js
public/main.js
public/status.js

View File

@ -11,10 +11,9 @@ COPY public $HOME/public
WORKDIR $HOME
RUN apk add --no-cache make gcc g++ python && \
npm install && \
apk del make gcc g++ python && \
npm run build
RUN npm install && \
npm run build && \
rm -rf node_modules
###########################
# Server
@ -27,13 +26,10 @@ COPY .babelrc config.js log.js index.js package.json $HOME/
WORKDIR $HOME
RUN apk add --no-cache make gcc g++ python && \
npm install --production
RUN npm install --production
COPY api $HOME/api
COPY migrations $HOME/migrations
COPY config $HOME/config
COPY script $HOME/script
COPY --from=build /app/public $HOME/public
EXPOSE 3000

View File

@ -14,7 +14,7 @@ let casparIsConnected
let currentHost
export function initialise(log, db, socket) {
io = socket.socket
io = socket
logger = log
db = db

View File

@ -1,4 +1,4 @@
import template from 'lodash.template'
import _ from 'lodash'
export const active = { }
@ -13,7 +13,7 @@ function getSocket(ctx, all) {
* Display a specific graphic content
*/
export async function display(ctx, data) {
let compiled = template(data.graphic.settings.html)
let compiled = _.template(data.graphic.settings.html)
let html = compiled(data.data)
// let old = await Content.getSingle(data.graphic.name)
@ -68,7 +68,7 @@ function generateDisplayText(item) {
// return `${item.data.text} - ${item.data.finished}`
// }
try {
return template(item.graphic.settings.main)(item.data)
return _.template(item.graphic.settings.main)(item.data)
} catch (e) {
return `Error creating display: ${e.message}`
}

View File

@ -41,9 +41,9 @@ export async function create(ctx, data) {
data.settings.main = '<%- text %> - <%- finished %>'
}
let graphics = ctx.db.get('graphics').insert(data)
let graphics = ctx.db.get('graphics')
await graphics.insert(data).write()
let graphic = graphics.last().value()
await graphics.write()
ctx.io.emit('graphic.single', graphic)
}

View File

@ -1,4 +1,4 @@
import bunyan from 'bunyan'
import bunyan from 'bunyan-lite'
import defaults from './defaults.mjs'
import config from './config.mjs'

View File

@ -1,40 +0,0 @@
export function bunyanLogger(logger) {
return async (ctx, next) => {
ctx.log = logger.child({
})
const d1 = new Date().getTime()
await next()
const d2 = new Date().getTime()
let level = 'info'
if (ctx.status >= 400) {
level = 'warn'
}
if (ctx.status >= 500) {
level = 'error'
}
ctx.log[level]({
duration: (d2 - d1),
status: ctx.res.statusCode,
}, `<-- ${ctx.request.method} ${ctx.request.url}`)
}
}
export function errorHandler() {
return async (ctx, next) => {
try {
await next()
} catch(err) {
ctx.log.error(err, 'Unknown error occured')
ctx.status = 500
ctx.render('error', {
error: err,
})
}
}
}

View File

@ -11,8 +11,8 @@ import * as settings from './settings/routes.mjs'
import * as schedule from './schedule/routes.mjs'
function onConnection(server, db, data) {
const io = server.socket
const socket = data.socket
const io = server
const socket = data
const log = logger.child({
id: socket.id,
})

View File

@ -1,38 +1,69 @@
import Koa from 'koa'
import serve from 'koa-better-serve'
import socket from 'koa-socket'
import socket from 'socket.io-serveronly'
import http from 'http'
import nStatic from 'node-static'
import * as casparcg from './casparcg/client.mjs'
import lowdb from './db.mjs'
import config from './config.mjs'
import log from './log.mjs'
import onConnection from './routerio.mjs'
import { bunyanLogger, errorHandler } from './middlewares.mjs'
log.info('Server: Opening database db.json')
lowdb().then(function(db) {
const app = new Koa()
const io = new socket()
const fileServer = new nStatic.Server('./public')
const server = http.createServer(function (req, res) {
const child = log.child({})
io.attach(app)
const d1 = new Date().getTime()
var done = function () {
var requestTime = new Date().getTime() - d1
let level = 'info'
if (res.status >= 400) {
level = 'warn'
}
if (res.status >= 500) {
level = 'error'
}
child[level]({
duration: requestTime,
status: res.statusCode,
}, `<-- ${req.method} ${req.url}`)
}
res.addListener('finish', done);
res.addListener('close', done);
req.addListener('end', function () {
if (req.url === '/') {
res.writeHead(302, { Location: '/index.html' })
return res.end()
}
fileServer.serve(req, res, function (err) {
if (err) {
log.error(err);
res.writeHead(err.status, err.headers);
res.end(err.message);
}
});
}).resume()
})
const io = new socket(server)
io.on('connection', onConnection.bind(this, io, db))
casparcg.initialise(log, db, io)
app.use(bunyanLogger(log))
app.use(errorHandler())
app.use(async (ctx, next) => {
if (ctx.url === '/') {
return ctx.redirect('/index.html')
server.listen(config.get('server:port'), '0.0.0.0', function(err) {
if (err) {
log.fatal(err)
return process.exit(2)
}
await next()
})
app.use(serve('./public', ''))
app.listen(config.get('server:port'), err => {
if (err) return log.fatal(err)
log.info(`Server is listening on ${config.get('server:port')}`)
})
}, function(e) {

187
db.json
View File

@ -1,187 +0,0 @@
{
"graphics": [
{
"name": "Nidurteljari",
"engine": "countdown",
"settings": {
"html": "<%- text %><br><span id=\"Nidurteljari-countdown-timer\">countdown appears here</span>",
"main": "text",
"text": "Sunnudagssamkoman hefst klukkan 11:00",
"countdown": "2018-07-01 11:00",
"finished": "Skamma stund",
"css": "#Nidurteljari {\n position: absolute;\n font: 2em \"Berthold Akzidenz Grotesk BE\";\n top: 830px;\n left: 230px;\n width: 1450px;\n padding-top: 20px;\n border-top: 1px solid #095376;\n text-align: center;\n color: #095376;\n font-size: 60pt;\n line-height: 70pt;\n font-weight: bold;\n}\n#Nidurteljari-countdown-timer {\n font-size: 80pt;\n}"
},
"id": 1586112780891
},
{
"name": "Nafn",
"engine": "text",
"settings": {
"properties": [
"nafn",
"titill"
],
"main": "<%- nafn %>",
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
},
"id": 1586112780892
},
{
"name": "Minnisvers",
"engine": "text",
"settings": {
"properties": [
"bok",
"vers"
],
"main": "bok",
"css": "#Minnisvers {\n position: absolute;\n font: 2em \"Berthold Akzidenz Grotesk BE\";\n top: 850px;\n right: 0px;\n}\n.bok-holder {\n background: rgba(0,68,105,0.6);\n line-height: 60px;\n font-size: 60px;\n color: white;\n padding: 10px 60px 0px 30px;\n}\n.vers-holder {\n background: rgba(33,29,29,0.6);\n font-size: 30px;\n line-height: 30px;\n color: white;\n padding: 10px 60px 0px 40px;\n}",
"html": "<div class=\"bok-holder\"><%- bok %></div>\n<div class=\"vers-holder\"><%- vers %></div>"
},
"id": 1586112780893
},
{
"name": "Forn",
"engine": "text",
"settings": {
"properties": [
"Titill",
"Text"
],
"main": "<%- Titill %> - <%- Text %>",
"css": "#Forn {\nposition: absolute;\ntop: 50px;\nleft: 95px;\nborder: 4px solid white;\npadding: 6px;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\n}\n\n#Forn .inside {\npadding: 6px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Forn .inside h2 {\nfont-weight: bold;\nfont-size: 24px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\n}\n\n#Forn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\n}",
"html": "<div class=\"inside\">\n<h2><%- Titill %></h2>\n<h4><%= Text.replace('\\n', '<br>') %></h4>\n</div>"
},
"id": 1586112780894
},
{
"name": "Lög",
"engine": "text",
"settings": {
"properties": [
"nafn"
],
"html": "<div class=\"box-before\"></div>\n<div class=\"box-logo\"></div>\n<div class=\"box-after\"></div>\n<div class=\"box-name\">\n <div class=\"holder\">\n <div class=\"name-holder\"><%- nafn %>\n <div class=\"name-triangle\"></div><div class=\"titill-triangle\"></div>\n </div>\n </div>\n</div>",
"css": ".box-before {\n margin-bottom: 15px;\n width: 160px;\n height: 112px;\n margin-right: -37px;\n /* ---------- THEME COLOR ---------- */\n background-image: -webkit-radial-gradient(200px 50%, circle, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 75px, rgba(0,68,105,1) 77px);\n /* ---------- END THEME COLOR ---------- */\n}\n.box-after {\n /* ---------- THEME COLOR ---------- */\n background-image: -webkit-radial-gradient(-40px 50%, circle, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 75px, rgba(0,68,105,1) 77px);\n /* ---------- END THEME COLOR ---------- */\n margin-bottom: 15px;\n width: 100px;\n height: 112px;\n margin-left: -37px;\n}\n\n#Lög {\n position: absolute;\n color: white;\n font: 2em \"Berthold Akzidenz Grotesk BE\";\n top: 100px;\n left: 0px;\n}\n\n#Lög > div { display: inline-block; }\n\n.box-logo {\n width: 141px;\n height: 141px;\n background: url('uploads/logo.png') 0px 0px no-repeat;\n background-size: contain;\n}\n\n.box-name {\n margin-bottom: 15px;\n height: 112px;\n position: relative;\n margin-left: -6px;\n width: 700px;\n}\n.holder { position: absolute; }\n.name-holder {\n position: relative;\n background: linear-gradient(to right, rgba(207,209,210,0.6) 0%,rgba(235,235,237,0.6) 50%,rgba(183,185,185,0.6) 100%);\n line-height: 102px;\n font-size: 60px;\n color: rgba(0,68,105,1);\n padding: 10px 30px 0px 20px;\n}\n.name-triangle {\n position: absolute;\n right: -112px;\n border-width: 0 112px 112px 0px;\n top: 0;\n border-style: solid;\n border-color: transparent transparent rgba(183,185,185,0.6) transparent;\n}",
"main": "nafn"
},
"id": 1586112780895
},
{
"name": "Dagskra",
"engine": "schedule",
"settings": {
"properties": [
"temp"
],
"textfields": [
"item1"
],
"main": "temp"
},
"id": 1586112780896
}
],
"presets": [
{
"graphic_id": 1586112780892,
"values": {
"nafn": "Bla",
"titill": "test"
},
"sort": 1,
"id": 1586205588587
},
{
"graphic_id": 1586112780892,
"values": {
"nafn": "Bla 2",
"titill": "test 2"
},
"sort": 2,
"id": 1586205644890
}
],
"playing": [
{
"graphic": {
"name": "Nafn",
"engine": "text",
"settings": {
"properties": [
"nafn",
"titill"
],
"main": "<%- nafn %>",
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
},
"id": 1586112780892
},
"name": "Nafn",
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2>Bla 2</h2>\n<h4>test 2</h4>\n</div>\n</div>",
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}",
"data": {
"nafn": "Bla 2",
"titill": "test 2"
},
"is_deleted": false,
"id": 1586213076185
}
],
"schedule": [
{
"graphic_id": 1586112780892,
"values": {
"nafn": "Bla 2",
"titill": "test 2"
},
"sort": 1,
"id": 1586213073361,
"graphic": {
"name": "Nafn",
"engine": "text",
"settings": {
"properties": [
"nafn",
"titill"
],
"main": "<%- nafn %>",
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
},
"id": 1586112780892
}
},
{
"graphic_id": 1586112780892,
"values": {
"nafn": "Bla",
"titill": "test"
},
"sort": 2,
"id": 1586213074043,
"graphic": {
"name": "Nafn",
"engine": "text",
"settings": {
"properties": [
"nafn",
"titill"
],
"main": "<%- nafn %>",
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
},
"id": 1586112780892
}
}
],
"settings": {
"casparplayhost": "localhost:3000",
"casparhost": "host.docker.internal"
},
"version": 1,
"trash": []
}

2772
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
"start:win": "node --experimental-modules index.mjs | bunyan -o short",
"dev": "run-p js:watch start:watch",
"build": "run-p js:build:main js:build:client js:build:status",
"docker": "docker run -it --rm --name my-running-script -p 3000:3000 -v \"%cd%\":/usr/src/app -w /usr/src/app node",
"docker": "docker run -it --rm --name my-running-script -p 3000:3000 -v \"%cd%\":/usr/src/app -w /usr/src/app node:alpine",
"docker:install": "npm run docker -- npm install",
"docker:dev": "npm run docker -- npm run dev"
},
@ -34,19 +34,17 @@
},
"homepage": "https://github.com/nfp-projects/caspar-sup#readme",
"dependencies": {
"bunyan": "^1.8.12",
"bunyan-lite": "^1.0.1",
"casparcg-connection": "4.9.0",
"koa": "^2.4.1",
"koa-better-serve": "^2.0.7",
"koa-socket": "^4.4.0",
"lodash.template": "^4.5.0",
"lodash": "^4.5.0",
"lowdb": "^1.0.0",
"nconf": "^0.9.1",
"socket.io": "^2.3.0",
"node-static": "^0.7.11",
"socket.io-serveronly": "^2.3.0",
"tslib": "^1.11.1"
},
"devDependencies": {
"asbundle": "TheThing/asbundle",
"asbundle": "^2.6.1",
"dragula": "^3.7.2",
"mithril": "^1.1.5",
"nodemon": "^2.0.2",