From d9af103b9a8aed86d6ac834f1240edfb2173ffa0 Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Sat, 8 Mar 2025 02:17:52 +0900 Subject: Restructure js and css into single block modules Each block is defined by: * html: front-end elements (modify: templates/index.html) (for now) * css: front-end design (modify: static/style.css) * js: front-end code (new file: static/block_name.js) * python: back-end code (new file: ./block_name.py) (will move later from the root to an "app" directory (python package) --- .gitignore | 1 + block_weather.py | 2 +- static/block_time.js | 49 +++++++++++++++++++++++++++++ static/block_weather.js | 14 +++++++++ static/script.js | 78 +++++++++++++++++++---------------------------- static/style.css | 52 +++++++++++++++++++++++++++++-- static/timeVisualizer.css | 44 -------------------------- static/timeVisualizer.js | 35 --------------------- templates/index.html | 1 - 9 files changed, 146 insertions(+), 130 deletions(-) create mode 100644 static/block_time.js create mode 100644 static/block_weather.js delete mode 100644 static/timeVisualizer.css delete mode 100644 static/timeVisualizer.js diff --git a/.gitignore b/.gitignore index 0359188..a58cf92 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .venv/ __pycache__/ +tmp/ config.py diff --git a/block_weather.py b/block_weather.py index 4443de3..84c0092 100644 --- a/block_weather.py +++ b/block_weather.py @@ -33,7 +33,7 @@ def _format_current_weather(data: dict) -> str: s = f"""{data['name']}, {data['sys']['country']} ({ts[0]}) {data['weather'][0]['description']} {data['main']['temp']}°C (feels like {data['main']['feels_like']}°C), humidity: {data['main']['humidity']}%, pressure: {data['main']['grnd_level']} hPa -visibility: {data['visibility']/1000:.1f}km +visibility: {data.get('visibility', 0)/1000:.1f}km wind: {data['wind']['speed']}m/s from {data['wind']['deg']}°N clouds: {data['clouds']['all']}% sunrise & sunset: {ts[1].strftime('%H:%M')}, {ts[2].strftime('%H:%M')}""" diff --git a/static/block_time.js b/static/block_time.js new file mode 100644 index 0000000..d6510ae --- /dev/null +++ b/static/block_time.js @@ -0,0 +1,49 @@ +function init() { + initTimeVisualizer('timeVisualizer'); +} + +export function updateTime() { + fetch("/time") + .then(res => res.json()) + .then(data => { + document.getElementById("weatherSummary").innerText = data.time; + }); +} + +function initTimeVisualizer(containerId) { + const grid = document.createElement('div'); + grid.className = 'grid'; + document.getElementById(containerId).appendChild(grid); + + function updateTime() { + grid.innerHTML = ''; + const now = new Date(); + const hours = now.getHours(); + const minutes = now.getMinutes(); + + for (let i = 0; i < 24; i++) { + const cell = document.createElement('div'); + cell.className = 'cell'; + + if (i >= 20 || i < 4) cell.classList.add('sleep'); + if (i < hours) cell.classList.add('past'); + + if (i === hours) { + cell.classList.add('current'); + const fillPercentage = (minutes / 60) * 100; + cell.style.setProperty('--fill', `${fillPercentage}%`); + const line = document.createElement('div'); + line.className = 'timeline'; + line.style.left = `calc(${fillPercentage}% - 1px)`; + cell.appendChild(line); + } + + grid.appendChild(cell); + } + } + + updateTime(); + setInterval(updateTime, 60000); // 1min +} + +init() diff --git a/static/block_weather.js b/static/block_weather.js new file mode 100644 index 0000000..4ae6d2d --- /dev/null +++ b/static/block_weather.js @@ -0,0 +1,14 @@ +export function updateWeather() { + const city = document.getElementById("city").value; + fetch(`/weather?city=${encodeURIComponent(city)}`) + .then(res => res.json()) + .then(data => { + if (!data) { + document.getElementById("weather-summary").innerText = `Error, "${city}" city not found`; + return + } + document.getElementById("weather-summary").innerText = data.summary; + document.getElementById("weather-icon").src = data.icon_url; + }); +} + diff --git a/static/script.js b/static/script.js index f81f9ef..efd6836 100644 --- a/static/script.js +++ b/static/script.js @@ -1,37 +1,35 @@ -import { initTimeVisualizer } from './timeVisualizer.js'; +import { updateTime } from './block_time.js'; +import { updateWeather } from './block_weather.js'; -let polling = true -const blocks = { - time: { interval: 30 * 1000, lastUpdate: 0, update: updateTime }, // 30s - weather: { interval: 30 * 60000, lastUpdate: 0, update: updateWeather } // 30min - // Add more: { interval: X, lastUpdate: 0, update: updateFunction } -}; -let lastPoll = 0; +const config = { + polling: true +} + +function init() { + const blocks = { + time: { interval: 30 * 1000, lastUpdate: 0, update: updateTime }, // 30s + weather: { interval: 30 * 60000, lastUpdate: 0, update: updateWeather } // 30min + // Add more: { interval: X, lastUpdate: 0, update: updateFunction } + }; + + initHeaderControls(blocks) -function updateTime() { - fetch("/time") - .then(res => res.json()) - .then(data => { - document.getElementById("weatherSummary").innerText = data.time; - }); + // Initial load + // Poll every 500ms to check intervals (fast enough for 1s updates, light on CPU) + // maybe the 1s updates should be special case, but for now let's keep it simple + reloadAll(blocks); + setInterval(() => pollUpdates(blocks), 500); } -function updateWeather() { - const city = document.getElementById("city").value; - fetch(`/weather?city=${encodeURIComponent(city)}`) - .then(res => res.json()) - .then(data => { - if (!data) { - document.getElementById("weather-summary").innerText = `Error, "${city}" city not found`; - return - } - document.getElementById("weather-summary").innerText = data.summary; - document.getElementById("weather-icon").src = data.icon_url; - }); +function reloadAll(blocks) { + Object.keys(blocks).forEach(key => { + blocks[key].update(); + blocks[key].lastUpdate = Date.now(); + }); } -function pollUpdates() { - if (!polling) return; +function pollUpdates(blocks) { + if (!config.polling) return; const now = Date.now(); Object.keys(blocks).forEach(key => { const block = blocks[key]; @@ -40,27 +38,13 @@ function pollUpdates() { block.lastUpdate = now; } }); - lastPoll = now; } -function reloadAll() { - Object.keys(blocks).forEach(key => { - blocks[key].update(); - blocks[key].lastUpdate = Date.now(); +function initHeaderControls(blocks) { + document.getElementById("reload").addEventListener("click", () => reloadAll(blocks)); + document.getElementById("pause").addEventListener("change", (e) => { + config.polling = e.target.checked; }); } -// Header controls -document.getElementById("reload").addEventListener("click", reloadAll); -document.getElementById("pause").addEventListener("change", (e) => { - polling = e.target.checked; -}); - -// Initial load -reloadAll(); -// Poll every 500ms to check intervals (fast enough for 1s updates, light on CPU) -// maybe the 1s updates should be special case, but for now let's keep it simple -setInterval(pollUpdates, 500); - -// timeVisualizer -initTimeVisualizer('timeVisualizer'); +init() diff --git a/static/style.css b/static/style.css index 4b3696e..a186f24 100644 --- a/static/style.css +++ b/static/style.css @@ -1,3 +1,4 @@ +/* MASU */ body { margin: 0; padding: 0; @@ -46,7 +47,54 @@ header button, header label { } } -/* Block specific stuff */ -.block #time { +/* block_time */ +#time .block { justify-content: center; } + +#timeVisualizer .grid { + display: grid; + grid-template-columns: repeat(8, 42px); + grid-template-rows: repeat(3, 42px); + gap: 2px; + background: #f0f0f0; + padding: 5px; + width: fit-content; + margin: 0 auto; +} + +#timeVisualizer .cell { + width: 42px; + height: 42px; + background: #ffffff; + position: relative; + border: 1px solid #ddd; +} + +#timeVisualizer .sleep { + background: #e6f3ff; +} + +#timeVisualizer .past { + background: #cccccc; +} + +#timeVisualizer .current::after { + content: ''; + position: absolute; + left: 0; + top: 0; + height: 100%; + width: var(--fill); + background: #cccccc; +} + +#timeVisualizer .timeline { + position: absolute; + width: 2px; + height: 100%; + background: #000000; + z-index: 1; +} + +/* block_weather */ diff --git a/static/timeVisualizer.css b/static/timeVisualizer.css deleted file mode 100644 index 600ec4b..0000000 --- a/static/timeVisualizer.css +++ /dev/null @@ -1,44 +0,0 @@ -#timeVisualizer .grid { - display: grid; - grid-template-columns: repeat(8, 42px); - grid-template-rows: repeat(3, 42px); - gap: 2px; - background: #f0f0f0; - padding: 5px; - width: fit-content; - margin: 0 auto; -} - -#timeVisualizer .cell { - width: 42px; - height: 42px; - background: #ffffff; - position: relative; - border: 1px solid #ddd; -} - -#timeVisualizer .sleep { - background: #e6f3ff; -} - -#timeVisualizer .past { - background: #cccccc; -} - -#timeVisualizer .current::after { - content: ''; - position: absolute; - left: 0; - top: 0; - height: 100%; - width: var(--fill); - background: #cccccc; -} - -#timeVisualizer .timeline { - position: absolute; - width: 2px; - height: 100%; - background: #000000; - z-index: 1; -} diff --git a/static/timeVisualizer.js b/static/timeVisualizer.js deleted file mode 100644 index 2dfb59e..0000000 --- a/static/timeVisualizer.js +++ /dev/null @@ -1,35 +0,0 @@ -export function initTimeVisualizer(containerId) { - const grid = document.createElement('div'); - grid.className = 'grid'; - document.getElementById(containerId).appendChild(grid); - - function updateTime() { - grid.innerHTML = ''; - const now = new Date(); - const hours = now.getHours(); - const minutes = now.getMinutes(); - - for (let i = 0; i < 24; i++) { - const cell = document.createElement('div'); - cell.className = 'cell'; - - if (i >= 20 || i < 4) cell.classList.add('sleep'); - if (i < hours) cell.classList.add('past'); - - if (i === hours) { - cell.classList.add('current'); - const fillPercentage = (minutes / 60) * 100; - cell.style.setProperty('--fill', `${fillPercentage}%`); - const line = document.createElement('div'); - line.className = 'timeline'; - line.style.left = `calc(${fillPercentage}% - 1px)`; - cell.appendChild(line); - } - - grid.appendChild(cell); - } - } - - updateTime(); - setInterval(updateTime, 60000); -} diff --git a/templates/index.html b/templates/index.html index be23282..332b78b 100644 --- a/templates/index.html +++ b/templates/index.html @@ -3,7 +3,6 @@ MASU -
-- cgit v1.2.3