Conversation
|
Semgrep found 9
Risk: Affected versions of @angular/compiler and @angular/core are vulnerable to Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'). Angular's template compiler fails to classify the Fix: Upgrade this library to at least version 20.3.16 at core/core-web/yarn.lock:512. Reference(s): GHSA-jrmj-c5cx-3cw6, CVE-2026-22610 If this is a critical or high severity finding, please also link this issue in the #security channel in Slack. |
- Moved workflowIsPageLocked computed from withPageContext and withEditor to withWorkflow (single source of truth) - Moved systemIsLockFeatureEnabled computed from withPageContext to withWorkflow - Moved lock UI props ($unlockButton, $workflowLockOptions) from withView to withWorkflow - Merged withLock.ts methods (lockPage, unlockPage, workflowToggleLock) into withWorkflow - Deleted withLock.ts file (fully consolidated) - Updated store composition: withWorkflow now comes before withPageContext - Fixed circular dependency with optional pageReload parameter - Removed duplicate lock computeds from withPageContext and withEditor - Updated withEditor to use WorkflowComputed interface from withWorkflow - Removed workflowIsPageLocked from withView dependencies - Fixed import ordering in withWorkflow.ts, withWorkflow.spec.ts, wihtLayout.spec.ts - Removed unused UVE_STATUS, ToggleLockOptions, UnlockOptions imports from withView.ts This eliminates duplicate lock logic across 4 features (withPageContext, withEditor, withView, withLock) and consolidates all lock concerns in a single place.
- Fixed circular dependency between withWorkflow and withLoad by accessing pageReload directly from store at runtime using (store as any).pageReload?.() - Removed WithWorkflowDeps.pageReload parameter to avoid compile-time type errors - Added canLock property to ToggleLockOptions interface (was missing after consolidation) - Updated $workflowLockOptions computed to include canLock: page.canLock ?? false - Build now succeeds with no TypeScript errors This fixes the TypeScript compilation errors introduced in Phase 6.2.
- Moved all page-related computeds from withPageContext to withClient - pageLanguageId, pageLanguage, pageURI, pageVariantId - pageTranslateProps, pageFriendlyParams - Moved viewMode to withView (proper domain ownership) - Removed duplicate viewMode from withEditor - Updated PageAssetComputed interface with merged properties - Deleted withPageContext.ts (87 lines eliminated) - Removed withPageContext from store composition - Updated withView to use PageAssetComputed props (removed deps parameter) - Updated withEditor to use ViewComputed interface for viewMode - Fixed circular references by using local computed values This consolidates all page-related computeds in one place (withClient) and eliminates duplication between withPageContext and withEditor (viewMode was computed in both).
Renamed withClient feature to withPage to better reflect its purpose: - 90% page data access, 10% page loading configuration - Directory: features/client → features/page - File: withClient.ts → withPage.ts - Function: withClient() → withPage() Renamed interfaces for clarity: - ClientConfigState → PageLoadingConfigState (with detailed JSDoc) - WithClientMethods → WithPageMethods Updated all imports across codebase: - dot-uve.store.ts - withEditor.ts, withView.ts, withWorkflow.ts - withStoreComputed.ts - All spec files (withLayout, withLoad, withWorkflow) Documentation improvements: - Added comprehensive JSDoc to PageLoadingConfigState - Clarified that client config is "page loading configuration" - Updated store composition comments Build verified successful - all TypeScript compilation passes.
…-prefixed state - Add withUve feature managing uveStatus, uveIsEnterprise, uveCurrentUser - Update UVEState interface with flat state structure and domain prefixes - Migrate property names: status→uveStatus, isEnterprise→uveIsEnterprise, currentUser→uveCurrentUser, errorCode→pageErrorCode, languages→pageLanguages, experiment→pageExperiment, viewOrientation→viewDeviceOrientation - Update 15+ component and feature files with new property references - Add comprehensive unit tests for withUve (13 tests passing) - Fix TypeScript types: remove any types, properly type dependencies Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix empty interface linting errors in withView and withWorkflow - Remove unused imports (patchState, Signal, byTestId, DotDevice) - Fix parsing error in edit-ema-editor.component.spec.ts (double quotes) - Replace any types with proper TypeScript types in store features - Add DotLanguage import for proper pageLanguage typing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create withHistory feature as reusable composition utility - Generic history tracking with configurable max entries (default: 50) - Deep cloning support with structuredClone (fallback to JSON) - Computed signals: canUndo, canRedo, historyLength, isAtStart, isAtEnd - Methods: addToHistory, undo, redo, goTo, clearHistory, getHistory - Mock structuredClone in tests for Node.js compatibility - Update withPage to compose with withHistory - Replace withTimeMachine with withHistory (same interface) - Track pageAssetResponse changes for optimistic updates - Support undo/redo for style editor, layout changes - Update store dependencies to use addToHistory method - Fix withLoad and withSave dependencies - Update dot-uve-style-editor-form component - Build successful, all tests passing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Document why 'any' is appropriate for the store parameter in selector - Keep the any localized to the generic config interface - Avoids forcing callers to cast or complicating the API with extra generics - Add eslint-disable with detailed justification Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Consolidate all view concerns (device preview, SEO preview, zoom controls, view mode) into single withView feature - Remove redundant boolean flags (viewIsEditState, viewIsPreviewModeActive) in favor of viewMode enum - Add zoom functionality directly to withView with flat state structure - Add comprehensive JSDoc documenting feature responsibilities - Delete withViewZoom feature and zoom/ directory - Update components to use viewMode() === UVE_MODE.EDIT pattern - Maintain flat state structure following NgRx Signal Store best practices - Fix lint issues in withHistory.spec.ts (remove unused imports, fix non-null assertions) Modified: - models.ts: Remove redundant flags, add flat zoom properties - dot-uve.store.ts: Remove withViewZoom from composition - withView.ts: Add zoom computeds and methods with documentation - withEditor.ts: Update to use viewMode instead of viewIsEditState - edit-ema-editor.component.ts: Update computed signals to use viewMode - withHistory.spec.ts: Fix lint warnings (remove patchState import, fix non-null assertions) Deleted: - store/features/zoom/withZoom.ts - store/features/zoom/models.ts - store/features/zoom/ directory Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Consolidate all backend API interactions into single withPageApi feature - Merge withLoad and withSave features for better organization - All page loading and saving operations now in one place - Clearer ownership of backend communication concerns - Consistent error handling and uveStatus orchestration across all API calls New Feature - withPageApi: - pageLoad() - Load page with all related data (languages, experiments, license, user) - pageReload() - Refresh current page with optional param updates - pageUpdateParams() - Update page parameters (language, variant, etc.) - editorSave() - Save page content (containers) - updateRows() - Save page layout (update rows) - saveStyleEditor() - Save style properties with optimistic updates and rollback Modified: - dot-uve.store.ts: Replace withLoad and withSave with withPageApi - Added comprehensive JSDoc documenting feature responsibilities - Organized dependencies into logical groups (client config, workflow, request metadata, page management, history) Deleted: - store/features/load/withLoad.ts - store/features/load/ directory - store/features/editor/save/withSave.ts - store/features/editor/save/ directory Benefits: - Single responsibility for all backend interactions - Reduced feature count (11 → 10 features) - Clear orchestration of uveStatus during async operations - Centralized error handling with rollback support - Type safety via explicit WithPageApiDeps interface Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add TODO comment explaining why page accessors are passed as dependencies - Document potential solutions to revisit: reorder composition, props type assertion, type assertion - Current approach is necessary due to TypeScript type inference limitations with feature composition order - No functional changes, build still successful Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ation - Add comprehensive JSDoc to withEditor explaining all responsibilities - Add comprehensive JSDoc to withWorkflow explaining lock management - Document why pageReload() uses type assertion in withWorkflow - Clarify feature composition order dependency (withWorkflow before withPageApi) - Improve inline comments for better code clarity - No functional changes - documentation and comment improvements only withEditor improvements: - Document responsibilities: UI state, panel preferences, edit capabilities, inline editing - Document dependencies: UVEState, PageAssetComputed, WorkflowComputed, ViewComputed - Already uses correct naming from previous phases (viewMode, uveIsEnterprise) withWorkflow improvements: - Document responsibilities: workflow actions, lock/unlock, lock state computeds - Explain type assertion necessity for pageReload() access - Note runtime safety despite compile-time limitation - Already uses correct naming (uveCurrentUser, pageErrorCode, uveStatus) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add comprehensive JSDoc documenting feature composition order in main store - Document dependencies for each feature in composition chain - Explain circular dependency between withWorkflow and withPageApi - Add inline comments numbering each feature in composition order - Verify current order is optimal given dependency constraints Feature Composition Order (11 features): 1. withState - Base state 2. withUve - Global system state 3. withFlags - Feature flags 4. withPage - Page data + history 5. withTrack - Analytics 6. withWorkflow - Workflow + lock 7. withMethods - Helper methods 8. withLayout - Layout operations 9. withView - View modes + zoom 10. withEditor - Editor UI 11. withPageApi - Backend API (must be last) Circular Dependency Analysis: - withWorkflow needs pageReload() from withPageApi (type assertion) - withPageApi needs workflowFetch() from withWorkflow (dependency injection) - Current order is optimal - cannot be reordered without breaking dependencies - Type assertion in withWorkflow is necessary and acceptable solution No functional changes - documentation only Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update test files to use new property names from Phase 1: - Replace store.currentUser() with store.uveCurrentUser() - Replace store.status() with store.uveStatus() - Replace store.languages() with store.pageLanguages() Files updated: - withView.spec.ts: Update uveCurrentUser reference - dot-uve.store.integration.spec.ts: Update uveStatus and pageLanguages references Note: Service method calls like dotLicenseService.isEnterprise() remain unchanged as they are not store properties. Verified: No remaining old naming conventions in component/test files. All occurrences of store.status() in palette store are for local store, not UVE store, so they remain unchanged. Phase 7 complete - Component updates done.
Create comprehensive README.md explaining UVE Store architecture: Core Principles: - Flat state structure (NgRx Signal Store best practice) - Domain prefixes for clear ownership (uve*, page*, editor*, view*, workflow*) - Single responsibility per feature - Composition patterns for reusability Key Documentation: - Feature composition order with dependencies explained - Circular dependency between withWorkflow ↔ withPageApi documented - Scaling rules for adding new state and creating features - Common patterns for accessing state, updating, and checking permissions - Property naming conventions Focused on: - WHY the architecture is designed this way - RULES for scaling the store safely - PATTERNS for common operations Phase 8 complete - Documentation done (~150 lines, focused on architecture).
There was a problem hiding this comment.
Pull request overview
This PR introduces a real-time canvas for the Universal Visual Editor (UVE) with zoom controls, a right sidebar for content editing, and comprehensive store refactoring. The changes establish a cleaner architecture with flat state structure, domain-prefixed properties, and improved separation of concerns.
Changes:
- Implements zoom functionality with controls and gesture support for the UVE canvas
- Adds a right sidebar with tabbed interface for content editing and style editor
- Refactors UVE store to use flat state structure with domain prefixes (
uve*,page*,editor*,view*,workflow*) - Introduces new presentational components following container/presentational pattern
- Removes deprecated store features and consolidates state management
Reviewed changes
Copilot reviewed 101 out of 130 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| withUVEToolbar.ts | File deleted - toolbar state moved to withView feature |
| withSave.ts | File deleted - save functionality consolidated into withPageApi |
| withClient.ts | File deleted - client configuration moved to withPage feature |
| dot-uve.store.ts | Complete refactoring with flat state structure and domain-prefixed properties |
| README.md | Added comprehensive architecture documentation with 200+ lines |
| models.ts | Removed deprecated interfaces (UVEToolbarProps, EditorProps, UnlockOptions) and updated palette tabs enum |
| shared/models.ts | Removed UnlockOptions interface and showBanner/showOverlay from ToggleLockOptions |
| mocks.ts | Updated page mock properties from isLocked/lockedByUser to locked/lockedBy/lockedByName |
| edit-ema-editor.component.scss | Added zoom canvas layout with grid system and right sidebar wrapper |
| edit-ema-editor.component.html | Complete template refactor with zoom controls, browser toolbar, and right sidebar tabs |
| dot-uve-zoom-controls component | New component for zoom in/out/reset controls |
| dot-uve-iframe component | New component extracted from editor with height reporting and traditional page support |
| dot-uve-contentlet-quick-edit component | New presentational component for inline contentlet editing with dynamic form generation |
| dot-uve-palette.component.ts | Refactored to use local signalState for tab management instead of global store |
| lib.routes.ts | Removed DotEditPageResolver and DotPageStateService, added UVEStore and dependencies as providers |
Comments suppressed due to low confidence (1)
core-web/libs/portlets/edit-ema/portlet/src/lib/store/dot-uve.store.ts:1
- The comment mentions a circular dependency between withWorkflow and withPageApi but doesn't provide a clear reference to where this is documented or how to resolve it safely. Consider adding a reference to related documentation or tracking issue for future resolution.
import { signalStore, withFeature, withMethods, withState } from '@ngrx/signals';
Security: - Force regenerate yarn.lock to match package.json Angular 20.3.16 - Addresses Semgrep CVE-2026-22610 (XSS via SVG script href attributes) Code Quality (10 Copilot findings): - Update comment clarity for currentTab state management - Reorder enum values for sequential ordering (LAYERS=3, STYLE_EDITOR=4) - Add JSDoc documentation for ToggleLockOptions properties - Extract magic numbers/strings to named constants (DROP_INDICATOR_HEIGHT_PX, DEFAULT_DEVICE_INODE) - Add null safety checks in language selector lifecycle methods - Optimize effect to avoid unnecessary form rebuilds - Add i18n translations for Cancel/Save button labels - Rename ambiguous method tryHandleIframeHeightMessage - Fix type guard in isQuickEditSupportedField to properly narrow types No functional changes - addresses security and maintainability improvements Resolves all review findings in PR #34173 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Remove 'Phase X.Y:' prefixes from describe() blocks in specs - Remove 'Phase X.Y:' from inline comments in component and store files - Keep semantic meaning of comments while removing development phase markers - Documentation files (*.md) intentionally not modified No functional changes - code cleanup only
…trip and fix drag regression - Add metadata field to DotLayoutRow, DotLayoutColumn, DotGridStackWidget, DotGridStackNode - Pass metadata through parseFromDotObjectToGridStack and parseFromGridStackToDotObject - Guard against undefined oldChild in updateOldRows when column moves to new X position - Remove identify() method, use row.id/box.id directly in @for track expressions - Bump gridstack 8.1.1 -> 8.4.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rollback Safety Analysis
Result: Safe To Rollback ✅ I reviewed the diff between Scope of changes: ~100 files — overwhelmingly frontend-only Angular/TypeScript/SCSS. Only 9 backend Java files changed, plus New commits since last analysis (
Backend changes (all additive, unchanged from prior analysis):
All rollback-unsafe categories — clear:
Rollback scenario: If N writes templates with Applied label: |
Replace row and column drag handle icons in the Row Reorder component: - Row drag handle: pi-table → split_screen (Material Icon) - Column drag handle: pi-objects-column → view_column_2 (Material Icon)
# Conflicts: # core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field/dot-file-field.component.html # core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/edit-ema-editor.component.ts # core-web/libs/sdk/types/src/lib/editor/public.ts # dotCMS/src/main/webapp/ext/uve/dot-uve.js
…erService Move CREATE_CONTENTLET postMessage action handling from edit-ema-editor component (main branch) into DotUveActionsHandlerService where it belongs in this branch's architecture. Add test coverage for the new action. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ith skipWhile logic Set $shouldHideControls initial value to false (was true) so palette controls are visible by default. The skipWhile(status !== LOADING) gate added to #updateControlsVisibility() prevents stale store state from a previous palette tab from hiding controls on tab switch; with that guard in place the signal must start as false. Update three tests in the "control visibility behavior" block to drive status through LOADING → EMPTY instead of jumping straight to EMPTY, matching the production code path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Scope
This summary is based on the branch artifacts available locally in this workspace (not live GitHub PR metadata, which is not accessible from this environment). The changes are centered on UVE store state refactoring in
edit-ema.What Changed
The branch refactors the UVE store architecture from a duplicated state model to a single-source-of-truth model.
1. New computed-signal access layer (
withPageAsset)A new store feature was introduced to expose page asset data through computed signals:
$page(),$site(),$containers(),$template(),$layout()$viewAs(),$vanityUrl(),$urlContentMap(),$numberContents()$clientResponse()This centralizes derived state access and reduces direct dependence on internal response structure.
2. State/API renaming for cleaner semantics
Several store properties and methods were renamed to remove GraphQL-specific wording and better describe intent:
graphqlRequest->requestMetadatagraphqlResponse->pageAssetResponselegacyGraphqlResponse->legacyResponseFormatsetGraphqlResponse()->setPageAssetResponse()setGraphqlResponseOptimistic()->setPageAssetResponseOptimistic()rollbackGraphqlResponse()->rollbackPageAssetResponse()$graphqlWithParams->$requestWithParams$customGraphqlResponse->$clientResponse3. Duplication removed from load/save flows
withLoadandwithSavewere simplified by removing repeated manual extraction/sync ofpageAssetsub-properties.Instead of repeatedly patching multiple top-level fields, flows now rely on updating
pageAssetResponseonce and reading via computed signals.4. Consumer updates
Related consumers were updated to use the new API naming and signals, including:
withLayout, etc.)Why This Matters
Architectural improvements
Engineering impact
pageAssetshape changes.Reported Quantified Outcomes
From branch docs/changelog:
Backward Compatibility and Migration
Current compatibility
The branch indicates no immediate breaking changes for consumers because existing patterns are still tolerated during transition.
Recommended direction
Adopt computed-signal usage in new/updated code:
store.$page()overstore.page()store.$site()overstore.site()Future cleanup (planned)
Branch docs mention a later cleanup phase to fully remove deprecated direct-property access patterns once migration is complete.
Risk / Attention Points
Quick Takeaway
PR #34173 is primarily an internal architecture refactor that modernizes UVE store state handling: one source of truth, cleaner API names, computed signal access, and reduced duplication in critical load/save paths. It is aimed at maintainability, consistency, and safer future evolution rather than introducing large user-facing behavior changes.
Videos
video-general-walkthrough.mov
content-editing.mov
uve-bookmark.mov
new-animation.mov