ropegeo-common 1.15.0 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/components/RopeGeoDataLoader.d.ts +51 -0
- package/dist/components/RopeGeoDataLoader.d.ts.map +1 -0
- package/dist/components/{RopeGeoHttpRequest.js → RopeGeoDataLoader.js} +113 -45
- package/dist/components/RopeGeoPagedDataLoader.d.ts +23 -0
- package/dist/components/RopeGeoPagedDataLoader.d.ts.map +1 -0
- package/dist/components/{RopeGeoCursorPaginationHttpRequest.js → RopeGeoPagedDataLoader.js} +81 -63
- package/dist/components/RopeGeoProgressDataLoader.d.ts +23 -0
- package/dist/components/RopeGeoProgressDataLoader.d.ts.map +1 -0
- package/dist/components/{RopeGeoPaginationHttpRequest.js → RopeGeoProgressDataLoader.js} +57 -39
- package/dist/components/index.d.ts +3 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +10 -10
- package/dist/models/api/params/cursorPaginationParams.d.ts +5 -0
- package/dist/models/api/params/cursorPaginationParams.d.ts.map +1 -1
- package/dist/models/api/params/cursorPaginationParams.js +10 -0
- package/dist/models/api/params/paginationParams.d.ts +5 -0
- package/dist/models/api/params/paginationParams.d.ts.map +1 -1
- package/dist/models/api/params/paginationParams.js +10 -0
- package/package.json +1 -1
- package/dist/components/RopeGeoCursorPaginationHttpRequest.d.ts +0 -56
- package/dist/components/RopeGeoCursorPaginationHttpRequest.d.ts.map +0 -1
- package/dist/components/RopeGeoHttpRequest.d.ts +0 -68
- package/dist/components/RopeGeoHttpRequest.d.ts.map +0 -1
- package/dist/components/RopeGeoPaginationHttpRequest.d.ts +0 -69
- package/dist/components/RopeGeoPaginationHttpRequest.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -326,9 +326,9 @@ Legend entries for page minimaps are keyed objects (`legend` on `PageMiniMap`);
|
|
|
326
326
|
|
|
327
327
|
| Name | Description | Import |
|
|
328
328
|
| --- | --- | --- |
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
329
|
+
| `RopeGeoDataLoader` | Single-request loader: `onlinePath` / `onlinePathParams`, optional `offlineData` (object used as `data` immediately; no network), optional `timeoutAfterSeconds` and `isOnline`. Children receive `data`, `errors`, `timeoutCountdown` (numeric only while an online fetch is in flight, otherwise `null`), and `reload`. Reconnect refetch uses `dirtyWhileOffline` driven by a semantic key (no `refreshOnReconnect` prop). Also exports `Method`, `Service`, `SERVICE_BASE_URL`. | `import { RopeGeoDataLoader, Method, Service } from 'ropegeo-common/components'` |
|
|
330
|
+
| `RopeGeoPagedDataLoader` | Cursor-paginated list: same networking props as above; children get `loadNextPage`, `loadingNextPage`, `morePages`, plus `data`, `errors`, `timeoutCountdown`, `reload`. | `import { RopeGeoPagedDataLoader } from 'ropegeo-common/components'` |
|
|
331
|
+
| `RopeGeoProgressDataLoader` | Page-based “progress” fetch: batches additional pages until `total` is satisfied; children get `received`, `total`, `data`, `errors`, `timeoutCountdown`, `reload`. | `import { RopeGeoProgressDataLoader } from 'ropegeo-common/components'` |
|
|
332
332
|
|
|
333
333
|
---
|
|
334
334
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export declare const Service: {
|
|
3
|
+
readonly WEBSCRAPER: "WEBSCRAPER";
|
|
4
|
+
};
|
|
5
|
+
export type Service = (typeof Service)[keyof typeof Service];
|
|
6
|
+
export declare const Method: {
|
|
7
|
+
readonly GET: "GET";
|
|
8
|
+
readonly POST: "POST";
|
|
9
|
+
readonly PUT: "PUT";
|
|
10
|
+
readonly DELETE: "DELETE";
|
|
11
|
+
};
|
|
12
|
+
export type Method = (typeof Method)[keyof typeof Method];
|
|
13
|
+
export declare const SERVICE_BASE_URL: Record<Service, string>;
|
|
14
|
+
export type RopeGeoDataLoaderProps<T = unknown> = {
|
|
15
|
+
service: Service;
|
|
16
|
+
method: Method;
|
|
17
|
+
/** HTTP path template (e.g. `/ropewiki/page/:id`). Used when loading from the network. */
|
|
18
|
+
onlinePath: string;
|
|
19
|
+
onlinePathParams?: Record<string, string>;
|
|
20
|
+
queryParams?: Record<string, string | number | boolean | undefined>;
|
|
21
|
+
body?: object;
|
|
22
|
+
/**
|
|
23
|
+
* Request deadline in seconds (abort + timeout error). When omitted, {@link timeoutCountdown}
|
|
24
|
+
* stays `null` and no deadline is enforced.
|
|
25
|
+
*/
|
|
26
|
+
timeoutAfterSeconds?: number;
|
|
27
|
+
/**
|
|
28
|
+
* When `false`, the online request is not started and children receive {@link NO_NETWORK_MESSAGE}
|
|
29
|
+
* as the error. Previously loaded `data` is kept until the network returns. When `true` or
|
|
30
|
+
* omitted, behavior is unchanged.
|
|
31
|
+
*/
|
|
32
|
+
isOnline?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* When set, this value is used as `data` immediately (no network). Callers that load from disk
|
|
35
|
+
* should read and parse the file themselves, then pass the resulting object here.
|
|
36
|
+
*/
|
|
37
|
+
offlineData?: T;
|
|
38
|
+
children: (args: {
|
|
39
|
+
data: T | null;
|
|
40
|
+
errors: Error | null;
|
|
41
|
+
/**
|
|
42
|
+
* Whole seconds remaining until abort while an **online** fetch is in flight, only when
|
|
43
|
+
* `timeoutAfterSeconds` is set. Otherwise always `null`.
|
|
44
|
+
*/
|
|
45
|
+
timeoutCountdown: number | null;
|
|
46
|
+
/** Re-runs the online request while online. No-op when `isOnline` is `false`. */
|
|
47
|
+
reload: () => void;
|
|
48
|
+
}) => ReactNode;
|
|
49
|
+
};
|
|
50
|
+
export declare function RopeGeoDataLoader<T = unknown>({ service, method, onlinePath, onlinePathParams, queryParams, body, timeoutAfterSeconds, isOnline, offlineData, children, }: RopeGeoDataLoaderProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
//# sourceMappingURL=RopeGeoDataLoader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RopeGeoDataLoader.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoDataLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,eAAO,MAAM,OAAO;;CAEV,CAAC;AACX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;AAE7D,eAAO,MAAM,MAAM;;;;;CAKT,CAAC;AACX,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAEpD,CAAC;AAoEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,OAAO,IAAI;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB;;;WAGG;QACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,iFAAiF;QACjF,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,KAAK,SAAS,CAAC;CACjB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,EAC7C,OAAO,EACP,MAAM,EACN,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,WAAW,EACX,QAAQ,GACT,EAAE,sBAAsB,CAAC,CAAC,CAAC,2CAwT3B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SERVICE_BASE_URL = exports.Method = exports.Service = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.RopeGeoDataLoader = RopeGeoDataLoader;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const network_1 = require("../helpers/network");
|
|
@@ -40,38 +40,101 @@ function buildUrl(baseUrl, path, pathParams, queryParams) {
|
|
|
40
40
|
}
|
|
41
41
|
return url.toString();
|
|
42
42
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
43
|
+
function hasEffectiveQueryParams(queryParams) {
|
|
44
|
+
if (queryParams == null)
|
|
45
|
+
return false;
|
|
46
|
+
return Object.entries(queryParams).some(([, v]) => v !== undefined && v !== "");
|
|
47
|
+
}
|
|
48
|
+
function dataLoaderReconnectSemanticKey(service, method, onlinePath, pathParamsKey, bodyKey, queryParams, queryParamsKey) {
|
|
49
|
+
const bodyStr = bodyKey === undefined || bodyKey === null
|
|
50
|
+
? ""
|
|
51
|
+
: typeof bodyKey === "object"
|
|
52
|
+
? JSON.stringify(bodyKey)
|
|
53
|
+
: String(bodyKey);
|
|
54
|
+
const q = hasEffectiveQueryParams(queryParams) ? queryParamsKey : "";
|
|
55
|
+
return `${service}|${method}|${onlinePath}|${pathParamsKey}|${bodyStr}|${q}`;
|
|
56
|
+
}
|
|
57
|
+
function offlineDataKeyPart(offlineData) {
|
|
58
|
+
if (offlineData === undefined)
|
|
59
|
+
return "";
|
|
60
|
+
return `|obj:${JSON.stringify(offlineData)}`;
|
|
61
|
+
}
|
|
62
|
+
function RopeGeoDataLoader({ service, method, onlinePath, onlinePathParams, queryParams, body, timeoutAfterSeconds, isOnline, offlineData, children, }) {
|
|
45
63
|
const [data, setData] = (0, react_1.useState)(null);
|
|
46
64
|
const [errors, setErrors] = (0, react_1.useState)(null);
|
|
47
65
|
const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
|
|
48
|
-
const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
|
|
49
66
|
const [reloadTick, setReloadTick] = (0, react_1.useState)(0);
|
|
50
67
|
const pendingReloadRef = (0, react_1.useRef)(false);
|
|
51
68
|
const errorsRef = (0, react_1.useRef)(errors);
|
|
52
|
-
const hasCommittedRef = (0, react_1.useRef)(
|
|
69
|
+
const hasCommittedRef = (0, react_1.useRef)(false);
|
|
53
70
|
errorsRef.current = errors;
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
pendingReloadRef.current = true;
|
|
59
|
-
setReloadTick((n) => n + 1);
|
|
60
|
-
}, [isOnline]);
|
|
61
|
-
const pathParamsKey = JSON.stringify(pathParams ?? null);
|
|
71
|
+
const dirtyWhileOfflineRef = (0, react_1.useRef)(false);
|
|
72
|
+
const semanticSnapshotRef = (0, react_1.useRef)(null);
|
|
73
|
+
const prevIsOnlineRef = (0, react_1.useRef)(undefined);
|
|
74
|
+
const pathParamsKey = JSON.stringify(onlinePathParams ?? null);
|
|
62
75
|
const queryParamsKey = JSON.stringify(queryParams ?? null);
|
|
63
76
|
const bodyKey = body === undefined || body === null
|
|
64
77
|
? body
|
|
65
78
|
: typeof body === "object"
|
|
66
79
|
? JSON.stringify(body)
|
|
67
80
|
: body;
|
|
68
|
-
const requestKey = (0, react_1.useMemo)(() => `${service}|${method}|${
|
|
69
|
-
|
|
81
|
+
const requestKey = (0, react_1.useMemo)(() => `${service}|${method}|${onlinePath}|${pathParamsKey}|${queryParamsKey}|${String(bodyKey)}|${timeoutAfterSeconds ?? ""}${offlineDataKeyPart(offlineData)}`, [
|
|
82
|
+
service,
|
|
83
|
+
method,
|
|
84
|
+
onlinePath,
|
|
85
|
+
pathParamsKey,
|
|
86
|
+
queryParamsKey,
|
|
87
|
+
bodyKey,
|
|
88
|
+
timeoutAfterSeconds,
|
|
89
|
+
offlineData,
|
|
90
|
+
]);
|
|
91
|
+
const reconnectSemanticKey = (0, react_1.useMemo)(() => dataLoaderReconnectSemanticKey(service, method, onlinePath, pathParamsKey, bodyKey, queryParams, queryParamsKey), [
|
|
92
|
+
service,
|
|
93
|
+
method,
|
|
94
|
+
onlinePath,
|
|
95
|
+
pathParamsKey,
|
|
96
|
+
bodyKey,
|
|
97
|
+
queryParams,
|
|
98
|
+
queryParamsKey,
|
|
99
|
+
]);
|
|
100
|
+
const reload = (0, react_1.useCallback)(() => {
|
|
101
|
+
if (isOnline === false)
|
|
102
|
+
return;
|
|
103
|
+
pendingReloadRef.current = true;
|
|
104
|
+
setReloadTick((n) => n + 1);
|
|
105
|
+
}, [isOnline]);
|
|
70
106
|
const lastRequestKeyRef = (0, react_1.useRef)("");
|
|
107
|
+
/** `offlineData` object — immediate `data`, no network. */
|
|
108
|
+
(0, react_1.useEffect)(() => {
|
|
109
|
+
if (offlineData === undefined) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
setData(offlineData);
|
|
113
|
+
setErrors(null);
|
|
114
|
+
hasCommittedRef.current = true;
|
|
115
|
+
dirtyWhileOfflineRef.current = false;
|
|
116
|
+
semanticSnapshotRef.current = null;
|
|
117
|
+
}, [offlineData]);
|
|
71
118
|
(0, react_1.useEffect)(() => {
|
|
72
119
|
const online = isOnline !== false;
|
|
73
120
|
const prevOnline = prevIsOnlineRef.current;
|
|
121
|
+
const enteringOffline = prevOnline === true && !online;
|
|
74
122
|
const reconnecting = prevOnline === false && online;
|
|
123
|
+
if (enteringOffline) {
|
|
124
|
+
dirtyWhileOfflineRef.current = false;
|
|
125
|
+
semanticSnapshotRef.current = reconnectSemanticKey;
|
|
126
|
+
}
|
|
127
|
+
if (!online && prevOnline !== undefined) {
|
|
128
|
+
if (semanticSnapshotRef.current != null &&
|
|
129
|
+
reconnectSemanticKey !== semanticSnapshotRef.current) {
|
|
130
|
+
dirtyWhileOfflineRef.current = true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Object `offlineData`: dedicated effect owns `data`; never hit the network here. */
|
|
134
|
+
if (offlineData !== undefined) {
|
|
135
|
+
prevIsOnlineRef.current = online;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
75
138
|
const keyChanged = lastRequestKeyRef.current !== requestKey;
|
|
76
139
|
const isManualReload = pendingReloadRef.current;
|
|
77
140
|
if (isManualReload) {
|
|
@@ -82,30 +145,30 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
82
145
|
if (keyChanged) {
|
|
83
146
|
lastRequestKeyRef.current = requestKey;
|
|
84
147
|
setData(null);
|
|
85
|
-
|
|
148
|
+
hasCommittedRef.current = false;
|
|
86
149
|
setErrors(null);
|
|
87
150
|
}
|
|
88
151
|
prevIsOnlineRef.current = false;
|
|
89
|
-
setLoading(false);
|
|
90
152
|
setErrors(new Error(network_1.NO_NETWORK_MESSAGE));
|
|
91
153
|
setTimeoutCountdown(null);
|
|
92
154
|
return;
|
|
93
155
|
}
|
|
94
156
|
if (keyChanged) {
|
|
95
157
|
lastRequestKeyRef.current = requestKey;
|
|
96
|
-
|
|
158
|
+
hasCommittedRef.current = false;
|
|
97
159
|
setData(null);
|
|
98
160
|
setErrors(null);
|
|
99
161
|
}
|
|
100
162
|
if (!keyChanged && reconnecting) {
|
|
101
163
|
const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
|
|
102
|
-
|
|
103
|
-
hasCommittedRef.current
|
|
104
|
-
onlyNoNetwork
|
|
105
|
-
|
|
164
|
+
const shouldRefetchAfterReconnect = dirtyWhileOfflineRef.current ||
|
|
165
|
+
!hasCommittedRef.current ||
|
|
166
|
+
!onlyNoNetwork;
|
|
167
|
+
if (!isManualReload && !shouldRefetchAfterReconnect) {
|
|
106
168
|
setErrors(null);
|
|
107
|
-
setLoading(false);
|
|
108
169
|
prevIsOnlineRef.current = true;
|
|
170
|
+
dirtyWhileOfflineRef.current = false;
|
|
171
|
+
semanticSnapshotRef.current = null;
|
|
109
172
|
return;
|
|
110
173
|
}
|
|
111
174
|
}
|
|
@@ -115,15 +178,14 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
115
178
|
const timedOutRef = { current: false };
|
|
116
179
|
const requestStartedAt = Date.now();
|
|
117
180
|
const timeoutMs = (0, network_1.resolveRequestTimeoutMs)(timeoutAfterSeconds);
|
|
118
|
-
setLoading(true);
|
|
119
181
|
setErrors(null);
|
|
120
182
|
setTimeoutCountdown(null);
|
|
121
|
-
const
|
|
183
|
+
const keepStaleForManualReload = isManualReload && hasCommittedRef.current;
|
|
184
|
+
const keepStaleDuringReconnectRefetch = reconnecting &&
|
|
122
185
|
hasCommittedRef.current &&
|
|
123
186
|
errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (!keyChanged && !keepStaleDuringFetch && !keepStaleForManualReload) {
|
|
187
|
+
dirtyWhileOfflineRef.current;
|
|
188
|
+
if (!keyChanged && !keepStaleForManualReload && !keepStaleDuringReconnectRefetch) {
|
|
127
189
|
setData(null);
|
|
128
190
|
}
|
|
129
191
|
const policyDispose = timeoutMs == null
|
|
@@ -144,7 +206,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
144
206
|
},
|
|
145
207
|
});
|
|
146
208
|
const baseUrl = exports.SERVICE_BASE_URL[service];
|
|
147
|
-
const url = buildUrl(baseUrl,
|
|
209
|
+
const url = buildUrl(baseUrl, onlinePath, onlinePathParams, queryParams);
|
|
148
210
|
const init = {
|
|
149
211
|
method,
|
|
150
212
|
headers: {
|
|
@@ -163,13 +225,15 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
163
225
|
if (!res.ok) {
|
|
164
226
|
setErrors(new Error((0, network_1.formatHttpStatusMessage)(res.status, text || res.statusText)));
|
|
165
227
|
setData(null);
|
|
166
|
-
|
|
228
|
+
hasCommittedRef.current = false;
|
|
167
229
|
return;
|
|
168
230
|
}
|
|
169
231
|
if (text.length === 0) {
|
|
170
232
|
setData(null);
|
|
171
233
|
setErrors(null);
|
|
172
|
-
|
|
234
|
+
hasCommittedRef.current = true;
|
|
235
|
+
dirtyWhileOfflineRef.current = false;
|
|
236
|
+
semanticSnapshotRef.current = null;
|
|
173
237
|
return;
|
|
174
238
|
}
|
|
175
239
|
try {
|
|
@@ -178,20 +242,26 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
178
242
|
if (!cancelled) {
|
|
179
243
|
setData(parsed.result);
|
|
180
244
|
setErrors(null);
|
|
181
|
-
|
|
245
|
+
hasCommittedRef.current = true;
|
|
246
|
+
dirtyWhileOfflineRef.current = false;
|
|
247
|
+
semanticSnapshotRef.current = null;
|
|
182
248
|
}
|
|
183
249
|
}
|
|
184
250
|
catch (parseError) {
|
|
185
251
|
if (!cancelled) {
|
|
186
|
-
console.error("[
|
|
252
|
+
console.error("[RopeGeoDataLoader] Invalid JSON response", {
|
|
187
253
|
url,
|
|
188
254
|
status: res.status,
|
|
189
255
|
responseText: text.slice(0, 500),
|
|
190
|
-
parseError: parseError instanceof Error
|
|
256
|
+
parseError: parseError instanceof Error
|
|
257
|
+
? parseError.message
|
|
258
|
+
: String(parseError),
|
|
191
259
|
});
|
|
192
|
-
setErrors(parseError instanceof Error
|
|
260
|
+
setErrors(parseError instanceof Error
|
|
261
|
+
? parseError
|
|
262
|
+
: new Error("Invalid JSON response"));
|
|
193
263
|
setData(null);
|
|
194
|
-
|
|
264
|
+
hasCommittedRef.current = false;
|
|
195
265
|
}
|
|
196
266
|
}
|
|
197
267
|
})
|
|
@@ -201,24 +271,23 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
201
271
|
if (timedOutRef.current) {
|
|
202
272
|
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE))));
|
|
203
273
|
setData(null);
|
|
204
|
-
|
|
274
|
+
hasCommittedRef.current = false;
|
|
205
275
|
return;
|
|
206
276
|
}
|
|
207
277
|
if ((0, network_1.isAbortError)(err))
|
|
208
278
|
return;
|
|
209
|
-
console.error("[
|
|
279
|
+
console.error("[RopeGeoDataLoader] Request failed", {
|
|
210
280
|
url,
|
|
211
281
|
error: err instanceof Error ? err.message : String(err),
|
|
212
282
|
});
|
|
213
283
|
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(err)));
|
|
214
284
|
setData(null);
|
|
215
|
-
|
|
285
|
+
hasCommittedRef.current = false;
|
|
216
286
|
})
|
|
217
287
|
.finally(() => {
|
|
218
288
|
policyDispose();
|
|
219
289
|
if (!cancelled) {
|
|
220
290
|
setTimeoutCountdown(null);
|
|
221
|
-
setLoading(false);
|
|
222
291
|
}
|
|
223
292
|
});
|
|
224
293
|
return () => {
|
|
@@ -229,20 +298,19 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
229
298
|
}, [
|
|
230
299
|
service,
|
|
231
300
|
method,
|
|
232
|
-
|
|
301
|
+
onlinePath,
|
|
233
302
|
pathParamsKey,
|
|
234
303
|
queryParamsKey,
|
|
235
304
|
bodyKey,
|
|
236
305
|
timeoutAfterSeconds,
|
|
237
306
|
isOnline,
|
|
238
|
-
refreshOnReconnect,
|
|
239
307
|
requestKey,
|
|
240
308
|
reloadTick,
|
|
309
|
+
offlineData,
|
|
310
|
+
reconnectSemanticKey,
|
|
311
|
+
queryParams,
|
|
241
312
|
]);
|
|
242
|
-
const refreshing = loading && hasCommittedOnce;
|
|
243
313
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
|
|
244
|
-
loading,
|
|
245
|
-
refreshing,
|
|
246
314
|
data,
|
|
247
315
|
errors,
|
|
248
316
|
timeoutCountdown,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { type CursorPaginationParams } from "../models";
|
|
3
|
+
import { Method, Service } from "./RopeGeoDataLoader";
|
|
4
|
+
export type RopeGeoPagedDataLoaderProps<T = unknown> = {
|
|
5
|
+
service: Service;
|
|
6
|
+
method?: (typeof Method)[keyof typeof Method];
|
|
7
|
+
onlinePath: string;
|
|
8
|
+
onlinePathParams?: Record<string, string>;
|
|
9
|
+
queryParams: CursorPaginationParams;
|
|
10
|
+
timeoutAfterSeconds?: number;
|
|
11
|
+
isOnline?: boolean;
|
|
12
|
+
children: (args: {
|
|
13
|
+
loadingNextPage: boolean;
|
|
14
|
+
data: T[] | null;
|
|
15
|
+
errors: Error | null;
|
|
16
|
+
loadNextPage: () => void;
|
|
17
|
+
morePages: boolean;
|
|
18
|
+
timeoutCountdown: number | null;
|
|
19
|
+
reload: () => void;
|
|
20
|
+
}) => ReactNode;
|
|
21
|
+
};
|
|
22
|
+
export declare function RopeGeoPagedDataLoader<T = unknown>({ service, method, onlinePath, onlinePathParams, queryParams, timeoutAfterSeconds, isOnline, children, }: RopeGeoPagedDataLoaderProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=RopeGeoPagedDataLoader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RopeGeoPagedDataLoader.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoPagedDataLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAWvC,OAAO,EACL,KAAK,sBAAsB,EAE5B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAoB,MAAM,qBAAqB,CAAC;AAqCxE,MAAM,MAAM,2BAA2B,CAAC,CAAC,GAAG,OAAO,IAAI;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,WAAW,EAAE,sBAAsB,CAAC;IACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,eAAe,EAAE,OAAO,CAAC;QACzB,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB,YAAY,EAAE,MAAM,IAAI,CAAC;QACzB,SAAS,EAAE,OAAO,CAAC;QACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,KAAK,SAAS,CAAC;CACjB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,EAClD,OAAO,EACP,MAAmB,EACnB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,QAAQ,GACT,EAAE,2BAA2B,CAAC,CAAC,CAAC,2CAsahC"}
|