@tunghtml/strapi-plugin-export-import-clsx 1.1.0 → 1.2.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.
@@ -93,80 +93,6 @@ const ExportImportButtons = (props) => {
93
93
  return filters;
94
94
  };
95
95
 
96
- // Get selected entries from props
97
- const getSelectedEntries = () => {
98
- // Try to get selected entries from various possible props
99
- if (props.selectedEntries && props.selectedEntries.length > 0) {
100
- return props.selectedEntries;
101
- }
102
- if (props.selected && props.selected.length > 0) {
103
- return props.selected;
104
- }
105
- if (props.selection && props.selection.length > 0) {
106
- return props.selection;
107
- }
108
- const selectedIds = [];
109
- let field = "";
110
- const getHeaderKey = (i) => {
111
- const el = document.querySelector(
112
- `thead th:nth-child(${i}) button, thead th:nth-child(${i}) span`
113
- );
114
- if (!el) return "";
115
- const parts = el.textContent.trim().split(/\s+/);
116
- return parts.pop(); // last word
117
- };
118
-
119
- try {
120
- const rows = document.querySelectorAll("tbody tr");
121
- const allowedFields = [
122
- "id",
123
- "name",
124
- "title",
125
- "tickerCode",
126
- "fullName",
127
- "email",
128
- "businessEmail",
129
- "telephone",
130
- "mobile",
131
- ];
132
-
133
- let foundIndex = null;
134
-
135
- for (let i = 1; i <= 10; i++) {
136
- const headerBtn = getHeaderKey(i);
137
- if (headerBtn !== "" && allowedFields.includes(headerBtn)) {
138
- field = headerBtn;
139
- foundIndex = i;
140
- break;
141
- }
142
- }
143
-
144
- if (!foundIndex) {
145
- console.warn("No valid header column found");
146
- return [[], ""];
147
- }
148
-
149
- // gather values for selected rows
150
- rows.forEach((row) => {
151
- const checkbox = row.querySelector(
152
- 'td:nth-child(1) button[role="checkbox"]'
153
- );
154
- if (checkbox?.getAttribute("aria-checked") === "true") {
155
- const cellSpan = row.querySelector(
156
- `td:nth-child(${foundIndex}) span`
157
- );
158
- const text = cellSpan?.textContent.trim();
159
- if (text) selectedIds.push(text);
160
- }
161
- });
162
-
163
- return [selectedIds, field];
164
- } catch (e) {
165
- console.error(e);
166
- return [[], ""];
167
- }
168
- };
169
-
170
96
  const handleExport = async () => {
171
97
  const contentType = getContentType();
172
98
  if (!contentType) {
@@ -180,8 +106,7 @@ const ExportImportButtons = (props) => {
180
106
  setIsExporting(true);
181
107
  try {
182
108
  const filters = getCurrentFilters();
183
- const eventFilter = getEventFilter(); // Back to sync
184
- const [selectedEntries, selectedField] = getSelectedEntries();
109
+ const eventFilter = getEventFilter();
185
110
 
186
111
  const queryParams = new URLSearchParams({
187
112
  format: "excel",
@@ -197,12 +122,6 @@ const ExportImportButtons = (props) => {
197
122
  );
198
123
  }
199
124
 
200
- // Add selected IDs if any
201
- if (selectedEntries.length > 0) {
202
- queryParams.set("selectedIds", JSON.stringify(selectedEntries));
203
- queryParams.set("selectedField", selectedField);
204
- }
205
-
206
125
  const response = await fetch(`/export-import-clsx/export?${queryParams}`);
207
126
 
208
127
  if (response.ok) {
@@ -211,11 +130,9 @@ const ExportImportButtons = (props) => {
211
130
  const a = document.createElement("a");
212
131
  a.href = url;
213
132
 
214
- // Set filename based on selection
215
- const filename =
216
- selectedEntries.length > 0
217
- ? `${contentType.replace("api::", "")}-selected-${selectedEntries.length}-${new Date().toISOString().split("T")[0]}.xlsx`
218
- : `${contentType.replace("api::", "")}-export-${new Date().toISOString().split("T")[0]}.xlsx`;
133
+ const filename = `${contentType.replace("api::", "")}-export-${
134
+ new Date().toISOString().split("T")[0]
135
+ }.xlsx`;
219
136
 
220
137
  a.download = filename;
221
138
  document.body.appendChild(a);
@@ -225,10 +142,7 @@ const ExportImportButtons = (props) => {
225
142
 
226
143
  toggleNotification({
227
144
  type: "success",
228
- message:
229
- selectedEntries.length > 0
230
- ? `Successfully exported ${selectedEntries.length} selected entries`
231
- : "Successfully exported data",
145
+ message: "Successfully exported data",
232
146
  });
233
147
  } else {
234
148
  throw new Error("Export failed");
@@ -323,19 +237,12 @@ const ExportImportButtons = (props) => {
323
237
  // Create ref for file input
324
238
  const fileInputRef = useRef(null);
325
239
 
326
- const [selectedEntries, selectedField] = getSelectedEntries();
327
- const exportButtonText =
328
- selectedEntries.length > 0
329
- ? `Export (${selectedEntries.length})`
330
- : "Export";
331
-
332
240
  return (
333
241
  <div
334
242
  style={{
335
243
  display: "flex",
336
244
  gap: "8px",
337
245
  alignItems: "center",
338
- marginRight: "16px",
339
246
  order: -1,
340
247
  }}
341
248
  >
@@ -346,7 +253,7 @@ const ExportImportButtons = (props) => {
346
253
  variant="secondary"
347
254
  size="S"
348
255
  >
349
- {exportButtonText}
256
+ Export
350
257
  </Button>
351
258
 
352
259
  <input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tunghtml/strapi-plugin-export-import-clsx",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A powerful Strapi plugin for exporting and importing data with Excel support and advanced filtering",
5
5
  "main": "./strapi-server.js",
6
6
  "scripts": {
@@ -1,62 +1,75 @@
1
1
  module.exports = ({ strapi }) => ({
2
2
  async export(ctx) {
3
3
  try {
4
- const { format = 'excel', contentType, selectedIds, selectedField, ...filters } = ctx.query;
5
- const exportService = strapi.plugin('export-import-clsx').service('export-service');
6
-
7
- // Parse selectedIds if provided
8
- let parsedSelectedIds = [];
9
- if (selectedIds) {
10
- try {
11
- parsedSelectedIds = Array.isArray(selectedIds) ? selectedIds : JSON.parse(selectedIds);
12
- } catch (error) {
13
- strapi.log.warn('Failed to parse selectedIds:', error.message);
14
- }
15
- }
16
-
17
- if (format === 'excel') {
18
- const buffer = await exportService.exportData('excel', contentType, filters, parsedSelectedIds, selectedField);
19
-
20
- const filename = parsedSelectedIds.length > 0
21
- ? `${contentType?.replace('api::', '') || 'strapi'}-selected-${parsedSelectedIds.length}-${new Date().toISOString().split('T')[0]}.xlsx`
22
- : `${contentType?.replace('api::', '') || 'strapi'}-export-${new Date().toISOString().split('T')[0]}.xlsx`;
23
-
24
- ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
25
- ctx.set('Content-Disposition', `attachment; filename="${filename}"`);
26
-
4
+ const { format = "excel", contentType, ...filters } = ctx.query;
5
+ const exportService = strapi
6
+ .plugin("export-import-clsx")
7
+ .service("export-service");
8
+
9
+ if (format === "excel") {
10
+ const buffer = await exportService.exportData(
11
+ "excel",
12
+ contentType,
13
+ filters
14
+ );
15
+
16
+ const filename = `${
17
+ contentType?.replace("api::", "") || "strapi"
18
+ }-export-${new Date().toISOString().split("T")[0]}.xlsx`;
19
+
20
+ ctx.set(
21
+ "Content-Type",
22
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
23
+ );
24
+ ctx.set("Content-Disposition", `attachment; filename="${filename}"`);
25
+
27
26
  ctx.body = buffer;
28
27
  } else {
29
- const data = await exportService.exportData('json', contentType, filters, parsedSelectedIds);
30
-
31
- const filename = parsedSelectedIds.length > 0
32
- ? `${contentType?.replace('api::', '') || 'strapi'}-selected-${parsedSelectedIds.length}-${new Date().toISOString().split('T')[0]}.json`
33
- : `${contentType?.replace('api::', '') || 'strapi'}-export-${new Date().toISOString().split('T')[0]}.json`;
34
-
35
- ctx.set('Content-Type', 'application/json');
36
- ctx.set('Content-Disposition', `attachment; filename="${filename}"`);
37
-
28
+ const data = await exportService.exportData(
29
+ "json",
30
+ contentType,
31
+ filters
32
+ );
33
+
34
+ const filename = `${
35
+ contentType?.replace("api::", "") || "strapi"
36
+ }-export-${new Date().toISOString().split("T")[0]}.json`;
37
+
38
+ ctx.set("Content-Type", "application/json");
39
+ ctx.set("Content-Disposition", `attachment; filename="${filename}"`);
40
+
38
41
  ctx.body = JSON.stringify(data, null, 2);
39
42
  }
40
43
  } catch (error) {
41
- strapi.log.error('Export error:', error);
42
- ctx.throw(500, 'Export failed');
44
+ strapi.log.error("Export error:", error);
45
+ ctx.throw(500, "Export failed");
43
46
  }
44
47
  },
45
48
 
46
49
  async exportSingle(ctx) {
47
50
  try {
48
51
  const { contentType, id } = ctx.params;
49
- const exportService = strapi.plugin('export-import-clsx').service('export-service');
50
-
52
+ const exportService = strapi
53
+ .plugin("export-import-clsx")
54
+ .service("export-service");
55
+
51
56
  const buffer = await exportService.exportSingleEntry(contentType, id);
52
-
53
- ctx.set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
54
- ctx.set('Content-Disposition', `attachment; filename="entry-${id}-${new Date().toISOString().split('T')[0]}.xlsx"`);
55
-
57
+
58
+ ctx.set(
59
+ "Content-Type",
60
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
61
+ );
62
+ ctx.set(
63
+ "Content-Disposition",
64
+ `attachment; filename="entry-${id}-${
65
+ new Date().toISOString().split("T")[0]
66
+ }.xlsx"`
67
+ );
68
+
56
69
  ctx.body = buffer;
57
70
  } catch (error) {
58
- strapi.log.error('Export single error:', error);
59
- ctx.throw(500, 'Export failed');
71
+ strapi.log.error("Export single error:", error);
72
+ ctx.throw(500, "Export failed");
60
73
  }
61
74
  },
62
- });
75
+ });
@@ -1,13 +1,7 @@
1
1
  const XLSX = require("xlsx");
2
2
 
3
3
  module.exports = ({ strapi }) => ({
4
- async exportData(
5
- format = "json",
6
- contentType = null,
7
- rawFilters = {},
8
- selectedIds = [],
9
- selectedField = null
10
- ) {
4
+ async exportData(format = "json", contentType = null, rawFilters = {}) {
11
5
  // Normalize content type - handle both content-manager and event-manager formats
12
6
  if (contentType && !contentType.startsWith("api::")) {
13
7
  // If it's already in api:: format from event-manager, use as is
@@ -52,87 +46,67 @@ module.exports = ({ strapi }) => ({
52
46
  `Exporting ${ct} with raw filters: ${JSON.stringify(rawFilters)}`
53
47
  );
54
48
  strapi.log.info(`Parsed filters: ${JSON.stringify(parsedFilters)}`);
55
- strapi.log.info(`Selected IDs: ${JSON.stringify(selectedIds)}`);
56
49
 
57
50
  let entries = [];
58
51
  let filters = parsedFilters.filters;
59
52
 
60
- // If specific IDs are selected, export only those
61
- if (selectedIds && selectedIds.length > 0) {
53
+ // Export all entries with filters
54
+ const searchable = this.getSearchableFields(strapi.contentTypes[ct]);
55
+ const numberSearchable = this.getNumberFields(strapi.contentTypes[ct]);
56
+
57
+ if (parsedFilters._q) {
62
58
  strapi.log.info(
63
- `Exporting selected: ${JSON.stringify(selectedIds)}, field: ${selectedField}`
64
- );
65
- if (
66
- selectedField === "id" ||
67
- (strapi.contentTypes[ct].attributes[selectedField] &&
68
- ["number", "integer", "biginteger", "float", "decimal"].includes(
69
- strapi.contentTypes[ct].attributes[selectedField].type
70
- ))
71
- ) {
72
- selectedIds = selectedIds.map((id) => Number(id));
73
- }
74
- try {
75
- entries = await strapi.documents(ct).findMany({
76
- filters: {
77
- [selectedField]: { $in: selectedIds },
78
- },
79
- populate: "*",
80
- });
81
- } catch (error) {
82
- strapi.log.error(`Failed to export selected entries:`, error);
83
- }
84
- } else {
85
- // Export all entries with filters
86
- const searchable = this.getSearchableFields(strapi.contentTypes[ct]);
87
- const numberSearchable = this.getNumberFields(
88
- strapi.contentTypes[ct]
59
+ `Applying search query: ${
60
+ parsedFilters._q
61
+ } for fields: ${JSON.stringify([
62
+ ...searchable,
63
+ ...numberSearchable,
64
+ ])}`
89
65
  );
66
+ const orConditions = [];
90
67
 
91
- if (parsedFilters._q) {
92
- strapi.log.info(
93
- `Applying search query: ${parsedFilters._q} for fields: ${JSON.stringify([...searchable, ...numberSearchable])}`
68
+ if (searchable.length > 0) {
69
+ orConditions.push(
70
+ ...searchable.map((field) => ({
71
+ [field]: { $containsi: parsedFilters._q },
72
+ }))
94
73
  );
95
- const orConditions = [];
96
-
97
- if (searchable.length > 0) {
98
- orConditions.push(
99
- ...searchable.map((field) => ({
100
- [field]: { $containsi: parsedFilters._q },
101
- }))
102
- );
103
- }
104
-
105
- if (numberSearchable.length > 0 && !isNaN(parsedFilters._q)) {
106
- orConditions.push(
107
- ...numberSearchable.map((field) => ({
108
- [field]: { $eq: Number(parsedFilters._q) },
109
- }))
110
- );
111
- }
112
-
113
- if (orConditions.length > 0) {
114
- filters = {
115
- ...filters,
116
- $and: [...(filters?.$and || []), { $or: orConditions }],
117
- };
118
- }
119
74
  }
120
- strapi.log.info(`Parsed query filters: ${JSON.stringify(filters)}`);
121
- try {
122
- entries = await strapi.documents(ct).findMany({
123
- filters: { ...filters },
124
- populate: "*",
125
- });
126
- strapi.log.info(
127
- `EntityService found ${entries?.length || 0} entries`
75
+
76
+ if (numberSearchable.length > 0 && !isNaN(parsedFilters._q)) {
77
+ orConditions.push(
78
+ ...numberSearchable.map((field) => ({
79
+ [field]: { $eq: Number(parsedFilters._q) },
80
+ }))
128
81
  );
129
- } catch (error) {
130
- strapi.log.error(`Failed to query entries:`, error);
131
82
  }
83
+
84
+ if (orConditions.length > 0) {
85
+ filters = {
86
+ ...filters,
87
+ $and: [...(filters?.$and || []), { $or: orConditions }],
88
+ };
89
+ }
90
+ }
91
+
92
+ strapi.log.info(`Parsed query filters: ${JSON.stringify(filters)}`);
93
+
94
+ try {
95
+ entries = await strapi.documents(ct).findMany({
96
+ filters: { ...filters },
97
+ populate: "*",
98
+ });
99
+ strapi.log.info(
100
+ `EntityService found ${entries?.length || 0} entries`
101
+ );
102
+ } catch (error) {
103
+ strapi.log.error(`Failed to query entries:`, error);
132
104
  }
133
105
 
134
106
  strapi.log.info(
135
- `Final result: ${entries?.length || 0} entries for ${ct} (total found: ${entries?.length || 0})`
107
+ `Final result: ${
108
+ entries?.length || 0
109
+ } entries for ${ct} (total found: ${entries?.length || 0})`
136
110
  );
137
111
 
138
112
  if (entries && entries.length > 0) {
package/strapi-admin.js CHANGED
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import pluginPkg from "./package.json";
3
2
  import pluginId from "./admin/src/pluginId";
4
3
  import Initializer from "./admin/src/components/Initializer";
@@ -19,73 +18,12 @@ export default {
19
18
  },
20
19
 
21
20
  bootstrap(app) {
22
- // Try different injection methods for Strapi v5
23
- try {
24
- // Method 1: Direct injection
25
- if (app.injectContentManagerComponent) {
26
- app.injectContentManagerComponent("listView", "actions", {
27
- name: "export-import-buttons",
28
- Component: ExportImportButtons,
29
- });
30
- }
31
- // Method 2: Plugin-based injection
32
- else if (app.getPlugin) {
33
- const contentManager = app.getPlugin("content-manager");
34
- if (contentManager && contentManager.injectComponent) {
35
- contentManager.injectComponent("listView", "actions", {
36
- name: "export-import-buttons",
37
- Component: ExportImportButtons,
38
- });
39
- }
40
- }
41
- // Method 3: Global injection
42
- else if (app.addComponent) {
43
- app.addComponent(
44
- "content-manager.listView.actions",
45
- ExportImportButtons
46
- );
47
- }
48
- } catch (error) {
49
- console.warn("Failed to inject export-import buttons:", error);
50
-
51
- // Fallback: Add as menu item if injection fails
52
- app.addMenuLink({
53
- to: `/plugins/${pluginId}`,
54
- icon: () => React.createElement("span", null, "📊"),
55
- intlLabel: {
56
- id: `${pluginId}.plugin.name`,
57
- defaultMessage: "Export Import",
58
- },
59
- Component: async () => {
60
- const component = await import("./admin/src/pages/App");
61
- return component;
62
- },
63
- permissions: [],
21
+ const contentManager = app.getPlugin("content-manager");
22
+ if (contentManager && contentManager.injectComponent) {
23
+ contentManager.injectComponent("listView", "actions", {
24
+ name: "export-import-buttons",
25
+ Component: ExportImportButtons,
64
26
  });
65
27
  }
66
28
  },
67
-
68
- async registerTrads(app) {
69
- const { locales } = app;
70
-
71
- const importedTrads = await Promise.all(
72
- locales.map((locale) => {
73
- return import(`./admin/src/translations/${locale}.json`)
74
- .then(({ default: data }) => {
75
- return {
76
- data: data,
77
- locale,
78
- };
79
- })
80
- .catch(() => {
81
- return {
82
- data: {},
83
- locale,
84
- };
85
- });
86
- })
87
- );
88
-
89
- return Promise.resolve(importedTrads);
90
- },
91
29
  };
@@ -1,70 +0,0 @@
1
- import React from 'react';
2
- import ExportButton from '../ExportButton';
3
- import ImportButton from '../ImportButton';
4
-
5
- const BulkActions = ({ layout }) => {
6
- const handleExportAll = async () => {
7
- try {
8
- const contentType = layout.uid;
9
-
10
- // Get current filters from URL if any
11
- const urlParams = new URLSearchParams(window.location.search);
12
- const filters = {};
13
-
14
- // Build filters from URL params
15
- for (const [key, value] of urlParams.entries()) {
16
- if (key.startsWith('filters[')) {
17
- filters[key] = value;
18
- }
19
- }
20
-
21
- const queryString = new URLSearchParams({
22
- format: 'excel',
23
- contentType: contentType,
24
- ...filters
25
- }).toString();
26
-
27
- const response = await fetch(`/export-import-clsx/export?${queryString}`);
28
-
29
- if (response.ok) {
30
- const blob = await response.blob();
31
- const url = window.URL.createObjectURL(blob);
32
- const a = document.createElement('a');
33
- a.href = url;
34
- a.download = `${contentType.replace('api::', '')}-export-${new Date().toISOString().split('T')[0]}.xlsx`;
35
- document.body.appendChild(a);
36
- a.click();
37
- window.URL.revokeObjectURL(url);
38
- document.body.removeChild(a);
39
- } else {
40
- throw new Error('Export failed');
41
- }
42
- } catch (error) {
43
- alert('Export failed: ' + error.message);
44
- }
45
- };
46
-
47
- return React.createElement('div', {
48
- style: {
49
- display: 'flex',
50
- gap: '8px',
51
- alignItems: 'center',
52
- marginLeft: '16px'
53
- }
54
- },
55
- React.createElement('button', {
56
- onClick: handleExportAll,
57
- style: {
58
- padding: '8px 16px',
59
- backgroundColor: '#4945ff',
60
- color: 'white',
61
- border: 'none',
62
- borderRadius: '4px',
63
- cursor: 'pointer'
64
- }
65
- }, 'Export All'),
66
- React.createElement(ImportButton)
67
- );
68
- };
69
-
70
- export default BulkActions;
@@ -1,71 +0,0 @@
1
- import React, { useState } from "react";
2
- import { Button } from "@strapi/design-system";
3
- import { Download } from "@strapi/icons";
4
- import { useNotification } from "@strapi/strapi/admin";
5
-
6
- const ExportButton = ({ layout, modifiedData }) => {
7
- const [isExporting, setIsExporting] = useState(false);
8
- const { toggleNotification } = useNotification();
9
-
10
- const handleExport = async () => {
11
- try {
12
- const contentType = layout.uid;
13
- const entryId = modifiedData.id;
14
-
15
- if (!entryId) {
16
- toggleNotification({
17
- type: "warning",
18
- message: "Please save the entry first",
19
- });
20
- return;
21
- }
22
-
23
- setIsExporting(true);
24
-
25
- const response = await fetch(
26
- `/export-import-clsx/export/${contentType}/${entryId}`
27
- );
28
-
29
- if (response.ok) {
30
- const blob = await response.blob();
31
- const url = window.URL.createObjectURL(blob);
32
- const a = document.createElement("a");
33
- a.href = url;
34
- a.download = `entry-${entryId}-${new Date().toISOString().split("T")[0]}.xlsx`;
35
- document.body.appendChild(a);
36
- a.click();
37
- window.URL.revokeObjectURL(url);
38
- document.body.removeChild(a);
39
-
40
- toggleNotification({
41
- type: "success",
42
- message: "Entry exported successfully",
43
- });
44
- } else {
45
- throw new Error("Export failed");
46
- }
47
- } catch (error) {
48
- toggleNotification({
49
- type: "danger",
50
- message: `Export failed: ${error.message}`,
51
- });
52
- } finally {
53
- setIsExporting(false);
54
- }
55
- };
56
-
57
- return (
58
- <Button
59
- onClick={handleExport}
60
- loading={isExporting}
61
- startIcon={<Download />}
62
- variant="secondary"
63
- size="S"
64
- style={{ marginLeft: "8px" }}
65
- >
66
- Export Entry
67
- </Button>
68
- );
69
- };
70
-
71
- export default ExportButton;
@@ -1,81 +0,0 @@
1
- import React, { useState } from "react";
2
- import { Button } from "@strapi/design-system";
3
- import { Upload } from "@strapi/icons";
4
- import { useNotification } from "@strapi/strapi/admin";
5
-
6
- const ImportButton = () => {
7
- const [isImporting, setIsImporting] = useState(false);
8
- const { toggleNotification } = useNotification();
9
-
10
- const handleImport = async (event) => {
11
- const file = event.target.files[0];
12
- if (!file) return;
13
-
14
- setIsImporting(true);
15
- const formData = new FormData();
16
- formData.append("file", file);
17
-
18
- try {
19
- const response = await fetch("/export-import-clsx/import", {
20
- method: "POST",
21
- body: formData,
22
- });
23
-
24
- if (response.ok) {
25
- const result = await response.json();
26
- const imported = result.result.imported || 0;
27
- const errors = result.result.errors?.length || 0;
28
-
29
- if (errors > 0) {
30
- toggleNotification({
31
- type: "warning",
32
- message: `Import completed with ${errors} error(s). Imported: ${imported} entries`,
33
- });
34
- } else {
35
- toggleNotification({
36
- type: "success",
37
- message: `Import completed successfully! Imported: ${imported} entries`,
38
- });
39
- }
40
-
41
- window.location.reload();
42
- } else {
43
- throw new Error("Import failed");
44
- }
45
- } catch (error) {
46
- toggleNotification({
47
- type: "danger",
48
- message: `Import failed: ${error.message}`,
49
- });
50
- } finally {
51
- setIsImporting(false);
52
- event.target.value = "";
53
- }
54
- };
55
-
56
- return (
57
- <div style={{ display: "inline-block", marginLeft: "8px" }}>
58
- <input
59
- type="file"
60
- accept=".xlsx,.xls,.json"
61
- onChange={handleImport}
62
- disabled={isImporting}
63
- style={{ display: "none" }}
64
- id="import-file-input"
65
- />
66
- <Button
67
- as="label"
68
- htmlFor="import-file-input"
69
- loading={isImporting}
70
- startIcon={<Upload />}
71
- variant="secondary"
72
- size="S"
73
- style={{ cursor: isImporting ? "not-allowed" : "pointer" }}
74
- >
75
- Import Data
76
- </Button>
77
- </div>
78
- );
79
- };
80
-
81
- export default ImportButton;
@@ -1,14 +0,0 @@
1
- {
2
- "plugin.name": "Export Import CLSX",
3
- "plugin.description": "Export and import data with enhanced functionality",
4
- "export.title": "Export Data",
5
- "export.description": "Export all your content types data to a JSON file",
6
- "export.button": "Export Data",
7
- "export.success": "Export completed successfully",
8
- "export.error": "Export failed",
9
- "import.title": "Import Data",
10
- "import.description": "Import data from a JSON file to your Strapi instance",
11
- "import.button": "Import Data",
12
- "import.success": "Import completed successfully",
13
- "import.error": "Import failed"
14
- }