From 02fffc67e578b5616b8c3cbbed26f7bc9febf5c9 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Wed, 26 Feb 2025 16:46:34 +0300 Subject: [PATCH] M: Improve notification delays --- .../frontend/src/backend/apiTransport.ts | 74 +++++++++---------- rsconcept/frontend/src/utils/constants.ts | 1 + 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/rsconcept/frontend/src/backend/apiTransport.ts b/rsconcept/frontend/src/backend/apiTransport.ts index 96b93f55..3cb61b40 100644 --- a/rsconcept/frontend/src/backend/apiTransport.ts +++ b/rsconcept/frontend/src/backend/apiTransport.ts @@ -6,6 +6,7 @@ import axios, { type AxiosError, type AxiosRequestConfig } from 'axios'; import { type z, ZodError } from 'zod'; import { buildConstants } from '@/utils/buildConstants'; +import { PARAMETER } from '@/utils/constants'; import { errorMsg } from '@/utils/labels'; import { extractErrorMessage } from '@/utils/utils'; @@ -62,11 +63,7 @@ export function axiosGet({ endpoint, options, schema }: IAxiosGetR .catch((error: Error | AxiosError) => { // Note: Ignore cancellation errors if (error.name !== 'CanceledError') { - if (error instanceof ZodError) { - toast.error(errorMsg.invalidResponse); - } else { - toast.error(extractErrorMessage(error)); - } + notifyError(error); console.error(error); } throw error; @@ -83,21 +80,11 @@ export function axiosPost({ .post(endpoint, request?.data, options) .then(response => { schema?.parse(response.data); - if (request?.successMessage) { - if (typeof request.successMessage === 'string') { - toast.success(request.successMessage); - } else { - toast.success(request.successMessage(response.data)); - } - } + notifySuccess(response.data, request?.successMessage); return response.data; }) .catch((error: Error | AxiosError | ZodError) => { - if (error instanceof ZodError) { - toast.error(errorMsg.invalidResponse); - } else { - toast.error(extractErrorMessage(error)); - } + notifyError(error); throw error; }); } @@ -112,21 +99,11 @@ export function axiosDelete({ .delete(endpoint, options) .then(response => { schema?.parse(response.data); - if (request?.successMessage) { - if (typeof request.successMessage === 'string') { - toast.success(request.successMessage); - } else { - toast.success(request.successMessage(response.data)); - } - } + notifySuccess(response.data, request?.successMessage); return response.data; }) .catch((error: Error | AxiosError | ZodError) => { - if (error instanceof ZodError) { - toast.error(errorMsg.invalidResponse); - } else { - toast.error(extractErrorMessage(error)); - } + notifyError(error); throw error; }); } @@ -141,21 +118,36 @@ export function axiosPatch({ .patch(endpoint, request?.data, options) .then(response => { schema?.parse(response.data); - if (request?.successMessage) { - if (typeof request.successMessage === 'string') { - toast.success(request.successMessage); - } else { - toast.success(request.successMessage(response.data)); - } - } + notifySuccess(response.data, request?.successMessage); return response.data; }) .catch((error: Error | AxiosError | ZodError) => { - if (error instanceof ZodError) { - toast.error(errorMsg.invalidResponse); - } else { - toast.error(extractErrorMessage(error)); - } + notifyError(error); throw error; }); } + +// ====== Internals ========= +function notifySuccess( + data: ResponseData, + message: string | ((data: ResponseData) => string) | undefined +) { + if (!message) { + return; + } + setTimeout(() => { + if (typeof message === 'string') { + toast.success(message); + } else { + toast.success(message(data)); + } + }, PARAMETER.notificationDelay); +} + +function notifyError(error: Error | AxiosError | ZodError) { + if (error instanceof ZodError) { + toast.error(errorMsg.invalidResponse); + } else { + toast.error(extractErrorMessage(error)); + } +} diff --git a/rsconcept/frontend/src/utils/constants.ts b/rsconcept/frontend/src/utils/constants.ts index ac95b45e..d0435bfe 100644 --- a/rsconcept/frontend/src/utils/constants.ts +++ b/rsconcept/frontend/src/utils/constants.ts @@ -9,6 +9,7 @@ export const PARAMETER = { smallScreen: 640, // == tailwind:sm smallTreeNodes: 50, // amount of nodes threshold for size increase for large graphs refreshTimeout: 100, // milliseconds delay for post-refresh actions + notificationDelay: 300, // milliseconds delay for notifications minimalTimeout: 10, // milliseconds delay for fast updates zoomDuration: 500, // milliseconds animation duration moveDuration: 500, // milliseconds - duration of move animation