@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.esm.js
CHANGED
|
@@ -60494,6 +60494,37 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
60494
60494
|
|
|
60495
60495
|
// Snapshot of the workspace before editing — used to restore on Cancel
|
|
60496
60496
|
var originalWorkspaceRef = useRef(null);
|
|
60497
|
+
|
|
60498
|
+
// ─── Unsaved-changes guard (Phase 2B) ────────────────────────────
|
|
60499
|
+
// Single source of truth for "is the user mid-edit with un-saved
|
|
60500
|
+
// work?". Edit mode (`previewMode === false`) is necessary; a
|
|
60501
|
+
// populated `currentWorkspaceRef` is sufficient — the layout
|
|
60502
|
+
// builder mutates that ref on every drag/drop/widget change.
|
|
60503
|
+
//
|
|
60504
|
+
// The flag is mirrored to `globalThis.__dashboardIsDirty` so the
|
|
60505
|
+
// Electron main process can poll it synchronously during window
|
|
60506
|
+
// close + app-quit handlers without an IPC round-trip.
|
|
60507
|
+
//
|
|
60508
|
+
// A `pendingNavigation` object captures a navigation request that
|
|
60509
|
+
// arrived while dirty so the user can choose to discard or keep
|
|
60510
|
+
// editing. Shapes:
|
|
60511
|
+
// { kind: "open-workspace", workspace } — sidebar switch
|
|
60512
|
+
// { kind: "cancel-edit" } — Cancel button
|
|
60513
|
+
var _useState57 = useState(null),
|
|
60514
|
+
_useState58 = _slicedToArray(_useState57, 2),
|
|
60515
|
+
pendingNavigation = _useState58[0],
|
|
60516
|
+
setPendingNavigation = _useState58[1];
|
|
60517
|
+
var isDirty = previewMode === false && currentWorkspaceRef.current !== null;
|
|
60518
|
+
useEffect(function () {
|
|
60519
|
+
if (typeof globalThis !== "undefined") {
|
|
60520
|
+
globalThis.__dashboardIsDirty = isDirty;
|
|
60521
|
+
}
|
|
60522
|
+
return function () {
|
|
60523
|
+
if (typeof globalThis !== "undefined") {
|
|
60524
|
+
globalThis.__dashboardIsDirty = false;
|
|
60525
|
+
}
|
|
60526
|
+
};
|
|
60527
|
+
}, [isDirty]);
|
|
60497
60528
|
useEffect(function () {
|
|
60498
60529
|
isLoadingWorkspaces === false && loadWorkspaces();
|
|
60499
60530
|
isLoadingMenuItems === false && loadMenuItems();
|
|
@@ -60581,10 +60612,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
60581
60612
|
// We record the requested ID and open it once it appears in
|
|
60582
60613
|
// workspaceConfig — handles the case where the workspace was just
|
|
60583
60614
|
// created and the config reload is still in flight.
|
|
60584
|
-
var
|
|
60585
|
-
|
|
60586
|
-
pendingOpenWorkspaceId =
|
|
60587
|
-
setPendingOpenWorkspaceId =
|
|
60615
|
+
var _useState59 = useState(null),
|
|
60616
|
+
_useState60 = _slicedToArray(_useState59, 2),
|
|
60617
|
+
pendingOpenWorkspaceId = _useState60[0],
|
|
60618
|
+
setPendingOpenWorkspaceId = _useState60[1];
|
|
60588
60619
|
useEffect(function () {
|
|
60589
60620
|
var handler = function handler(e) {
|
|
60590
60621
|
var _e$detail2;
|
|
@@ -60841,6 +60872,29 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
60841
60872
|
});
|
|
60842
60873
|
}
|
|
60843
60874
|
}
|
|
60875
|
+
|
|
60876
|
+
// Guarded variant of handleOpenTab for user-driven entry points
|
|
60877
|
+
// (sidebar dashboard list, recents). If the user is mid-edit with
|
|
60878
|
+
// unsaved changes AND the request would navigate to a DIFFERENT
|
|
60879
|
+
// workspace than the currently active tab, surface the discard
|
|
60880
|
+
// confirmation modal instead of switching immediately.
|
|
60881
|
+
//
|
|
60882
|
+
// Programmatic callers (post-create auto-open, popout init, the
|
|
60883
|
+
// wizard's create-then-open flow) keep calling `handleOpenTab`
|
|
60884
|
+
// directly — they only fire after an explicit save and have no
|
|
60885
|
+
// dirty state to lose.
|
|
60886
|
+
function handleOpenTabGuarded(workspaceItem) {
|
|
60887
|
+
if (!workspaceItem) return;
|
|
60888
|
+
var switchingAway = activeTabId && activeTabId !== workspaceItem.id;
|
|
60889
|
+
if (isDirty && switchingAway) {
|
|
60890
|
+
setPendingNavigation({
|
|
60891
|
+
kind: "open-workspace",
|
|
60892
|
+
workspace: workspaceItem
|
|
60893
|
+
});
|
|
60894
|
+
return;
|
|
60895
|
+
}
|
|
60896
|
+
handleOpenTab(workspaceItem);
|
|
60897
|
+
}
|
|
60844
60898
|
function handleCloseTab(tabId) {
|
|
60845
60899
|
setOpenTabs(function (prev) {
|
|
60846
60900
|
var remaining = prev.filter(function (tab) {
|
|
@@ -61185,10 +61239,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
61185
61239
|
}
|
|
61186
61240
|
|
|
61187
61241
|
// ─── Page State ──────────────────────────────────────────────────
|
|
61188
|
-
var
|
|
61189
|
-
|
|
61190
|
-
activePageId =
|
|
61191
|
-
setActivePageId =
|
|
61242
|
+
var _useState61 = useState(null),
|
|
61243
|
+
_useState62 = _slicedToArray(_useState61, 2),
|
|
61244
|
+
activePageId = _useState62[0],
|
|
61245
|
+
setActivePageId = _useState62[1];
|
|
61192
61246
|
|
|
61193
61247
|
// Page history stack for goBack() — pushes the previous page id
|
|
61194
61248
|
// whenever a navigation happens through navigateToPage().
|
|
@@ -61574,20 +61628,35 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
61574
61628
|
}
|
|
61575
61629
|
function handleSaveMenuItemError(e, message) {
|
|
61576
61630
|
}
|
|
61631
|
+
|
|
61632
|
+
// Internal: the unguarded cancel-edit operation. Called both from
|
|
61633
|
+
// the direct Cancel button (when nothing is dirty) and from the
|
|
61634
|
+
// confirmation modal's Discard action.
|
|
61635
|
+
function performCancelEdit() {
|
|
61636
|
+
if (originalWorkspaceRef.current) {
|
|
61637
|
+
updateTabWorkspace(originalWorkspaceRef.current);
|
|
61638
|
+
}
|
|
61639
|
+
currentWorkspaceRef.current = null;
|
|
61640
|
+
originalWorkspaceRef.current = null;
|
|
61641
|
+
setPreviewMode(true);
|
|
61642
|
+
}
|
|
61577
61643
|
function handleToggleEditMode() {
|
|
61578
61644
|
if (previewMode) {
|
|
61579
61645
|
// Entering edit mode — snapshot the current workspace
|
|
61580
61646
|
originalWorkspaceRef.current = deepCopy(workspaceSelected);
|
|
61581
61647
|
setPreviewMode(false);
|
|
61582
|
-
|
|
61583
|
-
// Canceling edit mode — restore original workspace
|
|
61584
|
-
if (originalWorkspaceRef.current) {
|
|
61585
|
-
updateTabWorkspace(originalWorkspaceRef.current);
|
|
61586
|
-
}
|
|
61587
|
-
currentWorkspaceRef.current = null;
|
|
61588
|
-
originalWorkspaceRef.current = null;
|
|
61589
|
-
setPreviewMode(true);
|
|
61648
|
+
return;
|
|
61590
61649
|
}
|
|
61650
|
+
// Cancel path: prompt only if there are unsaved edits. The
|
|
61651
|
+
// `isDirty` value flips true the moment LayoutBuilder writes
|
|
61652
|
+
// anything into `currentWorkspaceRef`.
|
|
61653
|
+
if (isDirty) {
|
|
61654
|
+
setPendingNavigation({
|
|
61655
|
+
kind: "cancel-edit"
|
|
61656
|
+
});
|
|
61657
|
+
return;
|
|
61658
|
+
}
|
|
61659
|
+
performCancelEdit();
|
|
61591
61660
|
}
|
|
61592
61661
|
function handleWorkspaceNameChange(name) {
|
|
61593
61662
|
if (!workspaceSelected) return;
|
|
@@ -61938,7 +62007,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
61938
62007
|
recentDashboards: recentDashboards,
|
|
61939
62008
|
authStatus: authStatus,
|
|
61940
62009
|
authProfile: authProfile,
|
|
61941
|
-
onOpenWorkspace:
|
|
62010
|
+
onOpenWorkspace: handleOpenTabGuarded,
|
|
61942
62011
|
onNewDashboard: function onNewDashboard() {
|
|
61943
62012
|
return setIsLayoutPickerOpen(true);
|
|
61944
62013
|
},
|
|
@@ -62129,7 +62198,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
62129
62198
|
onReloadWorkspaces: loadWorkspaces,
|
|
62130
62199
|
onReloadMenuItems: loadMenuItems,
|
|
62131
62200
|
onOpenWorkspace: function onOpenWorkspace(ws) {
|
|
62132
|
-
|
|
62201
|
+
handleOpenTabGuarded(ws);
|
|
62133
62202
|
setIsAppSettingsOpen(false);
|
|
62134
62203
|
},
|
|
62135
62204
|
onOpenThemeEditor: function onOpenThemeEditor() {
|
|
@@ -62171,7 +62240,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
62171
62240
|
onSaveMenuItem: handleSaveNewMenuItem,
|
|
62172
62241
|
appId: credentials === null || credentials === void 0 ? void 0 : credentials.appId,
|
|
62173
62242
|
onReloadWorkspaces: loadWorkspaces,
|
|
62174
|
-
onOpenWorkspace:
|
|
62243
|
+
onOpenWorkspace: handleOpenTabGuarded,
|
|
62175
62244
|
onOpenWizard: function onOpenWizard() {
|
|
62176
62245
|
return setIsWizardOpen(true);
|
|
62177
62246
|
}
|
|
@@ -62256,6 +62325,36 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
|
|
|
62256
62325
|
onOpenWizard: function onOpenWizard() {
|
|
62257
62326
|
return setIsWizardOpen(true);
|
|
62258
62327
|
}
|
|
62328
|
+
}), /*#__PURE__*/jsx(ConfirmationModal, {
|
|
62329
|
+
isOpen: Boolean(pendingNavigation),
|
|
62330
|
+
setIsOpen: function setIsOpen(open) {
|
|
62331
|
+
if (!open) setPendingNavigation(null);
|
|
62332
|
+
},
|
|
62333
|
+
title: "Discard unsaved changes?",
|
|
62334
|
+
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?",
|
|
62335
|
+
confirmLabel: "Discard changes",
|
|
62336
|
+
cancelLabel: "Keep editing",
|
|
62337
|
+
variant: "danger",
|
|
62338
|
+
onConfirm: function onConfirm() {
|
|
62339
|
+
var pending = pendingNavigation;
|
|
62340
|
+
// Clear the prompt first so the modal teardown doesn't race
|
|
62341
|
+
// a re-trigger from the same dirty-state read.
|
|
62342
|
+
setPendingNavigation(null);
|
|
62343
|
+
if (!pending) return;
|
|
62344
|
+
if (pending.kind === "cancel-edit") {
|
|
62345
|
+
performCancelEdit();
|
|
62346
|
+
} else if (pending.kind === "open-workspace") {
|
|
62347
|
+
// Clear edit refs before navigating so the new workspace
|
|
62348
|
+
// mount doesn't inherit dirty state.
|
|
62349
|
+
currentWorkspaceRef.current = null;
|
|
62350
|
+
originalWorkspaceRef.current = null;
|
|
62351
|
+
setPreviewMode(true);
|
|
62352
|
+
handleOpenTab(pending.workspace);
|
|
62353
|
+
}
|
|
62354
|
+
},
|
|
62355
|
+
onCancel: function onCancel() {
|
|
62356
|
+
return setPendingNavigation(null);
|
|
62357
|
+
}
|
|
62259
62358
|
})]
|
|
62260
62359
|
});
|
|
62261
62360
|
};
|