diff --git a/README.MD b/README.MD index a31bb79..54bcd5a 100644 --- a/README.MD +++ b/README.MD @@ -6,5 +6,5 @@ - [X] time on countdown page - [X] one-way messaging - [ ] Better UI -- [ ] Progress bar -- [ ] Endpoint docs +- [X] Progress bar +- [P] Endpoint docs diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..dd9b3d7 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,323 @@ +swagger: "2.0" +info: + description: "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters." + version: "1.0.0" + title: "openCountdown API" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" +host: "localhost:3005" +basePath: "/api/v1" +tags: +- name: "pet" + description: "Everything about your Pets" + externalDocs: + description: "Find out more" + url: "http://swagger.io" +- name: "store" + description: "Access to Petstore orders" +- name: "user" + description: "Operations about user" + externalDocs: + description: "Find out more about about openCountdown" + url: "http://swagger.io" +schemes: +- "http" +paths: + /set/mode: + get: + tags: + - "pet" + summary: "Set the current timers mode" + description: "" + operationId: "setMode" + parameters: + - in: path + name: mode + required: true + type: string + description: The timers mode, can be any of timer, clock, test or black. + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + + + /set/timerGoal: + get: + tags: + - "pet" + summary: "Sets the timers goal to `time`, using epoch" + description: "" + operationId: "setTimerGoal" + parameters: + - in: path + name: "time" + required: true + type: number + description: The time when the timer will reach 0 in milliseconds since the epoch start. + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + /set/addMillisToTimer: + get: + tags: + - "pet" + summary: "Sets the timers goal to now + `time`" + description: "" + operationId: "addMillis" + parameters: + - in: path + name: "time" + required: true + type: number + description: Adds the given input to the current time. Using milliseconds + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + + /set/layout/showTime: + get: + tags: + - "layout" + summary: "If set to true will show the current time on timer page" + description: "" + operationId: "showTime" + parameters: + - in: path + name: "show" + required: true + type: boolean + description: If true will show the current time as a clock below the timer + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + + /set/layout/showMillis: + get: + tags: + - "layout" + summary: "If set to true will show the milliseconds left on timer page" + description: "" + operationId: "showMillis" + parameters: + - in: path + name: "show" + required: true + type: boolean + description: If true will show the milliseconds left on the timer page + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + /set/progressbar/show: + get: + tags: + - "progressbar" + summary: "If set to true will show the progressbar" + description: "" + operationId: "showProgress" + parameters: + - in: path + name: "show" + required: true + type: boolean + description: "If true will show the progressbar on the timer page" + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + /set/progressbar/colors: + get: + tags: + - "progressbar" + summary: "Allows to set the color by value" + description: "" + operationId: "progressColors" + parameters: + - in: path + name: "colors" + required: true + type: string + description: "Takes a dictonary with the key being the time left on the countdown and any css color as the value. Example: `{5000: 'red'}`" + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + /set/text/enableColoring: + get: + tags: + - "text" + summary: "Enable or disable color based on value for the timer" + description: "" + operationId: "textEnableColoring" + parameters: + - in: path + name: "show" + required: true + type: boolean + description: "If true the timer will change color by value, else the timer stays white." + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + + /set/text/colors: + get: + tags: + - "text" + summary: "Allows to set the color by value" + description: "" + operationId: "textColors" + parameters: + - in: path + name: "colors" + required: true + type: string + description: "Takes a dictonary with the key being the time left on the countdown and any css color as the value. Example: `{5000: 'red'}`" + produces: + - "application/json" + responses: + "200": + description: "Request was succesful" + +definitions: + Order: + type: "object" + properties: + id: + type: "integer" + format: "int64" + petId: + type: "integer" + format: "int64" + quantity: + type: "integer" + format: "int32" + shipDate: + type: "string" + format: "date-time" + status: + type: "string" + description: "Order Status" + enum: + - "placed" + - "approved" + - "delivered" + complete: + type: "boolean" + default: false + xml: + name: "Order" + Category: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Category" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + username: + type: "string" + firstName: + type: "string" + lastName: + type: "string" + email: + type: "string" + password: + type: "string" + phone: + type: "string" + userStatus: + type: "integer" + format: "int32" + description: "User Status" + xml: + name: "User" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Tag" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + properties: + id: + type: "integer" + format: "int64" + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + xml: + name: "Pet" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" +externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io" \ No newline at end of file diff --git a/index.js b/index.js index 4de5617..3597f74 100644 --- a/index.js +++ b/index.js @@ -28,9 +28,16 @@ currentState = { showMessage: false, messageAppearTime: 0, showProgressbar: true, - colorSegments: {20000: "#FFAE00", 5000: "#ff0000", "START": "yellow"} + colorSegments: {20000: "#FFAE00", 5000: "#ff0000", "START": "yellow"}, + textColors: {}, + srvTime: 0, + enableColoredText: true, + debug: false }; +currentState.textColors = currentState.colorSegments + + app.get("/", function (req, res) { const data = fs.readFileSync("templates/adminPanel.html", "utf8"); res.send(data); @@ -42,6 +49,7 @@ app.get("/timer", function (req, res) { }); app.get("/api/v1/data", function (req, res) { + currentState.srvTime = new Date().getTime() res.json(currentState); }); @@ -50,13 +58,13 @@ app.get("/api/v1/set/mode", function (req, res) { res.json({ status: "ok" }); }); -app.get("/api/v1/set/showMillis", function (req, res) { +app.get("/api/v1/set/layout/showMillis", function (req, res) { currentState.showMilliSeconds = (req.query.show === 'true'); res.json({ status: "ok" }); }); app.get("/api/v1/set/timerGoal", function (req, res) { - currentState.countdownGoal = new Date(parseInt(req.query.time)).getTime(); + currentState.countdownGoal = new Date(parseInt(req.query.time)).getTime(); // ToDO error handling res.json({ status: "ok" }); }); @@ -83,16 +91,41 @@ app.get("/api/v1/ctrl/timer/restart", function (req, res) { res.json({ status: "ok" }); }); -app.get("/api/v1/set/showTime", function (req, res) { +app.get("/api/v1/set/layout/showTime", function (req, res) { currentState.showTimeOnCountdown = (req.query.show === 'true'); res.json({ status: "ok" }); }); -app.get("/api/v1/set/showProgressBar", function (req, res) { +app.get("/api/v1/set/progressbar/show", function (req, res) { currentState.showProgressbar = (req.query.show === 'true'); res.json({ status: "ok" }); }); +app.get("/api/v1/set/progressbar/colors", function (req, res) { + try { + currentState.colorSegments = JSON.parse(req.query.colors); + res.json({ status: "ok" }); + } catch (error) { + res.json({ status: "error", message: error }); + } +}); + +app.get("/api/v1/set/text/colors", function (req, res) { + try { + if(req.query.copy === "true"){ + currentState.textColors = currentState.colorSegments; + } else { + currentState.textColors = JSON.parse(req.query.colors); + } + res.json({ status: "ok" }); + } catch (error) { + res.json({ status: "error", message: error }); + } +}); + +app.get("/api/v1/set/text/enableColoring", function (req, res) { + currentState.enableColoredText = (req.query.enable === 'true'); +}); app.get("/api/v1/ctrl/message/show", function (req, res) { currentState.message = req.query.msg @@ -101,6 +134,11 @@ app.get("/api/v1/ctrl/message/show", function (req, res) { res.json({ status: "ok" }); }); +app.get("/api/v1/debug", function (req, res) { + currentState.debug = (req.query.enable === 'true'); + res.json({ status: "ok" }); +}); + app.get("/api/v1/ctrl/message/hide", function (req, res) { currentState.showMessage = false res.json({ status: "ok" }); diff --git a/static/js/script.js b/static/js/script.js index cbb54bd..88211bb 100644 --- a/static/js/script.js +++ b/static/js/script.js @@ -1,31 +1,37 @@ var newDateObj = new Date(); -newDateObj = new Date(newDateObj.getTime() + 1000*20) +newDateObj = new Date(newDateObj.getTime() + 1000 * 20) allowFullscreen = true function enterFullscreen(element) { - if(element.requestFullscreen) { + if (element.requestFullscreen) { element.requestFullscreen(); - } else if(element.msRequestFullscreen) { // for IE11 (remove June 15, 2022) + } else if (element.msRequestFullscreen) { // for IE11 (remove June 15, 2022) element.msRequestFullscreen(); - } else if(element.webkitRequestFullscreen) { // iOS Safari + } else if (element.webkitRequestFullscreen) { // iOS Safari element.webkitRequestFullscreen(); } } +function returnData() { + return (JSON.parse(document.getElementById("incomeData").innerHTML)) +} + function percentage(partialValue, totalValue) { return (100 * partialValue) / totalValue; -} +} -function updateFullscreen(){ - if(JSON.parse(document.getElementById("incomeData").innerHTML).defaultFullScreen && allowFullscreen){ +function updateFullscreen() { + if (JSON.parse(document.getElementById("incomeData").innerHTML).defaultFullScreen && allowFullscreen) { enterFullscreen(document.documentElement) } } + + function msToTime(s, data) { isSmallerThenZero = false - if(s < 0){ + if (s < 0) { isSmallerThenZero = true } @@ -37,108 +43,129 @@ function msToTime(s, data) { var hrs = (s - mins) / 60; let out = "" - if(!data.showMilliSeconds){ - out = ('00' + Math.abs(hrs)).slice(-2) + ':' + ('00'+Math.abs(mins)).slice(-2) + ':' + ('00'+Math.abs(secs)).slice(-2) - }else { - out = ('00' + Math.abs(hrs)).slice(-2) + ':' + ('00'+Math.abs(mins)).slice(-2) + ':' + ('00'+Math.abs(secs)).slice(-2) + '.' + ('000'+Math.abs(ms)).slice(-3) + if (!data.showMilliSeconds) { + out = ('00' + Math.abs(hrs)).slice(-2) + ':' + ('00' + Math.abs(mins)).slice(-2) + ':' + ('00' + Math.abs(secs)).slice(-2) + } else { + out = ('00' + Math.abs(hrs)).slice(-2) + ':' + ('00' + Math.abs(mins)).slice(-2) + ':' + ('00' + Math.abs(secs)).slice(-2) + '.' + ('000' + Math.abs(ms)).slice(-3) } - if(isSmallerThenZero){ + if (isSmallerThenZero) { out = "-" + out } return out; } -function findProgessColor(colors, value){ - console.info("\n\n\n\n\n") +function findProgessColor(colors, value) { const allColors = Object.keys(colors); let resColor = colors["START"] - - for(let color in allColors){ + for (let color in allColors) { const currColor = allColors[color] - console.log(color, currColor, parseInt(currColor), value, colors[String(currColor)]) - if(value <= parseInt(currColor)){ - console.log("trith") - resColor = colors[currColor] + // console.log(color, currColor, parseInt(currColor), value, colors[String(currColor)], resColor) + if (value <= parseInt(currColor)) { + resColor = colors[String(currColor)] + break } } - - // console.info(resColor, value) - return(resColor) + return (resColor) } function handleUpdate() { resp = httpGet("/api/v1/data"); - var data = JSON.parse(resp); - document.getElementById("incomeData").innerHTML = JSON.stringify(data) - - if(data.defaultFullScreen && document.getElementById("initalDate").innerHTML.includes("true") && allowFullscreen){ - enterFullscreen(document.documentElement); - document.getElementById("initalDate").innerHTML = "false" - } - - if(data.showMessage) { - document.getElementById("overlay").style.display = "block"; - document.getElementById("text").innerHTML = data.message - }else{ - off() - } - - if(new Date().getTime() - data.messageAppearTime < 5000) { - if (! document.getElementById("text").classList.contains('blink') ){ - document.getElementById("text").classList.add("blink") + resp.onloadend = function (e) { + if(resp.status == 200){ + resp = resp.responseText; + var data = JSON.parse(resp); + document.getElementById("incomeData").innerHTML = JSON.stringify(data) + document.getElementById("timediff").innerHTML = new Date().getTime() - data.srvTime; + if(data.debug){ + document.getElementById("timediff").style.display = "block"; + }else{ + document.getElementById("timediff").style.display = "none"; + } + + if (data.defaultFullScreen && document.getElementById("initalDate").innerHTML.includes("true") && allowFullscreen) { + enterFullscreen(document.documentElement); + document.getElementById("initalDate").innerHTML = "false" + } + + if (data.showMessage) { + document.getElementById("overlay").style.display = "block"; + document.getElementById("text").innerHTML = data.message + } else { + off() + } + + if (new Date().getTime() - data.messageAppearTime < 5000) { + if (!document.getElementById("text").classList.contains('blink')) { + document.getElementById("text").classList.add("blink") + } + } else { + if (document.getElementById("text").classList.contains('blink')) { + document.getElementById("text").classList.remove("blink") + } + } + + + if (data.mode == "clock") { + document.getElementById("timer").innerHTML = getTime(); + document.getElementById("testImg").style.display = "none"; + document.getElementById("wholeProgBar").style.display = "none"; + + } else if (data.mode == "timer") { + + document.getElementById("wholeProgBar").style.display = "block"; + + if (data.timerRunState) { + const now = new Date() + const diff = data.countdownGoal - now.getTime() + document.getElementById("timer").innerHTML = msToTime(diff, data); + if (diff > 0) { + document.getElementById("progBar").style.width = percentage(diff, data.timeAmountInital) + "%"; + } else { + document.getElementById("progBar").style.width = "0%"; + } + + document.getElementById("progBar").style.backgroundColor = findProgessColor(data.colorSegments, diff) + document.getElementById("testImg").style.display = "none"; + if (data.enableColoredText) { + document.getElementById("timer").style.color = findProgessColor(data.textColors, diff) + } else { + document.getElementById("timer").style.color = "white" + } + + } + if (data.showTimeOnCountdown) { + document.getElementById("clockSec").innerHTML = getTime(); + } else { + document.getElementById("clockSec").innerHTML = ""; + } + + } else if (data.mode == "black") { + document.getElementById("timer").innerHTML = ""; + document.getElementById("testImg").style.display = "none"; + document.getElementById("wholeProgBar").style.display = "none"; + + } else if (data.mode == "test") { + document.getElementById("timer").innerHTML = ""; + document.getElementById("testImg").style.display = "block"; + document.getElementById("progBar").style.display = "none"; + } } - }else{ - if ( document.getElementById("text").classList.contains('blink') ){ - document.getElementById("text").classList.remove("blink") - } - } - - - if (data.mode == "clock") { - document.getElementById("timer").innerHTML = getTime(); - document.getElementById("testImg").style.display = "none"; - document.getElementById("wholeProgBar").style.display = "none"; - - } else if (data.mode == "timer") { - - - - document.getElementById("wholeProgBar").style.display = "block"; - if(data.timerRunState){ - const now = new Date() - const diff = data.countdownGoal - now.getTime() - document.getElementById("timer").innerHTML = msToTime(diff, data); - document.getElementById("progBar").style.width = percentage(diff, data.timeAmountInital) + "%"; - document.getElementById("progBar").style.backgroundColor = findProgessColor(data.colorSegments,diff) - document.getElementById("testImg").style.display = "none"; - - } - if(data.showTimeOnCountdown){ - document.getElementById("clockSec").innerHTML = getTime(); - } else { - document.getElementById("clockSec").innerHTML = ""; - } - - } else if (data.mode == "black") { - document.getElementById("timer").innerHTML = ""; - document.getElementById("testImg").style.display = "none"; - document.getElementById("wholeProgBar").style.display = "none"; - - } else if (data.mode == "test") { - document.getElementById("timer").innerHTML = ""; - document.getElementById("testImg").style.display = "block"; - document.getElementById("progBar").style.display = "none"; } + + } function httpGet(theUrl) { var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("GET", theUrl, false); // false for synchronous request + xmlHttp.open("GET", theUrl, true); // false for synchronous request xmlHttp.send(null); - return xmlHttp.responseText; + xmlHttp.onerror = function (e) { + console.log(e); + }; + return xmlHttp; } function getTime() { @@ -170,6 +197,6 @@ let temp = new URLSearchParams(window.location.search).get("smaller"); if (temp == "true") { var cssURL = '/css/smallerTextMod.css'; - document.head.innerHTML +='' + document.head.innerHTML += '' allowFullscreen = false } diff --git a/templates/timerPage.html b/templates/timerPage.html index 8f9955e..a08a0a1 100644 --- a/templates/timerPage.html +++ b/templates/timerPage.html @@ -34,9 +34,10 @@ 00:00:00
-
- +
+ +