From f923310fe13ba22b4b9f42fb9a97975a836eceac Mon Sep 17 00:00:00 2001 From: Jared Donovan Date: Sat, 16 Jun 2018 22:02:17 +1000 Subject: [PATCH 1/2] Add custom function to compare if files are the same. Don't rely on the lodash _.isEqual function, which results in false if properties `isEditingName` and `isOptionsOpen` are set to false, which is not relevant for comparing whether the files are the same. --- client/modules/IDE/actions/project.js | 43 +++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js index eeb146dcc5..0884ee1393 100644 --- a/client/modules/IDE/actions/project.js +++ b/client/modules/IDE/actions/project.js @@ -2,7 +2,7 @@ import { browserHistory } from 'react-router'; import axios from 'axios'; import objectID from 'bson-objectid'; import each from 'async/each'; -import { isEqual } from 'lodash'; +import { isEqual, isPlainObject } from 'lodash'; import * as ActionTypes from '../../../constants'; import { showToast, setToastText } from './toast'; import { setUnsavedChanges, @@ -71,6 +71,45 @@ export function clearPersistedState() { }; } +function projectIsEqual(base, other) { + const filter = ['isEditingName', 'isOptionsOpen']; + + // debugger; + if (Array.isArray(base)) { + // It must be a collection of children (files or folders). + if (!Array.isArray(other) || other.length !== base.length) { + // If the other one is not also an array, or if the length is different + // then they cannot be the same. + return false; + } + + // Check each of the items in the array for equality with the corresponding + // object in the other. + let allEqual = true; + for (let i = 0; i < base.length; i += 1) { + allEqual = allEqual && projectIsEqual(base[i], other[i]); + } + return allEqual; + } else if (isPlainObject(base)) { + if (!isPlainObject(other)) { + // If the other one is not also a plain object, then they cannot match. + return false; + } + // It must be either a file or a folder object. + // Check the individual object for equality. + let allEqual = true; + Object.keys(base).forEach((k, i) => { + // Only compare keys that are not in the filter. + if (filter.indexOf(k) < 0) { + allEqual = allEqual && isEqual(base[k], other[k]); + } + }); + return allEqual; + } + // Otherwise, I don't know what kind of object it is. Return false. + return false; +} + export function saveProject(autosave = false) { return (dispatch, getState) => { const state = getState(); @@ -84,7 +123,7 @@ export function saveProject(autosave = false) { .then((response) => { const currentState = getState(); const savedProject = Object.assign({}, response.data); - if (!isEqual(currentState.files, response.data.files)) { + if (!projectIsEqual(currentState.files, response.data.files)) { savedProject.files = currentState.files; dispatch(setUnsavedChanges(true)); } else { From 40b813705ab2ed31fa3aad3c1cb3028f38174e22 Mon Sep 17 00:00:00 2001 From: Jared Donovan Date: Sat, 16 Jun 2018 22:09:07 +1000 Subject: [PATCH 2/2] Compare filtered properties if set true. Allow comparison of filtered properties if they are set to true. --- client/modules/IDE/actions/project.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js index 0884ee1393..1e048c3cc0 100644 --- a/client/modules/IDE/actions/project.js +++ b/client/modules/IDE/actions/project.js @@ -71,10 +71,13 @@ export function clearPersistedState() { }; } +/** + * Compare whether two project objects are the same. Used to check that the + * response returned from the server still matches the local copy. + */ function projectIsEqual(base, other) { const filter = ['isEditingName', 'isOptionsOpen']; - // debugger; if (Array.isArray(base)) { // It must be a collection of children (files or folders). if (!Array.isArray(other) || other.length !== base.length) { @@ -99,14 +102,14 @@ function projectIsEqual(base, other) { // Check the individual object for equality. let allEqual = true; Object.keys(base).forEach((k, i) => { - // Only compare keys that are not in the filter. - if (filter.indexOf(k) < 0) { + // Only compare keys that are not in the filter (unless they are set true) + if (filter.indexOf(k) < 0 || base[k] === true) { allEqual = allEqual && isEqual(base[k], other[k]); } }); return allEqual; } - // Otherwise, I don't know what kind of object it is. Return false. + // Otherwise, we don't know what kind of object it is. Return false. return false; }