add colorblind setting and friendly palettes

- mode applies to plot data, plot background color, statsseries colors, roofline timescale
This commit is contained in:
Christoph Kluge 2025-01-14 17:40:25 +01:00
parent 42e8e37bd4
commit 736236e9ca
5 changed files with 125 additions and 16 deletions

View File

@ -18,6 +18,7 @@
const ccconfig = getContext("cc-config");
let message = { msg: "", target: "", color: "#d63384" };
let displayMessage = false;
let cbmode = ccconfig?.plot_general_colorblindMode || false;
async function handleSettingSubmit(event) {
const selector = event.detail.selector
@ -28,6 +29,9 @@
const res = await fetch(form.action, { method: "POST", body: formData });
if (res.ok) {
let text = await res.text();
if (formData.get("key") === "plot_general_colorblindMode") {
cbmode = JSON.parse(formData.get("value"));
}
popMessage(text, target, "#048109");
} else {
let text = await res.text();
@ -51,4 +55,4 @@
<UserOptions config={ccconfig} {username} {isApi} bind:message bind:displayMessage on:update-config={(e) => handleSettingSubmit(e)}/>
<PlotRenderOptions config={ccconfig} bind:message bind:displayMessage on:update-config={(e) => handleSettingSubmit(e)}/>
<PlotColorScheme config={ccconfig} bind:message bind:displayMessage on:update-config={(e) => handleSettingSubmit(e)}/>
<PlotColorScheme config={ccconfig} bind:cbmode bind:message bind:displayMessage on:update-config={(e) => handleSettingSubmit(e)}/>

View File

@ -24,6 +24,7 @@
export let config;
export let message;
export let displayMessage;
export let cbmode = false;
const dispatch = createEventDispatcher();
function updateSetting(selector, target) {
@ -265,6 +266,62 @@
],
};
// https://personal.sron.nl/~pault/
// https://tsitsul.in/blog/coloropt/
const cvdschemes = {
HighContrast: [
"rgb(221,170,51)",
"rgb(187,85,102)",
"rgb(0,68,136)",
"rgb(0,0,0)",
],
Bright: [
"rgb(68,119,170)",
"rgb(102,204,238)",
"rgb(34,136,51)",
"rgb(204,187,68)",
"rgb(238,102,119)",
"rgb(170,51,119)",
"rgb(187,187,187)",
],
Muted: [
"rgb(51,34,136)",
"rgb(136,204,238)",
"rgb(68,170,153)",
"rgb(17,119,51)",
"rgb(153,153,51)",
"rgb(221,204,119)",
"rgb(204,102,119)",
"rgb(136,34,85)",
"rgb(170,68,153)",
"rgb(221,221,221)",
],
NormalSixColor: [
"rgb(64,83,211)",
"rgb(221,179,16)",
"rgb(181,29,20)",
"rgb(0,190,255)",
"rgb(251,73,176)",
"rgb(0,178,93)",
"rgb(202,202,202)",
],
NormalTwelveColor: [
"rgb(235,172,35)",
"rgb(184,0,88)",
"rgb(0,140,249)",
"rgb(0,110,0)",
"rgb(0,187,173)",
"rgb(209,99,230)",
"rgb(178,69,2)",
"rgb(255,146,135)",
"rgb(89,84,214)",
"rgb(0,198,248)",
"rgb(135,133,0)",
"rgb(0,167,108)",
"rgb(189,189,189)",
]
}
</script>
<Row cols={1} class="p-2 g-2">
@ -281,7 +338,7 @@
<CardTitle
style="margin-bottom: 1em; display: flex; align-items: center;"
>
<div>Color Scheme for Timeseries Plots</div>
<div>Color Scheme for Timeseries Plots {cbmode ? `(Color Blind Friendly Palettes)` : ``}</div>
{#if displayMessage && message.target == "cs"}<div
style="margin-left: auto; font-size: 0.9em;"
>
@ -293,7 +350,7 @@
<input type="hidden" name="key" value="plot_general_colorscheme" />
<Table hover>
<tbody>
{#each Object.entries(colorschemes) as [name, rgbrow]}
{#each Object.entries(cbmode ? cvdschemes : colorschemes) as [name, rgbrow]}
<tr>
<th scope="col">{name}</th>
<td>
@ -333,8 +390,9 @@
<style>
.color-dot {
height: 10px;
width: 10px;
margin-left: 1px;
height: 12px;
width: 12px;
border-radius: 50%;
display: inline-block;
}

View File

@ -129,8 +129,8 @@
>
<!-- BACKGROUND -->
<Col
><Card class="h-100">
<Col class="d-flex justify-content-between"
><Card class="h-100" style="width: 49%;">
<form
id="backgrounds-form"
method="post"
@ -173,6 +173,50 @@
</div>
<Button color="primary" type="submit">Submit</Button>
</form>
</Card></Col
</Card>
<Card class="h-100" style="width: 49%;">
<form
id="colorblindmode-form"
method="post"
action="/frontend/configuration/"
class="card-body"
on:submit|preventDefault={() =>
updateSetting("#colorblindmode-form", "cbm")}
>
<!-- Svelte 'class' directive only on DOMs directly, normal 'class="xxx"' does not work, so style-array it is. -->
<CardTitle
style="margin-bottom: 1em; display: flex; align-items: center;"
>
<div>Color Blind Mode</div>
{#if displayMessage && message.target == "cbm"}<div
style="margin-left: auto; font-size: 0.9em;"
>
<code style="color: {message.color};" out:fade
>Update: {message.msg}</code
>
</div>{/if}
</CardTitle>
<input type="hidden" name="key" value="plot_general_colorblindMode" />
<div class="mb-3">
<div>
{#if config?.plot_general_colorblindMode}
<input type="radio" id="cbm-true-checked" name="value" value="true" checked />
{:else}
<input type="radio" id="cbm-true" name="value" value="true" />
{/if}
<label for="true">Yes</label>
</div>
<div>
{#if config?.plot_general_colorblindMode}
<input type="radio" id="cbm-false" name="value" value="false" />
{:else}
<input type="radio" id="cbm-false-checked" name="value" value="false" checked />
{/if}
<label for="false">No</label>
</div>
</div>
<Button color="primary" type="submit">Submit</Button>
</form>
</Card>
</Col>
</Row>

View File

@ -152,10 +152,12 @@
const lineWidth =
clusterCockpitConfig.plot_general_lineWidth / window.devicePixelRatio;
const lineColors = clusterCockpitConfig.plot_general_colorscheme;
const cbmode = clusterCockpitConfig?.plot_general_colorblindMode || false;
const backgroundColors = {
normal: "rgba(255, 255, 255, 1.0)",
caution: "rgba(255, 128, 0, 0.3)",
alert: "rgba(255, 0, 0, 0.3)",
caution: cbmode ? "rgba(239, 230, 69, 0.3)" : "rgba(255, 128, 0, 0.3)",
alert: cbmode ? "rgba(225, 86, 44, 0.3)" : "rgba(255, 0, 0, 0.3)",
};
const thresholds = findThresholds(
subClusterTopology,
@ -346,13 +348,13 @@
label: "min",
scale: "y",
width: lineWidth,
stroke: "red",
stroke: cbmode ? "rgb(0,255,0)" : "red",
});
plotSeries.push({
label: "max",
scale: "y",
width: lineWidth,
stroke: "green",
stroke: cbmode ? "rgb(0,0,255)" : "green",
});
plotSeries.push({
label: usesMeanStatsSeries ? "mean" : "median",
@ -362,8 +364,8 @@
});
plotBands = [
{ series: [2, 3], fill: "rgba(0,255,0,0.1)" },
{ series: [3, 1], fill: "rgba(255,0,0,0.1)" },
{ series: [2, 3], fill: cbmode ? "rgba(0,0,255,0.1)" : "rgba(0,255,0,0.1)" },
{ series: [3, 1], fill: cbmode ? "rgba(0,255,0,0.1)" : "rgba(255,0,0,0.1)" },
];
} else {
for (let i = 0; i < series.length; i++) {

View File

@ -40,6 +40,7 @@
let timeoutId = null;
const lineWidth = clusterCockpitConfig.plot_general_lineWidth;
const cbmode = clusterCockpitConfig?.plot_general_colorblindMode || false;
// Helpers
function getGradientR(x) {
@ -61,7 +62,7 @@
return Math.floor(x * 255.0);
}
function getRGB(c) {
return `rgb(${getGradientR(c)}, ${getGradientG(c)}, ${getGradientB(c)})`;
return `rgb(${cbmode ? '0' : getGradientR(c)}, ${getGradientG(c)}, ${getGradientB(c)})`;
}
function nearestThousand(num) {
return Math.ceil(num / 1000) * 1000;