From 139e0242475daeea8474c815df9f670195bcd13b Mon Sep 17 00:00:00 2001 From: Finley Garton Date: Thu, 3 Mar 2022 14:55:39 +0000 Subject: [PATCH 1/8] added frontend group export UI --- admin/src/containers/GroupExport/index.js | 175 +++++++++++++++++++ admin/src/containers/SingleExport/index.js | 187 +++++++++++++++++++++ admin/src/hooks/useExportFormat.js | 20 +++ admin/src/hooks/useExportOptions.js | 29 ++++ yarn.lock | 23 +++ 5 files changed, 434 insertions(+) create mode 100644 admin/src/containers/GroupExport/index.js create mode 100644 admin/src/containers/SingleExport/index.js create mode 100644 admin/src/hooks/useExportFormat.js create mode 100644 admin/src/hooks/useExportOptions.js create mode 100644 yarn.lock diff --git a/admin/src/containers/GroupExport/index.js b/admin/src/containers/GroupExport/index.js new file mode 100644 index 0000000..7014a16 --- /dev/null +++ b/admin/src/containers/GroupExport/index.js @@ -0,0 +1,175 @@ +/* + * + * GroupExport + * + */ + +import React, { memo, useState, useMemo } from "react"; +import PropTypes from "prop-types"; + +import { Row } from "../../components/common"; +import { Select, Label, Button } from "@buffetjs/core"; + +import pluginId from "../../pluginId"; +import { request, auth } from "strapi-helper-plugin"; + +import { Collapse } from "reactstrap"; +import { FilterIcon } from "strapi-helper-plugin"; +import OptionsExport from "../../components/OptionsExport"; +import useExportFormats from "../../hooks/useExportFormat"; +import useExportOptions from "../../hooks/useExportOptions"; + +function GroupExport({ contentTypes, setIsLoading }) { + const [targets, setTargets] = useState( + contentTypes.reduce((acc, type) => ({ + ...acc, [type.uid]: { + enabled: true, + label: info.label || apiID, + } + }), {}) + ); + + const { + exportFormat, + setExportFormat, + exportFormatsOptions, + } = useExportFormats(); + + const { + options, + isOptionsOpen, + setIsOptionsOpen, + updateOption, + } = useExportOptions(); + + const handleSelectExportFormat = ({ target: { value } }) => { + setExportFormat(value); + }; + + const getContent = async () => { + if (sourceExports === "") + return strapi.notification.toggle({ + type: "warning", + message: "export.source.empty", + }); + + try { + setIsLoading(true); + + const token = auth.getToken(); + + const response = await fetch(`/${pluginId}/export-multi`, { + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + }, + body: { + targets: Object.keys(targets).filter(uid => targets[uid].enabled), + type: exportFormat, + options + }, + }); + + const blob = await response.blob(); + + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `export.zip`; + document.body.appendChild(a); + a.click(); + a.remove(); + + setContentToExport(data); + } catch (error) { + strapi.notification.toggle({ + type: "warning", + message: `export.items.error`, + }); + } + + setIsLoading(false); + }; + + return ( + <> + +
+ +
    + {Object.keys(targets).map(current => { + return ( +
  • + { + setTargets(prevState => ({ + ...prevState, + [name]: { + enabled: value, + ...targets[current] + }, + })); + }} + /> +
  • + ); + })} +
+
+
+ +
+ + +
+
+ + -
-
- - {exportType === 'single' && ( - + )} - c {exportType === 'group' && ( - + )} ) diff --git a/admin/src/containers/GroupExport/index.js b/admin/src/containers/GroupExport/index.js index 8695f70..fc9a4f3 100644 --- a/admin/src/containers/GroupExport/index.js +++ b/admin/src/containers/GroupExport/index.js @@ -8,7 +8,7 @@ import React, { memo, useState, useMemo } from "react"; import PropTypes from "prop-types"; import { Row } from "../../components/common"; -import { Select, Label, Button } from "@buffetjs/core"; +import { Select, Label, Button, Checkbox } from "@buffetjs/core"; import pluginId from "../../pluginId"; import { request, auth } from "strapi-helper-plugin"; @@ -24,7 +24,7 @@ function GroupExport({ contentTypes, setIsLoading }) { contentTypes.reduce((acc, type) => ({ ...acc, [type.uid]: { enabled: true, - label: info.label || apiID, + label: type.info.label || apiID, } }), {}) ); @@ -47,7 +47,7 @@ function GroupExport({ contentTypes, setIsLoading }) { }; const getContent = async () => { - if (sourceExports === "") + if (Object.keys(targets).every(uid => !targets[uid].enabled)) return strapi.notification.toggle({ type: "warning", message: "export.source.empty", @@ -63,24 +63,24 @@ function GroupExport({ contentTypes, setIsLoading }) { headers: { Authorization: `Bearer ${token}`, }, - body: { - targets: contentTypes.filter(({ uid }) => !!targets[uid]), + body: JSON.stringify({ + targets: contentTypes.filter(({ uid }) => !!targets[uid].enabled), type: exportFormat, options - }, + }), }); - const blob = await response.blob(); - - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = `export.zip`; - document.body.appendChild(a); - a.click(); - a.remove(); + if (response.status === 200) { + const blob = await response.blob(); - setContentToExport(data); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `export.zip`; + document.body.appendChild(a); + a.click(); + a.remove(); + } } catch (error) { strapi.notification.toggle({ type: "warning", @@ -96,28 +96,26 @@ function GroupExport({ contentTypes, setIsLoading }) {
-
    - {Object.keys(targets).map(current => { - return ( -
  • - { - setTargets(prevState => ({ - ...prevState, - [name]: { - enabled: value, - ...targets[current] - }, - })); - }} - /> -
  • - ); - })} -
+ {Object.keys(targets).map(current => { + return ( +
+ { + setTargets(prevState => ({ + ...prevState, + [current]: { + ...targets[current], + enabled: value, + }, + })); + }} + /> +
+ ); + })}
diff --git a/admin/src/hooks/useExportFormat.js b/admin/src/hooks/useExportFormat.js index bc39afb..3ac6e2b 100644 --- a/admin/src/hooks/useExportFormat.js +++ b/admin/src/hooks/useExportFormat.js @@ -13,7 +13,6 @@ function useExportFormats(defaultFormat = "application/json") { exportFormat, setExportFormat, exportFormatsOptions, - getExtension } } diff --git a/controllers/import-export-content.js b/controllers/import-export-content.js index 8bfa866..d7fdda6 100644 --- a/controllers/import-export-content.js +++ b/controllers/import-export-content.js @@ -105,7 +105,7 @@ module.exports = { }, exportItemsMulti: async (ctx) => { - const { targets, type, options } = ctx.request.body; + const { targets, type, options } = JSON.parse(ctx.request.body); if (!targets || !type || !options) { return ctx.throw(400, "Required parameters missing"); @@ -113,39 +113,29 @@ module.exports = { const { userAbility } = ctx.state; - const zip = new JSZip(); - const service = getService(); - - const operations = []; - const createOperation = async (target) => { - const data = await service.exportItem({ - target, - options, - type, - }, ctx); + try { + const zip = new JSZip(); + const service = getService(); - zip.file(`${target.uid}.${mimeExtension(type)}`, data); - } + const createOperation = async (target) => { + const data = await service.exportItems({ + target, + options, + type, + }, ctx); - for (const target of targets) { - if (userAbility.cannot(PERMISSIONS.read, target)) { - return ctx.forbidden(); + zip.file(`${target.info.name}.${mimeExtension(type)}`, data); } - } - - for (const target of targets) { - this.operations.push(createOperation(target)); - } - try { - await Promise.all(operations); + for (const target of targets) { + if (userAbility.cannot(PERMISSIONS.read, target.uid)) { + return ctx.forbidden(); + } + } - const blob = await zip.generateAsync({ type: 'blob' }) - const buffer = Buffer.from(blob.arrayBuffer()); + await Promise.all(targets.map(createOperation)); - ctx.writeHead(200, { - "Content-Type": "application/zip", - }); + const buffer = await zip.generateAsync({ type: 'nodebuffer' }); ctx.send(buffer); } catch (error) { diff --git a/services/utils/mimeExtension.js b/services/utils/mimeExtension.js index 648284f..470fa89 100644 --- a/services/utils/mimeExtension.js +++ b/services/utils/mimeExtension.js @@ -1,13 +1,13 @@ -function mimeExtension() { +function mimeExtension(type) { switch (type) { case "text/csv": case "application/vnd.ms-excel": { return 'csv'; } case "application/json": { - return '.json' + return 'json' } } } -export default mimeExtension; \ No newline at end of file +module.exports = mimeExtension; \ No newline at end of file From 9b4474ec9f63b6c3b93d31bd00b52613025132bb Mon Sep 17 00:00:00 2001 From: Finley Garton Date: Thu, 3 Mar 2022 17:14:58 +0000 Subject: [PATCH 7/8] renamed package name --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 291f791..f8c6f78 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "strapi-plugin-import-export-content", + "name": "strapi-plugin-import-export-content-fogldn", "version": "0.4.2", "description": "This is a plugin for import and export content of collection types.", "license": "MIT", @@ -42,4 +42,4 @@ "url": "https://github.com/EdisonPeM/strapi-plugin-import-export-content/issues" }, "homepage": "https://github.com/EdisonPeM/strapi-plugin-import-export-content#readme" -} +} \ No newline at end of file From eb6589b512844fbff193a1a55e17f4c6f257d731 Mon Sep 17 00:00:00 2001 From: Finley Garton Date: Thu, 3 Mar 2022 17:44:46 +0000 Subject: [PATCH 8/8] reverted package name --- controllers/import-export-content.js | 3 +-- package.json | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/controllers/import-export-content.js b/controllers/import-export-content.js index d7fdda6..fe480c7 100644 --- a/controllers/import-export-content.js +++ b/controllers/import-export-content.js @@ -115,10 +115,9 @@ module.exports = { try { const zip = new JSZip(); - const service = getService(); const createOperation = async (target) => { - const data = await service.exportItems({ + const data = await getService().exportItems({ target, options, type, diff --git a/package.json b/package.json index a54e5ff..a272023 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "strapi-plugin-import-export-content-fogldn", - "version": "0.4.2", + "name": "strapi-plugin-import-export-content", + "version": "0.4.3", "description": "This is a plugin for import and export content of collection types.", "license": "MIT", "strapi": {