Skip to content

Commit

Permalink
feat(edit-content) change from dialog to sidebar #28764
Browse files Browse the repository at this point in the history
  • Loading branch information
oidacra committed Jun 11, 2024
1 parent 7f68e2e commit 3f30e53
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 149 deletions.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<p-sidebar
(onHide)="this.closedSidebar.emit()"
[(visible)]="visible"
[showCloseIcon]="false"
#sidebar
data-testId="sidebar"
position="right"
styleClass="w-9">
<ng-template pTemplate="header">
<div class="flex flex-row category-field__header">
<button
(click)="sidebar.close($event)"
class="p-button-rounded p-button-text"
data-testId="back-btn"
icon="pi pi-angle-left"
pButton></button>
<div class="category-field__header-title" data-testId="sidebar-title">
{{ 'edit.content.category-field.sidebar.header.select-categories' | dm }}
</div>
</div>
</ng-template>

<div class="category-field__content h-full w-full">
<div class="category-field__left-pane flex flex-column">
<div class="category-field__search">Input Search</div>
<div class="flex-grow-1 category-field__categories">Categories</div>
</div>

<div class="category-field__right-pane flex flex-column">
<div class="category-field__selected-categories-list flex-1">Selected Categories</div>
<div class="category-field__actions flex justify-content-end">
<button class="p-button p-button-link" data-testId="clear_all-btn" pButton>
{{ 'edit.content.category-field.button.clear-all' | dm }}
</button>
</div>
</div>
</div>
</p-sidebar>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@use "variables" as *;

.category-field__header {
height: 60px;
align-items: center;
flex-wrap: wrap;
gap: $spacing-0;
padding: 0 $spacing-4;
}

.category-field__header-title {
font-size: $font-size-lg;
font-weight: $font-weight-medium-bold;
margin: 0;
}

.category-field__content {
display: grid;
grid-template-columns: 2fr 1fr;
margin: auto;
background-color: $color-palette-gray-300;
padding: $spacing-4;
gap: $spacing-1;
}

.category-field__left-pane,
.category-field__right-pane {
gap: $spacing-1;
}

.category-field__search,
.category-field__categories,
.category-field__right-pane {
border: $field-border-size solid $color-palette-gray-400;
border-radius: $border-radius-md;
background-color: $white;

padding: $spacing-3;
}

:host ::ng-deep .p-sidebar-content {
padding: 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { expect, it } from '@jest/globals';
import { byTestId, createComponentFactory, Spectator } from '@ngneat/spectator';
import { mockProvider } from '@ngneat/spectator/jest';

import { DotMessageService } from '@dotcms/data-access';

import { DotEditContentCategoryFieldSidebarComponent } from './dot-edit-content-category-field-sidebar.component';

describe('DotEditContentCategoryFieldSidebarComponent', () => {
let spectator: Spectator<DotEditContentCategoryFieldSidebarComponent>;

const createComponent = createComponentFactory({
component: DotEditContentCategoryFieldSidebarComponent,
providers: [mockProvider(DotMessageService)]
});

beforeEach(() => {
spectator = createComponent();
});

afterEach(() => {
jest.resetAllMocks();
});

it('should have `visible` property by default `true`', () => {
expect(spectator.component.visible).toBe(true);
});

it('should have a sidebar', () => {
expect(spectator.query(byTestId('sidebar'))).not.toBeNull();
});

it('should have a clear all button', () => {
expect(spectator.query(byTestId('clear_all-btn'))).not.toBeNull();
});

it('should close the sidebar when you click back', () => {
const closedSidebarSpy = jest.spyOn(spectator.component.closedSidebar, 'emit');
const cancelBtn = spectator.query(byTestId('back-btn'));
expect(cancelBtn).not.toBeNull();

expect(closedSidebarSpy).not.toHaveBeenCalled();

spectator.click(cancelBtn);
expect(closedSidebarSpy).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ChangeDetectionStrategy, Component, EventEmitter } from '@angular/core';

import { ButtonModule } from 'primeng/button';
import { DialogModule } from 'primeng/dialog';
import { SidebarModule } from 'primeng/sidebar';

import { DotMessagePipe } from '@dotcms/ui';

/**
* Component for the sidebar that appears when editing content category field.
*/
@Component({
selector: 'dot-edit-content-category-field-sidebar',
standalone: true,
imports: [DialogModule, ButtonModule, DotMessagePipe, SidebarModule],
templateUrl: './dot-edit-content-category-field-sidebar.component.html',
styleUrl: './dot-edit-content-category-field-sidebar.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DotEditContentCategoryFieldSidebarComponent {
/**
* Indicates whether the sidebar is visible or not.
*
*/
visible = true;

/**
* The event is fired whenever the sidebar is closed either by hitting 'Escape',
* clicking on the overlay, or on the back button.
*
*/
closedSidebar = new EventEmitter<void>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@
}

<div class="dot-category-field__select">
<p-button
(onClick)="showCategories()"
[label]="'edit.content.category-field.show-categories-dialog' | dm"
data-testId="show-dialog-btn"
icon="pi pi-pencil"
styleClass="p-button-sm p-button-text p-button-secondary" />
<button
(click)="showCategoriesSidebar()"
[disabled]="disableSelectCategoriesButton()"
[label]="'edit.content.category-field.button.show-categories' | dm"
class="p-button-sm p-button-text p-button-secondary"
data-testId="show-sidebar-btn"
pButton></button>
</div>

<ng-container dotDynamic></ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { mockProvider } from '@ngneat/spectator/jest';

import { DotMessageService } from '@dotcms/data-access';

import { DotEditContentCategoryFieldSidebarComponent } from './components/dot-edit-content-category-field-sidebar/dot-edit-content-category-field-sidebar.component';
import { DotEditContentCategoryFieldComponent } from './dot-edit-content-category-field.component';

describe('DotEditContentCategoryFieldComponent', () => {
Expand All @@ -22,17 +23,75 @@ describe('DotEditContentCategoryFieldComponent', () => {
jest.resetAllMocks();
});

it('should have a select categories button', () => {
expect(spectator.query(byTestId('show-dialog-btn'))).not.toBeNull();
describe('Elements', () => {
it('should render a button for selecting categories', () => {
expect(spectator.query(byTestId('show-sidebar-btn'))).not.toBeNull();
});

it('should display the category list with chips when there are categories', () => {
spectator.component.values = [];
spectator.detectComponentChanges();
expect(spectator.query(byTestId('category-chip-list'))).toBeNull();

spectator.component.values = [{ id: 1, value: 'Streetwear' }];
spectator.detectComponentChanges();
expect(spectator.query(byTestId('category-chip-list'))).not.toBeNull();
});
});

it('should show the category list wrapper', () => {
spectator.component.values = [];
spectator.detectComponentChanges();
expect(spectator.query(byTestId('category-chip-list'))).toBeNull();
describe('Interactions', () => {
it('should invoke `showCategoriesSidebar` method when the select button is clicked', () => {
const selectBtn = spectator.query(byTestId('show-sidebar-btn'));
const showCategoriesSidebarSpy = jest.spyOn(
spectator.component,
'showCategoriesSidebar'
);
expect(selectBtn).not.toBeNull();

spectator.click(selectBtn);

expect(showCategoriesSidebarSpy).toHaveBeenCalled();
});

it('should disable the `Select` button after `showCategoriesSidebar` method is invoked', () => {
const selectBtn = spectator.query(byTestId('show-sidebar-btn')) as HTMLButtonElement;
expect(selectBtn).not.toBeNull();

spectator.click(selectBtn);

expect(selectBtn.disabled).toBe(true);
});

it('should create a DotEditContentCategoryFieldSidebarComponent instance when the `Select` button is clicked', () => {
const selectBtn = spectator.query(byTestId('show-sidebar-btn')) as HTMLButtonElement;
expect(selectBtn).not.toBeNull();
expect(spectator.query(DotEditContentCategoryFieldSidebarComponent)).toBeNull();

spectator.click(selectBtn);
expect(spectator.query(DotEditContentCategoryFieldSidebarComponent)).not.toBeNull();
});

it('should remove DotEditContentCategoryFieldSidebarComponent when `closedSidebar` emit', async () => {
const selectBtn = spectator.query(byTestId('show-sidebar-btn')) as HTMLButtonElement;
expect(selectBtn).not.toBeNull();
spectator.click(selectBtn);

const sidebarComponentRef = spectator.query(
DotEditContentCategoryFieldSidebarComponent
);
expect(sidebarComponentRef).not.toBeNull();

sidebarComponentRef.closedSidebar.emit();

spectator.detectComponentChanges();

// Due to a delay in the pipe of the subscription
await new Promise((resolve) => setTimeout(resolve, 400));

expect(spectator.query(DotEditContentCategoryFieldSidebarComponent)).toBeNull();

spectator.component.values = [{ id: 1, value: 'Streetwear' }];
spectator.detectComponentChanges();
expect(spectator.query(byTestId('category-chip-list'))).not.toBeNull();
spectator.detectComponentChanges();
expect(selectBtn.disabled).toBe(false);
});
});
});
Loading

0 comments on commit 3f30e53

Please sign in to comment.