From 821bd942f6687e0d5e448af31936030e5d7294f8 Mon Sep 17 00:00:00 2001 From: esikkala <esko.ikkala@aalto.fi> Date: Thu, 13 Jan 2022 16:38:41 +0200 Subject: [PATCH] Adapt to ApexCharts timeline config --- .../components/facet_results/ApexCharts.js | 3 +- .../facet_results/ResultClassRoute.js | 2 + .../ApexCharts/ApexChartsConfig.js | 151 ++++++++++++++++++ src/server/index.js | 4 +- src/server/sparql/FacetResults.js | 10 +- 5 files changed, 167 insertions(+), 3 deletions(-) diff --git a/src/client/components/facet_results/ApexCharts.js b/src/client/components/facet_results/ApexCharts.js index 73ca7496..70a2648c 100644 --- a/src/client/components/facet_results/ApexCharts.js +++ b/src/client/components/facet_results/ApexCharts.js @@ -123,7 +123,8 @@ class ApexChart extends React.Component { this.state.createChartData({ ...this.props, resultClassConfig: this.state.resultClassConfig, - chartTypeObj + chartTypeObj, + fetchInstanceAnalysis: this.props.fetchInstanceAnalysis }) ) this.chart.render() diff --git a/src/client/components/facet_results/ResultClassRoute.js b/src/client/components/facet_results/ResultClassRoute.js index be8cd478..200b090d 100644 --- a/src/client/components/facet_results/ResultClassRoute.js +++ b/src/client/components/facet_results/ResultClassRoute.js @@ -261,7 +261,9 @@ const ResultClassRoute = props => { results: perspectiveState.results, fetching: perspectiveState.fetching, resultUpdateID: perspectiveState.resultUpdateID, + fetchInstanceAnalysis: props.fetchInstanceAnalysis, instanceAnalysisDataUpdateID: perspectiveState.instanceAnalysisDataUpdateID, + instanceAnalysisData: perspectiveState.instanceAnalysisData, facetUpdateID: facetState ? facetState.facetUpdateID : null, fetchData: props.fetchResults } diff --git a/src/client/library_configs/ApexCharts/ApexChartsConfig.js b/src/client/library_configs/ApexCharts/ApexChartsConfig.js index bf51863b..d2fa91af 100644 --- a/src/client/library_configs/ApexCharts/ApexChartsConfig.js +++ b/src/client/library_configs/ApexCharts/ApexChartsConfig.js @@ -329,3 +329,154 @@ const apexBarChartOptions = { } } } + +export const createApexTimelineChartData = ({ + resultClass, + facetClass, + perspectiveState, + results, + resultClassConfig, + screenSize, + fetchInstanceAnalysis +}) => { + const { + xaxisTitle, + yaxisTitle + } = resultClassConfig + let min + let max + if (results && results.length > 0) { + preprocessTimelineData(results) + min = new Date(results[0].beginDate).getTime() + max = new Date(results[results.length - 1].endDate).getTime() + } + const apexChartOptionsWithData = { + ...timelineOptions, + chart: { + type: 'rangeBar', + width: '100%', + height: '100%', + events: { + click: (event, chartContext, config) => { + if (chartContext.w.globals.initialSeries[config.seriesIndex]) { + const data = chartContext.w.globals.initialSeries[config.seriesIndex].data[config.dataPointIndex] + fetchInstanceAnalysis({ + resultClass: `${resultClass}Dialog`, + facetClass, + period: data.period, + province: data.id + }) + } + }, + beforeResetZoom: (chartContext, opts) => { + return { xaxis: { min, max } } + } + } + }, + xaxis: { + ...timelineOptions.xaxis, + title: { + text: xaxisTitle + }, + min, + max + }, + yaxis: { title: { text: yaxisTitle } }, + series: results + } + return apexChartOptionsWithData +} + +const timelineOptions = { + plotOptions: { + bar: { + horizontal: true, + barHeight: '70%' + // rangeBarGroupRows: true + } + }, + colors: [ + '#008FFB', '#00E396', '#FEB019', '#FF4560', '#775DD0', + '#3F51B5', '#546E7A', '#D4526E', '#8D5B4C', '#F86624', + '#D7263D', '#1B998B', '#2E294E', '#F46036', '#E2C044' + ], + fill: { + type: 'solid' + }, + xaxis: { + type: 'datetime', + labels: { + formatter: value => { + return new Date(value).getFullYear() + } + } + }, + legend: { + position: 'top' + }, + tooltip: { + custom: opts => { + const data = opts.w.globals.initialSeries[opts.seriesIndex].data[opts.dataPointIndex] + const { ylabel, seriesName } = opts.ctx.rangeBar.getTooltipValues(opts) + // const startYear = new Date(opts.y1).getFullYear() + // const endYear = new Date(opts.y2).getFullYear() + return ` + <div class="apexcharts-custom-tooltip"> + <p><b>Maakunta:</b> ${ylabel.replace(':', '')}</p> + <p><b>Aikakausi:</b> ${seriesName.replace(':', '')}</p> + <p><b>Löytöjen lukumäärä:</b> ${data.instanceCount}</p> + </div> + ` + } + // fixed: { + // enabled: true, + // position: 'topLeft', + // offsetX: 0, + // offsetY: 0 + // } + }, + grid: { + borderColor: '#000', + // row: { + // opacity: 0 + // }, + padding: { + right: 15 + } + } +} + +const preprocessTimelineData = rawData => { + const lengths = [] + rawData.sort((a, b) => new Date(a.beginDate) - new Date(b.beginDate) || new Date(a.endDate) - new Date(b.endDate)) + rawData.forEach((obj, index) => { + if (!Array.isArray(obj.data)) { obj.data = [obj.data] } + obj.data.forEach(dataObj => { + dataObj.y = [ + new Date(obj.beginDate).getTime(), + new Date(obj.endDate).getTime() + ] + }) + obj.data.sort((a, b) => a.x.localeCompare(b.x)) + lengths.push({ index, length: obj.data.length }) + }) + lengths.sort((a, b) => b.length - a.length) + if (rawData[0].data.length < lengths[0].length) { + const indexOfLongestArr = lengths[0].index + /* + * The first data array must hold all possible values, + * because it is used for sortable y-axis. + */ + rawData[indexOfLongestArr].data.forEach((obj, index) => { + if (!rawData[0].data.find(x => x.id === obj.id)) { + rawData[0].data.push({ + id: obj.id, + x: obj.x, + y: [null, null], + instanceCount: 0 + }) + } + }) + } + rawData[0].data.sort((a, b) => a.x.localeCompare(b.x)) +} diff --git a/src/server/index.js b/src/server/index.js index f9d47252..3a0661e8 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -105,7 +105,9 @@ createBackendSearchConfig().then(backendSearchConfig => { limit: body.limit, optimize: body.optimize, fromID: body.fromID, - toID: body.toID + toID: body.toID, + period: body.period, + province: body.province }) if (resultFormat === 'csv') { res.writeHead(200, { diff --git a/src/server/sparql/FacetResults.js b/src/server/sparql/FacetResults.js index f59171d2..27dbb4dd 100644 --- a/src/server/sparql/FacetResults.js +++ b/src/server/sparql/FacetResults.js @@ -103,7 +103,9 @@ export const getAllResults = ({ optimize, limit, fromID = null, - toID = null + toID = null, + period = null, + province = null }) => { const finalPerspectiveID = perspectiveID || facetClass const perspectiveConfig = backendSearchConfig[finalPerspectiveID] @@ -164,6 +166,12 @@ export const getAllResults = ({ if (toID) { q = q.replace(/<TO_ID>/g, `<${toID}>`) } + if (period) { + q = q.replace(/<PERIOD>/g, `<${period}>`) + } + if (province) { + q = q.replace(/<PROVINCE>/g, `<${province}>`) + } if (property) { q = q.replace(/<PROPERTY>/g, property) } -- GitLab