-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#9242: migrate unsaved standalone mod components in the Page Editor #9246
Conversation
); | ||
for (const formState of modComponentFormStates) { | ||
formState.modMetadata = modMetadata; | ||
} | ||
}, | ||
addModComponentFormStateToMod( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop unused action
@@ -670,53 +628,6 @@ export const editorSlice = createSlice({ | |||
state.visibleModalKey = ModalKey.MOVE_COPY_TO_MOD; | |||
state.keepLocalCopyOnCreateMod = moveOrCopy === "copy"; | |||
}, | |||
removeModComponentFormStateFromMod( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop unused action
* The mod metadata for the mod component | ||
* @see createNewUnsavedModMetadata | ||
*/ | ||
modMetadata: ModMetadata; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Main type change: require modMetadata
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of Except
, would SetRequired
be better here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure - I'll make the change. I think the end result is the same? I agree SetRequired is probably more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we can't use it since SetRequired seems to operate on "?" and not types where the prop exists but the value might be set to undefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense now that I think about it. I need to poll with the team whether we want to start differentiating between ?
and | undefined
, since we've run into at least one bug due to the difference. There's a TS setting to enforce similar to strictNullChecks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, historically when adding a new prop, we've used foo: X | undefined
so that the type checker forces us to think about where to provide a default value, etc. vs. accidentally leaving the property off
Agree that we might choose to revisit that decision, e.g., now that we have strict null checks enabled
export function migrateEditorStateV8( | ||
state: EditorStateV8 & PersistedState, | ||
): EditorStateV9 & PersistedState { | ||
return produce(state, (draft) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slice migration code
If the user has any unsaved standalone mod components in their Page Editor, then we need to change them (structurally and visually) to match the new behavior when you create a new mod but don't save it via the dropdown (pushing metadata down with the This is so we can get rid of the UI affordances for standalone mod components entirely
Sure, the idea is to be defensive:
|
99f9601
to
9c49084
Compare
modComponentActions.UNSAFE_setModComponents( | ||
array(activatedModComponentFactory, 3)(), | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot about that helper. There are so many places that would be useful
// FIXME: why is this hook still required? | ||
// See comment: https://www.notion.so/pixiebrix/Re-Slicing-Eliminate-Standalone-mods-from-UI-694e4c85e61441809e14aec18f6b6109?pvs=4#10a43b21a25380e4974ae924d03f3fc5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted on the PR comment, it's purely for backwards compatibility in case the user skipped multiple versions or didn't open the Page Editor in the time since the hook was added. We could consider other options as well (have redux-persist migrations delete any still-existing standalone mod components from both the options and editor stores?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the hook is a NOP though given the migration in this PR. Given the migration, standaloneComponentFormStates
will always be an empty array
I agree there's a corner case for someone on 1/ a version of PixieBrix without the mod component slice migration, 2/ an unsaved standalone mod form state. They could get into a case where a different mod id is assigned to the form state vs. the mod component, but the mod id component will be the same
Personally, I don't think we need to account for people with unsaved standalone mod component who haven't opened the Page Editor in 2+ releases. They can recover just by saving deleting the unsaved mod from the Page Editor and recreating it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. Though in that case we could end up in a situation where the App converted a persisted standalone mod component into a mod definition and the Extension converted the same persisted standalone mod component into an UnsavedMod.
I'll leave it to you to determine how defensive we want to be. It might be that the correct thing to do in that case is to update the hook to find mod components that have a temporary registry id instead of nullish metadata instead of removing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. Though in that case we could end up in a situation where the App converted a persisted standalone mod component into a mod definition and the Extension converted the same persisted standalone mod component into an UnsavedMod.
Yep - that's the corner case.
I'll leave it to you to determine how defensive we want to be
My strong preference is to just drop the code given that it's over a month/2+ releases away, outside our enterprise support window, and a recoverable issue
url, | ||
modMetadata, | ||
starterBrickMetadata, | ||
element, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: I agree that button
is the wrong name for this, but perhaps selectionResult
would read better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's using "element" because of the method name fromNativeElement
. That's the "element" it's being created from. So if we wanted to use selectionResult
, we'd probably want to rename the whole method in the adapter protocol
Leaving off of this PR
const modComponentFormState = | ||
action.payload as Draft<ModComponentFormState>; | ||
// Ensure the form state is writeable for normalization | ||
const modComponentFormState = cloneDeep(action.payload); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious if we should consider switching to structuredClone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷 Not sure. Initial Google search/chatter indicates structuredClone might be slower?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be. I haven't looked into any tests. I do know that structuredClone makes a copy of the prototype, whereas lodash cloneDeep apparently copies a reference to it. That's unlikely to ever be a problem for us though
1040c91
to
666f093
Compare
Fixup for _recipe/modMetadata Revert cross-cutting refactoring Revert cross-cutting refactoring
666f093
to
accb448
Compare
Playwright test resultsDetails Open report ↗︎ Flaky testschrome › tests/pageEditor/addStarterBrick.spec.ts › Add starter brick to mod Skipped testschrome › tests/regressions/doNotCloseSidebarOnPageEditorSave.spec.ts › #8104: Do not automatically close the sidebar when saving in the Page Editor |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #9246 +/- ##
==========================================
+ Coverage 74.24% 75.10% +0.85%
==========================================
Files 1332 1370 +38
Lines 40817 42306 +1489
Branches 7634 7891 +257
==========================================
+ Hits 30306 31773 +1467
- Misses 10511 10533 +22 ☔ View full report in Codecov by Sentry. |
// Can't use SetRequired because the property is required (it does not use ?), but it can be set to undefined | ||
Except<BaseFormStateV5<TModComponent, TStarterBrick>, "modMetadata"> & { | ||
/** | ||
* The mod metadata for the mod component | ||
* @see createNewUnsavedModMetadata | ||
*/ | ||
modMetadata: ModMetadata; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
No loom links were found in the first post. Please add one there if you'd like to it to appear on Slack. Do not edit this comment manually. |
What does this PR do?
modMetadata
?
on form state modMetadatafromNativeElement
to accept Mod MetadataReviewer Notes
useMigrateStandaloneComponentsToMods
. See decision/discussion here: #9242: migrate unsaved standalone mod components in the Page Editor #9246 (comment)UnsavedModDefinition
typeFuture Work
_recipe
/modMetadata
For more information on our expectations for the PR process, see the
code review principles doc