mirror of
https://github.com/ae-utbm/sith.git
synced 2025-07-03 16:45:18 +00:00
commit
3e3c6631ff
38
core/static/bundled/utils/alert-message.ts
Normal file
38
core/static/bundled/utils/alert-message.ts
Normal 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;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import type { Client, Options, RequestResult, TDataShape } from "@hey-api/client-fetch";
|
||||
import { client } from "#openapi";
|
||||
import type { Client, RequestResult, TDataShape } from "#openapi:client";
|
||||
import { type Options, client } from "#openapi";
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
count: number;
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { AlertMessage } from "#core:utils/alert-message";
|
||||
import { BasketItem } from "#counter:counter/basket";
|
||||
import type { CounterConfig, ErrorMessage } from "#counter:counter/types";
|
||||
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", () => {
|
||||
Alpine.data("counter", (config: CounterConfig) => ({
|
||||
basket: {} as Record<string, BasketItem>,
|
||||
errors: [],
|
||||
customerBalance: config.customerBalance,
|
||||
codeField: null as CounterProductSelect | null,
|
||||
alertMessage: {
|
||||
content: "",
|
||||
show: false,
|
||||
timeout: null,
|
||||
},
|
||||
alertMessage: new AlertMessage({ defaultDuration: 2000 }),
|
||||
|
||||
init() {
|
||||
// Fill the basket with the initial data
|
||||
@ -77,22 +73,10 @@ document.addEventListener("alpine:init", () => {
|
||||
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) {
|
||||
const message = this.addToBasket(id, quantity);
|
||||
if (message.length > 0) {
|
||||
this.showAlertMessage(message);
|
||||
this.alertMessage.display(message, { success: false });
|
||||
}
|
||||
},
|
||||
|
||||
@ -109,7 +93,9 @@ document.addEventListener("alpine:init", () => {
|
||||
|
||||
finish() {
|
||||
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;
|
||||
}
|
||||
this.$refs.basketForm.submit();
|
||||
|
@ -167,7 +167,7 @@ document.addEventListener("alpine:init", () => {
|
||||
});
|
||||
// if products to download are already in-memory, directly take them.
|
||||
// If not, fetch them.
|
||||
const products =
|
||||
const products: ProductSchema[] =
|
||||
this.nbPages > 1
|
||||
? await paginated(productSearchProductsDetailed, this.getQueryParams())
|
||||
: Object.values<ProductSchema[]>(this.products).flat();
|
||||
|
@ -1,15 +1,11 @@
|
||||
import { AlertMessage } from "#core:utils/alert-message";
|
||||
import Alpine from "alpinejs";
|
||||
import { producttypeReorder } from "#openapi";
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("productTypesList", () => ({
|
||||
loading: false,
|
||||
alertMessage: {
|
||||
open: false,
|
||||
success: true,
|
||||
content: "",
|
||||
timeout: null,
|
||||
},
|
||||
alertMessage: new AlertMessage({ defaultDuration: 2000 }),
|
||||
|
||||
async reorder(itemId: number, newPosition: number) {
|
||||
// The sort plugin of Alpine doesn't manage dynamic lists with x-sort
|
||||
@ -41,23 +37,14 @@ document.addEventListener("alpine:init", () => {
|
||||
},
|
||||
|
||||
openAlertMessage(response: Response) {
|
||||
if (response.ok) {
|
||||
this.alertMessage.success = true;
|
||||
this.alertMessage.content = gettext("Products types reordered!");
|
||||
} else {
|
||||
this.alertMessage.success = false;
|
||||
this.alertMessage.content = interpolate(
|
||||
gettext("Product type reorganisation failed with status code : %d"),
|
||||
[response.status],
|
||||
);
|
||||
}
|
||||
this.alertMessage.open = true;
|
||||
if (this.alertMessage.timeout !== null) {
|
||||
clearTimeout(this.alertMessage.timeout);
|
||||
}
|
||||
this.alertMessage.timeout = setTimeout(() => {
|
||||
this.alertMessage.open = false;
|
||||
}, 2000);
|
||||
const success = response.ok;
|
||||
const content = response.ok
|
||||
? gettext("Products types reordered!")
|
||||
: interpolate(
|
||||
gettext("Product type reorganisation failed with status code : %d"),
|
||||
[response.status],
|
||||
);
|
||||
this.alertMessage.display(content, { success: success });
|
||||
this.loading = false;
|
||||
},
|
||||
}));
|
||||
|
2
counter/static/bundled/counter/types.d.ts
vendored
2
counter/static/bundled/counter/types.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
type ErrorMessage = string;
|
||||
export type ErrorMessage = string;
|
||||
|
||||
export interface InitialFormData {
|
||||
/* Used to refill the form when the backend raises an error */
|
||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -48,6 +48,7 @@
|
||||
"@types/cytoscape-cxtmenu": "^3.4.4",
|
||||
"@types/cytoscape-klay": "^3.1.4",
|
||||
"@types/jquery": "^3.5.31",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.2.5",
|
||||
"vite-bundle-visualizer": "^1.2.1",
|
||||
@ -2865,6 +2866,13 @@
|
||||
"@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": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
|
@ -10,7 +10,7 @@
|
||||
"openapi": "openapi-ts",
|
||||
"analyse-dev": "vite-bundle-visualizer --mode development",
|
||||
"analyse-prod": "vite-bundle-visualizer --mode production",
|
||||
"check": "biome check --write"
|
||||
"check": "tsc && biome check --write"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@ -30,9 +30,10 @@
|
||||
"@hey-api/openapi-ts": "^0.73.0",
|
||||
"@rollup/plugin-inject": "^5.0.5",
|
||||
"@types/alpinejs": "^3.13.10",
|
||||
"@types/jquery": "^3.5.31",
|
||||
"@types/cytoscape-cxtmenu": "^3.4.4",
|
||||
"@types/cytoscape-klay": "^3.1.4",
|
||||
"@types/jquery": "^3.5.31",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.2.5",
|
||||
"vite-bundle-visualizer": "^1.2.1",
|
||||
|
@ -83,7 +83,6 @@ document.addEventListener("alpine:init", () => {
|
||||
|
||||
Alpine.data("pictureUpload", (albumId: number) => ({
|
||||
errors: [] as string[],
|
||||
pictures: [],
|
||||
sending: false,
|
||||
progress: null as HTMLProgressElement,
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import type { UserAjaxSelect } from "#core:core/components/ajax-select-index";
|
||||
import { paginated } from "#core:utils/api";
|
||||
import { exportToHtml } from "#core:utils/globals";
|
||||
import { History } from "#core:utils/history";
|
||||
@ -130,7 +131,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
|
||||
currentPicture: {
|
||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||
is_moderated: true,
|
||||
id: null,
|
||||
id: null as number,
|
||||
name: "",
|
||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||
display_name: "",
|
||||
@ -142,7 +143,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
|
||||
full_size_url: "",
|
||||
owner: "",
|
||||
date: new Date(),
|
||||
identifications: [],
|
||||
identifications: [] as IdentifiedUserSchema[],
|
||||
},
|
||||
/**
|
||||
* 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
|
||||
**/
|
||||
selector: undefined,
|
||||
selector: undefined as UserAjaxSelect,
|
||||
/**
|
||||
* Error message when a moderation operation fails
|
||||
**/
|
||||
|
@ -14,6 +14,7 @@
|
||||
"types": ["jquery", "alpinejs"],
|
||||
"paths": {
|
||||
"#openapi": ["./staticfiles/generated/openapi/client/index.ts"],
|
||||
"#openapi:*": ["./staticfiles/generated/openapi/client/*"],
|
||||
"#core:*": ["./core/static/bundled/*"],
|
||||
"#pedagogy:*": ["./pedagogy/static/bundled/*"],
|
||||
"#counter:*": ["./counter/static/bundled/*"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user