rastack 0.0.16 → 0.0.19
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/CHANGELOG.md +43874 -43013
- package/dist/.prettierrc +7 -7
- package/dist/compile/analyze.js +19 -11
- package/dist/compile/index.js +26 -17
- package/dist/compile/manifest.js +2 -3
- package/dist/compile/openapi.js +5 -8
- package/dist/compile/program.js +19 -10
- package/dist/csv-schema.js +5 -6
- package/dist/define/index.js +2 -2
- package/dist/entity-generation/delete-method.js +8 -10
- package/dist/entity-generation/form.js +80 -82
- package/dist/entity-generation/get-method.js +35 -36
- package/dist/entity-generation/imports.js +24 -20
- package/dist/entity-generation/sync-method.d.ts +1 -1
- package/dist/entity-generation/sync-method.js +45 -46
- package/dist/entity-generation/update-method.js +9 -10
- package/dist/rad-wasm-build.d.ts +1 -1
- package/dist/rad-wasm-build.js +15 -6
- package/dist/rad.js +9 -2
- package/dist/schema/camel-to-pastel.js +1 -2
- package/dist/schema/capitalise-first-letter.js +1 -2
- package/dist/schema/extract-response.js +3 -4
- package/dist/schema/fetch-schema.js +4 -16
- package/dist/schema/remove-non-model-paths.js +1 -2
- package/dist/schema/to-camel-case.js +1 -2
- package/dist/schema/to-pastel-case.js +1 -2
- package/dist/schema-convert.js +22 -33
- package/dist/schema-entities.js +177 -189
- package/dist/schema-fetch.js +46 -63
- package/dist/schema-full.js +23 -36
- package/dist/schema-index.js +16 -27
- package/dist/schema-params.js +11 -22
- package/dist/seed.js +95 -97
- package/hooks/form/form.ts +207 -207
- package/hooks/form/index.ts +8 -8
- package/hooks/form/interfaces.ts +217 -217
- package/hooks/form/structure.ts +39 -39
- package/hooks/form/validate-schema.ts +49 -49
- package/hooks/index.ts +3 -3
- package/hooks/query/api.ts +42 -42
- package/hooks/query/delete.ts +45 -45
- package/hooks/query/fetch.ts +48 -48
- package/hooks/query/index.ts +21 -21
- package/hooks/query/interfaces.ts +111 -111
- package/hooks/query/list.ts +286 -286
- package/hooks/query/update.ts +88 -88
- package/hooks/query/url.ts +31 -31
- package/hooks/real-time/index.ts +1 -1
- package/hooks/real-time/pusher.ts +43 -43
- package/jest.config.cjs +6 -6
- package/package.json +57 -57
- package/provider/index.ts +13 -13
- package/provider/provider.tsx +187 -187
- package/provider/types.ts +114 -114
- package/provider/warehouse.ts +167 -167
- package/provider/wasm.ts +124 -124
- package/runtime.ts +3 -3
- package/src/.prettierrc +7 -7
- package/src/compile/analyze.ts +224 -224
- package/src/compile/index.ts +86 -86
- package/src/compile/manifest.ts +10 -10
- package/src/compile/model.ts +69 -69
- package/src/compile/openapi.ts +266 -266
- package/src/compile/program.ts +40 -40
- package/src/csv-schema.ts +187 -187
- package/src/define/index.ts +162 -162
- package/src/entity-generation/delete-method.ts +37 -37
- package/src/entity-generation/form.ts +169 -169
- package/src/entity-generation/get-method.ts +80 -80
- package/src/entity-generation/imports.ts +110 -110
- package/src/entity-generation/sync-method.ts +222 -222
- package/src/entity-generation/update-method.ts +38 -38
- package/src/index.ts +77 -77
- package/src/rad-compile.ts +88 -88
- package/src/rad-wasm-build.ts +102 -102
- package/src/rad.ts +101 -101
- package/src/scan.ts +89 -89
- package/src/schema/camel-to-pastel.ts +3 -3
- package/src/schema/capitalise-first-letter.ts +3 -3
- package/src/schema/extract-response.ts +38 -38
- package/src/schema/fetch-schema.ts +12 -12
- package/src/schema/remove-non-model-paths.ts +13 -13
- package/src/schema/to-camel-case.ts +7 -7
- package/src/schema/to-pastel-case.ts +6 -6
- package/src/schema-convert.ts +61 -61
- package/src/schema-entities.ts +401 -401
- package/src/schema-fetch.ts +82 -82
- package/src/schema-full.ts +38 -38
- package/src/schema-index.ts +29 -29
- package/src/schema-params.ts +116 -116
- package/src/seed.ts +297 -297
- package/sync/engine.ts +392 -392
- package/sync/hooks.ts +450 -450
- package/sync/index.ts +8 -8
- package/sync/persistence.ts +237 -237
- package/sync/provider.tsx +91 -91
- package/sync/registry.ts +36 -36
- package/sync/store.ts +126 -126
- package/sync/transactions.ts +300 -300
- package/sync/types.ts +94 -94
- package/test/compile.spec.ts +192 -192
- package/test/csv-schema.spec.ts +143 -143
- package/test/schema-entities.spec.ts +688 -688
- package/tsconfig.json +24 -24
- package/types.ts +18 -18
package/hooks/query/list.ts
CHANGED
|
@@ -1,286 +1,286 @@
|
|
|
1
|
-
import { AxiosResponse } from "axios";
|
|
2
|
-
import { useQuery } from "react-query";
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
4
|
-
import {
|
|
5
|
-
IFilterActions,
|
|
6
|
-
IListQuery,
|
|
7
|
-
IPaginatedResponse,
|
|
8
|
-
IPaginationActions,
|
|
9
|
-
ISearchingActions,
|
|
10
|
-
ISortingActions,
|
|
11
|
-
ListQueryOptions,
|
|
12
|
-
NormalizedField,
|
|
13
|
-
} from "./interfaces";
|
|
14
|
-
import { stringifyQueryParams } from "./url";
|
|
15
|
-
import { useDebounceValue } from "usehooks-ts";
|
|
16
|
-
import { API } from "./api";
|
|
17
|
-
import { ExtractKey } from "../../types";
|
|
18
|
-
|
|
19
|
-
export interface GetPaginatedQueryListProps<TParam, TResult> {
|
|
20
|
-
postUrl?: string;
|
|
21
|
-
getUrl?: string;
|
|
22
|
-
queryKey: string;
|
|
23
|
-
pathParameters: (keyof TParam)[];
|
|
24
|
-
isAuthenticated: boolean;
|
|
25
|
-
options?: ListQueryOptions<TParam, TResult>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function useGetPaginatedQueryList<TParam, TResult>({
|
|
29
|
-
postUrl,
|
|
30
|
-
getUrl,
|
|
31
|
-
queryKey,
|
|
32
|
-
pathParameters,
|
|
33
|
-
isAuthenticated,
|
|
34
|
-
options,
|
|
35
|
-
}: GetPaginatedQueryListProps<TParam, TResult>): IListQuery<TParam, TResult> {
|
|
36
|
-
const [searchText, setSearchText] = useState<string | undefined>(undefined);
|
|
37
|
-
const [serverSearchText, setServerSearchText] = useDebounceValue<
|
|
38
|
-
string | undefined
|
|
39
|
-
>(undefined, 500);
|
|
40
|
-
|
|
41
|
-
const [queryParamState, setQueryParamState] = useState({
|
|
42
|
-
page: 1,
|
|
43
|
-
page_size: options?.pageSize ? options?.pageSize : 20,
|
|
44
|
-
order_by: options?.defaultSortFields ?? [],
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const pageParams = ["page", "page_size"] as unknown as (keyof TParam)[];
|
|
48
|
-
const requiredParams = options?.requiredParams
|
|
49
|
-
? [...options.requiredParams, ...pageParams]
|
|
50
|
-
: pageParams;
|
|
51
|
-
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
if (!options?.localCache) {
|
|
54
|
-
setServerSearchText(searchText);
|
|
55
|
-
}
|
|
56
|
-
}, [searchText]);
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
if (options?.searchKey) {
|
|
60
|
-
setQueryParamState((current) => ({
|
|
61
|
-
...current,
|
|
62
|
-
page: 1,
|
|
63
|
-
[options?.searchKey as string]: serverSearchText,
|
|
64
|
-
}));
|
|
65
|
-
}
|
|
66
|
-
}, [serverSearchText]);
|
|
67
|
-
|
|
68
|
-
const serverQueryParamState = {
|
|
69
|
-
...queryParamState,
|
|
70
|
-
...options?.params,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const isRequiredQueryParamsPresent = requiredParams?.every(
|
|
74
|
-
// @ts-ignore Pre Validation of page, page_size and order_by will happen when the two hooks are combined
|
|
75
|
-
(param) => serverQueryParamState[param] !== undefined,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
const fetchDataForAllPages = async (
|
|
79
|
-
currentPage: number = 1,
|
|
80
|
-
accumulatedData: TResult[] = [],
|
|
81
|
-
): Promise<IPaginatedResponse<TResult>> => {
|
|
82
|
-
const serverURL = `${getUrl}?${stringifyQueryParams(pathParameters, {
|
|
83
|
-
...serverQueryParamState,
|
|
84
|
-
// @ts-ignore Pre Validation of page, page_size and order_by will happen when the two hooks are combined
|
|
85
|
-
page: currentPage,
|
|
86
|
-
})}`;
|
|
87
|
-
|
|
88
|
-
const response: AxiosResponse<IPaginatedResponse<TResult>> = postUrl
|
|
89
|
-
? await API.post(postUrl, serverQueryParamState)
|
|
90
|
-
: await API.get(serverURL);
|
|
91
|
-
|
|
92
|
-
// @ts-ignore This will be resolved when the List and Get endpoints will be merged
|
|
93
|
-
const newData = response.data.results;
|
|
94
|
-
|
|
95
|
-
const mergedData = [...accumulatedData, ...newData];
|
|
96
|
-
|
|
97
|
-
if (currentPage < response.data.pagination.last) {
|
|
98
|
-
return fetchDataForAllPages(currentPage + 1, mergedData);
|
|
99
|
-
} else {
|
|
100
|
-
return {
|
|
101
|
-
...response.data,
|
|
102
|
-
pagination: {
|
|
103
|
-
current: 1,
|
|
104
|
-
last: 1,
|
|
105
|
-
next: 1,
|
|
106
|
-
previous: 1,
|
|
107
|
-
page_size: mergedData.length,
|
|
108
|
-
count: mergedData.length,
|
|
109
|
-
},
|
|
110
|
-
results: mergedData,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const fetchData = async () => {
|
|
116
|
-
if (options?.localCache) {
|
|
117
|
-
return fetchDataForAllPages();
|
|
118
|
-
} else {
|
|
119
|
-
// @ts-ignore Pre Validation of page, page_size and order_by will happen when the two hooks are combined
|
|
120
|
-
const serverURL = `${getUrl}?${stringifyQueryParams(pathParameters, serverQueryParamState)}`;
|
|
121
|
-
const response: AxiosResponse<IPaginatedResponse<TResult>> = postUrl
|
|
122
|
-
? await API.post(postUrl, serverQueryParamState)
|
|
123
|
-
: await API.get(serverURL);
|
|
124
|
-
return response.data;
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const query = useQuery<IPaginatedResponse<TResult>>(
|
|
129
|
-
[queryKey, getUrl, options?.params, serverQueryParamState],
|
|
130
|
-
fetchData,
|
|
131
|
-
{
|
|
132
|
-
enabled: isRequiredQueryParamsPresent && isAuthenticated,
|
|
133
|
-
onSuccess: options?.onSuccess,
|
|
134
|
-
},
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const pageCount = query.data?.pagination?.last || 0;
|
|
138
|
-
const itemCount = query.data?.pagination?.count || 0;
|
|
139
|
-
|
|
140
|
-
function previousPage() {
|
|
141
|
-
if (queryParamState.page) {
|
|
142
|
-
const previousPage = (queryParamState.page as unknown as number) - 1;
|
|
143
|
-
setQueryParamState((current) => ({
|
|
144
|
-
...current,
|
|
145
|
-
page: previousPage < 1 ? 1 : previousPage,
|
|
146
|
-
}));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function nextPage() {
|
|
151
|
-
if (queryParamState.page) {
|
|
152
|
-
const nextPage = (queryParamState.page as unknown as number) + 1;
|
|
153
|
-
setQueryParamState((current) => ({
|
|
154
|
-
...current,
|
|
155
|
-
page: nextPage > pageCount ? pageCount : nextPage,
|
|
156
|
-
}));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function setPageSize(pageSize: number) {
|
|
161
|
-
setQueryParamState((current) => ({
|
|
162
|
-
...current,
|
|
163
|
-
page_size: pageSize,
|
|
164
|
-
}));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const pagination: IPaginationActions = {
|
|
168
|
-
previousPage,
|
|
169
|
-
nextPage,
|
|
170
|
-
currentPage: serverQueryParamState.page,
|
|
171
|
-
pageSize: serverQueryParamState.page_size,
|
|
172
|
-
pageCount,
|
|
173
|
-
itemCount,
|
|
174
|
-
setPageSize,
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const searching: ISearchingActions<TParam> = {
|
|
178
|
-
searchText,
|
|
179
|
-
setSearchText,
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
function sortField(field: NormalizedField<ExtractKey<TParam, "order_by">>) {
|
|
183
|
-
setQueryParamState((current) => {
|
|
184
|
-
const ascendingField = current.order_by?.find((item) => item === field);
|
|
185
|
-
const descendingField = current.order_by?.find(
|
|
186
|
-
(item) => item === `-${field}`,
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
let result: (string & ExtractKey<TParam, "order_by">)[] | undefined = [];
|
|
190
|
-
if (descendingField) {
|
|
191
|
-
result = current.order_by?.filter((item) => item !== `-${field}`);
|
|
192
|
-
} else if (ascendingField) {
|
|
193
|
-
result = current.order_by?.filter((item) => item !== field);
|
|
194
|
-
result?.push(`-${field}` as string & ExtractKey<TParam, "order_by">);
|
|
195
|
-
} else {
|
|
196
|
-
result = current.order_by
|
|
197
|
-
? [
|
|
198
|
-
...current.order_by,
|
|
199
|
-
field as string & ExtractKey<TParam, "order_by">,
|
|
200
|
-
]
|
|
201
|
-
: [field as string & ExtractKey<TParam, "order_by">];
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
...current,
|
|
206
|
-
order_by: result,
|
|
207
|
-
page: 1,
|
|
208
|
-
};
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function getSortingDirection(
|
|
213
|
-
field: NormalizedField<ExtractKey<TParam, "order_by">>,
|
|
214
|
-
) {
|
|
215
|
-
const invertedField = `-${field}`;
|
|
216
|
-
if (serverQueryParamState.order_by?.find((item) => item === field)) {
|
|
217
|
-
return "asc";
|
|
218
|
-
} else if (
|
|
219
|
-
serverQueryParamState.order_by?.find((item) => item === invertedField)
|
|
220
|
-
) {
|
|
221
|
-
return "desc";
|
|
222
|
-
} else {
|
|
223
|
-
return undefined;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const sorting: ISortingActions<TParam> = {
|
|
228
|
-
sortField,
|
|
229
|
-
getSortingDirection,
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
function getFilterFieldValue(key: keyof TParam) {
|
|
233
|
-
// @ts-ignore correctly handle the keyof in the future
|
|
234
|
-
return queryParamState[key] as TParam[keyof TParam];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function setFilterFieldValue(key: keyof TParam) {
|
|
238
|
-
return (value: unknown) => {
|
|
239
|
-
setQueryParamState((current) => ({
|
|
240
|
-
...current,
|
|
241
|
-
[key]: value,
|
|
242
|
-
page: 1,
|
|
243
|
-
}));
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const filtering: IFilterActions<TParam> = {
|
|
248
|
-
getFilterFieldValue,
|
|
249
|
-
setFilterFieldValue,
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
const data =
|
|
253
|
-
options?.localCache && searchText
|
|
254
|
-
? // @ts-ignore the results key is based on the interface returned. This will get sorted out in a future version
|
|
255
|
-
query.data?.results.filter((value: any) => {
|
|
256
|
-
if (options.localSearchFunction && searchText) {
|
|
257
|
-
if (searchText.includes(" ")) {
|
|
258
|
-
const searchWords = searchText.split(" ");
|
|
259
|
-
return searchWords.every((word) => {
|
|
260
|
-
if (options.localSearchFunction) {
|
|
261
|
-
return options.localSearchFunction(word, value);
|
|
262
|
-
} else {
|
|
263
|
-
return false;
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
} else {
|
|
267
|
-
return options.localSearchFunction(searchText, value);
|
|
268
|
-
}
|
|
269
|
-
} else {
|
|
270
|
-
return true;
|
|
271
|
-
}
|
|
272
|
-
})
|
|
273
|
-
: // @ts-ignore
|
|
274
|
-
query.data?.results;
|
|
275
|
-
|
|
276
|
-
return {
|
|
277
|
-
...query,
|
|
278
|
-
raw: query.data,
|
|
279
|
-
data,
|
|
280
|
-
header: query.data?.headers,
|
|
281
|
-
pagination,
|
|
282
|
-
searching,
|
|
283
|
-
sorting,
|
|
284
|
-
filtering,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
1
|
+
import { AxiosResponse } from "axios";
|
|
2
|
+
import { useQuery } from "react-query";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import {
|
|
5
|
+
IFilterActions,
|
|
6
|
+
IListQuery,
|
|
7
|
+
IPaginatedResponse,
|
|
8
|
+
IPaginationActions,
|
|
9
|
+
ISearchingActions,
|
|
10
|
+
ISortingActions,
|
|
11
|
+
ListQueryOptions,
|
|
12
|
+
NormalizedField,
|
|
13
|
+
} from "./interfaces";
|
|
14
|
+
import { stringifyQueryParams } from "./url";
|
|
15
|
+
import { useDebounceValue } from "usehooks-ts";
|
|
16
|
+
import { API } from "./api";
|
|
17
|
+
import { ExtractKey } from "../../types";
|
|
18
|
+
|
|
19
|
+
export interface GetPaginatedQueryListProps<TParam, TResult> {
|
|
20
|
+
postUrl?: string;
|
|
21
|
+
getUrl?: string;
|
|
22
|
+
queryKey: string;
|
|
23
|
+
pathParameters: (keyof TParam)[];
|
|
24
|
+
isAuthenticated: boolean;
|
|
25
|
+
options?: ListQueryOptions<TParam, TResult>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function useGetPaginatedQueryList<TParam, TResult>({
|
|
29
|
+
postUrl,
|
|
30
|
+
getUrl,
|
|
31
|
+
queryKey,
|
|
32
|
+
pathParameters,
|
|
33
|
+
isAuthenticated,
|
|
34
|
+
options,
|
|
35
|
+
}: GetPaginatedQueryListProps<TParam, TResult>): IListQuery<TParam, TResult> {
|
|
36
|
+
const [searchText, setSearchText] = useState<string | undefined>(undefined);
|
|
37
|
+
const [serverSearchText, setServerSearchText] = useDebounceValue<
|
|
38
|
+
string | undefined
|
|
39
|
+
>(undefined, 500);
|
|
40
|
+
|
|
41
|
+
const [queryParamState, setQueryParamState] = useState({
|
|
42
|
+
page: 1,
|
|
43
|
+
page_size: options?.pageSize ? options?.pageSize : 20,
|
|
44
|
+
order_by: options?.defaultSortFields ?? [],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const pageParams = ["page", "page_size"] as unknown as (keyof TParam)[];
|
|
48
|
+
const requiredParams = options?.requiredParams
|
|
49
|
+
? [...options.requiredParams, ...pageParams]
|
|
50
|
+
: pageParams;
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!options?.localCache) {
|
|
54
|
+
setServerSearchText(searchText);
|
|
55
|
+
}
|
|
56
|
+
}, [searchText]);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (options?.searchKey) {
|
|
60
|
+
setQueryParamState((current) => ({
|
|
61
|
+
...current,
|
|
62
|
+
page: 1,
|
|
63
|
+
[options?.searchKey as string]: serverSearchText,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
}, [serverSearchText]);
|
|
67
|
+
|
|
68
|
+
const serverQueryParamState = {
|
|
69
|
+
...queryParamState,
|
|
70
|
+
...options?.params,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const isRequiredQueryParamsPresent = requiredParams?.every(
|
|
74
|
+
// @ts-ignore Pre Validation of page, page_size and order_by will happen when the two hooks are combined
|
|
75
|
+
(param) => serverQueryParamState[param] !== undefined,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const fetchDataForAllPages = async (
|
|
79
|
+
currentPage: number = 1,
|
|
80
|
+
accumulatedData: TResult[] = [],
|
|
81
|
+
): Promise<IPaginatedResponse<TResult>> => {
|
|
82
|
+
const serverURL = `${getUrl}?${stringifyQueryParams(pathParameters, {
|
|
83
|
+
...serverQueryParamState,
|
|
84
|
+
// @ts-ignore Pre Validation of page, page_size and order_by will happen when the two hooks are combined
|
|
85
|
+
page: currentPage,
|
|
86
|
+
})}`;
|
|
87
|
+
|
|
88
|
+
const response: AxiosResponse<IPaginatedResponse<TResult>> = postUrl
|
|
89
|
+
? await API.post(postUrl, serverQueryParamState)
|
|
90
|
+
: await API.get(serverURL);
|
|
91
|
+
|
|
92
|
+
// @ts-ignore This will be resolved when the List and Get endpoints will be merged
|
|
93
|
+
const newData = response.data.results;
|
|
94
|
+
|
|
95
|
+
const mergedData = [...accumulatedData, ...newData];
|
|
96
|
+
|
|
97
|
+
if (currentPage < response.data.pagination.last) {
|
|
98
|
+
return fetchDataForAllPages(currentPage + 1, mergedData);
|
|
99
|
+
} else {
|
|
100
|
+
return {
|
|
101
|
+
...response.data,
|
|
102
|
+
pagination: {
|
|
103
|
+
current: 1,
|
|
104
|
+
last: 1,
|
|
105
|
+
next: 1,
|
|
106
|
+
previous: 1,
|
|
107
|
+
page_size: mergedData.length,
|
|
108
|
+
count: mergedData.length,
|
|
109
|
+
},
|
|
110
|
+
results: mergedData,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const fetchData = async () => {
|
|
116
|
+
if (options?.localCache) {
|
|
117
|
+
return fetchDataForAllPages();
|
|
118
|
+
} else {
|
|
119
|
+
// @ts-ignore Pre Validation of page, page_size and order_by will happen when the two hooks are combined
|
|
120
|
+
const serverURL = `${getUrl}?${stringifyQueryParams(pathParameters, serverQueryParamState)}`;
|
|
121
|
+
const response: AxiosResponse<IPaginatedResponse<TResult>> = postUrl
|
|
122
|
+
? await API.post(postUrl, serverQueryParamState)
|
|
123
|
+
: await API.get(serverURL);
|
|
124
|
+
return response.data;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const query = useQuery<IPaginatedResponse<TResult>>(
|
|
129
|
+
[queryKey, getUrl, options?.params, serverQueryParamState],
|
|
130
|
+
fetchData,
|
|
131
|
+
{
|
|
132
|
+
enabled: isRequiredQueryParamsPresent && isAuthenticated,
|
|
133
|
+
onSuccess: options?.onSuccess,
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const pageCount = query.data?.pagination?.last || 0;
|
|
138
|
+
const itemCount = query.data?.pagination?.count || 0;
|
|
139
|
+
|
|
140
|
+
function previousPage() {
|
|
141
|
+
if (queryParamState.page) {
|
|
142
|
+
const previousPage = (queryParamState.page as unknown as number) - 1;
|
|
143
|
+
setQueryParamState((current) => ({
|
|
144
|
+
...current,
|
|
145
|
+
page: previousPage < 1 ? 1 : previousPage,
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function nextPage() {
|
|
151
|
+
if (queryParamState.page) {
|
|
152
|
+
const nextPage = (queryParamState.page as unknown as number) + 1;
|
|
153
|
+
setQueryParamState((current) => ({
|
|
154
|
+
...current,
|
|
155
|
+
page: nextPage > pageCount ? pageCount : nextPage,
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function setPageSize(pageSize: number) {
|
|
161
|
+
setQueryParamState((current) => ({
|
|
162
|
+
...current,
|
|
163
|
+
page_size: pageSize,
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const pagination: IPaginationActions = {
|
|
168
|
+
previousPage,
|
|
169
|
+
nextPage,
|
|
170
|
+
currentPage: serverQueryParamState.page,
|
|
171
|
+
pageSize: serverQueryParamState.page_size,
|
|
172
|
+
pageCount,
|
|
173
|
+
itemCount,
|
|
174
|
+
setPageSize,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const searching: ISearchingActions<TParam> = {
|
|
178
|
+
searchText,
|
|
179
|
+
setSearchText,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
function sortField(field: NormalizedField<ExtractKey<TParam, "order_by">>) {
|
|
183
|
+
setQueryParamState((current) => {
|
|
184
|
+
const ascendingField = current.order_by?.find((item) => item === field);
|
|
185
|
+
const descendingField = current.order_by?.find(
|
|
186
|
+
(item) => item === `-${field}`,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
let result: (string & ExtractKey<TParam, "order_by">)[] | undefined = [];
|
|
190
|
+
if (descendingField) {
|
|
191
|
+
result = current.order_by?.filter((item) => item !== `-${field}`);
|
|
192
|
+
} else if (ascendingField) {
|
|
193
|
+
result = current.order_by?.filter((item) => item !== field);
|
|
194
|
+
result?.push(`-${field}` as string & ExtractKey<TParam, "order_by">);
|
|
195
|
+
} else {
|
|
196
|
+
result = current.order_by
|
|
197
|
+
? [
|
|
198
|
+
...current.order_by,
|
|
199
|
+
field as string & ExtractKey<TParam, "order_by">,
|
|
200
|
+
]
|
|
201
|
+
: [field as string & ExtractKey<TParam, "order_by">];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
...current,
|
|
206
|
+
order_by: result,
|
|
207
|
+
page: 1,
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getSortingDirection(
|
|
213
|
+
field: NormalizedField<ExtractKey<TParam, "order_by">>,
|
|
214
|
+
) {
|
|
215
|
+
const invertedField = `-${field}`;
|
|
216
|
+
if (serverQueryParamState.order_by?.find((item) => item === field)) {
|
|
217
|
+
return "asc";
|
|
218
|
+
} else if (
|
|
219
|
+
serverQueryParamState.order_by?.find((item) => item === invertedField)
|
|
220
|
+
) {
|
|
221
|
+
return "desc";
|
|
222
|
+
} else {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const sorting: ISortingActions<TParam> = {
|
|
228
|
+
sortField,
|
|
229
|
+
getSortingDirection,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
function getFilterFieldValue(key: keyof TParam) {
|
|
233
|
+
// @ts-ignore correctly handle the keyof in the future
|
|
234
|
+
return queryParamState[key] as TParam[keyof TParam];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function setFilterFieldValue(key: keyof TParam) {
|
|
238
|
+
return (value: unknown) => {
|
|
239
|
+
setQueryParamState((current) => ({
|
|
240
|
+
...current,
|
|
241
|
+
[key]: value,
|
|
242
|
+
page: 1,
|
|
243
|
+
}));
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const filtering: IFilterActions<TParam> = {
|
|
248
|
+
getFilterFieldValue,
|
|
249
|
+
setFilterFieldValue,
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const data =
|
|
253
|
+
options?.localCache && searchText
|
|
254
|
+
? // @ts-ignore the results key is based on the interface returned. This will get sorted out in a future version
|
|
255
|
+
query.data?.results.filter((value: any) => {
|
|
256
|
+
if (options.localSearchFunction && searchText) {
|
|
257
|
+
if (searchText.includes(" ")) {
|
|
258
|
+
const searchWords = searchText.split(" ");
|
|
259
|
+
return searchWords.every((word) => {
|
|
260
|
+
if (options.localSearchFunction) {
|
|
261
|
+
return options.localSearchFunction(word, value);
|
|
262
|
+
} else {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
} else {
|
|
267
|
+
return options.localSearchFunction(searchText, value);
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
: // @ts-ignore
|
|
274
|
+
query.data?.results;
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
...query,
|
|
278
|
+
raw: query.data,
|
|
279
|
+
data,
|
|
280
|
+
header: query.data?.headers,
|
|
281
|
+
pagination,
|
|
282
|
+
searching,
|
|
283
|
+
sorting,
|
|
284
|
+
filtering,
|
|
285
|
+
};
|
|
286
|
+
}
|