Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/app/pages/dashboards/DashboardPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function DashboardComponent(props) {
const [bottomPanelStyles, setBottomPanelStyles] = useState({});
const onParametersEdit = parameters => {
const paramOrder = map(parameters, "name");
updateDashboard({ options: { globalParamOrder: paramOrder } });
updateDashboard({ options: { ...dashboard.options, globalParamOrder: paramOrder } });
};

useEffect(() => {
Expand Down
6 changes: 5 additions & 1 deletion client/app/pages/dashboards/components/DashboardHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,11 @@ function DashboardEditControl({ dashboardConfiguration, headerExtra }) {
doneBtnClickedWhileSaving,
dashboardStatus,
retrySaveDashboardLayout,
saveDashboardParameters,
} = dashboardConfiguration;
const handleDoneEditing = () => {
saveDashboardParameters().then(() => setEditingLayout(false));
Copy link

@cubic-dev-ai cubic-dev-ai bot Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Missing error handling: if saveDashboardParameters() fails (it re-throws after showing a notification), setEditingLayout(false) is never called and the user gets stuck in edit mode. Add a .finally() or .catch() to ensure the user can exit edit mode even on save failure.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/app/pages/dashboards/components/DashboardHeader.jsx, line 258:

<comment>Missing error handling: if `saveDashboardParameters()` fails (it re-throws after showing a notification), `setEditingLayout(false)` is never called and the user gets stuck in edit mode. Add a `.finally()` or `.catch()` to ensure the user can exit edit mode even on save failure.</comment>

<file context>
@@ -252,7 +252,11 @@ function DashboardEditControl({ dashboardConfiguration, headerExtra }) {
+    saveDashboardParameters,
   } = dashboardConfiguration;
+  const handleDoneEditing = () =&gt; {
+    saveDashboardParameters().then(() =&gt; setEditingLayout(false));
+  };
   let status;
</file context>
Fix with Cubic

};
let status;
if (dashboardStatus === DashboardStatusEnum.SAVED) {
status = <span className="save-status">Saved</span>;
Expand All @@ -277,7 +281,7 @@ function DashboardEditControl({ dashboardConfiguration, headerExtra }) {
Retry
</Button>
) : (
<Button loading={doneBtnClickedWhileSaving} type="primary" onClick={() => setEditingLayout(false)}>
<Button loading={doneBtnClickedWhileSaving} type="primary" onClick={handleDoneEditing}>
{!doneBtnClickedWhileSaving && <i className="fa fa-check m-r-5" aria-hidden="true" />} Done Editing
</Button>
)}
Expand Down
16 changes: 16 additions & 0 deletions client/app/pages/dashboards/hooks/useDashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,21 @@ function useDashboard(dashboardData) {
[refreshing, loadDashboard]
);

const saveDashboardParameters = useCallback(() => {
const currentDashboard = dashboardRef.current;

return updateDashboard({
options: {
...currentDashboard.options,
parameters: map(globalParameters, p => p.toSaveableObject()),
},
}).catch(error => {
console.error("Failed to persist parameter values:", error);
notification.error("Parameter values could not be saved. Your changes may not be persisted.");
throw error;
});
}, [globalParameters, updateDashboard]);

const archiveDashboard = useCallback(() => {
recordEvent("archive", "dashboard", dashboard.id);
Dashboard.delete(dashboard).then(updatedDashboard =>
Expand Down Expand Up @@ -238,6 +253,7 @@ function useDashboard(dashboardData) {
setRefreshRate,
disableRefreshRate,
...editModeHandler,
saveDashboardParameters,
gridDisabled,
setGridDisabled,
fullscreen,
Expand Down
8 changes: 6 additions & 2 deletions client/app/services/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,14 @@ Dashboard.prototype.getParametersDefs = function getParametersDefs() {
});
}
});
const mergedValues = {
..._.mapValues(globalParams, p => p.value),
...Object.fromEntries((this.options.parameters || []).map(param => [param.name, param.value])),
};
const resultingGlobalParams = _.values(
_.each(globalParams, param => {
param.setValue(param.value); // apply global param value to all locals
param.fromUrlParams(queryParams); // try to initialize from url (may do nothing)
param.setValue(mergedValues[param.name]); // apply merged value
param.fromUrlParams(queryParams); // allow param-specific parsing logic
})
);

Expand Down
2 changes: 1 addition & 1 deletion client/app/services/parameters/Parameter.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class Parameter {

/** Get a saveable version of the Parameter by omitting unnecessary props */
toSaveableObject() {
return omit(this, ["$$value", "urlPrefix", "pendingValue", "parentQueryId"]);
return omit(this, ["$$value", "urlPrefix", "pendingValue", "parentQueryId", "locals"]);
}
}

Expand Down
Loading