Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
ea890e4
refactor(uve): replace iframe height observation with explicit sizing
fmontes Apr 30, 2026
7eee895
fix(uve): make dot-uve-iframe host fill the iframe wrapper
fmontes Apr 30, 2026
a9734f7
feat(uve): add iframe resize handles, size inputs and responsive auto…
fmontes Apr 30, 2026
5600a2d
fix(uve): clamp iframe to canvas viewport on zoom and resize
fmontes Apr 30, 2026
8056aab
fix(uve): hide contentlet-tools while resizing the iframe
fmontes Apr 30, 2026
2864bd0
fix(uve): make resize handles track cursor 1:1 while canvas is centered
fmontes Apr 30, 2026
5efaf68
fix(uve): clamp iframe to canvas viewport in responsive mode
fmontes Apr 30, 2026
c93940a
fix(uve): align toolbar items to a uniform height
fmontes Apr 30, 2026
793987e
fix(uve): drop zoom-time clamp; reset zoom now also fits canvas
fmontes Apr 30, 2026
85140ae
feat(uve): zoom adjusts iframe internal viewport, not on-screen size
fmontes Apr 30, 2026
6c1561e
fix(uve): resize math and canvas clamp use on-screen iframe size
fmontes Apr 30, 2026
a36c06c
feat(uve): auto-fit device presets and keep resize handles in device …
fmontes Apr 30, 2026
a0c83c3
fix(uve): reset to canvas size at 100% zoom when picking desktop preset
fmontes Apr 30, 2026
5c6f138
feat(uve): replace zoom +/- buttons with a p-select
fmontes Apr 30, 2026
a2c1b4a
style(uve): tighten zoom select sizing
fmontes Apr 30, 2026
38c0270
feat(uve): merge size input and zoom select into one toolbar pill
fmontes Apr 30, 2026
d7b9f88
fix(uve): show non-preset zoom values in the select label
fmontes Apr 30, 2026
90eea54
feat(uve): wrap device buttons in p-buttongroup; tighten toolbar
fmontes Apr 30, 2026
4a0c97a
fix(uve): keep toolbar on one row; ellipsis the URL pill on overflow
fmontes Apr 30, 2026
3c9610a
style(uve): tighten toolbar layout and unify icon colors
fmontes May 1, 2026
c50ebff
feat(uve): collapse URL pill to icon-only when toolbar center is narrow
fmontes May 1, 2026
3a8d952
fix(uve): URL pill prefers its content width
fmontes May 1, 2026
bb5f5b8
style(uve): tighten URL popover layout
fmontes May 1, 2026
7262244
feat(uve): add current site URL to the copy-URL popover
fmontes May 1, 2026
5ba62e7
fix(uve): pin progress bar to toolbar bottom without affecting layout
fmontes May 1, 2026
5cba616
fix(uve): no jump when resizing from a device preset
fmontes May 1, 2026
ea1e14c
fix(uve): highlight desktop button when no device is selected
fmontes May 1, 2026
c40f0eb
style(uve): refine iframe resize handles
fmontes May 1, 2026
25aa83e
style(uve): lower right sidebar min width to 360px
fmontes May 1, 2026
983cfc5
style(uve): clean up tablist markup and apply gray background
fmontes May 1, 2026
bc3da05
fix(uve): wrap resize-handle signal reads in untracked()
fmontes May 2, 2026
5c43139
refactor(uve): use dedicated EDITOR_STATE.RESIZING for iframe resize
fmontes May 2, 2026
9cbaef6
refactor(uve): dedupe responsive-mode predicate
fmontes May 2, 2026
b57bafe
refactor(uve): replace isDeviceActive method with $activeDeviceInode …
fmontes May 2, 2026
1435a16
fix(uve): size-input uses viewExitDevicePreset, not full viewSetDevice
fmontes May 2, 2026
38eb255
refactor(uve): split zoom computeds into explicit factor/pct units
fmontes May 2, 2026
292d2c0
docs(uve): clarify the resize/responsive sync ordering contract
fmontes May 2, 2026
33a0ca3
refactor(uve): extract canvas measurement to utils
fmontes May 2, 2026
2ec7580
docs(uve): document the 48rem container-query threshold
fmontes May 2, 2026
dd27bac
fix format
fmontes May 2, 2026
69120b1
test(uve): fix specs broken by phase 1/3 refactor
fmontes May 2, 2026
53ce926
test(uve): cover withView iframe sizing and zoom logic
fmontes May 2, 2026
6fb8e56
refactor(uve): remove unused viewZoomIn / viewZoomOut
fmontes May 2, 2026
6cbe551
fix format
fmontes May 2, 2026
1fbb991
fix(uve): section jump scrolls the iframe, not the canvas viewport
fmontes May 2, 2026
45c8536
fix(uve): clean up resize listeners on destroy mid-drag
fmontes May 2, 2026
88eaa6f
fix(uve): keep device-preset internal viewport correct below 10% fit …
fmontes May 2, 2026
f322d5a
fix(uve): nullable DotUveViewParams fields match runtime reality
fmontes May 2, 2026
cecb266
chore(uve): remove dead ngOnInit hook from edit-ema-editor
fmontes May 2, 2026
fe6e111
test(uve): cover zoom-controls option-list and change handler
fmontes May 2, 2026
7a1bd5f
fix(uve): preserve user iframe size when side panels toggle
fmontes May 2, 2026
6f5d837
fix format
fmontes May 2, 2026
6b03fff
refactor(uve): atomic viewResizeIframe for user-driven size changes
fmontes May 2, 2026
10272d3
chore(sdk/uve): drop iframe height reporting
fmontes May 2, 2026
84344c5
fix(uve): clear stale contentlet-tools position on canvas resize
fmontes May 2, 2026
895cd2c
feat(uve): SDK click → editor selection so hover overlay can be click…
fmontes May 2, 2026
81ceeaf
fix format
fmontes May 2, 2026
f6d72f4
test(uve): adapt contentlet-tools spec to store-driven selection
fmontes May 2, 2026
a587e26
style(uve): replace hover fill with outline + content-type label
fmontes May 2, 2026
21a417c
fix(uve): clear stale contentlet-tools on device preset switch
fmontes May 2, 2026
b94b856
refactor(uve): clear selection + RESIZING in store on device change
fmontes May 2, 2026
96b859d
fix(uve): show selection toolbar without prior hover; gate page reload
fmontes May 2, 2026
c64e5d0
refactor(uve): one-click copy decision in quick-edit
fmontes May 2, 2026
2f21e9f
fix(uve): reset SDK selection tracker when editor clears selection
fmontes May 4, 2026
888eede
feat(uve): show action toolbar on hover with promote-to-selected
fmontes May 4, 2026
d0675d2
fix(uve): preserve selection across canvas scroll/resize
fmontes May 4, 2026
6b49016
fix(uve): preserve selection across reflow and re-anchor via SET_BOUNDS
fmontes May 4, 2026
c2aa99b
fix(uve): match selection re-anchor on inode + container id + uuid
fmontes May 4, 2026
9072b98
refactor(uve): selected overlay shows border only, tools live on hover
fmontes May 4, 2026
dee481b
fix(uve): re-anchor selected overlay after iframe scroll
fmontes May 4, 2026
42ea94e
feat(uve): show content-type label on selected overlay
fmontes May 4, 2026
d194912
fix(uve): re-anchor selected overlay and hide hover on zoom change
fmontes May 4, 2026
0ec424d
feat(uve): SDK signals hover-end so editor can clear hover overlay
fmontes May 4, 2026
7a3e1e1
feat(uve): SDK auto-pushes bounds via debounced ResizeObserver
fmontes May 4, 2026
393249b
fix(uve): include iframe scroll in auto-bounds channel
fmontes May 4, 2026
fe49586
fix(uve): SET_BOUNDS owns IDLE flip for transient states
fmontes May 4, 2026
f69cd66
refactor(uve): name the iframe-layout-lock predicate
fmontes May 5, 2026
2457685
refactor(uve): one bounds channel, with a flush escape hatch
fmontes May 5, 2026
535feb1
refactor(uve): extract selection re-anchor into a store feature
fmontes May 5, 2026
78e298e
docs(uve): add ARCHITECTURE.md for the edit-ema portlet
fmontes May 5, 2026
1026c39
fix(uve): keep editor chrome mounted during page navigation
fmontes May 5, 2026
f1fc0fd
fix(uve): clear selection state on page navigation
fmontes May 5, 2026
4061161
docs(uve): add glossary for the three contentlet signals
fmontes May 5, 2026
2a1cb28
feat(uve): visual hint between hovered and selected overlays
fmontes May 5, 2026
02bfdfb
feat(uve): split pencil and quick-edit into separate hover toolbar bu…
fmontes May 5, 2026
a8c5a9c
refactor(ui): align dot-binary-selector with the quick-edit copy-deci…
fmontes May 5, 2026
0fbc05d
refactor(uve): swap p-button for plain buttons in copy-decision cards
fmontes May 5, 2026
503f9c2
fix(uve): pencil click no longer overwrites the side panel's contentlet
fmontes May 5, 2026
70a1ac0
Revert "fix(uve): pencil click no longer overwrites the side panel's …
fmontes May 5, 2026
4d5a128
fix(uve): pencil button is stateless w.r.t. editor selection
fmontes May 5, 2026
3fcc83d
feat(uve): tooltips on every hover-toolbar button and reorder palette
fmontes May 5, 2026
83d105f
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
fmontes May 5, 2026
ca4cee8
feat(uve): quick-edit form behavior + bolt icon for quick-edit button
fmontes May 5, 2026
3a9cd19
refactor(uve): polish quick-edit form layout
fmontes May 5, 2026
eb56d3d
feat(uve): refactor quick-edit component structure and introduce new …
fmontes May 5, 2026
8a3df43
refactor(uve): merge editorSelected* + editorActiveContentlet into on…
fmontes May 5, 2026
eef662d
feat(uve): collapse hover toolbar actions into a menu on narrow conte…
fmontes May 5, 2026
0dbe42e
fix(uve): provide DotEditContentService to the quick-edit form
fmontes May 5, 2026
35f05b0
fix(uve): keep + add-top button centered at every contentlet width
fmontes May 5, 2026
c421931
fix(uve): re-emit UVE_SET_PAGE_DATA on contentlet changes
fmontes May 5, 2026
71d38ec
chore(uve): drop unused getEditorStates helper + clarify zoom doc
fmontes May 6, 2026
babafe8
feat(apps): gray out unconfigured app configuration items
fmontes May 6, 2026
77a11d8
app material icon class
fmontes May 6, 2026
e73d520
chore(uve): drop unused RouterLink + redundant overflow:hidden
fmontes May 6, 2026
472dc03
fix format
fmontes May 6, 2026
1ee57e0
test(ui): align dot-binary-selector spec with the new card UI
fmontes May 6, 2026
9c3b26e
test(uve): migrate contentlet-tools spec to editorSelected signal
fmontes May 6, 2026
e51fbf4
test(uve): migrate edit-ema-editor spec to setSelected/resetSelected
fmontes May 6, 2026
2dcac43
test(uve): migrate style-editor-form spec to editorSelected signal
fmontes May 6, 2026
004d2ae
test(uve): align store integration spec with editorSelected + RESIZING
fmontes May 6, 2026
d013042
test(uve): wire markPageLoading dep + editorSelected in withPageApi spec
fmontes May 6, 2026
47bcd8b
test(uve): rename requestBounds to flushBounds in messenger spec
fmontes May 6, 2026
2a8040e
test(uve): drop stale overflow:hidden assertion in withView spec
fmontes May 6, 2026
fdf0a33
test(uve): align withEditor spec with editorSelected + setSelected
fmontes May 6, 2026
c8733f6
fix format
fmontes May 6, 2026
0cc1785
fix format
fmontes May 6, 2026
cf6c5b7
fix(uve): guard null document.body in onAutoBounds observer
fmontes May 6, 2026
ac5ea7c
fix(uve): align contentlet-tools viewChild refs with renamed menus
fmontes May 6, 2026
cc783ad
i18n(uve): localize quick-edit select/multiselect placeholders
fmontes May 6, 2026
b4edfd7
fix(uve): release pointer capture on destroy mid-drag
fmontes May 6, 2026
acfe79d
chore(uve): drop stray ext/uve/package.json
fmontes May 6, 2026
eaa1a65
test(uve): add withSelectionAnchor spec
fmontes May 6, 2026
fd87048
refactor(uve): drop redundant $viewZoomPct alias
fmontes May 6, 2026
450d2c0
refactor(uve): fold RESIZING flip into viewSetCanvasAvailableSize
fmontes May 6, 2026
63b8088
chore(uve): review feedback nits
fmontes May 6, 2026
2f4f40d
fix format
fmontes May 6, 2026
db37062
fix handlers
fmontes May 6, 2026
ebd9a5a
feat(uve): empty-state for layers tab on advanced templates
fmontes May 6, 2026
d602f26
chore(uve): simplify quick-edit empty-state markup
fmontes May 6, 2026
760a608
chore(uve): simplify style-editor empty-state markup and widen message
fmontes May 6, 2026
d351d36
i18n(uve): drop <br/> tags from style-editor empty-state message
fmontes May 6, 2026
0f96af0
i18n(uve): link "Learn more" to templating docs in layers empty-state
fmontes May 6, 2026
4a9ddef
style(uve): switch empty-state icons to material symbols
fmontes May 6, 2026
561ce85
style(uve): use space_dashboard icon for layers empty-state
fmontes May 6, 2026
db2c17c
style(uve): lighten empty-state icons to gray-300
fmontes May 6, 2026
c6ee9c7
fix format
fmontes May 6, 2026
708e0ac
refactor(uve): collapse canvas wrapper tree
fmontes May 6, 2026
8368c79
fix(uve): require both canEdit AND drawed for layout edit
fmontes May 6, 2026
5a7b7b7
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
fmontes May 6, 2026
511c41e
Fixed style editor form patch
KevinDavilaDotCMS May 6, 2026
86622fe
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
fmontes May 6, 2026
8c02e6f
fix(edit-content): suppress mount-time onChange in dot-file-field CVA
fmontes May 7, 2026
17185ca
feat(uve-quick-edit): support defaultValue and refine radio/checkbox …
fmontes May 7, 2026
8014041
fix(uve): canvas-outer falls back to 100% before iframe size is known
fmontes May 7, 2026
f81f3a8
clean up
fmontes May 7, 2026
b4cb0ab
fix(uve): address PR feedback — back-compat alias, dedupe, doc fixes
fmontes May 7, 2026
24b6f96
fix(uve-style-editor): seed editorSelected in spec beforeEach
fmontes May 7, 2026
d8d7f11
Manually merge with main
KevinDavilaDotCMS May 7, 2026
0e111e3
Bring back message on empty state style editor
KevinDavilaDotCMS May 7, 2026
3e2a15d
fix test and empty container content type label
zJaaal May 7, 2026
11caa5c
Update dot-uve.js
zJaaal May 7, 2026
a5145cf
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
zJaaal May 8, 2026
7d5c7fe
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
zJaaal May 8, 2026
0ed6821
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
zJaaal May 8, 2026
6e97634
Merge branch 'issue-35514-uve-iframe-sizing-phase-1' of https://githu…
zJaaal May 8, 2026
ae3e348
fix(uve): restore style-editor debounce on traditional + dedup saves …
zJaaal May 8, 2026
b11b2c8
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
zJaaal May 8, 2026
df6b4b5
Add Site URL to Language Properties for Toolbar
rjvelazco May 8, 2026
b1bdbaa
Merge branch 'issue-35514-uve-iframe-sizing-phase-1' of https://githu…
rjvelazco May 8, 2026
ac3c2d5
chore(uve): fix formatting in dot-uve-style-editor-form.component.ts
rjvelazco May 8, 2026
5f11f37
Merge branch 'main' into issue-35514-uve-iframe-sizing-phase-1
zJaaal May 8, 2026
85c97ca
fix(uve): hanlde internal navigation
rjvelazco May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
dotAvatar />
} @else if (app.icon) {
<dot-color-icon [color]="app.color ?? 'surface'" size="sm" variant="light">
<span class="material-icons">{{ app.icon }}</span>
<span class="material-symbols-outlined">{{ app.icon }}</span>
</dot-color-icon>
} @else {
<p-avatar class="shadow-lg rounded-full" [label]="app.name" size="large" dotAvatar />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ describe('DotAppsConfigurationHeaderComponent', () => {
expect(colorIcon).toBeTruthy();
expect(colorIcon.componentInstance.color()).toBe('#3b82f6');
expect(
colorIcon.nativeElement.querySelector('.material-icons').textContent.trim()
colorIcon.nativeElement
.querySelector('.material-symbols-outlined')
.textContent.trim()
).toBe('search');
expect(newFixture.debugElement.query(By.css('p-avatar'))).toBeFalsy();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, HostListener, inject, input, output } from '@angular/core';
import { Component, inject, input, output } from '@angular/core';

import { ButtonModule } from 'primeng/button';
import { TooltipModule } from 'primeng/tooltip';
Expand All @@ -13,7 +13,12 @@ import { DotCopyLinkComponent } from '../../../../../../view/components/dot-copy
selector: 'dot-apps-configuration-item',
templateUrl: './dot-apps-configuration-item.component.html',
styleUrls: ['./dot-apps-configuration-item.component.scss'],
imports: [DotCopyLinkComponent, TooltipModule, DotMessagePipe, ButtonModule]
imports: [DotCopyLinkComponent, TooltipModule, DotMessagePipe, ButtonModule],
host: {
'[class.bg-gray-100]': '!site()?.configured',
'[class.text-gray-500]': '!site()?.configured',
'(click)': 'onClick($event)'
}
})
export class DotAppsConfigurationItemComponent {
private dotMessageService = inject(DotMessageService);
Expand All @@ -25,8 +30,7 @@ export class DotAppsConfigurationItemComponent {
export = output<DotAppsSite>();
delete = output<DotAppsSite>();

@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
onClick(event: MouseEvent): void {
event.stopPropagation();
this.edit.emit(this.site());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
dotAvatar />
} @else if (app.icon) {
<dot-color-icon [color]="app.color ?? 'surface'" size="sm" variant="light">
<span class="material-icons">{{ app.icon }}</span>
<span class="material-symbols-outlined">{{ app.icon }}</span>
</dot-color-icon>
} @else {
<p-avatar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ describe('DotAppsCardComponent', () => {
expect(colorIcon).toBeTruthy();
expect(colorIcon.componentInstance.color()).toBe('#3b82f6');
expect(
colorIcon.nativeElement.querySelector('.material-icons').textContent.trim()
colorIcon.nativeElement
.querySelector('.material-symbols-outlined')
.textContent.trim()
).toBe('search');
expect(fixture.debugElement.query(By.css('p-avatar'))).toBeFalsy();
});
Expand Down
2 changes: 1 addition & 1 deletion core-web/apps/dotcms-ui/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ a:visited {
@apply flex flex-col gap-1;
}

.form .field label {
.form .field > label {
@apply text-sm font-medium;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,11 +472,46 @@ export class DotFileFieldComponent
this.#dialogRef?.close();
}

/**
* Mount-time chatter suppression for `handleStoreValueChange`.
*
* The signalMethod's initial firing observes the store's default
* empty value before any user interaction, and after `writeValue`
* the `handleValueChange` -> `store.getAssetData` async hydration
* causes additional ticks (one or more empty-value ticks during
* the in-flight HTTP, then one with the resolved identifier).
* Propagating any of these dirties the parent form on mount.
*
* The rule: ignore every `handleStoreValueChange` tick until
* `writeValue` has run *and* (if it had a value) the store has
* caught up to it once. After that, every emission is user-driven.
*/
#hasHydrated = false;

override writeValue(value: string): void {
super.writeValue(value);
// If Angular wrote a falsy value, there is no async hydration
// to wait for — the next tick is already user-territory.
if (!value) {
this.#hasHydrated = true;
}
}

readonly handleStoreValueChange = signalMethod<string>((value) => {
if (value === null || value === undefined || !this.onChange) {
return;
}

if (!this.#hasHydrated) {
// Mark hydration complete the first time the store catches
// up to the value Angular pushed via `writeValue`. Skip
// propagating that round-trip emission itself.
if (value === this.$value()) {
this.#hasHydrated = true;
}
return;
}

this.onChange(value);
});

Expand Down
Loading
Loading