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'
}