Skip to content

Commit

Permalink
refactor: Remove Flot, use Chart.js for corpus chooser time graph
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed May 24, 2024
1 parent 7fcd4e7 commit fb6a425
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 223 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- Improved UI reactivity for Simple search
- Make the search button(s) more visible [#308](https://github.com/spraakbanken/korp-frontend/issues/308)
- Use native checkboxes in corpus chooser, not images [#362](https://github.com/spraakbanken/korp-frontend/issues/362)
- Replaced JQuery Flot library with Chart.js, used in corpus chooser time graph
- Added TypeScript definitions for Korp backend parameters and responses
- Wrapped `GraphProxy`, `KwicProxy`, `LemgramProxy`, `StatsProxy` and `TimeProxy` with factories; see [@/util/Factory](./app/scripts/util.ts)
- Removed the `stats_rewrite` config option, as the change above eliminated the need for this
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/components/corpus_chooser/corpus-chooser.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import * as authenticationProxy from "@/components/auth/auth"
import { html } from "@/util"
import { loc } from "@/i18n"
import * as treeUtil from "./util"
import "@/components/corpus_chooser/corpus-time-graph"
import "@/components/corpus_chooser/info-box"
import "@/components/corpus_chooser/time-graph"
import "@/components/corpus_chooser/tree"

angular.module("korpApp").component("corpusChooser", {
Expand Down Expand Up @@ -52,7 +52,7 @@ angular.module("korpApp").component("corpusChooser", {
<div ng-if="$ctrl.showChooser" class="corpus-chooser flex bg-white">
<div class="popupchecks shrink-0 p-4 h-full">
<div class="flex">
<cc-time-graph ng-if="$ctrl.showTimeGraph"></cc-time-graph>
<corpus-time-graph ng-if="$ctrl.showTimeGraph"></corpus-time-graph>
<div class="p-2">
<button ng-click="$ctrl.selectAll()" class="btn btn-default btn-sm w-full mb-2">
<span class="fa-solid fa-check"></span>
Expand Down
138 changes: 138 additions & 0 deletions app/scripts/components/corpus_chooser/corpus-time-graph.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/** @format */
import angular, { IRootScopeService } from "angular"
import range from "lodash/range"
import { Chart } from "chart.js/auto"
import { getLang, loc } from "@/i18n"
import {
calculateYearTicks,
getSeries,
getSeriesSelected,
getCountUndatedSelected,
getSpan,
getCountUndated,
} from "@/timeseries"
import { html } from "@/util"

angular.module("korpApp").component("corpusTimeGraph", {
template: html`<canvas id="time-graph-chart" height="80"></canvas>`,
controller: [
"$rootScope",
function ($rootScope: IRootScopeService) {
const { min, max } = getSpan()

const datasetsDated = [
{
label: loc("corpselector_selected"),
data: {},
backgroundColor: "navy",
},
{
label: loc("corpselector_all"),
data: getSeries(),
backgroundColor: "lightgrey",
},
]

// If there is undated data, add another bar.
// To include the undated part on the side, make it show as a year slightly higher than the max of dated data.
const undatedFakeYear: number = max + Math.max(2, Math.ceil((max - min) / 60))
const datasetsUndated = [
{
label: loc("corpselector_selected"),
data: {},
backgroundColor: "#cd5c5c",
},
{
label: loc("corpselector_all"),
data: { [undatedFakeYear]: getCountUndated() },
backgroundColor: "lightgrey",
},
]

function updateSelectedData() {
datasetsDated[0].data = getSeriesSelected()
datasetsUndated[0].data[undatedFakeYear] = getCountUndatedSelected() || undefined
}
updateSelectedData()

const chart = new Chart(document.getElementById("time-graph-chart") as HTMLCanvasElement, {
type: "bar",
data: getCountUndated()
? {
// Labels need to be strings to match with the `{[year]: count}` format of the datasets.
// `max + 1` because `range` excludes end value.
labels: range(min, undatedFakeYear + 1).map(String),
datasets: [...datasetsDated, ...datasetsUndated],
}
: {
labels: range(min, max + 1).map(String),
datasets: datasetsDated,
},
options: {
scales: {
y: {
display: false,
beginAtZero: true,
},
x: {
ticks: {
autoSkip: false,
},
// Calculate what years to label. Subtract `min` because Chart.js wants the indices, not the labels.
afterBuildTicks: (axis) =>
(axis.ticks = calculateYearTicks(min, max).map((v) => ({ value: v - min }))),
},
},
datasets: {
bar: {
// Show bars behind each other, not next to.
grouped: false,
// Eliminate space between bars
categoryPercentage: 1.0,
barPercentage: 1.0,
// Make low-resource years show more
minBarLength: 2,
},
},
locale: getLang(),
plugins: {
legend: {
display: false,
},
tooltip: {
caretSize: 0,
yAlign: "bottom",
callbacks: {
title: (items) =>
Number(items[0].label) < undatedFakeYear
? `${loc("corpselector_year")} ${items[0].label}`
: loc("corpselector_undated"),
},
// See `defaults` in https://github.com/chartjs/Chart.js/blob/master/src/plugins/plugin.tooltip.js
animations: {
opacity: {
duration: 100,
},
},
},
},
interaction: {
mode: "nearest",
axis: "x",
intersect: false,
},
animation: {
duration: 200,
},
},
})

$rootScope.$on("corpuschooserchange", () => {
updateSelectedData()
// `'none'` to disable animations. Animations would be nice, but they look weird when new data has different min/max year.
// TODO Do animations look better if data is given as array including empty years, not a record?
chart.update("none")
})
},
],
})
190 changes: 0 additions & 190 deletions app/scripts/components/corpus_chooser/time-graph.js

This file was deleted.

Loading

0 comments on commit fb6a425

Please sign in to comment.