mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Let a weather source describe its own products
A weather source can describe its own products (credit, units, coverage, legend) through an optional `display` object in each product manifest: source, credit, units, coverage, info, legend and extent. The weather layer uses each valid field in the row summary, legend, info text, coverage navigation, outside-coverage status, layer stats and imagery credit, and keeps today's built-in value for any field that is absent or invalid. Units and legend describe one scale, so they apply only as a valid pair; otherwise both keep their built-in values, and the radar info heading names the units in use. Text is single-line and length-capped. It rejects control characters (U+0000-U+001F, U+007F-U+009F), line and paragraph separators, and invisible or format characters: soft hyphen (U+00AD), combining grapheme joiner (U+034F), Arabic letter mark (U+061C), Mongolian vowel separator (U+180E), zero-width and direction marks (U+200B-U+200F), bidi embedding and override (U+202A-U+202E), word joiner, invisible operators and bidi isolates (U+2060-U+2069), variation selectors (U+FE00-U+FE0F), the byte-order mark (U+FEFF) and tag characters (U+E0000-U+E007F). Legends need 2-16 stops whose labels are plain decimal numbers or short text and whose colours are #rrggbb. A number label must read back exactly as the legend shows it: within the safe integer range, with no leading zeros and no digits lost to rounding. Extents must be finite, in range and non-empty. Supplied source and units text is data: the layer marks it so the panels show it untranslated, while built-in values are translated as before. The imagery credit is escaped as plain text and follows a refreshed manifest even when the shown frame stays the same. A refresh changes only the credit: the shown frame keeps the snapshot it was staged from, so a later host switch restages it with its own time and bounds and the refreshed credit. Manifests without `display`, including the bundled nowCOAST ones, render exactly as before.
This commit is contained in:
1 parent
3cd7d0fe15
commit
039b0828b7
23 files changed
+1243
-63
No files matched your search
@@ -635,7 +635,11 @@ export class LayerPanel {
|
||||
const stats = layer.stats || {};
|
||||
const feedState = layerFeedState(stats);
|
||||
const stateLabel = t(FEED_STATE_LABEL_KEYS[feedState]);
|
||||
const source = sourceLabel(stats.source || layer.source);
|
||||
// A layer marks source text that is data rather than a catalog name.
|
||||
const source =
|
||||
stats.sourceVerbatim === true && stats.source
|
||||
? stats.source
|
||||
: sourceLabel(stats.source || layer.source);
|
||||
const lifecycleState =
|
||||
layer.lifecycleState || (layer.enabled ? 'enabled' : 'disabled');
|
||||
if (lifecycleState === 'enabling' || lifecycleState === 'disabling') {
|
||||
|
||||
@@ -87,3 +87,21 @@ for (const locale of ['es', 'ru']) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test('a source a layer marks as data is shown untranslated in the row', () => {
|
||||
setLocale('ru');
|
||||
try {
|
||||
const row = (stats) =>
|
||||
LayerPanel.prototype._buildMetaText({
|
||||
id: 'weather-lightning',
|
||||
enabled: true,
|
||||
stats: { count: 1, lastUpdate: Date.now(), ...stats },
|
||||
});
|
||||
assert.match(row({ source: 'Local ADS-B' }), /Локальный ADS-B/);
|
||||
const verbatim = row({ source: 'Local ADS-B', sourceVerbatim: true });
|
||||
assert.match(verbatim, /Local ADS-B/);
|
||||
assert.doesNotMatch(verbatim, /Локальный/);
|
||||
} finally {
|
||||
setLocale('en');
|
||||
}
|
||||
});
|
||||
@@ -16,9 +16,10 @@ const order = (parent, nodes) =>
|
||||
parent.insertBefore(node, parent.children[i] || null);
|
||||
});
|
||||
|
||||
// "960 — 1050+ гПа": the unit stays with the last number.
|
||||
const scaleText = (low, high, units) => {
|
||||
const unit = unitLabel(units);
|
||||
// "960 — 1050+ гПа": the unit stays with the last number. Units a source
|
||||
// supplied as data are shown as given.
|
||||
const scaleText = (low, high, units, verbatim) => {
|
||||
const unit = verbatim ? units || '' : unitLabel(units);
|
||||
const range = `${formatScaleLabel(low)} — ${formatScaleLabel(high)}`;
|
||||
return unit ? `${range}\u00a0${unit}` : range;
|
||||
};
|
||||
@@ -309,7 +310,12 @@ export function createRailCardBlocks({ container, cardId, onParams }) {
|
||||
block.scale,
|
||||
'textContent',
|
||||
visible
|
||||
? scaleText(legend.labels[0], legend.labels.at(-1), legend.units)
|
||||
? scaleText(
|
||||
legend.labels[0],
|
||||
legend.labels.at(-1),
|
||||
legend.units,
|
||||
legend.unitsVerbatim === true,
|
||||
)
|
||||
: '',
|
||||
);
|
||||
} else if (props.type === 'actions') {
|
||||
|
||||
@@ -215,6 +215,7 @@ export function createWeatherPanel({
|
||||
colors: legend.map(({ color }) => color),
|
||||
labels: legend.map(({ label }) => label),
|
||||
units: categorical ? '' : summary.units,
|
||||
...(summary.unitsVerbatim === true ? { unitsVerbatim: true } : {}),
|
||||
zeroIndex: legend.findIndex(({ label }) => label === '0'),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -752,3 +752,27 @@ test('air-quality readout renders its band legend, Canada coverage and worst-fir
|
||||
view.destroy();
|
||||
layer.destroy();
|
||||
});
|
||||
test('source-supplied legend units are shown as given; catalog units are translated', () => {
|
||||
setLocale('ru');
|
||||
try {
|
||||
const f = fixture();
|
||||
const view = createWeatherPanel(f);
|
||||
const row = (summary) => ({
|
||||
...radar,
|
||||
summary: { ...radar.summary, units: 'km/h', ...summary },
|
||||
legend: [
|
||||
{ label: '1', color: '#000000' },
|
||||
{ label: '2', color: '#ffffff' },
|
||||
],
|
||||
});
|
||||
const scale = () =>
|
||||
f.find((n) => n.className === 'rail-card-scale').textContent;
|
||||
view.update([row()]);
|
||||
assert.equal(scale(), '1 — 2 км/ч');
|
||||
view.update([row({ unitsVerbatim: true })]);
|
||||
assert.equal(scale(), '1 — 2 km/h');
|
||||
view.destroy();
|
||||
} finally {
|
||||
setLocale('en');
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user