fix(dashboard): use server-side lastModifiedTime for co-edit check (#11614)

* fix: [dashboard][co-edit] Round client-side lastModifiedTime

* another try: server-side returns last_updated_time in save_dash response
This commit is contained in:
Grace Guo 2020-11-09 13:30:40 -08:00 committed by GitHub
parent dda95ed250
commit b9284d3a3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 15 deletions

View File

@ -131,19 +131,22 @@ describe('dashboardState reducer', () => {
expect(result.updatedColorScheme).toBe(false); expect(result.updatedColorScheme).toBe(false);
}); });
it('should set lastModifiedTime on save', () => { it('should reset lastModifiedTime on save', () => {
const lastModifiedTime = new Date().getTime() / 1000; const initTime = new Date().getTime() / 1000;
dashboardStateReducer( dashboardStateReducer(
{ {
lastModifiedTime, lastModifiedTime: initTime,
}, },
{}, {},
); );
const lastModifiedTime = Math.round(new Date().getTime() / 1000);
expect( expect(
dashboardStateReducer({ hasUnsavedChanges: true }, { type: ON_SAVE }) dashboardStateReducer(
.lastModifiedTime, { hasUnsavedChanges: true },
).toBeGreaterThanOrEqual(lastModifiedTime); { type: ON_SAVE, lastModifiedTime },
).lastModifiedTime,
).toBeGreaterThanOrEqual(initTime);
}); });
it('should clear the focused filter field', () => { it('should clear the focused filter field', () => {

View File

@ -152,8 +152,8 @@ export function onChange() {
} }
export const ON_SAVE = 'ON_SAVE'; export const ON_SAVE = 'ON_SAVE';
export function onSave() { export function onSave(lastModifiedTime) {
return { type: ON_SAVE }; return { type: ON_SAVE, lastModifiedTime };
} }
export const SET_REFRESH_FREQUENCY = 'SET_REFRESH_FREQUENCY'; export const SET_REFRESH_FREQUENCY = 'SET_REFRESH_FREQUENCY';
@ -161,9 +161,9 @@ export function setRefreshFrequency(refreshFrequency, isPersistent = false) {
return { type: SET_REFRESH_FREQUENCY, refreshFrequency, isPersistent }; return { type: SET_REFRESH_FREQUENCY, refreshFrequency, isPersistent };
} }
export function saveDashboardRequestSuccess() { export function saveDashboardRequestSuccess(lastModifiedTime) {
return dispatch => { return dispatch => {
dispatch(onSave()); dispatch(onSave(lastModifiedTime));
// clear layout undo history // clear layout undo history
dispatch(UndoActionCreators.clearHistory()); dispatch(UndoActionCreators.clearHistory());
}; };
@ -199,7 +199,7 @@ export function saveDashboardRequest(data, id, saveType) {
}, },
}) })
.then(response => { .then(response => {
dispatch(saveDashboardRequestSuccess()); dispatch(saveDashboardRequestSuccess(response.json.last_modified_time));
dispatch(addSuccessToast(t('This dashboard was saved successfully.'))); dispatch(addSuccessToast(t('This dashboard was saved successfully.')));
return response; return response;
}) })

View File

@ -25,7 +25,8 @@ export default function dashboardStateReducer(state = {}, action) {
return { return {
...state, ...state,
...action.newInfo, ...action.newInfo,
lastModifiedTime: new Date().getTime() / 1000, // server-side compare last_modified_time in second level
lastModifiedTime: Math.round(new Date().getTime() / 1000),
}; };
default: default:
return state; return state;

View File

@ -106,8 +106,8 @@ export default function dashboardStateReducer(state = {}, action) {
maxUndoHistoryExceeded: false, maxUndoHistoryExceeded: false,
editMode: false, editMode: false,
updatedColorScheme: false, updatedColorScheme: false,
// server-side compare last_modified_time in second level // server-side returns last_modified_time for latest change
lastModifiedTime: new Date().getTime() / 1000, lastModifiedTime: action.lastModifiedTime,
}; };
}, },
[SET_UNSAVED_CHANGES]() { [SET_UNSAVED_CHANGES]() {

View File

@ -1085,8 +1085,14 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
DashboardDAO.set_dash_metadata(dash, data) DashboardDAO.set_dash_metadata(dash, data)
session.merge(dash) session.merge(dash)
session.commit() session.commit()
# get updated changed_on
dash = session.query(Dashboard).get(dashboard_id)
last_modified_time = dash.changed_on.replace(microsecond=0).timestamp()
session.close() session.close()
return json_success(json.dumps({"status": "SUCCESS"})) return json_success(
json.dumps({"status": "SUCCESS", "last_modified_time": last_modified_time,})
)
@api @api
@has_access_api @has_access_api