From cadf6536f96caca7907f8e9f7820475f647f7e19 Mon Sep 17 00:00:00 2001 From: Nicolas Molina Monroy Date: Wed, 11 Dec 2024 14:53:39 -0400 Subject: [PATCH] chore(edit-content): enhance dialog and table functionality (#30901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Parent Issue https://github.com/dotCMS/core/issues/30523 ### Proposed Changes This pull request includes changes to the `dot-select-existing-content.component.html` and `dot-select-existing-content.component.ts` files to improve the user interface and functionality of the content selection dialog. The most important changes include adding a header template to the dialog, making the dialog non-draggable, and introducing a method to check if an item is selected. Improvements to user interface: * [`dot-select-existing-content.component.html`](diffhunk://#diff-ba794904cc95635d9efca07b7e2bfeb948b5b0bb0c8e1e97c777c615398ba011R4-R22): Added a header template to the dialog with a search icon and title. * [`dot-select-existing-content.component.html`](diffhunk://#diff-ba794904cc95635d9efca07b7e2bfeb948b5b0bb0c8e1e97c777c615398ba011R4-R22): Made the dialog non-draggable and updated the style to include a height property. Functionality enhancements: * [`dot-select-existing-content.component.html`](diffhunk://#diff-ba794904cc95635d9efca07b7e2bfeb948b5b0bb0c8e1e97c777c615398ba011L79-R89): Added a conditional class to highlight selected rows in the table. * [`dot-select-existing-content.component.ts`](diffhunk://#diff-14d3d666b0a074fe26436013ebf4abe96e518e28e9799b85b393d14b82ac528bR115-R123): Introduced the `checkIfSelected` method to determine if an item is selected. ### Checklist - [x] Tests - [x] Translations - [x] Security Implications Contemplated (add notes if applicable) ### Screenshots - The title should be "Search" and not "Select existing content". Screenshot 2024-12-09 at 8 45 05 PM - If the user make a search, close the dialog and open it again the search input and the entries button are not clean, keeps the state. https://github.com/user-attachments/assets/b92a8307-c43c-4f4c-b14f-fb3210c91b6a - Following patterns, Dialog should keep the same height. when the user perform a search with a couple of rows the height change https://github.com/user-attachments/assets/286c9e15-29d3-4de4-ac7a-b9972928a973 - Form figma: The selected items will have an active state background. - Dialog should not be draggable. https://github.com/user-attachments/assets/767a049a-a713-4365-87b1-44c2c8f648ba --- .../dotcms-binary-field-builder/project.json | 2 +- ...dot-select-existing-content.component.html | 238 ++++++++++-------- ...dot-select-existing-content.component.scss | 9 +- ...-select-existing-content.component.spec.ts | 61 +++++ .../dot-select-existing-content.component.ts | 17 ++ .../store/existing-content.store.ts | 6 + ...-content-relationship-field.component.html | 2 +- ...-content-relationship-field.component.scss | 2 +- .../WEB-INF/messages/Language.properties | 1 + 9 files changed, 221 insertions(+), 117 deletions(-) diff --git a/core-web/apps/dotcms-binary-field-builder/project.json b/core-web/apps/dotcms-binary-field-builder/project.json index 0ce4f73112ef..8de29bdf6508 100644 --- a/core-web/apps/dotcms-binary-field-builder/project.json +++ b/core-web/apps/dotcms-binary-field-builder/project.json @@ -46,7 +46,7 @@ { "type": "initial", "maximumWarning": "500kb", - "maximumError": "2mb" + "maximumError": "2.5mb" }, { "type": "anyComponentStyle", diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.html b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.html index 474a86d1fc92..cf611578ffd5 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.html +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.html @@ -1,121 +1,137 @@ @let data = store.data(); @let pagination = store.pagination(); - - - -
-
-
- +@if ($visible()) { + @defer { + + +
+ + + {{ 'dot.file.relationship.dialog.search' | dm }} + +
+
+ + +
+
+
+ +
+
+

+ {{ + 'dot.file.relationship.dialog.per.page' + | dm: [pagination.rowsPerPage.toString()] + }} +

+
+
+
-
+ + + + + + Title + + + + Step + + + + Description + + + + Last Update + + + Menu + + + + + +
+

+ {{ 'dot.file.relationship.dialog.search.empty.content' | dm }} +

+
+ + +
+ + + + + + +

{{ item.title }}

+ + {{ item.step }} + +

{{ item.description }}

+ + {{ item.lastUpdate | date }} + + + + +
+ + +
+

{{ - 'dot.file.relationship.dialog.per.page' - | dm: [pagination.rowsPerPage.toString()] + 'dot.file.relationship.dialog.selected.items' + | dm: [$selectedItems().length.toString()] }}

-
- -
-
- - - - - Title - - - - Step - - - - Description - - - - Last Update - - - Menu - - - - - -
-

Relate content by clicking on the Plus Button

+
+ +
- - - - - - - - - -

{{ item.title }}

- - {{ item.step }} - -

{{ item.description }}

- - {{ item.lastUpdate | date }} - - - - -
- - -
-
-

- {{ - 'dot.file.relationship.dialog.selected.items' - | dm: [$selectedItems().length.toString()] - }} -

-
-
- - -
-
-
- +
+
+
+ } +} diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.scss b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.scss index c34af3986231..ca07422c372f 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.scss +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.scss @@ -2,12 +2,10 @@ ::ng-deep { p-table { - .p-datatable-sm.p-datatable-existing-content { + .p-datatable-existing-content { .p-datatable-header { background-color: $white; border: 0px; - padding-left: 0px; - padding-right: 0px; } .p-datatable-table { border: 1px solid $color-palette-gray-300; @@ -24,5 +22,10 @@ height: auto; } } + .dotTable.p-datatable { + .p-datatable-tbody > tr > td:first-child:has(p-tableCheckbox) + td { + padding: 0 $spacing-1; + } + } } } diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.spec.ts index ec2a9dc5ed84..d4988f8efa21 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.spec.ts @@ -1,5 +1,9 @@ import { Spectator, createComponentFactory } from '@ngneat/spectator/jest'; +import { fakeAsync, tick } from '@angular/core/testing'; + +import { Dialog } from 'primeng/dialog'; + import { DotMessageService } from '@dotcms/data-access'; import { RelationshipFieldItem } from '@dotcms/edit-content/fields/dot-edit-content-relationship-field/models/relationship.models'; import { MockDotMessageService } from '@dotcms/utils-testing'; @@ -85,4 +89,61 @@ describe('DotSelectExistingContentComponent', () => { expect(label).toBe('Apply 2 entries'); }); }); + + describe('checkIfSelected', () => { + it('should return true when content is in selectedContent array', () => { + // Arrange + const testContent = mockRelationshipItem('1'); + spectator.component.$selectedItems.set([testContent]); + + // Act + const result = spectator.component.checkIfSelected(testContent); + + // Assert + expect(result).toBe(true); + }); + + it('should return false when content is not in selectedContent array', () => { + // Arrange + const testContent = mockRelationshipItem('123'); + const differentContent = mockRelationshipItem('456'); + spectator.component.$selectedItems.set([differentContent]); + + // Act + const result = spectator.component.checkIfSelected(testContent); + + // Assert + expect(result).toBe(false); + }); + + it('should return false when selectedContent is empty', () => { + // Arrange + const testContent = mockRelationshipItem('123'); + spectator.component.$selectedItems.set([]); + + // Act + const result = spectator.component.checkIfSelected(testContent); + + // Assert + expect(result).toBe(false); + }); + }); + + describe('onShowDialog', () => { + it('should call onShowDialog when dialog is shown', fakeAsync(() => { + // Arrange + spectator.component.$visible.set(true); + + spectator.detectChanges(); + + tick(100); + const spy = jest.spyOn(spectator.component, 'onShowDialog'); + + // Act + spectator.triggerEventHandler(Dialog, 'onShow', null); + + // Assert + expect(spy).toHaveBeenCalled(); + })); + }); }); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.ts index 0e066ed75105..8917e5db9af7 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/dot-select-existing-content.component.ts @@ -112,4 +112,21 @@ export class DotSelectExistingContentComponent { emitSelectedItems() { this.onSelectItems.emit(this.$selectedItems()); } + + /** + * Checks if an item is selected. + * @param item - The item to check. + * @returns True if the item is selected, false otherwise. + */ + checkIfSelected(item: RelationshipFieldItem) { + return this.$selectedItems().some((selectedItem) => selectedItem.id === item.id); + } + + /** + * Shows the existing content dialog and loads the content. + */ + onShowDialog() { + this.store.applyInitialState(); + this.store.loadContent(); + } } diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/store/existing-content.store.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/store/existing-content.store.ts index c65414f675bc..1c352ef61257 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/store/existing-content.store.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/components/dot-select-existing-content/store/existing-content.store.ts @@ -70,6 +70,12 @@ export const ExistingContentStore = signalStore( ) ) ), + /** + * Applies the initial state for the existing content. + */ + applyInitialState: () => { + patchState(store, initialState); + }, /** * Advances the pagination to the next page and updates the state accordingly. */ diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/dot-edit-content-relationship-field.component.html b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/dot-edit-content-relationship-field.component.html index ccc2e97d92f6..ad9bc0c48fdc 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/dot-edit-content-relationship-field.component.html +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-relationship-field/dot-edit-content-relationship-field.component.html @@ -4,7 +4,7 @@