Activity TimeGrid WIP

This commit is contained in:
NaNoMelo 2024-10-15 18:33:25 +02:00 committed by imperosol
parent a44e8a68cb
commit 09dbda87bc
3 changed files with 109 additions and 27 deletions

View File

@ -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(),
},
} 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,
},
],
},
options: {
scales: {
y: {
beginAtZero: true,
},
},
start_date: options.startDate.toString(),
},
} 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,
},
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;
}

View File

@ -5,7 +5,7 @@
{% trans counter_name=counter %}{{ counter_name }} activity{% endtrans %}
{% endblock %}
{% block additionnal_js %}
{% block additional_js %}
<script defer src="{{ static('webpack/graph-index.ts') }}"></script>
{% endblock %}
@ -27,7 +27,8 @@
{% endif %}
</ul>
<h4>{% trans %}Last Week Activity {% endtrans %}</h4>
<canvas id="activityChart" width="400" height="200"></canvas>
<div id="activityGraph" width="400" height="200"></div>
<br/>
{% endif %}
<h5>{% trans %}Legend{% endtrans %}</h5>
@ -48,7 +49,7 @@
<script>
window.addEventListener("DOMContentLoaded", () => {
loadChart({
canvas: document.getElementById("activityChart"),
canvas: document.getElementById("activityGraph"),
startDate: new Date().setDate(new Date().getDate() - 7),
counterId: {{ counter.id }},
});

View File

@ -34,6 +34,8 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.6.0",
"@fullcalendar/core": "^6.1.15",
"@fullcalendar/timegrid": "^6.1.15",
"@hey-api/client-fetch": "^0.4.0",
"@sentry/browser": "^8.34.0",
"@zip.js/zip.js": "^2.7.52",