@payloadcms/plugin-import-export 3.47.0-internal.b17506e → 3.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/dist/components/ExportSaveButton/index.d.ts.map +1 -1
- package/dist/components/ExportSaveButton/index.js +21 -2
- package/dist/components/ExportSaveButton/index.js.map +1 -1
- package/dist/components/FieldsToExport/index.d.ts.map +1 -1
- package/dist/components/FieldsToExport/index.js +28 -41
- package/dist/components/FieldsToExport/index.js.map +1 -1
- package/dist/components/SelectionToUseField/index.d.ts +3 -0
- package/dist/components/SelectionToUseField/index.d.ts.map +1 -0
- package/dist/components/SelectionToUseField/index.js +128 -0
- package/dist/components/SelectionToUseField/index.js.map +1 -0
- package/dist/components/SortBy/index.js +3 -2
- package/dist/components/SortBy/index.js.map +1 -1
- package/dist/export/createExport.d.ts.map +1 -1
- package/dist/export/createExport.js +1 -2
- package/dist/export/createExport.js.map +1 -1
- package/dist/export/flattenObject.d.ts.map +1 -1
- package/dist/export/flattenObject.js +48 -30
- package/dist/export/flattenObject.js.map +1 -1
- package/dist/export/getCustomFieldFunctions.d.ts +2 -3
- package/dist/export/getCustomFieldFunctions.d.ts.map +1 -1
- package/dist/export/getCustomFieldFunctions.js +3 -5
- package/dist/export/getCustomFieldFunctions.js.map +1 -1
- package/dist/export/getFields.d.ts.map +1 -1
- package/dist/export/getFields.js +15 -10
- package/dist/export/getFields.js.map +1 -1
- package/dist/exports/rsc.d.ts +1 -1
- package/dist/exports/rsc.d.ts.map +1 -1
- package/dist/exports/rsc.js +1 -1
- package/dist/exports/rsc.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/utilities/getFlattenedFieldKeys.d.ts.map +1 -1
- package/dist/utilities/getFlattenedFieldKeys.js +16 -5
- package/dist/utilities/getFlattenedFieldKeys.js.map +1 -1
- package/package.json +7 -7
- package/dist/components/WhereField/index.d.ts +0 -4
- package/dist/components/WhereField/index.d.ts.map +0 -1
- package/dist/components/WhereField/index.js +0 -72
- package/dist/components/WhereField/index.js.map +0 -1
- package/dist/components/WhereField/index.scss +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ExportSaveButton/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ExportSaveButton/index.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAwFpC,CAAA"}
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Button, SaveButton, Translation, useConfig, useForm, useTranslation } from '@payloadcms/ui';
|
|
3
|
+
import { Button, SaveButton, toast, Translation, useConfig, useForm, useFormModified, useTranslation } from '@payloadcms/ui';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
export const ExportSaveButton = ()=>{
|
|
6
6
|
const { t } = useTranslation();
|
|
7
7
|
const { config: { routes: { api }, serverURL } } = useConfig();
|
|
8
|
-
const { getData } = useForm();
|
|
8
|
+
const { getData, setModified } = useForm();
|
|
9
|
+
const modified = useFormModified();
|
|
9
10
|
const label = t('general:save');
|
|
10
11
|
const handleDownload = async ()=>{
|
|
12
|
+
let timeoutID = null;
|
|
13
|
+
let toastID = null;
|
|
11
14
|
try {
|
|
15
|
+
setModified(false) // Reset modified state
|
|
16
|
+
;
|
|
12
17
|
const data = getData();
|
|
18
|
+
// Set a timeout to show toast if the request takes longer than 200ms
|
|
19
|
+
timeoutID = setTimeout(()=>{
|
|
20
|
+
toastID = toast.success('Your export is being processed...');
|
|
21
|
+
}, 200);
|
|
13
22
|
const response = await fetch(`${serverURL}${api}/exports/download`, {
|
|
14
23
|
body: JSON.stringify({
|
|
15
24
|
data
|
|
@@ -20,6 +29,14 @@ export const ExportSaveButton = ()=>{
|
|
|
20
29
|
},
|
|
21
30
|
method: 'POST'
|
|
22
31
|
});
|
|
32
|
+
// Clear the timeout if fetch completes quickly
|
|
33
|
+
if (timeoutID) {
|
|
34
|
+
clearTimeout(timeoutID);
|
|
35
|
+
}
|
|
36
|
+
// Dismiss the toast if it was shown
|
|
37
|
+
if (toastID) {
|
|
38
|
+
toast.dismiss(toastID);
|
|
39
|
+
}
|
|
23
40
|
if (!response.ok) {
|
|
24
41
|
throw new Error('Failed to download file');
|
|
25
42
|
}
|
|
@@ -51,6 +68,7 @@ export const ExportSaveButton = ()=>{
|
|
|
51
68
|
URL.revokeObjectURL(url);
|
|
52
69
|
} catch (error) {
|
|
53
70
|
console.error('Error downloading file:', error);
|
|
71
|
+
toast.error('Error downloading file');
|
|
54
72
|
}
|
|
55
73
|
};
|
|
56
74
|
return /*#__PURE__*/ _jsxs(React.Fragment, {
|
|
@@ -59,6 +77,7 @@ export const ExportSaveButton = ()=>{
|
|
|
59
77
|
label: label
|
|
60
78
|
}),
|
|
61
79
|
/*#__PURE__*/ _jsx(Button, {
|
|
80
|
+
disabled: !modified,
|
|
62
81
|
onClick: handleDownload,
|
|
63
82
|
size: "medium",
|
|
64
83
|
type: "button",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ExportSaveButton/index.tsx"],"sourcesContent":["'use client'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ExportSaveButton/index.tsx"],"sourcesContent":["'use client'\n\nimport {\n Button,\n SaveButton,\n toast,\n Translation,\n useConfig,\n useForm,\n useFormModified,\n useTranslation,\n} from '@payloadcms/ui'\nimport React from 'react'\n\nimport type {\n PluginImportExportTranslationKeys,\n PluginImportExportTranslations,\n} from '../../translations/index.js'\n\nexport const ExportSaveButton: React.FC = () => {\n const { t } = useTranslation<PluginImportExportTranslations, PluginImportExportTranslationKeys>()\n const {\n config: {\n routes: { api },\n serverURL,\n },\n } = useConfig()\n\n const { getData, setModified } = useForm()\n const modified = useFormModified()\n\n const label = t('general:save')\n\n const handleDownload = async () => {\n let timeoutID: null | ReturnType<typeof setTimeout> = null\n let toastID: null | number | string = null\n\n try {\n setModified(false) // Reset modified state\n const data = getData()\n\n // Set a timeout to show toast if the request takes longer than 200ms\n timeoutID = setTimeout(() => {\n toastID = toast.success('Your export is being processed...')\n }, 200)\n\n const response = await fetch(`${serverURL}${api}/exports/download`, {\n body: JSON.stringify({\n data,\n }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n // Clear the timeout if fetch completes quickly\n if (timeoutID) {\n clearTimeout(timeoutID)\n }\n\n // Dismiss the toast if it was shown\n if (toastID) {\n toast.dismiss(toastID)\n }\n\n if (!response.ok) {\n throw new Error('Failed to download file')\n }\n\n const fileStream = response.body\n const reader = fileStream?.getReader()\n const decoder = new TextDecoder()\n let result = ''\n\n while (reader) {\n const { done, value } = await reader.read()\n if (done) {\n break\n }\n result += decoder.decode(value, { stream: true })\n }\n\n const blob = new Blob([result], { type: 'text/plain' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `${data.name}.${data.format}`\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(url)\n } catch (error) {\n console.error('Error downloading file:', error)\n toast.error('Error downloading file')\n }\n }\n\n return (\n <React.Fragment>\n <SaveButton label={label}></SaveButton>\n <Button disabled={!modified} onClick={handleDownload} size=\"medium\" type=\"button\">\n <Translation i18nKey=\"upload:download\" t={t} />\n </Button>\n </React.Fragment>\n )\n}\n"],"names":["Button","SaveButton","toast","Translation","useConfig","useForm","useFormModified","useTranslation","React","ExportSaveButton","t","config","routes","api","serverURL","getData","setModified","modified","label","handleDownload","timeoutID","toastID","data","setTimeout","success","response","fetch","body","JSON","stringify","credentials","headers","method","clearTimeout","dismiss","ok","Error","fileStream","reader","getReader","decoder","TextDecoder","result","done","value","read","decode","stream","blob","Blob","type","url","URL","createObjectURL","a","document","createElement","href","download","name","format","appendChild","click","removeChild","revokeObjectURL","error","console","Fragment","disabled","onClick","size","i18nKey"],"mappings":"AAAA;;AAEA,SACEA,MAAM,EACNC,UAAU,EACVC,KAAK,EACLC,WAAW,EACXC,SAAS,EACTC,OAAO,EACPC,eAAe,EACfC,cAAc,QACT,iBAAgB;AACvB,OAAOC,WAAW,QAAO;AAOzB,OAAO,MAAMC,mBAA6B;IACxC,MAAM,EAAEC,CAAC,EAAE,GAAGH;IACd,MAAM,EACJI,QAAQ,EACNC,QAAQ,EAAEC,GAAG,EAAE,EACfC,SAAS,EACV,EACF,GAAGV;IAEJ,MAAM,EAAEW,OAAO,EAAEC,WAAW,EAAE,GAAGX;IACjC,MAAMY,WAAWX;IAEjB,MAAMY,QAAQR,EAAE;IAEhB,MAAMS,iBAAiB;QACrB,IAAIC,YAAkD;QACtD,IAAIC,UAAkC;QAEtC,IAAI;YACFL,YAAY,OAAO,uBAAuB;;YAC1C,MAAMM,OAAOP;YAEb,qEAAqE;YACrEK,YAAYG,WAAW;gBACrBF,UAAUnB,MAAMsB,OAAO,CAAC;YAC1B,GAAG;YAEH,MAAMC,WAAW,MAAMC,MAAM,GAAGZ,YAAYD,IAAI,iBAAiB,CAAC,EAAE;gBAClEc,MAAMC,KAAKC,SAAS,CAAC;oBACnBP;gBACF;gBACAQ,aAAa;gBACbC,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,QAAQ;YACV;YAEA,+CAA+C;YAC/C,IAAIZ,WAAW;gBACba,aAAab;YACf;YAEA,oCAAoC;YACpC,IAAIC,SAAS;gBACXnB,MAAMgC,OAAO,CAACb;YAChB;YAEA,IAAI,CAACI,SAASU,EAAE,EAAE;gBAChB,MAAM,IAAIC,MAAM;YAClB;YAEA,MAAMC,aAAaZ,SAASE,IAAI;YAChC,MAAMW,SAASD,YAAYE;YAC3B,MAAMC,UAAU,IAAIC;YACpB,IAAIC,SAAS;YAEb,MAAOJ,OAAQ;gBACb,MAAM,EAAEK,IAAI,EAAEC,KAAK,EAAE,GAAG,MAAMN,OAAOO,IAAI;gBACzC,IAAIF,MAAM;oBACR;gBACF;gBACAD,UAAUF,QAAQM,MAAM,CAACF,OAAO;oBAAEG,QAAQ;gBAAK;YACjD;YAEA,MAAMC,OAAO,IAAIC,KAAK;gBAACP;aAAO,EAAE;gBAAEQ,MAAM;YAAa;YACrD,MAAMC,MAAMC,IAAIC,eAAe,CAACL;YAChC,MAAMM,IAAIC,SAASC,aAAa,CAAC;YACjCF,EAAEG,IAAI,GAAGN;YACTG,EAAEI,QAAQ,GAAG,GAAGpC,KAAKqC,IAAI,CAAC,CAAC,EAAErC,KAAKsC,MAAM,EAAE;YAC1CL,SAAS5B,IAAI,CAACkC,WAAW,CAACP;YAC1BA,EAAEQ,KAAK;YACPP,SAAS5B,IAAI,CAACoC,WAAW,CAACT;YAC1BF,IAAIY,eAAe,CAACb;QACtB,EAAE,OAAOc,OAAO;YACdC,QAAQD,KAAK,CAAC,2BAA2BA;YACzC/D,MAAM+D,KAAK,CAAC;QACd;IACF;IAEA,qBACE,MAACzD,MAAM2D,QAAQ;;0BACb,KAAClE;gBAAWiB,OAAOA;;0BACnB,KAAClB;gBAAOoE,UAAU,CAACnD;gBAAUoD,SAASlD;gBAAgBmD,MAAK;gBAASpB,MAAK;0BACvE,cAAA,KAAC/C;oBAAYoE,SAAQ;oBAAkB7D,GAAGA;;;;;AAIlD,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FieldsToExport/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FieldsToExport/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAkBzD,eAAO,MAAM,cAAc,EAAE,0BAoE5B,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { FieldLabel, ReactSelect, useConfig, useDocumentInfo, useField,
|
|
4
|
-
import React, { useEffect
|
|
3
|
+
import { FieldLabel, ReactSelect, useConfig, useDocumentInfo, useField, useListQuery } from '@payloadcms/ui';
|
|
4
|
+
import React, { useEffect } from 'react';
|
|
5
5
|
import { useImportExport } from '../ImportExportProvider/index.js';
|
|
6
6
|
import { reduceFields } from './reduceFields.js';
|
|
7
7
|
const baseClass = 'fields-to-export';
|
|
@@ -13,63 +13,40 @@ export const FieldsToExport = (props)=>{
|
|
|
13
13
|
});
|
|
14
14
|
const { getEntityConfig } = useConfig();
|
|
15
15
|
const { collection } = useImportExport();
|
|
16
|
-
const {
|
|
17
|
-
const [displayedValue, setDisplayedValue] = useState([]);
|
|
16
|
+
const { query } = useListQuery();
|
|
18
17
|
const collectionConfig = getEntityConfig({
|
|
19
18
|
collectionSlug: collectionSlug ?? collection
|
|
20
19
|
});
|
|
21
20
|
const fieldOptions = reduceFields({
|
|
22
21
|
fields: collectionConfig?.fields
|
|
23
22
|
});
|
|
24
|
-
useEffect(()=>{
|
|
25
|
-
if (value && value.length > 0) {
|
|
26
|
-
setDisplayedValue((prevDisplayedValue)=>{
|
|
27
|
-
if (prevDisplayedValue.length > 0) {
|
|
28
|
-
return prevDisplayedValue;
|
|
29
|
-
} // Prevent unnecessary updates
|
|
30
|
-
return value.map((field)=>{
|
|
31
|
-
const match = fieldOptions.find((option)=>option.value === field);
|
|
32
|
-
return match ? {
|
|
33
|
-
...match,
|
|
34
|
-
id: field
|
|
35
|
-
} : {
|
|
36
|
-
id: field,
|
|
37
|
-
label: field,
|
|
38
|
-
value: field
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}, [
|
|
44
|
-
value,
|
|
45
|
-
fieldOptions
|
|
46
|
-
]);
|
|
47
23
|
useEffect(()=>{
|
|
48
24
|
if (id || !collectionSlug) {
|
|
49
25
|
return;
|
|
50
26
|
}
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
27
|
+
const queryColumns = query?.columns;
|
|
28
|
+
if (Array.isArray(queryColumns)) {
|
|
29
|
+
const cleanColumns = queryColumns.filter((col)=>typeof col === 'string' && !col.startsWith('-'));
|
|
30
|
+
// If columns are specified in the query, use them
|
|
31
|
+
setValue(cleanColumns);
|
|
32
|
+
} else {
|
|
33
|
+
// Fallback if no columns in query
|
|
34
|
+
setValue(collectionConfig?.admin?.defaultColumns ?? []);
|
|
35
|
+
}
|
|
57
36
|
}, [
|
|
58
|
-
getPreference,
|
|
59
|
-
collection,
|
|
60
|
-
setValue,
|
|
61
|
-
collectionSlug,
|
|
62
37
|
id,
|
|
63
|
-
|
|
38
|
+
collectionSlug,
|
|
39
|
+
query?.columns,
|
|
40
|
+
collectionConfig?.admin?.defaultColumns,
|
|
41
|
+
setValue
|
|
64
42
|
]);
|
|
65
43
|
const onChange = (options)=>{
|
|
66
44
|
if (!options) {
|
|
67
45
|
setValue([]);
|
|
68
46
|
return;
|
|
69
47
|
}
|
|
70
|
-
const updatedValue = options
|
|
48
|
+
const updatedValue = options.map((option)=>typeof option === 'object' ? option.value : option);
|
|
71
49
|
setValue(updatedValue);
|
|
72
|
-
setDisplayedValue(options);
|
|
73
50
|
};
|
|
74
51
|
return /*#__PURE__*/ _jsxs("div", {
|
|
75
52
|
className: baseClass,
|
|
@@ -89,7 +66,17 @@ export const FieldsToExport = (props)=>{
|
|
|
89
66
|
// @ts-expect-error react select option
|
|
90
67
|
onChange: onChange,
|
|
91
68
|
options: fieldOptions,
|
|
92
|
-
value:
|
|
69
|
+
value: Array.isArray(value) ? value.map((val)=>{
|
|
70
|
+
const match = fieldOptions.find((opt)=>opt.value === val);
|
|
71
|
+
return match ? {
|
|
72
|
+
...match,
|
|
73
|
+
id: val
|
|
74
|
+
} : {
|
|
75
|
+
id: val,
|
|
76
|
+
label: val,
|
|
77
|
+
value: val
|
|
78
|
+
};
|
|
79
|
+
}) : []
|
|
93
80
|
})
|
|
94
81
|
]
|
|
95
82
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/FieldsToExport/index.tsx"],"sourcesContent":["'use client'\n\nimport type {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/FieldsToExport/index.tsx"],"sourcesContent":["'use client'\n\nimport type { SelectFieldClientComponent } from 'payload'\nimport type { ReactNode } from 'react'\n\nimport {\n FieldLabel,\n ReactSelect,\n useConfig,\n useDocumentInfo,\n useField,\n useListQuery,\n} from '@payloadcms/ui'\nimport React, { useEffect } from 'react'\n\nimport { useImportExport } from '../ImportExportProvider/index.js'\nimport { reduceFields } from './reduceFields.js'\n\nconst baseClass = 'fields-to-export'\n\nexport const FieldsToExport: SelectFieldClientComponent = (props) => {\n const { id } = useDocumentInfo()\n const { setValue, value } = useField<string[]>()\n const { value: collectionSlug } = useField<string>({ path: 'collectionSlug' })\n const { getEntityConfig } = useConfig()\n const { collection } = useImportExport()\n const { query } = useListQuery()\n\n const collectionConfig = getEntityConfig({ collectionSlug: collectionSlug ?? collection })\n const fieldOptions = reduceFields({ fields: collectionConfig?.fields })\n\n useEffect(() => {\n if (id || !collectionSlug) {\n return\n }\n\n const queryColumns = query?.columns\n\n if (Array.isArray(queryColumns)) {\n const cleanColumns = queryColumns.filter(\n (col): col is string => typeof col === 'string' && !col.startsWith('-'),\n )\n // If columns are specified in the query, use them\n setValue(cleanColumns)\n } else {\n // Fallback if no columns in query\n setValue(collectionConfig?.admin?.defaultColumns ?? [])\n }\n }, [id, collectionSlug, query?.columns, collectionConfig?.admin?.defaultColumns, setValue])\n\n const onChange = (options: { id: string; label: ReactNode; value: string }[]) => {\n if (!options) {\n setValue([])\n return\n }\n\n const updatedValue = options.map((option) =>\n typeof option === 'object' ? option.value : option,\n )\n\n setValue(updatedValue)\n }\n\n return (\n <div className={baseClass}>\n <FieldLabel label={props.field.label} path={props.path} />\n <ReactSelect\n className={baseClass}\n disabled={props.readOnly}\n getOptionValue={(option) => String(option.value)}\n inputId={`field-${props.path.replace(/\\./g, '__')}`}\n isClearable={true}\n isMulti={true}\n isSortable={true}\n // @ts-expect-error react select option\n onChange={onChange}\n options={fieldOptions}\n value={\n Array.isArray(value)\n ? value.map((val) => {\n const match = fieldOptions.find((opt) => opt.value === val)\n return match ? { ...match, id: val } : { id: val, label: val, value: val }\n })\n : []\n }\n />\n </div>\n )\n}\n"],"names":["FieldLabel","ReactSelect","useConfig","useDocumentInfo","useField","useListQuery","React","useEffect","useImportExport","reduceFields","baseClass","FieldsToExport","props","id","setValue","value","collectionSlug","path","getEntityConfig","collection","query","collectionConfig","fieldOptions","fields","queryColumns","columns","Array","isArray","cleanColumns","filter","col","startsWith","admin","defaultColumns","onChange","options","updatedValue","map","option","div","className","label","field","disabled","readOnly","getOptionValue","String","inputId","replace","isClearable","isMulti","isSortable","val","match","find","opt"],"mappings":"AAAA;;AAKA,SACEA,UAAU,EACVC,WAAW,EACXC,SAAS,EACTC,eAAe,EACfC,QAAQ,EACRC,YAAY,QACP,iBAAgB;AACvB,OAAOC,SAASC,SAAS,QAAQ,QAAO;AAExC,SAASC,eAAe,QAAQ,mCAAkC;AAClE,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,MAAMC,YAAY;AAElB,OAAO,MAAMC,iBAA6C,CAACC;IACzD,MAAM,EAAEC,EAAE,EAAE,GAAGV;IACf,MAAM,EAAEW,QAAQ,EAAEC,KAAK,EAAE,GAAGX;IAC5B,MAAM,EAAEW,OAAOC,cAAc,EAAE,GAAGZ,SAAiB;QAAEa,MAAM;IAAiB;IAC5E,MAAM,EAAEC,eAAe,EAAE,GAAGhB;IAC5B,MAAM,EAAEiB,UAAU,EAAE,GAAGX;IACvB,MAAM,EAAEY,KAAK,EAAE,GAAGf;IAElB,MAAMgB,mBAAmBH,gBAAgB;QAAEF,gBAAgBA,kBAAkBG;IAAW;IACxF,MAAMG,eAAeb,aAAa;QAAEc,QAAQF,kBAAkBE;IAAO;IAErEhB,UAAU;QACR,IAAIM,MAAM,CAACG,gBAAgB;YACzB;QACF;QAEA,MAAMQ,eAAeJ,OAAOK;QAE5B,IAAIC,MAAMC,OAAO,CAACH,eAAe;YAC/B,MAAMI,eAAeJ,aAAaK,MAAM,CACtC,CAACC,MAAuB,OAAOA,QAAQ,YAAY,CAACA,IAAIC,UAAU,CAAC;YAErE,kDAAkD;YAClDjB,SAASc;QACX,OAAO;YACL,kCAAkC;YAClCd,SAASO,kBAAkBW,OAAOC,kBAAkB,EAAE;QACxD;IACF,GAAG;QAACpB;QAAIG;QAAgBI,OAAOK;QAASJ,kBAAkBW,OAAOC;QAAgBnB;KAAS;IAE1F,MAAMoB,WAAW,CAACC;QAChB,IAAI,CAACA,SAAS;YACZrB,SAAS,EAAE;YACX;QACF;QAEA,MAAMsB,eAAeD,QAAQE,GAAG,CAAC,CAACC,SAChC,OAAOA,WAAW,WAAWA,OAAOvB,KAAK,GAAGuB;QAG9CxB,SAASsB;IACX;IAEA,qBACE,MAACG;QAAIC,WAAW9B;;0BACd,KAACV;gBAAWyC,OAAO7B,MAAM8B,KAAK,CAACD,KAAK;gBAAExB,MAAML,MAAMK,IAAI;;0BACtD,KAAChB;gBACCuC,WAAW9B;gBACXiC,UAAU/B,MAAMgC,QAAQ;gBACxBC,gBAAgB,CAACP,SAAWQ,OAAOR,OAAOvB,KAAK;gBAC/CgC,SAAS,CAAC,MAAM,EAAEnC,MAAMK,IAAI,CAAC+B,OAAO,CAAC,OAAO,OAAO;gBACnDC,aAAa;gBACbC,SAAS;gBACTC,YAAY;gBACZ,uCAAuC;gBACvCjB,UAAUA;gBACVC,SAASb;gBACTP,OACEW,MAAMC,OAAO,CAACZ,SACVA,MAAMsB,GAAG,CAAC,CAACe;oBACT,MAAMC,QAAQ/B,aAAagC,IAAI,CAAC,CAACC,MAAQA,IAAIxC,KAAK,KAAKqC;oBACvD,OAAOC,QAAQ;wBAAE,GAAGA,KAAK;wBAAExC,IAAIuC;oBAAI,IAAI;wBAAEvC,IAAIuC;wBAAKX,OAAOW;wBAAKrC,OAAOqC;oBAAI;gBAC3E,KACA,EAAE;;;;AAKhB,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SelectionToUseField/index.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA6B,MAAM,OAAO,CAAA;AAkBjD,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAmGvC,CAAA"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { RadioGroupField, useDocumentInfo, useField, useListQuery, useSelection, useTranslation } from '@payloadcms/ui';
|
|
4
|
+
import React, { useEffect, useMemo } from 'react';
|
|
5
|
+
const isWhereEmpty = (where)=>{
|
|
6
|
+
if (!where || typeof where !== 'object') {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
// Flatten one level of OR/AND wrappers
|
|
10
|
+
if (Array.isArray(where.and)) {
|
|
11
|
+
return where.and.length === 0;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(where.or)) {
|
|
14
|
+
return where.or.length === 0;
|
|
15
|
+
}
|
|
16
|
+
return Object.keys(where).length === 0;
|
|
17
|
+
};
|
|
18
|
+
export const SelectionToUseField = ()=>{
|
|
19
|
+
const { id } = useDocumentInfo();
|
|
20
|
+
const { query } = useListQuery();
|
|
21
|
+
const { selectAll, selected } = useSelection();
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const { setValue: setSelectionToUseValue, value: selectionToUseValue } = useField({
|
|
24
|
+
path: 'selectionToUse'
|
|
25
|
+
});
|
|
26
|
+
const { setValue: setWhere } = useField({
|
|
27
|
+
path: 'where'
|
|
28
|
+
});
|
|
29
|
+
const hasMeaningfulFilters = query?.where && !isWhereEmpty(query.where);
|
|
30
|
+
const availableOptions = useMemo(()=>{
|
|
31
|
+
const options = [
|
|
32
|
+
{
|
|
33
|
+
// @ts-expect-error - this is not correctly typed in plugins right now
|
|
34
|
+
label: t('plugin-import-export:selectionToUse-allDocuments'),
|
|
35
|
+
value: 'all'
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
if (hasMeaningfulFilters) {
|
|
39
|
+
options.unshift({
|
|
40
|
+
// @ts-expect-error - this is not correctly typed in plugins right now
|
|
41
|
+
label: t('plugin-import-export:selectionToUse-currentFilters'),
|
|
42
|
+
value: 'currentFilters'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if ([
|
|
46
|
+
'allInPage',
|
|
47
|
+
'some'
|
|
48
|
+
].includes(selectAll)) {
|
|
49
|
+
options.unshift({
|
|
50
|
+
// @ts-expect-error - this is not correctly typed in plugins right now
|
|
51
|
+
label: t('plugin-import-export:selectionToUse-currentSelection'),
|
|
52
|
+
value: 'currentSelection'
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return options;
|
|
56
|
+
}, [
|
|
57
|
+
hasMeaningfulFilters,
|
|
58
|
+
selectAll,
|
|
59
|
+
t
|
|
60
|
+
]);
|
|
61
|
+
// Auto-set default
|
|
62
|
+
useEffect(()=>{
|
|
63
|
+
if (id) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
let defaultSelection = 'all';
|
|
67
|
+
if ([
|
|
68
|
+
'allInPage',
|
|
69
|
+
'some'
|
|
70
|
+
].includes(selectAll)) {
|
|
71
|
+
defaultSelection = 'currentSelection';
|
|
72
|
+
} else if (query?.where) {
|
|
73
|
+
defaultSelection = 'currentFilters';
|
|
74
|
+
}
|
|
75
|
+
setSelectionToUseValue(defaultSelection);
|
|
76
|
+
}, [
|
|
77
|
+
id,
|
|
78
|
+
selectAll,
|
|
79
|
+
query?.where,
|
|
80
|
+
setSelectionToUseValue
|
|
81
|
+
]);
|
|
82
|
+
// Sync where clause with selected option
|
|
83
|
+
useEffect(()=>{
|
|
84
|
+
if (id) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (selectionToUseValue === 'currentFilters' && query?.where) {
|
|
88
|
+
setWhere(query.where);
|
|
89
|
+
} else if (selectionToUseValue === 'currentSelection' && selected) {
|
|
90
|
+
const ids = [
|
|
91
|
+
...selected.entries()
|
|
92
|
+
].filter(([_, isSelected])=>isSelected).map(([id])=>id);
|
|
93
|
+
setWhere({
|
|
94
|
+
id: {
|
|
95
|
+
in: ids
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
} else if (selectionToUseValue === 'all') {
|
|
99
|
+
setWhere({});
|
|
100
|
+
}
|
|
101
|
+
}, [
|
|
102
|
+
id,
|
|
103
|
+
selectionToUseValue,
|
|
104
|
+
query?.where,
|
|
105
|
+
selected,
|
|
106
|
+
setWhere
|
|
107
|
+
]);
|
|
108
|
+
// Hide component if no other options besides "all" are available
|
|
109
|
+
if (availableOptions.length <= 1) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
return /*#__PURE__*/ _jsx(RadioGroupField, {
|
|
113
|
+
field: {
|
|
114
|
+
name: 'selectionToUse',
|
|
115
|
+
type: 'radio',
|
|
116
|
+
admin: {},
|
|
117
|
+
// @ts-expect-error - this is not correctly typed in plugins right now
|
|
118
|
+
label: t('plugin-import-export:field-selectionToUse-label'),
|
|
119
|
+
options: availableOptions
|
|
120
|
+
},
|
|
121
|
+
// @ts-expect-error - this is not correctly typed in plugins right now
|
|
122
|
+
label: t('plugin-import-export:field-selectionToUse-label'),
|
|
123
|
+
options: availableOptions,
|
|
124
|
+
path: "selectionToUse"
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/SelectionToUseField/index.tsx"],"sourcesContent":["'use client'\n\nimport type { Where } from 'payload'\n\nimport {\n RadioGroupField,\n useDocumentInfo,\n useField,\n useListQuery,\n useSelection,\n useTranslation,\n} from '@payloadcms/ui'\nimport React, { useEffect, useMemo } from 'react'\n\nconst isWhereEmpty = (where: Where): boolean => {\n if (!where || typeof where !== 'object') {\n return true\n }\n\n // Flatten one level of OR/AND wrappers\n if (Array.isArray(where.and)) {\n return where.and.length === 0\n }\n if (Array.isArray(where.or)) {\n return where.or.length === 0\n }\n\n return Object.keys(where).length === 0\n}\n\nexport const SelectionToUseField: React.FC = () => {\n const { id } = useDocumentInfo()\n const { query } = useListQuery()\n const { selectAll, selected } = useSelection()\n const { t } = useTranslation()\n\n const { setValue: setSelectionToUseValue, value: selectionToUseValue } = useField({\n path: 'selectionToUse',\n })\n\n const { setValue: setWhere } = useField({\n path: 'where',\n })\n\n const hasMeaningfulFilters = query?.where && !isWhereEmpty(query.where)\n\n const availableOptions = useMemo(() => {\n const options = [\n {\n // @ts-expect-error - this is not correctly typed in plugins right now\n label: t('plugin-import-export:selectionToUse-allDocuments'),\n value: 'all',\n },\n ]\n\n if (hasMeaningfulFilters) {\n options.unshift({\n // @ts-expect-error - this is not correctly typed in plugins right now\n label: t('plugin-import-export:selectionToUse-currentFilters'),\n value: 'currentFilters',\n })\n }\n\n if (['allInPage', 'some'].includes(selectAll)) {\n options.unshift({\n // @ts-expect-error - this is not correctly typed in plugins right now\n label: t('plugin-import-export:selectionToUse-currentSelection'),\n value: 'currentSelection',\n })\n }\n\n return options\n }, [hasMeaningfulFilters, selectAll, t])\n\n // Auto-set default\n useEffect(() => {\n if (id) {\n return\n }\n\n let defaultSelection: 'all' | 'currentFilters' | 'currentSelection' = 'all'\n\n if (['allInPage', 'some'].includes(selectAll)) {\n defaultSelection = 'currentSelection'\n } else if (query?.where) {\n defaultSelection = 'currentFilters'\n }\n\n setSelectionToUseValue(defaultSelection)\n }, [id, selectAll, query?.where, setSelectionToUseValue])\n\n // Sync where clause with selected option\n useEffect(() => {\n if (id) {\n return\n }\n\n if (selectionToUseValue === 'currentFilters' && query?.where) {\n setWhere(query.where)\n } else if (selectionToUseValue === 'currentSelection' && selected) {\n const ids = [...selected.entries()].filter(([_, isSelected]) => isSelected).map(([id]) => id)\n\n setWhere({ id: { in: ids } })\n } else if (selectionToUseValue === 'all') {\n setWhere({})\n }\n }, [id, selectionToUseValue, query?.where, selected, setWhere])\n\n // Hide component if no other options besides \"all\" are available\n if (availableOptions.length <= 1) {\n return null\n }\n\n return (\n <RadioGroupField\n field={{\n name: 'selectionToUse',\n type: 'radio',\n admin: {},\n // @ts-expect-error - this is not correctly typed in plugins right now\n label: t('plugin-import-export:field-selectionToUse-label'),\n options: availableOptions,\n }}\n // @ts-expect-error - this is not correctly typed in plugins right now\n label={t('plugin-import-export:field-selectionToUse-label')}\n options={availableOptions}\n path=\"selectionToUse\"\n />\n )\n}\n"],"names":["RadioGroupField","useDocumentInfo","useField","useListQuery","useSelection","useTranslation","React","useEffect","useMemo","isWhereEmpty","where","Array","isArray","and","length","or","Object","keys","SelectionToUseField","id","query","selectAll","selected","t","setValue","setSelectionToUseValue","value","selectionToUseValue","path","setWhere","hasMeaningfulFilters","availableOptions","options","label","unshift","includes","defaultSelection","ids","entries","filter","_","isSelected","map","in","field","name","type","admin"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/SortBy/index.tsx"],"sourcesContent":["'use client'\n\nimport type { SelectFieldClientComponent } from 'payload'\nimport type { ReactNode } from 'react'\n\nimport {\n FieldLabel,\n ReactSelect,\n useConfig,\n useDocumentInfo,\n useField,\n useListQuery,\n} from '@payloadcms/ui'\nimport React, { useEffect, useState } from 'react'\n\nimport { reduceFields } from '../FieldsToExport/reduceFields.js'\nimport { useImportExport } from '../ImportExportProvider/index.js'\n\nconst baseClass = 'sort-by-fields'\n\nexport const SortBy: SelectFieldClientComponent = (props) => {\n const { id } = useDocumentInfo()\n const { setValue, value } = useField<string>()\n const { value: collectionSlug } = useField<string>({ path: 'collectionSlug' })\n const { query } = useListQuery()\n const { getEntityConfig } = useConfig()\n const { collection } = useImportExport()\n\n const [displayedValue, setDisplayedValue] = useState<{\n id: string\n label: ReactNode\n value: string\n } | null>(null)\n\n const collectionConfig = getEntityConfig({ collectionSlug: collectionSlug ?? collection })\n const fieldOptions = reduceFields({ fields: collectionConfig?.fields })\n\n // Sync displayedValue with value from useField\n useEffect(() => {\n if (!value) {\n setDisplayedValue(null)\n return\n }\n\n const option = fieldOptions.find((field) => field.value === value)\n if (option && (!displayedValue || displayedValue.value !== value)) {\n setDisplayedValue(option)\n }\n }, [
|
|
1
|
+
{"version":3,"sources":["../../../src/components/SortBy/index.tsx"],"sourcesContent":["'use client'\n\nimport type { SelectFieldClientComponent } from 'payload'\nimport type { ReactNode } from 'react'\n\nimport {\n FieldLabel,\n ReactSelect,\n useConfig,\n useDocumentInfo,\n useField,\n useListQuery,\n} from '@payloadcms/ui'\nimport React, { useEffect, useState } from 'react'\n\nimport { reduceFields } from '../FieldsToExport/reduceFields.js'\nimport { useImportExport } from '../ImportExportProvider/index.js'\n\nconst baseClass = 'sort-by-fields'\n\nexport const SortBy: SelectFieldClientComponent = (props) => {\n const { id } = useDocumentInfo()\n const { setValue, value } = useField<string>()\n const { value: collectionSlug } = useField<string>({ path: 'collectionSlug' })\n const { query } = useListQuery()\n const { getEntityConfig } = useConfig()\n const { collection } = useImportExport()\n\n const [displayedValue, setDisplayedValue] = useState<{\n id: string\n label: ReactNode\n value: string\n } | null>(null)\n\n const collectionConfig = getEntityConfig({ collectionSlug: collectionSlug ?? collection })\n const fieldOptions = reduceFields({ fields: collectionConfig?.fields })\n\n // Sync displayedValue with value from useField\n useEffect(() => {\n if (!value) {\n setDisplayedValue(null)\n return\n }\n\n const option = fieldOptions.find((field) => field.value === value)\n if (option && (!displayedValue || displayedValue.value !== value)) {\n setDisplayedValue(option)\n }\n }, [displayedValue, fieldOptions, value])\n\n useEffect(() => {\n if (id || !query?.sort || value) {\n return\n }\n\n const option = fieldOptions.find((field) => field.value === query.sort)\n if (option) {\n setValue(option.value)\n setDisplayedValue(option)\n }\n }, [fieldOptions, id, query?.sort, value, setValue])\n\n const onChange = (option: { id: string; label: ReactNode; value: string } | null) => {\n if (!option) {\n setValue('')\n setDisplayedValue(null)\n } else {\n setValue(option.value)\n setDisplayedValue(option)\n }\n }\n\n return (\n <div className={baseClass} style={{ '--field-width': '33%' } as React.CSSProperties}>\n <FieldLabel label={props.field.label} path={props.path} />\n <ReactSelect\n className={baseClass}\n disabled={props.readOnly}\n getOptionValue={(option) => String(option.value)}\n inputId={`field-${props.path.replace(/\\./g, '__')}`}\n isClearable={true}\n isSortable={true}\n // @ts-expect-error react select option\n onChange={onChange}\n options={fieldOptions}\n // @ts-expect-error react select\n value={displayedValue}\n />\n </div>\n )\n}\n"],"names":["FieldLabel","ReactSelect","useConfig","useDocumentInfo","useField","useListQuery","React","useEffect","useState","reduceFields","useImportExport","baseClass","SortBy","props","id","setValue","value","collectionSlug","path","query","getEntityConfig","collection","displayedValue","setDisplayedValue","collectionConfig","fieldOptions","fields","option","find","field","sort","onChange","div","className","style","label","disabled","readOnly","getOptionValue","String","inputId","replace","isClearable","isSortable","options"],"mappings":"AAAA;;AAKA,SACEA,UAAU,EACVC,WAAW,EACXC,SAAS,EACTC,eAAe,EACfC,QAAQ,EACRC,YAAY,QACP,iBAAgB;AACvB,OAAOC,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAElD,SAASC,YAAY,QAAQ,oCAAmC;AAChE,SAASC,eAAe,QAAQ,mCAAkC;AAElE,MAAMC,YAAY;AAElB,OAAO,MAAMC,SAAqC,CAACC;IACjD,MAAM,EAAEC,EAAE,EAAE,GAAGX;IACf,MAAM,EAAEY,QAAQ,EAAEC,KAAK,EAAE,GAAGZ;IAC5B,MAAM,EAAEY,OAAOC,cAAc,EAAE,GAAGb,SAAiB;QAAEc,MAAM;IAAiB;IAC5E,MAAM,EAAEC,KAAK,EAAE,GAAGd;IAClB,MAAM,EAAEe,eAAe,EAAE,GAAGlB;IAC5B,MAAM,EAAEmB,UAAU,EAAE,GAAGX;IAEvB,MAAM,CAACY,gBAAgBC,kBAAkB,GAAGf,SAIlC;IAEV,MAAMgB,mBAAmBJ,gBAAgB;QAAEH,gBAAgBA,kBAAkBI;IAAW;IACxF,MAAMI,eAAehB,aAAa;QAAEiB,QAAQF,kBAAkBE;IAAO;IAErE,+CAA+C;IAC/CnB,UAAU;QACR,IAAI,CAACS,OAAO;YACVO,kBAAkB;YAClB;QACF;QAEA,MAAMI,SAASF,aAAaG,IAAI,CAAC,CAACC,QAAUA,MAAMb,KAAK,KAAKA;QAC5D,IAAIW,UAAW,CAAA,CAACL,kBAAkBA,eAAeN,KAAK,KAAKA,KAAI,GAAI;YACjEO,kBAAkBI;QACpB;IACF,GAAG;QAACL;QAAgBG;QAAcT;KAAM;IAExCT,UAAU;QACR,IAAIO,MAAM,CAACK,OAAOW,QAAQd,OAAO;YAC/B;QACF;QAEA,MAAMW,SAASF,aAAaG,IAAI,CAAC,CAACC,QAAUA,MAAMb,KAAK,KAAKG,MAAMW,IAAI;QACtE,IAAIH,QAAQ;YACVZ,SAASY,OAAOX,KAAK;YACrBO,kBAAkBI;QACpB;IACF,GAAG;QAACF;QAAcX;QAAIK,OAAOW;QAAMd;QAAOD;KAAS;IAEnD,MAAMgB,WAAW,CAACJ;QAChB,IAAI,CAACA,QAAQ;YACXZ,SAAS;YACTQ,kBAAkB;QACpB,OAAO;YACLR,SAASY,OAAOX,KAAK;YACrBO,kBAAkBI;QACpB;IACF;IAEA,qBACE,MAACK;QAAIC,WAAWtB;QAAWuB,OAAO;YAAE,iBAAiB;QAAM;;0BACzD,KAAClC;gBAAWmC,OAAOtB,MAAMgB,KAAK,CAACM,KAAK;gBAAEjB,MAAML,MAAMK,IAAI;;0BACtD,KAACjB;gBACCgC,WAAWtB;gBACXyB,UAAUvB,MAAMwB,QAAQ;gBACxBC,gBAAgB,CAACX,SAAWY,OAAOZ,OAAOX,KAAK;gBAC/CwB,SAAS,CAAC,MAAM,EAAE3B,MAAMK,IAAI,CAACuB,OAAO,CAAC,OAAO,OAAO;gBACnDC,aAAa;gBACbC,YAAY;gBACZ,uCAAuC;gBACvCZ,UAAUA;gBACVa,SAASnB;gBACT,gCAAgC;gBAChCT,OAAOM;;;;AAIf,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExport.d.ts","sourceRoot":"","sources":["../../src/export/createExport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAWrE,MAAM,MAAM,MAAM,GAAG;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,IAAI,GAAG,KAAK,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,cAAc,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,YAAY,SAAgB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"createExport.d.ts","sourceRoot":"","sources":["../../src/export/createExport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAWrE,MAAM,MAAM,MAAM,GAAG;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,IAAI,GAAG,KAAK,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,cAAc,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,YAAY,SAAgB,gBAAgB,kCA0PxD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/export/createExport.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-objects */\nimport type { PayloadRequest, Sort, TypedUser, Where } from 'payload'\n\nimport { stringify } from 'csv-stringify/sync'\nimport { APIError } from 'payload'\nimport { Readable } from 'stream'\n\nimport { flattenObject } from './flattenObject.js'\nimport { getCustomFieldFunctions } from './getCustomFieldFunctions.js'\nimport { getFilename } from './getFilename.js'\nimport { getSelect } from './getSelect.js'\n\nexport type Export = {\n collectionSlug: string\n /**\n * If true, enables debug logging\n */\n debug?: boolean\n drafts?: 'no' | 'yes'\n exportsCollection: string\n fields?: string[]\n format: 'csv' | 'json'\n globals?: string[]\n id: number | string\n locale?: string\n name: string\n slug: string\n sort: Sort\n user: string\n userCollection: string\n where?: Where\n}\n\nexport type CreateExportArgs = {\n /**\n * If true, stream the file instead of saving it\n */\n download?: boolean\n input: Export\n req: PayloadRequest\n user?: TypedUser\n}\n\nexport const createExport = async (args: CreateExportArgs) => {\n const {\n download,\n input: {\n id,\n name: nameArg,\n collectionSlug,\n debug = false,\n drafts,\n exportsCollection,\n fields,\n format,\n locale: localeInput,\n sort,\n user,\n where,\n },\n req: { locale: localeArg, payload },\n req,\n } = args\n\n if (debug) {\n req.payload.logger.info({\n message: 'Starting export process with args:',\n collectionSlug,\n drafts,\n fields,\n format,\n })\n }\n\n const locale = localeInput ?? localeArg\n const collectionConfig = payload.config.collections.find(({ slug }) => slug === collectionSlug)\n if (!collectionConfig) {\n throw new APIError(`Collection with slug ${collectionSlug} not found`)\n }\n\n const name = `${nameArg ?? `${getFilename()}-${collectionSlug}`}.${format}`\n const isCSV = format === 'csv'\n const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined\n\n if (debug) {\n req.payload.logger.info({ message: 'Export configuration:', name, isCSV, locale })\n }\n\n const findArgs = {\n collection: collectionSlug,\n depth: 1,\n draft: drafts === 'yes',\n limit: 100,\n locale,\n overrideAccess: false,\n page: 0,\n select,\n sort,\n user,\n where,\n }\n\n if (debug) {\n req.payload.logger.info({ message: 'Find arguments:', findArgs })\n }\n\n const toCSVFunctions = getCustomFieldFunctions({\n fields: collectionConfig.flattenedFields,\n select,\n })\n\n if (download) {\n if (debug) {\n req.payload.logger.info('Pre-scanning all columns before streaming')\n }\n\n const allColumnsSet = new Set<string>()\n const allColumns: string[] = []\n let scanPage = 1\n let hasMore = true\n\n while (hasMore) {\n const result = await payload.find({ ...findArgs, page: scanPage })\n\n result.docs.forEach((doc) => {\n const flat = flattenObject({ doc, fields, toCSVFunctions })\n Object.keys(flat).forEach((key) => {\n if (!allColumnsSet.has(key)) {\n allColumnsSet.add(key)\n allColumns.push(key)\n }\n })\n })\n\n hasMore = result.hasNextPage\n scanPage += 1\n }\n\n if (debug) {\n req.payload.logger.info(`Discovered ${allColumns.length} columns`)\n }\n\n const encoder = new TextEncoder()\n let isFirstBatch = true\n let streamPage = 1\n\n const stream = new Readable({\n async read() {\n const result = await payload.find({ ...findArgs, page: streamPage })\n\n if (debug) {\n req.payload.logger.info(`Streaming batch ${streamPage} with ${result.docs.length} docs`)\n }\n\n if (result.docs.length === 0) {\n this.push(null)\n return\n }\n\n const batchRows = result.docs.map((doc) => flattenObject({ doc, fields, toCSVFunctions }))\n\n const paddedRows = batchRows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of allColumns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n const csvString = stringify(paddedRows, {\n header: isFirstBatch,\n columns: allColumns,\n })\n\n this.push(encoder.encode(csvString))\n isFirstBatch = false\n streamPage += 1\n\n if (!result.hasNextPage) {\n if (debug) {\n req.payload.logger.info('Stream complete - no more pages')\n }\n this.push(null) // End the stream\n }\n },\n })\n\n return new Response(stream as any, {\n headers: {\n 'Content-Disposition': `attachment; filename=\"${name}\"`,\n 'Content-Type': isCSV ? 'text/csv' : 'application/json',\n },\n })\n }\n\n // Non-download path (buffered export)\n if (debug) {\n req.payload.logger.info('Starting file generation')\n }\n\n const outputData: string[] = []\n const rows: Record<string, unknown>[] = []\n const columnsSet = new Set<string>()\n const columns: string[] = []\n let page = 1\n let hasNextPage = true\n\n while (hasNextPage) {\n const result = await payload.find({\n ...findArgs,\n page,\n })\n\n if (debug) {\n req.payload.logger.info(\n `Processing batch ${findArgs.page} with ${result.docs.length} documents`,\n )\n }\n\n if (isCSV) {\n const batchRows = result.docs.map((doc) => flattenObject({ doc, fields, toCSVFunctions }))\n\n // Track discovered column keys\n batchRows.forEach((row) => {\n Object.keys(row).forEach((key) => {\n if (!columnsSet.has(key)) {\n columnsSet.add(key)\n columns.push(key)\n }\n })\n })\n\n rows.push(...batchRows)\n } else {\n const jsonInput = result.docs.map((doc) => JSON.stringify(doc))\n outputData.push(jsonInput.join(',\\n'))\n }\n\n hasNextPage = result.hasNextPage\n page += 1\n }\n\n if (isCSV) {\n const paddedRows = rows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of columns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n outputData.push(\n stringify(paddedRows, {\n header: true,\n columns,\n }),\n )\n }\n\n const buffer = Buffer.from(format === 'json' ? `[${outputData.join(',')}]` : outputData.join(''))\n if (debug) {\n req.payload.logger.info(`${format} file generation complete`)\n }\n\n if (!id) {\n if (debug) {\n req.payload.logger.info('Creating new export file')\n }\n req.file = {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv' : 'application/json',\n size: buffer.length,\n }\n } else {\n if (debug) {\n req.payload.logger.info(`Updating existing export with id: ${id}`)\n }\n await req.payload.update({\n id,\n collection: exportsCollection,\n data: {},\n file: {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv' : 'application/json',\n size: buffer.length,\n },\n user,\n })\n }\n if (debug) {\n req.payload.logger.info('Export process completed successfully')\n }\n}\n"],"names":["stringify","APIError","Readable","flattenObject","getCustomFieldFunctions","getFilename","getSelect","createExport","args","download","input","id","name","nameArg","collectionSlug","debug","drafts","exportsCollection","fields","format","locale","localeInput","sort","user","where","req","localeArg","payload","logger","info","message","collectionConfig","config","collections","find","slug","isCSV","select","Array","isArray","length","undefined","findArgs","collection","depth","draft","limit","overrideAccess","page","toCSVFunctions","flattenedFields","allColumnsSet","Set","allColumns","scanPage","hasMore","result","docs","forEach","doc","flat","Object","keys","key","has","add","push","hasNextPage","encoder","TextEncoder","isFirstBatch","streamPage","stream","read","batchRows","map","paddedRows","row","fullRow","col","csvString","header","columns","encode","Response","headers","outputData","rows","columnsSet","jsonInput","JSON","join","buffer","Buffer","from","file","data","mimetype","size","update"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/export/createExport.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-objects */\nimport type { PayloadRequest, Sort, TypedUser, Where } from 'payload'\n\nimport { stringify } from 'csv-stringify/sync'\nimport { APIError } from 'payload'\nimport { Readable } from 'stream'\n\nimport { flattenObject } from './flattenObject.js'\nimport { getCustomFieldFunctions } from './getCustomFieldFunctions.js'\nimport { getFilename } from './getFilename.js'\nimport { getSelect } from './getSelect.js'\n\nexport type Export = {\n collectionSlug: string\n /**\n * If true, enables debug logging\n */\n debug?: boolean\n drafts?: 'no' | 'yes'\n exportsCollection: string\n fields?: string[]\n format: 'csv' | 'json'\n globals?: string[]\n id: number | string\n locale?: string\n name: string\n slug: string\n sort: Sort\n user: string\n userCollection: string\n where?: Where\n}\n\nexport type CreateExportArgs = {\n /**\n * If true, stream the file instead of saving it\n */\n download?: boolean\n input: Export\n req: PayloadRequest\n user?: TypedUser\n}\n\nexport const createExport = async (args: CreateExportArgs) => {\n const {\n download,\n input: {\n id,\n name: nameArg,\n collectionSlug,\n debug = false,\n drafts,\n exportsCollection,\n fields,\n format,\n locale: localeInput,\n sort,\n user,\n where,\n },\n req: { locale: localeArg, payload },\n req,\n } = args\n\n if (debug) {\n req.payload.logger.info({\n message: 'Starting export process with args:',\n collectionSlug,\n drafts,\n fields,\n format,\n })\n }\n\n const locale = localeInput ?? localeArg\n const collectionConfig = payload.config.collections.find(({ slug }) => slug === collectionSlug)\n if (!collectionConfig) {\n throw new APIError(`Collection with slug ${collectionSlug} not found`)\n }\n\n const name = `${nameArg ?? `${getFilename()}-${collectionSlug}`}.${format}`\n const isCSV = format === 'csv'\n const select = Array.isArray(fields) && fields.length > 0 ? getSelect(fields) : undefined\n\n if (debug) {\n req.payload.logger.info({ message: 'Export configuration:', name, isCSV, locale })\n }\n\n const findArgs = {\n collection: collectionSlug,\n depth: 1,\n draft: drafts === 'yes',\n limit: 100,\n locale,\n overrideAccess: false,\n page: 0,\n select,\n sort,\n user,\n where,\n }\n\n if (debug) {\n req.payload.logger.info({ message: 'Find arguments:', findArgs })\n }\n\n const toCSVFunctions = getCustomFieldFunctions({\n fields: collectionConfig.flattenedFields,\n })\n\n if (download) {\n if (debug) {\n req.payload.logger.info('Pre-scanning all columns before streaming')\n }\n\n const allColumnsSet = new Set<string>()\n const allColumns: string[] = []\n let scanPage = 1\n let hasMore = true\n\n while (hasMore) {\n const result = await payload.find({ ...findArgs, page: scanPage })\n\n result.docs.forEach((doc) => {\n const flat = flattenObject({ doc, fields, toCSVFunctions })\n Object.keys(flat).forEach((key) => {\n if (!allColumnsSet.has(key)) {\n allColumnsSet.add(key)\n allColumns.push(key)\n }\n })\n })\n\n hasMore = result.hasNextPage\n scanPage += 1\n }\n\n if (debug) {\n req.payload.logger.info(`Discovered ${allColumns.length} columns`)\n }\n\n const encoder = new TextEncoder()\n let isFirstBatch = true\n let streamPage = 1\n\n const stream = new Readable({\n async read() {\n const result = await payload.find({ ...findArgs, page: streamPage })\n\n if (debug) {\n req.payload.logger.info(`Streaming batch ${streamPage} with ${result.docs.length} docs`)\n }\n\n if (result.docs.length === 0) {\n this.push(null)\n return\n }\n\n const batchRows = result.docs.map((doc) => flattenObject({ doc, fields, toCSVFunctions }))\n\n const paddedRows = batchRows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of allColumns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n const csvString = stringify(paddedRows, {\n header: isFirstBatch,\n columns: allColumns,\n })\n\n this.push(encoder.encode(csvString))\n isFirstBatch = false\n streamPage += 1\n\n if (!result.hasNextPage) {\n if (debug) {\n req.payload.logger.info('Stream complete - no more pages')\n }\n this.push(null) // End the stream\n }\n },\n })\n\n return new Response(stream as any, {\n headers: {\n 'Content-Disposition': `attachment; filename=\"${name}\"`,\n 'Content-Type': isCSV ? 'text/csv' : 'application/json',\n },\n })\n }\n\n // Non-download path (buffered export)\n if (debug) {\n req.payload.logger.info('Starting file generation')\n }\n\n const outputData: string[] = []\n const rows: Record<string, unknown>[] = []\n const columnsSet = new Set<string>()\n const columns: string[] = []\n let page = 1\n let hasNextPage = true\n\n while (hasNextPage) {\n const result = await payload.find({\n ...findArgs,\n page,\n })\n\n if (debug) {\n req.payload.logger.info(\n `Processing batch ${findArgs.page} with ${result.docs.length} documents`,\n )\n }\n\n if (isCSV) {\n const batchRows = result.docs.map((doc) => flattenObject({ doc, fields, toCSVFunctions }))\n\n // Track discovered column keys\n batchRows.forEach((row) => {\n Object.keys(row).forEach((key) => {\n if (!columnsSet.has(key)) {\n columnsSet.add(key)\n columns.push(key)\n }\n })\n })\n\n rows.push(...batchRows)\n } else {\n const jsonInput = result.docs.map((doc) => JSON.stringify(doc))\n outputData.push(jsonInput.join(',\\n'))\n }\n\n hasNextPage = result.hasNextPage\n page += 1\n }\n\n if (isCSV) {\n const paddedRows = rows.map((row) => {\n const fullRow: Record<string, unknown> = {}\n for (const col of columns) {\n fullRow[col] = row[col] ?? ''\n }\n return fullRow\n })\n\n outputData.push(\n stringify(paddedRows, {\n header: true,\n columns,\n }),\n )\n }\n\n const buffer = Buffer.from(format === 'json' ? `[${outputData.join(',')}]` : outputData.join(''))\n if (debug) {\n req.payload.logger.info(`${format} file generation complete`)\n }\n\n if (!id) {\n if (debug) {\n req.payload.logger.info('Creating new export file')\n }\n req.file = {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv' : 'application/json',\n size: buffer.length,\n }\n } else {\n if (debug) {\n req.payload.logger.info(`Updating existing export with id: ${id}`)\n }\n await req.payload.update({\n id,\n collection: exportsCollection,\n data: {},\n file: {\n name,\n data: buffer,\n mimetype: isCSV ? 'text/csv' : 'application/json',\n size: buffer.length,\n },\n user,\n })\n }\n if (debug) {\n req.payload.logger.info('Export process completed successfully')\n }\n}\n"],"names":["stringify","APIError","Readable","flattenObject","getCustomFieldFunctions","getFilename","getSelect","createExport","args","download","input","id","name","nameArg","collectionSlug","debug","drafts","exportsCollection","fields","format","locale","localeInput","sort","user","where","req","localeArg","payload","logger","info","message","collectionConfig","config","collections","find","slug","isCSV","select","Array","isArray","length","undefined","findArgs","collection","depth","draft","limit","overrideAccess","page","toCSVFunctions","flattenedFields","allColumnsSet","Set","allColumns","scanPage","hasMore","result","docs","forEach","doc","flat","Object","keys","key","has","add","push","hasNextPage","encoder","TextEncoder","isFirstBatch","streamPage","stream","read","batchRows","map","paddedRows","row","fullRow","col","csvString","header","columns","encode","Response","headers","outputData","rows","columnsSet","jsonInput","JSON","join","buffer","Buffer","from","file","data","mimetype","size","update"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flattenObject.d.ts","sourceRoot":"","sources":["../../src/export/flattenObject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,QAAQ,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CAC9C,CAAA;AAED,eAAO,MAAM,aAAa,6CAKvB,IAAI,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"flattenObject.d.ts","sourceRoot":"","sources":["../../src/export/flattenObject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,QAAQ,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CAC9C,CAAA;AAED,eAAO,MAAM,aAAa,6CAKvB,IAAI,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CA6H/B,CAAA"}
|