-
Notifications
You must be signed in to change notification settings - Fork 480
chore(style-editor): Implement optimistic updates for real time headless rendering #34183
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
Conversation
…chine functionality and code cleanup - Added time machine capabilities to manage state history for optimistic updates in the style editor. - Cleaned up code formatting and ensured consistent use of semicolons and newlines across various files. These changes improve the maintainability and functionality of the style editor, allowing for better state management and user experience.
…gement - Refactored the style editor form component to utilize a dedicated form builder service, enhancing form creation and management. - Removed unused imports and cleaned up code for better readability. - Updated methods for extracting and updating style properties to streamline functionality and improve performance. - Ensured consistent handling of form values during rollback operations. These changes enhance the maintainability and efficiency of the style editor, providing a more robust user experience.
…nger import - Removed the test button from the edit-ema editor component to streamline the UI. - Updated the import path for the UveIframeMessengerService to reflect its new location. - Cleaned up console log statements in the contentlet tools component for better code clarity. - Adjusted style properties handling in the GraphQL utility functions for consistency. These changes enhance the maintainability of the code and improve the overall user experience in the edit-ema editor.
- Removed unused imports from the edit-ema editor component and style editor form builder service for improved clarity. - Updated import paths for consistency across components, ensuring better maintainability. - Streamlined the GraphQL utility functions by adjusting import statements, enhancing code readability. These changes contribute to a cleaner codebase and facilitate easier future modifications.
…tyle-editor-for-real-time-headless-rendering
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.
Pull request overview
This PR implements optimistic updates for real-time headless rendering in the style editor. The implementation adds immediate visual feedback when users modify styles by updating the iframe instantly while debouncing the actual API save calls. A time machine feature provides history tracking and automatic rollback capabilities when save operations fail.
Key Changes:
- Time machine feature for undo/rollback with deep cloning support for state snapshots
- New iframe messenger service centralizing postMessage communication
- Optimistic update pattern with automatic rollback on API failure
- Form builder service extracting reactive form creation logic
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
public.ts |
Adds styleProperties field to DotCMSBasicContentlet interface |
withTimeMachine.ts |
New time machine feature providing history tracking, undo/redo, and state navigation |
withTimeMachine.spec.ts |
Comprehensive tests for time machine functionality |
withLoad.ts |
Adds history tracking on page load |
withEditor.ts |
Updates type signatures from ContentletPayload to ActionPayload |
withEditor.spec.ts |
Updates test mocks to match new ActionPayload structure |
withSave.ts |
Adds saveStyleEditor method with optimistic update rollback on failure |
models.ts |
Adds StyleEditorProperties type and SaveStylePropertiesPayload interface |
withClient.ts |
Integrates time machine for graphqlResponse with optimistic update methods |
uve-iframe-messenger.service.ts |
New service centralizing iframe communication |
uve-iframe-messenger.service.spec.ts |
Tests for iframe messenger service |
dot-page-api.service.ts |
Adds saveStyleProperties API method |
dot-page-api.service.spec.ts |
Tests for saveStyleProperties endpoint |
edit-ema-editor.component.ts |
Refactors to use iframe messenger service throughout |
style-editor-graphql.utils.ts |
Utilities for updating/extracting style properties from GraphQL responses |
style-editor-form-builder.service.ts |
Service for building reactive forms from schemas |
dot-uve-style-editor-form.component.ts |
Implements optimistic updates with immediate iframe sync and debounced saves |
dot-uve-style-editor-form.component.spec.ts |
Updates tests with mocked dependencies |
dot-uve-style-editor-form.component.scss |
Adds form actions styling |
uve-style-editor-field-input.component.spec.ts |
Adds jest-dom import |
dot-uve-contentlet-tools.component.ts |
Updates to emit ActionPayload instead of ContentletPayload |
dot-uve-contentlet-tools.component.spec.ts |
Updates test expectations for ActionPayload |
dot-uve-contentlet-tools.component.html |
Calls new setSelectedContent method |
.../dot-uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.ts
Outdated
Show resolved
Hide resolved
.../dot-uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.ts
Outdated
Show resolved
Hide resolved
...uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.spec.ts
Outdated
Show resolved
Hide resolved
core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/save/withSave.ts
Outdated
Show resolved
Hide resolved
core-web/libs/portlets/edit-ema/portlet/src/lib/services/dot-page-api.service.spec.ts
Outdated
Show resolved
Hide resolved
.../dot-uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.ts
Show resolved
Hide resolved
core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/load/withLoad.ts
Show resolved
Hide resolved
core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts
Outdated
Show resolved
Hide resolved
core-web/libs/portlets/edit-ema/portlet/src/lib/services/dot-page-api.service.ts
Outdated
Show resolved
Hide resolved
.../dot-uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.ts
Outdated
Show resolved
Hide resolved
| this.$previousIndex.set(currentIndex); | ||
| }); | ||
|
|
||
| $reloadSchemaEffect = effect(() => { |
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.
Can we use a LinkedSignal or a signalMethod?
|
|
||
| describe('schema changes', () => { | ||
| // TODO: Remove skip when we have the styleProperties in PageAPI response and remove the untracked in $reloadSchemaEffect. | ||
| xdescribe('schema changes', () => { |
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.
Just a comment as a reminder
| readonly STYLE_EDITOR_FIELD_TYPES = STYLE_EDITOR_FIELD_TYPES; | ||
| readonly $previousIndex = signal(-1); | ||
|
|
||
| readonly #rollbackDetectionEffect = effect(() => { |
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.
linkedSignal/signalMethod?
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.
Do you mean previousIndex?
I think no, we need as a local variable to compare with the index on the store
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 we can do something like:
const $undoChange = linkedSignal({
source: this.#uveStore.currentIndex,
computed: (next, prev) => {
return prev >= 0 && next < prev;
},
});
const handleRollback = signalMethod(shouldRollback => {
if (shouldRollback) {
this.#restoreFormFromRollback();
}
});
// Constructor
handleRollback(this.$undoChange);
.../dot-uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.ts
Outdated
Show resolved
Hide resolved
.../dot-uve-palette/components/dot-uve-style-editor-form/dot-uve-style-editor-form.component.ts
Outdated
Show resolved
Hide resolved
.../portlets/edit-ema/portlet/src/lib/services/iframe-messenger/uve-iframe-messenger.service.ts
Show resolved
Hide resolved
| * ); | ||
| * ``` | ||
| */ | ||
| export function withTimeMachine<T>(options?: TimeMachineOptions) { |
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.
YOU ARE THE MAN!
…e and debounce functionality - Integrated MessageService for user notifications on style property saves, improving user feedback. - Implemented a debounce mechanism for form value changes to optimize performance and reduce unnecessary API calls. - Updated variable names for consistency and clarity, ensuring better maintainability. - Cleaned up code and imports across the style editor component and related files. These changes enhance the user experience and performance of the style editor, providing timely feedback and efficient state management.
…tyle-editor-for-real-time-headless-rendering
8e617c1 to
d19e996
Compare
...nts/dot-uve-palette/components/dot-uve-style-editor-form/utils/style-editor-graphql.utils.ts
Show resolved
Hide resolved
...nts/dot-uve-palette/components/dot-uve-style-editor-form/utils/style-editor-graphql.utils.ts
Show resolved
Hide resolved
|
Closed in favor of: #34208 |
style.editor.mechanis.mov