@grafosoft/excel-validator 1.1.6 → 1.1.8
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/README.md
CHANGED
|
@@ -52,6 +52,7 @@ export default function Page() {
|
|
|
52
52
|
environment: "https://lab.globho.com/api/v1/",
|
|
53
53
|
title: "Catálogo Cuental",
|
|
54
54
|
type: "items",
|
|
55
|
+
redirect: "",
|
|
55
56
|
};
|
|
56
57
|
|
|
57
58
|
const jsonValidator = [
|
|
@@ -86,6 +87,7 @@ type SettingsProps = {
|
|
|
86
87
|
environment: string;
|
|
87
88
|
title: string;
|
|
88
89
|
type: string;
|
|
90
|
+
redirect: string;
|
|
89
91
|
};
|
|
90
92
|
```
|
|
91
93
|
|
|
@@ -105,11 +107,20 @@ type ExcelLayoutProps = {
|
|
|
105
107
|
- `"decimal"`: valida decimal
|
|
106
108
|
- `"bool"`: valida booleano
|
|
107
109
|
- `"string(n)"`: valida texto con longitud máxima `n`
|
|
110
|
+
- `"code(n)"`: valida texto alfanumérico con longitud máxima `n`; solo admite letras y números, sin caracteres especiales
|
|
108
111
|
- `"string(yyyy-mm-dd)"`: valida formato fecha
|
|
109
112
|
- Regla opcional: prefijo `$`, por ejemplo `"$string(20)"`
|
|
110
113
|
- `{ type: "fetch", url, prop }`: valida contra catálogo remoto
|
|
111
114
|
- `{ type: "string-empty", url, prop, validation }`: permite vacío o valida con consulta remota
|
|
112
115
|
|
|
116
|
+
## Redirect después del envío
|
|
117
|
+
|
|
118
|
+
El campo `redirect` en `initData` te permite redireccionar al usuario después de que la plantilla se envía correctamente.
|
|
119
|
+
|
|
120
|
+
- Si `redirect` tiene un valor, se redirige a esa URL.
|
|
121
|
+
- Si viene vacío, la página se recarga.
|
|
122
|
+
- Esto aplica en el flujo del botón `Enviar Plantilla`.
|
|
123
|
+
|
|
113
124
|
## Configuraciones de ejemplo (tomadas de `page.tsx`)
|
|
114
125
|
|
|
115
126
|
### PLAN DE CUENTAS
|
|
@@ -236,7 +247,7 @@ const jsonValidator = [
|
|
|
236
247
|
{
|
|
237
248
|
type: "fetch",
|
|
238
249
|
url: "valueset/identificationTypes",
|
|
239
|
-
prop: "
|
|
250
|
+
prop: "code",
|
|
240
251
|
},
|
|
241
252
|
{
|
|
242
253
|
type: "string-empty",
|
|
@@ -276,7 +287,7 @@ const jsonValidator = [
|
|
|
276
287
|
{
|
|
277
288
|
type: "fetch",
|
|
278
289
|
url: "valueset/activities",
|
|
279
|
-
prop: "
|
|
290
|
+
prop: "code",
|
|
280
291
|
},
|
|
281
292
|
{
|
|
282
293
|
type: "fetch",
|
|
@@ -344,9 +355,11 @@ const jsonValidator = [
|
|
|
344
355
|
|
|
345
356
|
- `environment` debe ser una URL base válida (ejemplo: `https://lab.globho.com/`).
|
|
346
357
|
- El componente normaliza automáticamente la barra final `/`.
|
|
358
|
+
- `redirect` puede ir vacío o con la ruta final a la que quieres enviar al usuario luego del envío exitoso.
|
|
347
359
|
- Las reglas `fetch` y `string-empty` construyen URL final con:
|
|
348
360
|
- `apikey`
|
|
349
361
|
- `companyId`
|
|
362
|
+
- El contenido TXT generado usa codificación UTF-8 para conservar caracteres como `ñ` y tildes al exportar y al enviarlo en base64.
|
|
350
363
|
|
|
351
364
|
## Publicación del paquete
|
|
352
365
|
|
|
@@ -6,7 +6,6 @@ const react_1 = require("@heroui/react");
|
|
|
6
6
|
const react_2 = require("react");
|
|
7
7
|
const tb_1 = require("react-icons/tb");
|
|
8
8
|
const ExcelValidator_1 = require("./ExcelValidator");
|
|
9
|
-
const ThemeSwitcher_1 = require("./ThemeSwitcher");
|
|
10
9
|
const ExcelFile = ({ initData, fileContent, matrix, error, onFileSelected, onReset, validationErrors, onSelectError, onClearSelectedError, hasBalanceDifference = false, onApplyStringEmptyFilter, onDownloadFilteredExcel, isStringEmptyFilterApplied, hasStringEmptyDuplicateErrors, }) => {
|
|
11
10
|
var _a;
|
|
12
11
|
const [isVisible, setIsVisible] = (0, react_2.useState)(false);
|
|
@@ -29,7 +28,7 @@ const ExcelFile = ({ initData, fileContent, matrix, error, onFileSelected, onRes
|
|
|
29
28
|
}
|
|
30
29
|
return (bytes / KB).toFixed(2) + " KB";
|
|
31
30
|
};
|
|
32
|
-
return ((0, jsx_runtime_1.jsxs)("section", { className: "h-full bg-content1 p-4 border-none md:border-l border-default-200", children: [(0, jsx_runtime_1.
|
|
31
|
+
return ((0, jsx_runtime_1.jsxs)("section", { className: "h-full bg-content1 p-4 border-none md:border-l border-default-200", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "text-xl font-semibold text-default-700", children: ["Importa ", initData.title] }), error ? ((0, jsx_runtime_1.jsx)(react_1.Alert, { color: "danger", title: error, className: "mt-3", radius: "sm", hideIconWrapper: true })) : isVisible ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_1.Alert, { radius: "sm", hideIconWrapper: true, hideIcon: true, isVisible: isVisible, className: "mt-4 max-w-full overflow-hidden", classNames: {
|
|
33
32
|
mainWrapper: "min-w-0 flex-1 overflow-hidden",
|
|
34
33
|
closeButton: "shrink-0",
|
|
35
34
|
}, variant: "bordered", onClose: handleReset, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 max-w-full items-center gap-2 overflow-hidden text-default-700", children: [(0, jsx_runtime_1.jsx)(tb_1.TbFile, { className: "shrink-0", size: 28 }), " ", (0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [(0, jsx_runtime_1.jsx)("p", { className: "max-w-full truncate text-sm", title: fileContent === null || fileContent === void 0 ? void 0 : fileContent.name, children: fileContent === null || fileContent === void 0 ? void 0 : fileContent.name }), (0, jsx_runtime_1.jsx)("small", { className: "text-default-500", children: bytesFormat((_a = fileContent === null || fileContent === void 0 ? void 0 : fileContent.size) !== null && _a !== void 0 ? _a : 0) })] })] }) }), initData.type === "accounts" && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-4 space-y-2 flex md:flex-col gap-5 md:gap-0", children: [(0, jsx_runtime_1.jsx)(react_1.Button, { className: "w-full border-1", color: "warning", variant: "bordered", radius: "sm", startContent: (0, jsx_runtime_1.jsx)(tb_1.TbFilter, { size: 18 }), onPress: onApplyStringEmptyFilter, isDisabled: !hasStringEmptyDuplicateErrors || isStringEmptyFilterApplied, children: isStringEmptyFilterApplied
|
|
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ExcelValidator = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("@heroui/react");
|
|
6
|
+
const navigation_1 = require("next/navigation");
|
|
6
7
|
const react_2 = require("react");
|
|
7
8
|
const tb_1 = require("react-icons/tb");
|
|
8
9
|
const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSelectError, onClearSelectedError, hasBalanceDifference = false, }) => {
|
|
10
|
+
const { replace } = (0, navigation_1.useRouter)();
|
|
9
11
|
const [selectedErrorId, setSelectedErrorId] = (0, react_2.useState)(null);
|
|
10
12
|
const [isUploadingTemplate, setIsUploadingTemplate] = (0, react_2.useState)(false);
|
|
11
13
|
const [uploadMessage, setUploadMessage] = (0, react_2.useState)(null);
|
|
@@ -13,6 +15,7 @@ const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSel
|
|
|
13
15
|
return null;
|
|
14
16
|
}
|
|
15
17
|
const handleTXTFormat = async () => {
|
|
18
|
+
var _a;
|
|
16
19
|
setIsUploadingTemplate(true);
|
|
17
20
|
setUploadMessage(null);
|
|
18
21
|
const dataRows = matrix
|
|
@@ -24,23 +27,27 @@ const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSel
|
|
|
24
27
|
return padded.join("|");
|
|
25
28
|
});
|
|
26
29
|
const content = lines.join("\n");
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const utf8Content = `\uFEFF${content}`;
|
|
31
|
+
const base64Content = (() => {
|
|
32
|
+
const bytes = new TextEncoder().encode(utf8Content);
|
|
33
|
+
const chunkSize = 8192;
|
|
34
|
+
let binary = "";
|
|
35
|
+
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
|
|
36
|
+
const chunk = bytes.subarray(offset, offset + chunkSize);
|
|
37
|
+
binary += String.fromCharCode(...chunk);
|
|
38
|
+
}
|
|
39
|
+
return btoa(binary);
|
|
40
|
+
})();
|
|
35
41
|
try {
|
|
36
42
|
const response = await fetch(`${initData.environment}plains/upload?companyId=${initData.companyId}&apikey=${initData.apikey}`, {
|
|
37
43
|
method: "POST",
|
|
38
44
|
headers: {
|
|
39
|
-
"Content-Type": "application/json",
|
|
45
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
40
46
|
},
|
|
41
47
|
body: JSON.stringify({
|
|
42
|
-
content:
|
|
48
|
+
content: base64Content,
|
|
43
49
|
extension: "txt",
|
|
50
|
+
encoding: "utf-8",
|
|
44
51
|
name: `Plantilla ${initData.title}`,
|
|
45
52
|
type: initData.type,
|
|
46
53
|
}),
|
|
@@ -48,15 +55,21 @@ const ExcelValidator = ({ initData, fileContent, matrix, validationErrors, onSel
|
|
|
48
55
|
if (!response.ok) {
|
|
49
56
|
throw new Error("No se pudo enviar la plantilla");
|
|
50
57
|
}
|
|
58
|
+
const redirectUrl = ((_a = initData.redirect) !== null && _a !== void 0 ? _a : "").trim();
|
|
51
59
|
setUploadMessage({
|
|
52
60
|
type: "success",
|
|
53
|
-
text: "
|
|
61
|
+
text: "Se descargó y se envió la plantilla correctamente.",
|
|
54
62
|
});
|
|
63
|
+
if (redirectUrl) {
|
|
64
|
+
replace(redirectUrl);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
window.location.reload();
|
|
55
68
|
}
|
|
56
|
-
catch (
|
|
69
|
+
catch (_b) {
|
|
57
70
|
setUploadMessage({
|
|
58
71
|
type: "error",
|
|
59
|
-
text: "
|
|
72
|
+
text: "No se pudo enviar la plantilla.",
|
|
60
73
|
});
|
|
61
74
|
}
|
|
62
75
|
finally {
|