fix(edit-content): refine relationship field UI to match Content Drive#36377
fix(edit-content): refine relationship field UI to match Content Drive#36377oidacra wants to merge 6 commits into
Conversation
Align the Relationship field in the new Edit Contentlet with the Content Drive look-and-feel and the rest of the form fields: - Rename the "Languages" column to "Locales" and render each value as a chip (p-tag) instead of plain text - Reuse the shared status badge (already Content Drive's colors) and left-align the Status column header with its chips - Move the field hint/error outside the card via dot-card-field-footer, consistent with the other field wrappers - Rewrite the empty state with an inline "Relate content" link that opens the same flow as the + button; hidden when the field is read-only - Enable horizontal scrolling so extra showFields columns are not clipped Adds a spec for the inner dot-relationship-field component and footer-hint coverage on the wrapper spec. Closes #36155
🤖 dotBot Review (Bedrock)Reviewed 11 file(s); 5 candidate(s) → 4 confirmed, 0 uncertain (unverified, kept for review). Confirmed findings
us.deepseek.r1-v1:0 · Run: #28606379361 · tokens: in: 56047 · out: 11489 · total: 67536 · calls: 20 · est. ~$0.138 |
| [isRequired]="isRequired" /> | ||
| </dot-card-field-content> | ||
| <dot-card-field-footer> | ||
| @if (fieldHasError) { |
There was a problem hiding this comment.
🟠 [High] Error message only shows required validation
The error message conditional *ngIf="control?.errors?.required" only displays when the 'required' error is present. Other validation errors (e.g., invalid format, custom validators) will not trigger the error message, leaving users unaware of other issues. Should check for any error with *ngIf="control?.errors" to surface all validation failures.
…ayout - Do not mark the relationship control as touched on the initial value sync, so a required empty field no longer shows its validation error on first render (touched now fires only on user-driven changes) - Constrain the Locales column to a fixed width so it no longer stretches - Right-align the Status column header and chips Refs #36155
| <dot-card-field-footer> | ||
| @if (fieldHasError) { | ||
| <div class="error-message"> | ||
| @if (isRequired) { |
There was a problem hiding this comment.
🟠 [High] Missing non-required validation error handling
The validation message only displays for 'required' errors (line 23 condition). Other validation errors (e.g., invalid relationships) will trigger the error state but not show a message, violating validation feedback expectations. The *ngIf should check for any error presence rather than specific error types.
…mplate Address code-review findings: - Keep the p-table summary template always registered; make only the pagination content conditional (avoids dynamic template create/destroy) - Add data-testid to the Locales and Status column headers; query tests via byTestId and assert alignment with jest-dom toHaveClass - Use createFakeLanguage instead of a hand-built DotLanguage mock - Make the CVA contract test behavioral (setDisabledState flips state) - Cover the footer error branch (required + invalid → error, hint hidden) - Tailwind v4: focus-visible:outline-none → outline-hidden Refs #36155
| }); | ||
| }); | ||
|
|
||
| describe('Status column header alignment', () => { |
There was a problem hiding this comment.
🟠 [High] Incorrect Tailwind class in status header alignment test
The test checks for 'text-right!' class which is invalid Tailwind syntax. The correct class for right-aligned text with important modifier is '!text-right'. This test would fail if the component properly uses '!text-right', leading to false negatives in test results.
| // error as soon as the form renders. | ||
| if (this.#hasSyncedInitialValue) { | ||
| this.onTouched(); | ||
| } else { |
There was a problem hiding this comment.
🟠 [High] Incorrect touched state on programmatic value changes
The control is marked as touched on any value change after initial sync via this.control.markAsTouched(), including programmatic updates. This causes validation errors to appear prematurely when values are changed by code rather than user interaction, violating Angular's form control state semantics.
| [hasError]="fieldHasError" | ||
| [isRequired]="isRequired" /> | ||
| </dot-card-field-content> | ||
| <dot-card-field-footer> |
There was a problem hiding this comment.
🟠 [High] Missing non-required error messages in relationship field
The error message block in dot-edit-content-relationship-field.component.html line 20 only displays when isRequired is true. This misses validation errors from other sources (e.g., custom validators), leaving users unaware of non-required validation failures. The condition should check fieldHasError generally, not just required state.
…rename The default language column header was renamed from "Language" to "Locales"; update the E2E header assertion and comment to match. Refs #36155
| <th scope="col" class="w-32 max-w-32 min-w-32 text-right!"> | ||
| <th | ||
| scope="col" | ||
| class="w-32 max-w-32 min-w-32 text-right!" |
There was a problem hiding this comment.
🟠 [High] Status column header misaligned due to text-right! class
The Status column header uses 'text-right!' class which forces right alignment, contradicting the requirement to left-align it with the chips. The PR's AC specifies left alignment, and the class should be 'text-left' or removed if default aligns left.
| describe('Status column header alignment', () => { | ||
| beforeEach(() => setup()); | ||
|
|
||
| it('should right-align the status header so it lines up with the chips', () => { |
There was a problem hiding this comment.
🟠 [High] Invalid Tailwind class in status header alignment test
The test checks for 'text-right!' class, but Tailwind's important modifier uses '!text-right'. This test would fail as the actual class is correctly applied with '!text-right'.
| [hasError]="fieldHasError" | ||
| [isRequired]="isRequired" /> | ||
| </dot-card-field-content> | ||
| <dot-card-field-footer> |
There was a problem hiding this comment.
🟠 [High] Missing validation error messages for non-required errors
The error message block in dot-edit-content-relationship-field.component.html line 20 only checks for 'required' errors using *ngIf="control?.errors?.['required']". This means other validation errors (e.g. custom validators, format errors) will not display their messages to users, leaving them without critical feedback when non-required validations fail. The PR's stated goal of maintaining existing validation behavior is violated as error visibility is reduced.
…t severity Covers the issue #36155 suggested E2E: after relating content, the Locales cell renders a p-tag chip (not plain text) and the Status cell renders a status chip with the correct PrimeNG severity class (Published -> p-tag-success). Adds localeTag()/statusTag() locators to the relationship-field helper. Refs #36155
| beforeEach(() => setup()); | ||
|
|
||
| it('should render the Locales header using the table language key', () => { | ||
| const localeHeader = spectator.query(byTestId('relationship-locale-header')); |
There was a problem hiding this comment.
🟠 [High] Test uses outdated i18n key for Locales column
The test at line 129 references 'dot.file.relationship.field.table.language' which no longer exists in Language.properties. The column was renamed to 'Locales' in the UI but the test wasn't updated to use the new i18n key, causing test failures.
| describe('Status column header alignment', () => { | ||
| beforeEach(() => setup()); | ||
|
|
||
| it('should right-align the status header so it lines up with the chips', () => { |
There was a problem hiding this comment.
🟠 [High] Status header alignment test expects right-aligned style conflicting with PR's left-alignment requirement
The test at line 146 checks for 'right' text alignment on the Status header column (expect(headerStyles.textAlign).toBe('right')), which directly contradicts the PR's stated requirement to left-align the Status column header. This creates a false-positive test that would pass even if the implementation regressed to right-alignment.
| @@ -17,4 +17,21 @@ | |||
| [hasError]="fieldHasError" | |||
| [isRequired]="isRequired" /> | |||
There was a problem hiding this comment.
🟠 [High] Error message only handles required validation
The error message template only displays messages for 'required' errors (line 18), leaving other validation errors with empty messages. The [showError] binding correctly triggers visibility on any invalid state, but users see an empty message box for non-required errors.
…s test
The chips spec configures the relationship as ONE_TO_MANY, which renders
multi-select checkboxes in the select-existing-content dialog. The test was
calling selectSingleItem() (radio button), so the p-tableradiobutton locator
never resolved and the test hit the 60s timeout ("Target closed"). Switch to
selectItem() (checkbox), matching every other ONE_TO_MANY test in the suite.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ATxLthJvmM9tBfKUTCRBwA
| @@ -3,10 +3,6 @@ | |||
| @let data = store.paginatedData(); | |||
There was a problem hiding this comment.
🟠 [High] Missing validation feedback in relationship field
The HTML template for dot-relationship-field.component.html removed the previous hint/error display (likely in a
|
|
||
| describe('Status column header alignment', () => { | ||
| beforeEach(() => setup()); | ||
|
|
There was a problem hiding this comment.
🟠 [High] Incorrect status header alignment assertion in test
The test asserts that the status header has 'text-right!' class (right-aligned), but PR description states the status header should be left-aligned to match chips. This creates a false-positive test that validates against the intended UI change. The test should check for left-alignment instead.
| [isRequired]="isRequired" /> | ||
| </dot-card-field-content> | ||
| <dot-card-field-footer> | ||
| @if (fieldHasError) { |
There was a problem hiding this comment.
🟠 [High] Missing error message for non-required validation failures
The error message block in dot-edit-content-relationship-field.component.html line 21 uses *ngIf="fieldHasError && isRequired", meaning only required validation errors display messages. Non-required validations (e.g. format, custom rules) will trigger fieldHasError=true but not show error messages, breaking validation feedback for these cases.
Summary
Refines the Relationship field UI in the new Edit Contentlet so it aligns with the Content Drive look-and-feel and with the rest of the form fields. Frontend-only (plus one i18n string change); no backend or API contract changes.
Changes
p-tagwithwhitespace-nowrap) instead of plain text.dot-contentlet-status-badge(sameSTATUS_SEVERITYcolors as Content Drive — verified, no color change needed). The Status column header is now left-aligned to the leading edge of its chips.dot-card-field-footer, matching every other field wrapper; removed from the table'ssummarytemplate.+button. The link (and its suffix) are hidden when the field is read-only.showFieldscolumns are not clipped or collapsed.Acceptance Criteria
+buttonshowFieldscolumns there is no clipping; the table scrolls horizontallyTest plan
pnpm nx lint edit-content— passes (no new errors)pnpm nx test edit-content— passes (102 suites, 1877 tests)dot-relationship-fieldcomponent covering: Locales header, locale chip rendering, status header alignment, empty-state message + link click + read-only hiding, horizontal scroll, and the CVA contract.Changed files
.../dot-relationship-field/dot-relationship-field.component.{html,ts,scss}.../dot-relationship-field/dot-relationship-field.component.spec.ts(new).../dot-edit-content-relationship-field.component.{html,ts,spec.ts}dotCMS/src/main/webapp/WEB-INF/messages/Language.propertiesThis PR fixes: #36155