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

@@ -16,14 +16,19 @@
*/
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 { DocumentListComponent } from '../document-list/components/document-list.component';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'adf-breadcrumb',
standalone: true,
imports: [CommonModule, MatIconModule, TranslateModule, MatSelectModule],
templateUrl: './breadcrumb.component.html',
styleUrls: ['./breadcrumb.component.scss'],
encapsulation: ViewEncapsulation.None,

View File

@@ -15,27 +15,15 @@
* limitations under the License.
*/
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { BreadcrumbComponent } from './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({
imports: [
CommonModule,
MaterialModule,
CoreModule
],
exports: [
BreadcrumbComponent,
DropdownBreadcrumbComponent
],
declarations: [
BreadcrumbComponent,
DropdownBreadcrumbComponent
]
imports: [...BREADCRUMB_DIRECTIVES],
exports: [...BREADCRUMB_DIRECTIVES]
})
export class BreadcrumbModule {}

View File

@@ -16,12 +16,17 @@
*/
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 { BreadcrumbComponent } from './breadcrumb.component';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'adf-dropdown-breadcrumb',
standalone: true,
imports: [CommonModule, MatIconModule, MatSelectModule, TranslateModule],
templateUrl: './dropdown-breadcrumb.component.html',
styleUrls: ['./dropdown-breadcrumb.component.scss'],
encapsulation: ViewEncapsulation.None,

View File

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

View File

@@ -17,11 +17,19 @@
import { Category } from '@alfresco/js-api';
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 { debounce, first, map, takeUntil, tap } from 'rxjs/operators';
import { CategoriesManagementMode } from './categories-management-mode';
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 {
duplicatedExistingCategory?: boolean;
@@ -32,6 +40,18 @@ interface CategoryNameControlErrors {
@Component({
selector: 'adf-categories-management',
standalone: true,
imports: [
CommonModule,
TranslateModule,
AutoFocusDirective,
ReactiveFormsModule,
MatFormFieldModule,
MatButtonModule,
MatIconModule,
MatListModule,
MatProgressSpinnerModule
],
templateUrl: './categories-management.component.html',
styleUrls: ['./categories-management.component.scss'],
encapsulation: ViewEncapsulation.None

View File

@@ -15,27 +15,12 @@
* limitations under the License.
*/
import { CoreModule } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
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';
/** @deprecated use `CategoriesManagementComponent` standalone component instead */
@NgModule({
imports: [
CommonModule,
CoreModule,
MaterialModule,
TranslateModule,
ContentDirectiveModule
],
declarations: [
CategoriesManagementComponent
],
exports: [
CategoriesManagementComponent
]
imports: [CategoriesManagementComponent],
exports: [CategoriesManagementComponent]
})
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 { ContentNodeSelectorComponentData } from './content-node-selector.component-data.interface';
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 { 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
export class ContentNodeDialogService {
static nonDocumentSiteContent = [
'blog',
'calendar',
'dataLists',
'discussions',
'links',
'wiki'
];
static nonDocumentSiteContent = ['blog', 'calendar', 'dataLists', 'discussions', 'links', 'wiki'];
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
constructor(private dialog: MatDialog,
private contentService: ContentService,
private documentListService: DocumentListService,
private siteService: SitesService,
private translation: TranslationService,
private thumbnailService: ThumbnailService) {
}
constructor(
private dialog: MatDialog,
private contentService: ContentService,
private documentListService: DocumentListService,
private siteService: SitesService,
private translation: TranslationService,
private thumbnailService: ThumbnailService
) {}
/**
* Opens a file browser at a chosen folder location.
@@ -65,7 +59,9 @@ export class ContentNodeDialogService {
* @returns Information about the selected file(s)
*/
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)
*/
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)
*/
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[]> {
if (this.contentService.hasAllowableOperations(contentEntry, permission)) {
const select = new Subject<Node[]>();
const data: ContentNodeSelectorComponentData = {
@@ -236,7 +235,11 @@ export class ContentNodeDialogService {
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, {
data,
panelClass,
@@ -275,5 +278,4 @@ export class ContentNodeDialogService {
private isSite(entry) {
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 { ContentNodeSelectorPanelComponent } from './content-node-selector-panel/content-node-selector-panel.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 { CoreModule } from '@alfresco/adf-core';
import { DocumentListModule } from '../document-list/document-list.module';
@@ -39,7 +39,7 @@ import { DropdownSitesComponent } from './site-dropdown/sites-dropdown.component
CommonModule,
MaterialModule,
DropdownSitesComponent,
BreadcrumbModule,
...BREADCRUMB_DIRECTIVES,
SearchModule,
DocumentListModule,
UploadModule,

View File

@@ -19,19 +19,17 @@ import { CommonModule } from '@angular/common';
import { NgModule, ModuleWithProviders, APP_INITIALIZER } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CoreModule, SearchTextModule, provideTranslations } from '@alfresco/adf-core';
import { MaterialModule } from './material.module';
import { TagModule } from './tag/tag.module';
import { DocumentListModule } from './document-list/document-list.module';
import { UploadModule } from './upload/upload.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 { ContentNodeSelectorModule } from './content-node-selector/content-node-selector.module';
import { ContentNodeShareModule } from './content-node-share/content-node-share.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 { PermissionManagerModule } from './permission-manager/permission-manager.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 { CONTENT_PIPES } from './pipes/content-pipe.module';
import { NodeCommentsModule } from './node-comments/node-comments.module';
import { TreeModule } from './tree/tree.module';
import { AlfrescoViewerModule } from './viewer/alfresco-viewer.module';
import { CategoriesModule } from './category/category.module';
import { contentAuthLoaderFactory } from './auth-loader/content-auth-loader-factory';
import { ContentAuthLoaderService } from './auth-loader/content-auth-loader.service';
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({
imports: [
@@ -57,13 +56,13 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
CommonModule,
FormsModule,
ReactiveFormsModule,
DialogModule,
...CONTENT_DIALOG_DIRECTIVES,
SearchModule,
DocumentListModule,
UploadModule,
MaterialModule,
DropdownSitesComponent,
BreadcrumbModule,
...BREADCRUMB_DIRECTIVES,
ContentNodeSelectorModule,
ContentNodeShareModule,
ContentMetadataModule,
@@ -75,10 +74,11 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
AspectListModule,
VersionCompatibilityModule,
NodeCommentsModule,
TreeModule,
TreeComponent,
SearchTextModule,
AlfrescoViewerModule,
CategoriesModule
CategoriesManagementComponent,
NewVersionUploaderDialogComponent
],
providers: [provideTranslations('adf-content-services', 'assets/adf-content-services')],
exports: [
@@ -88,11 +88,11 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
UploadModule,
SearchModule,
DropdownSitesComponent,
BreadcrumbModule,
...BREADCRUMB_DIRECTIVES,
ContentNodeSelectorModule,
ContentNodeShareModule,
ContentMetadataModule,
DialogModule,
...CONTENT_DIALOG_DIRECTIVES,
ContentDirectiveModule,
PermissionManagerModule,
VersionManagerModule,
@@ -101,10 +101,11 @@ import { DropdownSitesComponent } from './content-node-selector/site-dropdown/si
ContentTypeModule,
VersionCompatibilityModule,
NodeCommentsModule,
TreeModule,
TreeComponent,
SearchTextModule,
AlfrescoViewerModule,
CategoriesModule
CategoriesManagementComponent,
NewVersionUploaderDialogComponent
]
})
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 { TranslateModule } from '@ngx-translate/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 { MatFormFieldModule } from '@angular/material/form-field';
describe('Category selector dialog component', () => {
let fixture: ComponentFixture<CategorySelectorDialogComponent>;
@@ -52,14 +51,19 @@ describe('Category selector dialog component', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [MatFormFieldModule, TranslateModule.forRoot(), MatDialogModule, HttpClientTestingModule],
imports: [
TranslateModule.forRoot(),
MatDialogModule,
HttpClientTestingModule,
CategoriesManagementComponent,
CategorySelectorDialogComponent
],
providers: [
{ provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: MatDialogRef, useValue: dialogRef },
{ provide: MAT_DIALOG_DATA, useValue: options },
{ provide: TranslationService, useClass: TranslationMock }
],
declarations: [CategoriesManagementComponent, CategorySelectorDialogComponent]
]
});
dialogRef.close.calls.reset();
fixture = TestBed.createComponent(CategorySelectorDialogComponent);

View File

@@ -16,10 +16,13 @@
*/
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 { 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 {
select: Subject<Category[]>;
@@ -28,6 +31,8 @@ export interface CategorySelectorDialogOptions {
@Component({
selector: 'adf-category-selector-dialog',
standalone: true,
imports: [CommonModule, MatDialogModule, TranslateModule, CategoriesManagementComponent, MatButtonModule],
templateUrl: './category-selector.dialog.html',
styleUrls: ['./category-selector.dialog.scss'],
encapsulation: ViewEncapsulation.None
@@ -40,8 +45,7 @@ export class CategorySelectorDialogComponent implements OnInit {
constructor(
private dialog: MatDialogRef<CategorySelectorDialogComponent, boolean>,
@Inject(MAT_DIALOG_DATA) private options: CategorySelectorDialogOptions
) {
}
) {}
ngOnInit() {
this.multiSelect = this.options.multiSelect ?? true;

View File

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

View File

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

View File

@@ -17,11 +17,11 @@
import { TestBed, ComponentFixture } from '@angular/core/testing';
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 { BehaviorSubject, throwError } from 'rxjs';
import { ContentTestingModule } from '../testing/content.testing.module';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { By } from '@angular/platform-browser';
describe('FolderDialogComponent', () => {

View File

@@ -16,19 +16,33 @@
*/
import { Observable } from 'rxjs';
import { Component, Inject, OnInit, Optional, EventEmitter, Output, ViewEncapsulation } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { Node } from '@alfresco/js-api';
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 { 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({
selector: 'adf-folder-dialog',
standalone: true,
imports: [
CommonModule,
MatDialogModule,
TranslateModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
AutoFocusDirective,
MatButtonModule
],
templateUrl: './folder.dialog.html',
styleUrls: ['./folder.dialog.scss'],
encapsulation: ViewEncapsulation.None,

View File

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

View File

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

View File

@@ -16,14 +16,33 @@
*/
import { Component, Inject, OnInit, Optional, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { differenceInSeconds } from 'date-fns';
import { NodeBodyLock, Node, NodeEntry, NodesApi } from '@alfresco/js-api';
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({
selector: 'adf-node-lock',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatDialogModule,
ReactiveFormsModule,
MatCheckboxModule,
MatFormFieldModule,
MatDatetimepickerModule,
MatInputModule,
MatButtonModule
],
templateUrl: './node-lock.dialog.html',
encapsulation: ViewEncapsulation.None
})

View File

@@ -15,9 +15,9 @@
* limitations under the License.
*/
export * from './folder.dialog';
export * from './node-lock.dialog';
export * from './category-selector.dialog';
export * from './folder/folder.dialog';
export * from './node-lock/node-lock.dialog';
export * from './category-selector/category-selector.dialog';
export * from './dialog.module';
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.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 { MatDialog } from '@angular/material/dialog';
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';
const DIALOG_WIDTH: number = 400;

View File

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

View File

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

View File

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

View File

@@ -15,19 +15,12 @@
* limitations under the License.
*/
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
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';
/** @deprecated use `NewVersionUploaderDialogComponent` standalone component instead */
@NgModule({
imports: [CommonModule, MaterialModule, CoreModule, UploadModule, FormsModule, VersionManagerModule],
declarations: [NewVersionUploaderDialogComponent],
exports: [NewVersionUploaderDialogComponent, FormsModule]
imports: [NewVersionUploaderDialogComponent],
exports: [NewVersionUploaderDialogComponent]
})
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 { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContextMenuDirective, ContextMenuModule, DataTableModule, IconModule, UserPreferencesService } from '@alfresco/adf-core';
import { MatTreeModule } from '@angular/material/tree';
import { ContextMenuDirective, UserPreferencesService } from '@alfresco/adf-core';
import { TreeNode, TreeNodeType } from '../models/tree-node.interface';
import { singleNode, treeNodesChildrenMockExpanded, treeNodesMock, treeNodesMockExpanded, treeNodesNoChildrenMock } from '../mock/tree-node.mock';
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 { TranslateModule } from '@ngx-translate/core';
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 { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
describe('TreeComponent', () => {
let fixture: ComponentFixture<TreeComponent<TreeNode>>;
@@ -69,21 +64,7 @@ describe('TreeComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
HttpClientTestingModule,
TranslateModule.forRoot(),
MatTreeModule,
MatIconModule,
MatMenuModule,
MatTreeModule,
DataTableModule,
ContextMenuModule,
MatCheckboxModule,
MatProgressSpinnerModule,
IconModule
],
declarations: [TreeComponent],
imports: [NoopAnimationsModule, HttpClientTestingModule, TranslateModule.forRoot(), TreeComponent],
providers: [UserPreferencesService, { provide: TreeService, useClass: TreeServiceMock }]
});

View File

@@ -31,22 +31,41 @@ import {
import { BehaviorSubject, merge, Observable, Subject } from 'rxjs';
import { TreeNode, TreeNodeType } from '../models/tree-node.interface';
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 { 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 { 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({
selector: 'adf-tree',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatTreeModule,
MatProgressSpinnerModule,
MatButtonModule,
IconComponent,
ContextMenuDirective,
MatCheckboxModule,
MatMenuModule,
MatIconModule
],
templateUrl: './tree.component.html',
styleUrls: ['./tree.component.scss'],
host: { class: 'adf-tree' },
encapsulation: ViewEncapsulation.None
})
export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
/** TemplateRef to provide empty template when no nodes are loaded */
@Input()
public emptyContentTemplate: TemplateRef<any>;
@@ -98,8 +117,7 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
public loadingRoot$: Observable<boolean>;
public treeNodesSelection = new SelectionModel<T>(true, [], true, (node1: T, node2: T) => node1.id === node2.id);
constructor(public treeService: TreeService<T>,
private userPreferenceService: UserPreferencesService) {}
constructor(public treeService: TreeService<T>, private userPreferenceService: UserPreferencesService) {}
set contextMenuSource(contextMenuSource: T) {
this._contextMenuSource = contextMenuSource;
@@ -119,7 +137,8 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
}
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) => {
this.contextMenuOptionSelected.emit({
row: this._contextMenuSource,
@@ -231,16 +250,18 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
const parentNode: T = this.treeService.getParentNode(node.parentId);
this.treeService.removeNode(node);
const loadedChildren: number = this.treeService.getChildren(parentNode).length;
this.treeService.getSubNodes(parentNode.id, loadedChildren, this.userPreferenceService.paginationSize).subscribe((response: TreeResponse<T>) => {
this.treeService.appendNodes(parentNode, response.entries);
node.isLoading = false;
if (this.treeNodesSelection.isSelected(parentNode)) {
//timeout used to update nodeCheckboxes query list after new nodes are added so they can be selected
setTimeout(() => {
this.treeNodesSelection.select(...response.entries);
});
}
});
this.treeService
.getSubNodes(parentNode.id, loadedChildren, this.userPreferenceService.paginationSize)
.subscribe((response: TreeResponse<T>) => {
this.treeService.appendNodes(parentNode, response.entries);
node.isLoading = false;
if (this.treeNodesSelection.isSelected(parentNode)) {
//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);
const descendants: T[] = this.treeService.treeControl.getDescendants(node).filter(this.isRegularNode);
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);
}
@@ -276,12 +299,16 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
*/
public descendantsPartiallySelected(node: T): boolean {
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 {
let parent: T = this.treeService.getParentNode(node.parentId);
while(parent) {
while (parent) {
this.checkRootNodeSelection(parent);
parent = this.treeService.getParentNode(parent.parentId);
}

View File

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