Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dashboard: Add annotations for Warning without TAN #3434

Merged
merged 5 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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