From 8f244455acf84805bc05de241e23cfc8153139ef Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 6 Jul 2026 11:52:55 +0300 Subject: [PATCH] refactor(static): refactor static module --- static/src/{ => app/common}/language.ts | 22 ++++++----- static/src/{ => app/common}/theme.ts | 24 ++++++------ static/src/app/common/tooltips.ts | 6 +++ .../components/app-link.ts} | 0 static/src/{schedule => app}/schedule.ts | 1 - static/src/{weather => app}/weather.ts | 0 static/src/index.ts | 17 +++----- static/src/lib/flag-icons.scss | 7 ---- static/src/main.scss | 39 ++----------------- static/src/styles/app.scss | 32 +++++++++++++++ static/src/{ => styles}/mobile.scss | 2 +- static/src/{weather => styles}/weather.scss | 0 static/src/{ => styles}/widget.scss | 0 static/webpack.config.ts | 7 ++-- 14 files changed, 78 insertions(+), 79 deletions(-) rename static/src/{ => app/common}/language.ts (67%) rename static/src/{ => app/common}/theme.ts (71%) create mode 100644 static/src/app/common/tooltips.ts rename static/src/{components.ts => app/components/app-link.ts} (100%) rename static/src/{schedule => app}/schedule.ts (99%) rename static/src/{weather => app}/weather.ts (100%) create mode 100644 static/src/styles/app.scss rename static/src/{ => styles}/mobile.scss (97%) rename static/src/{weather => styles}/weather.scss (100%) rename static/src/{ => styles}/widget.scss (100%) diff --git a/static/src/language.ts b/static/src/app/common/language.ts similarity index 67% rename from static/src/language.ts rename to static/src/app/common/language.ts index e531861..e5d0f5d 100644 --- a/static/src/language.ts +++ b/static/src/app/common/language.ts @@ -19,7 +19,7 @@ setLanguage(getPreferredLanguage()); const showActiveLanguage = (language: string, focus = false) => { - const languageSwitcher = document.querySelector("#bd-language"); + const languageSwitcher = document.querySelector("#bd-language"); if (!languageSwitcher) { return; @@ -27,24 +27,26 @@ const languageSwitcherText = document.querySelector("#bd-language-text"); const activeLanguageIcon = document.querySelector(".language-icon-active"); - const btnToActive = document.querySelector(`[data-bs-language-value="${language}"]`); - const activeLanguageIconClass = btnToActive.querySelector(".fi").className.match(/fi-[\w-]+/)[0]; + const btnToActive = document.querySelector(`[data-bs-language-value="${language}"]`); + const activeLanguageIconClass = (btnToActive?.querySelector(".fi")?.className.match(/fi-[\w-]+/) || [])[0] || ""; document.querySelectorAll("[data-bs-language-value]").forEach((element) => { element.classList.remove("active"); element.setAttribute("aria-pressed", "false"); }); - btnToActive.classList.add("active"); - btnToActive.setAttribute("aria-pressed", "true"); - const classesToRemove = Array.from(activeLanguageIcon.classList).filter((className) => className.startsWith("fi-")); - activeLanguageIcon.classList.remove(...classesToRemove); - activeLanguageIcon.classList.add(activeLanguageIconClass); - const languageSwitcherLabel = `${languageSwitcherText.textContent} (${btnToActive.dataset.bsLanguageValue})`; + btnToActive?.classList.add("active"); + btnToActive?.setAttribute("aria-pressed", "true"); + const classesToRemove = Array.from(activeLanguageIcon?.classList || []).filter((className) => + className.startsWith("fi-"), + ); + activeLanguageIcon?.classList.remove(...classesToRemove); + activeLanguageIcon?.classList.add(activeLanguageIconClass); + const languageSwitcherLabel = `${languageSwitcherText?.textContent} (${btnToActive?.dataset.bsLanguageValue})`; languageSwitcher.setAttribute("aria-label", languageSwitcherLabel); if (focus) { - languageSwitcher.focus(); + languageSwitcher?.focus(); } }; diff --git a/static/src/theme.ts b/static/src/app/common/theme.ts similarity index 71% rename from static/src/theme.ts rename to static/src/app/common/theme.ts index ea5da8a..e387d73 100644 --- a/static/src/theme.ts +++ b/static/src/app/common/theme.ts @@ -25,7 +25,7 @@ setTheme(getPreferredTheme()); const showActiveTheme = (theme: string, focus = false) => { - const themeSwitcher = document.querySelector("#bd-theme"); + const themeSwitcher = document.querySelector("#bd-theme"); if (!themeSwitcher) { return; @@ -33,24 +33,26 @@ const themeSwitcherText = document.querySelector("#bd-theme-text"); const activeThemeIcon = document.querySelector(".theme-icon-active"); - const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`); - const activeThemeIconClass = btnToActive.querySelector(".bi").className.match(/bi-[\w-]+/)[0]; + const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`); + const activeThemeIconClass = (btnToActive?.querySelector(".bi")?.className.match(/bi-[\w-]+/) || [])[0] || ""; document.querySelectorAll("[data-bs-theme-value]").forEach((element) => { element.classList.remove("active"); element.setAttribute("aria-pressed", "false"); }); - btnToActive.classList.add("active"); - btnToActive.setAttribute("aria-pressed", "true"); - const classesToRemove = Array.from(activeThemeIcon.classList).filter((className) => className.startsWith("bi-")); - activeThemeIcon.classList.remove(...classesToRemove); - activeThemeIcon.classList.add(activeThemeIconClass); - const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`; + btnToActive?.classList.add("active"); + btnToActive?.setAttribute("aria-pressed", "true"); + const classesToRemove = Array.from(activeThemeIcon?.classList || []).filter((className) => + className.startsWith("bi-"), + ); + activeThemeIcon?.classList.remove(...classesToRemove); + activeThemeIcon?.classList.add(activeThemeIconClass); + const themeSwitcherLabel = `${themeSwitcherText?.textContent} (${btnToActive?.dataset.bsThemeValue})`; themeSwitcher.setAttribute("aria-label", themeSwitcherLabel); if (focus) { - themeSwitcher.focus(); + themeSwitcher?.focus(); } }; @@ -66,7 +68,7 @@ document.querySelectorAll("[data-bs-theme-value]").forEach((toggle) => { toggle.addEventListener("click", () => { - const theme = toggle.getAttribute("data-bs-theme-value") || ''; + const theme = toggle.getAttribute("data-bs-theme-value") || ""; setStoredTheme(theme); setTheme(theme); showActiveTheme(theme, true); diff --git a/static/src/app/common/tooltips.ts b/static/src/app/common/tooltips.ts new file mode 100644 index 0000000..5322c8d --- /dev/null +++ b/static/src/app/common/tooltips.ts @@ -0,0 +1,6 @@ +import { Tooltip } from "bootstrap"; + +document.addEventListener("DOMContentLoaded", (event) => { + const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); + const tooltipList = [...tooltipTriggerList].map((tooltipTriggerEl) => new Tooltip(tooltipTriggerEl)); +}); diff --git a/static/src/components.ts b/static/src/app/components/app-link.ts similarity index 100% rename from static/src/components.ts rename to static/src/app/components/app-link.ts diff --git a/static/src/schedule/schedule.ts b/static/src/app/schedule.ts similarity index 99% rename from static/src/schedule/schedule.ts rename to static/src/app/schedule.ts index dfbb233..5db8d8f 100644 --- a/static/src/schedule/schedule.ts +++ b/static/src/app/schedule.ts @@ -108,4 +108,3 @@ declare global { window.scheduleChannelStorage = new ScheduleChannelStorage(); window.scheduleChannelManager = new ScheduleChannelManager(); -console.log("ok"); diff --git a/static/src/weather/weather.ts b/static/src/app/weather.ts similarity index 100% rename from static/src/weather/weather.ts rename to static/src/app/weather.ts diff --git a/static/src/index.ts b/static/src/index.ts index 94fa0cb..d3374d8 100644 --- a/static/src/index.ts +++ b/static/src/index.ts @@ -1,11 +1,6 @@ -import * as bootstrap from "bootstrap"; -import "./components"; -import "./language"; -import "./theme"; -import "./weather/weather"; -import "./schedule/schedule"; - -document.addEventListener("DOMContentLoaded", (event) => { - const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); - const tooltipList = [...tooltipTriggerList].map((tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl)); -}); +import "./app/common/language"; +import "./app/common/theme"; +import "./app/common/tooltips"; +import "./app/components/app-link"; +import "./app/schedule"; +import "./app/weather"; diff --git a/static/src/lib/flag-icons.scss b/static/src/lib/flag-icons.scss index b48ed89..1877358 100644 --- a/static/src/lib/flag-icons.scss +++ b/static/src/lib/flag-icons.scss @@ -1,12 +1,5 @@ @use "flag-icons/sass/flag-icons" with ( $flag-icons-path: "flag-icons/flags", - $flag-icons-included-countries: ( - "gb", - "ru", - "by", - "ua", - "kz", - ) ); .fir { diff --git a/static/src/main.scss b/static/src/main.scss index 5b3a9e7..101d191 100644 --- a/static/src/main.scss +++ b/static/src/main.scss @@ -3,38 +3,7 @@ @import "./lib/bootstrap-icons"; @import "./lib/weather-icons"; -@import "./widget.scss"; -@import "./weather/weather.scss"; - -.table.table-compact { - td { - padding: 0.1rem 0.4rem; - } -} - -.icon-header { - @include font-size($h4-font-size); -} - -.app-header { - display: flex; - flex-direction: row; - - > .link-list { - display: flex; - flex-direction: row; - gap: 1rem; - - app-link { - display: flex; - align-items: center; - - &:not(:last-child)::after { - margin-left: 1rem; - content: "|"; - } - } - } -} - -@import "./mobile"; +@import "./styles/weather.scss"; +@import "./styles/app"; +@import "./styles/widget.scss"; +@import "./styles/mobile"; diff --git a/static/src/styles/app.scss b/static/src/styles/app.scss new file mode 100644 index 0000000..68e8928 --- /dev/null +++ b/static/src/styles/app.scss @@ -0,0 +1,32 @@ +@import "../lib/bootstrap"; + +.table.table-compact { + td { + padding: 0.1rem 0.4rem; + } +} + +.icon-header { + @include font-size($h4-font-size); +} + +.app-header { + display: flex; + flex-direction: row; + + > .link-list { + display: flex; + flex-direction: row; + gap: 1rem; + + app-link { + display: flex; + align-items: center; + + &:not(:last-child)::after { + margin-left: 1rem; + content: "|"; + } + } + } +} diff --git a/static/src/mobile.scss b/static/src/styles/mobile.scss similarity index 97% rename from static/src/mobile.scss rename to static/src/styles/mobile.scss index ca265f5..55a0811 100644 --- a/static/src/mobile.scss +++ b/static/src/styles/mobile.scss @@ -1,4 +1,4 @@ -@import "./lib/bootstrap"; +@import "../lib/bootstrap"; $default-space: 2; diff --git a/static/src/weather/weather.scss b/static/src/styles/weather.scss similarity index 100% rename from static/src/weather/weather.scss rename to static/src/styles/weather.scss diff --git a/static/src/widget.scss b/static/src/styles/widget.scss similarity index 100% rename from static/src/widget.scss rename to static/src/styles/widget.scss diff --git a/static/webpack.config.ts b/static/webpack.config.ts index b981e99..f0099d2 100644 --- a/static/webpack.config.ts +++ b/static/webpack.config.ts @@ -17,9 +17,6 @@ const config: webpack.Configuration = { test: /\.tsx?$/, use: { loader: "ts-loader", - options: { - transpileOnly: true, // TODO: fix errors - }, }, exclude: /node_modules/, }, @@ -63,6 +60,10 @@ const config: webpack.Configuration = { from: "./node_modules/flag-icons/flags/1x1/*.svg", to: "flag-icons/flags/1x1/[name][ext]", }, + { + from: "./node_modules/flag-icons/flags/4x3/*.svg", + to: "flag-icons/flags/4x3/[name][ext]", + }, ], }), ],