From f314942206b2b9025861e27425aafda3181c8b3e Mon Sep 17 00:00:00 2001 From: Arcadio Quintero Date: Thu, 30 May 2024 20:28:27 -0400 Subject: [PATCH] feat(edit-content) add category field #28658 --- core-web/libs/edit-content/project.json | 2 +- .../dot-edit-content-field.component.html | 69 ++++++++++--------- .../dot-edit-content-field.component.scss | 5 ++ .../dot-edit-content-field.component.ts | 9 +-- .../dot-edit-content-form.component.html | 4 +- ...ntent-category-field-dialog.component.html | 16 +++++ ...ntent-category-field-dialog.component.scss | 37 ++++++++++ ...nt-category-field-dialog.component.spec.ts | 47 +++++++++++++ ...content-category-field-dialog.component.ts | 17 +++++ ...edit-content-category-field.component.html | 22 ++++++ ...edit-content-category-field.component.scss | 34 +++++++++ ...t-content-category-field.component.spec.ts | 22 ++++++ ...t-edit-content-category-field.component.ts | 59 ++++++++++++++++ .../fields/dot-edit-content-fields.module.ts | 7 +- .../lib/models/dot-edit-content-field.enum.ts | 3 +- 15 files changed, 311 insertions(+), 42 deletions(-) create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.html create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.scss create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.spec.ts create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.ts create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.html create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.scss create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.ts diff --git a/core-web/libs/edit-content/project.json b/core-web/libs/edit-content/project.json index 4a7529437d5f..44746a6fd794 100644 --- a/core-web/libs/edit-content/project.json +++ b/core-web/libs/edit-content/project.json @@ -17,5 +17,5 @@ "outputs": ["{options.outputFile}"] } }, - "tags": [] + "tags": ["type:feature", "scope:dotcms-ui", "portlet:edit-content"] } diff --git a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html index 0c2d394bbe75..dbfdab8844dc 100644 --- a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html +++ b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html @@ -1,87 +1,92 @@ + [for]="field.variable" + dotFieldRequired> + {{ field.name }} + + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field"> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + [formControlName]="field.variable" /> + [field]="field" /> + [formControlName]="field.variable" /> + [attr.data-testId]="'field-' + field.variable" + [formControlName]="field.variable" /> + [attr.data-testId]="'field-' + field.variable" + [field]="field" /> + + {{ field.hint }} diff --git a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.scss b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.scss index cbc28aeef29a..e2a894a99ef6 100644 --- a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.scss +++ b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.scss @@ -2,4 +2,9 @@ display: block; height: fit-content; margin-bottom: 0; + + small { + margin-top: 0.5rem; + display: block; + } } diff --git a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.ts b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.ts index 58cd844fc6cb..34d838aefe33 100644 --- a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.ts +++ b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.ts @@ -1,9 +1,9 @@ -import { NgIf, NgSwitch, NgSwitchCase } from '@angular/common'; -import { ChangeDetectionStrategy, Component, HostBinding, Input, inject } from '@angular/core'; +import { JsonPipe, NgIf, NgSwitch, NgSwitchCase } from '@angular/common'; +import { ChangeDetectionStrategy, Component, HostBinding, inject, Input } from '@angular/core'; import { ControlContainer, ReactiveFormsModule } from '@angular/forms'; import { BlockEditorModule } from '@dotcms/block-editor'; -import { DotCMSContentTypeField, DotCMSContentlet } from '@dotcms/dotcms-models'; +import { DotCMSContentlet, DotCMSContentTypeField } from '@dotcms/dotcms-models'; import { DotFieldRequiredDirective } from '@dotcms/ui'; import { DotEditContentBinaryFieldComponent } from '../../fields/dot-edit-content-binary-field/dot-edit-content-binary-field.component'; @@ -35,7 +35,8 @@ import { FIELD_TYPES } from '../../models/dot-edit-content-field.enum'; BlockEditorModule, DotEditContentBinaryFieldComponent, DotEditContentKeyValueComponent, - DotEditContentWYSIWYGFieldComponent + DotEditContentWYSIWYGFieldComponent, + JsonPipe ] }) export class DotEditContentFieldComponent { diff --git a/core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.html b/core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.html index 74815ef7efb9..ab89f9bc3ce3 100644 --- a/core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.html +++ b/core-web/libs/edit-content/src/lib/components/dot-edit-content-form/dot-edit-content-form.component.html @@ -17,9 +17,9 @@
diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.html b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.html new file mode 100644 index 000000000000..98a7ea288f66 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.html @@ -0,0 +1,16 @@ +
+
Search & category tree
+
+
Selected Categories
+
+ + +
+
+
diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.scss b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.scss new file mode 100644 index 000000000000..38dc603410e0 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.scss @@ -0,0 +1,37 @@ +@use "variables" as *; + +:host { + display: block; + height: 100%; + + .category-field__dialog { + display: grid; + grid-template-columns: 2fr 1fr; + max-width: 1200px; + margin: auto; + } + + .category-field__left-pane, + .category-field__right-pane { + padding: $spacing-3; + gap: $spacing-3; + } + + .category-field__left-pane { + background-color: $color-palette-gray-300; + } + + .category-field__selected-categories { + border: $field-border-size solid $color-palette-gray-400; + border-radius: $border-radius-sm; + padding: $spacing-3; + } + + .category-field__actions { + gap: $spacing-1; + } +} + +::ng-deep .category-field__dialog .p-dialog-content { + padding: 0; +} diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.spec.ts new file mode 100644 index 000000000000..4b4a3ad10688 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.spec.ts @@ -0,0 +1,47 @@ +import { expect, it } from '@jest/globals'; +import { byTestId, createComponentFactory, Spectator } from '@ngneat/spectator'; +import { mockProvider } from '@ngneat/spectator/jest'; + +import { DynamicDialogRef } from 'primeng/dynamicdialog'; + +import { DotEditContentCategoryFieldDialogComponent } from './dot-edit-content-category-field-dialog.component'; + +describe('DotEditContentCategoryFieldDialogComponent', () => { + let spectator: Spectator; + let dialogRef: DynamicDialogRef; + + const createComponent = createComponentFactory({ + component: DotEditContentCategoryFieldDialogComponent, + providers: [ + mockProvider(DynamicDialogRef, { + close: jest.fn() + }) + ] + }); + + beforeEach(() => { + spectator = createComponent(); + dialogRef = spectator.inject(DynamicDialogRef); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should have a cancel button', () => { + expect(spectator.query(byTestId('cancel-btn'))).not.toBeNull(); + }); + it('should have a apply button', () => { + expect(spectator.query(byTestId('apply-btn'))).not.toBeNull(); + }); + + it('should close the dialog when you click cancel', () => { + const cancelBtn = spectator.query(byTestId('cancel-btn')); + expect(cancelBtn).not.toBeNull(); + + expect(dialogRef.close).not.toHaveBeenCalled(); + + spectator.click(cancelBtn); + expect(dialogRef.close).toHaveBeenCalled(); + }); +}); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.ts new file mode 100644 index 000000000000..fcef298bbf44 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component.ts @@ -0,0 +1,17 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; + +import { ButtonModule } from 'primeng/button'; +import { DialogModule } from 'primeng/dialog'; +import { DynamicDialogRef } from 'primeng/dynamicdialog'; + +@Component({ + selector: 'dot-edit-content-category-field-dialog', + standalone: true, + imports: [DialogModule, ButtonModule], + templateUrl: './dot-edit-content-category-field-dialog.component.html', + styleUrl: './dot-edit-content-category-field-dialog.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DotEditContentCategoryFieldDialogComponent { + protected dialogRef: DynamicDialogRef = inject(DynamicDialogRef); +} diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.html b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.html new file mode 100644 index 000000000000..129b1e061a24 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.html @@ -0,0 +1,22 @@ +
+ @if (values.length) { +
+ @for (category of values; track category.id) { + + } +
+ } + +
+ +
+
diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.scss b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.scss new file mode 100644 index 000000000000..e3f46403b26f --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.scss @@ -0,0 +1,34 @@ +@use "variables" as *; + +.dot-category-field__wrapper { + .dot-category-field__categories, + .dot-category-field__select { + border: $field-border-size solid $color-palette-gray-400; + display: flex; + flex-wrap: wrap; + align-items: center; + } + + .dot-category-field__categories { + padding: $spacing-1; + gap: $spacing-1; + border-radius: $border-radius-md $border-radius-md 0 0; + } + + .dot-category-field__select { + height: $field-height-md; + border-radius: $border-radius-md; + padding: 0 $spacing-0; + justify-content: flex-end; + } + + &.has-categories { + .dot-category-field__select { + border-radius: 0 0 $border-radius-md $border-radius-md; + } + + .dot-category-field__categories { + border-bottom: none; + } + } +} diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts new file mode 100644 index 000000000000..b8f8c4140e1d --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DotEditContentCategoryFieldComponent } from './dot-edit-content-category-field.component'; + +describe('DotEditContentCategoryFieldComponent', () => { + let component: DotEditContentCategoryFieldComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [DotEditContentCategoryFieldComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(DotEditContentCategoryFieldComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.ts new file mode 100644 index 000000000000..e274ff6dfeb9 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.ts @@ -0,0 +1,59 @@ +import { NgClass } from '@angular/common'; +import { ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; +import { ControlContainer, ReactiveFormsModule } from '@angular/forms'; + +import { ButtonModule } from 'primeng/button'; +import { ChipModule } from 'primeng/chip'; +import { ChipsModule } from 'primeng/chips'; +import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { TooltipModule } from 'primeng/tooltip'; + +import { DotCMSContentTypeField } from '@dotcms/dotcms-models'; + +import { DotEditContentCategoryFieldDialogComponent } from './components/dot-edit-content-category-field-dialog/dot-edit-content-category-field-dialog.component'; + +@Component({ + selector: 'dot-edit-content-category-field', + standalone: true, + imports: [ChipsModule, ReactiveFormsModule, ButtonModule, ChipModule, NgClass, TooltipModule], + templateUrl: './dot-edit-content-category-field.component.html', + styleUrl: './dot-edit-content-category-field.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, + viewProviders: [ + { + provide: ControlContainer, + useFactory: () => inject(ControlContainer, { skipSelf: true }) + } + ], + providers: [DialogService] +}) +export class DotEditContentCategoryFieldComponent { + field = input.required(); + // values = []; + values = [ + { id: 1, value: 'Streetwear' }, + { id: 2, value: 'Boys' }, + { id: 2, value: 'Jeans' }, + { id: 2, value: 'Pants' }, + { id: 2, value: 'Formal' }, + { id: 2, value: 'Plain' }, + { id: 2, value: 'Pants with linen for woman' }, + { id: 2, value: 'Printed' }, + { id: 2, value: 'Formal pants for man' }, + { id: 2, value: 'Kids' }, + { id: 2, value: 'Kids streetwear' } + ]; + #ref: DynamicDialogRef; + + #dialogService = inject(DialogService); + + showCategories() { + this.#ref = this.#dialogService.open(DotEditContentCategoryFieldDialogComponent, { + showHeader: false, + styleClass: 'category-field__dialog', + width: '1000px', + height: '600px', + position: 'center' + }); + } +} diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-fields.module.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-fields.module.ts index 42f186a479d5..ba5c5751376c 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-fields.module.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-fields.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { DotEditContentBinaryFieldComponent } from './dot-edit-content-binary-field/dot-edit-content-binary-field.component'; import { DotEditContentCalendarFieldComponent } from './dot-edit-content-calendar-field/dot-edit-content-calendar-field.component'; +import { DotEditContentCategoryFieldComponent } from './dot-edit-content-category-field/dot-edit-content-category-field.component'; import { DotEditContentCheckboxFieldComponent } from './dot-edit-content-checkbox-field/dot-edit-content-checkbox-field.component'; import { DotEditContentCustomFieldComponent } from './dot-edit-content-custom-field/dot-edit-content-custom-field.component'; import { DotEditContentJsonFieldComponent } from './dot-edit-content-json-field/dot-edit-content-json-field.component'; @@ -27,7 +28,8 @@ import { DotEditContentWYSIWYGFieldComponent } from './dot-edit-content-wysiwyg- DotEditContentBinaryFieldComponent, DotEditContentJsonFieldComponent, DotEditContentCustomFieldComponent, - DotEditContentWYSIWYGFieldComponent + DotEditContentWYSIWYGFieldComponent, + DotEditContentCategoryFieldComponent ], exports: [ DotEditContentTextAreaComponent, @@ -41,7 +43,8 @@ import { DotEditContentWYSIWYGFieldComponent } from './dot-edit-content-wysiwyg- DotEditContentBinaryFieldComponent, DotEditContentJsonFieldComponent, DotEditContentCustomFieldComponent, - DotEditContentWYSIWYGFieldComponent + DotEditContentWYSIWYGFieldComponent, + DotEditContentCategoryFieldComponent ] }) export class DotEditContentFieldsModule {} diff --git a/core-web/libs/edit-content/src/lib/models/dot-edit-content-field.enum.ts b/core-web/libs/edit-content/src/lib/models/dot-edit-content-field.enum.ts index 7fc7ecfb8683..fef8d1062f74 100644 --- a/core-web/libs/edit-content/src/lib/models/dot-edit-content-field.enum.ts +++ b/core-web/libs/edit-content/src/lib/models/dot-edit-content-field.enum.ts @@ -24,5 +24,6 @@ export enum FIELD_TYPES { CUSTOM_FIELD = 'Custom-Field', JSON = 'JSON-Field', KEY_VALUE = 'Key-Value', - WYSIWYG = 'WYSIWYG' + WYSIWYG = 'WYSIWYG', + CATEGORY = 'Category' }