@v1ct0rbr/minivault-web 0.3.1 → 0.4.1

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.
Files changed (2) hide show
  1. package/dist/minivault-web.js +166 -120
  2. package/package.json +1 -1
@@ -927,8 +927,8 @@ function Y() {
927
927
  let e = O(), t = w(), n = T(t.data?.configured), [r, a] = o(!1), [s, c] = o(() => ({
928
928
  type: "LOCAL",
929
929
  localPath: ""
930
- })), [l, u] = o(!1), [d, h] = o({
931
- format: "custom",
930
+ })), [l, u] = o(!0), [d, h] = o({
931
+ format: "plain",
932
932
  includeData: !0,
933
933
  includeDropTable: !1,
934
934
  includeCreateTable: !0,
@@ -938,12 +938,12 @@ function Y() {
938
938
  }), [g, _] = o(() => /* @__PURE__ */ new Set()), [v, y] = o(null), [b, x] = o({}), [S, C] = o(""), D = E(v, t.data?.configured), k = i(() => new Set((t.data?.exportExcludedTables ?? []).map(te)), [t.data?.exportExcludedTables]), A = i(() => {
939
939
  let e = n.data ?? [], t = S.trim().toLowerCase();
940
940
  return t ? e.filter((e) => e.fullName.toLowerCase().includes(t)) : e;
941
- }, [n.data, S]), j = (e) => {
941
+ }, [n.data, S]), j = i(() => Object.values(b).reduce((e, t) => e + t.length, 0), [b]), M = (e) => {
942
942
  _((t) => {
943
943
  let n = new Set(t);
944
944
  return n.has(e) ? n.delete(e) : n.add(e), n;
945
945
  });
946
- }, M = (e, t) => {
946
+ }, N = (e, t) => {
947
947
  x((n) => {
948
948
  let r = n[e] ?? [], i = r.includes(t) ? r.filter((e) => e !== t) : [...r, t];
949
949
  return {
@@ -951,7 +951,7 @@ function Y() {
951
951
  [e]: i
952
952
  };
953
953
  });
954
- }, N = () => {
954
+ }, P = () => {
955
955
  let t;
956
956
  if (l) {
957
957
  t = { ...d }, g.size > 0 && (t.tables = [...g]);
@@ -964,7 +964,7 @@ function Y() {
964
964
  originStorage: r ? s : void 0,
965
965
  dumpOptions: t
966
966
  });
967
- }, P = e.isPending, F = t.data?.configured && !P;
967
+ }, F = e.isPending, I = t.data?.configured && !F;
968
968
  return /* @__PURE__ */ m("div", { children: [
969
969
  /* @__PURE__ */ m("div", {
970
970
  className: "mb-3",
@@ -973,7 +973,7 @@ function Y() {
973
973
  children: "Criar novo backup"
974
974
  }), /* @__PURE__ */ p("p", {
975
975
  className: "text-muted small mb-0",
976
- children: "O minivault usa o banco configurado no servidor (via variáveis de ambiente). Selecione tabelas e colunas a incluir/omitir no dump."
976
+ children: "O minivault usa o banco configurado no servidor (via variáveis de ambiente). Selecione as tabelas no grid e expanda um card para marcar colunas cujo conteúdo será nulificado na exportação."
977
977
  })]
978
978
  }),
979
979
  /* @__PURE__ */ p(U, {
@@ -1042,9 +1042,12 @@ function Y() {
1042
1042
  children: "Nenhuma tabela encontrada."
1043
1043
  }),
1044
1044
  /* @__PURE__ */ p("div", {
1045
- className: "list-group list-group-flush",
1045
+ className: "p-2",
1046
1046
  style: {
1047
- maxHeight: 380,
1047
+ display: "grid",
1048
+ gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))",
1049
+ gap: "0.5rem",
1050
+ maxHeight: 420,
1048
1051
  overflow: "auto"
1049
1052
  },
1050
1053
  children: A.map((e) => /* @__PURE__ */ p(ee, {
@@ -1052,17 +1055,32 @@ function Y() {
1052
1055
  disabled: k.has(e.fullName),
1053
1056
  selected: g.has(e.fullName),
1054
1057
  expanded: v === e.fullName,
1055
- showColumnsToggle: d.format === "plain",
1056
1058
  excluded: b[e.fullName] ?? [],
1057
- onToggleTable: () => j(e.fullName),
1059
+ onToggleTable: () => M(e.fullName),
1058
1060
  onToggleExpand: () => y(v === e.fullName ? null : e.fullName),
1059
- onToggleColumn: (t) => M(e.fullName, t),
1061
+ onToggleColumn: (t) => N(e.fullName, t),
1060
1062
  detail: v === e.fullName ? D : void 0
1061
1063
  }, e.fullName))
1062
1064
  }),
1063
- /* @__PURE__ */ p("div", {
1064
- className: "p-2 small text-muted border-top",
1065
- children: "Deixe tudo desmarcado para incluir todas as tabelas (exceto as bloqueadas por segurança)."
1065
+ /* @__PURE__ */ m("div", {
1066
+ className: "p-2 small border-top d-flex flex-wrap gap-2 align-items-center",
1067
+ children: [/* @__PURE__ */ m("span", {
1068
+ className: "text-muted",
1069
+ children: [/* @__PURE__ */ p("i", {
1070
+ className: "bi bi-info-circle me-1",
1071
+ "aria-hidden": !0
1072
+ }), "Deixe tudo desmarcado para incluir todas as tabelas (exceto as bloqueadas por segurança)."]
1073
+ }), j > 0 && d.format !== "plain" && /* @__PURE__ */ m("span", {
1074
+ className: "badge text-bg-warning ms-auto text-wrap text-start",
1075
+ children: [
1076
+ /* @__PURE__ */ p("i", {
1077
+ className: "bi bi-exclamation-triangle me-1",
1078
+ "aria-hidden": !0
1079
+ }),
1080
+ j,
1081
+ " coluna(s) marcada(s) serão nulificadas apenas com formato Plain SQL (texto)"
1082
+ ]
1083
+ })]
1066
1084
  })
1067
1085
  ]
1068
1086
  })]
@@ -1079,7 +1097,7 @@ function Y() {
1079
1097
  }), /* @__PURE__ */ p("label", {
1080
1098
  className: "form-check-label",
1081
1099
  htmlFor: "minivault-with-dump-options",
1082
- children: "Configurar opcoes do dump (formato, dados, indices)"
1100
+ children: "Configurar opcoes do dump (formato, dados, indices) — desmarcar envia sem opcoes (formato padrão custom/binary no servidor)"
1083
1101
  })]
1084
1102
  }),
1085
1103
  l && /* @__PURE__ */ m("div", {
@@ -1096,31 +1114,44 @@ function Y() {
1096
1114
  className: "row g-3 mb-3",
1097
1115
  children: /* @__PURE__ */ m("div", {
1098
1116
  className: "col-md-4",
1099
- children: [/* @__PURE__ */ p("label", {
1100
- className: "form-label",
1101
- children: "Formato"
1102
- }), /* @__PURE__ */ m("select", {
1103
- className: "form-select",
1104
- value: d.format,
1105
- onChange: (e) => h((t) => ({
1106
- ...t,
1107
- format: e.target.value
1108
- })),
1109
- children: [
1110
- /* @__PURE__ */ p("option", {
1111
- value: "custom",
1112
- children: "Custom (-Fc, recomendado)"
1113
- }),
1114
- /* @__PURE__ */ p("option", {
1115
- value: "plain",
1116
- children: "Plain SQL (texto)"
1117
- }),
1118
- /* @__PURE__ */ p("option", {
1119
- value: "tar",
1120
- children: "Tar (-Ft)"
1121
- })
1122
- ]
1123
- })]
1117
+ children: [
1118
+ /* @__PURE__ */ p("label", {
1119
+ className: "form-label",
1120
+ children: "Formato"
1121
+ }),
1122
+ /* @__PURE__ */ m("select", {
1123
+ className: "form-select",
1124
+ value: d.format,
1125
+ onChange: (e) => h((t) => ({
1126
+ ...t,
1127
+ format: e.target.value
1128
+ })),
1129
+ children: [
1130
+ /* @__PURE__ */ p("option", {
1131
+ value: "plain",
1132
+ children: "Plain SQL (texto, legível — padrão)"
1133
+ }),
1134
+ /* @__PURE__ */ p("option", {
1135
+ value: "custom",
1136
+ children: "Custom (-Fc, binário, mais compacto)"
1137
+ }),
1138
+ /* @__PURE__ */ p("option", {
1139
+ value: "tar",
1140
+ children: "Tar (-Ft, binário)"
1141
+ })
1142
+ ]
1143
+ }),
1144
+ /* @__PURE__ */ m("div", {
1145
+ className: "form-text",
1146
+ children: [
1147
+ "Plain gera um arquivo SQL legível (",
1148
+ /* @__PURE__ */ p("code", { children: "database_dump.sql" }),
1149
+ ") — necessário para nulificar colunas. Custom/Tar geram dump binário (",
1150
+ /* @__PURE__ */ p("code", { children: "database_dump.dump" }),
1151
+ "), não abrir como texto; usar com pg_restore."
1152
+ ]
1153
+ })
1154
+ ]
1124
1155
  })
1125
1156
  }), /* @__PURE__ */ p("div", {
1126
1157
  className: "row g-3",
@@ -1363,10 +1394,10 @@ function Y() {
1363
1394
  children: /* @__PURE__ */ m("button", {
1364
1395
  type: "button",
1365
1396
  className: "btn btn-primary",
1366
- onClick: N,
1367
- disabled: !F,
1397
+ onClick: P,
1398
+ disabled: !I,
1368
1399
  children: [
1369
- P && /* @__PURE__ */ p("span", {
1400
+ F && /* @__PURE__ */ p("span", {
1370
1401
  className: "spinner-border spinner-border-sm me-2",
1371
1402
  "aria-hidden": !0
1372
1403
  }),
@@ -1380,104 +1411,119 @@ function Y() {
1380
1411
  })
1381
1412
  ] });
1382
1413
  }
1383
- function ee({ table: e, disabled: t, selected: n, expanded: r, showColumnsToggle: i, excluded: a, detail: o, onToggleTable: s, onToggleExpand: c, onToggleColumn: l }) {
1384
- return /* @__PURE__ */ m("div", {
1385
- className: "list-group-item px-3 py-2",
1386
- children: [/* @__PURE__ */ m("div", {
1387
- className: "d-flex align-items-center gap-2",
1388
- children: [
1389
- /* @__PURE__ */ p("input", {
1390
- className: "form-check-input",
1414
+ function ee({ table: e, disabled: t, selected: n, expanded: r, excluded: i, detail: a, onToggleTable: o, onToggleExpand: s, onToggleColumn: c }) {
1415
+ return /* @__PURE__ */ p("div", {
1416
+ className: `card h-100 ${n ? "border-primary" : ""}`,
1417
+ style: { minWidth: 0 },
1418
+ children: /* @__PURE__ */ m("div", {
1419
+ className: "card-body p-2 d-flex flex-column gap-1",
1420
+ children: [/* @__PURE__ */ m("div", {
1421
+ className: "d-flex align-items-center gap-2",
1422
+ children: [/* @__PURE__ */ p("input", {
1423
+ className: "form-check-input mt-0",
1391
1424
  type: "checkbox",
1392
1425
  checked: n,
1393
1426
  disabled: t,
1394
1427
  title: t ? "Bloqueada por segurança (BACKUP_EXPORT_EXCLUDED_TABLES)" : void 0,
1395
- onChange: s
1396
- }),
1397
- /* @__PURE__ */ m("span", {
1398
- className: "font-monospace small",
1428
+ onChange: o
1429
+ }), /* @__PURE__ */ m("span", {
1430
+ className: "font-monospace small text-truncate",
1431
+ style: { minWidth: 0 },
1432
+ title: e.fullName,
1399
1433
  children: [e.fullName, e.type === "VIEW" && /* @__PURE__ */ p("span", {
1400
1434
  className: "badge text-bg-light ms-1",
1401
1435
  children: "view"
1402
1436
  })]
1403
- }),
1404
- t && /* @__PURE__ */ m("span", {
1405
- className: "badge text-bg-secondary ms-auto",
1406
- title: "Exportação sempre ignora esta tabela",
1407
- children: [/* @__PURE__ */ p("i", {
1408
- className: "bi bi-shield-lock me-1",
1409
- "aria-hidden": !0
1410
- }), "excluída"]
1411
- }),
1412
- !t && /* @__PURE__ */ m("button", {
1437
+ })]
1438
+ }), t ? /* @__PURE__ */ m("span", {
1439
+ className: "badge text-bg-secondary text-wrap text-start",
1440
+ title: "Exportação sempre ignora esta tabela",
1441
+ children: [/* @__PURE__ */ p("i", {
1442
+ className: "bi bi-shield-lock me-1",
1443
+ "aria-hidden": !0
1444
+ }), "excluída por segurança"]
1445
+ }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("div", {
1446
+ className: "d-flex align-items-center justify-content-between gap-2",
1447
+ children: [/* @__PURE__ */ m("button", {
1413
1448
  type: "button",
1414
- className: "btn btn-sm btn-outline-secondary ms-auto",
1415
- onClick: c,
1449
+ className: "btn btn-sm btn-outline-secondary",
1450
+ onClick: s,
1416
1451
  "aria-expanded": r,
1417
1452
  children: [/* @__PURE__ */ p("i", {
1418
1453
  className: `bi ${r ? "bi-chevron-up" : "bi-chevron-down"} me-1`,
1419
1454
  "aria-hidden": !0
1420
- }), r ? "Ocultar" : "Colunas"]
1421
- })
1422
- ]
1423
- }), r && /* @__PURE__ */ m("div", {
1424
- className: "mt-2 ps-3",
1425
- children: [
1426
- o?.isLoading && /* @__PURE__ */ p("small", {
1427
- className: "text-muted",
1428
- children: "Carregando colunas..."
1429
- }),
1430
- o?.isError && /* @__PURE__ */ m("small", {
1431
- className: "text-danger",
1432
- children: ["Erro: ", G(o.error)]
1433
- }),
1434
- o?.data && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("table", {
1435
- className: "table table-sm small mb-2",
1436
- children: [/* @__PURE__ */ p("thead", { children: /* @__PURE__ */ m("tr", { children: [
1437
- i && /* @__PURE__ */ p("th", { style: { width: 30 } }),
1438
- /* @__PURE__ */ p("th", { children: "Coluna" }),
1439
- /* @__PURE__ */ p("th", { children: "Tipo" }),
1440
- /* @__PURE__ */ p("th", { children: "Null" })
1441
- ] }) }), /* @__PURE__ */ p("tbody", { children: o.data.columns.map((e) => /* @__PURE__ */ m("tr", { children: [
1442
- i && /* @__PURE__ */ p("td", { children: /* @__PURE__ */ p("input", {
1443
- className: "form-check-input",
1444
- type: "checkbox",
1445
- title: "Omitir esta coluna na exportação",
1446
- checked: a.includes(e.name),
1447
- onChange: () => l(e.name)
1448
- }) }),
1449
- /* @__PURE__ */ m("td", { children: [
1455
+ }), r ? "Ocultar colunas" : "Colunas"]
1456
+ }), i.length > 0 && /* @__PURE__ */ m("span", {
1457
+ className: "badge text-bg-warning",
1458
+ title: "Conteúdo desta(s) coluna(s) será nulificado na exportação",
1459
+ children: [
1460
+ i.length,
1461
+ " omitida",
1462
+ i.length > 1 ? "s" : ""
1463
+ ]
1464
+ })]
1465
+ }), r && /* @__PURE__ */ m("div", {
1466
+ className: "mt-1 pt-2 border-top",
1467
+ style: {
1468
+ maxHeight: 210,
1469
+ overflowY: "auto"
1470
+ },
1471
+ children: [
1472
+ a?.isLoading && /* @__PURE__ */ p("small", {
1473
+ className: "text-muted",
1474
+ children: "Carregando colunas..."
1475
+ }),
1476
+ a?.isError && /* @__PURE__ */ m("small", {
1477
+ className: "text-danger",
1478
+ children: ["Erro: ", G(a.error)]
1479
+ }),
1480
+ a?.data && /* @__PURE__ */ m(f, { children: [a.data.columns.map((e) => /* @__PURE__ */ m("div", {
1481
+ className: "d-flex align-items-center gap-2 py-1",
1482
+ title: e.dataType,
1483
+ children: [
1484
+ /* @__PURE__ */ p("input", {
1485
+ className: "form-check-input mt-0",
1486
+ type: "checkbox",
1487
+ title: "Omitir esta coluna (conteúdo nulificado na exportação)",
1488
+ checked: i.includes(e.name),
1489
+ onChange: () => c(e.name)
1490
+ }),
1450
1491
  /* @__PURE__ */ p("span", {
1451
- className: "font-monospace",
1492
+ className: "font-monospace small text-truncate flex-grow-1",
1493
+ style: { minWidth: 0 },
1452
1494
  children: e.name
1453
1495
  }),
1454
1496
  e.primaryKey && /* @__PURE__ */ p("span", {
1455
- className: "badge text-bg-warning ms-1",
1497
+ className: "badge text-bg-warning",
1498
+ style: { fontSize: "0.6rem" },
1456
1499
  children: "PK"
1457
1500
  }),
1458
1501
  e.generated && /* @__PURE__ */ p("span", {
1459
- className: "badge text-bg-info ms-1",
1502
+ className: "badge text-bg-info",
1503
+ style: { fontSize: "0.6rem" },
1460
1504
  children: "auto"
1505
+ }),
1506
+ /* @__PURE__ */ p("span", {
1507
+ className: "small text-body-secondary text-truncate",
1508
+ style: { maxWidth: 80 },
1509
+ children: e.dataType
1461
1510
  })
1462
- ] }),
1463
- /* @__PURE__ */ p("td", {
1464
- className: "text-body-secondary",
1465
- children: e.dataType
1466
- }),
1467
- /* @__PURE__ */ p("td", { children: e.nullable ? "sim" : "não" })
1468
- ] }, e.name)) })]
1469
- }), o.data.relationships.length > 0 && /* @__PURE__ */ m("div", {
1470
- className: "small text-body-secondary",
1471
- children: [/* @__PURE__ */ p("i", {
1472
- className: "bi bi-diagram-3 me-1",
1473
- "aria-hidden": !0
1474
- }), o.data.relationships.map((e) => /* @__PURE__ */ p("div", {
1475
- className: "ms-4 font-monospace",
1476
- children: e.summary
1477
- }, `${e.constraintName}-${e.fromTable}-${e.toTable}`))]
1478
- })] })
1479
- ]
1480
- })]
1511
+ ]
1512
+ }, e.name)), a.data.relationships.length > 0 && /* @__PURE__ */ m("div", {
1513
+ className: "small text-body-secondary mt-2 text-truncate",
1514
+ title: a.data.relationships.map((e) => e.summary).join(" • "),
1515
+ children: [
1516
+ /* @__PURE__ */ p("i", {
1517
+ className: "bi bi-diagram-3 me-1",
1518
+ "aria-hidden": !0
1519
+ }),
1520
+ a.data.relationships.length,
1521
+ " relação(ões)"
1522
+ ]
1523
+ })] })
1524
+ ]
1525
+ })] })]
1526
+ })
1481
1527
  });
1482
1528
  }
1483
1529
  function te(e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v1ct0rbr/minivault-web",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "Módulo independente de gerenciamento de backups (minivault). Consumível como pacote npm em qualquer app React. Cliente do minivault REST API (acesso tipicamente via proxy autenticado).",
5
5
  "author": "Victor Queiroga (https://www.linkedin.com/in/victor-queiroga)",
6
6
  "license": "MIT",