Skip to content

Commit

Permalink
Update dashboard: Add annotations for Warning without TAN (#3434)
Browse files Browse the repository at this point in the history
Co-authored-by: Thorben Kurowski <[email protected]>
  • Loading branch information
larswmh and thorbenkuro authored Mar 23, 2023
1 parent 5ab93e3 commit a49d744
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 111 deletions.
25 changes: 13 additions & 12 deletions src/assets/js/analyse/chart.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import $ from 'jquery';
import ApexCharts from 'apexcharts'
import ApexCharts from 'apexcharts';
import { Subject } from 'rxjs';

import chartOptions from './chart/options.js';
import { update } from './chart/update.js';
let chartsAry = [];

window.ApexCharts = ApexCharts;
Object.assign(Apex, chartOptions);
Object.assign(Apex, chartOptions);

$(() => {
// loop over all board
$(".analyseChart").each(async function(i){
// init ApexCharts with base options
new ApexCharts(this, Object.assign({}, {chart:{id:`chart${i}`}})).render();

const chart$ = new Subject;
await chart$.subscribe(e => update(e, i));
chartsAry.push(chart$);
});
// loop over all board
$('.analyseChart').each(async function (i) {
// init ApexCharts with base options
const chart = new ApexCharts(this, Object.assign({}, { chart: { id: `chart${i}` } }));
chart.render();

const chart$ = new Subject();
await chart$.subscribe((e) => update(e, i));
chartsAry.push(chart$);
});
});

export default chartsAry;
export default chartsAry;
227 changes: 131 additions & 96 deletions src/assets/js/analyse/chart/update.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ApexCharts from 'apexcharts'
import ApexCharts from 'apexcharts';
import _get from 'lodash/get';
import _set from 'lodash/set';

Expand All @@ -8,101 +8,136 @@ import { debugLog, debugTime, debugTimeEnd } from '../debug.js';

import { checkLegendReset, renderLegend } from './legend.js';
import chartConfig from './config.js';
import { DateTime } from 'luxon';

const delay = (ms) => new Promise((res) => setTimeout(res, ms));

const selfWarningAnnotation = {
key: 'self-test-submission',
label_de: 'Warnen ohne TAN',
label_en: 'Warning without TAN',
targetCharts: ['chart2', 'chart3'],
dataPoints: {
daily: `__${DateTime.fromISO('2023-01-18').toLocaleString({ day: '2-digit', month: 'short', year: '2-digit' })}__`,
weekly: documentLang == 'de' ? '__KW 03 2023__' : '__CW 03 2023__',
},
};



const delay = ms => new Promise(res => setTimeout(res, ms));

const update = async function({
barthreshold,
categories,
data,
date,
keys,
mode,
range,
reallabels,
switchId,
tabs1,
tabs2,
tooltipDate,
updated
},
i
)
{
const id = `chart${i}`;

$(`.analyseBoard-loading[data-id="${id}"]`).addClass("active");
await delay(100);
debugTime('updateOptions' + id)

if(i == 1){
// switch title on chart1 tabs
$(`.${id}`).find(".analyseBoard-title .analyseBoard-title-title").html(translate(["analyseBoardTitleTitle", i, tabs1]));
}

if(i == 1 || i == 2){
// update total values based on selected tabs
totalValuesUpdate($(`.${id}`).find(".analyseBoard-total-value"), i, ((i == 1)? tabs1: (i == 2)? tabs2: 0));
}


let chartConfigObj = _get(chartConfig, [id, switchId], []);
if(Array.isArray(chartConfigObj)){
chartConfigObj = _get(chartConfigObj, [(id == "chart1")? tabs1: (id == "chart2")? tabs2: []], []);
}

const chartType = _get(chartConfigObj, ["type"], "line");
const type = (chartType == "bar")? (barthreshold)? chartType: "area": chartType;


let opt = {
chart: {
id,
type,
stacked: _get(chartConfigObj, ["stacked"], false)
},
seriesall: _get(chartConfigObj, ["series"], []).map(obj => {
return {
ghost: obj.ghost,
color: (obj.color)? obj.color: undefined,
type: (obj.type)? (barthreshold)? obj.type: "line": type,
name: (obj.name)? translate(obj.name): translate(obj.data),
data: (keys.indexOf(obj.data) >= 0)? data.map(m => m[keys.indexOf(obj.data)]): [],
key: obj.data
}
})
};

// add only if needed
if(updated){
opt = Object.assign(opt, {mode, reallabels, tooltipDate, xaxis: {categories}})
}

// set series without the ghosts
_set(opt, ["series"], opt.seriesall.filter(e => !e.ghost));

// set dasharray for legend and switch 4
_set(opt, ["stroke", "dashArray"], (switchId == 4)? opt.seriesall.filter(e => !e.ghost).map(obj => (!!~obj.key.indexOf("_daily"))? 5: 0): new Array(opt.series.length).fill(0));

//Only reset series if necessary
checkLegendReset(opt, () => {
ApexCharts.exec(id, "resetSeries", true, false);
});


// update chart options
ApexCharts.exec(id, "updateOptions", opt, true, false, false);



// render custom legend
renderLegend(opt);
debugTimeEnd('updateOptions'+id)
debugLog("chart update", id, opt);
const update = async function (
{ barthreshold, categories, data, date, keys, mode, range, reallabels, switchId, tabs1, tabs2, tooltipDate, updated },
i
) {
const id = `chart${i}`;

$(`.analyseBoard-loading[data-id="${id}"]`).addClass('active');
await delay(100);
debugTime('updateOptions' + id);

if (i == 1) {
// switch title on chart1 tabs
$(`.${id}`)
.find('.analyseBoard-title .analyseBoard-title-title')
.html(translate(['analyseBoardTitleTitle', i, tabs1]));
}

if (i == 1 || i == 2) {
// update total values based on selected tabs
totalValuesUpdate($(`.${id}`).find('.analyseBoard-total-value'), i, i == 1 ? tabs1 : i == 2 ? tabs2 : 0);
}

let chartConfigObj = _get(chartConfig, [id, switchId], []);
if (Array.isArray(chartConfigObj)) {
chartConfigObj = _get(chartConfigObj, [id == 'chart1' ? tabs1 : id == 'chart2' ? tabs2 : []], []);
}

const chartType = _get(chartConfigObj, ['type'], 'line');
const type = chartType == 'bar' ? (barthreshold ? chartType : 'area') : chartType;

let opt = {
chart: {
id,
type,
stacked: _get(chartConfigObj, ['stacked'], false),
},
seriesall: _get(chartConfigObj, ['series'], []).map((obj) => {
return {
ghost: obj.ghost,
color: obj.color ? obj.color : undefined,
type: obj.type ? (barthreshold ? obj.type : 'line') : type,
name: obj.name ? translate(obj.name) : translate(obj.data),
data: keys.indexOf(obj.data) >= 0 ? data.map((m) => m[keys.indexOf(obj.data)]) : [],
key: obj.data,
};
}),
};

// add only if needed
if (updated) {
opt = Object.assign(opt, { mode, reallabels, tooltipDate, xaxis: { categories } });
}

// set series without the ghosts
_set(
opt,
['series'],
opt.seriesall.filter((e) => !e.ghost)
);

// set dasharray for legend and switch 4
_set(
opt,
['stroke', 'dashArray'],
switchId == 4
? opt.seriesall.filter((e) => !e.ghost).map((obj) => (!!~obj.key.indexOf('_daily') ? 5 : 0))
: new Array(opt.series.length).fill(0)
);

//Only reset series if necessary
checkLegendReset(opt, () => {
ApexCharts.exec(id, 'resetSeries', true, false);
});

// update chart options
ApexCharts.exec(id, 'updateOptions', opt, true, false, false);

// update and set annotations
const calculateAnnotationPosition = () => {
const dataPointIndex = categories.findIndex((category) =>
Object.values(selfWarningAnnotation.dataPoints).includes(category)
);
const magicNum = (dataPointIndex / categories.length) * 100;
return {
textAnchor: magicNum < 60 ? 'start' : 'end',
offsetX: magicNum < 60 ? 4 : -4,
};
};

if (selfWarningAnnotation.targetCharts.includes(id)) {
const annotationPosition = calculateAnnotationPosition();

ApexCharts.exec(id, 'clearAnnotations');

ApexCharts.exec(id, 'addXaxisAnnotation', {
x: mode === 'weekly' ? selfWarningAnnotation.dataPoints.weekly : selfWarningAnnotation.dataPoints.daily,
strokeDashArray: 0,
borderColor: '#775DD0',
label: {
orientation: 'horizontal',
textAnchor: annotationPosition.textAnchor,
offsetX: annotationPosition.offsetX,
offsetY: 5,
text: documentLang == 'de' ? selfWarningAnnotation.label_de : selfWarningAnnotation.label_en,
style: {
background: '#775DD0',
},
},
});
}

// render custom legend
renderLegend(opt);
debugTimeEnd('updateOptions' + id);
debugLog('chart update', id, opt);
};

export {
update
}
export { update };
4 changes: 1 addition & 3 deletions src/assets/js/analyse/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ function filterData(dataOrg, date, mode){
out.barthreshold = (out.range <= barThreshold[mode]);
out.categories = out.reallabels.map(e => {
let d = DateTime.fromISO(e);
//our.range is changed from 28 to 1000
//Due to this issue https://github.com/corona-warn-app/cwa-website/issues/2414
d = (mode == "daily")? d.toLocaleString((out.range <= 1000 )? { day: "2-digit", month: 'short' , year: '2-digit'}: { month: 'short', year: '2-digit' }): d.toFormat((documentLang == "de")? "'KW' WW": "'CW' WW");
d = (mode == "daily")? d.toLocaleString({ day: "2-digit", month: 'short' , year: '2-digit'}): d.toFormat((documentLang == "de")? "'KW' WW yyyy": "'CW' WW yyyy");
return `__${d}__`;
});
out.tooltipDate = out.reallabels.map(o => (mode == "weekly")? DateTime.fromISO(o).toFormat((documentLang == "de")? "'KW' WW": "'CW' WW") + " - " + DateTime.fromISO(o).toLocaleString(DateTime.DATE_HUGE): DateTime.fromISO(o).toLocaleString(DateTime.DATE_HUGE));
Expand Down
6 changes: 6 additions & 0 deletions src/assets/scss/_analyse.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,12 @@

}

.apexcharts-xaxis-annotations {
.apexcharts-xaxis-annotation-label {
fill: #fff !important;
}
}

.info-textblock {
position: relative;
top: -1px
Expand Down

0 comments on commit a49d744

Please sign in to comment.