Compare commits
No commits in common. "854d6ccc1500cece4d28021df07e2b8e720a04ca" and "fcf17224dec66ccbe7df7091ab9abd8ea6090932" have entirely different histories.
854d6ccc15
...
fcf17224de
12
README.md
|
|
@ -29,18 +29,6 @@ This fork is focused on:
|
||||||
* global radar and global regional observations on the newer map stack
|
* global radar and global regional observations on the newer map stack
|
||||||
* pragmatic feature additions instead of broad platform expansion
|
* pragmatic feature additions instead of broad platform expansion
|
||||||
|
|
||||||
## Themes
|
|
||||||
|
|
||||||
`ws4kp-linhanced` supports live asset theme swapping from the main page. Themes are discovered automatically from the `themes/` directory and can be changed from the `Theme` selector under the `More information` link without reloading the page.
|
|
||||||
|
|
||||||
Current themes include:
|
|
||||||
|
|
||||||
* `Default`: the standard WeatherStar 4000+ asset set.
|
|
||||||
* `oceanview`: based on the Oceanview Weather Channel presentation from the Eventide Media Center analog horror series.
|
|
||||||
* `slackware`: based on the Oceanview theme, but with the Slackware Linux badge/logo treatment.
|
|
||||||
|
|
||||||
At the moment, theming covers the major background assets and the corner logo. Additional theme asset overrides can be added by placing matching files in `themes/<theme-name>/`.
|
|
||||||
|
|
||||||
## What's your motivation
|
## What's your motivation
|
||||||
|
|
||||||
Nostalgia, Linux affinity, and an interest in keeping a practical retro weather display alive without turning it into a sprawling platform.
|
Nostalgia, Linux affinity, and an interest in keeping a practical retro weather display alive without turning it into a sprawling platform.
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import dartSass from 'sass';
|
||||||
import gulpSass from 'gulp-sass';
|
import gulpSass from 'gulp-sass';
|
||||||
import sourceMaps from 'gulp-sourcemaps';
|
import sourceMaps from 'gulp-sourcemaps';
|
||||||
import OVERRIDES from '../src/overrides.mjs';
|
import OVERRIDES from '../src/overrides.mjs';
|
||||||
import { discoverThemes } from '../src/theme-discovery.mjs';
|
|
||||||
|
|
||||||
// get cloudfront
|
// get cloudfront
|
||||||
import reader from '../src/playlist-reader.mjs';
|
import reader from '../src/playlist-reader.mjs';
|
||||||
|
|
@ -112,7 +111,6 @@ const htmlSources = [
|
||||||
];
|
];
|
||||||
const packageJson = await readFile('package.json');
|
const packageJson = await readFile('package.json');
|
||||||
let { version } = JSON.parse(packageJson);
|
let { version } = JSON.parse(packageJson);
|
||||||
const { themes, themeAssets } = await discoverThemes();
|
|
||||||
const previewVersion = async () => {
|
const previewVersion = async () => {
|
||||||
// generate a relatively unique timestamp for cache invalidation of the preview site
|
// generate a relatively unique timestamp for cache invalidation of the preview site
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
@ -125,8 +123,6 @@ const compressHtml = async () => src(htmlSources)
|
||||||
production: version,
|
production: version,
|
||||||
serverAvailable: false,
|
serverAvailable: false,
|
||||||
version,
|
version,
|
||||||
themes,
|
|
||||||
themeAssets,
|
|
||||||
OVERRIDES,
|
OVERRIDES,
|
||||||
query: {},
|
query: {},
|
||||||
}))
|
}))
|
||||||
|
|
@ -142,9 +138,6 @@ const otherFiles = [
|
||||||
const copyOtherFiles = () => src(otherFiles, { base: 'server/', encoding: false })
|
const copyOtherFiles = () => src(otherFiles, { base: 'server/', encoding: false })
|
||||||
.pipe(dest('./dist'));
|
.pipe(dest('./dist'));
|
||||||
|
|
||||||
const copyThemes = () => src('themes/**', { base: '.', encoding: false })
|
|
||||||
.pipe(dest('./dist'));
|
|
||||||
|
|
||||||
// Copy JSON data files for static hosting
|
// Copy JSON data files for static hosting
|
||||||
const copyDataFiles = () => src([
|
const copyDataFiles = () => src([
|
||||||
'datagenerators/output/travelcities.json',
|
'datagenerators/output/travelcities.json',
|
||||||
|
|
@ -227,7 +220,7 @@ const logVersion = async () => {
|
||||||
log(`Version Published: ${version}`);
|
log(`Version Published: ${version}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildDist = series(clean, parallel(buildJs, compressJsVendor, buildCss, compressHtml, copyOtherFiles, copyThemes, copyDataFiles, copyImageSources, buildPlaylist));
|
const buildDist = series(clean, parallel(buildJs, compressJsVendor, buildCss, compressHtml, copyOtherFiles, copyDataFiles, copyImageSources, buildPlaylist));
|
||||||
|
|
||||||
// upload_images could be in parallel with upload, but _images logs a lot and has little changes
|
// upload_images could be in parallel with upload, but _images logs a lot and has little changes
|
||||||
// by running upload last the majority of the changes will be at the bottom of the log for easy viewing
|
// by running upload last the majority of the changes will be at the bottom of the log for easy viewing
|
||||||
|
|
@ -238,7 +231,6 @@ export default publishFrontend;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
buildDist,
|
buildDist,
|
||||||
copyThemes,
|
|
||||||
invalidate,
|
invalidate,
|
||||||
stageFrontend,
|
stageFrontend,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import playlist from './src/playlist.mjs';
|
||||||
import OVERRIDES from './src/overrides.mjs';
|
import OVERRIDES from './src/overrides.mjs';
|
||||||
import cache from './proxy/cache.mjs';
|
import cache from './proxy/cache.mjs';
|
||||||
import devTools from './src/com.chrome.devtools.mjs';
|
import devTools from './src/com.chrome.devtools.mjs';
|
||||||
import { discoverThemes } from './src/theme-discovery.mjs';
|
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
|
|
@ -91,7 +90,6 @@ const travelCities = JSON.parse(await readFile('./datagenerators/output/travelci
|
||||||
const regionalCities = JSON.parse(await readFile('./datagenerators/output/regionalcities.json'));
|
const regionalCities = JSON.parse(await readFile('./datagenerators/output/regionalcities.json'));
|
||||||
const stationInfo = JSON.parse(await readFile('./datagenerators/output/stations.json'));
|
const stationInfo = JSON.parse(await readFile('./datagenerators/output/stations.json'));
|
||||||
const radarCities = JSON.parse(await readFile('./datagenerators/output/radarcities.json'));
|
const radarCities = JSON.parse(await readFile('./datagenerators/output/radarcities.json'));
|
||||||
const { themes, themeAssets } = await discoverThemes();
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = process.env.WS4KP_PORT ?? 8080;
|
const port = process.env.WS4KP_PORT ?? 8080;
|
||||||
|
|
@ -136,8 +134,6 @@ const renderIndex = (req, res, production = false) => {
|
||||||
production,
|
production,
|
||||||
serverAvailable: !process.env?.STATIC, // Disable caching proxy server in static mode
|
serverAvailable: !process.env?.STATIC, // Disable caching proxy server in static mode
|
||||||
version,
|
version,
|
||||||
themes,
|
|
||||||
themeAssets,
|
|
||||||
OVERRIDES,
|
OVERRIDES,
|
||||||
query: req.query,
|
query: req.query,
|
||||||
});
|
});
|
||||||
|
|
@ -270,7 +266,6 @@ if (!process.env?.STATIC) {
|
||||||
app.use('/rainviewer/', rainViewerProxy);
|
app.use('/rainviewer/', rainViewerProxy);
|
||||||
app.use('/arcgis-server/', arcGisServerProxy);
|
app.use('/arcgis-server/', arcGisServerProxy);
|
||||||
app.use('/arcgis-services/', arcGisServicesProxy);
|
app.use('/arcgis-services/', arcGisServicesProxy);
|
||||||
app.use('/themes', express.static('./themes', staticOptions));
|
|
||||||
|
|
||||||
// Playlist route is available in server mode (not in static mode)
|
// Playlist route is available in server mode (not in static mode)
|
||||||
app.get('/playlist.json', playlist);
|
app.get('/playlist.json', playlist);
|
||||||
|
|
@ -300,7 +295,6 @@ if (process.env?.DIST === '1') {
|
||||||
app.use('/scripts', express.static('./server/scripts', staticOptions));
|
app.use('/scripts', express.static('./server/scripts', staticOptions));
|
||||||
app.use('/geoip', geoip);
|
app.use('/geoip', geoip);
|
||||||
app.use('/music', express.static('./server/music', staticOptions));
|
app.use('/music', express.static('./server/music', staticOptions));
|
||||||
app.use('/themes', express.static('./dist/themes', staticOptions));
|
|
||||||
|
|
||||||
// render the EJS template in production mode (serve compressed files from dist directory)
|
// render the EJS template in production mode (serve compressed files from dist directory)
|
||||||
app.get('/', (req, res) => { renderIndex(req, res, true); });
|
app.get('/', (req, res) => { renderIndex(req, res, true); });
|
||||||
|
|
@ -311,7 +305,6 @@ if (process.env?.DIST === '1') {
|
||||||
app.get('/index.html', index);
|
app.get('/index.html', index);
|
||||||
app.use('/geoip', geoip);
|
app.use('/geoip', geoip);
|
||||||
app.use('/resources', express.static('./server/scripts/modules'));
|
app.use('/resources', express.static('./server/scripts/modules'));
|
||||||
app.use('/themes', express.static('./themes', staticOptions));
|
|
||||||
app.get('/', index);
|
app.get('/', index);
|
||||||
app.get('/.well-known/appspecific/com.chrome.devtools.json', devTools);
|
app.get('/.well-known/appspecific/com.chrome.devtools.json', devTools);
|
||||||
app.get('*name', express.static('./server', staticOptions));
|
app.get('*name', express.static('./server', staticOptions));
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 422 KiB |
BIN
server/images/backgrounds/1.png.old
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 420 KiB |
BIN
server/images/backgrounds/2.png.old
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 9.9 KiB |
BIN
server/images/logos/logo-corner.png.original
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
|
|
@ -6,7 +6,6 @@ import {
|
||||||
import { round2 } from './modules/utils/units.mjs';
|
import { round2 } from './modules/utils/units.mjs';
|
||||||
import { registerHiddenSetting } from './modules/share.mjs';
|
import { registerHiddenSetting } from './modules/share.mjs';
|
||||||
import settings from './modules/settings.mjs';
|
import settings from './modules/settings.mjs';
|
||||||
import './modules/utils/theme.mjs';
|
|
||||||
import AutoComplete from './modules/autocomplete.mjs';
|
import AutoComplete from './modules/autocomplete.mjs';
|
||||||
import { loadAllData } from './modules/utils/data-loader.mjs';
|
import { loadAllData } from './modules/utils/data-loader.mjs';
|
||||||
import { debugFlag } from './modules/utils/debug.mjs';
|
import { debugFlag } from './modules/utils/debug.mjs';
|
||||||
|
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
const THEME_STORAGE_KEY = 'settings-theme-select';
|
|
||||||
const DEFAULT_THEME = 'default';
|
|
||||||
const BUILTIN_ASSETS = {
|
|
||||||
background1: '../images/backgrounds/1.png',
|
|
||||||
background1Chart: '../images/backgrounds/1-chart.png',
|
|
||||||
background2: '../images/backgrounds/2.png',
|
|
||||||
background3: '../images/backgrounds/3.png',
|
|
||||||
background4: '../images/backgrounds/4.png',
|
|
||||||
background5: '../images/backgrounds/5.png',
|
|
||||||
logoCorner: 'images/logos/logo-corner.png',
|
|
||||||
};
|
|
||||||
|
|
||||||
const getThemeAssets = () => window.WS4KP_THEME_ASSETS ?? {};
|
|
||||||
const getAvailableThemes = () => window.WS4KP_THEMES ?? [DEFAULT_THEME];
|
|
||||||
|
|
||||||
const getStoredTheme = () => {
|
|
||||||
const storedTheme = localStorage.getItem(THEME_STORAGE_KEY) ?? DEFAULT_THEME;
|
|
||||||
return getAvailableThemes().includes(storedTheme) ? storedTheme : DEFAULT_THEME;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getThemeAssetUrl = (themeName, assetKey) => {
|
|
||||||
if (themeName === DEFAULT_THEME) {
|
|
||||||
return BUILTIN_ASSETS[assetKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
const themeAssetAvailability = getThemeAssets()[themeName] ?? {};
|
|
||||||
if (!themeAssetAvailability[assetKey]) {
|
|
||||||
return BUILTIN_ASSETS[assetKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (assetKey) {
|
|
||||||
case 'background1':
|
|
||||||
return `../themes/${themeName}/1.png`;
|
|
||||||
case 'background1Chart':
|
|
||||||
return `../themes/${themeName}/1-chart.png`;
|
|
||||||
case 'background2':
|
|
||||||
return `../themes/${themeName}/2.png`;
|
|
||||||
case 'background3':
|
|
||||||
return `../themes/${themeName}/3.png`;
|
|
||||||
case 'background4':
|
|
||||||
return `../themes/${themeName}/4.png`;
|
|
||||||
case 'background5':
|
|
||||||
return `../themes/${themeName}/5.png`;
|
|
||||||
case 'logoCorner':
|
|
||||||
return `themes/${themeName}/logo-corner.png`;
|
|
||||||
default:
|
|
||||||
return BUILTIN_ASSETS[assetKey];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const applyTheme = (themeName) => {
|
|
||||||
const selectedTheme = getAvailableThemes().includes(themeName) ? themeName : DEFAULT_THEME;
|
|
||||||
localStorage.setItem(THEME_STORAGE_KEY, selectedTheme);
|
|
||||||
|
|
||||||
document.documentElement.style.setProperty('--theme-background-1', `url('${getThemeAssetUrl(selectedTheme, 'background1')}')`);
|
|
||||||
document.documentElement.style.setProperty('--theme-background-1-chart', `url('${getThemeAssetUrl(selectedTheme, 'background1Chart')}')`);
|
|
||||||
document.documentElement.style.setProperty('--theme-background-2', `url('${getThemeAssetUrl(selectedTheme, 'background2')}')`);
|
|
||||||
document.documentElement.style.setProperty('--theme-background-3', `url('${getThemeAssetUrl(selectedTheme, 'background3')}')`);
|
|
||||||
document.documentElement.style.setProperty('--theme-background-4', `url('${getThemeAssetUrl(selectedTheme, 'background4')}')`);
|
|
||||||
document.documentElement.style.setProperty('--theme-background-5', `url('${getThemeAssetUrl(selectedTheme, 'background5')}')`);
|
|
||||||
|
|
||||||
document.querySelectorAll('.theme-logo').forEach((img) => {
|
|
||||||
img.src = getThemeAssetUrl(selectedTheme, 'logoCorner');
|
|
||||||
});
|
|
||||||
|
|
||||||
const select = document.querySelector('#theme-select');
|
|
||||||
if (select && select.value !== selectedTheme) {
|
|
||||||
select.value = selectedTheme;
|
|
||||||
}
|
|
||||||
return selectedTheme;
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
applyTheme(getStoredTheme());
|
|
||||||
const select = document.querySelector('#theme-select');
|
|
||||||
if (!select) return;
|
|
||||||
select.addEventListener('change', (event) => applyTheme(event.target.value));
|
|
||||||
select.value = getStoredTheme();
|
|
||||||
applyTheme(select.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
export {
|
|
||||||
applyTheme,
|
|
||||||
getStoredTheme,
|
|
||||||
};
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
@use 'shared/_utils' as u;
|
@use 'shared/_utils' as u;
|
||||||
|
|
||||||
#almanac-html.weather-display {
|
#almanac-html.weather-display {
|
||||||
background-image: var(--theme-background-3);
|
background-image: url('../images/backgrounds/3.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.weather-display .main.almanac {
|
.weather-display .main.almanac {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
@use 'shared/_utils'as u;
|
@use 'shared/_utils'as u;
|
||||||
|
|
||||||
#extended-forecast-html.weather-display {
|
#extended-forecast-html.weather-display {
|
||||||
background-image: var(--theme-background-2);
|
background-image: url('../images/backgrounds/2.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.weather-display .main.extended-forecast {
|
.weather-display .main.extended-forecast {
|
||||||
|
|
@ -69,4 +69,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
@use 'shared/_utils'as u;
|
@use 'shared/_utils'as u;
|
||||||
|
|
||||||
#hourly-graph-html {
|
#hourly-graph-html {
|
||||||
background-image: var(--theme-background-1-chart);
|
background-image: url(../images/backgrounds/1-chart.png);
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
.right {
|
.right {
|
||||||
|
|
@ -156,4 +156,4 @@
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,15 +328,6 @@ body {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
|
||||||
--theme-background-1: url('../images/backgrounds/1.png');
|
|
||||||
--theme-background-1-chart: url('../images/backgrounds/1-chart.png');
|
|
||||||
--theme-background-2: url('../images/backgrounds/2.png');
|
|
||||||
--theme-background-3: url('../images/backgrounds/3.png');
|
|
||||||
--theme-background-4: url('../images/backgrounds/4.png');
|
|
||||||
--theme-background-5: url('../images/backgrounds/5.png');
|
|
||||||
}
|
|
||||||
|
|
||||||
#display {
|
#display {
|
||||||
font-family: "Star4000";
|
font-family: "Star4000";
|
||||||
margin: 0 0 0 0;
|
margin: 0 0 0 0;
|
||||||
|
|
@ -348,7 +339,7 @@ body {
|
||||||
width: 640px;
|
width: 640px;
|
||||||
height: 480px;
|
height: 480px;
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
background-image: var(--theme-background-1);
|
background-image: url(../images/backgrounds/1.png);
|
||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
@ -830,4 +821,4 @@ body.kiosk #loading .instructions {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
@use 'shared/_utils'as u;
|
@use 'shared/_utils'as u;
|
||||||
|
|
||||||
#radar-html.weather-display {
|
#radar-html.weather-display {
|
||||||
background-image: var(--theme-background-4);
|
background-image: url('../images/backgrounds/4.png');
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
height: 83px;
|
height: 83px;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
@use 'shared/_utils'as u;
|
@use 'shared/_utils'as u;
|
||||||
|
|
||||||
#regional-forecast-html.weather-display {
|
#regional-forecast-html.weather-display {
|
||||||
background-image: var(--theme-background-5);
|
background-image: url('../images/backgrounds/5.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.weather-display .main.regional-forecast {
|
.weather-display .main.regional-forecast {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
height: 480px;
|
height: 480px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-image: var(--theme-background-1);
|
background-image: url(../images/backgrounds/1.png);
|
||||||
|
|
||||||
/* this method is required to hide blocks so they can be measured while off screen */
|
/* this method is required to hide blocks so they can be measured while off screen */
|
||||||
height: 0px;
|
height: 0px;
|
||||||
|
|
|
||||||
2
server/styles/ws.min.css
vendored
|
|
@ -1,40 +0,0 @@
|
||||||
import { readdir } from 'fs/promises';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
const THEMES_DIR = path.resolve('./themes');
|
|
||||||
|
|
||||||
const discoverThemes = async () => {
|
|
||||||
try {
|
|
||||||
const entries = await readdir(THEMES_DIR, { withFileTypes: true });
|
|
||||||
const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
||||||
const themeAssets = {};
|
|
||||||
|
|
||||||
await Promise.all(directories.map(async (themeName) => {
|
|
||||||
const files = await readdir(path.join(THEMES_DIR, themeName));
|
|
||||||
themeAssets[themeName] = {
|
|
||||||
background1: files.includes('1.png'),
|
|
||||||
background1Chart: files.includes('1-chart.png'),
|
|
||||||
background2: files.includes('2.png'),
|
|
||||||
background3: files.includes('3.png'),
|
|
||||||
background4: files.includes('4.png'),
|
|
||||||
background5: files.includes('5.png'),
|
|
||||||
logoCorner: files.includes('logo-corner.png'),
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
return {
|
|
||||||
themes: ['default', ...directories],
|
|
||||||
themeAssets,
|
|
||||||
};
|
|
||||||
} catch {
|
|
||||||
return {
|
|
||||||
themes: ['default'],
|
|
||||||
themeAssets: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export {
|
|
||||||
THEMES_DIR,
|
|
||||||
discoverThemes,
|
|
||||||
};
|
|
||||||
|
Before Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 295 KiB |
|
Before Width: | Height: | Size: 244 KiB |
|
Before Width: | Height: | Size: 760 KiB |
|
Before Width: | Height: | Size: 225 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 234 KiB |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 295 KiB |
|
Before Width: | Height: | Size: 244 KiB |
|
Before Width: | Height: | Size: 760 KiB |
|
Before Width: | Height: | Size: 225 KiB |
|
Before Width: | Height: | Size: 9.9 KiB |
|
|
@ -31,10 +31,6 @@
|
||||||
window.WS4KP_SERVER_AVAILABLE = true;
|
window.WS4KP_SERVER_AVAILABLE = true;
|
||||||
</script>
|
</script>
|
||||||
<% } %>
|
<% } %>
|
||||||
<script type="text/javascript">
|
|
||||||
window.WS4KP_THEMES = <%- JSON.stringify(themes ?? ['default']) %>;
|
|
||||||
window.WS4KP_THEME_ASSETS = <%- JSON.stringify(themeAssets ?? {}) %>;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<% if (production) { %>
|
<% if (production) { %>
|
||||||
<link rel="stylesheet" type="text/css" href="resources/ws.min.css?_=<%=production%>" />
|
<link rel="stylesheet" type="text/css" href="resources/ws.min.css?_=<%=production%>" />
|
||||||
|
|
@ -184,14 +180,6 @@
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<a href="https://mentalnet.xyz/forgejo/markmental/ws4kp-linhanced">More information</a>
|
<a href="https://mentalnet.xyz/forgejo/markmental/ws4kp-linhanced">More information</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
|
||||||
<label for="theme-select">Theme</label>
|
|
||||||
<select id="theme-select" name="theme-select">
|
|
||||||
<% (themes ?? ['default']).forEach((themeName) => { %>
|
|
||||||
<option value="<%= themeName %>"><%= themeName === 'default' ? 'Default' : themeName %></option>
|
|
||||||
<% }) %>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="media"></div>
|
<div class="media"></div>
|
||||||
|
|
||||||
<div class='heading'>Selected displays</div>
|
<div class='heading'>Selected displays</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="logo"><img class="theme-logo" src="images/logos/logo-corner.png" /></div>
|
<div class="logo"><img src="images/logos/logo-corner.png" /></div>
|
||||||
<% if (locals?.titleDual) { %>
|
<% if (locals?.titleDual) { %>
|
||||||
<div class="title dual">
|
<div class="title dual">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
|
|
@ -25,4 +25,4 @@
|
||||||
<img src="images/logos/noaa.gif" />
|
<img src="images/logos/noaa.gif" />
|
||||||
</div>
|
</div>
|
||||||
<%}%>
|
<%}%>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="logo"><img class="theme-logo" src="images/logos/logo-corner.png" /></div>
|
<div class="logo"><img src="images/logos/logo-corner.png" /></div>
|
||||||
<div class="title dual">
|
<div class="title dual">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
Local
|
Local
|
||||||
|
|
|
||||||