]> OzVa Git service - shopping-channel/commitdiff
Some small control changes
authorMax Value <greenwoodw50@gmail.com>
Sat, 5 Apr 2025 22:56:20 +0000 (23:56 +0100)
committerMax Value <greenwoodw50@gmail.com>
Sat, 5 Apr 2025 22:56:20 +0000 (23:56 +0100)
+ markupsafe requirement
+ end_timer_main for tracking when the clock ticks should be
+ schedule marks to the clock control pannel
~ moved the note feild to the text pannel

requirements.txt
schema
teleshopping.py
templates/clock.html
templates/price.html
templates/text.html

index 3517df0c9f9fcd13acacea8a0e24bdc278ffcf83..83260ee34097e5a3b20c80e6dd1fecf68fcbcc8a 100644 (file)
@@ -1,4 +1,5 @@
 flask_httpauth
 flask
+markupsafe
 werkzeug
 jinja2
diff --git a/schema b/schema
index 13b859a2e7ff9c70d267f7763d582d000a8c5b07..5869f54383c4da3585c142142ce6bc5e387f43aa 100644 (file)
--- a/schema
+++ b/schema
@@ -28,6 +28,7 @@ CREATE TABLE state (
        end_timer_4 INTEGER,
        end_timer_5 INTEGER,
        end_timer_6 INTEGER,
+       end_timer_main INTEGER,
        focus_timer_1 INTEGER,
        focus_timer_2 INTEGER,
        focus_timer_3 INTEGER,
index 14122a17f8c40971cb002091c4cd9ae1effcdd5d..5ea67435e02ad1219e0ed4e46eec88f68b092446 100755 (executable)
@@ -7,6 +7,7 @@ from flask_httpauth import HTTPBasicAuth
 from datetime import datetime, timezone
 from os import path, environ, system
 from math import radians, cos, sin
+from markupsafe import escape
 from ast import literal_eval
 import sqlite3
 import json
@@ -124,7 +125,7 @@ def admin_page(page):
 
                                valid_data = {k: type_note[k].__call__(aggrigate_data[k]) for k in aggrigate_data if k in type_note}
 
-                               data_list = ', '.join([f"{k} = '{v}'" if type(v) == str else f"{k} = {v}" for (k,v) in valid_data.items()])
+                               data_list = ', '.join([f"{k} = '{escape(v)}'" if type(v) == str else f"{k} = {v}" for (k,v) in valid_data.items()])
                                query = f"""
                                        UPDATE state SET
                                        {data_list}
index 64a1d6bd4a3c52b8c9bc0d05b9c1f690495568f1..00b3d6d654a9641e944e018e1c187afc46133872 100644 (file)
@@ -4,12 +4,6 @@
                <meta charset="utf-8">
                <title>XMDV</title>
                <style>
-.split {
-       display: inline-block;
-       width: calc(50% - 20px);
-       margin: 10px;
-       vertical-align: top;
-}
 /*
 clock styling
        - makes div square
@@ -19,6 +13,27 @@ clock styling
 /*
 media query to make sure the clock is always displayed well
 */
+.clockTimeLeft,.clockTimeRight,.clockTimeTop,.clockTimeBottom {
+       position: absolute;
+       display: block;
+       width: 60px;
+
+}
+#nextLabel, #startLabel {
+       position: absolute;
+       width: 50%;
+       height: 50%;
+       margin: 0;
+       transform: translateX(-50%);
+       top: 50%;
+       left: 50%;
+       text-align: center;
+       line-height: 50%;
+}
+#startLabel {
+       transform: translate(-50%, -2em);
+}
+
 @media (orientation: portrait) {
        :root {
                font-size: 2em;
@@ -33,6 +48,7 @@ media query to make sure the clock is always displayed well
        .clock {
                position: relative;
                width: 100%;
+               margin: 10px 60px 10px 60px;
                aspect-ratio: 1;
        }
        .clockButton {
@@ -44,11 +60,29 @@ media query to make sure the clock is always displayed well
        {% for p in positions %}
                .angle{{p.i}} {top: calc({{p.y}}% - 1em); left: calc({{p.x}}% - 1em);}
        {% endfor %}
+
+       .clockTimeLeft {
+               text-align: left;
+               transform: translateX(2em);
+       }
+       .clockTimeRight {
+               text-align: right;
+               transform: translateX(-60px);
+       }
+       .clockTimeTop {
+               text-align: center;
+               transform: translate(calc(-30px + 1em), -2em);
+       }
+       .clockTimeBottom {
+               text-align: center;
+               transform: translate(calc(-30px + 1em), 2em);
+       }
 }
 @media (orientation: landscape) {
        .clock {
                position: relative;
                height: 70vh;
+               margin: 10px 60px 10px 60px;
                aspect-ratio: 1;
        }
        .clockButton {
@@ -60,27 +94,63 @@ media query to make sure the clock is always displayed well
        {% for p in positions %}
                .angle{{p.i}} {top: calc({{p.y}}% - 0.75em); left: calc({{p.x}}% - 0.75em);}
        {% endfor %}
+
+       .clockTimeLeft {
+               text-align: left;
+               transform: translateX(1.5em);
+       }
+       .clockTimeRight {
+               text-align: right;
+               transform: translateX(-60px);
+       }
+       .clockTimeTop {
+               text-align: center;
+               transform: translate(calc(-30px + 0.75em), -1.5em);
+       }
+       .clockTimeBottom {
+               text-align: center;
+               transform: translate(calc(-30px + 0.75em), 1.5em);
+       }
 }
 
                </style>
        </head>
-       <body>
+       <body onload="update();mainTimer({{data.current_position}});">
                <a href="/admin">.. Back to admin pannel</a>
+               <form action="/admin/clock" method="POST">
+                       <input type="checkbox" value="0" name="end_timer_main" checked="checked" style="display: none">
+                       <input type="submit" name="update" value="Manual time reset">
+               </form>
+
                <form action="/admin/clock" method="POST">
                <fieldset>
                        <legend>Doomsday clock <em>(Incr. {{positions[1].i}} deg)</em></legend>
                        <div class=clock>
                                <svg class='clockFace' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'><circle r='45' cx='50' cy='50' fill='none' stroke='#a0a0a0' stroke-width='0.15px'/></svg>
 
+                               <input type="checkbox" value="0" name="end_timer_main" id="checkbox" style="display: none">
                                {% for p in positions %}
+
+                                       {% set extra = "" %}
                                        {% if p.i == data.current_position %}
-                                               <input type='radio' class='clockButton angle{{p.i}}' value='{{p.i}}' name='current_position' checked='checked' style='outline: 2px solid red;'>
+                                               {% set next_index = loop.index %}
+                                               {% set extra = "checked='checked' style='outline: 2px solid red;'"|safe %}
+                                       {% endif %}
+                                       <input type='radio' class='clockButton angle{{p.i}}' value='{{p.i}}' name='current_position' onclick='mainTimer({{p.i}});' {{extra}}>
+                                       {% if loop.first %}
+                                               <span class='clockTimeTop angle{{p.i}}' id="{{loop.index0}}">T+00:00</span>
+                                       {% elif p.i == 180 %}
+                                               <span class='clockTimeBottom angle{{p.i}}' id="{{loop.index0}}">T+00:00</span>
+                                       {% elif p.i < 180 %}
+                                               <span class='clockTimeLeft angle{{p.i}}' id="{{loop.index0}}">T+00:00</span>
                                        {% else %}
-                                               <input type='radio' class='clockButton angle{{p.i}}' value='{{p.i}}' name='current_position'>
+                                               <span class='clockTimeRight angle{{p.i}}' id="{{loop.index0}}">T+00:00</span>
                                        {% endif %}
                                {% endfor %}
-
+                               <h3 id="startLabel">TX Start @ <span id="start">00:00</span></h3>
+                               <h2 id="nextLabel">Next tick in <span id="next">T+00:00</span></h2>
                        </div>
+                       <em>Time will reset automatically on clock reset</em>
                        </fieldset>
                        <fieldset>
                                <legend>Movement</legend>
@@ -96,5 +166,78 @@ media query to make sure the clock is always displayed well
                        </fieldset>
                        <input type="submit" name="update" value="Update">
                </form>
+
+               <script>
+
+const timeTotal = 3600;
+
+function mainTimer (value) {
+       const checkbox = document.getElementById("checkbox");
+       if (value == 0) {checkbox.checked = true;}
+       else {checkbox.checked = false;}
+}
+
+function update() {
+       fetch("/api", {cache: "no-store"})
+               .then(data => data.json())
+               .then(data => {
+                       for (let t = 0; t <= {{positions|length}}; t++) {
+                               const timer = document.getElementById(t);
+                               const incrementTime = Math.round(timeTotal / {{positions|length}});
+
+                               let current = Math.round((Date.now() + data['timer_offset']) / 1000);
+                               var time = (data["end_timer_main"] - current) + (t * incrementTime);
+
+                               let negate = "";
+                               if (time > 0) {
+                                       var minutes = Math.floor(time / 60);
+                                       var seconds = (time - (minutes * 60));
+                               } else {
+                                       var minutes = Math.ceil(time / 60);
+                                       var seconds = -(time - (minutes * 60));
+                                       negate = "-";
+                               }
+                               if (minutes < 0) {seconds = 60 - seconds;} // reverse tick if in the past
+
+                               var minutesString = negate + minutes.toString().padStart(2, "0");
+                               var secondsString = seconds.toString().padStart(2, "0");
+
+                               timer.innerHTML = `T-${minutesString}:${secondsString}`.replace("--","+");
+                               if (minutes < 1) {
+                                       if (time <= 0) {timer.style.color = "red";}
+                                       else if (seconds % 2 == 0) {timer.style.color = "green";}
+                                       else {timer.style.color = "orange";}
+                               } else {
+                                       timer.style.color = "green";
+                               }
+
+                               if (t ==
+                                       {% for p in positions %}
+                                               {% if p.i == data.current_position %}
+                                                       {{loop.index}}
+                                               {% endif %}
+                                       {% endfor %}
+                                                       ) {
+                                       document.getElementById("next").innerHTML = `T-${minutesString}:${secondsString}`.replace("--","+");
+
+                                       const nextLabel = document.getElementById("nextLabel");
+                                       if (minutes < 1) {
+                                               if (time <= 0) {nextLabel.style.color = "red";}
+                                               else if (seconds % 2 == 0) {nextLabel.style.color = "green";}
+                                               else {nextLabel.style.color = "orange";}
+                                       } else {
+                                               nextLabel.style.color = "green";
+                                       }
+
+                                       var date = new Date(data["end_timer_main"] * 1000);
+                                       document.getElementById("start").innerHTML = `${date.getHours()}:${date.getMinutes()}`;
+                               }
+                       }
+               });
+}
+
+setInterval(update, 1000)
+
+               </script>
        </body>
 </html>
index 0515521e9569eeaf71ee5fce9d4a08056c7c2a16..c4b7d4e15937ba7d8edb2363dd1f54d13be5ee1b 100644 (file)
                                {% endif %}
                        </fieldset>
 
-                       <fieldset>
-                               <legend>Note</legend>
-                               <textarea name='note' rows='10' style='width: 100%;'>{{data.note}}</textarea>
-                       </fieldset>
                        <input type="submit" name="update" value="Update">
                </form>
        </body>
index 0a50f07b7f4fe82f5d75a01133d8a7094efc807f..25218a7e12c40f6a4601a5c93efb44ecfb60c405 100644 (file)
                                {% endfor %}
                        </fieldset>
 
+                       <fieldset>
+                               <legend>Note</legend>
+                               <textarea name='note' rows='10' style='width: 100%;'>{{data.note|safe}}</textarea>
+                       </fieldset>
+
                        <input type="submit" name="update" value="Update">
                </form>
        </body>