@manta-eu/react 0.9.0 → 0.11.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.
Files changed (46) hide show
  1. package/dist/components/datastore-management/use-datastore-status.d.ts +15 -0
  2. package/dist/components/datastore-management/use-datastore-status.d.ts.map +1 -1
  3. package/dist/components/datastore-management/use-datastore-status.js +73 -2
  4. package/dist/components/datastore-management/use-datastore-status.js.map +1 -1
  5. package/dist/components/explain-fact/ExplainFact.d.ts +2 -0
  6. package/dist/components/explain-fact/ExplainFact.d.ts.map +1 -1
  7. package/dist/components/explain-fact/ExplainFact.js +6 -10
  8. package/dist/components/explain-fact/ExplainFact.js.map +1 -1
  9. package/dist/components/fact/Fact.d.ts +16 -0
  10. package/dist/components/fact/Fact.d.ts.map +1 -0
  11. package/dist/components/fact/Fact.js +27 -0
  12. package/dist/components/fact/Fact.js.map +1 -0
  13. package/dist/globals.css +15 -0
  14. package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.d.ts.map +1 -1
  15. package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.js +2 -0
  16. package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.js.map +1 -1
  17. package/dist/routes/datastores/components/StatusBadge.d.ts +8 -6
  18. package/dist/routes/datastores/components/StatusBadge.d.ts.map +1 -1
  19. package/dist/routes/datastores/components/StatusBadge.js +59 -20
  20. package/dist/routes/datastores/components/StatusBadge.js.map +1 -1
  21. package/dist/routes/datastores/deletion-warning.d.ts +2 -0
  22. package/dist/routes/datastores/deletion-warning.d.ts.map +1 -0
  23. package/dist/routes/datastores/deletion-warning.js +8 -0
  24. package/dist/routes/datastores/deletion-warning.js.map +1 -0
  25. package/dist/routes/datastores/flatten.d.ts +8 -3
  26. package/dist/routes/datastores/flatten.d.ts.map +1 -1
  27. package/dist/routes/datastores/flatten.js +16 -11
  28. package/dist/routes/datastores/flatten.js.map +1 -1
  29. package/dist/routes/datastores/hooks/useDatastoreColumns.d.ts +12 -2
  30. package/dist/routes/datastores/hooks/useDatastoreColumns.d.ts.map +1 -1
  31. package/dist/routes/datastores/hooks/useDatastoreColumns.js +142 -95
  32. package/dist/routes/datastores/hooks/useDatastoreColumns.js.map +1 -1
  33. package/dist/routes/datastores/index.d.ts.map +1 -1
  34. package/dist/routes/datastores/index.js +48 -57
  35. package/dist/routes/datastores/index.js.map +1 -1
  36. package/package.json +12 -7
  37. package/src/app-subpaths.json +1 -0
  38. package/src/components/datastore-management/use-datastore-status.ts +137 -2
  39. package/src/components/explain-fact/ExplainFact.tsx +19 -17
  40. package/src/components/fact/Fact.tsx +103 -0
  41. package/src/routes/datastores/components/LinkUnlinkedDatastoreDialog.tsx +2 -0
  42. package/src/routes/datastores/components/StatusBadge.tsx +90 -27
  43. package/src/routes/datastores/deletion-warning.ts +7 -0
  44. package/src/routes/datastores/flatten.ts +27 -14
  45. package/src/routes/datastores/hooks/useDatastoreColumns.tsx +198 -117
  46. package/src/routes/datastores/index.tsx +67 -72
@@ -1,19 +1,18 @@
1
1
  import {
2
2
  useBringDatastoreOnlineMutation,
3
+ useContinueDatastoreDeletionMutation,
3
4
  useDeleteDatastoreMutation,
4
5
  useOrganizationLinkingQuery,
5
6
  useLinkOrganizationToProviderMutation,
6
7
  useLinkUnlinkedDatastoreMutation,
8
+ useDatastoreDeletionsQuery,
7
9
  useDatastoreTreeQuery,
8
10
  useProvisionDatastoreMutation,
9
11
  useRegisterDatastoreMutation,
10
- useRemoveDatastoreMutation,
11
12
  useRenameDatastoreGroupMutation,
12
- useRestoreDatastoreMutation,
13
13
  useUnlinkedDatastoresQuery,
14
14
  type GQLRegisterDatastoreMutationVariables,
15
15
  } from "@manta-eu/client";
16
- import { enableDatastoreRemoval } from "@manta-eu/client/shared/constants";
17
16
  import { deriveDatastoreId } from "@manta-eu/client/shared/datastore-id";
18
17
  import { parseError } from "@manta-eu/client/shared/error-utils";
19
18
  import { namesAGroup, pathSegments } from "@manta-eu/client/shared/team";
@@ -50,6 +49,7 @@ import {
50
49
  visibilityForStatusFilter,
51
50
  visibleDatastoreRows,
52
51
  type DatastoreRow,
52
+ type DatastoreRowFilter,
53
53
  type DatastoreRowVisibility,
54
54
  type ProviderFilter,
55
55
  } from "./flatten";
@@ -60,13 +60,16 @@ import {
60
60
  useDatastoreColumns,
61
61
  } from "./hooks/useDatastoreColumns";
62
62
  import { useDatastoreTable, type StatusFilter } from "./hooks/useDatastoreTable";
63
+ import { toastDeletionWarning } from "./deletion-warning";
63
64
  import { linkProviderOutcome, toastProviderWarning } from "./link-provider";
64
65
  import { Banner } from "#components/banner/index";
65
66
  import { Button } from "#components/button/index";
66
67
  import { collectDatastoreIds } from "#components/datastore-management/tree";
67
- import { useDatastoreStatusByDatastoreId } from "#components/datastore-management/use-datastore-status";
68
+ import {
69
+ useDatastoreDeletionsByDatastoreId,
70
+ useDatastoreStatusByDatastoreId,
71
+ } from "#components/datastore-management/use-datastore-status";
68
72
  import { EmptyState } from "#components/empty-state/index";
69
- import { DeleteConfirmationDialog } from "#components/layouts/DeleteConfirmationDialog";
70
73
  import { PageHeader } from "#components/layouts/page/index";
71
74
  import { RouteLayout } from "#components/layouts/RouteLayout";
72
75
  import { ScopeTabs, type ScopeTab } from "#components/scope-tabs/index";
@@ -75,6 +78,7 @@ import { TablePagination } from "#components/table-pagination/index";
75
78
  import { Tabs, TabsContent } from "#components/tabs/index";
76
79
  import { Tooltip, TooltipContent, TooltipTrigger } from "#components/tooltip/index";
77
80
  import { useDatastoreSelection } from "#hooks/useDatastoreSelection";
81
+ import { invalidateQueries } from "#lib/tanstack-query";
78
82
  import { useAuthContext } from "#providers/AuthContext";
79
83
  import { useMantaClient } from "#providers/index";
80
84
 
@@ -113,8 +117,8 @@ export function DatastoresRoute() {
113
117
  const indented = !isPresent(sorting);
114
118
 
115
119
  const [formTarget, setFormTarget] = useState<DatastoreFormTarget | null>(null);
116
- const [pendingRemoval, setPendingRemoval] = useState<DatastoreRow | null>(null);
117
120
  const [pendingDeletion, setPendingDeletion] = useState<DatastoreRow | null>(null);
121
+ const [handedOff, setHandedOff] = useState<ReadonlyMap<string, number>>(new Map());
118
122
  const [renameTarget, setRenameTarget] = useState<DatastoreRow | null>(null);
119
123
  const [linkDialogTarget, setLinkDialogTarget] = useState<string | null>(null);
120
124
  const [visibility, setVisibility] = useState<DatastoreRowVisibility>({
@@ -189,6 +193,7 @@ export function DatastoresRoute() {
189
193
  toast.success(`Datastore "${name}" is ready`);
190
194
  }
191
195
  toastProviderWarning(result.provisionDatastore.providerWarning);
196
+ toastDeletionWarning(result.provisionDatastore.deletionWarning);
192
197
  },
193
198
  onError: (error) => {
194
199
  const info = parseError(error, "Couldn't create the datastore");
@@ -196,18 +201,6 @@ export function DatastoresRoute() {
196
201
  },
197
202
  });
198
203
 
199
- const removeMutation = useRemoveDatastoreMutation(mantaClient, {
200
- onSuccess: (result) => {
201
- invalidateTree();
202
- if (result.removeDatastore.success) toast.success("Datastore removed");
203
- else toast.error("Couldn't remove the datastore", { description: result.removeDatastore.error ?? undefined });
204
- },
205
- onError: (error) => {
206
- const info = parseError(error, "Couldn't remove the datastore");
207
- toast.error(info.message, { description: info.description });
208
- },
209
- });
210
-
211
204
  const deleteMutation = useDeleteDatastoreMutation(mantaClient, {
212
205
  onSuccess: (result, variables) => {
213
206
  void refreshDatastores();
@@ -218,7 +211,11 @@ export function DatastoresRoute() {
218
211
  return;
219
212
  }
220
213
 
221
- toast.success(`"${variables.confirmName}" was deleted permanently`);
214
+ setHandedOff((previous) => new Map(previous).set(variables.datastoreId, Date.now()));
215
+ void invalidateQueries(queryClient, [useDatastoreDeletionsQuery]);
216
+ toast.success(`"${variables.confirmName}" is being deleted`, {
217
+ description: "This finishes in the background and can take a few minutes.",
218
+ });
222
219
  },
223
220
  onError: (error) => {
224
221
  setPendingDeletion(null);
@@ -227,14 +224,22 @@ export function DatastoresRoute() {
227
224
  },
228
225
  });
229
226
 
230
- const restoreMutation = useRestoreDatastoreMutation(mantaClient, {
231
- onSuccess: (result) => {
232
- invalidateTree();
233
- if (result.restoreDatastore.success) toast.success("Datastore restored");
234
- else toast.error("Couldn't restore the datastore", { description: result.restoreDatastore.error ?? undefined });
227
+ const continueDeletionMutation = useContinueDatastoreDeletionMutation(mantaClient, {
228
+ onSuccess: (result, variables) => {
229
+ void invalidateQueries(queryClient, [useDatastoreDeletionsQuery]);
230
+ const { success, error } = result.continueDatastoreDeletion;
231
+ if (!success) {
232
+ toast.error("Couldn't continue the deletion", { description: error ?? undefined });
233
+ return;
234
+ }
235
+
236
+ setHandedOff((previous) => new Map(previous).set(variables.datastoreId, Date.now()));
237
+ toast.success("The deletion is going on", {
238
+ description: "This finishes in the background and can take a few minutes.",
239
+ });
235
240
  },
236
241
  onError: (error) => {
237
- const info = parseError(error, "Couldn't restore the datastore");
242
+ const info = parseError(error, "Couldn't continue the deletion");
238
243
  toast.error(info.message, { description: info.description });
239
244
  },
240
245
  });
@@ -345,12 +350,29 @@ export function DatastoresRoute() {
345
350
  );
346
351
  const allRows = useMemo(() => [...treeRows, ...unlinkedRows], [treeRows, unlinkedRows]);
347
352
  const nestedDatastoreNames = useMemo(() => nestedDatastoreNamesByRowId(treeRows), [treeRows]);
348
- const rows = useMemo(() => visibleDatastoreRows(treeRows, visibility), [treeRows, visibility]);
353
+ const deletableDatastoreIds = useMemo(
354
+ () =>
355
+ allRows.flatMap((row) =>
356
+ isPresent(row.datastoreId) && (row.removed || row.isUnlinked === true) ? [row.datastoreId] : [],
357
+ ),
358
+ [allRows],
359
+ );
360
+ const deletionByDatastoreId = useDatastoreDeletionsByDatastoreId({
361
+ datastoreIds: deletableDatastoreIds,
362
+ enabled: !!isOperator,
363
+ onFinished: refreshDatastores,
364
+ handedOff,
365
+ });
366
+ const rowFilter = useMemo<DatastoreRowFilter>(
367
+ () => ({ rows: treeRows, visibility, deleting: new Set(Object.keys(deletionByDatastoreId)) }),
368
+ [treeRows, visibility, deletionByDatastoreId],
369
+ );
370
+ const rows = useMemo(() => visibleDatastoreRows(rowFilter), [rowFilter]);
349
371
  const unprovisionedCount = useMemo(
350
- () => hiddenRowCount(treeRows, visibility, "showUnprovisioned", rows.length),
351
- [treeRows, visibility, rows.length],
372
+ () => hiddenRowCount(rowFilter, "showUnprovisioned", rows.length),
373
+ [rowFilter, rows.length],
352
374
  );
353
- const archivedCount = useMemo(() => hiddenRemovedRowCount(treeRows, visibility), [treeRows, visibility]);
375
+ const archivedCount = useMemo(() => hiddenRemovedRowCount(rowFilter), [rowFilter]);
354
376
  const groupPathsByOrganization = useMemo(() => organizationGroupPaths(treeRows), [treeRows]);
355
377
  const removedSubtreeIds = useMemo(() => removedSubtreeRowIds(treeRows), [treeRows]);
356
378
  const providerLinkEnabled = linkingQuery.data?.organizationLinking?.linkEnabled;
@@ -446,6 +468,7 @@ export function DatastoresRoute() {
446
468
  : `Linked to the existing datastore "${result.linkUnlinkedDatastore.datastoreId}"`,
447
469
  );
448
470
  toastProviderWarning(result.linkUnlinkedDatastore.providerWarning);
471
+ toastDeletionWarning(result.linkUnlinkedDatastore.deletionWarning);
449
472
  } else {
450
473
  toast.error("Couldn't link the existing datastore", {
451
474
  description: result.linkUnlinkedDatastore.error ?? undefined,
@@ -496,13 +519,6 @@ export function DatastoresRoute() {
496
519
  if (isPresent(row.datastoreId)) setLinkDialogTarget(row.datastoreId);
497
520
  }, []);
498
521
 
499
- const onRestore = useCallback(
500
- (row: DatastoreRow) => {
501
- if (isPresent(row.datastoreId)) restoreMutation.mutate({ datastoreId: row.datastoreId });
502
- },
503
- [restoreMutation.mutate],
504
- );
505
-
506
522
  const onRegister = useCallback(
507
523
  (row: DatastoreRow) => {
508
524
  if (isPresent(row.datastoreId)) {
@@ -535,6 +551,13 @@ export function DatastoresRoute() {
535
551
  [bringOnlineMutation.mutate],
536
552
  );
537
553
 
554
+ const onContinueDeletion = useCallback(
555
+ (row: DatastoreRow) => {
556
+ if (isPresent(row.datastoreId)) continueDeletionMutation.mutate({ datastoreId: row.datastoreId });
557
+ },
558
+ [continueDeletionMutation.mutate],
559
+ );
560
+
538
561
  const onLinkProvider = useCallback(
539
562
  (row: DatastoreRow) => {
540
563
  linkProviderMutation.mutate({ organizationId: row.organizationId });
@@ -544,6 +567,7 @@ export function DatastoresRoute() {
544
567
 
545
568
  const columns = useDatastoreColumns({
546
569
  statusByDatastoreId,
570
+ deletionByDatastoreId,
547
571
  currentDatastoreId: datastore?.id ?? realmDatastoreId,
548
572
  isSwitching,
549
573
  indented,
@@ -555,9 +579,9 @@ export function DatastoresRoute() {
555
579
  onLink,
556
580
  onProvision: provisionExisting,
557
581
  onLinkExisting,
558
- onRemove: setPendingRemoval,
559
582
  onDelete: setPendingDeletion,
560
- onRestore,
583
+ onContinueDeletion,
584
+ isContinuingDeletion: continueDeletionMutation.isPending,
561
585
  onRename: setRenameTarget,
562
586
  onRegister,
563
587
  registeringDatastoreIds,
@@ -572,30 +596,19 @@ export function DatastoresRoute() {
572
596
  });
573
597
 
574
598
  const filterToggles: DatastoreFilterToggle[] = [
575
- ...(enableDatastoreRemoval
599
+ ...(showArchived || archivedCount > 0
576
600
  ? [
577
601
  {
578
602
  key: "archived",
579
- label: showArchived ? "Hide archived" : "Show archived",
580
- description: "Datastores that were removed; nothing is deleted, so they can be restored.",
603
+ label: showArchived ? "Hide removed" : `Show removed (${archivedCount})`,
604
+ description:
605
+ "Out of use: a permanent delete stopped partway, or they were removed before removal was turned off.",
581
606
  icon: showArchived ? EyeOff : Archive,
582
607
  active: showArchived,
583
608
  onToggle: () => toggleVisibility("showArchived"),
584
609
  },
585
610
  ]
586
- : showArchived || archivedCount > 0
587
- ? [
588
- {
589
- key: "archived",
590
- label: showArchived ? "Hide removed" : `Show removed (${archivedCount})`,
591
- description:
592
- "Out of use: a permanent delete stopped partway, or they were removed before removal was turned off.",
593
- icon: showArchived ? EyeOff : Archive,
594
- active: showArchived,
595
- onToggle: () => toggleVisibility("showArchived"),
596
- },
597
- ]
598
- : []),
611
+ : []),
599
612
  ...(showUnprovisioned || unprovisionedCount > 0
600
613
  ? [
601
614
  {
@@ -899,24 +912,6 @@ export function DatastoresRoute() {
899
912
  onCancel={() => setPendingDeletion(null)}
900
913
  />
901
914
  )}
902
-
903
- {pendingRemoval && isPresent(pendingRemoval.datastoreId) && (
904
- <DeleteConfirmationDialog
905
- title="Remove datastore"
906
- description={`Remove "${pendingRemoval.name}"? Its knowledge graph is taken offline and it stops appearing here. Nothing is deleted - Infisical integrations are untouched - so it can be restored later.`}
907
- confirmLabel="Remove"
908
- confirmingLabel="Removing..."
909
- open={true}
910
- onOpenChange={(nextOpen) => !nextOpen && setPendingRemoval(null)}
911
- onConfirm={() => {
912
- if (isPresent(pendingRemoval.datastoreId)) {
913
- removeMutation.mutate({ datastoreId: pendingRemoval.datastoreId });
914
- }
915
- setPendingRemoval(null);
916
- }}
917
- onCancel={() => setPendingRemoval(null)}
918
- />
919
- )}
920
915
  </RouteLayout>
921
916
  );
922
917
  }