Write frontend
This commit is contained in:
parent
638b43c29b
commit
0aece8b8ca
2 changed files with 402 additions and 62 deletions
|
@ -3,48 +3,205 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>LED strip control</title>
|
<title>LAP</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
html, body {
|
html, body {
|
||||||
background-color: white;
|
background-color: #222;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button, textarea {
|
||||||
|
color: inherit;
|
||||||
|
background-color: #222;
|
||||||
|
padding: 1ex;
|
||||||
|
border-radius: 1ex;
|
||||||
|
border: 1px solid #777;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0.4em 0.4em 1em #0d0d0d inset;
|
||||||
|
}
|
||||||
|
input:focus, button:focus, textarea:focus {
|
||||||
|
border-color: #6688ff;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding: 0.5ex 1ex;
|
||||||
|
box-shadow: -0.4em -0.4em 1em #0d0d0d inset, 0.2em 0.2em 0.5em #1d1d1d;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
border-color: #656565;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
box-shadow: 0.4em 0.4em 1em #0d0d0d inset, 0.2em 0.2em 0.5em #1d1d1d;
|
||||||
|
}
|
||||||
|
input[disabled], button[disabled], textarea[disabled] {
|
||||||
|
box-shadow: none;
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
button[disabled] {
|
||||||
|
color: #777;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 600px;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.yesscript {
|
.yesscript {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.segment {
|
||||||
|
font-size: 70%;
|
||||||
|
display: inline-block;
|
||||||
|
height: 1em;
|
||||||
|
line-height: 1em;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
margin: 1px;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
padding: 2px;
|
||||||
|
box-shadow: 0 0.2em 0.5em #1d1d1d;
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment:first-child {
|
||||||
|
border-top-left-radius: 0.75em;
|
||||||
|
border-bottom-left-radius: 0.75em;
|
||||||
|
}
|
||||||
|
.segment:last-child {
|
||||||
|
border-top-right-radius: 0.75em;
|
||||||
|
border-bottom-right-radius: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment.active {
|
||||||
|
border-color: #fff;
|
||||||
|
z-index: 101;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment:focus, .segment:hover {
|
||||||
|
border-color: #6688ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#owner_label {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
z-index: 300;
|
||||||
|
background-color: #4466dd;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
padding: 0.2em 0.4em;
|
||||||
|
color: white;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led {
|
||||||
|
display: inline-block;
|
||||||
|
height: 6px;
|
||||||
|
width: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-right: 2px;
|
||||||
|
background-color: #fff;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment.active .led {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
#segment-control, #program {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#owner_line {
|
||||||
|
line-height: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lua_editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
(function() {
|
(function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var styleObject = document.createElement("style");
|
var styleObject = document.createElement("style");
|
||||||
styleObject.innerHTML = ".yesscript { display: initial; }";
|
styleObject.innerHTML = ".yesscript { display: block; }";
|
||||||
document.head.appendChild(styleObject);
|
document.head.appendChild(styleObject);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>LED strip control</h1>
|
<div id="owner_label"></div>
|
||||||
|
|
||||||
<p class="noscript">This application requires JavaScript.</p>
|
<h1>Zeus WPI – LED-Automaten-Programmatie</h1>
|
||||||
<div class="yesscript"><input type="text" name="us" id="us" onchange="ledStripControl.updateUs()"></div>
|
|
||||||
<svg id="segments" class="yesscript">
|
|
||||||
|
|
||||||
</svg>
|
<p class="noscript">Voor deze applicatie is helaas JavaScript vereist.</p>
|
||||||
|
|
||||||
|
<div id="configuration" class="yesscript">
|
||||||
|
<h2>Configuratie</h2>
|
||||||
|
Je schuilnaam: <input type="text" name="us" id="us" onchange="ledStripControl.updateUs()">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="led-strip" class="yesscript">
|
||||||
|
<h2>LED-strip</h2>
|
||||||
|
<div id="segments">
|
||||||
|
LED-strip wordt geladen...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="segment-control">
|
||||||
|
<h2>Segmentcontrole</h2>
|
||||||
|
<div>
|
||||||
|
Segment <b id="active_segment_id"></b>
|
||||||
|
van LED <b id="active_segment_begin"></b>
|
||||||
|
tot <b id="active_segment_end"></b>
|
||||||
|
</div>
|
||||||
|
<div id="owner_line">Toegewezen aan: <b id="active_segment_owner"></b> <button id="claim_button"></button> <button id="release_button"></button></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="program">
|
||||||
|
<h2>Programma</h2>
|
||||||
|
<p id="not-your-own">Dit segment is niet van jou. Je kunt de code enkel bekijken.</p>
|
||||||
|
<textarea id="lua_editor" spellcheck="false"></textarea>
|
||||||
|
<div id="program-controls">
|
||||||
|
<button id="publish-button">Publiceren</button>
|
||||||
|
<p>De code wordt niet bestendig bewaard. <strong>Sla ze zelf op op je computer.</strong> Gebruik dit veld bij voorkeur enkel om naar te kopiëren-en-plakken.</p>
|
||||||
|
</div>
|
||||||
|
<div id="program-instructions">
|
||||||
|
<p>Programmeer je segment in Lua. Voor je code lijkt het alsof je LED 0 tot <span id="active_segment_last_virtual">x</span> hebt. Extra beschikbare functies:</p>
|
||||||
|
<dl>
|
||||||
|
<dt>led(led_nr, r, g, b)</dt>
|
||||||
|
<dd>Stel LED <i>led_nr</i> in op de kleur met gegeven RGB-waarden (0–255)</dd>
|
||||||
|
<dt>ledamount(something, probably)</dt>
|
||||||
|
<dd>Uhh</dd>
|
||||||
|
<dt>delay(ms)</dt>
|
||||||
|
<dd>Wacht gedurende <i>ms</i> milliseconden</dd>
|
||||||
|
<dt>waitframes(frames)</dt>
|
||||||
|
<dd>Wacht gedurende <i>frames</i> frames</dd>
|
||||||
|
<dt>print(message)</dt>
|
||||||
|
<dd>Stuur <i>message</i> naar de console</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
(function() {
|
||||||
var ledStripControl = (function() {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var objects = document.getElementsByClassName("noscript");
|
var objects = document.getElementsByClassName("noscript");
|
||||||
|
@ -53,57 +210,9 @@ var ledStripControl = (function() {
|
||||||
objects[i].parentElement.removeChild(objects[i]);
|
objects[i].parentElement.removeChild(objects[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var HOST = "http://10.1.0.212:8080";
|
|
||||||
|
|
||||||
function getJson(url, callback) {
|
|
||||||
function reqListener() {
|
|
||||||
callback(JSON.parse(this.responseText));
|
|
||||||
}
|
|
||||||
|
|
||||||
var oReq = new XMLHttpRequest();
|
|
||||||
oReq.addEventListener("load", reqListener);
|
|
||||||
oReq.open("GET", url);
|
|
||||||
oReq.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
var us = null;
|
|
||||||
function updateUs() {
|
|
||||||
us = document.getElementById("us").value;
|
|
||||||
showSegments();
|
|
||||||
}
|
|
||||||
updateUs();
|
|
||||||
|
|
||||||
var segments = null;
|
|
||||||
|
|
||||||
function saveAndShowSegments(segs) {
|
|
||||||
segments = segs;
|
|
||||||
showSegments();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showSegments() {
|
|
||||||
var segmentsContent = "";
|
|
||||||
if (segments !== null) for (var i in segments) {
|
|
||||||
var seg = segments[i];
|
|
||||||
var color = seg.owner == "" ? "gray" : seg.owner == us ? "green" : "red";
|
|
||||||
var left = 12.5 + (7 * parseFloat(seg.begin));
|
|
||||||
console.log(left);
|
|
||||||
segmentsContent += '<rect' +
|
|
||||||
' width="100" height="25"' +
|
|
||||||
' x="' + left + '" y="12.5"' +
|
|
||||||
' rx="12.5" ry="12.5"' +
|
|
||||||
' id="segment' + seg.id + '" ' +
|
|
||||||
' fill="' + color + '"/>';
|
|
||||||
}
|
|
||||||
document.getElementById("segments").innerHTML = segmentsContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
getJson(HOST + "/api/segments.json", saveAndShowSegments);
|
|
||||||
|
|
||||||
return {
|
|
||||||
updateUs: updateUs,
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script type="application/javascript" src="main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
231
frontend/main.js
Normal file
231
frontend/main.js
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
var ledStripControl = (function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var HOST = "http://localhost:8080";
|
||||||
|
|
||||||
|
var segments = null;
|
||||||
|
var activeSegmentId = null;
|
||||||
|
var us = null;
|
||||||
|
|
||||||
|
function xhr(url, method, data, callback) {
|
||||||
|
var oReq = new XMLHttpRequest();
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
function reqListener() {
|
||||||
|
var json = null;
|
||||||
|
try { json = JSON.parse(this.responseText); } catch(e) {}
|
||||||
|
callback(json);
|
||||||
|
}
|
||||||
|
oReq.addEventListener("load", reqListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
oReq.open(method, url);
|
||||||
|
oReq.send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJson(url, callback) {
|
||||||
|
xhr(url, "GET", "", callback);
|
||||||
|
}
|
||||||
|
function putJson(url, data, callback) {
|
||||||
|
xhr(url, "PUT", JSON.stringify(data), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUs() {
|
||||||
|
us = document.getElementById("us").value;
|
||||||
|
showSegments();
|
||||||
|
}
|
||||||
|
updateUs();
|
||||||
|
|
||||||
|
function saveAndShowSegments(segs) {
|
||||||
|
segments = {};
|
||||||
|
for (var i in segs) {
|
||||||
|
segments[segs[i].id] = segs[i];
|
||||||
|
}
|
||||||
|
showSegments();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchSegments() {
|
||||||
|
getJson(HOST + "/api/segments.json", saveAndShowSegments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function activateSegment(segment) {
|
||||||
|
activeSegmentId = segment.id;
|
||||||
|
getJson(HOST + "/api/segments.json", saveAndShowSegments);
|
||||||
|
showSegments();
|
||||||
|
document.getElementById("segment-control").style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
function repeatString(text, amount) {
|
||||||
|
var result = "";
|
||||||
|
for (var i = 0; i < amount; i++) {
|
||||||
|
result += text;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSegmentEventListener(e) {
|
||||||
|
if (e.currentTarget.dataset["segment"] !== "true") return;
|
||||||
|
|
||||||
|
var id = e.currentTarget.dataset["id"];
|
||||||
|
activateSegment(segments[id]);
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
function showOwnerEventListener(e) {
|
||||||
|
if (e.currentTarget.dataset["segment"] !== "true") return;
|
||||||
|
|
||||||
|
var owner = e.currentTarget.dataset["owner"];
|
||||||
|
if (owner) {
|
||||||
|
document.getElementById("owner_label").innerText = owner;
|
||||||
|
} else {
|
||||||
|
document.getElementById("owner_label").innerHTML = "<i>Vrij</i>";
|
||||||
|
}
|
||||||
|
document.getElementById("owner_label").style.display = "block";
|
||||||
|
document.getElementById("owner_label").style.left = (e.currentTarget.clientWidth/2 + e.currentTarget.offsetLeft - document.getElementById("owner_label").clientWidth/2) + "px";
|
||||||
|
document.getElementById("owner_label").style.top = (e.currentTarget.offsetTop - document.getElementById("owner_label").clientHeight - 2) + "px";
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
function hideOwnerEventListener(e) {
|
||||||
|
if (e.currentTarget.dataset["segment"] !== "true") return;
|
||||||
|
|
||||||
|
document.getElementById("owner_label").innerHTML = "";
|
||||||
|
document.getElementById("owner_label").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePublishButton() {
|
||||||
|
var activeSegment = activeSegmentId !== null ? segments[activeSegmentId] : null;
|
||||||
|
if (document.getElementById("lua_editor").value == activeSegment.code) {
|
||||||
|
document.getElementById("publish-button").innerText = "Gepubliceerd";
|
||||||
|
document.getElementById("publish-button").setAttribute("disabled", "disabled");
|
||||||
|
} else {
|
||||||
|
document.getElementById("publish-button").innerText = "Publiceren";
|
||||||
|
document.getElementById("publish-button").removeAttribute("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSegments() {
|
||||||
|
var segmentsContainer = document.getElementById("segments");
|
||||||
|
segmentsContainer.innerHTML = "";
|
||||||
|
|
||||||
|
var prevSegEnd = 0;
|
||||||
|
if (segments !== null) for (var i in segments) {
|
||||||
|
if (!segments.hasOwnProperty(i)) continue;
|
||||||
|
var seg = segments[i];
|
||||||
|
var color = seg.owner === "" ? "#555" : seg.owner === us ? "#050" : "#700";
|
||||||
|
|
||||||
|
var unsegmented = parseFloat(seg.begin) - prevSegEnd;
|
||||||
|
if (unsegmented > 0) {
|
||||||
|
var unsegmented_el = document.createElement("span");
|
||||||
|
unsegmented_el.className = "unsegmented";
|
||||||
|
unsegmented_el.innerHTML = repeatString("<span class='led'></span>", unsegmented);
|
||||||
|
segmentsContainer.append(unsegmented_el);
|
||||||
|
}
|
||||||
|
|
||||||
|
var rect = document.createElement("a");
|
||||||
|
rect.className = seg.id === activeSegmentId ? "active segment" : "segment";
|
||||||
|
rect.style.backgroundColor = color;
|
||||||
|
rect.id = "segment" + seg.id;
|
||||||
|
rect.href = "#segment" + seg.id;
|
||||||
|
rect.dataset["segment"] = "true";
|
||||||
|
rect.dataset["owner"] = seg.owner;
|
||||||
|
rect.dataset["id"] = seg.id;
|
||||||
|
rect.addEventListener("click", showSegmentEventListener);
|
||||||
|
rect.addEventListener("focus", showOwnerEventListener);
|
||||||
|
rect.addEventListener("blur", hideOwnerEventListener);
|
||||||
|
rect.addEventListener("mouseover", showOwnerEventListener);
|
||||||
|
rect.addEventListener("mouseout", hideOwnerEventListener);
|
||||||
|
rect.innerHTML = repeatString("<span class='led'></span>", seg.length);
|
||||||
|
segmentsContainer.appendChild(rect);
|
||||||
|
|
||||||
|
prevSegEnd = seg.begin + seg.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeSegment = activeSegmentId !== null ? segments[activeSegmentId] : null;
|
||||||
|
if (activeSegment !== null) {
|
||||||
|
document.getElementById("active_segment_id").innerText = activeSegmentId;
|
||||||
|
document.getElementById("active_segment_begin").innerText = activeSegment.begin;
|
||||||
|
document.getElementById("active_segment_end").innerText = activeSegment.begin + activeSegment.length - 1;
|
||||||
|
document.getElementById("active_segment_last_virtual").innerText = activeSegment.length - 1;
|
||||||
|
|
||||||
|
updatePublishButton();
|
||||||
|
|
||||||
|
document.getElementById("lua_editor").value = activeSegment.code;
|
||||||
|
|
||||||
|
if (activeSegment.owner !== "" && activeSegment.owner === us) {
|
||||||
|
document.getElementById("release_button").style.display = "";
|
||||||
|
document.getElementById("release_button").innerText = "Onteigen";
|
||||||
|
document.getElementById("release_button").removeAttribute("disabled");
|
||||||
|
|
||||||
|
document.getElementById("lua_editor").removeAttribute("disabled");
|
||||||
|
document.getElementById("not-your-own").style.display = "none";
|
||||||
|
document.getElementById("program-controls").style.display = "block";
|
||||||
|
document.getElementById("program-instructions").style.display = "block";
|
||||||
|
} else {
|
||||||
|
document.getElementById("release_button").style.display = "none";
|
||||||
|
|
||||||
|
document.getElementById("lua_editor").setAttribute("disabled", "disabled");
|
||||||
|
document.getElementById("not-your-own").style.display = "block";
|
||||||
|
document.getElementById("program-controls").style.display = "none";
|
||||||
|
document.getElementById("program-instructions").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeSegment.owner !== "") {
|
||||||
|
document.getElementById("active_segment_owner").innerText = activeSegment.owner;
|
||||||
|
document.getElementById("claim_button").style.display = "none";
|
||||||
|
|
||||||
|
document.getElementById("program").style.display = "block";
|
||||||
|
} else {
|
||||||
|
document.getElementById("active_segment_owner").innerText = "nog niemand";
|
||||||
|
document.getElementById("claim_button").style.display = "";
|
||||||
|
document.getElementById("claim_button").innerText = "Eigen je toe";
|
||||||
|
document.getElementById("claim_button").removeAttribute("disabled");
|
||||||
|
|
||||||
|
document.getElementById("program").style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("claim_button").addEventListener("click", function() {
|
||||||
|
document.getElementById("claim_button").innerText = "Bezig met toe-eigenen...";
|
||||||
|
document.getElementById("claim_button").setAttribute("disabled", "disabled");
|
||||||
|
var activeSegment = segments[activeSegmentId];
|
||||||
|
if (!activeSegment) { throw new Error("Trying to claim segment but no segment active"); }
|
||||||
|
putJson(HOST + "/api/code.json", {
|
||||||
|
"id": activeSegmentId,
|
||||||
|
"owner": us,
|
||||||
|
"code": activeSegment.code
|
||||||
|
}, fetchSegments);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("release_button").addEventListener("click", function() {
|
||||||
|
document.getElementById("release_button").innerText = "Bezig met onteigenen...";
|
||||||
|
document.getElementById("release_button").setAttribute("disabled", "disabled");
|
||||||
|
var activeSegment = segments[activeSegmentId];
|
||||||
|
if (!activeSegment) { throw new Error("Trying to release segment but no segment active"); }
|
||||||
|
putJson(HOST + "/api/code.json", {
|
||||||
|
"id": activeSegmentId,
|
||||||
|
"owner": "",
|
||||||
|
"code": activeSegment.code
|
||||||
|
}, fetchSegments);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("publish-button").addEventListener("click", function() {
|
||||||
|
document.getElementById("publish-button").innerText = "Bezig met publiceren...";
|
||||||
|
document.getElementById("publish-button").setAttribute("disabled", "disabled");
|
||||||
|
var activeSegment = segments[activeSegmentId];
|
||||||
|
if (!activeSegment) { throw new Error("Trying to update code of segment but no segment active"); }
|
||||||
|
putJson(HOST + "/api/code.json", {
|
||||||
|
"id": activeSegmentId,
|
||||||
|
"owner": activeSegment.owner,
|
||||||
|
"code": document.getElementById("lua_editor").value
|
||||||
|
}, fetchSegments);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("lua_editor").addEventListener("keyup", updatePublishButton);
|
||||||
|
document.getElementById("lua_editor").addEventListener("change", updatePublishButton);
|
||||||
|
|
||||||
|
fetchSegments();
|
||||||
|
|
||||||
|
return {
|
||||||
|
updateUs: updateUs,
|
||||||
|
};
|
||||||
|
})();
|
Loading…
Reference in a new issue