From 3b927a6372f247522dfa75ab4fa6360e534606e4 Mon Sep 17 00:00:00 2001 From: Marie Birner Date: Sun, 1 Oct 2023 18:41:20 +0200 Subject: [PATCH 1/2] [WIP] typescript --- frontend/logbook.ts | 138 +++++++++++++++++++-------------------- templates/stat.html.tera | 1 + 2 files changed, 68 insertions(+), 71 deletions(-) diff --git a/frontend/logbook.ts b/frontend/logbook.ts index 7a100dd..ce698a6 100644 --- a/frontend/logbook.ts +++ b/frontend/logbook.ts @@ -1,85 +1,81 @@ import * as d3 from 'd3'; -const margin = { top: 20, right: 20, bottom: 50, left: 50 }, -width = 960 - margin.left - margin.right, -height = 500 - margin.top - margin.bottom; +export interface Data { + date: Date; + km: number; +} -const parseTime = d3.timeParse('%Y-%m-%d'); +let data = [ + { date: new Date('2023-01-01'), km: 5 }, + { date: new Date('2023-02-01'), km: 24 }, + { date: new Date('2023-08-30'), km: 4000 }, +]; -data.forEach((d: any) => { - d.date = parseTime(d.date); - d.km = +d.km; -}); +if(sessionStorage.getItem('userStats')) { + data = JSON.parse(sessionStorage.getItem('userStats') as Data[]); -const x = d3.scaleTime() -.domain(d3.extent(data, d => d.date)) -.range([0, width]); + const margin = { top: 20, right: 20, bottom: 50, left: 50 }; + const width: number = 960 - margin.left - margin.right; + const height: number = 500 - margin.top - margin.bottom; + + data.forEach((d: Data) => { + d.date = new Date(d.date) + d.km = +d.km; + }); + + const x = d3.scaleTime() + .domain(<[Date, Date]>d3.extent(data, (d: Data) => d.date)) + .range([0, width]); + + const y = d3.scaleLinear() + .domain([0, Number(d3.max(data, (d: Data) => d.km))]) + .range([height, 0]); + + const line = d3.line() + .x((d: Data) => x(d.date)) + .y((d: Data) => y(d.km)); + + const svg = d3.select('#container') + .append('svg') + .attr('width', width + margin.left + margin.right) + .attr('height', height + margin.top + margin.bottom) + .call(responsivefy) + .append('g') + .attr('transform', `translate(${margin.left},${margin.top})`); + + svg.append('path') + .data([data]) + .attr('class', 'line') + .attr('d', line); + + svg.append('g') + .attr('transform', `translate(0,${height})`) + .call(d3.axisBottom(x)); + + svg.append('g') + .call(d3.axisLeft(y)); +} -const y = d3.scaleLinear() -.domain([0, d3.max(data, d => d.km)]) -.range([height, 0]); - -const line = d3.line() -.x(d => x(d.date)) -.y(d => y(d.km)); - -const svg = d3.select('#container') -.append('svg') - .attr('width', width + margin.left + margin.right) - .attr('height', height + margin.top + margin.bottom) - .call(responsivefy) -.append('g') - .attr('transform', `translate(${margin.left},${margin.top})`); - -svg.append('path') -.data([data]) -.attr('class', 'line') -.attr('d', line); - -svg.append('g') -.attr('transform', `translate(0,${height})`) -.call(d3.axisBottom(x)); - -svg.append('g') -.call(d3.axisLeft(y)); function responsivefy(svg: any) { - // container will be the DOM element - // that the svg is appended to - // we then measure the container - // and find its aspect ratio - const container = d3.select(svg.node().parentNode), - width = parseInt(svg.style('width'), 10), - height = parseInt(svg.style('height'), 10), - aspect = width / height; - - // set viewBox attribute to the initial size - // control scaling with preserveAspectRatio - // resize svg on inital page load + const container = d3.select(svg.node().parentNode); + const width = parseInt(svg.style('width'), 10); + const height = parseInt(svg.style('height'), 10); + const aspect = width / height; + svg.attr('viewBox', `0 0 ${width} ${height}`) - .attr('preserveAspectRatio', 'xMinYMid') - .call(resize); - - // add a listener so the chart will be resized - // when the window resizes - // multiple listeners for the same event type - // requires a namespace, i.e., 'click.foo' - // api docs: https://goo.gl/F3ZCFr + .attr('preserveAspectRatio', 'xMinYMid') + .call(resize); + d3.select(window).on( - 'resize.' + container.attr('id'), - resize + 'resize.' + container.attr('id'), + resize ); - - // this is the code that resizes the chart - // it will be called on load - // and in response to window resizes - // gets the width of the container - // and resizes the svg to fill it - // while maintaining a consistent aspect ratio + function resize() { - const w = parseInt(container.style('width')); - svg.attr('width', w); - svg.attr('height', Math.round(w / aspect)); + const w = parseInt(container.style('width')); + svg.attr('width', w); + svg.attr('height', Math.round(w / aspect)); } -} +} \ No newline at end of file diff --git a/templates/stat.html.tera b/templates/stat.html.tera index 780ba6b..fb612fe 100644 --- a/templates/stat.html.tera +++ b/templates/stat.html.tera @@ -43,6 +43,7 @@ const data = [ { date: '{{p.date}}', km: {{p.km}} }, {%- endfor %} ] +sessionStorage.setItem('userStats', JSON.stringify(data)); From a78539fc61ac3af5cb77835ebda44c22e03ac524 Mon Sep 17 00:00:00 2001 From: Marie Birner Date: Sun, 1 Oct 2023 18:44:44 +0200 Subject: [PATCH 2/2] [BUGFIX] stats typescript --- frontend/logbook.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/frontend/logbook.ts b/frontend/logbook.ts index ce698a6..ea4e194 100644 --- a/frontend/logbook.ts +++ b/frontend/logbook.ts @@ -5,14 +5,8 @@ export interface Data { km: number; } -let data = [ - { date: new Date('2023-01-01'), km: 5 }, - { date: new Date('2023-02-01'), km: 24 }, - { date: new Date('2023-08-30'), km: 4000 }, -]; - if(sessionStorage.getItem('userStats')) { - data = JSON.parse(sessionStorage.getItem('userStats') as Data[]); + const data = JSON.parse(sessionStorage.getItem('userStats') || '{}') as Data[]; const margin = { top: 20, right: 20, bottom: 50, left: 50 }; const width: number = 960 - margin.left - margin.right;