ACS-7390: Deprecate Material Module in Content Services library (#9983)

* ACS-7391: breadcrumb component

* ACS-7392: category management as standalone

* ACS-7405: tree component as standalone

* ACS-7396: content dialogs as standalone

* ACS-7396: content dialogs as standalone

* ACS-7396: content dialogs as standalone

* ACS-7396: content dialogs as standalone

* mark material module for deprecation [ci:force]
This commit is contained in:
Denys Vuika
2024-07-24 20:49:01 -04:00
committed by GitHub
parent d91fba7259
commit af9e916056
35 changed files with 324 additions and 316 deletions

View File

@@ -5,7 +5,7 @@ Status: Active
Last reviewed: 2024-03-12 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") # Category Selector Dialog
Allows the user to select one or multiple categories. Allows the user to select one or multiple categories.
@@ -13,43 +13,41 @@ Allows the user to select one or multiple categories.
## Dialog inputs ## Dialog inputs
| Name | Type | Default value | Description | | 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 | | select | `Subject<Category[]>` | | Emits an array of selected categories when the dialog closes |
| multiSelect | `boolean` | `true` | (optional) Toggles multiselect mode | | multiSelect | `boolean` | `true` | (optional) Toggles multiselect mode |
## Basic Usage ## Basic Usage
```ts ```ts
constructor(private dialog: MatDialog) {} export class MyComponent {
constructor(private dialog: MatDialog) {
}
... openCatDialog() {
const data: CategorySelectorDialogOptions = {
select: new Subject<Category[]>(),
multiSelect: false
};
function openCatDialog() { this.dialog.open(CategorySelectorDialogComponent, {
const data: CategorySelectorDialogOptions = { data,
select: new Subject<Category[]>(), width: '400px'
multiSelect: false });
};
this.dialog.open(CategorySelectorDialogComponent, { data.select.subscribe((selections) => {
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. All the results will be streamed to the `select` 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. When the category is selected by clicking the `Select` button, the `options.select` stream will be completed.
## Details ## Details
This component lets the user select categories. Use the This component lets the user select categories. Use the Angular `MatDialog`
Angular [`MatDialog`](https://material.angular.io/components/dialog/overview)
service to open the dialog, as shown in the example, and pass a `options` object service to open the dialog, as shown in the example, and pass a `options` object
with properties. with properties.

View File

@@ -16,14 +16,19 @@
*/ */
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild, ViewEncapsulation, OnDestroy } from '@angular/core'; import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild, ViewEncapsulation, OnDestroy } from '@angular/core';
import { MatSelect } from '@angular/material/select'; import { MatSelect, MatSelectModule } from '@angular/material/select';
import { Node, PathElement } from '@alfresco/js-api'; import { Node, PathElement } from '@alfresco/js-api';
import { DocumentListComponent } from '../document-list/components/document-list.component'; import { DocumentListComponent } from '../document-list/components/document-list.component';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { TranslateModule } from '@ngx-translate/core';
@Component({ @Component({
selector: 'adf-breadcrumb', selector: 'adf-breadcrumb',
standalone: true,
imports: [CommonModule, MatIconModule, TranslateModule, MatSelectModule],
templateUrl: './breadcrumb.component.html', templateUrl: './breadcrumb.component.html',
styleUrls: ['./breadcrumb.component.scss'], styleUrls: ['./breadcrumb.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,

View File

@@ -15,27 +15,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { BreadcrumbComponent } from './breadcrumb.component'; import { BreadcrumbComponent } from './breadcrumb.component';
import { DropdownBreadcrumbComponent } from './dropdown-breadcrumb.component'; import { DropdownBreadcrumbComponent } from './dropdown-breadcrumb.component';
import { CoreModule } from '@alfresco/adf-core';
export const BREADCRUMB_DIRECTIVES = [BreadcrumbComponent, DropdownBreadcrumbComponent] as const;
/** @deprecated use `...BREADCRUMB_DIRECTIVES` instead */
@NgModule({ @NgModule({
imports: [ imports: [...BREADCRUMB_DIRECTIVES],
CommonModule, exports: [...BREADCRUMB_DIRECTIVES]
MaterialModule,
CoreModule
],
exports: [
BreadcrumbComponent,
DropdownBreadcrumbComponent
],
declarations: [
BreadcrumbComponent,
DropdownBreadcrumbComponent
]
}) })
export class BreadcrumbModule {} export class BreadcrumbModule {}

View File

@@ -16,12 +16,17 @@
*/ */
import { Component, OnChanges, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, OnChanges, ViewChild, ViewEncapsulation } from '@angular/core';
import { MatSelect } from '@angular/material/select'; import { MatSelect, MatSelectModule } from '@angular/material/select';
import { PathElement, Node } from '@alfresco/js-api'; import { PathElement, Node } from '@alfresco/js-api';
import { BreadcrumbComponent } from './breadcrumb.component'; import { BreadcrumbComponent } from './breadcrumb.component';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { TranslateModule } from '@ngx-translate/core';
@Component({ @Component({
selector: 'adf-dropdown-breadcrumb', selector: 'adf-dropdown-breadcrumb',
standalone: true,
imports: [CommonModule, MatIconModule, MatSelectModule, TranslateModule],
templateUrl: './dropdown-breadcrumb.component.html', templateUrl: './dropdown-breadcrumb.component.html',
styleUrls: ['./dropdown-breadcrumb.component.scss'], styleUrls: ['./dropdown-breadcrumb.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,

View File

@@ -47,8 +47,7 @@ describe('CategoriesManagementComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [CategoriesManagementComponent], imports: [ContentTestingModule, CategoriesManagementComponent],
imports: [ContentTestingModule],
providers: [ providers: [
{ {
provide: CategoryService, provide: CategoryService,

View File

@@ -17,11 +17,19 @@
import { Category } from '@alfresco/js-api'; import { Category } from '@alfresco/js-api';
import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { FormControl, Validators } from '@angular/forms'; import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { EMPTY, Observable, Subject, timer } from 'rxjs'; import { EMPTY, Observable, Subject, timer } from 'rxjs';
import { debounce, first, map, takeUntil, tap } from 'rxjs/operators'; import { debounce, first, map, takeUntil, tap } from 'rxjs/operators';
import { CategoriesManagementMode } from './categories-management-mode'; import { CategoriesManagementMode } from './categories-management-mode';
import { CategoryService } from '../services/category.service'; import { CategoryService } from '../services/category.service';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { AutoFocusDirective } from '../../directives';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
interface CategoryNameControlErrors { interface CategoryNameControlErrors {
duplicatedExistingCategory?: boolean; duplicatedExistingCategory?: boolean;
@@ -32,6 +40,18 @@ interface CategoryNameControlErrors {
@Component({ @Component({
selector: 'adf-categories-management', selector: 'adf-categories-management',
standalone: true,
imports: [
CommonModule,
TranslateModule,
AutoFocusDirective,
ReactiveFormsModule,
MatFormFieldModule,
MatButtonModule,
MatIconModule,
MatListModule,
MatProgressSpinnerModule
],
templateUrl: './categories-management.component.html', templateUrl: './categories-management.component.html',
styleUrls: ['./categories-management.component.scss'], styleUrls: ['./categories-management.component.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None

View File

@@ -15,27 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { CoreModule } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { ContentDirectiveModule } from '../directives/content-directive.module';
import { MaterialModule } from '../material.module';
import { CategoriesManagementComponent } from './categories-management/categories-management.component'; import { CategoriesManagementComponent } from './categories-management/categories-management.component';
/** @deprecated use `CategoriesManagementComponent` standalone component instead */
@NgModule({ @NgModule({
imports: [ imports: [CategoriesManagementComponent],
CommonModule, exports: [CategoriesManagementComponent]
CoreModule,
MaterialModule,
TranslateModule,
ContentDirectiveModule
],
declarations: [
CategoriesManagementComponent
],
exports: [
CategoriesManagementComponent
]
}) })
export class CategoriesModule {} export class CategoriesModule {}

View File

@@ -27,7 +27,7 @@ import { DocumentListService } from '../document-list/services/document-list.ser
import { ContentNodeSelectorComponent } from './content-node-selector.component'; import { ContentNodeSelectorComponent } from './content-node-selector.component';
import { ContentNodeSelectorComponentData } from './content-node-selector.component-data.interface'; import { ContentNodeSelectorComponentData } from './content-node-selector.component-data.interface';
import { NodeAction } from '../document-list/models/node-action.enum'; import { NodeAction } from '../document-list/models/node-action.enum';
import { NodeLockDialogComponent } from '../dialogs/node-lock.dialog'; import { NodeLockDialogComponent } from '../dialogs/node-lock/node-lock.dialog';
import { switchMap } from 'rxjs/operators'; import { switchMap } from 'rxjs/operators';
import { SitesService } from '../common/services/sites.service'; import { SitesService } from '../common/services/sites.service';
@@ -36,26 +36,20 @@ import { SitesService } from '../common/services/sites.service';
}) })
// eslint-disable-next-line @angular-eslint/directive-class-suffix // eslint-disable-next-line @angular-eslint/directive-class-suffix
export class ContentNodeDialogService { export class ContentNodeDialogService {
static nonDocumentSiteContent = [ static nonDocumentSiteContent = ['blog', 'calendar', 'dataLists', 'discussions', 'links', 'wiki'];
'blog',
'calendar',
'dataLists',
'discussions',
'links',
'wiki'
];
/** Emitted when an error occurs. */ /** Emitted when an error occurs. */
@Output() @Output()
error: EventEmitter<any> = new EventEmitter<any>(); error: EventEmitter<any> = new EventEmitter<any>();
constructor(private dialog: MatDialog, constructor(
private contentService: ContentService, private dialog: MatDialog,
private documentListService: DocumentListService, private contentService: ContentService,
private siteService: SitesService, private documentListService: DocumentListService,
private translation: TranslationService, private siteService: SitesService,
private thumbnailService: ThumbnailService) { private translation: TranslationService,
} private thumbnailService: ThumbnailService
) {}
/** /**
* Opens a file browser at a chosen folder location. * Opens a file browser at a chosen folder location.
@@ -65,7 +59,9 @@ export class ContentNodeDialogService {
* @returns Information about the selected file(s) * @returns Information about the selected file(s)
*/ */
openFileBrowseDialogByFolderId(folderNodeId: string): Observable<Node[]> { openFileBrowseDialogByFolderId(folderNodeId: string): Observable<Node[]> {
return this.documentListService.getFolderNode(folderNodeId).pipe(switchMap((nodeEntry: NodeEntry) => this.openUploadFileDialog(NodeAction.CHOOSE, nodeEntry.entry, true))); return this.documentListService
.getFolderNode(folderNodeId)
.pipe(switchMap((nodeEntry: NodeEntry) => this.openUploadFileDialog(NodeAction.CHOOSE, nodeEntry.entry, true)));
} }
/** /**
@@ -102,7 +98,9 @@ export class ContentNodeDialogService {
* @returns Information about the selected file(s) * @returns Information about the selected file(s)
*/ */
openFileBrowseDialogBySite(): Observable<Node[]> { openFileBrowseDialogBySite(): Observable<Node[]> {
return this.siteService.getSites().pipe(switchMap((response: SitePaging) => this.openFileBrowseDialogByFolderId(response.list.entries[0].entry.guid))); return this.siteService
.getSites()
.pipe(switchMap((response: SitePaging) => this.openFileBrowseDialogByFolderId(response.list.entries[0].entry.guid)));
} }
/** /**
@@ -131,7 +129,9 @@ export class ContentNodeDialogService {
* @returns Information about the selected folder(s) * @returns Information about the selected folder(s)
*/ */
openFolderBrowseDialogByFolderId(folderNodeId: string): Observable<Node[]> { openFolderBrowseDialogByFolderId(folderNodeId: string): Observable<Node[]> {
return this.documentListService.getFolderNode(folderNodeId).pipe(switchMap((node: NodeEntry) => this.openUploadFolderDialog(NodeAction.CHOOSE, node.entry))); return this.documentListService
.getFolderNode(folderNodeId)
.pipe(switchMap((node: NodeEntry) => this.openUploadFolderDialog(NodeAction.CHOOSE, node.entry)));
} }
/** /**
@@ -145,7 +145,6 @@ export class ContentNodeDialogService {
*/ */
openCopyMoveDialog(action: NodeAction, contentEntry: Node, permission?: string, excludeSiteContent?: string[]): Observable<Node[]> { openCopyMoveDialog(action: NodeAction, contentEntry: Node, permission?: string, excludeSiteContent?: string[]): Observable<Node[]> {
if (this.contentService.hasAllowableOperations(contentEntry, permission)) { if (this.contentService.hasAllowableOperations(contentEntry, permission)) {
const select = new Subject<Node[]>(); const select = new Subject<Node[]>();
const data: ContentNodeSelectorComponentData = { const data: ContentNodeSelectorComponentData = {
@@ -236,7 +235,11 @@ export class ContentNodeDialogService {
return select; return select;
} }
private openContentNodeDialog(data: ContentNodeSelectorComponentData, panelClass: string, width: string): MatDialogRef<ContentNodeSelectorComponent> { private openContentNodeDialog(
data: ContentNodeSelectorComponentData,
panelClass: string,
width: string
): MatDialogRef<ContentNodeSelectorComponent> {
return this.dialog.open(ContentNodeSelectorComponent, { return this.dialog.open(ContentNodeSelectorComponent, {
data, data,
panelClass, panelClass,
@@ -275,5 +278,4 @@ export class ContentNodeDialogService {
private isSite(entry) { private isSite(entry) {
return !!entry.guid || entry.nodeType === 'st:site' || entry.nodeType === 'st:sites'; return !!entry.guid || entry.nodeType === 'st:site' || entry.nodeType === 'st:sites';
} }
} }

View File

@@ -21,7 +21,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MaterialModule } from '../material.module'; import { MaterialModule } from '../material.module';
import { ContentNodeSelectorPanelComponent } from './content-node-selector-panel/content-node-selector-panel.component'; import { ContentNodeSelectorPanelComponent } from './content-node-selector-panel/content-node-selector-panel.component';
import { ContentNodeSelectorComponent } from './content-node-selector.component'; import { ContentNodeSelectorComponent } from './content-node-selector.component';
import { BreadcrumbModule } from '../breadcrumb/breadcrumb.module'; import { BREADCRUMB_DIRECTIVES } from '../breadcrumb/breadcrumb.module';
import { SearchModule } from '../search/search.module'; import { SearchModule } from '../search/search.module';
import { CoreModule } from '@alfresco/adf-core'; import { CoreModule } from '@alfresco/adf-core';
import { DocumentListModule } from '../document-list/document-list.module'; import { DocumentListModule } from '../document-list/document-list.module';
@@ -39,7 +39,7 @@ import { DropdownSitesComponent } from './site-dropdown/sites-dropdown.component
CommonModule, CommonModule,
MaterialModule, MaterialModule,
DropdownSitesComponent, DropdownSitesComponent,
BreadcrumbModule, ...BREADCRUMB_DIRECTIVES,
SearchModule, SearchModule,
DocumentListModule, DocumentListModule,
UploadModule, UploadModule,

View File

@@ -19,19 +19,17 @@ import { CommonModule } from '@angular/common';
import { NgModule, ModuleWithProviders, APP_INITIALIZER } from '@angular/core'; import { NgModule, ModuleWithProviders, APP_INITIALIZER } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CoreModule, SearchTextModule, provideTranslations } from '@alfresco/adf-core'; import { CoreModule, SearchTextModule, provideTranslations } from '@alfresco/adf-core';
import { MaterialModule } from './material.module'; import { MaterialModule } from './material.module';
import { TagModule } from './tag/tag.module'; import { TagModule } from './tag/tag.module';
import { DocumentListModule } from './document-list/document-list.module'; import { DocumentListModule } from './document-list/document-list.module';
import { UploadModule } from './upload/upload.module'; import { UploadModule } from './upload/upload.module';
import { SearchModule } from './search/search.module'; import { SearchModule } from './search/search.module';
import { BreadcrumbModule } from './breadcrumb/breadcrumb.module'; import { BREADCRUMB_DIRECTIVES } from './breadcrumb/breadcrumb.module';
import { VersionManagerModule } from './version-manager/version-manager.module'; import { VersionManagerModule } from './version-manager/version-manager.module';
import { ContentNodeSelectorModule } from './content-node-selector/content-node-selector.module'; import { ContentNodeSelectorModule } from './content-node-selector/content-node-selector.module';
import { ContentNodeShareModule } from './content-node-share/content-node-share.module'; import { ContentNodeShareModule } from './content-node-share/content-node-share.module';
import { ContentDirectiveModule } from './directives/content-directive.module'; import { ContentDirectiveModule } from './directives/content-directive.module';
import { DialogModule } from './dialogs/dialog.module'; import { CONTENT_DIALOG_DIRECTIVES } from './dialogs/dialog.module';
import { ContentMetadataModule } from './content-metadata/content-metadata.module'; import { ContentMetadataModule } from './content-metadata/content-metadata.module';
import { PermissionManagerModule } from './permission-manager/permission-manager.module'; import { PermissionManagerModule } from './permission-manager/permission-manager.module';
import { TreeViewModule } from './tree-view/tree-view.module'; import { TreeViewModule } from './tree-view/tree-view.module';
@@ -42,12 +40,13 @@ import { versionCompatibilityFactory } from './version-compatibility/version-com
import { VersionCompatibilityService } from './version-compatibility/version-compatibility.service'; import { VersionCompatibilityService } from './version-compatibility/version-compatibility.service';
import { CONTENT_PIPES } from './pipes/content-pipe.module'; import { CONTENT_PIPES } from './pipes/content-pipe.module';
import { NodeCommentsModule } from './node-comments/node-comments.module'; import { NodeCommentsModule } from './node-comments/node-comments.module';
import { TreeModule } from './tree/tree.module';
import { AlfrescoViewerModule } from './viewer/alfresco-viewer.module'; import { AlfrescoViewerModule } from './viewer/alfresco-viewer.module';
import { CategoriesModule } from './category/category.module';
import { contentAuthLoaderFactory } from './auth-loader/content-auth-loader-factory'; import { contentAuthLoaderFactory } from './auth-loader/content-auth-loader-factory';
import { ContentAuthLoaderService } from './auth-loader/content-auth-loader.service'; import { ContentAuthLoaderService } from './auth-loader/content-auth-loader.service';
import { DropdownSitesComponent } from './content-node-selector/site-dropdown/sites-dropdown.component'; import { DropdownSitesComponent } from './content-node-selector/site-dropdown/sites-dropdown.component';
import { CategoriesManagementComponent } from './category';
import { TreeComponent } from './tree';
import { NewVersionUploaderDialogComponent } from './new-version-uploader';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -57,13 +56,13 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
CommonModule, CommonModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
DialogModule, ...CONTENT_DIALOG_DIRECTIVES,
SearchModule, SearchModule,
DocumentListModule, DocumentListModule,
UploadModule, UploadModule,
MaterialModule, MaterialModule,
DropdownSitesComponent, DropdownSitesComponent,
BreadcrumbModule, ...BREADCRUMB_DIRECTIVES,
ContentNodeSelectorModule, ContentNodeSelectorModule,
ContentNodeShareModule, ContentNodeShareModule,
ContentMetadataModule, ContentMetadataModule,
@@ -75,10 +74,11 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
AspectListModule, AspectListModule,
VersionCompatibilityModule, VersionCompatibilityModule,
NodeCommentsModule, NodeCommentsModule,
TreeModule, TreeComponent,
SearchTextModule, SearchTextModule,
AlfrescoViewerModule, AlfrescoViewerModule,
CategoriesModule CategoriesManagementComponent,
NewVersionUploaderDialogComponent
], ],
providers: [provideTranslations('adf-content-services', 'assets/adf-content-services')], providers: [provideTranslations('adf-content-services', 'assets/adf-content-services')],
exports: [ exports: [
@@ -88,11 +88,11 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
UploadModule, UploadModule,
SearchModule, SearchModule,
DropdownSitesComponent, DropdownSitesComponent,
BreadcrumbModule, ...BREADCRUMB_DIRECTIVES,
ContentNodeSelectorModule, ContentNodeSelectorModule,
ContentNodeShareModule, ContentNodeShareModule,
ContentMetadataModule, ContentMetadataModule,
DialogModule, ...CONTENT_DIALOG_DIRECTIVES,
ContentDirectiveModule, ContentDirectiveModule,
PermissionManagerModule, PermissionManagerModule,
VersionManagerModule, VersionManagerModule,
@@ -101,10 +101,11 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
ContentTypeModule, ContentTypeModule,
VersionCompatibilityModule, VersionCompatibilityModule,
NodeCommentsModule, NodeCommentsModule,
TreeModule, TreeComponent,
SearchTextModule, SearchTextModule,
AlfrescoViewerModule, AlfrescoViewerModule,
CategoriesModule CategoriesManagementComponent,
NewVersionUploaderDialogComponent
] ]
}) })
export class ContentModule { export class ContentModule {

View File

@@ -23,9 +23,8 @@ import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/materia
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { AppConfigService, AppConfigServiceMock, TranslationMock, TranslationService } from '@alfresco/adf-core'; import { AppConfigService, AppConfigServiceMock, TranslationMock, TranslationService } from '@alfresco/adf-core';
import { CategoriesManagementComponent } from '../category'; import { CategoriesManagementComponent } from '../../category';
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MatFormFieldModule } from '@angular/material/form-field';
describe('Category selector dialog component', () => { describe('Category selector dialog component', () => {
let fixture: ComponentFixture<CategorySelectorDialogComponent>; let fixture: ComponentFixture<CategorySelectorDialogComponent>;
@@ -52,14 +51,19 @@ describe('Category selector dialog component', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [MatFormFieldModule, TranslateModule.forRoot(), MatDialogModule, HttpClientTestingModule], imports: [
TranslateModule.forRoot(),
MatDialogModule,
HttpClientTestingModule,
CategoriesManagementComponent,
CategorySelectorDialogComponent
],
providers: [ providers: [
{ provide: AppConfigService, useClass: AppConfigServiceMock }, { provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: MatDialogRef, useValue: dialogRef }, { provide: MatDialogRef, useValue: dialogRef },
{ provide: MAT_DIALOG_DATA, useValue: options }, { provide: MAT_DIALOG_DATA, useValue: options },
{ provide: TranslationService, useClass: TranslationMock } { provide: TranslationService, useClass: TranslationMock }
], ]
declarations: [CategoriesManagementComponent, CategorySelectorDialogComponent]
}); });
dialogRef.close.calls.reset(); dialogRef.close.calls.reset();
fixture = TestBed.createComponent(CategorySelectorDialogComponent); fixture = TestBed.createComponent(CategorySelectorDialogComponent);

View File

@@ -16,10 +16,13 @@
*/ */
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { Category } from '@alfresco/js-api'; import { Category } from '@alfresco/js-api';
import { CategoriesManagementMode } from '../category'; import { CategoriesManagementComponent, CategoriesManagementMode } from '../../category';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
export interface CategorySelectorDialogOptions { export interface CategorySelectorDialogOptions {
select: Subject<Category[]>; select: Subject<Category[]>;
@@ -28,6 +31,8 @@ export interface CategorySelectorDialogOptions {
@Component({ @Component({
selector: 'adf-category-selector-dialog', selector: 'adf-category-selector-dialog',
standalone: true,
imports: [CommonModule, MatDialogModule, TranslateModule, CategoriesManagementComponent, MatButtonModule],
templateUrl: './category-selector.dialog.html', templateUrl: './category-selector.dialog.html',
styleUrls: ['./category-selector.dialog.scss'], styleUrls: ['./category-selector.dialog.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -40,8 +45,7 @@ export class CategorySelectorDialogComponent implements OnInit {
constructor( constructor(
private dialog: MatDialogRef<CategorySelectorDialogComponent, boolean>, private dialog: MatDialogRef<CategorySelectorDialogComponent, boolean>,
@Inject(MAT_DIALOG_DATA) private options: CategorySelectorDialogOptions @Inject(MAT_DIALOG_DATA) private options: CategorySelectorDialogOptions
) { ) {}
}
ngOnInit() { ngOnInit() {
this.multiSelect = this.options.multiSelect ?? true; this.multiSelect = this.options.multiSelect ?? true;

View File

@@ -15,44 +15,24 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FolderDialogComponent } from './folder/folder.dialog';
import { CoreModule } from '@alfresco/adf-core'; import { NodeLockDialogComponent } from './node-lock/node-lock.dialog';
import { MaterialModule } from '../material.module';
import { FolderDialogComponent } from './folder.dialog';
import { NodeLockDialogComponent } from './node-lock.dialog';
import { MatDatetimepickerModule } from '@mat-datetimepicker/core';
import { LibraryDialogComponent } from './library/library.dialog'; import { LibraryDialogComponent } from './library/library.dialog';
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 { CategorySelectorDialogComponent } from './category-selector/category-selector.dialog';
import { CategoriesModule } from '../category';
export const CONTENT_DIALOG_DIRECTIVES = [
DownloadZipDialogModule,
FolderDialogComponent,
NodeLockDialogComponent,
LibraryDialogComponent,
CategorySelectorDialogComponent
];
/** @deprecated use `..CONTENT_DIALOG_DIRECTIVES` or standalone component imports instead */
@NgModule({ @NgModule({
imports: [ imports: [...CONTENT_DIALOG_DIRECTIVES],
CommonModule, exports: [...CONTENT_DIALOG_DIRECTIVES]
MaterialModule,
CoreModule,
FormsModule,
ReactiveFormsModule,
MatDatetimepickerModule,
ContentDirectiveModule,
DownloadZipDialogModule,
CategoriesModule
],
declarations: [
FolderDialogComponent,
NodeLockDialogComponent,
LibraryDialogComponent,
CategorySelectorDialogComponent
],
exports: [
FolderDialogComponent,
NodeLockDialogComponent,
LibraryDialogComponent,
CategorySelectorDialogComponent
]
}) })
export class DialogModule {} export class DialogModule {}

View File

@@ -24,23 +24,29 @@ export const forbidSpecialCharacters = ({ value }: UntypedFormControl) => {
const specialCharacters: RegExp = /([\*\"\<\>\\\/\?\:\|])/; const specialCharacters: RegExp = /([\*\"\<\>\\\/\?\:\|])/;
const isValid: boolean = !specialCharacters.test(value); const isValid: boolean = !specialCharacters.test(value);
return (isValid) ? null : { return isValid
message: `${I18N_ERRORS_PATH}.SPECIAL_CHARACTERS` ? null
}; : {
message: `${I18N_ERRORS_PATH}.SPECIAL_CHARACTERS`
};
}; };
export const forbidEndingDot = ({ value }: UntypedFormControl) => { export const forbidEndingDot = ({ value }: UntypedFormControl) => {
const isValid: boolean = ((value || '').trim().split('').pop() !== '.'); const isValid: boolean = (value || '').trim().split('').pop() !== '.';
return isValid ? null : { return isValid
message: `${I18N_ERRORS_PATH}.ENDING_DOT` ? null
}; : {
message: `${I18N_ERRORS_PATH}.ENDING_DOT`
};
}; };
export const forbidOnlySpaces = ({ value }: UntypedFormControl) => { export const forbidOnlySpaces = ({ value }: UntypedFormControl) => {
const isValid: boolean = !!((value || '')).trim(); const isValid: boolean = !!(value || '').trim();
return isValid ? null : { return isValid
message: `${I18N_ERRORS_PATH}.ONLY_SPACES` ? null
}; : {
message: `${I18N_ERRORS_PATH}.ONLY_SPACES`
};
}; };

View File

@@ -17,11 +17,11 @@
import { TestBed, ComponentFixture } from '@angular/core/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { NodesApiService } from '../common/services/nodes-api.service'; import { NodesApiService } from '../../common/services/nodes-api.service';
import { FolderDialogComponent } from './folder.dialog'; import { FolderDialogComponent } from './folder.dialog';
import { BehaviorSubject, throwError } from 'rxjs'; import { BehaviorSubject, throwError } from 'rxjs';
import { ContentTestingModule } from '../testing/content.testing.module'; import { ContentTestingModule } from '../../testing/content.testing.module';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
describe('FolderDialogComponent', () => { describe('FolderDialogComponent', () => {

View File

@@ -16,19 +16,33 @@
*/ */
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Component, Inject, OnInit, Optional, EventEmitter, Output, ViewEncapsulation } from '@angular/core'; import { Component, Inject, OnInit, Optional, EventEmitter, Output, ViewEncapsulation } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
import { TranslationService } from '@alfresco/adf-core'; import { TranslationService } from '@alfresco/adf-core';
import { NodesApiService } from '../common/services/nodes-api.service'; import { NodesApiService } from '../../common/services/nodes-api.service';
import { forbidEndingDot, forbidOnlySpaces, forbidSpecialCharacters } from './folder-name.validators'; import { forbidEndingDot, forbidOnlySpaces, forbidSpecialCharacters } from './folder-name.validators';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { AutoFocusDirective } from '../../directives';
import { MatButtonModule } from '@angular/material/button';
@Component({ @Component({
selector: 'adf-folder-dialog', selector: 'adf-folder-dialog',
standalone: true,
imports: [
CommonModule,
MatDialogModule,
TranslateModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
AutoFocusDirective,
MatButtonModule
],
templateUrl: './folder.dialog.html', templateUrl: './folder.dialog.html',
styleUrls: ['./folder.dialog.scss'], styleUrls: ['./folder.dialog.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,

View File

@@ -39,7 +39,7 @@ describe('LibraryDialogComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ContentTestingModule], imports: [ContentTestingModule, LibraryDialogComponent],
providers: [{ provide: MatDialogRef, useValue: dialogRef }], providers: [{ provide: MatDialogRef, useValue: dialogRef }],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}); });

View File

@@ -16,29 +16,44 @@
*/ */
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { import { Component, OnInit, Output, EventEmitter, OnDestroy, ViewEncapsulation } from '@angular/core';
Component,
OnInit,
Output,
EventEmitter,
OnDestroy,
ViewEncapsulation
} from '@angular/core';
import { import {
UntypedFormBuilder, UntypedFormBuilder,
UntypedFormGroup, UntypedFormGroup,
Validators, Validators,
UntypedFormControl, UntypedFormControl,
AbstractControl AbstractControl,
ReactiveFormsModule,
FormsModule
} from '@angular/forms'; } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { QueriesApi, SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api'; import { QueriesApi, SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
import { AlfrescoApiService, NotificationService } from '@alfresco/adf-core'; import { AlfrescoApiService, NotificationService } from '@alfresco/adf-core';
import { debounceTime, finalize, mergeMap, takeUntil } from 'rxjs/operators'; import { debounceTime, finalize, mergeMap, takeUntil } from 'rxjs/operators';
import { SitesService } from '../../common/services/sites.service'; import { SitesService } from '../../common/services/sites.service';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { AutoFocusDirective } from '../../directives';
import { MatRadioModule } from '@angular/material/radio';
import { MatButtonModule } from '@angular/material/button';
@Component({ @Component({
selector: 'adf-library-dialog', selector: 'adf-library-dialog',
standalone: true,
imports: [
CommonModule,
MatDialogModule,
TranslateModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
AutoFocusDirective,
MatRadioModule,
FormsModule,
MatButtonModule
],
styleUrls: ['./library.dialog.scss'], styleUrls: ['./library.dialog.scss'],
templateUrl: './library.dialog.html', templateUrl: './library.dialog.html',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -86,22 +101,12 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
private formBuilder: UntypedFormBuilder, private formBuilder: UntypedFormBuilder,
private dialog: MatDialogRef<LibraryDialogComponent>, private dialog: MatDialogRef<LibraryDialogComponent>,
private notificationService: NotificationService private notificationService: NotificationService
) { ) {}
}
ngOnInit() { ngOnInit() {
const validators = { const validators = {
id: [ id: [Validators.required, Validators.maxLength(72), this.forbidSpecialCharacters],
Validators.required, title: [Validators.required, this.forbidOnlySpaces, Validators.minLength(2), Validators.maxLength(256)],
Validators.maxLength(72),
this.forbidSpecialCharacters
],
title: [
Validators.required,
this.forbidOnlySpaces,
Validators.minLength(2),
Validators.maxLength(256)
],
description: [Validators.maxLength(512)] description: [Validators.maxLength(512)]
}; };
@@ -165,13 +170,15 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
} }
this.disableCreateButton = true; this.disableCreateButton = true;
this.create().pipe(finalize(() => this.disableCreateButton = false)).subscribe( this.create()
(node: SiteEntry) => { .pipe(finalize(() => (this.disableCreateButton = false)))
this.success.emit(node); .subscribe(
dialog.close(node); (node: SiteEntry) => {
}, this.success.emit(node);
(error) => this.handleError(error) dialog.close(node);
); },
(error) => this.handleError(error)
);
} }
visibilityChangeHandler(event) { visibilityChangeHandler(event) {
@@ -238,9 +245,9 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> { private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
return this.queriesApi.findSites(libraryTitle, { return this.queriesApi.findSites(libraryTitle, {
maxItems: 1, maxItems: 1,
fields: ['title'] fields: ['title']
}); });
} }
private forbidSpecialCharacters({ value }: UntypedFormControl) { private forbidSpecialCharacters({ value }: UntypedFormControl) {
@@ -254,8 +261,8 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
return isValid return isValid
? null ? null
: { : {
message: 'LIBRARY.ERRORS.ILLEGAL_CHARACTERS' message: 'LIBRARY.ERRORS.ILLEGAL_CHARACTERS'
}; };
} }
private forbidOnlySpaces({ value }: UntypedFormControl) { private forbidOnlySpaces({ value }: UntypedFormControl) {
@@ -268,8 +275,8 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
return isValid return isValid
? null ? null
: { : {
message: 'LIBRARY.ERRORS.ONLY_SPACES' message: 'LIBRARY.ERRORS.ONLY_SPACES'
}; };
} }
private createSiteIdValidator() { private createSiteIdValidator() {
@@ -281,10 +288,14 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
} }
return new Promise((resolve) => { return new Promise((resolve) => {
timer = setTimeout(() => this.sitesService.getSite(control.value).subscribe( timer = setTimeout(
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }), () =>
() => resolve(null) this.sitesService.getSite(control.value).subscribe(
), 300); () => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
() => resolve(null)
),
300
);
}); });
}; };
} }

View File

@@ -18,7 +18,7 @@
import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing'; import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { NodeLockDialogComponent } from './node-lock.dialog'; import { NodeLockDialogComponent } from './node-lock.dialog';
import { ContentTestingModule } from '../testing/content.testing.module'; import { ContentTestingModule } from '../../testing/content.testing.module';
import { addMinutes } from 'date-fns'; import { addMinutes } from 'date-fns';
describe('NodeLockDialogComponent', () => { describe('NodeLockDialogComponent', () => {
@@ -32,7 +32,7 @@ describe('NodeLockDialogComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ContentTestingModule], imports: [ContentTestingModule, NodeLockDialogComponent],
providers: [{ provide: MatDialogRef, useValue: dialogRef }] providers: [{ provide: MatDialogRef, useValue: dialogRef }]
}); });
fixture = TestBed.createComponent(NodeLockDialogComponent); fixture = TestBed.createComponent(NodeLockDialogComponent);

View File

@@ -16,14 +16,33 @@
*/ */
import { Component, Inject, OnInit, Optional, ViewEncapsulation } from '@angular/core'; import { Component, Inject, OnInit, Optional, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { differenceInSeconds } from 'date-fns'; import { differenceInSeconds } from 'date-fns';
import { NodeBodyLock, Node, NodeEntry, NodesApi } from '@alfresco/js-api'; import { NodeBodyLock, Node, NodeEntry, NodesApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatetimepickerModule } from '@mat-datetimepicker/core';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
@Component({ @Component({
selector: 'adf-node-lock', selector: 'adf-node-lock',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatDialogModule,
ReactiveFormsModule,
MatCheckboxModule,
MatFormFieldModule,
MatDatetimepickerModule,
MatInputModule,
MatButtonModule
],
templateUrl: './node-lock.dialog.html', templateUrl: './node-lock.dialog.html',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })

View File

@@ -15,9 +15,9 @@
* limitations under the License. * limitations under the License.
*/ */
export * from './folder.dialog'; export * from './folder/folder.dialog';
export * from './node-lock.dialog'; export * from './node-lock/node-lock.dialog';
export * from './category-selector.dialog'; export * from './category-selector/category-selector.dialog';
export * from './dialog.module'; export * from './dialog.module';
export * from './library/library.dialog'; export * from './library/library.dialog';
@@ -25,4 +25,4 @@ export * from './library/library.dialog';
export * from './download-zip/download-zip.dialog'; export * from './download-zip/download-zip.dialog';
export * from './download-zip/download-zip.dialog.module'; export * from './download-zip/download-zip.dialog.module';
export * from './folder-name.validators'; export * from './folder/folder-name.validators';

View File

@@ -20,7 +20,7 @@
import { Directive, ElementRef, HostListener, Input, Output, EventEmitter } from '@angular/core'; import { Directive, ElementRef, HostListener, Input, Output, EventEmitter } from '@angular/core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
import { FolderDialogComponent } from '../dialogs/folder.dialog'; import { FolderDialogComponent } from '../dialogs/folder/folder.dialog';
import { ContentService } from '../common/services/content.service'; import { ContentService } from '../common/services/content.service';
const DIALOG_WIDTH: number = 400; const DIALOG_WIDTH: number = 400;

View File

@@ -38,6 +38,7 @@ import { MatSliderModule } from '@angular/material/slider';
import { MatTreeModule } from '@angular/material/tree'; import { MatTreeModule } from '@angular/material/tree';
import { MatBadgeModule } from '@angular/material/badge'; import { MatBadgeModule } from '@angular/material/badge';
/** @deprecated this module is deprecated and will be removed in future versions */
@NgModule({ @NgModule({
imports: [ imports: [
MatButtonModule, MatButtonModule,

View File

@@ -44,14 +44,8 @@ describe('NewVersionUploaderDialog', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ContentTestingModule], imports: [ContentTestingModule, NewVersionUploaderDialogComponent],
declarations: [ declarations: [VersionListComponent, VersionUploadComponent, UploadVersionButtonComponent, VersionComparisonComponent],
NewVersionUploaderDialogComponent,
VersionListComponent,
VersionUploadComponent,
UploadVersionButtonComponent,
VersionComparisonComponent
],
providers: [ providers: [
{ provide: MAT_DIALOG_DATA, useValue: { node: mockNode, showVersionsOnly, file: mockFile } }, { provide: MAT_DIALOG_DATA, useValue: { node: mockNode, showVersionsOnly, file: mockFile } },
{ {

View File

@@ -17,17 +17,23 @@
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
import { Component, EventEmitter, Inject, OnInit, Output, ViewEncapsulation } from '@angular/core'; import { Component, EventEmitter, Inject, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import { NewVersionUploaderDialogData, NewVersionUploaderData, NewVersionUploaderDataAction } from './models'; import { NewVersionUploaderDialogData, NewVersionUploaderData, NewVersionUploaderDataAction } from './models';
import { CommonModule } from '@angular/common';
import { VersionManagerModule } from '../version-manager';
import { AppConfigPipe } from '@alfresco/adf-core';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
@Component({ @Component({
selector: 'adf-new-version-uploader-dialog', selector: 'adf-new-version-uploader-dialog',
standalone: true,
imports: [CommonModule, VersionManagerModule, MatDialogModule, AppConfigPipe, TranslateModule, MatButtonModule],
templateUrl: './new-version-uploader.dialog.html', templateUrl: './new-version-uploader.dialog.html',
styleUrls: ['./new-version-uploader.dialog.scss'], styleUrls: ['./new-version-uploader.dialog.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class NewVersionUploaderDialogComponent implements OnInit { export class NewVersionUploaderDialogComponent implements OnInit {
/** /**
* Dialog title to show into the header. * Dialog title to show into the header.
* If data.title is not provided, a default title is set * If data.title is not provided, a default title is set
@@ -45,7 +51,7 @@ export class NewVersionUploaderDialogComponent implements OnInit {
constructor( constructor(
@Inject(MAT_DIALOG_DATA) public data: NewVersionUploaderDialogData, @Inject(MAT_DIALOG_DATA) public data: NewVersionUploaderDialogData,
private dialogRef: MatDialogRef<NewVersionUploaderDialogComponent> private dialogRef: MatDialogRef<NewVersionUploaderDialogComponent>
) { } ) {}
ngOnInit(): void { ngOnInit(): void {
this.setDialogTitle(); this.setDialogTitle();
@@ -79,5 +85,4 @@ export class NewVersionUploaderDialogComponent implements OnInit {
refresh(node: Node) { refresh(node: Node) {
this.dialogAction.emit({ action: NewVersionUploaderDataAction.refresh, node }); this.dialogAction.emit({ action: NewVersionUploaderDataAction.refresh, node });
} }
} }

View File

@@ -15,19 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { UploadModule } from '../upload/upload.module';
import { CoreModule } from '@alfresco/adf-core';
import { VersionManagerModule } from '../version-manager';
import { NewVersionUploaderDialogComponent } from './new-version-uploader.dialog'; import { NewVersionUploaderDialogComponent } from './new-version-uploader.dialog';
/** @deprecated use `NewVersionUploaderDialogComponent` standalone component instead */
@NgModule({ @NgModule({
imports: [CommonModule, MaterialModule, CoreModule, UploadModule, FormsModule, VersionManagerModule], imports: [NewVersionUploaderDialogComponent],
declarations: [NewVersionUploaderDialogComponent], exports: [NewVersionUploaderDialogComponent]
exports: [NewVersionUploaderDialogComponent, FormsModule]
}) })
export class NewVersionUploaderModule {} export class NewVersionUploaderModule {}

View File

@@ -1,19 +0,0 @@
<div id="adf-like-container" class="adf-like-container">
<div class="adf-like">
<span
id="adf-like-{{ nodeId }}"
[ngClass]="{ 'adf-like-select': isLike, 'adf-like-grey': !isLike }"
(click)="likeClick()"
tabindex="0"
role="button"
(keyup.enter)="likeClick()"
>
<mat-icon>thumb_up</mat-icon>
</span>
</div>
<div class="adf-like-counter-container">
<div id="adf-like-counter" class="adf-like-counter">{{ likesCounter }}</div>
<div class="adf-left" *ngIf="likesCounter === 1">Like</div>
<div class="adf-left" *ngIf="likesCounter !== 1">Likes</div>
</div>
</div>

View File

@@ -17,8 +17,7 @@
import { TreeComponent } from './tree.component'; import { TreeComponent } from './tree.component';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContextMenuDirective, ContextMenuModule, DataTableModule, IconModule, UserPreferencesService } from '@alfresco/adf-core'; import { ContextMenuDirective, UserPreferencesService } from '@alfresco/adf-core';
import { MatTreeModule } from '@angular/material/tree';
import { TreeNode, TreeNodeType } from '../models/tree-node.interface'; import { TreeNode, TreeNodeType } from '../models/tree-node.interface';
import { singleNode, treeNodesChildrenMockExpanded, treeNodesMock, treeNodesMockExpanded, treeNodesNoChildrenMock } from '../mock/tree-node.mock'; import { singleNode, treeNodesChildrenMockExpanded, treeNodesMock, treeNodesMockExpanded, treeNodesNoChildrenMock } from '../mock/tree-node.mock';
import { of, Subject } from 'rxjs'; import { of, Subject } from 'rxjs';
@@ -33,11 +32,7 @@ import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/te
import { MatCheckboxHarness } from '@angular/material/checkbox/testing'; import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
describe('TreeComponent', () => { describe('TreeComponent', () => {
let fixture: ComponentFixture<TreeComponent<TreeNode>>; let fixture: ComponentFixture<TreeComponent<TreeNode>>;
@@ -69,21 +64,7 @@ describe('TreeComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [NoopAnimationsModule, HttpClientTestingModule, TranslateModule.forRoot(), TreeComponent],
NoopAnimationsModule,
HttpClientTestingModule,
TranslateModule.forRoot(),
MatTreeModule,
MatIconModule,
MatMenuModule,
MatTreeModule,
DataTableModule,
ContextMenuModule,
MatCheckboxModule,
MatProgressSpinnerModule,
IconModule
],
declarations: [TreeComponent],
providers: [UserPreferencesService, { provide: TreeService, useClass: TreeServiceMock }] providers: [UserPreferencesService, { provide: TreeService, useClass: TreeServiceMock }]
}); });

View File

@@ -31,22 +31,41 @@ import {
import { BehaviorSubject, merge, Observable, Subject } from 'rxjs'; import { BehaviorSubject, merge, Observable, Subject } from 'rxjs';
import { TreeNode, TreeNodeType } from '../models/tree-node.interface'; import { TreeNode, TreeNodeType } from '../models/tree-node.interface';
import { TreeService } from '../services/tree.service'; import { TreeService } from '../services/tree.service';
import { PaginationModel, UserPreferencesService } from '@alfresco/adf-core'; import { ContextMenuDirective, IconComponent, PaginationModel, UserPreferencesService } from '@alfresco/adf-core';
import { SelectionChange, SelectionModel } from '@angular/cdk/collections'; import { SelectionChange, SelectionModel } from '@angular/cdk/collections';
import { TreeResponse } from '../models/tree-response.interface'; import { TreeResponse } from '../models/tree-response.interface';
import { MatCheckbox } from '@angular/material/checkbox'; import { MatCheckbox, MatCheckboxModule } from '@angular/material/checkbox';
import { TreeContextMenuResult } from '../models/tree-context-menu-result.interface'; import { TreeContextMenuResult } from '../models/tree-context-menu-result.interface';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { MatTreeModule } from '@angular/material/tree';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
@Component({ @Component({
selector: 'adf-tree', selector: 'adf-tree',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatTreeModule,
MatProgressSpinnerModule,
MatButtonModule,
IconComponent,
ContextMenuDirective,
MatCheckboxModule,
MatMenuModule,
MatIconModule
],
templateUrl: './tree.component.html', templateUrl: './tree.component.html',
styleUrls: ['./tree.component.scss'], styleUrls: ['./tree.component.scss'],
host: { class: 'adf-tree' }, host: { class: 'adf-tree' },
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy { export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
/** TemplateRef to provide empty template when no nodes are loaded */ /** TemplateRef to provide empty template when no nodes are loaded */
@Input() @Input()
public emptyContentTemplate: TemplateRef<any>; public emptyContentTemplate: TemplateRef<any>;
@@ -98,8 +117,7 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
public loadingRoot$: Observable<boolean>; public loadingRoot$: Observable<boolean>;
public treeNodesSelection = new SelectionModel<T>(true, [], true, (node1: T, node2: T) => node1.id === node2.id); public treeNodesSelection = new SelectionModel<T>(true, [], true, (node1: T, node2: T) => node1.id === node2.id);
constructor(public treeService: TreeService<T>, constructor(public treeService: TreeService<T>, private userPreferenceService: UserPreferencesService) {}
private userPreferenceService: UserPreferencesService) {}
set contextMenuSource(contextMenuSource: T) { set contextMenuSource(contextMenuSource: T) {
this._contextMenuSource = contextMenuSource; this._contextMenuSource = contextMenuSource;
@@ -119,7 +137,8 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
} }
return option; return option;
}); });
merge(...this.contextMenuOptions.map((option) => option.subject)).pipe(takeUntil(this.contextMenuOptionsChanged$)) merge(...this.contextMenuOptions.map((option) => option.subject))
.pipe(takeUntil(this.contextMenuOptionsChanged$))
.subscribe((option) => { .subscribe((option) => {
this.contextMenuOptionSelected.emit({ this.contextMenuOptionSelected.emit({
row: this._contextMenuSource, row: this._contextMenuSource,
@@ -231,16 +250,18 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
const parentNode: T = this.treeService.getParentNode(node.parentId); const parentNode: T = this.treeService.getParentNode(node.parentId);
this.treeService.removeNode(node); this.treeService.removeNode(node);
const loadedChildren: number = this.treeService.getChildren(parentNode).length; const loadedChildren: number = this.treeService.getChildren(parentNode).length;
this.treeService.getSubNodes(parentNode.id, loadedChildren, this.userPreferenceService.paginationSize).subscribe((response: TreeResponse<T>) => { this.treeService
this.treeService.appendNodes(parentNode, response.entries); .getSubNodes(parentNode.id, loadedChildren, this.userPreferenceService.paginationSize)
node.isLoading = false; .subscribe((response: TreeResponse<T>) => {
if (this.treeNodesSelection.isSelected(parentNode)) { this.treeService.appendNodes(parentNode, response.entries);
//timeout used to update nodeCheckboxes query list after new nodes are added so they can be selected node.isLoading = false;
setTimeout(() => { if (this.treeNodesSelection.isSelected(parentNode)) {
this.treeNodesSelection.select(...response.entries); //timeout used to update nodeCheckboxes query list after new nodes are added so they can be selected
}); setTimeout(() => {
} this.treeNodesSelection.select(...response.entries);
}); });
}
});
} }
/** /**
@@ -252,7 +273,9 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
this.treeNodesSelection.toggle(node); this.treeNodesSelection.toggle(node);
const descendants: T[] = this.treeService.treeControl.getDescendants(node).filter(this.isRegularNode); const descendants: T[] = this.treeService.treeControl.getDescendants(node).filter(this.isRegularNode);
if (descendants.length > 0) { if (descendants.length > 0) {
this.treeNodesSelection.isSelected(node) ? this.treeNodesSelection.select(...descendants) : this.treeNodesSelection.deselect(...descendants); this.treeNodesSelection.isSelected(node)
? this.treeNodesSelection.select(...descendants)
: this.treeNodesSelection.deselect(...descendants);
} }
this.checkParentsSelection(node); this.checkParentsSelection(node);
} }
@@ -276,12 +299,16 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
*/ */
public descendantsPartiallySelected(node: T): boolean { public descendantsPartiallySelected(node: T): boolean {
const descendants: T[] = this.treeService.treeControl.getDescendants(node).filter(this.isRegularNode); const descendants: T[] = this.treeService.treeControl.getDescendants(node).filter(this.isRegularNode);
return descendants.length > 0 && !this.descendantsAllSelected(node) && descendants.some((descendant: T) => this.treeNodesSelection.isSelected(descendant)); return (
descendants.length > 0 &&
!this.descendantsAllSelected(node) &&
descendants.some((descendant: T) => this.treeNodesSelection.isSelected(descendant))
);
} }
private checkParentsSelection(node: T): void { private checkParentsSelection(node: T): void {
let parent: T = this.treeService.getParentNode(node.parentId); let parent: T = this.treeService.getParentNode(node.parentId);
while(parent) { while (parent) {
this.checkRootNodeSelection(parent); this.checkRootNodeSelection(parent);
parent = this.treeService.getParentNode(parent.parentId); parent = this.treeService.getParentNode(parent.parentId);
} }

View File

@@ -15,27 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { ContextMenuModule, CoreModule } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { MaterialModule } from '../material.module';
import { TreeComponent } from './components/tree.component'; import { TreeComponent } from './components/tree.component';
/** @deprecated use `TreeComponent` standalone component instead */
@NgModule({ @NgModule({
imports: [ imports: [TreeComponent],
CommonModule, exports: [TreeComponent]
CoreModule,
MaterialModule,
TranslateModule,
ContextMenuModule
],
declarations: [
TreeComponent
],
exports: [
TreeComponent
]
}) })
export class TreeModule { export class TreeModule {}
}