Merge pull request #1146 from ae-utbm/fix-ts

Fix ts
This commit is contained in:
thomas girod 2025-07-02 09:01:24 +02:00 committed by GitHub
commit 3e3c6631ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 74 additions and 53 deletions

View File

@ -0,0 +1,38 @@
interface AlertParams {
success?: boolean;
duration?: number;
}
export class AlertMessage {
public open: boolean;
public success: boolean;
public content: string;
private timeoutId?: number;
private readonly defaultDuration: number;
constructor(params?: { defaultDuration: number }) {
this.open = false;
this.content = "";
this.timeoutId = null;
this.defaultDuration = params?.defaultDuration ?? 2000;
}
public display(message: string, params: AlertParams) {
this.clear();
this.open = true;
this.content = message;
this.success = params.success ?? true;
this.timeoutId = setTimeout(() => {
this.open = false;
this.timeoutId = null;
}, params.duration ?? this.defaultDuration);
}
public clear() {
if (this.timeoutId !== null) {
clearTimeout(this.timeoutId);
this.timeoutId = null;
}
this.open = false;
}
}

View File

@ -1,5 +1,5 @@
import type { Client, Options, RequestResult, TDataShape } from "@hey-api/client-fetch"; import type { Client, RequestResult, TDataShape } from "#openapi:client";
import { client } from "#openapi"; import { type Options, client } from "#openapi";
export interface PaginatedResponse<T> { export interface PaginatedResponse<T> {
count: number; count: number;

View File

@ -1,3 +1,4 @@
import { AlertMessage } from "#core:utils/alert-message";
import { BasketItem } from "#counter:counter/basket"; import { BasketItem } from "#counter:counter/basket";
import type { CounterConfig, ErrorMessage } from "#counter:counter/types"; import type { CounterConfig, ErrorMessage } from "#counter:counter/types";
import type { CounterProductSelect } from "./components/counter-product-select-index.ts"; import type { CounterProductSelect } from "./components/counter-product-select-index.ts";
@ -5,14 +6,9 @@ import type { CounterProductSelect } from "./components/counter-product-select-i
document.addEventListener("alpine:init", () => { document.addEventListener("alpine:init", () => {
Alpine.data("counter", (config: CounterConfig) => ({ Alpine.data("counter", (config: CounterConfig) => ({
basket: {} as Record<string, BasketItem>, basket: {} as Record<string, BasketItem>,
errors: [],
customerBalance: config.customerBalance, customerBalance: config.customerBalance,
codeField: null as CounterProductSelect | null, codeField: null as CounterProductSelect | null,
alertMessage: { alertMessage: new AlertMessage({ defaultDuration: 2000 }),
content: "",
show: false,
timeout: null,
},
init() { init() {
// Fill the basket with the initial data // Fill the basket with the initial data
@ -77,22 +73,10 @@ document.addEventListener("alpine:init", () => {
return total; return total;
}, },
showAlertMessage(message: string) {
if (this.alertMessage.timeout !== null) {
clearTimeout(this.alertMessage.timeout);
}
this.alertMessage.content = message;
this.alertMessage.show = true;
this.alertMessage.timeout = setTimeout(() => {
this.alertMessage.show = false;
this.alertMessage.timeout = null;
}, 2000);
},
addToBasketWithMessage(id: string, quantity: number) { addToBasketWithMessage(id: string, quantity: number) {
const message = this.addToBasket(id, quantity); const message = this.addToBasket(id, quantity);
if (message.length > 0) { if (message.length > 0) {
this.showAlertMessage(message); this.alertMessage.display(message, { success: false });
} }
}, },
@ -109,7 +93,9 @@ document.addEventListener("alpine:init", () => {
finish() { finish() {
if (this.getBasketSize() === 0) { if (this.getBasketSize() === 0) {
this.showAlertMessage(gettext("You can't send an empty basket.")); this.alertMessage.display(gettext("You can't send an empty basket."), {
success: false,
});
return; return;
} }
this.$refs.basketForm.submit(); this.$refs.basketForm.submit();

View File

@ -167,7 +167,7 @@ document.addEventListener("alpine:init", () => {
}); });
// if products to download are already in-memory, directly take them. // if products to download are already in-memory, directly take them.
// If not, fetch them. // If not, fetch them.
const products = const products: ProductSchema[] =
this.nbPages > 1 this.nbPages > 1
? await paginated(productSearchProductsDetailed, this.getQueryParams()) ? await paginated(productSearchProductsDetailed, this.getQueryParams())
: Object.values<ProductSchema[]>(this.products).flat(); : Object.values<ProductSchema[]>(this.products).flat();

View File

@ -1,15 +1,11 @@
import { AlertMessage } from "#core:utils/alert-message";
import Alpine from "alpinejs"; import Alpine from "alpinejs";
import { producttypeReorder } from "#openapi"; import { producttypeReorder } from "#openapi";
document.addEventListener("alpine:init", () => { document.addEventListener("alpine:init", () => {
Alpine.data("productTypesList", () => ({ Alpine.data("productTypesList", () => ({
loading: false, loading: false,
alertMessage: { alertMessage: new AlertMessage({ defaultDuration: 2000 }),
open: false,
success: true,
content: "",
timeout: null,
},
async reorder(itemId: number, newPosition: number) { async reorder(itemId: number, newPosition: number) {
// The sort plugin of Alpine doesn't manage dynamic lists with x-sort // The sort plugin of Alpine doesn't manage dynamic lists with x-sort
@ -41,23 +37,14 @@ document.addEventListener("alpine:init", () => {
}, },
openAlertMessage(response: Response) { openAlertMessage(response: Response) {
if (response.ok) { const success = response.ok;
this.alertMessage.success = true; const content = response.ok
this.alertMessage.content = gettext("Products types reordered!"); ? gettext("Products types reordered!")
} else { : interpolate(
this.alertMessage.success = false;
this.alertMessage.content = interpolate(
gettext("Product type reorganisation failed with status code : %d"), gettext("Product type reorganisation failed with status code : %d"),
[response.status], [response.status],
); );
} this.alertMessage.display(content, { success: success });
this.alertMessage.open = true;
if (this.alertMessage.timeout !== null) {
clearTimeout(this.alertMessage.timeout);
}
this.alertMessage.timeout = setTimeout(() => {
this.alertMessage.open = false;
}, 2000);
this.loading = false; this.loading = false;
}, },
})); }));

View File

@ -1,4 +1,4 @@
type ErrorMessage = string; export type ErrorMessage = string;
export interface InitialFormData { export interface InitialFormData {
/* Used to refill the form when the backend raises an error */ /* Used to refill the form when the backend raises an error */

8
package-lock.json generated
View File

@ -48,6 +48,7 @@
"@types/cytoscape-cxtmenu": "^3.4.4", "@types/cytoscape-cxtmenu": "^3.4.4",
"@types/cytoscape-klay": "^3.1.4", "@types/cytoscape-klay": "^3.1.4",
"@types/jquery": "^3.5.31", "@types/jquery": "^3.5.31",
"@types/js-cookie": "^3.0.6",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"vite": "^6.2.5", "vite": "^6.2.5",
"vite-bundle-visualizer": "^1.2.1", "vite-bundle-visualizer": "^1.2.1",
@ -2865,6 +2866,13 @@
"@types/sizzle": "*" "@types/sizzle": "*"
} }
}, },
"node_modules/@types/js-cookie": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
"integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/json-schema": { "node_modules/@types/json-schema": {
"version": "7.0.15", "version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",

View File

@ -10,7 +10,7 @@
"openapi": "openapi-ts", "openapi": "openapi-ts",
"analyse-dev": "vite-bundle-visualizer --mode development", "analyse-dev": "vite-bundle-visualizer --mode development",
"analyse-prod": "vite-bundle-visualizer --mode production", "analyse-prod": "vite-bundle-visualizer --mode production",
"check": "biome check --write" "check": "tsc && biome check --write"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
@ -30,9 +30,10 @@
"@hey-api/openapi-ts": "^0.73.0", "@hey-api/openapi-ts": "^0.73.0",
"@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-inject": "^5.0.5",
"@types/alpinejs": "^3.13.10", "@types/alpinejs": "^3.13.10",
"@types/jquery": "^3.5.31",
"@types/cytoscape-cxtmenu": "^3.4.4", "@types/cytoscape-cxtmenu": "^3.4.4",
"@types/cytoscape-klay": "^3.1.4", "@types/cytoscape-klay": "^3.1.4",
"@types/jquery": "^3.5.31",
"@types/js-cookie": "^3.0.6",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"vite": "^6.2.5", "vite": "^6.2.5",
"vite-bundle-visualizer": "^1.2.1", "vite-bundle-visualizer": "^1.2.1",

View File

@ -83,7 +83,6 @@ document.addEventListener("alpine:init", () => {
Alpine.data("pictureUpload", (albumId: number) => ({ Alpine.data("pictureUpload", (albumId: number) => ({
errors: [] as string[], errors: [] as string[],
pictures: [],
sending: false, sending: false,
progress: null as HTMLProgressElement, progress: null as HTMLProgressElement,

View File

@ -1,3 +1,4 @@
import type { UserAjaxSelect } from "#core:core/components/ajax-select-index";
import { paginated } from "#core:utils/api"; import { paginated } from "#core:utils/api";
import { exportToHtml } from "#core:utils/globals"; import { exportToHtml } from "#core:utils/globals";
import { History } from "#core:utils/history"; import { History } from "#core:utils/history";
@ -130,7 +131,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
currentPicture: { currentPicture: {
// biome-ignore lint/style/useNamingConvention: api is in snake_case // biome-ignore lint/style/useNamingConvention: api is in snake_case
is_moderated: true, is_moderated: true,
id: null, id: null as number,
name: "", name: "",
// biome-ignore lint/style/useNamingConvention: api is in snake_case // biome-ignore lint/style/useNamingConvention: api is in snake_case
display_name: "", display_name: "",
@ -142,7 +143,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
full_size_url: "", full_size_url: "",
owner: "", owner: "",
date: new Date(), date: new Date(),
identifications: [], identifications: [] as IdentifiedUserSchema[],
}, },
/** /**
* The picture which will be displayed next if the user press the "next" button * The picture which will be displayed next if the user press the "next" button
@ -155,7 +156,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
/** /**
* The select2 component used to identify users * The select2 component used to identify users
**/ **/
selector: undefined, selector: undefined as UserAjaxSelect,
/** /**
* Error message when a moderation operation fails * Error message when a moderation operation fails
**/ **/

View File

@ -14,6 +14,7 @@
"types": ["jquery", "alpinejs"], "types": ["jquery", "alpinejs"],
"paths": { "paths": {
"#openapi": ["./staticfiles/generated/openapi/client/index.ts"], "#openapi": ["./staticfiles/generated/openapi/client/index.ts"],
"#openapi:*": ["./staticfiles/generated/openapi/client/*"],
"#core:*": ["./core/static/bundled/*"], "#core:*": ["./core/static/bundled/*"],
"#pedagogy:*": ["./pedagogy/static/bundled/*"], "#pedagogy:*": ["./pedagogy/static/bundled/*"],
"#counter:*": ["./counter/static/bundled/*"], "#counter:*": ["./counter/static/bundled/*"],