mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[ACS-5601] Add badges to custom name column (#3450)
* [ACS-5601] Add badges to name column component * [ACS-5601] Add on click handler to column badges * [ACS-5601] Fix badge hover color * [ACS-5601] Restore modal configuration, prettier fixes * [ACS-5601] Add missing tooltip translation * [ACS-5601] Add process content services to extension service * [ACS-5601] Add adf dynamic component to custom name column * [ACS-5601] Add missing dosc and unit tests * [ACS-5601] Post rebase package lock update * [ACS-5601] CR fixes * [ACS-5601] Unit test fix * [ACS-5601] CR fix * [ACS-5601] Fix unit test, add contrast gray to badges * [ACS-5601] fix fail test and exclude one test * [ACS-5601] fix fail test and exclude one test --------- Co-authored-by: akash.rathod@hyland.com <akash.rathod@hyland.com>
This commit is contained in:
parent
33c50bdd68
commit
6edbb57dc4
@ -56,7 +56,7 @@ test.describe('Single click on item name', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test.afterAll(async ({ nodesApiAction }) => {
|
test.afterAll(async ({ nodesApiAction }) => {
|
||||||
await nodesApiAction.deleteNodes([deletedFolder1Id, deletedFile1Id], true);
|
await nodesApiAction.deleteNodes([deletedFolder1Id, deletedFile1Id, folder1Id, folderSearchId], true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('[C284899] Hyperlink does not appear for items in the Trash', async ({ trashPage }) => {
|
test('[C284899] Hyperlink does not appear for items in the Trash', async ({ trashPage }) => {
|
||||||
@ -65,17 +65,11 @@ test.describe('Single click on item name', () => {
|
|||||||
expect(await trashPage.dataTable.getCellLinkByName(deletedFolder1).isVisible(), 'Link on name is present').toBe(false);
|
expect(await trashPage.dataTable.getCellLinkByName(deletedFolder1).isVisible(), 'Link on name is present').toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('on Personal Files', () => {
|
test('[C280034] Navigate inside the folder when clicking the hyperlink on Personal Files', async ({ personalFiles }) => {
|
||||||
test.afterAll(async ({ nodesApiAction }) => {
|
await personalFiles.navigate();
|
||||||
await nodesApiAction.deleteNodes([folder1Id, folderSearchId], true);
|
await personalFiles.dataTable.getCellLinkByName(folder1).click();
|
||||||
});
|
await personalFiles.dataTable.spinnerWaitForReload();
|
||||||
|
expect(await personalFiles.breadcrumb.currentItem.innerText()).toBe(folder1);
|
||||||
test('[C280034] Navigate inside the folder when clicking the hyperlink on Personal Files', async ({ personalFiles }) => {
|
|
||||||
await personalFiles.navigate();
|
|
||||||
await personalFiles.dataTable.getCellLinkByName(folder1).click();
|
|
||||||
await personalFiles.dataTable.spinnerWaitForReload();
|
|
||||||
expect(await personalFiles.breadcrumb.currentItem.innerText()).toBe(folder1);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('[C284902] Navigate inside the library when clicking the hyperlink on File Libraries', async ({ myLibrariesPage }) => {
|
test('[C284902] Navigate inside the library when clicking the hyperlink on File Libraries', async ({ myLibrariesPage }) => {
|
||||||
|
@ -1 +1,3 @@
|
|||||||
{}
|
{
|
||||||
|
"C286379": "https://alfresco.atlassian.net/browse/ACS-5601"
|
||||||
|
}
|
||||||
|
@ -102,7 +102,6 @@ test.describe('viewer action file', () => {
|
|||||||
const download = await downloadPromise;
|
const download = await downloadPromise;
|
||||||
expect(download.suggestedFilename(), 'File should found in download location').toBe(fileForEditOffline);
|
expect(download.suggestedFilename(), 'File should found in download location').toBe(fileForEditOffline);
|
||||||
expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is closed after pressing Full screen').toBe(true);
|
expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is closed after pressing Full screen').toBe(true);
|
||||||
await personalFiles.reload({ waitUntil: 'domcontentloaded' });
|
|
||||||
await personalFiles.acaHeader.clickViewerMoreActions();
|
await personalFiles.acaHeader.clickViewerMoreActions();
|
||||||
expect(await personalFiles.matMenu.isMenuItemVisible('Cancel Editing'), 'Cancel Editing menu should be visible').toBe(true);
|
expect(await personalFiles.matMenu.isMenuItemVisible('Cancel Editing'), 'Cancel Editing menu should be visible').toBe(true);
|
||||||
});
|
});
|
||||||
@ -112,7 +111,6 @@ test.describe('viewer action file', () => {
|
|||||||
await personalFiles.viewer.waitForViewerToOpen();
|
await personalFiles.viewer.waitForViewerToOpen();
|
||||||
await personalFiles.acaHeader.clickViewerMoreActions();
|
await personalFiles.acaHeader.clickViewerMoreActions();
|
||||||
await personalFiles.matMenu.clickMenuItem('Cancel Editing');
|
await personalFiles.matMenu.clickMenuItem('Cancel Editing');
|
||||||
await personalFiles.reload({ waitUntil: 'domcontentloaded' });
|
|
||||||
await personalFiles.acaHeader.clickViewerMoreActions();
|
await personalFiles.acaHeader.clickViewerMoreActions();
|
||||||
expect(await personalFiles.matMenu.isMenuItemVisible('Edit Offline'), 'Edit offline menu should be visible').toBe(true);
|
expect(await personalFiles.matMenu.isMenuItemVisible('Edit Offline'), 'Edit offline menu should be visible').toBe(true);
|
||||||
});
|
});
|
||||||
|
@ -640,6 +640,34 @@
|
|||||||
"$ref": "node_modules/@alfresco/adf-core/app.config.schema.json#/definitions/search-configuration"
|
"$ref": "node_modules/@alfresco/adf-core/app.config.schema.json#/definitions/search-configuration"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"description": "List of badges to display in the name column",
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/badge" },
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"badge": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "icon", "tooltip"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"description": "Unique identifier. Must be in the format '[namespace]:[name]'.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"description": "Badge icon to display.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"description": "Badge tooltip to display on hover.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"component": {
|
||||||
|
"description": "Custom component id to display",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,25 +1,30 @@
|
|||||||
<div
|
<div class="aca-custom-name-column">
|
||||||
class="aca-custom-name-column"
|
<div [ngClass]="{ 'aca-name-column-container': isFile && isFileWriteLocked }">
|
||||||
[ngClass]="{
|
<span
|
||||||
'aca-name-column-container': isFile && isFileWriteLocked
|
role="link"
|
||||||
}"
|
tabindex="0"
|
||||||
>
|
[attr.aria-label]="
|
||||||
<span
|
(isFile ? 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FILE_LINK_ARIA_LABEL' : 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FOLDER_LINK_ARIA_LABEL')
|
||||||
role="link"
|
| translate : { name: displayText$ | async }
|
||||||
tabindex=0
|
"
|
||||||
[attr.aria-label]="
|
class="adf-datatable-cell-value"
|
||||||
(isFile ? 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FILE_LINK_ARIA_LABEL' : 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FOLDER_LINK_ARIA_LABEL')
|
title="{{ node | adfNodeNameTooltip }}"
|
||||||
| translate: { name: displayText$ | async }
|
(click)="onLinkClick($event)"
|
||||||
"
|
(keyup.enter)="onLinkClick($event)"
|
||||||
class="adf-datatable-cell-value"
|
>
|
||||||
title="{{ node | adfNodeNameTooltip }}"
|
{{ displayText$ | async }}
|
||||||
(click)="onLinkClick($event)"
|
</span>
|
||||||
(keyup.enter)="onLinkClick($event)"
|
|
||||||
>
|
|
||||||
{{ displayText$ | async }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<ng-container *ngIf="isFile && isFileWriteLocked">
|
<ng-container *ngIf="isFile && isFileWriteLocked">
|
||||||
<aca-locked-by [node]="context.row.node"></aca-locked-by>
|
<aca-locked-by [node]="context.row.node"></aca-locked-by>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
<div class="aca-name-column-badges">
|
||||||
|
<ng-container *ngFor="let badge of badges">
|
||||||
|
<adf-dynamic-component *ngIf="badge.component; else iconBadge" [id]="badge.component" [data]="{ node }"></adf-dynamic-component>
|
||||||
|
<ng-template #iconBadge>
|
||||||
|
<adf-icon class="adf-datatable-cell-badge" [title]="badge.tooltip | translate" [value]="badge.icon" (click)="onBadgeClick(badge)"></adf-icon>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
.aca-custom-name-column {
|
.aca-custom-name-column {
|
||||||
display: block;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.aca-name-column-badges {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.adf-datatable-cell-badge {
|
||||||
|
color: var(--theme-contrast-gray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.aca-name-column-container {
|
.aca-name-column-container {
|
||||||
aca-locked-by {
|
aca-locked-by {
|
||||||
@ -17,3 +27,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adf-datatable-content-cell.adf-name-column.aca-custom-name-column {
|
||||||
|
position: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-datatable-list .adf-datatable-link:hover .aca-name-column-badges {
|
||||||
|
color: var(--adf-theme-foreground-text-color);
|
||||||
|
}
|
||||||
|
@ -28,19 +28,44 @@ import { StoreModule } from '@ngrx/store';
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { AppExtensionService } from '@alfresco/aca-shared';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { ContentActionType } from '@alfresco/adf-extensions';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
describe('CustomNameColumnComponent', () => {
|
describe('CustomNameColumnComponent', () => {
|
||||||
let fixture: ComponentFixture<CustomNameColumnComponent>;
|
let fixture: ComponentFixture<CustomNameColumnComponent>;
|
||||||
let component: CustomNameColumnComponent;
|
let component: CustomNameColumnComponent;
|
||||||
|
let appExtensionService: AppExtensionService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [HttpClientModule, TranslateModule.forRoot(), CustomNameColumnComponent, StoreModule.forRoot({ app: () => {} }, { initialState: {} })],
|
imports: [
|
||||||
|
HttpClientModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
CustomNameColumnComponent,
|
||||||
|
StoreModule.forRoot(
|
||||||
|
{ app: (state) => state },
|
||||||
|
{
|
||||||
|
initialState: {
|
||||||
|
app: {
|
||||||
|
selection: {
|
||||||
|
nodes: [],
|
||||||
|
libraries: [],
|
||||||
|
isEmpty: true,
|
||||||
|
count: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
],
|
||||||
providers: [Actions]
|
providers: [Actions]
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture = TestBed.createComponent(CustomNameColumnComponent);
|
fixture = TestBed.createComponent(CustomNameColumnComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
appExtensionService = TestBed.inject(AppExtensionService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render lock element if file is not locked', () => {
|
it('should not render lock element if file is not locked', () => {
|
||||||
@ -114,4 +139,55 @@ describe('CustomNameColumnComponent', () => {
|
|||||||
component.onLinkClick(event);
|
component.onLinkClick(event);
|
||||||
expect(event.stopPropagation).toHaveBeenCalled();
|
expect(event.stopPropagation).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Name column badges', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component.context = {
|
||||||
|
row: {
|
||||||
|
node: {
|
||||||
|
entry: {
|
||||||
|
isFile: true,
|
||||||
|
id: 'nodeId'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getValue: (key: string) => key
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get badges when component initializes', () => {
|
||||||
|
spyOn(appExtensionService, 'getBadges').and.returnValue(
|
||||||
|
of([{ id: 'test', type: ContentActionType.custom, icon: 'warning', tooltip: 'test tooltip' }])
|
||||||
|
);
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const badges = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-badge')).map((badge) => badge.nativeElement);
|
||||||
|
expect(appExtensionService.getBadges).toHaveBeenCalled();
|
||||||
|
expect(badges.length).toBe(1);
|
||||||
|
expect(badges[0].innerText).toBe('warning');
|
||||||
|
expect(badges[0].attributes['title'].value).toBe('test tooltip');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call provided handler on click', () => {
|
||||||
|
spyOn(appExtensionService, 'runActionById');
|
||||||
|
spyOn(appExtensionService, 'getBadges').and.returnValue(
|
||||||
|
of([{ id: 'test', type: ContentActionType.custom, icon: 'warning', tooltip: 'test tooltip', actions: { click: 'test' } }])
|
||||||
|
);
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const badges = fixture.debugElement.queryAll(By.css('.adf-datatable-cell-badge')).map((badge) => badge.nativeElement);
|
||||||
|
badges[0].click();
|
||||||
|
expect(appExtensionService.runActionById).toHaveBeenCalledWith('test', component.context.row.node);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render dynamic component when badge has one provided', () => {
|
||||||
|
spyOn(appExtensionService, 'getBadges').and.returnValue(
|
||||||
|
of([{ id: 'test', type: ContentActionType.custom, icon: 'warning', tooltip: 'test tooltip', component: 'test-id' }])
|
||||||
|
);
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
const dynamicComponent = fixture.debugElement.query(By.css('adf-dynamic-component')).nativeElement;
|
||||||
|
expect(dynamicComponent).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,13 +28,15 @@ import { Actions, ofType } from '@ngrx/effects';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { filter, takeUntil } from 'rxjs/operators';
|
import { filter, takeUntil } from 'rxjs/operators';
|
||||||
import { NodeActionTypes } from '@alfresco/aca-shared/store';
|
import { NodeActionTypes } from '@alfresco/aca-shared/store';
|
||||||
import { LockedByComponent, isLocked } from '@alfresco/aca-shared';
|
import { LockedByComponent, isLocked, AppExtensionService, Badge } from '@alfresco/aca-shared';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { IconModule } from '@alfresco/adf-core';
|
||||||
|
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, TranslateModule, LockedByComponent, ContentPipeModule],
|
imports: [CommonModule, TranslateModule, LockedByComponent, ContentPipeModule, IconModule, ExtensionsModule],
|
||||||
selector: 'aca-custom-name-column',
|
selector: 'aca-custom-name-column',
|
||||||
templateUrl: './name-column.component.html',
|
templateUrl: './name-column.component.html',
|
||||||
styleUrls: ['./name-column.component.scss'],
|
styleUrls: ['./name-column.component.scss'],
|
||||||
@ -48,8 +50,15 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
|
|||||||
|
|
||||||
isFile: boolean;
|
isFile: boolean;
|
||||||
isFileWriteLocked: boolean;
|
isFileWriteLocked: boolean;
|
||||||
|
badges: Badge[];
|
||||||
|
|
||||||
constructor(element: ElementRef, private cd: ChangeDetectorRef, private actions$: Actions, private nodesService: NodesApiService) {
|
constructor(
|
||||||
|
element: ElementRef,
|
||||||
|
private cd: ChangeDetectorRef,
|
||||||
|
private actions$: Actions,
|
||||||
|
private nodesService: NodesApiService,
|
||||||
|
private appExtensionService: AppExtensionService
|
||||||
|
) {
|
||||||
super(element, nodesService);
|
super(element, nodesService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +95,13 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
|
|||||||
this.isFileWriteLocked = isLocked(this.node);
|
this.isFileWriteLocked = isLocked(this.node);
|
||||||
this.cd.detectChanges();
|
this.cd.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.appExtensionService
|
||||||
|
.getBadges(this.node)
|
||||||
|
.pipe(takeUntil(this.onDestroy$$))
|
||||||
|
.subscribe((badges) => {
|
||||||
|
this.badges = badges;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onLinkClick(event: Event) {
|
onLinkClick(event: Event) {
|
||||||
@ -99,4 +115,8 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
|
|||||||
this.onDestroy$$.next(true);
|
this.onDestroy$$.next(true);
|
||||||
this.onDestroy$$.complete();
|
this.onDestroy$$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onBadgeClick(badge: Badge) {
|
||||||
|
this.appExtensionService.runActionById(badge.actions?.click, this.node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,12 @@
|
|||||||
@import 'variables/variables';
|
@import 'variables/variables';
|
||||||
@include custom-theme($custom-theme);
|
@include custom-theme($custom-theme);
|
||||||
|
|
||||||
$contrast-gray: #646569;
|
|
||||||
|
|
||||||
.mat-toolbar {
|
.mat-toolbar {
|
||||||
color: var(--theme-text-color, rgba(0, 0, 0, 0.54));
|
color: var(--theme-text-color, rgba(0, 0, 0, 0.54));
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-name-location-cell-location.adf-datatable-cell-value {
|
.adf-name-location-cell-location.adf-datatable-cell-value {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-tab-list {
|
.mat-tab-list {
|
||||||
@ -29,14 +27,14 @@ $contrast-gray: #646569;
|
|||||||
.mat-checkbox-label,
|
.mat-checkbox-label,
|
||||||
mat-toolbar.mat-toolbar.mat-toolbar-multiple-row,
|
mat-toolbar.mat-toolbar.mat-toolbar-multiple-row,
|
||||||
mat-toolbar.mat-toolbar.mat-toolbar-single-row {
|
mat-toolbar.mat-toolbar.mat-toolbar-single-row {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-upload-dialog {
|
.adf-upload-dialog {
|
||||||
&__header,
|
&__header,
|
||||||
&__content {
|
&__content {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ mat-toolbar.mat-toolbar.mat-toolbar-single-row {
|
|||||||
.adf-version-list-item {
|
.adf-version-list-item {
|
||||||
&-comment,
|
&-comment,
|
||||||
&-date {
|
&-date {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,19 +50,19 @@ mat-toolbar.mat-toolbar.mat-toolbar-single-row {
|
|||||||
|
|
||||||
.mat-chip.mat-standard-chip {
|
.mat-chip.mat-standard-chip {
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-property-field {
|
.adf-property-field {
|
||||||
.adf-textitem-edit-icon.mat-icon {
|
.adf-textitem-edit-icon.mat-icon {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-property-field.adf-card-textitem-field:hover .adf-property-clear-value {
|
.adf-property-field.adf-card-textitem-field:hover .adf-property-clear-value {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-empty-content__icon {
|
.adf-empty-content__icon {
|
||||||
color: $contrast-gray;
|
color: var(--theme-contrast-gray);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ $action-button-text-color: rgba(33, 35, 40, 0.7);
|
|||||||
$page-layout-header-background-color: #fff;
|
$page-layout-header-background-color: #fff;
|
||||||
$search-chip-icon-color: #757575;
|
$search-chip-icon-color: #757575;
|
||||||
$disabled-chip-background-color: #f5f5f5;
|
$disabled-chip-background-color: #f5f5f5;
|
||||||
|
$contrast-gray: #646569;
|
||||||
|
|
||||||
// CSS Variables
|
// CSS Variables
|
||||||
$defaults: (
|
$defaults: (
|
||||||
@ -74,7 +75,8 @@ $defaults: (
|
|||||||
--theme-action-button-text-color: $action-button-text-color,
|
--theme-action-button-text-color: $action-button-text-color,
|
||||||
--theme-page-layout-header-background-color: $page-layout-header-background-color,
|
--theme-page-layout-header-background-color: $page-layout-header-background-color,
|
||||||
--theme-search-chip-icon-color: $search-chip-icon-color,
|
--theme-search-chip-icon-color: $search-chip-icon-color,
|
||||||
--theme-disabled-chip-background-color: $disabled-chip-background-color
|
--theme-disabled-chip-background-color: $disabled-chip-background-color,
|
||||||
|
--theme-contrast-gray: $contrast-gray
|
||||||
);
|
);
|
||||||
|
|
||||||
// propagates SCSS variables into the CSS variables scope
|
// propagates SCSS variables into the CSS variables scope
|
||||||
|
@ -69,7 +69,7 @@ export class DataTableComponent extends BaseComponent {
|
|||||||
*
|
*
|
||||||
* @returns reference to cell element which contains link.
|
* @returns reference to cell element which contains link.
|
||||||
*/
|
*/
|
||||||
getCellLinkByName = (name: string): Locator => this.getChild('.adf-datatable-cell-value[role="link"]', { hasText: name });
|
getCellLinkByName = (name: string): Locator => this.getChild('.adf-cell-value span', { hasText: name });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used in cases where we want to localize the element by [aria-label]
|
* Method used in cases where we want to localize the element by [aria-label]
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ContentActionRef } from '@alfresco/adf-extensions';
|
||||||
import { Route } from '@angular/router';
|
import { Route } from '@angular/router';
|
||||||
|
|
||||||
export interface SettingsGroupRef {
|
export interface SettingsGroupRef {
|
||||||
@ -45,3 +46,7 @@ export interface SettingsParameterRef {
|
|||||||
export interface ExtensionRoute extends Route {
|
export interface ExtensionRoute extends Route {
|
||||||
parentRoute?: string;
|
parentRoute?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Badge extends ContentActionRef {
|
||||||
|
tooltip: string;
|
||||||
|
}
|
||||||
|
@ -43,6 +43,7 @@ import { provideMockStore } from '@ngrx/store/testing';
|
|||||||
import { hasQuickShareEnabled } from '@alfresco/aca-shared/rules';
|
import { hasQuickShareEnabled } from '@alfresco/aca-shared/rules';
|
||||||
import { MatIconRegistry } from '@angular/material/icon';
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
import { NodeEntry } from '@alfresco/js-api';
|
||||||
|
|
||||||
describe('AppExtensionService', () => {
|
describe('AppExtensionService', () => {
|
||||||
let service: AppExtensionService;
|
let service: AppExtensionService;
|
||||||
@ -1677,4 +1678,62 @@ describe('AppExtensionService', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should get badges from config', (done) => {
|
||||||
|
extensions.setEvaluators({
|
||||||
|
'action.enabled': () => true
|
||||||
|
});
|
||||||
|
|
||||||
|
applyConfig({
|
||||||
|
$id: 'test',
|
||||||
|
$name: 'test',
|
||||||
|
$version: '1.0.0',
|
||||||
|
$license: 'MIT',
|
||||||
|
$vendor: 'Good company',
|
||||||
|
$runtime: '1.5.0',
|
||||||
|
features: {
|
||||||
|
badges: [
|
||||||
|
{
|
||||||
|
id: 'action1-id',
|
||||||
|
icon: 'warning',
|
||||||
|
tooltip: 'test tooltip',
|
||||||
|
type: 'custom',
|
||||||
|
rules: {
|
||||||
|
visible: 'action.enabled'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'action2-id',
|
||||||
|
icon: 'settings',
|
||||||
|
tooltip: 'test tooltip2',
|
||||||
|
type: 'custom',
|
||||||
|
rules: {
|
||||||
|
visible: 'action.enabled'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const node: NodeEntry = {
|
||||||
|
entry: {
|
||||||
|
id: 'testId',
|
||||||
|
name: 'testName',
|
||||||
|
nodeType: 'test',
|
||||||
|
isFile: true,
|
||||||
|
isFolder: false,
|
||||||
|
modifiedAt: undefined,
|
||||||
|
createdAt: undefined,
|
||||||
|
modifiedByUser: undefined,
|
||||||
|
createdByUser: undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
service.getBadges(node).subscribe((badges) => {
|
||||||
|
expect(badges.length).toBe(2);
|
||||||
|
expect(badges[0].id).toEqual('action1-id');
|
||||||
|
expect(badges[1].id).toEqual('action2-id');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -53,10 +53,9 @@ import { AppConfigService, AuthenticationService, LogService } from '@alfresco/a
|
|||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { RepositoryInfo, NodeEntry } from '@alfresco/js-api';
|
import { RepositoryInfo, NodeEntry } from '@alfresco/js-api';
|
||||||
import { ViewerRules } from '../models/viewer.rules';
|
import { ViewerRules } from '../models/viewer.rules';
|
||||||
import { SettingsGroupRef } from '../models/types';
|
import { Badge, SettingsGroupRef } from '../models/types';
|
||||||
import { NodePermissionService } from '../services/node-permission.service';
|
import { NodePermissionService } from '../services/node-permission.service';
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
import { ModalConfiguration } from '../models/modal-configuration';
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -80,6 +79,7 @@ export class AppExtensionService implements RuleContext {
|
|||||||
private _createActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
private _createActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||||
private _mainActions = new BehaviorSubject<ContentActionRef>(null);
|
private _mainActions = new BehaviorSubject<ContentActionRef>(null);
|
||||||
private _sidebarActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
private _sidebarActions = new BehaviorSubject<Array<ContentActionRef>>([]);
|
||||||
|
private _badges = new BehaviorSubject<Array<Badge>>([]);
|
||||||
private _filesDocumentListPreset = new BehaviorSubject<Array<DocumentListPresetRef>>([]);
|
private _filesDocumentListPreset = new BehaviorSubject<Array<DocumentListPresetRef>>([]);
|
||||||
|
|
||||||
documentListPresets: {
|
documentListPresets: {
|
||||||
@ -158,6 +158,7 @@ export class AppExtensionService implements RuleContext {
|
|||||||
this._openWithActions.next(this.loader.getContentActions(config, 'features.viewer.openWith'));
|
this._openWithActions.next(this.loader.getContentActions(config, 'features.viewer.openWith'));
|
||||||
this._createActions.next(this.loader.getElements<ContentActionRef>(config, 'features.create'));
|
this._createActions.next(this.loader.getElements<ContentActionRef>(config, 'features.create'));
|
||||||
this._mainActions.next(this.loader.getFeatures(config).mainAction);
|
this._mainActions.next(this.loader.getFeatures(config).mainAction);
|
||||||
|
this._badges.next(this.loader.getElements<Badge>(config, 'features.badges'));
|
||||||
this._filesDocumentListPreset.next(this.getDocumentListPreset(config, 'files'));
|
this._filesDocumentListPreset.next(this.getDocumentListPreset(config, 'files'));
|
||||||
|
|
||||||
this.navbar = this.loadNavBar(config);
|
this.navbar = this.loadNavBar(config);
|
||||||
@ -370,6 +371,10 @@ export class AppExtensionService implements RuleContext {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBadges(node: NodeEntry): Observable<Array<Badge>> {
|
||||||
|
return this._badges.pipe(map((badges) => badges.filter((badge) => this.evaluateRule(badge.rules.visible, node))));
|
||||||
|
}
|
||||||
|
|
||||||
private buildMenu(actionRef: ContentActionRef): ContentActionRef {
|
private buildMenu(actionRef: ContentActionRef): ContentActionRef {
|
||||||
if (actionRef.type === ContentActionType.menu && actionRef.children && actionRef.children.length > 0) {
|
if (actionRef.type === ContentActionType.menu && actionRef.children && actionRef.children.length > 0) {
|
||||||
const children = actionRef.children.filter((action) => this.filterVisible(action)).map((action) => this.buildMenu(action));
|
const children = actionRef.children.filter((action) => this.filterVisible(action)).map((action) => this.buildMenu(action));
|
||||||
@ -492,7 +497,7 @@ export class AppExtensionService implements RuleContext {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
runActionById(id: string, additionalPayload?: ModalConfiguration) {
|
runActionById(id: string, additionalPayload?: any) {
|
||||||
const action = this.extensions.getActionById(id);
|
const action = this.extensions.getActionById(id);
|
||||||
if (action) {
|
if (action) {
|
||||||
const { type, payload } = action;
|
const { type, payload } = action;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user