commit aba933b1d11ce531a76db78d8ff34e88f8a54950
parent ae440c305aa634896507dde8d8871fb169bc523e
Author: Sebastian <sebasjm@taler-systems.com>
Date: Thu, 26 Mar 2026 16:12:52 -0300
fix #11306
Diffstat:
3 files changed, 85 insertions(+), 69 deletions(-)
diff --git a/packages/merchant-backoffice-ui/src/hooks/order.ts b/packages/merchant-backoffice-ui/src/hooks/order.ts
@@ -22,11 +22,16 @@ import {
ListOrdersRequestParams,
TalerError,
TalerHttpError,
- TalerMerchantManagementResultByMethod
+ TalerMerchantManagementResultByMethod,
} from "@gnu-taler/taler-util";
-import { buildPaginatedResult, LONG_POLL_DELAY, useLongPolling } from "@gnu-taler/web-util/browser";
+import {
+ buildPaginatedResult,
+ LONG_POLL_DELAY,
+ useLongPolling,
+} from "@gnu-taler/web-util/browser";
import _useSWR, { mutate, SWRHook } from "swr";
import { useSessionContext } from "../context/session.js";
+import { useRef } from "preact/hooks";
const useSWR = _useSWR as unknown as SWRHook;
@@ -56,7 +61,7 @@ export function useOrderDetails(oderId: string) {
export function useOrderDetailsWithLongPoll(orderId: string) {
const { state, lib } = useSessionContext();
- const token = state.token
+ const token = state.token;
async function fetcher([dId, token]: [string, AccessToken]) {
return await lib.instance.getOrderDetails(token, dId);
@@ -71,20 +76,20 @@ export function useOrderDetailsWithLongPoll(orderId: string) {
data,
(result) => {
if (!result || result.type === "fail") return undefined;
- return result.body
+ return result.body;
},
async (latestStatus) => {
const r = await lib.instance.getOrderDetails(token!, orderId, {
longpoll: {
etag: latestStatus.etag!,
- timeout: LONG_POLL_DELAY
- }
+ timeout: LONG_POLL_DELAY,
+ },
});
- mutate(r, { revalidate: false })
- return r
+ mutate(r, { revalidate: false });
+ return r;
},
[orderId],
- { minTime: LONG_POLL_DELAY }
+ { minTime: LONG_POLL_DELAY },
);
if (error) return error;
@@ -108,56 +113,68 @@ export function revalidateInstanceOrders() {
}
export function useInstanceOrders(
args?: InstanceOrderFilter,
- updatePosition: (d: string | undefined) => void = () => { },
+ updatePosition: (d: string | undefined) => void = () => {},
) {
const { state, lib } = useSessionContext();
- const token = state.token!
- const params: ListOrdersRequestParams = {
+ const token = state.token!;
+
+ const cacheKey = [
+ args?.position,
+ args?.paid,
+ args?.refunded,
+ args?.wired,
+ args?.date,
+ "listOrders",
+ ];
+
+ console.log({ cacheKey: cacheKey.join(",") });
+
+ async function fetcher([position, paid, refunded, wired, date]: any) {
+ return await lib.instance.listOrders(token, {
limit: PAGINATED_LIST_REQUEST,
- offset: args?.position,
+ offset: position,
order: "dec",
- paid: args?.paid,
- refunded: args?.refunded,
- wired: args?.wired,
- date: args?.date,
- }
- async function fetcher([]) {
- return await lib.instance.listOrders(token, params);
+ paid: paid,
+ refunded: refunded,
+ wired: wired,
+ date: date,
+ });
}
- const cacheKey = [
- args?.position,
- args?.paid,
- args?.refunded,
- args?.wired,
- args?.date,
- "listOrders",
- ];
-
const { data, error } = useSWR<
TalerMerchantManagementResultByMethod<"listOrders">,
TalerHttpError
- >(
- cacheKey,
- fetcher,
- );
+ >(cacheKey, fetcher);
const result = useLongPolling(
data,
(result) => {
if (!result || result.type === "fail") return undefined;
- return result.body
+ return result.body;
},
- async (latestStatus) => {
- const r = await lib.instance.listOrders(token, {...params, timeout: LONG_POLL_DELAY});
- mutate(r, { revalidate: false })
- return r
+ async (latestStatus, args) => {
+ console.log(args)
+ const params: ListOrdersRequestParams = {
+ limit: PAGINATED_LIST_REQUEST,
+ offset: args[0],
+ order: "dec",
+ paid: args[1],
+ refunded: args[2],
+ wired: args[3],
+ date: args[4],
+ };
+ // console.log("PARAMS:", params)
+ const r = await lib.instance.listOrders(token, {
+ ...params,
+ timeout: LONG_POLL_DELAY,
+ });
+ mutate(r, { revalidate: false });
+ return r;
},
cacheKey,
- { minTime: LONG_POLL_DELAY }
+ { minTime: LONG_POLL_DELAY },
);
-
if (error || result instanceof TalerError) return error;
if (result === undefined) return undefined;
if (result.type !== "ok") return result;
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
@@ -32,29 +32,27 @@ import {
useLocalNotificationBetter,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { ErrorLoadingMerchant } from "../../../../components/ErrorLoadingMerchant.js";
import { Loading } from "../../../../components/exception/loading.js";
import { JumpToElementById } from "../../../../components/form/JumpToElementById.js";
+import { DatePicker } from "../../../../components/picker/DatePicker.js";
+import { Tooltip } from "../../../../components/Tooltip.js";
import { useSessionContext } from "../../../../context/session.js";
import {
- InstanceOrderFilter,
useInstanceOrders,
- useOrderDetails,
+ useOrderDetails
} from "../../../../hooks/order.js";
-import { LoginPage } from "../../../login/index.js";
-import { NotFoundPageOrAdminCreate } from "../../../notfound/index.js";
-import { ListPage } from "./ListPage.js";
-import { RefundModal } from "./Table.js";
-import { InputDate } from "../../../../components/form/InputDate.js";
import {
dateFormatForPreferences,
usePreference,
} from "../../../../hooks/preference.js";
-import { format } from "date-fns";
-import { DatePicker } from "../../../../components/picker/DatePicker.js";
-import { Tooltip } from "../../../../components/Tooltip.js";
+import { LoginPage } from "../../../login/index.js";
+import { NotFoundPageOrAdminCreate } from "../../../notfound/index.js";
+import { ListPage } from "./ListPage.js";
+import { RefundModal } from "./Table.js";
const TALER_SCREEN_ID = 46;
diff --git a/packages/web-util/src/hooks/useAsync.ts b/packages/web-util/src/hooks/useAsync.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { opUnknownFailure, TalerError } from "@gnu-taler/taler-util";
-import { useEffect, useState } from "preact/hooks";
+import { useCallback, useEffect, useState } from "preact/hooks";
/**
* convert the async function into preact hook
@@ -43,7 +43,7 @@ export function useAsync<Res>(
if (error instanceof TalerError) {
setError(error);
} else {
- setError(TalerError.fromException(error))
+ setError(TalerError.fromException(error));
}
});
}
@@ -52,17 +52,16 @@ export function useAsync<Res>(
};
}, deps);
- if (error) return (error);
+ if (error) return error;
if (!data) return undefined;
return data;
}
export const LONG_POLL_DELAY = 15000;
-
// FIXME: the problem with this compared with useSWR is that
-// if the hook is called from more than one place then
-// you will have multiple request. This needs to be merged, maybe based on a
+// if the hook is called from more than one place then
+// you will have multiple request. This needs to be merged, maybe based on a
// key
/**
* First start with `initial` value, if initial is undefined then finish.
@@ -71,12 +70,12 @@ export const LONG_POLL_DELAY = 15000;
* If the result is undefined then finish.
* Otherwise:
* Verify if the call is going to fast, if so slow down.
- *
+ *
* Call `retryFn` as the long poll function.
* The result will be the next `initial` value.
*
- *
- *
+ *
+ *
* @param fetcher fetcher should be a memoized function
* @param retry
* @param deps
@@ -85,7 +84,7 @@ export const LONG_POLL_DELAY = 15000;
export function useLongPolling<Res, Rt>(
initial: Res,
shouldRetryFn: (res: Res, count: number) => Rt | undefined,
- retryFn: (last: Rt) => Promise<Res>,
+ retryFn: (last: Rt, deps: Array<any>) => Promise<Res>,
deps: Array<any> = [],
opts: { minTime?: number } = {},
) {
@@ -105,6 +104,17 @@ export function useLongPolling<Res, Rt>(
const body = result ?? initial;
+ const doRetry = useCallback((rt: Rt) => {
+ return function doRetryImpl() {
+ // call again
+ setRetry((lt) => ({
+ // count: lt.count + 1,
+ fn: () => retryFn(rt, deps),
+ startMs: new Date().getTime(),
+ }));
+ };
+ }, deps);
+
useEffect(() => {
if (body === undefined || body instanceof TalerError) return;
const _body = body;
@@ -112,15 +122,6 @@ export function useLongPolling<Res, Rt>(
const rt = shouldRetryFn(_body, retry.startMs ?? 0);
if (rt === undefined) return;
- function doRetry(rt: Rt) {
- // call again
- setRetry((lt) => ({
- // count: lt.count + 1,
- fn: () => retryFn(rt),
- startMs: new Date().getTime(),
- }));
- }
-
if (retry.startMs === undefined) {
doRetry(rt);
} else {