@refinedev/core 4.46.2 → 4.47.0
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 +23 -1
- package/README.md +4 -4
- package/dist/components/canAccess/index.d.ts +3 -0
- package/dist/components/canAccess/index.d.ts.map +1 -1
- package/dist/components/containers/refine/index.d.ts +4 -4
- package/dist/components/containers/refine/index.d.ts.map +1 -1
- package/dist/components/pages/config-error/index.d.ts +3 -0
- package/dist/components/pages/config-error/index.d.ts.map +1 -0
- package/dist/components/pages/config-success/index.d.ts +6 -0
- package/dist/components/pages/config-success/index.d.ts.map +1 -0
- package/dist/components/pages/welcome/index.d.ts +2 -5
- package/dist/components/pages/welcome/index.d.ts.map +1 -1
- package/dist/contexts/accessControl/IAccessControlContext.d.ts +3 -0
- package/dist/contexts/accessControl/IAccessControlContext.d.ts.map +1 -1
- package/dist/contexts/accessControl/index.d.ts.map +1 -1
- package/dist/contexts/auth/IAuthContext.d.ts +1 -1
- package/dist/contexts/data/index.d.ts +5 -49
- package/dist/contexts/data/index.d.ts.map +1 -1
- package/dist/contexts/refine/IRefineContext.d.ts +2 -0
- package/dist/contexts/refine/IRefineContext.d.ts.map +1 -1
- package/dist/contexts/refine/index.d.ts.map +1 -1
- package/dist/definitions/helpers/downloadInBrowser/index.d.ts +2 -0
- package/dist/definitions/helpers/downloadInBrowser/index.d.ts.map +1 -0
- package/dist/definitions/helpers/index.d.ts +1 -0
- package/dist/definitions/helpers/index.d.ts.map +1 -1
- package/dist/esm/index.js +26 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/hooks/accessControl/useCan/index.d.ts +1 -1
- package/dist/hooks/accessControl/useCan/index.d.ts.map +1 -1
- package/dist/hooks/auth/useForgotPassword/index.d.ts.map +1 -1
- package/dist/hooks/auth/useLogin/index.d.ts.map +1 -1
- package/dist/hooks/auth/useLogout/index.d.ts.map +1 -1
- package/dist/hooks/auth/useRegister/index.d.ts.map +1 -1
- package/dist/hooks/auth/useUpdatePassword/index.d.ts.map +1 -1
- package/dist/hooks/data/useDataProvider.d.ts.map +1 -1
- package/dist/hooks/export/index.d.ts +27 -4
- package/dist/hooks/export/index.d.ts.map +1 -1
- package/dist/hooks/refine/useRefineContext.d.ts +1 -0
- package/dist/hooks/refine/useRefineContext.d.ts.map +1 -1
- package/dist/iife/index.js +26 -6
- package/dist/iife/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -6
- package/dist/index.js.map +1 -1
- package/dist/interfaces/bindings/auth.d.ts +7 -1
- package/dist/interfaces/bindings/auth.d.ts.map +1 -1
- package/dist/interfaces/bindings/index.d.ts +1 -1
- package/dist/interfaces/bindings/index.d.ts.map +1 -1
- package/dist/interfaces/metaData/graphqlQueryOptions.d.ts +47 -0
- package/dist/interfaces/metaData/graphqlQueryOptions.d.ts.map +1 -1
- package/package.json +1 -2
- package/src/components/canAccess/index.tsx +6 -0
- package/src/components/containers/refine/index.tsx +4 -4
- package/src/components/pages/config-error/index.tsx +444 -0
- package/src/components/pages/config-success/index.tsx +294 -0
- package/src/components/pages/welcome/index.tsx +10 -289
- package/src/contexts/accessControl/IAccessControlContext.ts +3 -0
- package/src/contexts/accessControl/index.tsx +1 -0
- package/src/contexts/auth/IAuthContext.ts +1 -1
- package/src/contexts/data/index.tsx +9 -24
- package/src/contexts/refine/IRefineContext.ts +2 -0
- package/src/contexts/refine/index.tsx +1 -0
- package/src/definitions/helpers/downloadInBrowser/index.ts +25 -0
- package/src/definitions/helpers/index.ts +1 -0
- package/src/hooks/accessControl/useCan/index.ts +12 -5
- package/src/hooks/auth/useForgotPassword/index.ts +17 -1
- package/src/hooks/auth/useLogin/index.ts +22 -1
- package/src/hooks/auth/useLogout/index.ts +17 -1
- package/src/hooks/auth/useRegister/index.ts +22 -1
- package/src/hooks/auth/useUpdatePassword/index.ts +17 -1
- package/src/hooks/data/useDataProvider.tsx +3 -2
- package/src/hooks/export/index.ts +90 -9
- package/src/hooks/refine/useRefineContext.ts +2 -0
- package/src/index.tsx +1 -0
- package/src/interfaces/bindings/auth.ts +9 -1
- package/src/interfaces/bindings/index.ts +1 -0
- package/src/interfaces/metaData/graphqlQueryOptions.ts +47 -0
|
@@ -67,6 +67,7 @@ export interface IRefineContextOptions {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export interface IRefineContext {
|
|
70
|
+
__initialized?: boolean;
|
|
70
71
|
hasDashboard: boolean;
|
|
71
72
|
mutationMode: MutationMode;
|
|
72
73
|
/**
|
|
@@ -90,6 +91,7 @@ export interface IRefineContext {
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
export interface IRefineContextProvider {
|
|
94
|
+
__initialized?: boolean;
|
|
93
95
|
hasDashboard: boolean;
|
|
94
96
|
mutationMode: MutationMode;
|
|
95
97
|
warnWhenUnsavedChanges: boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
export const downloadInBrowser = (
|
|
3
|
+
filename: string,
|
|
4
|
+
content: string,
|
|
5
|
+
type?: string
|
|
6
|
+
) => {
|
|
7
|
+
if (typeof window === "undefined") {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const blob = new Blob([content], { type });
|
|
12
|
+
|
|
13
|
+
const link = document.createElement("a");
|
|
14
|
+
link.setAttribute("visibility", "hidden");
|
|
15
|
+
link.download = filename;
|
|
16
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
17
|
+
link.href = blobUrl;
|
|
18
|
+
document.body.appendChild(link);
|
|
19
|
+
link.click();
|
|
20
|
+
document.body.removeChild(link);
|
|
21
|
+
// As per documentation, call URL.revokeObjectURL to remove the blob from memory.
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
URL.revokeObjectURL(blobUrl)
|
|
24
|
+
})
|
|
25
|
+
};
|
|
@@ -30,3 +30,4 @@ export { keys, stripUndefined } from "./keys";
|
|
|
30
30
|
export { KeyBuilder } from "./keys";
|
|
31
31
|
export { flattenObjectKeys } from "./flatten-object-keys";
|
|
32
32
|
export { propertyPathToArray } from "./property-path-to-array";
|
|
33
|
+
export { downloadInBrowser } from "./downloadInBrowser";
|
|
@@ -30,11 +30,18 @@ export const useCan = ({
|
|
|
30
30
|
action,
|
|
31
31
|
resource,
|
|
32
32
|
params,
|
|
33
|
-
queryOptions,
|
|
33
|
+
queryOptions: hookQueryOptions,
|
|
34
34
|
}: UseCanProps): UseQueryResult<CanReturnType> => {
|
|
35
|
-
const { can } = useContext(AccessControlContext);
|
|
35
|
+
const { can, options: globalOptions } = useContext(AccessControlContext);
|
|
36
36
|
const { keys, preferLegacyKeys } = useKeys();
|
|
37
37
|
|
|
38
|
+
const { queryOptions: globalQueryOptions } = globalOptions || {};
|
|
39
|
+
|
|
40
|
+
const mergedQueryOptions = {
|
|
41
|
+
...globalQueryOptions,
|
|
42
|
+
...hookQueryOptions,
|
|
43
|
+
};
|
|
44
|
+
|
|
38
45
|
/**
|
|
39
46
|
* Since `react-query` stringifies the query keys, it will throw an error for a circular dependency if we include `React.ReactNode` elements inside the keys.
|
|
40
47
|
* The feature in #2220(https://github.com/refinedev/refine/issues/2220) includes such change and to fix this, we need to remove `icon` property in the `resource`
|
|
@@ -52,7 +59,7 @@ export const useCan = ({
|
|
|
52
59
|
.action(action)
|
|
53
60
|
.params({
|
|
54
61
|
params: { ...paramsRest, resource: sanitizedResource },
|
|
55
|
-
enabled:
|
|
62
|
+
enabled: mergedQueryOptions?.enabled,
|
|
56
63
|
})
|
|
57
64
|
.get(preferLegacyKeys),
|
|
58
65
|
// Enabled check for `can` is enough to be sure that it's defined in the query function but TS is not smart enough to know that.
|
|
@@ -63,9 +70,9 @@ export const useCan = ({
|
|
|
63
70
|
params: { ...paramsRest, resource: sanitizedResource },
|
|
64
71
|
}) ?? Promise.resolve({ can: true }),
|
|
65
72
|
enabled: typeof can !== "undefined",
|
|
66
|
-
...
|
|
73
|
+
...mergedQueryOptions,
|
|
67
74
|
meta: {
|
|
68
|
-
...
|
|
75
|
+
...mergedQueryOptions?.meta,
|
|
69
76
|
...getXRay("useCan", preferLegacyKeys),
|
|
70
77
|
},
|
|
71
78
|
retry: false,
|
|
@@ -7,6 +7,7 @@ import { getXRay } from "@refinedev/devtools-internal";
|
|
|
7
7
|
|
|
8
8
|
import { useGo, useNavigation, useNotification, useRouterType } from "@hooks";
|
|
9
9
|
import { useAuthBindingsContext, useLegacyAuthContext } from "@contexts/auth";
|
|
10
|
+
import { SuccessNotificationResponse } from "src/interfaces/bindings/auth";
|
|
10
11
|
|
|
11
12
|
import {
|
|
12
13
|
AuthActionResponse,
|
|
@@ -127,9 +128,13 @@ export function useForgotPassword<TVariables = {}>({
|
|
|
127
128
|
.action("forgotPassword")
|
|
128
129
|
.get(preferLegacyKeys),
|
|
129
130
|
mutationFn: forgotPasswordFromContext,
|
|
130
|
-
onSuccess: ({ success, redirectTo, error }) => {
|
|
131
|
+
onSuccess: ({ success, redirectTo, error, successNotification }) => {
|
|
131
132
|
if (success) {
|
|
132
133
|
close?.("forgot-password-error");
|
|
134
|
+
|
|
135
|
+
if (successNotification) {
|
|
136
|
+
open?.(buildSuccessNotification(successNotification));
|
|
137
|
+
}
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
if (error || !success) {
|
|
@@ -204,3 +209,14 @@ const buildNotification = (
|
|
|
204
209
|
type: "error",
|
|
205
210
|
};
|
|
206
211
|
};
|
|
212
|
+
|
|
213
|
+
const buildSuccessNotification = (
|
|
214
|
+
successNotification: SuccessNotificationResponse,
|
|
215
|
+
): OpenNotificationParams => {
|
|
216
|
+
return {
|
|
217
|
+
message: successNotification.message,
|
|
218
|
+
description: successNotification.description,
|
|
219
|
+
key: "forgot-password-success",
|
|
220
|
+
type: "success",
|
|
221
|
+
};
|
|
222
|
+
};
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
TLoginData,
|
|
24
24
|
} from "../../../interfaces";
|
|
25
25
|
import { AuthActionResponse } from "src/interfaces/bindings/auth";
|
|
26
|
+
import { SuccessNotificationResponse } from "src/interfaces/bindings/auth";
|
|
26
27
|
import { useInvalidateAuthStore } from "../useInvalidateAuthStore";
|
|
27
28
|
import { useKeys } from "@hooks/useKeys";
|
|
28
29
|
|
|
@@ -148,9 +149,18 @@ export function useLogin<TVariables = {}>({
|
|
|
148
149
|
>({
|
|
149
150
|
mutationKey: keys().auth().action("login").get(preferLegacyKeys),
|
|
150
151
|
mutationFn: loginFromContext,
|
|
151
|
-
onSuccess: async ({
|
|
152
|
+
onSuccess: async ({
|
|
153
|
+
success,
|
|
154
|
+
redirectTo,
|
|
155
|
+
error,
|
|
156
|
+
successNotification,
|
|
157
|
+
}) => {
|
|
152
158
|
if (success) {
|
|
153
159
|
close?.("login-error");
|
|
160
|
+
|
|
161
|
+
if (successNotification) {
|
|
162
|
+
open?.(buildSuccessNotification(successNotification));
|
|
163
|
+
}
|
|
154
164
|
}
|
|
155
165
|
|
|
156
166
|
if (error || !success) {
|
|
@@ -250,3 +260,14 @@ const buildNotification = (
|
|
|
250
260
|
type: "error",
|
|
251
261
|
};
|
|
252
262
|
};
|
|
263
|
+
|
|
264
|
+
const buildSuccessNotification = (
|
|
265
|
+
successNotification: SuccessNotificationResponse,
|
|
266
|
+
): OpenNotificationParams => {
|
|
267
|
+
return {
|
|
268
|
+
message: successNotification.message,
|
|
269
|
+
description: successNotification.description,
|
|
270
|
+
key: "login-success",
|
|
271
|
+
type: "success",
|
|
272
|
+
};
|
|
273
|
+
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
TLogoutData,
|
|
14
14
|
} from "../../../interfaces";
|
|
15
15
|
import { AuthActionResponse } from "src/interfaces/bindings/auth";
|
|
16
|
+
import { SuccessNotificationResponse } from "src/interfaces/bindings/auth";
|
|
16
17
|
import { useInvalidateAuthStore } from "../useInvalidateAuthStore";
|
|
17
18
|
import { useKeys } from "@hooks/useKeys";
|
|
18
19
|
|
|
@@ -122,13 +123,17 @@ export function useLogout<TVariables = {}>({
|
|
|
122
123
|
mutationKey: keys().auth().action("logout").get(preferLegacyKeys),
|
|
123
124
|
mutationFn: logoutFromContext,
|
|
124
125
|
onSuccess: async (data, variables) => {
|
|
125
|
-
const { success, error, redirectTo } = data;
|
|
126
|
+
const { success, error, redirectTo, successNotification } = data;
|
|
126
127
|
const { redirectPath } = variables ?? {};
|
|
127
128
|
|
|
128
129
|
const redirect = redirectPath ?? redirectTo;
|
|
129
130
|
|
|
130
131
|
if (success) {
|
|
131
132
|
close?.("useLogout-error");
|
|
133
|
+
|
|
134
|
+
if (successNotification) {
|
|
135
|
+
open?.(buildSuccessNotification(successNotification));
|
|
136
|
+
}
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
if (error || !success) {
|
|
@@ -219,3 +224,14 @@ const buildNotification = (
|
|
|
219
224
|
description: error?.message || "Something went wrong during logout",
|
|
220
225
|
};
|
|
221
226
|
};
|
|
227
|
+
|
|
228
|
+
const buildSuccessNotification = (
|
|
229
|
+
successNotification: SuccessNotificationResponse,
|
|
230
|
+
): OpenNotificationParams => {
|
|
231
|
+
return {
|
|
232
|
+
message: successNotification.message,
|
|
233
|
+
description: successNotification.description,
|
|
234
|
+
key: "logout-success",
|
|
235
|
+
type: "success",
|
|
236
|
+
};
|
|
237
|
+
};
|
|
@@ -7,6 +7,7 @@ import { getXRay } from "@refinedev/devtools-internal";
|
|
|
7
7
|
|
|
8
8
|
import { useNavigation, useRouterType, useGo, useNotification } from "@hooks";
|
|
9
9
|
import { useAuthBindingsContext, useLegacyAuthContext } from "@contexts/auth";
|
|
10
|
+
import { SuccessNotificationResponse } from "src/interfaces/bindings/auth";
|
|
10
11
|
|
|
11
12
|
import {
|
|
12
13
|
AuthActionResponse,
|
|
@@ -123,9 +124,18 @@ export function useRegister<TVariables = {}>({
|
|
|
123
124
|
>({
|
|
124
125
|
mutationKey: keys().auth().action("register").get(preferLegacyKeys),
|
|
125
126
|
mutationFn: registerFromContext,
|
|
126
|
-
onSuccess: async ({
|
|
127
|
+
onSuccess: async ({
|
|
128
|
+
success,
|
|
129
|
+
redirectTo,
|
|
130
|
+
error,
|
|
131
|
+
successNotification,
|
|
132
|
+
}) => {
|
|
127
133
|
if (success) {
|
|
128
134
|
close?.("register-error");
|
|
135
|
+
|
|
136
|
+
if (successNotification) {
|
|
137
|
+
open?.(buildSuccessNotification(successNotification));
|
|
138
|
+
}
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
if (error || !success) {
|
|
@@ -215,3 +225,14 @@ const buildNotification = (
|
|
|
215
225
|
type: "error",
|
|
216
226
|
};
|
|
217
227
|
};
|
|
228
|
+
|
|
229
|
+
const buildSuccessNotification = (
|
|
230
|
+
successNotification: SuccessNotificationResponse,
|
|
231
|
+
): OpenNotificationParams => {
|
|
232
|
+
return {
|
|
233
|
+
message: successNotification.message,
|
|
234
|
+
description: successNotification.description,
|
|
235
|
+
key: "register-success",
|
|
236
|
+
type: "success",
|
|
237
|
+
};
|
|
238
|
+
};
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
useRouterContext,
|
|
17
17
|
} from "@hooks";
|
|
18
18
|
import { useAuthBindingsContext, useLegacyAuthContext } from "@contexts/auth";
|
|
19
|
+
import { SuccessNotificationResponse } from "src/interfaces/bindings/auth";
|
|
19
20
|
import {
|
|
20
21
|
AuthActionResponse,
|
|
21
22
|
RefineError,
|
|
@@ -170,9 +171,13 @@ export function useUpdatePassword<
|
|
|
170
171
|
...variables,
|
|
171
172
|
}) as Promise<AuthActionResponse>;
|
|
172
173
|
},
|
|
173
|
-
onSuccess: ({ success, redirectTo, error }) => {
|
|
174
|
+
onSuccess: ({ success, redirectTo, error, successNotification }) => {
|
|
174
175
|
if (success) {
|
|
175
176
|
close?.("update-password-error");
|
|
177
|
+
|
|
178
|
+
if (successNotification) {
|
|
179
|
+
open?.(buildSuccessNotification(successNotification));
|
|
180
|
+
}
|
|
176
181
|
}
|
|
177
182
|
|
|
178
183
|
if (error || !success) {
|
|
@@ -252,3 +257,14 @@ const buildNotification = (
|
|
|
252
257
|
type: "error",
|
|
253
258
|
};
|
|
254
259
|
};
|
|
260
|
+
|
|
261
|
+
const buildSuccessNotification = (
|
|
262
|
+
successNotification: SuccessNotificationResponse,
|
|
263
|
+
): OpenNotificationParams => {
|
|
264
|
+
return {
|
|
265
|
+
message: successNotification.message,
|
|
266
|
+
description: successNotification.description,
|
|
267
|
+
key: "update-password-success",
|
|
268
|
+
type: "success",
|
|
269
|
+
};
|
|
270
|
+
};
|
|
@@ -12,12 +12,13 @@ export const useDataProvider = (): ((
|
|
|
12
12
|
*/
|
|
13
13
|
dataProviderName?: string,
|
|
14
14
|
) => IDataContextProvider) => {
|
|
15
|
-
const context =
|
|
15
|
+
const context =
|
|
16
|
+
useContext<Partial<IDataMultipleContextProvider>>(DataContext);
|
|
16
17
|
|
|
17
18
|
const handleDataProvider = useCallback(
|
|
18
19
|
(dataProviderName?: string) => {
|
|
19
20
|
if (dataProviderName) {
|
|
20
|
-
const dataProvider = context[dataProviderName];
|
|
21
|
+
const dataProvider = context?.[dataProviderName];
|
|
21
22
|
if (!dataProvider) {
|
|
22
23
|
throw new Error(
|
|
23
24
|
`"${dataProviderName}" Data provider not found`,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
+
import { unparse, UnparseConfig } from "papaparse";
|
|
3
|
+
import warnOnce from "warn-once";
|
|
2
4
|
import { useResource, useDataProvider, useMeta } from "@hooks";
|
|
3
5
|
import {
|
|
4
6
|
BaseRecord,
|
|
@@ -11,8 +13,24 @@ import {
|
|
|
11
13
|
useUserFriendlyName,
|
|
12
14
|
pickDataProvider,
|
|
13
15
|
pickNotDeprecated,
|
|
16
|
+
downloadInBrowser,
|
|
14
17
|
} from "@definitions";
|
|
15
|
-
|
|
18
|
+
|
|
19
|
+
// Old options interface taken from export-to-csv-fix-source-map@0.2.1
|
|
20
|
+
// Kept here to ensure backward compatibility
|
|
21
|
+
export interface ExportOptions {
|
|
22
|
+
filename?: string;
|
|
23
|
+
fieldSeparator?: string;
|
|
24
|
+
quoteStrings?: string;
|
|
25
|
+
decimalSeparator?: string;
|
|
26
|
+
showLabels?: boolean;
|
|
27
|
+
showTitle?: boolean;
|
|
28
|
+
title?: string;
|
|
29
|
+
useTextFile?: boolean;
|
|
30
|
+
useBom?: boolean;
|
|
31
|
+
headers?: string[];
|
|
32
|
+
useKeysAsHeaders?: boolean;
|
|
33
|
+
}
|
|
16
34
|
|
|
17
35
|
type UseExportOptionsType<
|
|
18
36
|
TData extends BaseRecord = BaseRecord,
|
|
@@ -54,8 +72,14 @@ type UseExportOptionsType<
|
|
|
54
72
|
/**
|
|
55
73
|
* Used for exporting options
|
|
56
74
|
* @type [Options](https://github.com/alexcaza/export-to-csv)
|
|
75
|
+
* @deprecated `exportOptions` is deprecated. Use `unparseConfig` instead.
|
|
57
76
|
*/
|
|
58
|
-
exportOptions?:
|
|
77
|
+
exportOptions?: ExportOptions;
|
|
78
|
+
/**
|
|
79
|
+
* Used for exporting options
|
|
80
|
+
* @type [UnparseConfig](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/papaparse)
|
|
81
|
+
*/
|
|
82
|
+
unparseConfig?: UnparseConfig;
|
|
59
83
|
/**
|
|
60
84
|
* Metadata query for `dataProvider`
|
|
61
85
|
*/
|
|
@@ -73,11 +97,15 @@ type UseExportOptionsType<
|
|
|
73
97
|
* Callback to handle error events of this hook
|
|
74
98
|
*/
|
|
75
99
|
onError?: (error: any) => void;
|
|
100
|
+
/**
|
|
101
|
+
* Whether to generate download of the CSV in browser environments, defaults to true.
|
|
102
|
+
*/
|
|
103
|
+
download?: boolean;
|
|
76
104
|
};
|
|
77
105
|
|
|
78
106
|
type UseExportReturnType = {
|
|
79
107
|
isLoading: boolean;
|
|
80
|
-
triggerExport: () => Promise<
|
|
108
|
+
triggerExport: () => Promise<string | undefined>;
|
|
81
109
|
};
|
|
82
110
|
|
|
83
111
|
/**
|
|
@@ -102,10 +130,12 @@ export const useExport = <
|
|
|
102
130
|
pageSize = 20,
|
|
103
131
|
mapData = (item) => item as any,
|
|
104
132
|
exportOptions,
|
|
133
|
+
unparseConfig,
|
|
105
134
|
meta,
|
|
106
135
|
metaData,
|
|
107
136
|
dataProviderName,
|
|
108
137
|
onError,
|
|
138
|
+
download
|
|
109
139
|
}: UseExportOptionsType<TData, TVariables> = {}): UseExportReturnType => {
|
|
110
140
|
const [isLoading, setIsLoading] = useState(false);
|
|
111
141
|
|
|
@@ -175,15 +205,66 @@ export const useExport = <
|
|
|
175
205
|
}
|
|
176
206
|
}
|
|
177
207
|
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
208
|
+
const hasUnparseConfig = typeof unparseConfig !== "undefined" && unparseConfig !== null;
|
|
209
|
+
|
|
210
|
+
warnOnce(hasUnparseConfig && typeof exportOptions !== "undefined" && exportOptions !== null,
|
|
211
|
+
`[useExport]: resource: "${identifier}" \n\n` +
|
|
212
|
+
`Both \`unparseConfig\` and \`exportOptions\` are set, \`unparseConfig\` will take precedence`,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
const options: ExportOptions = {
|
|
216
|
+
filename,
|
|
217
|
+
useKeysAsHeaders: true,
|
|
218
|
+
useBom: true, // original default
|
|
219
|
+
title: 'My Generated Report', // original default
|
|
220
|
+
quoteStrings: '"', // original default
|
|
221
|
+
...exportOptions
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
warnOnce(exportOptions?.decimalSeparator !== undefined,
|
|
225
|
+
`[useExport]: resource: "${identifier}" \n\n` +
|
|
226
|
+
`Use of \`decimalSeparator\` no longer supported, please use \`mapData\` instead.\n\n` +
|
|
227
|
+
`See https://refine.dev/docs/api-reference/core/hooks/import-export/useExport/`,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if(!hasUnparseConfig) {
|
|
231
|
+
unparseConfig = {
|
|
232
|
+
// useKeysAsHeaders takes priority over options.headers
|
|
233
|
+
columns: options.useKeysAsHeaders ? undefined : options.headers,
|
|
234
|
+
delimiter: options.fieldSeparator,
|
|
235
|
+
header: options.showLabels || options.useKeysAsHeaders,
|
|
236
|
+
quoteChar: options.quoteStrings,
|
|
237
|
+
quotes: true
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
unparseConfig = {
|
|
241
|
+
// Set to force quote for better compatibility
|
|
242
|
+
quotes: true,
|
|
243
|
+
...unparseConfig
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let csv = unparse(rawData.map(mapData as any), unparseConfig);
|
|
248
|
+
if (options.showTitle) {
|
|
249
|
+
csv = options.title + '\r\n\n' + csv
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Backward compatibility support for downloadInBrowser of the exported file, only works for browsers.
|
|
253
|
+
if(typeof window !== "undefined" && csv.length > 0 && (download ?? true)){
|
|
254
|
+
const fileExtension = options.useTextFile ? '.txt' : '.csv';
|
|
255
|
+
const fileType = `text/${options.useTextFile ? "plain" : "csv"};charset=utf8;`;
|
|
256
|
+
const downloadFilename =
|
|
257
|
+
`${(options.filename ?? 'download').replace(/ /g, "_")}${fileExtension}`
|
|
183
258
|
|
|
184
|
-
|
|
259
|
+
downloadInBrowser(
|
|
260
|
+
downloadFilename,
|
|
261
|
+
`${options?.useBom ? "\ufeff" : ""}${csv}`,
|
|
262
|
+
fileType
|
|
263
|
+
);
|
|
264
|
+
}
|
|
185
265
|
|
|
186
266
|
setIsLoading(false);
|
|
267
|
+
return csv;
|
|
187
268
|
};
|
|
188
269
|
|
|
189
270
|
return {
|
package/src/index.tsx
CHANGED
|
@@ -46,11 +46,17 @@ export type OnErrorResponse = {
|
|
|
46
46
|
error?: RefineError | Error;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
export type SuccessNotificationResponse = {
|
|
50
|
+
message: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
export type AuthActionResponse = {
|
|
50
55
|
success: boolean;
|
|
51
56
|
redirectTo?: string;
|
|
52
57
|
error?: RefineError | Error;
|
|
53
58
|
[key: string]: unknown;
|
|
59
|
+
successNotification?: SuccessNotificationResponse;
|
|
54
60
|
};
|
|
55
61
|
|
|
56
62
|
export type PermissionResponse = unknown;
|
|
@@ -69,6 +75,8 @@ export type AuthBindings = {
|
|
|
69
75
|
getIdentity?: (params?: any) => Promise<IdentityResponse>;
|
|
70
76
|
};
|
|
71
77
|
|
|
72
|
-
export interface IAuthBindingsContext extends Partial<
|
|
78
|
+
export interface IAuthBindingsContext extends Partial<AuthProvider> {
|
|
73
79
|
isProvided: boolean;
|
|
74
80
|
}
|
|
81
|
+
|
|
82
|
+
export type AuthProvider = AuthBindings;
|
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
import type { DocumentNode } from "graphql";
|
|
2
2
|
|
|
3
3
|
export type GraphQLQueryOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* @description GraphQL query to be used by data providers.
|
|
6
|
+
* @optional
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import gql from 'graphql-tag'
|
|
10
|
+
* import { useOne } from '@refinedev/core'
|
|
11
|
+
*
|
|
12
|
+
* const PRODUCT_QUERY = gql`
|
|
13
|
+
* query GetProduct($id: ID!) {
|
|
14
|
+
* product(id: $id) {
|
|
15
|
+
* id
|
|
16
|
+
* name
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* `
|
|
20
|
+
*
|
|
21
|
+
* useOne({
|
|
22
|
+
* id: 1,
|
|
23
|
+
* meta: { gqlQuery: PRODUCT_QUERY }
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
4
27
|
gqlQuery?: DocumentNode;
|
|
28
|
+
/**
|
|
29
|
+
* @description GraphQL mutation to be used by data providers.
|
|
30
|
+
* @optional
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* import gql from 'graphql-tag'
|
|
34
|
+
* import { useCreate } from '@refinedev/core'
|
|
35
|
+
*
|
|
36
|
+
* const PRODUCT_CREATE_MUTATION = gql`
|
|
37
|
+
* mutation CreateProduct($input: CreateOneProductInput!) {
|
|
38
|
+
* createProduct(input: $input) {
|
|
39
|
+
* id
|
|
40
|
+
* name
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
* `
|
|
44
|
+
* const { mutate } = useCreate()
|
|
45
|
+
*
|
|
46
|
+
* mutate({
|
|
47
|
+
* values: { name: "My Product" },
|
|
48
|
+
* meta: { gqlQuery: PRODUCT_QUERY }
|
|
49
|
+
* })
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
5
52
|
gqlMutation?: DocumentNode;
|
|
6
53
|
};
|