- {{ category.name }}
+ {{ category.name }}
diff --git a/lib/content-services/src/lib/category/categories-management/categories-management.component.scss b/lib/content-services/src/lib/category/categories-management/categories-management.component.scss
index 32288cdf3a6..072bd026bf3 100644
--- a/lib/content-services/src/lib/category/categories-management/categories-management.component.scss
+++ b/lib/content-services/src/lib/category/categories-management/categories-management.component.scss
@@ -1,17 +1,27 @@
-.adf-categories-management {
- padding-top: 12px;
+@import 'styles/mat-selectors';
+.adf-categories-management {
.adf-category-name-field {
- justify-content: space-between;
- width: 100%;
- color: var(--adf-metadata-property-panel-text-color);
- background: var(--adf-metadata-buttons-background-color);
- height: 32px;
- border-radius: 12px;
- align-items: center;
+ display: flex;
+ flex-direction: column;
+ margin-right: 12px;
input {
+ background: var(--adf-metadata-buttons-background-color);
+ border-radius: 12px;
padding: 7px 8px;
+ border: none;
+ outline: none;
+ font: inherit;
+ color: currentcolor;
+ margin: 0;
+ vertical-align: bottom;
+ text-align: inherit;
+ box-sizing: content-box;
+ }
+
+ #{$mat-form-field-error} {
+ padding-top: 5px;
}
}
@@ -46,7 +56,7 @@
background-color: inherit;
color: inherit;
- &:hover {
+ &:not(#{$mat-list-item-disabled}):hover {
cursor: pointer;
background: var(--adf-theme-mat-grey-color-a200);
}
@@ -68,9 +78,15 @@
}
.adf-existing-categories-panel {
+ min-height: 22vh;
+
.adf-create-category-label {
color: var(--theme-primary-color);
cursor: pointer;
overflow-wrap: anywhere;
}
+
+ #{$mat-list-item-disabled} #{$mat-list-item-primary-text} {
+ opacity: 1;
+ }
}
diff --git a/lib/content-services/src/lib/category/categories-management/categories-management.component.ts b/lib/content-services/src/lib/category/categories-management/categories-management.component.ts
index 4b5cd191e8e..2300f308ef4 100644
--- a/lib/content-services/src/lib/category/categories-management/categories-management.component.ts
+++ b/lib/content-services/src/lib/category/categories-management/categories-management.component.ts
@@ -31,10 +31,10 @@ interface CategoryNameControlErrors {
}
@Component({
- selector: 'adf-categories-management',
- templateUrl: './categories-management.component.html',
- styleUrls: ['./categories-management.component.scss'],
- encapsulation: ViewEncapsulation.None
+ selector: 'adf-categories-management',
+ templateUrl: './categories-management.component.html',
+ styleUrls: ['./categories-management.component.scss'],
+ encapsulation: ViewEncapsulation.None
})
export class CategoriesManagementComponent implements OnInit, OnDestroy {
readonly nameErrorMessagesByErrors = new Map([
@@ -49,11 +49,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject();
private _categoryNameControl = new FormControl(
'',
- [
- this.validateIfNotAlreadyAdded.bind(this),
- this.validateEmptyCategory,
- Validators.required
- ],
+ [this.validateIfNotAlreadyAdded.bind(this), this.validateEmptyCategory, Validators.required],
this.validateIfNotAlreadyCreated.bind(this)
);
private _existingCategories: Category[];
@@ -78,23 +74,23 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
*
* @param categoryNameControlVisible control visibility.
*/
- @Input()
- set categoryNameControlVisible(categoryNameControlVisible: boolean) {
- this._categoryNameControlVisible = categoryNameControlVisible;
- if (categoryNameControlVisible) {
- setTimeout(() => {
- this.categoryNameInputElement.nativeElement.scrollIntoView();
- });
- this._existingCategoriesPanelVisible = true;
- } else {
+ @Input()
+ set categoryNameControlVisible(categoryNameControlVisible: boolean) {
+ this._categoryNameControlVisible = categoryNameControlVisible;
+ if (categoryNameControlVisible) {
+ setTimeout(() => {
+ this.categoryNameInputElement.nativeElement.scrollIntoView();
+ });
+ this._existingCategoriesPanelVisible = true;
+ } else {
this._existingCategoriesPanelVisible = false;
this.clearCategoryNameInput();
- }
- }
+ }
+ }
- get categoryNameControlVisible(): boolean {
- return this._categoryNameControlVisible;
- }
+ get categoryNameControlVisible(): boolean {
+ return this._categoryNameControlVisible;
+ }
/** Emits when classifiable aspect changes */
@Input()
@@ -150,9 +146,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
)
.subscribe((name: string) => this.onNameControlValueChange(name));
- this.categoryNameControl.statusChanges
- .pipe(takeUntil(this.onDestroy$))
- .subscribe(() => this.setCategoryNameControlErrorMessageKey());
+ this.categoryNameControl.statusChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.setCategoryNameControlErrorMessageKey());
this.setCategoryNameControlErrorMessageKey();
@@ -164,13 +158,11 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
this._categoryNameControl.removeValidators(Validators.required);
this.categories.forEach((category) => this.initialCategories.push(category));
if (this.classifiableChanged) {
- this.classifiableChanged
- .pipe(takeUntil(this.onDestroy$))
- .subscribe(() => {
- this.categories = [];
- this.categoryNameControlVisible = false;
- this.categoryNameControlVisibleChange.emit(false);
- });
+ this.classifiableChanged.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
+ this.categories = [];
+ this.categoryNameControlVisible = false;
+ this.categoryNameControlVisibleChange.emit(false);
+ });
}
}
}
@@ -188,7 +180,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
/*
* Returns `true` if categories empty and category panel non editable state, otherwise `false`
- */
+ */
get showEmptyCategoryMessage(): boolean {
return this.categories.length === 0 && !this.categoryNameControlVisible;
}
@@ -237,11 +229,13 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
* @param category - selection list change containing selected category
*/
addCategoryToAssign(category: Category) {
- const selectedCategory: Category = category;
- this.categories.push(selectedCategory);
- this._existingCategories.splice(this._existingCategories.indexOf(selectedCategory), 1);
- this.categoryNameControl.updateValueAndValidity();
- this.categoriesChange.emit(this.categories);
+ if (!(this.isCRUDMode || (!this.multiSelect && this.categories.length > 0))) {
+ const selectedCategory: Category = category;
+ this.categories.push(selectedCategory);
+ this._existingCategories.splice(this._existingCategories.indexOf(selectedCategory), 1);
+ this.categoryNameControl.updateValueAndValidity();
+ this.categoriesChange.emit(this.categories);
+ }
}
/**
@@ -275,7 +269,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
}
private searchForExistingCategories(searchTerm: string) {
- this.categoryService.searchCategories(searchTerm, 0 , this.existingCategoriesListLimit).subscribe((existingCategoriesResult) => {
+ this.categoryService.searchCategories(searchTerm, 0, this.existingCategoriesListLimit).subscribe((existingCategoriesResult) => {
this._existingCategories = existingCategoriesResult.list.entries.map((rowEntry) => {
const existingCat = new Category();
existingCat.id = rowEntry.entry.id;
@@ -283,7 +277,9 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
existingCat.name = path ? `${path}/${rowEntry.entry.name}` : rowEntry.entry.name;
return existingCat;
});
- this._existingCategories = this._existingCategories.filter((existingCat) => this.categories.find((category) => existingCat.id === category.id) === undefined);
+ this._existingCategories = this._existingCategories.filter(
+ (existingCat) => this.categories.find((category) => existingCat.id === category.id) === undefined
+ );
this.sortCategoriesList(this._existingCategories);
this._existingCategoriesLoading = false;
this._typing = false;
@@ -294,7 +290,9 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
private getChildrenCategories(searchTerm: string) {
this.categoryService.getSubcategories(this.parentId).subscribe((childrenCategories) => {
this._existingCategories = childrenCategories.list.entries.map((categoryEntry) => categoryEntry.entry);
- this._existingCategories = this._existingCategories.filter((existingCat) => existingCat.name.toLowerCase().includes(searchTerm.toLowerCase()));
+ this._existingCategories = this._existingCategories.filter((existingCat) =>
+ existingCat.name.toLowerCase().includes(searchTerm.toLowerCase())
+ );
this.sortCategoriesList(this._existingCategories);
this._existingCategoriesLoading = false;
this._typing = false;
@@ -308,11 +306,13 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
: null;
}
- private validateIfNotAlreadyCreated(nameControl: FormControl): Observable {
+ private validateIfNotAlreadyCreated(nameControl: FormControl): Observable {
return this.existingCategoryLoaded$.pipe(
- map(() => this.existingCategories.some((category) => this.compareCategories(category, nameControl.value)) && this.isCRUDMode
+ map(() =>
+ this.existingCategories.some((category) => this.compareCategories(category, nameControl.value)) && this.isCRUDMode
? { duplicatedExistingCategory: true }
- : null),
+ : null
+ ),
first()
);
}
@@ -322,9 +322,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
}
private validateEmptyCategory(categoryNameControl: FormControl): CategoryNameControlErrors | null {
- return categoryNameControl.value.length && !categoryNameControl.value.trim()
- ? { emptyCategory: true }
- : null;
+ return categoryNameControl.value.length && !categoryNameControl.value.trim() ? { emptyCategory: true } : null;
}
private setCategoryNameControlErrorMessageKey() {
diff --git a/lib/content-services/src/lib/category/services/category-tree-datasource.service.spec.ts b/lib/content-services/src/lib/category/services/category-tree-datasource.service.spec.ts
index 4ea2ece05e0..b318d337cc1 100644
--- a/lib/content-services/src/lib/category/services/category-tree-datasource.service.spec.ts
+++ b/lib/content-services/src/lib/category/services/category-tree-datasource.service.spec.ts
@@ -15,7 +15,6 @@
* limitations under the License.
*/
-import { CoreTestingModule } from '@alfresco/adf-core';
import { fakeAsync, TestBed } from '@angular/core/testing';
import { CategoryService } from '../services/category.service';
import { CategoryNode, CategoryTreeDatasourceService } from '@alfresco/adf-content-services';
@@ -25,17 +24,12 @@ import { EMPTY, of } from 'rxjs';
import { Pagination } from '@alfresco/js-api';
describe('CategoryTreeDatasourceService', () => {
- let categoryTreeDatasourceService: CategoryTreeDatasourceService;
- let categoryService: CategoryService;
+ let categoryTreeDatasourceService: CategoryTreeDatasourceService;
+ let categoryService: CategoryService;
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [
- CoreTestingModule
- ],
- providers: [
- { provide: CategoryService, useClass: CategoryServiceMock }
- ]
+ providers: [CategoryTreeDatasourceService, { provide: CategoryService, useClass: CategoryServiceMock }]
});
categoryTreeDatasourceService = TestBed.inject(CategoryTreeDatasourceService);
@@ -44,7 +38,7 @@ describe('CategoryTreeDatasourceService', () => {
it('should get root level categories', fakeAsync(() => {
spyOn(categoryTreeDatasourceService, 'getParentNode').and.returnValue(undefined);
- categoryTreeDatasourceService.getSubNodes(null, 0 , 100).subscribe((treeResponse: TreeResponse) => {
+ categoryTreeDatasourceService.getSubNodes(null, 0, 100).subscribe((treeResponse: TreeResponse) => {
expect(treeResponse.entries.length).toBe(1);
expect(treeResponse.entries[0].level).toBe(0);
expect(treeResponse.entries[0].nodeType).toBe(TreeNodeType.RegularNode);
@@ -62,7 +56,7 @@ describe('CategoryTreeDatasourceService', () => {
nodeType: TreeNodeType.RegularNode
};
spyOn(categoryTreeDatasourceService, 'getParentNode').and.returnValue(parentNode);
- categoryTreeDatasourceService.getSubNodes(parentNode.id, 0 , 100).subscribe((treeResponse: TreeResponse) => {
+ categoryTreeDatasourceService.getSubNodes(parentNode.id, 0, 100).subscribe((treeResponse: TreeResponse) => {
expect(treeResponse.entries.length).toBe(2);
expect(treeResponse.entries[0].parentId).toBe(parentNode.id);
expect(treeResponse.entries[0].level).toBe(1);
@@ -84,7 +78,8 @@ describe('CategoryTreeDatasourceService', () => {
});
it('should call getCategory for every instance if value of name parameter is defined', (done) => {
- spyOn(categoryService, 'getCategory').and.returnValues(of({
+ spyOn(categoryService, 'getCategory').and.returnValues(
+ of({
entry: {
name: 'name',
id: 'some id 1',
@@ -97,18 +92,18 @@ describe('CategoryTreeDatasourceService', () => {
id: 'some id 2',
hasChildren: false
}
- }));
- categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name')
- .subscribe(() => {
-
- expect(categoryService.getCategory).toHaveBeenCalledWith('some id 1');
- expect(categoryService.getCategory).toHaveBeenCalledWith('some id 2');
- done();
- });
+ })
+ );
+ categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name').subscribe(() => {
+ expect(categoryService.getCategory).toHaveBeenCalledWith('some id 1');
+ expect(categoryService.getCategory).toHaveBeenCalledWith('some id 2');
+ done();
+ });
});
it('should return observable which emits correct categories', (done) => {
- spyOn(categoryService, 'getCategory').and.returnValues(of({
+ spyOn(categoryService, 'getCategory').and.returnValues(
+ of({
entry: {
name: 'some name',
id: 'some id 1',
@@ -121,14 +116,15 @@ describe('CategoryTreeDatasourceService', () => {
id: 'some id 2',
hasChildren: false
}
- }));
- categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name')
- .subscribe((response) => {
- const pagination = new Pagination();
- pagination.count = 2;
- expect(response).toEqual({
- pagination,
- entries: [{
+ })
+ );
+ categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name').subscribe((response) => {
+ const pagination = new Pagination();
+ pagination.count = 2;
+ expect(response).toEqual({
+ pagination,
+ entries: [
+ {
id: 'some id 1',
nodeName: 'some name',
parentId: 'parent id 1',
@@ -136,7 +132,8 @@ describe('CategoryTreeDatasourceService', () => {
nodeType: TreeNodeType.RegularNode,
hasChildren: true,
isLoading: false
- }, {
+ },
+ {
id: 'some id 2',
nodeName: 'Language/some other name',
parentId: 'parent id 2',
@@ -144,9 +141,10 @@ describe('CategoryTreeDatasourceService', () => {
nodeType: TreeNodeType.RegularNode,
hasChildren: false,
isLoading: false
- }]
- });
- done();
+ }
+ ]
});
+ done();
+ });
});
});
diff --git a/lib/content-services/src/lib/category/services/category.service.spec.ts b/lib/content-services/src/lib/category/services/category.service.spec.ts
index 16890ad5e12..21bce87407b 100644
--- a/lib/content-services/src/lib/category/services/category.service.spec.ts
+++ b/lib/content-services/src/lib/category/services/category.service.spec.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { AppConfigService, CoreTestingModule, UserPreferencesService } from '@alfresco/adf-core';
+import { AppConfigService, TranslationMock, TranslationService, UserPreferencesService } from '@alfresco/adf-core';
import {
CategoryBody,
CategoryEntry,
@@ -29,6 +29,8 @@ import {
} from '@alfresco/js-api';
import { fakeAsync, TestBed } from '@angular/core/testing';
import { CategoryService } from './category.service';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TranslateModule } from '@ngx-translate/core';
describe('CategoryService', () => {
let categoryService: CategoryService;
@@ -44,7 +46,8 @@ describe('CategoryService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [CoreTestingModule]
+ imports: [HttpClientTestingModule, TranslateModule.forRoot()],
+ providers: [CategoryService, UserPreferencesService, { provide: TranslationService, useClass: TranslationMock }]
});
categoryService = TestBed.inject(CategoryService);
diff --git a/lib/content-services/src/lib/common/services/content.service.spec.ts b/lib/content-services/src/lib/common/services/content.service.spec.ts
index edbd2f860d6..71bdd1017c4 100644
--- a/lib/content-services/src/lib/common/services/content.service.spec.ts
+++ b/lib/content-services/src/lib/common/services/content.service.spec.ts
@@ -17,8 +17,10 @@
import { TestBed } from '@angular/core/testing';
import { ContentService } from './content.service';
-import { AppConfigService, AuthenticationService, StorageService, CoreTestingModule } from '@alfresco/adf-core';
+import { AppConfigService, AuthenticationService, RedirectAuthService, StorageService } from '@alfresco/adf-core';
import { Node, PermissionsInfo } from '@alfresco/js-api';
+import { EMPTY, of } from 'rxjs';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('ContentService', () => {
let contentService: ContentService;
@@ -27,7 +29,8 @@ describe('ContentService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [CoreTestingModule]
+ imports: [HttpClientTestingModule],
+ providers: [ContentService, AuthenticationService, { provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }]
});
authService = TestBed.inject(AuthenticationService);
contentService = TestBed.inject(ContentService);
diff --git a/lib/content-services/src/lib/common/services/people-content.service.spec.ts b/lib/content-services/src/lib/common/services/people-content.service.spec.ts
index 9dc0acac959..eff52f8f770 100644
--- a/lib/content-services/src/lib/common/services/people-content.service.spec.ts
+++ b/lib/content-services/src/lib/common/services/people-content.service.spec.ts
@@ -16,17 +16,23 @@
*/
import { createNewPersonMock, fakeEcmAdminUser, fakeEcmUser, fakeEcmUser2, fakeEcmUserList } from '../mocks/ecm-user.service.mock';
-import { AlfrescoApiService, AlfrescoApiServiceMock, CoreTestingModule } from '@alfresco/adf-core';
+import { AlfrescoApiService, AlfrescoApiServiceMock, RedirectAuthService } from '@alfresco/adf-core';
import { PeopleContentQueryRequestModel, PeopleContentService } from './people-content.service';
import { TestBed } from '@angular/core/testing';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { EMPTY, of } from 'rxjs';
describe('PeopleContentService', () => {
let peopleContentService: PeopleContentService;
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [CoreTestingModule],
- providers: [{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }]
+ imports: [HttpClientTestingModule],
+ providers: [
+ PeopleContentService,
+ { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
+ { provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }
+ ]
});
peopleContentService = TestBed.inject(PeopleContentService);
diff --git a/lib/content-services/src/lib/common/services/rendition.service.ts b/lib/content-services/src/lib/common/services/rendition.service.ts
index 002bfe6453a..e0fc85e1333 100644
--- a/lib/content-services/src/lib/common/services/rendition.service.ts
+++ b/lib/content-services/src/lib/common/services/rendition.service.ts
@@ -257,17 +257,14 @@ export class RenditionService {
printFile(url: string, type: string): void {
const pwa = window.open(url, RenditionService.TARGET);
if (pwa) {
- // Because of the way chrome focus and close image window vs. pdf preview window
- if (type === RenditionService.ContentGroup.IMAGE) {
- pwa.onfocus = () => {
+ pwa.onload = () => {
+ pwa.print();
+ if (type === RenditionService.ContentGroup.IMAGE) {
+ // Because of the way chrome focus and close image window vs. pdf preview window
setTimeout(() => {
pwa.close();
}, 500);
- };
- }
-
- pwa.onload = () => {
- pwa.print();
+ }
};
}
}
diff --git a/lib/content-services/src/lib/common/services/upload.service.spec.ts b/lib/content-services/src/lib/common/services/upload.service.spec.ts
index 3a0be5ca6f2..4dddb0d1e9b 100644
--- a/lib/content-services/src/lib/common/services/upload.service.spec.ts
+++ b/lib/content-services/src/lib/common/services/upload.service.spec.ts
@@ -17,12 +17,13 @@
import { EventEmitter } from '@angular/core';
import { TestBed } from '@angular/core/testing';
-import { AppConfigService, CoreTestingModule } from '@alfresco/adf-core';
+import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigModule, AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core';
import { UploadService } from './upload.service';
import { RepositoryInfo } from '@alfresco/js-api';
import { BehaviorSubject } from 'rxjs';
import { DiscoveryApiService } from '../../common/services/discovery-api.service';
import { FileModel, FileUploadStatus } from '../../common/models/file.model';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
declare let jasmine: any;
@@ -35,8 +36,11 @@ describe('UploadService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [CoreTestingModule],
+ imports: [AppConfigModule, HttpClientTestingModule],
providers: [
+ UploadService,
+ { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
+ { provide: AppConfigService, useClass: AppConfigServiceMock },
{
provide: DiscoveryApiService,
useValue: {
@@ -281,9 +285,7 @@ describe('UploadService', () => {
service.cancelUpload(...file);
const request = jasmine.Ajax.requests.mostRecent();
- expect(request.url).toBe(
- 'http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/fakeId/content?include=allowableOperations'
- );
+ expect(request.url).toContain('ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/fakeId/content?include=allowableOperations');
expect(request.method).toBe('PUT');
jasmine.Ajax.requests.mostRecent().respondWith({
@@ -338,8 +340,8 @@ describe('UploadService', () => {
service.uploadFilesInTheQueue(emitter);
const request = jasmine.Ajax.requests.mostRecent();
- expect(request.url).toBe(
- 'http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/123/children?autoRename=true&include=allowableOperations'
+ expect(request.url).toContain(
+ '/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/123/children?autoRename=true&include=allowableOperations'
);
expect(request.method).toBe('POST');
diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.html b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.html
index b45511e8cb7..756751988b2 100644
--- a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.html
+++ b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.html
@@ -1,4 +1,4 @@
-
+
{
let component: ContentMetadataCardComponent;
@@ -34,15 +45,40 @@ describe('ContentMetadataCardComponent', () => {
let node: Node;
const preset = 'custom-preset';
let nodeAspectService: NodeAspectService = null;
+ let tagService: TagService = null;
+ let categoryService: CategoryService = null;
+ let propertyDescriptorsService: PropertyDescriptorsService = null;
const getToggleEditButton = () => fixture.debugElement.query(By.css('[data-automation-id="meta-data-card-toggle-edit"]'));
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [ContentTestingModule]
+ imports: [
+ TranslateModule.forRoot(),
+ NoopAnimationsModule,
+ AuthModule.forRoot({ useHash: true }),
+ HttpClientModule,
+ MatDialogModule,
+ PipeModule,
+ MatSnackBarModule,
+ MatTooltipModule
+ ],
+ providers: [
+ { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
+ { provide: TranslationService, useClass: TranslationMock },
+ {
+ provide: APP_INITIALIZER,
+ useFactory: versionCompatibilityFactory,
+ deps: [ VersionCompatibilityService ],
+ multi: true
+ }
+ ]
});
fixture = TestBed.createComponent(ContentMetadataCardComponent);
contentMetadataService = TestBed.inject(ContentMetadataService);
+ tagService = TestBed.inject(TagService);
+ categoryService = TestBed.inject(CategoryService);
+ propertyDescriptorsService = TestBed.inject(PropertyDescriptorsService);
component = fixture.componentInstance;
node = {
aspectNames: [],
@@ -59,6 +95,9 @@ describe('ContentMetadataCardComponent', () => {
component.editAspectSupported = true;
nodeAspectService = TestBed.inject(NodeAspectService);
spyOn(contentMetadataService, 'getContentTypeProperty').and.returnValue(of([]));
+ spyOn(tagService, 'getTagsByNodeId').and.returnValue(of());
+ spyOn(categoryService, 'getCategoryLinksForNode').and.returnValue(of());
+ spyOn(propertyDescriptorsService, 'load').and.returnValue(of());
fixture.detectChanges();
});
diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata-header.component.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata-header.component.ts
index a0c6f607294..9c92a76833b 100644
--- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata-header.component.ts
+++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata-header.component.ts
@@ -28,21 +28,21 @@ import { TranslateModule } from '@ngx-translate/core';
encapsulation: ViewEncapsulation.None,
styles: [
`
- adf-content-metadata-header {
- display: flex;
- align-items: center;
- width: 100%;
- }
+ adf-content-metadata-header {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ }
- .adf-metadata-properties-title {
- display: block;
- overflow: hidden;
- text-overflow: ellipsis;
- font-weight: 700;
- font-size: 15px;
- padding-left: 12px;
- }
- `
+ .adf-metadata-properties-title {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-weight: 700;
+ font-size: 15px;
+ padding-left: 12px;
+ }
+ `
],
template: `
diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html
index 57f6e2e62d5..5c9522ac86b 100644
--- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html
+++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html
@@ -100,7 +100,9 @@
- {{ tag }}
+
+ {{ tag }}
+
{{ 'METADATA.BASIC.NO_TAGS_ADDED' | translate }}
diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss
index 9c26d77dca6..ca3636fbf0b 100644
--- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss
+++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss
@@ -1,3 +1,5 @@
+@import 'styles/mat-selectors';
+
$panel-properties-height: 56px !default;
.adf {
@@ -8,9 +10,24 @@ $panel-properties-height: 56px !default;
border-radius: 12px;
margin: 12px;
+ adf-card-view-textitem {
+ #{$mat-form-field-subscript-wrapper} {
+ display: none;
+ }
+
+ #{$mat-form-field-infix} {
+ padding-bottom: 0;
+ }
+ }
+
.adf-property-list .adf-property .adf-property-field {
.adf-property-value:not(.adf-card-view-selectitem .adf-property-value) {
- margin-top: 20px;
+ margin-top: 10px;
+ height: 32px;
+
+ &:is(textarea) {
+ padding-top: 6px;
+ }
}
label {
@@ -30,28 +47,32 @@ $panel-properties-height: 56px !default;
}
}
+ #{$mat-expansion-panel-body} {
+ padding-top: 16px;
+
+ input {
+ border-color: transparent;
+ width: 100%;
+
+ &:focus-visible {
+ outline: none;
+ }
+ }
+ }
+
.adf-edit-icon-buttons {
color: var(--adf-theme-foreground-text-color-054);
}
- .adf-metadata-properties-tag {
- min-height: 32px;
- display: inline-flex;
- align-items: center;
- border-radius: 16px;
- width: fit-content;
+ #{$mat-chip} {
background: var(--adf-metadata-buttons-background-color);
- margin-top: 12px;
- padding: 6px 12px;
- justify-content: center;
- margin-left: 8px;
- overflow-wrap: anywhere;
+ padding: 6px;
}
.adf-metadata-no-item-added {
word-break: break-all;
font-size: 15px;
- padding: 16px 0 0 12px;
+ padding: 0 0 0 12px;
}
&-tags {
diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts
index 4eb130da921..64b1db09665 100644
--- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts
+++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts
@@ -16,15 +16,25 @@
*/
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
-import { DebugElement, SimpleChange } from '@angular/core';
+import { SimpleChange } from '@angular/core';
import { By } from '@angular/platform-browser';
import { Category, CategoryPaging, ClassesApi, Node, Tag, TagBody, TagEntry, TagPaging, TagPagingList } from '@alfresco/js-api';
import { ContentMetadataComponent } from './content-metadata.component';
import { ContentMetadataService } from '../../services/content-metadata.service';
-import { AppConfigService, CardViewBaseItemModel, CardViewComponent, NotificationService, UpdateNotification } from '@alfresco/adf-core';
+import {
+ AppConfigService,
+ AuthModule,
+ CardViewBaseItemModel,
+ CardViewComponent,
+ NotificationService,
+ PipeModule,
+ TranslationMock,
+ TranslationService,
+ UpdateNotification
+} from '@alfresco/adf-core';
import { NodesApiService } from '../../../common/services/nodes-api.service';
import { EMPTY, of, throwError } from 'rxjs';
-import { ContentTestingModule } from '../../../testing/content.testing.module';
+import { TranslateModule } from '@ngx-translate/core';
import { CardViewContentUpdateService } from '../../../common/services/card-view-content-update.service';
import { PropertyGroup } from '../../interfaces/property-group.interface';
import { PropertyDescriptorsService } from '../../services/property-descriptors.service';
@@ -37,6 +47,14 @@ import {
TagService
} from '@alfresco/adf-content-services';
import { MatExpansionPanel } from '@angular/material/expansion';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { HttpClientModule } from '@angular/common/http';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatSnackBarModule } from '@angular/material/snack-bar';
+import { MatProgressBarModule } from '@angular/material/progress-bar';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { MatChipHarness } from '@angular/material/chips/testing';
describe('ContentMetadataComponent', () => {
let component: ContentMetadataComponent;
@@ -50,6 +68,7 @@ describe('ContentMetadataComponent', () => {
let categoryService: CategoryService;
let getClassSpy: jasmine.Spy;
let notificationService: NotificationService;
+ let getGroupedPropertiesSpy: jasmine.Spy;
const preset = 'custom-preset';
@@ -72,7 +91,16 @@ describe('ContentMetadataComponent', () => {
const category2 = new Category({ id: 'test2', name: 'testCat2' });
const categoryPagingResponse: CategoryPaging = { list: { pagination: {}, entries: [{ entry: category1 }, { entry: category2 }] } };
- const findTagElements = (): DebugElement[] => fixture.debugElement.queryAll(By.css('.adf-metadata-properties .adf-metadata-properties-tag'));
+ const findTagElements = async (): Promise
=> {
+ const matChipHarnessList = await TestbedHarnessEnvironment.loader(fixture).getAllHarnesses(
+ MatChipHarness.with({ selector: '[data-automation-id="metadata-properties-tag-chip"]' })
+ );
+ const tags = [];
+ for (const matChip of matChipHarnessList) {
+ tags.push(await matChip.getText());
+ }
+ return tags;
+ };
const findCancelButton = (): HTMLButtonElement => fixture.debugElement.query(By.css('[data-automation-id=reset-metadata]')).nativeElement;
const findCancelTagsButton = (): HTMLButtonElement =>
@@ -158,8 +186,19 @@ describe('ContentMetadataComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [ContentTestingModule],
+ imports: [
+ TranslateModule.forRoot(),
+ NoopAnimationsModule,
+ AuthModule.forRoot({ useHash: true }),
+ HttpClientModule,
+ MatDialogModule,
+ MatSnackBarModule,
+ MatProgressBarModule,
+ MatTooltipModule,
+ PipeModule
+ ],
providers: [
+ { provide: TranslationService, useClass: TranslationMock },
{
provide: TagService,
useValue: {
@@ -210,6 +249,7 @@ describe('ContentMetadataComponent', () => {
component.node = node;
component.preset = preset;
spyOn(contentMetadataService, 'getContentTypeProperty').and.returnValue(of([]));
+ getGroupedPropertiesSpy = spyOn(contentMetadataService, 'getGroupedProperties');
getClassSpy = spyOn(classesApi, 'getClass');
fixture.detectChanges();
});
@@ -231,6 +271,7 @@ describe('ContentMetadataComponent', () => {
describe('Folder', () => {
it('should show the folder node', (done) => {
component.expanded = false;
+ getGroupedPropertiesSpy.and.returnValue(of([]));
fixture.detectChanges();
component.basicProperties$.subscribe(() => {
@@ -258,7 +299,7 @@ describe('ContentMetadataComponent', () => {
it('nodeAspectUpdate', fakeAsync(() => {
const fakeNode = { id: 'fake-minimal-node', aspectNames: ['ft:a', 'ft:b', 'ft:c'], name: 'fake-node' } as Node;
- spyOn(contentMetadataService, 'getGroupedProperties').and.stub();
+ getGroupedPropertiesSpy.and.stub();
spyOn(contentMetadataService, 'getBasicProperties').and.stub();
updateService.updateNodeAspect(fakeNode);
@@ -268,7 +309,7 @@ describe('ContentMetadataComponent', () => {
}));
it('should save changedProperties on save click', fakeAsync(() => {
- spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
+ getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@@ -350,6 +391,8 @@ describe('ContentMetadataComponent', () => {
it('should throw error on unsuccessful save', fakeAsync(() => {
component.readOnly = false;
const property = { key: 'properties.property-key', value: 'original-value' } as CardViewBaseItemModel;
+ spyOn(nodesApiService, 'updateNode').and.returnValue(throwError(new Error('My bad')));
+
updateService.update(property, 'updated-value');
tick(600);
@@ -359,8 +402,6 @@ describe('ContentMetadataComponent', () => {
sub.unsubscribe();
});
- spyOn(nodesApiService, 'updateNode').and.returnValue(throwError(new Error('My bad')));
-
fixture.detectChanges();
toggleEditModeForGeneralInfo();
fixture.whenStable().then(() => clickOnGeneralInfoSave());
@@ -456,7 +497,7 @@ describe('ContentMetadataComponent', () => {
beforeEach(() => {
showErrorSpy = spyOn(notificationService, 'showError').and.stub();
- spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
+ getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@@ -612,7 +653,7 @@ describe('ContentMetadataComponent', () => {
});
it('should reset group edit ability on reset click', () => {
- spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
+ getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@@ -684,7 +725,7 @@ describe('ContentMetadataComponent', () => {
});
it('should load the group properties on node change', () => {
- spyOn(contentMetadataService, 'getGroupedProperties');
+ getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@@ -708,7 +749,7 @@ describe('ContentMetadataComponent', () => {
}
];
component.preset = presetConfig;
- spyOn(contentMetadataService, 'getGroupedProperties');
+ getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@@ -719,7 +760,7 @@ describe('ContentMetadataComponent', () => {
const expectedProperties = [];
component.expanded = true;
- spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of([{ properties: expectedProperties } as any]));
+ getGroupedPropertiesSpy.and.returnValue(of([{ properties: expectedProperties } as any]));
spyOn(component, 'showGroup').and.returnValue(true);
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@@ -733,7 +774,7 @@ describe('ContentMetadataComponent', () => {
component.expanded = true;
component.displayEmpty = false;
- spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of([{ properties: [] } as any]));
+ getGroupedPropertiesSpy.and.returnValue(of([{ properties: [] } as any]));
spyOn(component, 'showGroup').and.returnValue(true);
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@@ -744,7 +785,7 @@ describe('ContentMetadataComponent', () => {
});
it('should hide card views group when the grouped properties are empty', async () => {
- spyOn(contentMetadataService, 'getGroupedProperties').and.stub();
+ getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@@ -757,7 +798,7 @@ describe('ContentMetadataComponent', () => {
it('should display card views group when there is at least one property that is not empty', async () => {
component.expanded = true;
- spyOn(contentMetadataService, 'getGroupedProperties').and.stub();
+ getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@@ -779,7 +820,7 @@ describe('ContentMetadataComponent', () => {
});
it('should reload properties for group panel on cancel', () => {
- const getGroupedPropertiesSpy = spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
+ getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@@ -947,6 +988,7 @@ describe('ContentMetadataComponent', () => {
component.expanded = true;
component.preset = 'default';
+ getGroupedPropertiesSpy.and.callThrough();
});
it('should show Versionable with given content-metadata config', async () => {
@@ -1200,32 +1242,32 @@ describe('ContentMetadataComponent', () => {
component.displayTags = true;
});
- it('should render tags after loading tags in ngOnInit', () => {
+ it('should render tags after loading tags in ngOnInit', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnInit();
fixture.detectChanges();
expandTagsPanel();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(2);
- expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag);
- expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag);
+ expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag);
+ expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagService.getTagsByNodeId).toHaveBeenCalledWith(node.id);
});
- it('should not render tags after loading tags in ngOnInit if displayTags is false', () => {
+ it('should not render tags after loading tags in ngOnInit if displayTags is false', async () => {
component.displayTags = false;
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnInit();
fixture.detectChanges();
expandTagsPanel();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
- it('should render tags after loading tags in ngOnChanges', () => {
+ it('should render tags after loading tags in ngOnChanges', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({
@@ -1234,14 +1276,14 @@ describe('ContentMetadataComponent', () => {
fixture.detectChanges();
expandTagsPanel();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(2);
- expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag);
- expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag);
+ expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag);
+ expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagService.getTagsByNodeId).toHaveBeenCalledWith(node.id);
});
- it('should not render tags after loading tags in ngOnChanges if displayTags is false', () => {
+ it('should not render tags after loading tags in ngOnChanges if displayTags is false', async () => {
component.displayTags = false;
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({
@@ -1250,23 +1292,23 @@ describe('ContentMetadataComponent', () => {
expandTagsPanel();
fixture.detectChanges();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
- it('should not render tags after loading tags in ngOnChanges if node is not changed', () => {
+ it('should not render tags after loading tags in ngOnChanges if node is not changed', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({});
expandTagsPanel();
fixture.detectChanges();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
- it('should not render tags after loading tags in ngOnChanges if node is changed first time', () => {
+ it('should not render tags after loading tags in ngOnChanges if node is changed first time', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({
node: new SimpleChange(undefined, node, true)
@@ -1274,12 +1316,12 @@ describe('ContentMetadataComponent', () => {
expandTagsPanel();
fixture.detectChanges();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
- it('should render tags after loading tags after clicking on Cancel button', fakeAsync(() => {
+ it('should render tags after loading tags after clicking on Cancel button', fakeAsync(async () => {
component.readOnly = false;
fixture.detectChanges();
toggleEditModeForTags();
@@ -1293,14 +1335,14 @@ describe('ContentMetadataComponent', () => {
fixture.detectChanges();
expandTagsPanel();
- const tagElements = findTagElements();
+ const tagElements = await findTagElements();
expect(tagElements).toHaveSize(2);
- expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag);
- expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag);
+ expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag);
+ expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagService.getTagsByNodeId).toHaveBeenCalledOnceWith(node.id);
}));
- it('should be hidden when editable is true', () => {
+ it('should be hidden when editable is true', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnInit();
component.readOnly = false;
@@ -1308,7 +1350,7 @@ describe('ContentMetadataComponent', () => {
toggleEditModeForTags();
fixture.detectChanges();
- expect(findTagElements()).toHaveSize(0);
+ expect(await findTagElements()).toHaveSize(0);
});
});
diff --git a/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts b/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts
index 6634d0f6671..a7f01737a9f 100644
--- a/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts
+++ b/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts
@@ -33,15 +33,17 @@ describe('PropertyDescriptorLoaderService', () => {
classesApi = service['classesApi'];
});
- it('should load the groups passed by paramter', () => {
- spyOn(classesApi, 'getClass');
+ it('should load the groups passed by paramter', (done) => {
+ spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve({}));
- service.load(['exif:exif', 'cm:content', 'custom:custom']).subscribe(() => {});
-
- expect(classesApi.getClass).toHaveBeenCalledTimes(3);
- expect(classesApi.getClass).toHaveBeenCalledWith('exif_exif');
- expect(classesApi.getClass).toHaveBeenCalledWith('cm_content');
- expect(classesApi.getClass).toHaveBeenCalledWith('custom_custom');
+ service.load(['exif:exif', 'cm:content', 'custom:custom'])
+ .subscribe(() => {
+ expect(classesApi.getClass).toHaveBeenCalledTimes(3);
+ expect(classesApi.getClass).toHaveBeenCalledWith('exif_exif');
+ expect(classesApi.getClass).toHaveBeenCalledWith('cm_content');
+ expect(classesApi.getClass).toHaveBeenCalledWith('custom_custom');
+ done();
+ });
});
it('should merge the forked values', (done) => {
diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html
index a6e56b5177c..9893f98da0b 100644
--- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html
+++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html
@@ -1,10 +1,14 @@
-
+
+ {{ 'NODE_SELECTOR.SEARCH' | translate }}
diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.scss b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.scss
index 080e9260ee9..8561a5688e1 100644
--- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.scss
+++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.scss
@@ -1,3 +1,5 @@
+@import 'styles/mat-selectors';
+
/* stylelint-disable no-descending-specificity */
$content-node-selector-thumbnail-width: 35px !default;
$content-node-selector-thumbnail-max-width: 40px !default;
@@ -13,6 +15,12 @@ h2.adf-search-results-label {
color: var(--adf-theme-foreground-text-color-087);
}
+#{$mdc-dialog} {
+ #{$mat-dialog-surface}:is(div) {
+ padding-bottom: 0;
+ }
+}
+
.adf-content-node-selector-panel {
.adf-toolbar .adf-toolbar-container.adf-toolbar-container-row {
max-height: 48px;
@@ -28,90 +36,142 @@ h2.adf-search-results-label {
}
&-document-list-container {
+ margin-top: 16px;
width: 100%;
}
&-content {
+ #{$mat-input-element} {
+ &:focus::placeholder {
+ color: var(--theme-primary-color);
+ }
+ }
+
+ #{$mat-form-field-wrapper} {
+ #{$mat-form-field-flex} {
+ align-items: center;
+
+ #{$mat-form-field-infix} {
+ padding-bottom: 0;
+ }
+ }
+ }
+
+ .adf-sites-dropdown-form-field {
+ label {
+ {$mat-form-field-label} {
+ top: 32px;
+ }
+ }
+ }
+
+ #{$mat-form-field-subscript-wrapper} {
+ height: 16px;
+ }
+
padding-top: 0;
&-input {
width: 100%;
+ margin-bottom: 8px;
- &-icon {
+ .adf-content-node-selector-content-input-icon {
color: var(--adf-theme-foreground-icon-color-054);
cursor: pointer;
+ padding: 0 0 8px;
+ width: 1em;
+ height: 1em;
+ font-size: 20px;
&:hover {
color: var(--adf-theme-foreground-base-color);
}
}
- }
- .adf-site-dropdown-container {
- .adf-sites-dropdown-form-field {
- display: block;
- margin-bottom: 15px;
+ #{$mat-form-field-subscript-wrapper} {
+ display: none;
}
}
- .adf-site-dropdown-list-element {
- width: 100%;
- margin-bottom: 0;
+ .adf-site-dropdown-container {
+ display: block;
- .adf-sites-dropdown-select-trigger {
- font-size: var(--theme-body-1-font-size);
+ .adf-sites-dropdown-form-field {
+ width: 100%;
}
}
+ }
- &-breadcrumb {
- .adf-dropdown-breadcrumb-trigger {
- outline: none;
-
- .adf-dropdown-breadcrumb-icon {
- color: var(--adf-theme-foreground-base-color-045);
+ &-breadcrumb {
+ .adf-dropdown-breadcrumb-trigger {
+ outline: none;
- &:hover {
- color: var(--adf-theme-foreground-base-color-065);
- }
- }
+ .adf-dropdown-breadcrumb-icon {
+ color: var(--adf-theme-foreground-base-color-045);
- &:focus .adf-dropdown-breadcrumb-icon {
- color: var(--theme-primary-color);
+ &:hover {
+ color: var(--adf-theme-foreground-base-color-065);
}
}
- .adf-dropdown-breadcrumb-item-chevron {
- color: var(--adf-theme-foreground-base-color-045);
+ &:focus .adf-dropdown-breadcrumb-icon {
+ color: var(--theme-primary-color);
}
}
- &-list {
- height: 40vh;
- overflow: auto;
- border: 1px solid var(--adf-theme-foreground-text-color-007);
- border-top: 0;
- position: relative;
+ .adf-dropdown-breadcrumb-item-chevron {
+ color: var(--adf-theme-foreground-base-color-045);
+ }
+ }
+
+ &-content-list,
+ &-list {
+ height: 40vh;
+ overflow: auto;
+ border: 1px solid var(--adf-theme-foreground-text-color-007);
+ border-top: 0;
+ position: relative;
+
+ &-empty + adf-infinite-pagination {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ }
+
+ .adf-highlight {
+ color: var(--theme-primary-color);
+ }
+
+ .adf-datatable-list {
+ border: none;
+
+ .adf-name-location-cell-location {
+ display: none;
+ }
- &-empty + adf-infinite-pagination {
- position: absolute;
- bottom: 0;
+ .adf-datatable-selected {
+ height: 100%;
width: 100%;
}
- .adf-highlight {
- color: var(--theme-primary-color);
+ .adf-datatable-selected > svg {
+ fill: var(--theme-primary-color);
}
- .adf-datatable-list {
+ .adf-no-content-container.adf-datatable-cell {
+ text-align: center;
border: none;
+ }
- .adf-datatable-selected {
- height: 100%;
- width: 100%;
+ .adf-datatable-cell {
+ &--image {
+ min-width: $content-node-selector-thumbnail-width;
+ width: $content-node-selector-thumbnail-width;
+ max-width: $content-node-selector-thumbnail-max-width;
}
- .adf-datatable-selected > svg {
- fill: var(--theme-primary-color);
+ &:nth-child(2) {
+ flex: 1 0 95px;
}
.adf-no-content-container.adf-datatable-cell {
@@ -119,78 +179,61 @@ h2.adf-search-results-label {
border: none;
}
- .adf-datatable-cell {
- &--image {
- min-width: $content-node-selector-thumbnail-width;
- width: $content-node-selector-thumbnail-width;
- max-width: $content-node-selector-thumbnail-max-width;
- }
+ &.adf-content-selector-visibility-cell {
+ flex: 0 1 auto;
+ min-width: 1px;
- &:nth-child(2) {
- flex: 1 0 95px;
+ .adf-datatable-cell-value {
+ padding: 0;
}
+ }
+ }
- .adf-name-location-cell-location {
- display: none;
- }
+ .adf-datatable-body .adf-datatable-row {
+ min-height: 40px;
- &.adf-content-selector-visibility-cell {
- flex: 0 1 auto;
- min-width: 1px;
+ @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
+ padding-top: 15px;
+ }
- .adf-datatable-cell-value {
- padding: 0;
- }
+ &:first-child {
+ .adf-datatable-cell {
+ border-top: none;
}
}
- .adf-datatable-body .adf-datatable-row {
- min-height: 40px;
+ &:last-child {
+ .adf-datatable-cell {
+ border-bottom: none;
+ }
+ }
+ }
+ }
- @media screen and (-ms-high-contrast: active),
- screen and (-ms-high-contrast: none) {
- padding-top: 15px;
+ &-searchLayout {
+ .adf-datatable-list .adf-datatable-body .adf-datatable-row {
+ min-height: 65px;
+
+ .adf-datatable-cell-container {
+ .adf-name-location-cell-location {
+ padding: 0 10px;
+ display: block;
}
- &:first-child {
- .adf-datatable-cell {
- border-top: none;
- }
+ .adf-name-location-cell-name {
+ padding: 5px 10px 2px;
}
- &:last-child {
- .adf-datatable-cell {
- border-bottom: none;
- }
+ &.adf-content-selector-modified-cell {
+ display: none;
}
- }
- }
- &-searchLayout {
- .adf-datatable-list .adf-datatable-body .adf-datatable-row {
- min-height: 65px;
+ &.adf-content-selector-modifier-cell {
+ display: none;
+ }
- .adf-datatable-cell {
- .adf-name-location-cell-location {
- padding: 0 10px;
- display: block;
- }
-
- .adf-name-location-cell-name {
- padding: 5px 10px 2px;
- }
-
- &.adf-content-selector-modified-cell {
- display: none;
- }
-
- &.adf-content-selector-modifier-cell {
- display: none;
- }
-
- &.adf-content-selector-visibility-cell {
- display: none;
- }
+ &.adf-content-selector-visibility-cell {
+ display: none;
}
}
}
diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss
index 9a725d8c65b..545c6154e12 100644
--- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss
+++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss
@@ -1,3 +1,5 @@
+@import 'styles/mat-selectors';
+
adf-content-node-selector {
.adf-upload-dialog {
box-shadow: none;
@@ -40,6 +42,23 @@ adf-content-node-selector {
}
.adf-content-node-selector-dialog {
+ #{$mat-form-field} {
+ width: 100%;
+ }
+
+ .adf-dropdown-breadcrumb-icon {
+ color: var(--adf-theme-foreground-base-color-045);
+ }
+
+ #{$mat-dialog-title} {
+ margin-bottom: 0;
+ padding: 0;
+
+ &::before {
+ display: none;
+ }
+ }
+
.adf-content-node-selector-dialog-title {
font-size: var(--theme-title-font-size);
font-weight: 600;
@@ -48,6 +67,7 @@ adf-content-node-selector {
line-height: 1.6;
letter-spacing: -0.5px;
color: var(--adf-theme-foreground-text-color-087);
+ margin-bottom: 20px;
h2 {
margin: unset;
@@ -57,7 +77,8 @@ adf-content-node-selector {
.adf-content-node-selector-dialog-actions {
padding: 8px;
- height: 61px;
+ height: 77px;
+ background-color: var(--theme-background-color);
display: flex;
flex-direction: row;
justify-content: space-between;
diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts
index 71196ec8acc..83c6b3492c7 100644
--- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts
+++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.spec.ts
@@ -148,13 +148,13 @@ describe('ContentNodeSelectorComponent', () => {
it('should pass through the injected currentFolderId to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
- expect(documentList).not.toBeNull();
+ expect(documentList).not.toBeNull('Document list should be shown');
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
});
it('should pass through the injected rowFilter to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
- expect(documentList).not.toBeNull();
+ expect(documentList).not.toBeNull('Document list should be shown');
expect(
documentList.componentInstance.rowFilter({
node: {
@@ -178,69 +178,66 @@ describe('ContentNodeSelectorComponent', () => {
it('should pass through the injected imageResolver to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
- expect(documentList).not.toBeNull();
+ expect(documentList).not.toBeNull('Document list should be shown');
expect(documentList.componentInstance.imageResolver).toBe(data.imageResolver);
});
});
describe('Cancel button', () => {
- const getCancelButton = () => fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
-
it('should not be shown if dialogRef is NOT injected', () => {
const closeButton = fixture.debugElement.query(By.css('[content-node-selector-actions-cancel]'));
expect(closeButton).toBeNull();
});
it('should close the dialog', () => {
- let cancelButton = getCancelButton();
+ let cancelButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
cancelButton.triggerEventHandler('click', {});
expect(dialog.close).toHaveBeenCalled();
fixture.detectChanges();
- cancelButton = getCancelButton();
+ cancelButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
expect(cancelButton).not.toBeNull();
});
});
describe('Action button for the chosen node', () => {
- const getActionButton = () =>
- fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'))?.nativeElement as HTMLButtonElement;
-
it('should be disabled by default', () => {
fixture.detectChanges();
- const actionButton = getActionButton();
- expect(actionButton.disabled).toBeTruthy();
+ const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
+ expect(actionButton.nativeElement.disabled).toBeTruthy();
});
it('should be enabled when a node is chosen', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
- const actionButton = getActionButton();
- expect(actionButton.disabled).toBeFalsy();
+ const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
+ expect(actionButton.nativeElement.disabled).toBeFalsy();
});
it('should be disabled when no node chosen', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
- const actionButtonWithNodeSelected = getActionButton();
- expect(actionButtonWithNodeSelected.disabled).toBe(false);
+ const actionButtonWithNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
+
+ expect(actionButtonWithNodeSelected.nativeElement.disabled).toBe(false);
component.onSelect([]);
fixture.detectChanges();
- const actionButtonWithoutNodeSelected = getActionButton();
- expect(actionButtonWithoutNodeSelected.disabled).toBe(true);
+ const actionButtonWithoutNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
+
+ expect(actionButtonWithoutNodeSelected.nativeElement.disabled).toBe(true);
});
- it('should close the dialog when action button is clicked', () => {
+ it('should close the dialog when action button is clicked', async () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
- const actionButton = getActionButton();
- actionButton.click();
+ const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
+ await actionButton.nativeElement.click();
expect(dialog.close).toHaveBeenCalled();
});
@@ -260,8 +257,6 @@ describe('ContentNodeSelectorComponent', () => {
});
describe('Upload button', () => {
- const getUploadButton = () => fixture.debugElement.query(By.css('adf-upload-button button'))?.nativeElement as HTMLButtonElement;
-
it('Should not be able to upload a file whilst a search is still running', async () => {
enableLocalUpload();
fixture.detectChanges();
@@ -308,10 +303,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
- const adfUploadButton = getUploadButton();
+ const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
- expect(adfUploadButton.disabled).toBe(true);
+ expect(adfUploadButton.nativeElement.disabled).toBe(true);
});
it('should be able to enable UploadButton if showingSearch set to false', async () => {
@@ -320,10 +315,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
- const adfUploadButton = getUploadButton();
+ const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
- expect(adfUploadButton.disabled).toBe(false);
+ expect(adfUploadButton.nativeElement.disabled).toBe(false);
});
it('should be able to show warning message while searching', async () => {
@@ -333,7 +328,7 @@ describe('ContentNodeSelectorComponent', () => {
await selectTabByIndex(1);
fixture.detectChanges();
- const infoMatIcon = getTabInfoButton();
+ const infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
const iconTooltipMessage = infoMatIcon.attributes['ng-reflect-message'];
const expectedMessage = 'NODE_SELECTOR.UPLOAD_BUTTON_SEARCH_WARNING_MESSAGE';
@@ -359,10 +354,10 @@ describe('ContentNodeSelectorComponent', () => {
component.onTabSelectionChange(1);
fixture.detectChanges();
- const adfUploadButton = getUploadButton();
+ const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
- expect(adfUploadButton.disabled).toBe(true);
+ expect(adfUploadButton.nativeElement.disabled).toBe(true);
});
it('should be able to enable UploadButton if user has allowable operations', async () => {
@@ -370,10 +365,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
- const adfUploadButton = getUploadButton();
+ const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
- expect(adfUploadButton.disabled).toBe(false);
+ expect(adfUploadButton.nativeElement.disabled).toBe(false);
});
it('should not be able to show warning message if user has allowable operations', async () => {
@@ -393,7 +388,7 @@ describe('ContentNodeSelectorComponent', () => {
await selectTabByIndex(1);
fixture.detectChanges();
- const infoMatIcon = getTabInfoButton();
+ const infoMatIcon = fixture.debugElement.query(By.css('[data-automation-id="adf-content-node-selector-disabled-tab-info-icon"]'));
const iconTooltipMessage = infoMatIcon.attributes['ng-reflect-message'];
const expectedMessage = 'NODE_SELECTOR.UPLOAD_BUTTON_PERMISSION_WARNING_MESSAGE';
@@ -448,8 +443,6 @@ describe('ContentNodeSelectorComponent', () => {
});
describe('Drag and drop area', () => {
- const getEmptyList = () => fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
-
it('should uploadStarted be false by default', () => {
expect(component.uploadStarted).toBe(false);
});
@@ -467,8 +460,7 @@ describe('ContentNodeSelectorComponent', () => {
fixture.detectChanges();
await fixture.whenRenderingDone();
-
- const emptyListTemplate = getEmptyList();
+ const emptyListTemplate = fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
const dragAndDropArea = fixture.debugElement.query(By.css('.adf-upload-drag-area'));
expect(emptyListTemplate).not.toBeNull();
@@ -482,15 +474,13 @@ describe('ContentNodeSelectorComponent', () => {
component.uploadStarted = true;
fixture.detectChanges();
await fixture.whenRenderingDone();
+ const emptyListTemplate = fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
- const emptyListTemplate = getEmptyList();
expect(emptyListTemplate).toBeNull();
});
});
describe('Selected nodes counter', () => {
- const getNodeCounter = () => fixture.debugElement.nativeElement.querySelector('adf-node-counter');
-
it('should getSelectedCount return 0 by default', () => {
expect(component.getSelectedCount()).toBe(0);
});
@@ -504,19 +494,19 @@ describe('ContentNodeSelectorComponent', () => {
it('should show the counter depending on the action', () => {
component.action = NodeAction.ATTACH;
fixture.detectChanges();
- expect(getNodeCounter()).not.toBe(null);
+ expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).not.toBe(null);
component.action = NodeAction.CHOOSE;
fixture.detectChanges();
- expect(getNodeCounter()).not.toBe(null);
+ expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).not.toBe(null);
component.action = NodeAction.COPY;
fixture.detectChanges();
- expect(getNodeCounter()).toBe(null);
+ expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).toBe(null);
component.action = NodeAction.MOVE;
fixture.detectChanges();
- expect(getNodeCounter()).toBe(null);
+ expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).toBe(null);
});
});
});
diff --git a/lib/content-services/src/lib/content-node-share/content-node-share.dialog.html b/lib/content-services/src/lib/content-node-share/content-node-share.dialog.html
index a0583bbde60..35775a2787f 100644
--- a/lib/content-services/src/lib/content-node-share/content-node-share.dialog.html
+++ b/lib/content-services/src/lib/content-node-share/content-node-share.dialog.html
@@ -1,6 +1,6 @@