Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

FIX Make change tracking work again for inline editable blocks #1319

Merged

Conversation

GuySartorelli
Copy link
Member

@GuySartorelli GuySartorelli commented Feb 19, 2025

This PR effectively reverts dirty form detection for elemental back to how it was in 5.2 which was the last time it worked.
Change tracking is weirdly intertwined with a few other functionalities so other changes were also needed.

Behat tests have been made more robust to help prevent this sort of regression happening again.

Issues

@@ -435,6 +436,7 @@ const Element = (props) => {
broken={type.broken}
onFormSchemaSubmitResponse={handleFormSchemaSubmitResponse}
onFormInit={() => handleFormInit(activeTab)}
formDirty={formDirty}
Copy link
Member Author

Choose a reason for hiding this comment

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

I assume this was originally removed with the intention of using the new context in the Content component - but that's a class component so it can't use hooks. Using the prop that already exists is easier and more suitable as a patch compared with completely refactoring that component to a functional one.

@@ -8,12 +8,52 @@ Feature: Files can be saved in and removed from elemental blocks
And I add an extension "SilverStripe\FrameworkTest\Elemental\Extension\FileElementalExtension" to the "DNADesign\Elemental\Models\ElementContent" class
And I go to "/dev/build?flush"
And a "image" "file1.jpg"
And a "image" "file2.jpg"
Copy link
Member Author

Choose a reason for hiding this comment

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

If we add a file, save, remove the file and try to add the same file back, since it's the same file the form isn't dirty so we can't save.

The dirty state didn't change before, but now that it does we need to test this.
Anything with a file2 is for testing that scenario.

Comment on lines -49 to -56
// Note that formDirty from redux can be set to undefined after failed validation
// which is confusing as the block still has unsaved changes, hence why we create
// this state variable to track this instead
// props.formDirty is either undefined (when pristine) or an object (when dirty)
const formDirty = typeof props.formDirty !== 'undefined';
if (formDirty && !hasUnsavedChanges) {
setHasUnsavedChanges(true);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

That's not how formDirty works now - it's just a boolean same as it used to be in 5.2.

Comment on lines -493 to -502
dispatchAddFormChanged() {
// Ensures the form identifier is in unsavedForms in the global redux state
// This is used to derive the formDirty prop in mapStateToProps
dispatch(addFormChanged(`element.${elementName}`));
},
dispatchRemoveFormChanged() {
// Removes the form identifier from unsavedForms in the global redux store
// Opposite of beheaviour of dispatchAddFormChanged()
dispatch(removeFormChanged(`element.${elementName}`));
},
Copy link
Member Author

Choose a reason for hiding this comment

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

Just rely on the existing formdirty data from redux.

@@ -24,6 +25,7 @@ Feature: Blocks are validated when inline saving individual blocks
And I press the "Insert" button
And I press the "View actions" button
And I click on the ".element-editor__actions-save" element
And I dismiss all toasts
Copy link
Member Author

Choose a reason for hiding this comment

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

Sometimes I was getting the "saved block" toast from this save when checking in the test scenarios.

# Specifically swapping back to the original value - we don't actually save the block so not block save toast
And I fill in "My title" for "Title" for block 1
And I wait for 1 second
And I press the "Save" button
Copy link
Member Author

Choose a reason for hiding this comment

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

Because change tracking works now, we can't just leave the unsaved changes hanging there.

Comment on lines -42 to -43
const [doDispatchAddFormChanged, setDoDispatchAddFormChanged] = useState(false);
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
Copy link
Member Author

Choose a reason for hiding this comment

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

No need to separately keep track of hasUnsavedChanges because we can just rely on formDirty instead.
No need to use doDispatchAddFormChanged because redux form keeps track of that for us automatically.

Comment on lines -465 to +432
const formDirty = state.unsavedForms.find((unsaved) => unsaved.name === `element.${elementName}`);

const formName = loadElementFormStateName(ownProps.element.id);
const formDirty = isDirty(`element.${formName}`, getFormState)(state);
Copy link
Member Author

Choose a reason for hiding this comment

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

This is just swapping us back to how this was in CMS 5.2. This was changed in 5.3 but it's unclear why.
Dirty state tracking worked in 5.2 so I've just reverted this back to how it was then.

Comment on lines +42 to +48
// Scenario we've just clicked "save" or "submit" on the form
if (this.state.saveAllElements && !prevState.saveAllElements) {
// Reset the validation state of all blocks.
// This mirrors handleBeforeSubmitForm() for individual blocks.
this.resetState(prevState, false);
return;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Needed because otherwise we retain the old "invalid" state. As noted in the code comment, resetting the validation state is already done when saving a block with the ... menu, so makes sense to reset it when submitting via the page save button as well.

Comment on lines -157 to +164
const saveElement = this.state.saveAllElements
&& this.state.hasUnsavedChangesBlockIDs[element.id]
&& this.state.validBlockIDs[element.id] === null;
const saveElement = this.state.saveAllElements && this.state.hasUnsavedChangesBlockIDs[element.id];
Copy link
Member Author

Choose a reason for hiding this comment

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

We should attempt to save the block regardless of the validation state it was in prior to trying to save the block.

@GuySartorelli GuySartorelli marked this pull request as ready for review February 25, 2025 21:36
@GuySartorelli GuySartorelli force-pushed the pulls/5.3/change-tracking branch 2 times, most recently from 939dadd to 322f459 Compare February 25, 2025 23:32
@GuySartorelli GuySartorelli force-pushed the pulls/5.3/change-tracking branch from 322f459 to 4d377fd Compare February 26, 2025 01:59
Copy link
Member

@emteknetnz emteknetnz left a comment

Choose a reason for hiding this comment

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

Seems to work well

@emteknetnz emteknetnz merged commit c385dc8 into silverstripe:5.3 Feb 27, 2025
25 checks passed
@emteknetnz emteknetnz deleted the pulls/5.3/change-tracking branch February 27, 2025 21:26
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants