@v1ct0rbr/minivault-web 0.3.0 → 0.4.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.
@@ -382,7 +382,7 @@ function U({ dbInfo: e, isLoading: t, error: n, label: r }) {
382
382
  }),
383
383
  "Banco padrão não configurado no servidor minivault (variáveis",
384
384
  " ",
385
- /* @__PURE__ */ p("code", { children: "MINIVAULT_DB_*" }),
385
+ /* @__PURE__ */ p("code", { children: "BACKUP_DB_*" }),
386
386
  "). A criação e a importação usam esse banco."
387
387
  ]
388
388
  });
@@ -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
  })]
@@ -1096,31 +1114,38 @@ 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: "custom",
1132
+ children: "Custom (-Fc, recomendado)"
1133
+ }),
1134
+ /* @__PURE__ */ p("option", {
1135
+ value: "plain",
1136
+ children: "Plain SQL (texto)"
1137
+ }),
1138
+ /* @__PURE__ */ p("option", {
1139
+ value: "tar",
1140
+ children: "Tar (-Ft)"
1141
+ })
1142
+ ]
1143
+ }),
1144
+ /* @__PURE__ */ p("div", {
1145
+ className: "form-text",
1146
+ children: "Colunas marcadas como omitidas têm o conteúdo nulificado no dump — aplicado apenas quando o formato é Plain SQL (texto)."
1147
+ })
1148
+ ]
1124
1149
  })
1125
1150
  }), /* @__PURE__ */ p("div", {
1126
1151
  className: "row g-3",
@@ -1363,10 +1388,10 @@ function Y() {
1363
1388
  children: /* @__PURE__ */ m("button", {
1364
1389
  type: "button",
1365
1390
  className: "btn btn-primary",
1366
- onClick: N,
1367
- disabled: !F,
1391
+ onClick: P,
1392
+ disabled: !I,
1368
1393
  children: [
1369
- P && /* @__PURE__ */ p("span", {
1394
+ F && /* @__PURE__ */ p("span", {
1370
1395
  className: "spinner-border spinner-border-sm me-2",
1371
1396
  "aria-hidden": !0
1372
1397
  }),
@@ -1380,104 +1405,119 @@ function Y() {
1380
1405
  })
1381
1406
  ] });
1382
1407
  }
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",
1408
+ function ee({ table: e, disabled: t, selected: n, expanded: r, excluded: i, detail: a, onToggleTable: o, onToggleExpand: s, onToggleColumn: c }) {
1409
+ return /* @__PURE__ */ p("div", {
1410
+ className: `card h-100 ${n ? "border-primary" : ""}`,
1411
+ style: { minWidth: 0 },
1412
+ children: /* @__PURE__ */ m("div", {
1413
+ className: "card-body p-2 d-flex flex-column gap-1",
1414
+ children: [/* @__PURE__ */ m("div", {
1415
+ className: "d-flex align-items-center gap-2",
1416
+ children: [/* @__PURE__ */ p("input", {
1417
+ className: "form-check-input mt-0",
1391
1418
  type: "checkbox",
1392
1419
  checked: n,
1393
1420
  disabled: t,
1394
- title: t ? "Bloqueada por segurança (MINIVAULT_EXPORT_EXCLUDED_TABLES)" : void 0,
1395
- onChange: s
1396
- }),
1397
- /* @__PURE__ */ m("span", {
1398
- className: "font-monospace small",
1421
+ title: t ? "Bloqueada por segurança (BACKUP_EXPORT_EXCLUDED_TABLES)" : void 0,
1422
+ onChange: o
1423
+ }), /* @__PURE__ */ m("span", {
1424
+ className: "font-monospace small text-truncate",
1425
+ style: { minWidth: 0 },
1426
+ title: e.fullName,
1399
1427
  children: [e.fullName, e.type === "VIEW" && /* @__PURE__ */ p("span", {
1400
1428
  className: "badge text-bg-light ms-1",
1401
1429
  children: "view"
1402
1430
  })]
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", {
1431
+ })]
1432
+ }), t ? /* @__PURE__ */ m("span", {
1433
+ className: "badge text-bg-secondary text-wrap text-start",
1434
+ title: "Exportação sempre ignora esta tabela",
1435
+ children: [/* @__PURE__ */ p("i", {
1436
+ className: "bi bi-shield-lock me-1",
1437
+ "aria-hidden": !0
1438
+ }), "excluída por segurança"]
1439
+ }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("div", {
1440
+ className: "d-flex align-items-center justify-content-between gap-2",
1441
+ children: [/* @__PURE__ */ m("button", {
1413
1442
  type: "button",
1414
- className: "btn btn-sm btn-outline-secondary ms-auto",
1415
- onClick: c,
1443
+ className: "btn btn-sm btn-outline-secondary",
1444
+ onClick: s,
1416
1445
  "aria-expanded": r,
1417
1446
  children: [/* @__PURE__ */ p("i", {
1418
1447
  className: `bi ${r ? "bi-chevron-up" : "bi-chevron-down"} me-1`,
1419
1448
  "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: [
1449
+ }), r ? "Ocultar colunas" : "Colunas"]
1450
+ }), i.length > 0 && /* @__PURE__ */ m("span", {
1451
+ className: "badge text-bg-warning",
1452
+ title: "Conteúdo desta(s) coluna(s) será nulificado na exportação",
1453
+ children: [
1454
+ i.length,
1455
+ " omitida",
1456
+ i.length > 1 ? "s" : ""
1457
+ ]
1458
+ })]
1459
+ }), r && /* @__PURE__ */ m("div", {
1460
+ className: "mt-1 pt-2 border-top",
1461
+ style: {
1462
+ maxHeight: 210,
1463
+ overflowY: "auto"
1464
+ },
1465
+ children: [
1466
+ a?.isLoading && /* @__PURE__ */ p("small", {
1467
+ className: "text-muted",
1468
+ children: "Carregando colunas..."
1469
+ }),
1470
+ a?.isError && /* @__PURE__ */ m("small", {
1471
+ className: "text-danger",
1472
+ children: ["Erro: ", G(a.error)]
1473
+ }),
1474
+ a?.data && /* @__PURE__ */ m(f, { children: [a.data.columns.map((e) => /* @__PURE__ */ m("div", {
1475
+ className: "d-flex align-items-center gap-2 py-1",
1476
+ title: e.dataType,
1477
+ children: [
1478
+ /* @__PURE__ */ p("input", {
1479
+ className: "form-check-input mt-0",
1480
+ type: "checkbox",
1481
+ title: "Omitir esta coluna (conteúdo nulificado na exportação)",
1482
+ checked: i.includes(e.name),
1483
+ onChange: () => c(e.name)
1484
+ }),
1450
1485
  /* @__PURE__ */ p("span", {
1451
- className: "font-monospace",
1486
+ className: "font-monospace small text-truncate flex-grow-1",
1487
+ style: { minWidth: 0 },
1452
1488
  children: e.name
1453
1489
  }),
1454
1490
  e.primaryKey && /* @__PURE__ */ p("span", {
1455
- className: "badge text-bg-warning ms-1",
1491
+ className: "badge text-bg-warning",
1492
+ style: { fontSize: "0.6rem" },
1456
1493
  children: "PK"
1457
1494
  }),
1458
1495
  e.generated && /* @__PURE__ */ p("span", {
1459
- className: "badge text-bg-info ms-1",
1496
+ className: "badge text-bg-info",
1497
+ style: { fontSize: "0.6rem" },
1460
1498
  children: "auto"
1499
+ }),
1500
+ /* @__PURE__ */ p("span", {
1501
+ className: "small text-body-secondary text-truncate",
1502
+ style: { maxWidth: 80 },
1503
+ children: e.dataType
1461
1504
  })
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
- })]
1505
+ ]
1506
+ }, e.name)), a.data.relationships.length > 0 && /* @__PURE__ */ m("div", {
1507
+ className: "small text-body-secondary mt-2 text-truncate",
1508
+ title: a.data.relationships.map((e) => e.summary).join(" • "),
1509
+ children: [
1510
+ /* @__PURE__ */ p("i", {
1511
+ className: "bi bi-diagram-3 me-1",
1512
+ "aria-hidden": !0
1513
+ }),
1514
+ a.data.relationships.length,
1515
+ " relação(ões)"
1516
+ ]
1517
+ })] })
1518
+ ]
1519
+ })] })]
1520
+ })
1481
1521
  });
1482
1522
  }
1483
1523
  function te(e) {
@@ -79,7 +79,7 @@ export interface ImportFromStorageRequest {
79
79
  database?: DatabaseCredentials;
80
80
  storageConfig?: OriginStorageConfig;
81
81
  }
82
- /** Banco configurado no servidor via env (MINIVAULT_DB_*) e tabelas excluídas por segurança. */
82
+ /** Banco configurado no servidor via env (BACKUP_DB_*) e tabelas excluídas por segurança. */
83
83
  export interface DbInfo {
84
84
  configured: boolean;
85
85
  host: string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v1ct0rbr/minivault-web",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
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",