@adminforth/import-export 1.4.7 → 1.4.9

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/build.log CHANGED
@@ -10,5 +10,5 @@ custom/package-lock.json
10
10
  custom/package.json
11
11
  custom/tsconfig.json
12
12
 
13
- sent 16,779 bytes received 115 bytes 33,788.00 bytes/sec
14
- total size is 16,359 speedup is 0.97
13
+ sent 16,704 bytes received 115 bytes 33,638.00 bytes/sec
14
+ total size is 16,284 speedup is 0.97
@@ -54,12 +54,9 @@ async function exportCsv() {
54
54
  throw new Error(resp.error);
55
55
  }
56
56
 
57
- // Parse the CSV data to ensure proper formatting
58
- const parsedData = Papa.parse(resp.data).data;
59
-
60
57
  // Generate properly formatted CSV
61
- const csvContent = '\ufeff' + Papa.unparse(parsedData, {
62
- quotes: true, // Force quotes around all fields
58
+ const csvContent = '\ufeff' + Papa.unparse(resp.data, {
59
+ quotes: resp.columnsToForceQuote, // Force quotes only certain columns (!!!not all this breaks BI/Excel tasks)
63
60
  quoteChar: '"',
64
61
  escapeChar: '"',
65
62
  });
@@ -165,6 +165,7 @@ async function importCsv() {
165
165
  Papa.parse(text, {
166
166
  header: true,
167
167
  skipEmptyLines: true,
168
+ // dynamicTyping: true, - bad option becaue it tries to parse "1" -> int even if the column is string
168
169
 
169
170
  complete: async (results) => {
170
171
  if (results.errors.length > 0) {
@@ -214,12 +215,7 @@ async function importCsv() {
214
215
  reader.readAsText(file);
215
216
  };
216
217
  }
217
- function handleImportClick() {
218
- console.log('handleImportClick', checkProgress.value);
219
- if (!checkProgress.value) {
220
- importCsv();
221
- }
222
- }
218
+
223
219
 
224
220
  function click() {
225
221
  importCsv();
@@ -54,12 +54,9 @@ async function exportCsv() {
54
54
  throw new Error(resp.error);
55
55
  }
56
56
 
57
- // Parse the CSV data to ensure proper formatting
58
- const parsedData = Papa.parse(resp.data).data;
59
-
60
57
  // Generate properly formatted CSV
61
- const csvContent = '\ufeff' + Papa.unparse(parsedData, {
62
- quotes: true, // Force quotes around all fields
58
+ const csvContent = '\ufeff' + Papa.unparse(resp.data, {
59
+ quotes: resp.columnsToForceQuote, // Force quotes only certain columns (!!!not all this breaks BI/Excel tasks)
63
60
  quoteChar: '"',
64
61
  escapeChar: '"',
65
62
  });
@@ -165,6 +165,7 @@ async function importCsv() {
165
165
  Papa.parse(text, {
166
166
  header: true,
167
167
  skipEmptyLines: true,
168
+ // dynamicTyping: true, - bad option becaue it tries to parse "1" -> int even if the column is string
168
169
 
169
170
  complete: async (results) => {
170
171
  if (results.errors.length > 0) {
@@ -214,12 +215,7 @@ async function importCsv() {
214
215
  reader.readAsText(file);
215
216
  };
216
217
  }
217
- function handleImportClick() {
218
- console.log('handleImportClick', checkProgress.value);
219
- if (!checkProgress.value) {
220
- importCsv();
221
- }
222
- }
218
+
223
219
 
224
220
  function click() {
225
221
  importCsv();
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters } from "adminforth";
10
+ import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes } from "adminforth";
11
11
  export default class ImportExport extends AdminForthPlugin {
12
12
  constructor(options) {
13
13
  super(options, import.meta.url);
@@ -64,24 +64,23 @@ export default class ImportExport extends AdminForthPlugin {
64
64
  sort,
65
65
  getTotals: true,
66
66
  });
67
- // csv export
67
+ // prepare data for PapaParse unparse
68
68
  const columns = this.resourceConfig.columns.filter((col) => !col.virtual);
69
- const escapeCSV = (value) => {
70
- if (value === null || value === undefined)
71
- return '""';
72
- const str = String(value);
73
- if (str.includes(',') || str.includes('"') || str.includes('\n')) {
74
- return `"${str.replace(/"/g, '""')}"`;
75
- }
76
- return `"${str}"`;
69
+ const columnsToForceQuote = columns.map(col => {
70
+ return col.type !== AdminForthDataTypes.FLOAT
71
+ && col.type !== AdminForthDataTypes.INTEGER
72
+ && col.type !== AdminForthDataTypes.BOOLEAN;
73
+ });
74
+ const fields = columns.map((col) => col.name);
75
+ const rows = data.data.map((row) => {
76
+ return columns.map((col) => row[col.name]);
77
+ });
78
+ return {
79
+ data: { fields, data: rows },
80
+ columnsToForceQuote,
81
+ exportedCount: data.total,
82
+ ok: true
77
83
  };
78
- let csv = data.data.map((row) => {
79
- return columns.map((col) => escapeCSV(row[col.name])).join(',');
80
- }).join('\n');
81
- // add headers
82
- const headers = columns.map((col) => escapeCSV(col.name)).join(',');
83
- csv = `${headers}\n${csv}`;
84
- return { data: csv, exportedCount: data.total, ok: true };
85
84
  })
86
85
  });
87
86
  server.endpoint({
@@ -104,14 +103,28 @@ export default class ImportExport extends AdminForthPlugin {
104
103
  return { ok: false, errors };
105
104
  }
106
105
  const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
106
+ const resourceColumns = columns.map(colName => this.resourceConfig.columns.find(c => c.name === colName));
107
107
  const columnValues = Object.values(data);
108
108
  for (let i = 0; i < columnValues[0].length; i++) {
109
109
  const row = {};
110
110
  for (let j = 0; j < columns.length; j++) {
111
- row[columns[j]] = columnValues[j][i];
111
+ const val = columnValues[j][i];
112
+ const resourceCol = resourceColumns[j];
113
+ if ((resourceCol.type === AdminForthDataTypes.INTEGER
114
+ || resourceCol.type === AdminForthDataTypes.FLOAT) && val !== '') {
115
+ // convert empty strings to null for numeric fields
116
+ row[columns[j]] = +val;
117
+ }
118
+ else if (resourceCol.type === AdminForthDataTypes.BOOLEAN && val !== '') {
119
+ row[columns[j]] = (val.toLowerCase() === 'true' || val === '1' || val === 1);
120
+ }
121
+ else {
122
+ row[columns[j]] = val;
123
+ }
112
124
  }
113
125
  rows.push(row);
114
126
  }
127
+ console.log('Prepared rows for import:', rows);
115
128
  let importedCount = 0;
116
129
  let updatedCount = 0;
117
130
  yield Promise.all(rows.map((row) => __awaiter(this, void 0, void 0, function* () {
@@ -156,11 +169,24 @@ export default class ImportExport extends AdminForthPlugin {
156
169
  return { ok: false, errors };
157
170
  }
158
171
  const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
172
+ const resourceColumns = columns.map(colName => this.resourceConfig.columns.find(c => c.name === colName));
159
173
  const columnValues = Object.values(data);
160
174
  for (let i = 0; i < columnValues[0].length; i++) {
161
175
  const row = {};
162
176
  for (let j = 0; j < columns.length; j++) {
163
- row[columns[j]] = columnValues[j][i];
177
+ const val = columnValues[j][i];
178
+ const resourceCol = resourceColumns[j];
179
+ if ((resourceCol.type === AdminForthDataTypes.INTEGER
180
+ || resourceCol.type === AdminForthDataTypes.FLOAT) && val !== '') {
181
+ // convert empty strings to null for numeric fields
182
+ row[columns[j]] = +val;
183
+ }
184
+ else if (resourceCol.type === AdminForthDataTypes.BOOLEAN && val !== '') {
185
+ row[columns[j]] = (val.toLowerCase() === 'true' || val === '1' || val === 1);
186
+ }
187
+ else {
188
+ row[columns[j]] = val;
189
+ }
164
190
  }
165
191
  rows.push(row);
166
192
  }
package/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters } from "adminforth";
1
+ import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes } from "adminforth";
2
2
  import type { IAdminForth, IHttpServer, AdminForthResourceColumn, AdminForthComponentDeclaration, AdminForthResource } from "adminforth";
3
3
  import type { PluginOptions } from './types.js';
4
4
 
@@ -66,27 +66,27 @@ export default class ImportExport extends AdminForthPlugin {
66
66
  getTotals: true,
67
67
  });
68
68
 
69
- // csv export
69
+ // prepare data for PapaParse unparse
70
70
  const columns = this.resourceConfig.columns.filter((col) => !col.virtual);
71
-
72
- const escapeCSV = (value: any) => {
73
- if (value === null || value === undefined) return '""';
74
- const str = String(value);
75
- if (str.includes(',') || str.includes('"') || str.includes('\n')) {
76
- return `"${str.replace(/"/g, '""')}"`;
77
- }
78
- return `"${str}"`;
79
- };
80
71
 
81
- let csv = data.data.map((row) => {
82
- return columns.map((col) => escapeCSV(row[col.name])).join(',');
83
- }).join('\n');
72
+ const columnsToForceQuote = columns.map(col => {
73
+ return col.type !== AdminForthDataTypes.FLOAT
74
+ && col.type !== AdminForthDataTypes.INTEGER
75
+ && col.type !== AdminForthDataTypes.BOOLEAN;
76
+ })
77
+
78
+ const fields = columns.map((col) => col.name);
84
79
 
85
- // add headers
86
- const headers = columns.map((col) => escapeCSV(col.name)).join(',');
87
- csv = `${headers}\n${csv}`;
80
+ const rows = data.data.map((row) => {
81
+ return columns.map((col) => row[col.name]);
82
+ });
88
83
 
89
- return { data: csv, exportedCount: data.total, ok: true };
84
+ return {
85
+ data: { fields, data: rows },
86
+ columnsToForceQuote,
87
+ exportedCount: data.total,
88
+ ok: true
89
+ };
90
90
  }
91
91
  });
92
92
 
@@ -115,15 +115,31 @@ export default class ImportExport extends AdminForthPlugin {
115
115
 
116
116
  const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
117
117
 
118
+ const resourceColumns = columns.map(colName => this.resourceConfig.columns.find(c => c.name === colName));
119
+
118
120
  const columnValues: any[] = Object.values(data);
119
121
  for (let i = 0; i < columnValues[0].length; i++) {
120
122
  const row = {};
121
123
  for (let j = 0; j < columns.length; j++) {
122
- row[columns[j]] = columnValues[j][i];
124
+ const val = columnValues[j][i];
125
+ const resourceCol = resourceColumns[j];
126
+
127
+ if ( (resourceCol.type === AdminForthDataTypes.INTEGER
128
+ || resourceCol.type === AdminForthDataTypes.FLOAT) && val !== ''
129
+ ) {
130
+ // convert empty strings to null for numeric fields
131
+ row[columns[j]] = +val;
132
+ } else if (resourceCol.type === AdminForthDataTypes.BOOLEAN && val !== '') {
133
+ row[columns[j]] = (val.toLowerCase() === 'true' || val === '1' || val === 1);
134
+ } else {
135
+ row[columns[j]] = val;
136
+ }
123
137
  }
124
138
  rows.push(row);
125
139
  }
126
140
 
141
+ console.log('Prepared rows for import:', rows);
142
+
127
143
  let importedCount = 0;
128
144
  let updatedCount = 0;
129
145
 
@@ -175,11 +191,24 @@ export default class ImportExport extends AdminForthPlugin {
175
191
  }
176
192
 
177
193
  const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
194
+ const resourceColumns = columns.map(colName => this.resourceConfig.columns.find(c => c.name === colName));
178
195
  const columnValues: any[] = Object.values(data);
179
196
  for (let i = 0; i < columnValues[0].length; i++) {
180
197
  const row = {};
181
198
  for (let j = 0; j < columns.length; j++) {
182
- row[columns[j]] = columnValues[j][i];
199
+ const val = columnValues[j][i];
200
+ const resourceCol = resourceColumns[j];
201
+
202
+ if ( (resourceCol.type === AdminForthDataTypes.INTEGER
203
+ || resourceCol.type === AdminForthDataTypes.FLOAT) && val !== ''
204
+ ) {
205
+ // convert empty strings to null for numeric fields
206
+ row[columns[j]] = +val;
207
+ } else if (resourceCol.type === AdminForthDataTypes.BOOLEAN && val !== '') {
208
+ row[columns[j]] = (val.toLowerCase() === 'true' || val === '1' || val === 1);
209
+ } else {
210
+ row[columns[j]] = val;
211
+ }
183
212
  }
184
213
  rows.push(row);
185
214
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/import-export",
3
- "version": "1.4.7",
3
+ "version": "1.4.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",