Skip to content

Commit

Permalink
[ACS-5601] Add badges to custom name column (#3450)
Browse files Browse the repository at this point in the history
* [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: [email protected] <[email protected]>
  • Loading branch information
MichalKinas and akashrathod28 authored Oct 4, 2023
1 parent 33c50bd commit 6edbb57
Show file tree
Hide file tree
Showing 14 changed files with 268 additions and 58 deletions.
18 changes: 6 additions & 12 deletions e2e/playwright/navigation/src/tests/single-click.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test.describe('Single click on item name', () => {
});

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 }) => {
Expand All @@ -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);
});

test.describe('on Personal Files', () => {
test.afterAll(async ({ nodesApiAction }) => {
await nodesApiAction.deleteNodes([folder1Id, folderSearchId], true);
});

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('[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 }) => {
Expand Down
4 changes: 3 additions & 1 deletion e2e/playwright/viewer/exclude.tests.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"C286379": "https://alfresco.atlassian.net/browse/ACS-5601"
}
2 changes: 0 additions & 2 deletions e2e/playwright/viewer/src/tests/viewer-action.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ test.describe('viewer action file', () => {
const download = await downloadPromise;
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);
await personalFiles.reload({ waitUntil: 'domcontentloaded' });
await personalFiles.acaHeader.clickViewerMoreActions();
expect(await personalFiles.matMenu.isMenuItemVisible('Cancel Editing'), 'Cancel Editing menu should be visible').toBe(true);
});
Expand All @@ -112,7 +111,6 @@ test.describe('viewer action file', () => {
await personalFiles.viewer.waitForViewerToOpen();
await personalFiles.acaHeader.clickViewerMoreActions();
await personalFiles.matMenu.clickMenuItem('Cancel Editing');
await personalFiles.reload({ waitUntil: 'domcontentloaded' });
await personalFiles.acaHeader.clickViewerMoreActions();
expect(await personalFiles.matMenu.isMenuItemVisible('Edit Offline'), 'Edit offline menu should be visible').toBe(true);
});
Expand Down
28 changes: 28 additions & 0 deletions extension.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,34 @@
"$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"
}
}
}
},

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
<div
class="aca-custom-name-column"
[ngClass]="{
'aca-name-column-container': isFile && isFileWriteLocked
}"
>
<span
role="link"
tabindex=0
[attr.aria-label]="
(isFile ? 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FILE_LINK_ARIA_LABEL' : 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FOLDER_LINK_ARIA_LABEL')
| translate: { name: displayText$ | async }
"
class="adf-datatable-cell-value"
title="{{ node | adfNodeNameTooltip }}"
(click)="onLinkClick($event)"
(keyup.enter)="onLinkClick($event)"
>
{{ displayText$ | async }}
</span>
<div class="aca-custom-name-column">
<div [ngClass]="{ 'aca-name-column-container': isFile && isFileWriteLocked }">
<span
role="link"
tabindex="0"
[attr.aria-label]="
(isFile ? 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FILE_LINK_ARIA_LABEL' : 'CUSTOM_NAME_COLUMN.ACCESSIBILITY.FOLDER_LINK_ARIA_LABEL')
| translate : { name: displayText$ | async }
"
class="adf-datatable-cell-value"
title="{{ node | adfNodeNameTooltip }}"
(click)="onLinkClick($event)"
(keyup.enter)="onLinkClick($event)"
>
{{ displayText$ | async }}
</span>

<ng-container *ngIf="isFile && isFileWriteLocked">
<aca-locked-by [node]="context.row.node"></aca-locked-by>
</ng-container>
<ng-container *ngIf="isFile && isFileWriteLocked">
<aca-locked-by [node]="context.row.node"></aca-locked-by>
</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>
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
.aca-custom-name-column {
display: block;
display: flex;
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-locked-by {
Expand All @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,44 @@ import { StoreModule } from '@ngrx/store';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientModule } from '@angular/common/http';
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', () => {
let fixture: ComponentFixture<CustomNameColumnComponent>;
let component: CustomNameColumnComponent;
let appExtensionService: AppExtensionService;

beforeEach(() => {
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]
});

fixture = TestBed.createComponent(CustomNameColumnComponent);
component = fixture.componentInstance;
appExtensionService = TestBed.inject(AppExtensionService);
});

it('should not render lock element if file is not locked', () => {
Expand Down Expand Up @@ -114,4 +139,55 @@ describe('CustomNameColumnComponent', () => {
component.onLinkClick(event);
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();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ import { Actions, ofType } from '@ngrx/effects';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
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 { TranslateModule } from '@ngx-translate/core';
import { IconModule } from '@alfresco/adf-core';
import { ExtensionsModule } from '@alfresco/adf-extensions';

@Component({
standalone: true,
imports: [CommonModule, TranslateModule, LockedByComponent, ContentPipeModule],
imports: [CommonModule, TranslateModule, LockedByComponent, ContentPipeModule, IconModule, ExtensionsModule],
selector: 'aca-custom-name-column',
templateUrl: './name-column.component.html',
styleUrls: ['./name-column.component.scss'],
Expand All @@ -48,8 +50,15 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On

isFile: 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);
}

Expand Down Expand Up @@ -86,6 +95,13 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
this.isFileWriteLocked = isLocked(this.node);
this.cd.detectChanges();
});

this.appExtensionService
.getBadges(this.node)
.pipe(takeUntil(this.onDestroy$$))
.subscribe((badges) => {
this.badges = badges;
});
}

onLinkClick(event: Event) {
Expand All @@ -99,4 +115,8 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
this.onDestroy$$.next(true);
this.onDestroy$$.complete();
}

onBadgeClick(badge: Badge) {
this.appExtensionService.runActionById(badge.actions?.click, this.node);
}
}
18 changes: 8 additions & 10 deletions projects/aca-content/src/lib/ui/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
@import 'variables/variables';
@include custom-theme($custom-theme);

$contrast-gray: #646569;

.mat-toolbar {
color: var(--theme-text-color, rgba(0, 0, 0, 0.54));
}

.adf-name-location-cell-location.adf-datatable-cell-value {
color: $contrast-gray;
color: var(--theme-contrast-gray);
}

.mat-tab-list {
Expand All @@ -29,42 +27,42 @@ $contrast-gray: #646569;
.mat-checkbox-label,
mat-toolbar.mat-toolbar.mat-toolbar-multiple-row,
mat-toolbar.mat-toolbar.mat-toolbar-single-row {
color: $contrast-gray;
color: var(--theme-contrast-gray);
opacity: 1;
}

.adf-upload-dialog {
&__header,
&__content {
color: $contrast-gray;
color: var(--theme-contrast-gray);
}
}

.adf-version-list {
.adf-version-list-item {
&-comment,
&-date {
color: $contrast-gray;
color: var(--theme-contrast-gray);
opacity: 1;
}
}
}

.mat-chip.mat-standard-chip {
background-color: #efefef;
color: $contrast-gray;
color: var(--theme-contrast-gray);
}

.adf-property-field {
.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 {
color: $contrast-gray;
color: var(--theme-contrast-gray);
}

.adf-empty-content__icon {
color: $contrast-gray;
color: var(--theme-contrast-gray);
}
Loading

0 comments on commit 6edbb57

Please sign in to comment.