@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 +2 -2
- package/custom/ExportCsv.vue +2 -5
- package/custom/ImportCsv.vue +2 -6
- package/dist/custom/ExportCsv.vue +2 -5
- package/dist/custom/ImportCsv.vue +2 -6
- package/dist/index.js +45 -19
- package/index.ts +49 -20
- package/package.json +1 -1
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,
|
|
14
|
-
total size is 16,
|
|
13
|
+
sent 16,704 bytes received 115 bytes 33,638.00 bytes/sec
|
|
14
|
+
total size is 16,284 speedup is 0.97
|
package/custom/ExportCsv.vue
CHANGED
|
@@ -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(
|
|
62
|
-
quotes:
|
|
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
|
});
|
package/custom/ImportCsv.vue
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
62
|
-
quotes:
|
|
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
|
-
|
|
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
|
-
//
|
|
67
|
+
// prepare data for PapaParse unparse
|
|
68
68
|
const columns = this.resourceConfig.columns.filter((col) => !col.virtual);
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
82
|
-
return
|
|
83
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
const rows = data.data.map((row) => {
|
|
81
|
+
return columns.map((col) => row[col.name]);
|
|
82
|
+
});
|
|
88
83
|
|
|
89
|
-
return {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|