mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-6150] Add category selector dialog (#9423)
* [ACS-6150] add category selector dialog * [ACS-6150] fix import * [ACS-6150] cr fix * [ACS-6150] cr fix * [ACS-6150] change describe name * [ACS-6150] linting * [ACS-6150] style fix * [ACS-6150] align styles
This commit is contained in:
committed by
GitHub
parent
00404a3807
commit
c642d0e5c2
@@ -19,6 +19,7 @@ Component allows to both assign/unassign categories to content and create multip
|
|||||||
[parentId]="parentId"
|
[parentId]="parentId"
|
||||||
[managementMode]="categoriesManagementMode"
|
[managementMode]="categoriesManagementMode"
|
||||||
[classifiableChanged]="classifiableChanged"
|
[classifiableChanged]="classifiableChanged"
|
||||||
|
[multiSelect]="multiSelect"
|
||||||
(categoriesChange)="storeCategoriesToAssign($event)">
|
(categoriesChange)="storeCategoriesToAssign($event)">
|
||||||
</adf-categories-management>
|
</adf-categories-management>
|
||||||
```
|
```
|
||||||
@@ -35,6 +36,7 @@ Component allows to both assign/unassign categories to content and create multip
|
|||||||
| disableRemoval | `boolean` | false | Determines if categories assigned/created can be unassigned/removed from the list. |
|
| disableRemoval | `boolean` | false | Determines if categories assigned/created can be unassigned/removed from the list. |
|
||||||
| managementMode | `CategoriesManagementMode` | | Management mode determines if component works in assign/unassign mode or create mode. |
|
| managementMode | `CategoriesManagementMode` | | Management mode determines if component works in assign/unassign mode or create mode. |
|
||||||
| parentId | `string` | | (optional) ID of a parent category that new categories will be created under. |
|
| parentId | `string` | | (optional) ID of a parent category that new categories will be created under. |
|
||||||
|
| multiSelect | `boolean` | true | (optional) Toggles multiselect mode. |
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
|
58
docs/content-services/dialogs/category-selector.dialog.md
Normal file
58
docs/content-services/dialogs/category-selector.dialog.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
Title: Category selector dialog component
|
||||||
|
Added: v6.8.0
|
||||||
|
Status: Active
|
||||||
|
Last reviewed: 2024-03-12
|
||||||
|
---
|
||||||
|
|
||||||
|
# [Category selector dialog component](../../../lib/content-services/src/lib/dialogs/category-selector.dialog.ts "Defined in category-selector.dialog.ts")
|
||||||
|
|
||||||
|
Allows the user to select one or multiple categories.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Dialog inputs
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- |-----------| ------------- | ----------- |
|
||||||
|
| select | [`Subject<Category[]>`](https://github.com/Alfresco/alfresco-ng2-components/blob/develop/lib/js-api/src/api/content-rest-api/docs/CategoriesApi.md) | | Emits an array of selected categories when the dialog closes |
|
||||||
|
| multiSelect | `boolean` | `true` | (optional) Toggles multiselect mode |
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
```ts
|
||||||
|
constructor(private dialog: MatDialog) {}
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
function openCatDialog() {
|
||||||
|
const data: CategorySelectorDialogOptions = {
|
||||||
|
select: new Subject<Category[]>(),
|
||||||
|
multiSelect: false
|
||||||
|
};
|
||||||
|
|
||||||
|
this.dialog.open(CategorySelectorDialogComponent, {
|
||||||
|
data,
|
||||||
|
width: '400px'
|
||||||
|
});
|
||||||
|
|
||||||
|
data.select.subscribe(
|
||||||
|
(selections: Category[]) => {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
All the results will be streamed to the select [subject](http://reactivex.io/rxjs/manual/overview.html#subject) present in the `CategorySelectorDialogOptions` object passed to the dialog.
|
||||||
|
When the category is selected by clicking the `Select` button, the `options.select` stream will be completed.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
This component lets the user select categories. Use the
|
||||||
|
Angular [`MatDialog`](https://material.angular.io/components/dialog/overview)
|
||||||
|
service to open the dialog, as shown in the example, and pass a `options` object
|
||||||
|
with properties.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [Categories management component](../components/categories-management.component.md)
|
BIN
docs/docassets/images/adf-category-selector-dialog.png
Normal file
BIN
docs/docassets/images/adf-category-selector-dialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
@@ -12,6 +12,7 @@ backend services have been tested with each released version of ADF.
|
|||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
|
- [v6.8.0](#v680)
|
||||||
- [v6.7.0](#v670)
|
- [v6.7.0](#v670)
|
||||||
- [v6.4.0](#v640)
|
- [v6.4.0](#v640)
|
||||||
- [v6.2.0](#v620)
|
- [v6.2.0](#v620)
|
||||||
@@ -45,6 +46,14 @@ backend services have been tested with each released version of ADF.
|
|||||||
- [v2.1.0](#v210)
|
- [v2.1.0](#v210)
|
||||||
- [v2.0.0](#v200)
|
- [v2.0.0](#v200)
|
||||||
|
|
||||||
|
## v6.8.0
|
||||||
|
|
||||||
|
<!--680 start-->
|
||||||
|
|
||||||
|
- [Category selector dialog component](content-services/dialogs/category-selector.dialog.md)
|
||||||
|
|
||||||
|
<!--680 end-->
|
||||||
|
|
||||||
## v6.7.0
|
## v6.7.0
|
||||||
|
|
||||||
<!--670 start-->
|
<!--670 start-->
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
{{ existingCategoriesMsg | translate }}
|
{{ existingCategoriesMsg | translate }}
|
||||||
</p>
|
</p>
|
||||||
<mat-list
|
<mat-list
|
||||||
[disabled]="isCRUDMode"
|
[disabled]="isCRUDMode || !multiSelect && categories.length > 0"
|
||||||
class="adf-categories-management-list">
|
class="adf-categories-management-list">
|
||||||
<mat-list-item
|
<mat-list-item
|
||||||
*ngFor="let category of existingCategories"
|
*ngFor="let category of existingCategories"
|
||||||
|
@@ -43,6 +43,8 @@
|
|||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@@ -383,6 +383,14 @@ describe('CategoriesManagementComponent', () => {
|
|||||||
discardPeriodicTasks();
|
discardPeriodicTasks();
|
||||||
flush();
|
flush();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it ('should disable existing categories list if category already selected and multiSelect is false', fakeAsync(() => {
|
||||||
|
component.multiSelect = false;
|
||||||
|
fixture.detectChanges();
|
||||||
|
typeCategory('test');
|
||||||
|
|
||||||
|
expect(getSelectionList().disabled).toBeTrue();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('CRUD mode', () => {
|
describe('CRUD mode', () => {
|
||||||
|
@@ -116,6 +116,10 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
|
|||||||
@Input()
|
@Input()
|
||||||
parentId: string;
|
parentId: string;
|
||||||
|
|
||||||
|
/** Toggles multiselect mode */
|
||||||
|
@Input()
|
||||||
|
multiSelect = true;
|
||||||
|
|
||||||
/** Emits when state of upper categories list changes */
|
/** Emits when state of upper categories list changes */
|
||||||
@Output()
|
@Output()
|
||||||
categoriesChange = new EventEmitter<Category[]>();
|
categoriesChange = new EventEmitter<Category[]>();
|
||||||
@@ -159,13 +163,15 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
|
|||||||
if (!this.isCRUDMode) {
|
if (!this.isCRUDMode) {
|
||||||
this._categoryNameControl.removeValidators(Validators.required);
|
this._categoryNameControl.removeValidators(Validators.required);
|
||||||
this.categories.forEach((category) => this.initialCategories.push(category));
|
this.categories.forEach((category) => this.initialCategories.push(category));
|
||||||
this.classifiableChanged
|
if (this.classifiableChanged) {
|
||||||
.pipe(takeUntil(this.onDestroy$))
|
this.classifiableChanged
|
||||||
.subscribe(() => {
|
.pipe(takeUntil(this.onDestroy$))
|
||||||
this.categories = [];
|
.subscribe(() => {
|
||||||
this.categoryNameControlVisible = false;
|
this.categories = [];
|
||||||
this.categoryNameControlVisibleChange.emit(false);
|
this.categoryNameControlVisible = false;
|
||||||
});
|
this.categoryNameControlVisibleChange.emit(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
<h1 mat-dialog-title>
|
||||||
|
{{ 'CATEGORIES_MANAGEMENT.SELECT_EXISTING_CATEGORY' | translate }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<mat-dialog-content class="adf-dialog-content">
|
||||||
|
<adf-categories-management
|
||||||
|
(categoriesChange)="categories = $event"
|
||||||
|
[categoryNameControlVisible]="true"
|
||||||
|
[managementMode]="categoriesManagementMode"
|
||||||
|
[multiSelect]="multiSelect">
|
||||||
|
</adf-categories-management>
|
||||||
|
</mat-dialog-content>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button
|
||||||
|
data-automation-id="category-selector-dialog-cancel-button"
|
||||||
|
mat-button
|
||||||
|
mat-dialog-close>
|
||||||
|
{{ 'NODE_SELECTOR.CANCEL' | translate }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
(click)="selectCategories()"
|
||||||
|
[disabled]="!categories.length"
|
||||||
|
color="primary"
|
||||||
|
data-automation-id="category-selector-dialog-select-button"
|
||||||
|
mat-button>
|
||||||
|
{{ 'NODE_SELECTOR.CHOOSE' | translate }}
|
||||||
|
</button>
|
||||||
|
</mat-dialog-actions>
|
@@ -0,0 +1,5 @@
|
|||||||
|
adf-category-selector-dialog {
|
||||||
|
.adf-dialog-content {
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,98 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { CategorySelectorDialogComponent, CategorySelectorDialogOptions } from './category-selector.dialog';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { Category } from '@alfresco/js-api';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { CoreTestingModule } from '@alfresco/adf-core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
describe('Category selector dialog component', () => {
|
||||||
|
let fixture: ComponentFixture<CategorySelectorDialogComponent>;
|
||||||
|
let component: CategorySelectorDialogComponent;
|
||||||
|
let selectButton: HTMLButtonElement;
|
||||||
|
|
||||||
|
const dialogRef = {
|
||||||
|
close: jasmine.createSpy('close')
|
||||||
|
};
|
||||||
|
|
||||||
|
const options: CategorySelectorDialogOptions = {
|
||||||
|
select: new Subject<Category[]>()
|
||||||
|
};
|
||||||
|
|
||||||
|
const categories: Category[] = [{id: 'id1', name: 'cat1'}, {id: 'id2', name: 'cat3'}];
|
||||||
|
|
||||||
|
const setCategories = () => {
|
||||||
|
component.categories = categories;
|
||||||
|
fixture.detectChanges();
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [CoreTestingModule],
|
||||||
|
providers: [
|
||||||
|
{ provide: MatDialogRef, useValue: dialogRef },
|
||||||
|
{ provide: MAT_DIALOG_DATA, useValue: options }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
dialogRef.close.calls.reset();
|
||||||
|
fixture = TestBed.createComponent(CategorySelectorDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
selectButton = fixture.debugElement.query(By.css(`[data-automation-id="category-selector-dialog-select-button"]`)).nativeElement;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set params if they are provided as dialog options', () => {
|
||||||
|
options.multiSelect = true;
|
||||||
|
component.ngOnInit();
|
||||||
|
|
||||||
|
expect(component.multiSelect).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close dialog on cancel button click', () => {
|
||||||
|
fixture.debugElement.query(By.css(`[data-automation-id="category-selector-dialog-cancel-button"]`)).nativeElement.click();
|
||||||
|
expect(dialogRef.close).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close dialog if category is selected and Select button was clicked', () => {
|
||||||
|
selectButton.click();
|
||||||
|
expect(dialogRef.close).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
setCategories();
|
||||||
|
selectButton.click();
|
||||||
|
|
||||||
|
expect(dialogRef.close).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide selected categories as observable on Select click', () => {
|
||||||
|
spyOn(options.select, 'next');
|
||||||
|
setCategories();
|
||||||
|
selectButton.click();
|
||||||
|
|
||||||
|
expect(options.select.next).toHaveBeenCalledWith(categories);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable select button if no categories were selected', () => {
|
||||||
|
expect(selectButton.disabled).toBeTruthy();
|
||||||
|
setCategories();
|
||||||
|
expect(selectButton.disabled).toBeFalse();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,54 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { Category } from '@alfresco/js-api';
|
||||||
|
import { CategoriesManagementMode } from '../category';
|
||||||
|
|
||||||
|
export interface CategorySelectorDialogOptions {
|
||||||
|
select: Subject<Category[]>;
|
||||||
|
multiSelect?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-category-selector-dialog',
|
||||||
|
templateUrl: './category-selector.dialog.html',
|
||||||
|
styleUrls: ['./category-selector.dialog.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class CategorySelectorDialogComponent implements OnInit {
|
||||||
|
categories: Category[] = [];
|
||||||
|
categoriesManagementMode = CategoriesManagementMode.ASSIGN;
|
||||||
|
multiSelect = true;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private dialog: MatDialogRef<CategorySelectorDialogComponent, boolean>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) private options: CategorySelectorDialogOptions
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.multiSelect = this.options.multiSelect ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectCategories() {
|
||||||
|
this.options.select.next(this.categories);
|
||||||
|
this.dialog.close(true);
|
||||||
|
}
|
||||||
|
}
|
@@ -28,6 +28,8 @@ import { MatDatetimepickerModule } from '@mat-datetimepicker/core';
|
|||||||
import { LibraryDialogComponent } from './library/library.dialog';
|
import { LibraryDialogComponent } from './library/library.dialog';
|
||||||
import { ContentDirectiveModule } from '../directives';
|
import { ContentDirectiveModule } from '../directives';
|
||||||
import { DownloadZipDialogModule } from './download-zip/download-zip.dialog.module';
|
import { DownloadZipDialogModule } from './download-zip/download-zip.dialog.module';
|
||||||
|
import { CategorySelectorDialogComponent } from './category-selector.dialog';
|
||||||
|
import { CategoriesModule } from '../category';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -38,19 +40,22 @@ import { DownloadZipDialogModule } from './download-zip/download-zip.dialog.modu
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatDatetimepickerModule,
|
MatDatetimepickerModule,
|
||||||
ContentDirectiveModule,
|
ContentDirectiveModule,
|
||||||
DownloadZipDialogModule
|
DownloadZipDialogModule,
|
||||||
|
CategoriesModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
FolderDialogComponent,
|
FolderDialogComponent,
|
||||||
NodeLockDialogComponent,
|
NodeLockDialogComponent,
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
LibraryDialogComponent
|
LibraryDialogComponent,
|
||||||
|
CategorySelectorDialogComponent
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
FolderDialogComponent,
|
FolderDialogComponent,
|
||||||
NodeLockDialogComponent,
|
NodeLockDialogComponent,
|
||||||
ConfirmDialogComponent,
|
ConfirmDialogComponent,
|
||||||
LibraryDialogComponent
|
LibraryDialogComponent,
|
||||||
|
CategorySelectorDialogComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class DialogModule {}
|
export class DialogModule {}
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
export * from './folder.dialog';
|
export * from './folder.dialog';
|
||||||
export * from './node-lock.dialog';
|
export * from './node-lock.dialog';
|
||||||
export * from './confirm.dialog';
|
export * from './confirm.dialog';
|
||||||
|
export * from './category-selector.dialog';
|
||||||
|
|
||||||
export * from './dialog.module';
|
export * from './dialog.module';
|
||||||
export * from './library/library.dialog';
|
export * from './library/library.dialog';
|
||||||
|
@@ -93,6 +93,8 @@ adf-tags-creator {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: auto;
|
height: auto;
|
||||||
width: unset;
|
width: unset;
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
Reference in New Issue
Block a user