From f09827339f8b5c065abb16fbe20a02de0cb21724 Mon Sep 17 00:00:00 2001 From: NaNoMelo Date: Tue, 15 Oct 2024 18:33:25 +0200 Subject: [PATCH] Activity TimeGrid WIP --- counter/static/webpack/graph-index.ts | 127 ++++++++++++++++++----- counter/templates/counter/activity.jinja | 7 +- package-lock.json | 42 ++++++++ package.json | 2 + 4 files changed, 151 insertions(+), 27 deletions(-) diff --git a/counter/static/webpack/graph-index.ts b/counter/static/webpack/graph-index.ts index 885345d7..bec7826d 100644 --- a/counter/static/webpack/graph-index.ts +++ b/counter/static/webpack/graph-index.ts @@ -1,51 +1,130 @@ import { paginated } from "#core:utils/api"; import { exportToHtml } from "#core:utils/globals"; -import { Chart } from "chart.js/auto"; import { type PermanencyFetchPermananciesData, + type PermanencySchema, permanencyFetchPermanancies, } from "#openapi"; +import { Calendar } from "@fullcalendar/core"; +import timeGridPlugin from "@fullcalendar/timegrid"; + interface ActivityChartConfig { canvas: HTMLCanvasElement; startDate: Date; counterId: number; } -// Get permanancies from the last week using the API +interface OpeningTime { + start: Date; + end: Date; +} exportToHtml("loadChart", loadChart); async function loadChart(options: ActivityChartConfig) { - const permanancies = paginated(permanencyFetchPermanancies, { + const permanancies = await paginated(permanencyFetchPermanancies, { query: { counter: [options.counterId], // biome-ignore lint/style/useNamingConvention: backend API uses snake_case - start_date: options.startDate.toISOString(), + start_date: options.startDate.toString(), }, - } as PermanencyFetchPermananciesData).then((data) => { - console.log(data); - }); - const chart = new Chart(options.canvas, { - type: "bar", - data: { - labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], - datasets: [ - { - label: "# of Votes", - data: [12, 19, 3, 5, 2, 3], - borderWidth: 1, - }, - ], + } as PermanencyFetchPermananciesData); + + const events = getEvents(permanancies); + + const calendar = new Calendar(options.canvas, { + plugins: [timeGridPlugin], + initialView: "timeGridWeek", + locale: "fr", + slotLabelFormat: { + hour: "2-digit", + minute: "2-digit", + hour12: false, }, - options: { - scales: { - y: { - beginAtZero: true, - }, + dayHeaderFormat: { + weekday: "long", + }, + firstDay: 1, + views: { + timeGrid: { + allDaySlot: false, }, }, + scrollTime: "09:00:00", + headerToolbar: { + left: "", + center: "", + right: "", + }, + //weekends: false, + events: events, + nowIndicator: true, + //slotDuration: "00:15:00", + height: 600, }); + calendar.render(); } -console.log("Hello from graph-index.ts"); +function getOpeningTimes(rawPermanancies: PermanencySchema[]) { + const permanancies = rawPermanancies + .map(convertPermanancyToOpeningTime) + .sort((a, b) => a.start.getTime() - b.start.getTime()); + + const openingTimes: OpeningTime[] = []; + + for (const permanancy of permanancies) { + // if there are no opening times, add the first one + if (openingTimes.length === 0) { + openingTimes.push(permanancy); + } else { + const lastPermanancy = openingTimes[openingTimes.length - 1]; + if ( + // if the new permanancy starts before the 15 minutes following the end of the last one, merge them + new Date(permanancy.start).setMinutes(permanancy.start.getMinutes() - 15) < + lastPermanancy.end.getTime() + ) { + lastPermanancy.end = new Date( + Math.max(lastPermanancy.end.getTime(), permanancy.end.getTime()), + ); + } else { + openingTimes.push(permanancy); + } + } + } + return openingTimes; +} + +function convertPermanancyToOpeningTime(permanancy: PermanencySchema): OpeningTime { + return { + start: new Date(permanancy.start), + end: permanancy.end ? new Date(permanancy.end) : new Date(), + }; +} + +function getEvents(permanancies: PermanencySchema[]) { + const openingTimes = getOpeningTimes(permanancies); + const events = []; + for (const openingTime of openingTimes) { + const lastMonday: Date = new Date(); + lastMonday.setDate(new Date().getDate() - ((new Date().getDay() - 1) % 7)); + lastMonday.setHours(0, 0, 0); + + // if permanancies took place before monday (last week), display them in lightblue as part of the current week + if (openingTime.end < lastMonday) { + events.push({ + start: new Date(openingTime.start).setDate(openingTime.start.getDate() + 7), + end: new Date(openingTime.end).setDate(openingTime.end.getDate() + 7), + backgroundColor: "lightblue", + }); + } else { + events.push({ + start: openingTime.start, + end: openingTime.end, + backgroundColor: "green", + }); + } + } + //const openingTimesByDay = splitByDay(openingTimes); + return events; +} diff --git a/counter/templates/counter/activity.jinja b/counter/templates/counter/activity.jinja index 00f5294b..98fa552b 100644 --- a/counter/templates/counter/activity.jinja +++ b/counter/templates/counter/activity.jinja @@ -5,7 +5,7 @@ {% trans counter_name=counter %}{{ counter_name }} activity{% endtrans %} {% endblock %} -{% block additionnal_js %} +{% block additional_js %} {% endblock %} @@ -27,7 +27,8 @@ {% endif %}

{% trans %}Last Week Activity {% endtrans %}

- +
+
{% endif %}
{% trans %}Legend{% endtrans %}
@@ -48,7 +49,7 @@