@trops/dash-core 0.1.594 → 0.1.595
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/dist/index.esm.js +118 -19
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +118 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -60512,6 +60512,37 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
60512
60512
|
|
|
60513
60513
|
// Snapshot of the workspace before editing — used to restore on Cancel
|
|
60514
60514
|
var originalWorkspaceRef = React.useRef(null);
|
|
60515
|
+
|
|
60516
|
+
// ─── Unsaved-changes guard (Phase 2B) ────────────────────────────
|
|
60517
|
+
// Single source of truth for "is the user mid-edit with un-saved
|
|
60518
|
+
// work?". Edit mode (`previewMode === false`) is necessary; a
|
|
60519
|
+
// populated `currentWorkspaceRef` is sufficient — the layout
|
|
60520
|
+
// builder mutates that ref on every drag/drop/widget change.
|
|
60521
|
+
//
|
|
60522
|
+
// The flag is mirrored to `globalThis.__dashboardIsDirty` so the
|
|
60523
|
+
// Electron main process can poll it synchronously during window
|
|
60524
|
+
// close + app-quit handlers without an IPC round-trip.
|
|
60525
|
+
//
|
|
60526
|
+
// A `pendingNavigation` object captures a navigation request that
|
|
60527
|
+
// arrived while dirty so the user can choose to discard or keep
|
|
60528
|
+
// editing. Shapes:
|
|
60529
|
+
// { kind: "open-workspace", workspace } — sidebar switch
|
|
60530
|
+
// { kind: "cancel-edit" } — Cancel button
|
|
60531
|
+
var _useState57 = React.useState(null),
|
|
60532
|
+
_useState58 = _slicedToArray(_useState57, 2),
|
|
60533
|
+
pendingNavigation = _useState58[0],
|
|
60534
|
+
setPendingNavigation = _useState58[1];
|
|
60535
|
+
var isDirty = previewMode === false && currentWorkspaceRef.current !== null;
|
|
60536
|
+
React.useEffect(function () {
|
|
60537
|
+
if (typeof globalThis !== "undefined") {
|
|
60538
|
+
globalThis.__dashboardIsDirty = isDirty;
|
|
60539
|
+
}
|
|
60540
|
+
return function () {
|
|
60541
|
+
if (typeof globalThis !== "undefined") {
|
|
60542
|
+
globalThis.__dashboardIsDirty = false;
|
|
60543
|
+
}
|
|
60544
|
+
};
|
|
60545
|
+
}, [isDirty]);
|
|
60515
60546
|
React.useEffect(function () {
|
|
60516
60547
|
isLoadingWorkspaces === false && loadWorkspaces();
|
|
60517
60548
|
isLoadingMenuItems === false && loadMenuItems();
|
|
@@ -60599,10 +60630,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
60599
60630
|
// We record the requested ID and open it once it appears in
|
|
60600
60631
|
// workspaceConfig — handles the case where the workspace was just
|
|
60601
60632
|
// created and the config reload is still in flight.
|
|
60602
|
-
var
|
|
60603
|
-
|
|
60604
|
-
pendingOpenWorkspaceId =
|
|
60605
|
-
setPendingOpenWorkspaceId =
|
|
60633
|
+
var _useState59 = React.useState(null),
|
|
60634
|
+
_useState60 = _slicedToArray(_useState59, 2),
|
|
60635
|
+
pendingOpenWorkspaceId = _useState60[0],
|
|
60636
|
+
setPendingOpenWorkspaceId = _useState60[1];
|
|
60606
60637
|
React.useEffect(function () {
|
|
60607
60638
|
var handler = function handler(e) {
|
|
60608
60639
|
var _e$detail2;
|
|
@@ -60859,6 +60890,29 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
60859
60890
|
});
|
|
60860
60891
|
}
|
|
60861
60892
|
}
|
|
60893
|
+
|
|
60894
|
+
// Guarded variant of handleOpenTab for user-driven entry points
|
|
60895
|
+
// (sidebar dashboard list, recents). If the user is mid-edit with
|
|
60896
|
+
// unsaved changes AND the request would navigate to a DIFFERENT
|
|
60897
|
+
// workspace than the currently active tab, surface the discard
|
|
60898
|
+
// confirmation modal instead of switching immediately.
|
|
60899
|
+
//
|
|
60900
|
+
// Programmatic callers (post-create auto-open, popout init, the
|
|
60901
|
+
// wizard's create-then-open flow) keep calling `handleOpenTab`
|
|
60902
|
+
// directly — they only fire after an explicit save and have no
|
|
60903
|
+
// dirty state to lose.
|
|
60904
|
+
function handleOpenTabGuarded(workspaceItem) {
|
|
60905
|
+
if (!workspaceItem) return;
|
|
60906
|
+
var switchingAway = activeTabId && activeTabId !== workspaceItem.id;
|
|
60907
|
+
if (isDirty && switchingAway) {
|
|
60908
|
+
setPendingNavigation({
|
|
60909
|
+
kind: "open-workspace",
|
|
60910
|
+
workspace: workspaceItem
|
|
60911
|
+
});
|
|
60912
|
+
return;
|
|
60913
|
+
}
|
|
60914
|
+
handleOpenTab(workspaceItem);
|
|
60915
|
+
}
|
|
60862
60916
|
function handleCloseTab(tabId) {
|
|
60863
60917
|
setOpenTabs(function (prev) {
|
|
60864
60918
|
var remaining = prev.filter(function (tab) {
|
|
@@ -61203,10 +61257,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
61203
61257
|
}
|
|
61204
61258
|
|
|
61205
61259
|
// ─── Page State ──────────────────────────────────────────────────
|
|
61206
|
-
var
|
|
61207
|
-
|
|
61208
|
-
activePageId =
|
|
61209
|
-
setActivePageId =
|
|
61260
|
+
var _useState61 = React.useState(null),
|
|
61261
|
+
_useState62 = _slicedToArray(_useState61, 2),
|
|
61262
|
+
activePageId = _useState62[0],
|
|
61263
|
+
setActivePageId = _useState62[1];
|
|
61210
61264
|
|
|
61211
61265
|
// Page history stack for goBack() — pushes the previous page id
|
|
61212
61266
|
// whenever a navigation happens through navigateToPage().
|
|
@@ -61592,20 +61646,35 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
61592
61646
|
}
|
|
61593
61647
|
function handleSaveMenuItemError(e, message) {
|
|
61594
61648
|
}
|
|
61649
|
+
|
|
61650
|
+
// Internal: the unguarded cancel-edit operation. Called both from
|
|
61651
|
+
// the direct Cancel button (when nothing is dirty) and from the
|
|
61652
|
+
// confirmation modal's Discard action.
|
|
61653
|
+
function performCancelEdit() {
|
|
61654
|
+
if (originalWorkspaceRef.current) {
|
|
61655
|
+
updateTabWorkspace(originalWorkspaceRef.current);
|
|
61656
|
+
}
|
|
61657
|
+
currentWorkspaceRef.current = null;
|
|
61658
|
+
originalWorkspaceRef.current = null;
|
|
61659
|
+
setPreviewMode(true);
|
|
61660
|
+
}
|
|
61595
61661
|
function handleToggleEditMode() {
|
|
61596
61662
|
if (previewMode) {
|
|
61597
61663
|
// Entering edit mode — snapshot the current workspace
|
|
61598
61664
|
originalWorkspaceRef.current = DashReact.deepCopy(workspaceSelected);
|
|
61599
61665
|
setPreviewMode(false);
|
|
61600
|
-
|
|
61601
|
-
// Canceling edit mode — restore original workspace
|
|
61602
|
-
if (originalWorkspaceRef.current) {
|
|
61603
|
-
updateTabWorkspace(originalWorkspaceRef.current);
|
|
61604
|
-
}
|
|
61605
|
-
currentWorkspaceRef.current = null;
|
|
61606
|
-
originalWorkspaceRef.current = null;
|
|
61607
|
-
setPreviewMode(true);
|
|
61666
|
+
return;
|
|
61608
61667
|
}
|
|
61668
|
+
// Cancel path: prompt only if there are unsaved edits. The
|
|
61669
|
+
// `isDirty` value flips true the moment LayoutBuilder writes
|
|
61670
|
+
// anything into `currentWorkspaceRef`.
|
|
61671
|
+
if (isDirty) {
|
|
61672
|
+
setPendingNavigation({
|
|
61673
|
+
kind: "cancel-edit"
|
|
61674
|
+
});
|
|
61675
|
+
return;
|
|
61676
|
+
}
|
|
61677
|
+
performCancelEdit();
|
|
61609
61678
|
}
|
|
61610
61679
|
function handleWorkspaceNameChange(name) {
|
|
61611
61680
|
if (!workspaceSelected) return;
|
|
@@ -61956,7 +62025,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
61956
62025
|
recentDashboards: recentDashboards,
|
|
61957
62026
|
authStatus: authStatus,
|
|
61958
62027
|
authProfile: authProfile,
|
|
61959
|
-
onOpenWorkspace:
|
|
62028
|
+
onOpenWorkspace: handleOpenTabGuarded,
|
|
61960
62029
|
onNewDashboard: function onNewDashboard() {
|
|
61961
62030
|
return setIsLayoutPickerOpen(true);
|
|
61962
62031
|
},
|
|
@@ -62147,7 +62216,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
62147
62216
|
onReloadWorkspaces: loadWorkspaces,
|
|
62148
62217
|
onReloadMenuItems: loadMenuItems,
|
|
62149
62218
|
onOpenWorkspace: function onOpenWorkspace(ws) {
|
|
62150
|
-
|
|
62219
|
+
handleOpenTabGuarded(ws);
|
|
62151
62220
|
setIsAppSettingsOpen(false);
|
|
62152
62221
|
},
|
|
62153
62222
|
onOpenThemeEditor: function onOpenThemeEditor() {
|
|
@@ -62189,7 +62258,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
62189
62258
|
onSaveMenuItem: handleSaveNewMenuItem,
|
|
62190
62259
|
appId: credentials === null || credentials === void 0 ? void 0 : credentials.appId,
|
|
62191
62260
|
onReloadWorkspaces: loadWorkspaces,
|
|
62192
|
-
onOpenWorkspace:
|
|
62261
|
+
onOpenWorkspace: handleOpenTabGuarded,
|
|
62193
62262
|
onOpenWizard: function onOpenWizard() {
|
|
62194
62263
|
return setIsWizardOpen(true);
|
|
62195
62264
|
}
|
|
@@ -62274,6 +62343,36 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
62274
62343
|
onOpenWizard: function onOpenWizard() {
|
|
62275
62344
|
return setIsWizardOpen(true);
|
|
62276
62345
|
}
|
|
62346
|
+
}), /*#__PURE__*/jsxRuntime.jsx(DashReact.ConfirmationModal, {
|
|
62347
|
+
isOpen: Boolean(pendingNavigation),
|
|
62348
|
+
setIsOpen: function setIsOpen(open) {
|
|
62349
|
+
if (!open) setPendingNavigation(null);
|
|
62350
|
+
},
|
|
62351
|
+
title: "Discard unsaved changes?",
|
|
62352
|
+
message: (pendingNavigation === null || pendingNavigation === void 0 ? void 0 : pendingNavigation.kind) === "cancel-edit" ? "You have edits that haven't been saved. Discard them and exit edit mode?" : "You have edits that haven't been saved. Discard them and switch dashboards?",
|
|
62353
|
+
confirmLabel: "Discard changes",
|
|
62354
|
+
cancelLabel: "Keep editing",
|
|
62355
|
+
variant: "danger",
|
|
62356
|
+
onConfirm: function onConfirm() {
|
|
62357
|
+
var pending = pendingNavigation;
|
|
62358
|
+
// Clear the prompt first so the modal teardown doesn't race
|
|
62359
|
+
// a re-trigger from the same dirty-state read.
|
|
62360
|
+
setPendingNavigation(null);
|
|
62361
|
+
if (!pending) return;
|
|
62362
|
+
if (pending.kind === "cancel-edit") {
|
|
62363
|
+
performCancelEdit();
|
|
62364
|
+
} else if (pending.kind === "open-workspace") {
|
|
62365
|
+
// Clear edit refs before navigating so the new workspace
|
|
62366
|
+
// mount doesn't inherit dirty state.
|
|
62367
|
+
currentWorkspaceRef.current = null;
|
|
62368
|
+
originalWorkspaceRef.current = null;
|
|
62369
|
+
setPreviewMode(true);
|
|
62370
|
+
handleOpenTab(pending.workspace);
|
|
62371
|
+
}
|
|
62372
|
+
},
|
|
62373
|
+
onCancel: function onCancel() {
|
|
62374
|
+
return setPendingNavigation(null);
|
|
62375
|
+
}
|
|
62277
62376
|
})]
|
|
62278
62377
|
});
|
|
62279
62378
|
};
|