mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
Merge pull request #5332 from Alfresco/dev-siva-AAE-1200-add-edit-icon
[AAE-1200] AAE - FE - Provide a way to define icon on CardViewArrayItemComponent
This commit is contained in:
@@ -152,9 +152,14 @@ export class CardViewComponent implements OnInit, OnDestroy {
|
|||||||
}),
|
}),
|
||||||
new CardViewArrayItemModel({
|
new CardViewArrayItemModel({
|
||||||
label: 'CardView Array of items',
|
label: 'CardView Array of items',
|
||||||
value: of(['Zlatan', 'Lionel Messi', 'Mohamed', 'Ronaldo']),
|
value: of([
|
||||||
|
{ icon: 'directions_bike', value: 'Zlatan' },
|
||||||
|
{ icon: 'directions_bike', value: 'Lionel Messi'},
|
||||||
|
{ value: 'Mohamed', directions_bike: 'save'},
|
||||||
|
{ value: 'Ronaldo'}
|
||||||
|
]),
|
||||||
key: 'array',
|
key: 'array',
|
||||||
icon: 'directions_bike',
|
icon: 'edit',
|
||||||
default: 'Empty',
|
default: 'Empty',
|
||||||
noOfItemsToDisplay: 2
|
noOfItemsToDisplay: 2
|
||||||
})
|
})
|
||||||
|
@@ -90,7 +90,10 @@ Defining properties from Typescript:
|
|||||||
new CardViewArrayItemModel({
|
new CardViewArrayItemModel({
|
||||||
label: 'Array of items',
|
label: 'Array of items',
|
||||||
value: '',
|
value: '',
|
||||||
items$: of(['One', 'Two', 'Three', 'Four']),
|
items$: of([
|
||||||
|
{ icon: 'person', value: 'One' }, { icon: 'person', value: 'Two' },
|
||||||
|
{ icon: 'person', value: 'Three' }, { icon: 'person', value: 'Four' }
|
||||||
|
]),
|
||||||
key: 'array',
|
key: 'array',
|
||||||
default: 'Empty',
|
default: 'Empty',
|
||||||
noOfItemsToDisplay: 2
|
noOfItemsToDisplay: 2
|
||||||
@@ -358,7 +361,7 @@ const arrayItemProperty = new CardViewArrayItemModel(items);
|
|||||||
| label\* | string | | Item label |
|
| label\* | string | | Item label |
|
||||||
| key\* | string | | Identifying key (important when editing the item) |
|
| key\* | string | | Identifying key (important when editing the item) |
|
||||||
| editable | boolean | false | Toggles whether the item is editable |
|
| editable | boolean | false | Toggles whether the item is editable |
|
||||||
| value | [`Observable`](http://reactivex.io/documentation/observable.html)<`string`\[]> | | The original data value for the item |
|
| value | [`Observable`](http://reactivex.io/documentation/observable.html)<[`CardViewArrayItem`](../../../lib/core/card-view/models/card-view-arrayitem.model.ts)\[]> | | The original data value for the item |
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
@@ -1,15 +1,14 @@
|
|||||||
|
|
||||||
<div [attr.data-automation-id]="'card-array-label-' + property.key" class="adf-property-label">{{ property.label | translate }}</div>
|
<div [attr.data-automation-id]="'card-array-label-' + property.key" class="adf-property-label">{{ property.label | translate }}</div>
|
||||||
<div class="adf-property-value" (click)="clicked()">
|
<div class="adf-property-value adf-card-view-array-item-container" (click)="clicked()">
|
||||||
<ng-container *ngIf="(property.displayValue | async) as items; else elseEmptyValueBlock">
|
<ng-container *ngIf="(property.displayValue | async) as items; else elseEmptyValueBlock">
|
||||||
<mat-chip-list *ngIf="items.length > 0; else elseEmptyValueBlock" data-automation-id="card-arrayitem-chip-list-container">
|
<mat-chip-list *ngIf="items.length > 0; else elseEmptyValueBlock" data-automation-id="card-arrayitem-chip-list-container">
|
||||||
<ng-container *ngIf="displayCount() > 0; else withOutDisplayCount" >
|
<ng-container *ngIf="displayCount() > 0; else withOutDisplayCount" >
|
||||||
<mat-chip
|
<mat-chip
|
||||||
*ngFor="let item of items.slice(0, displayCount())"
|
*ngFor="let item of items.slice(0, displayCount())"
|
||||||
(click)="clicked()"
|
(click)="clicked()"
|
||||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item">
|
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||||
<mat-icon *ngIf="hasIcon()" class="adf-array-item-icon">{{property.icon}}</mat-icon>
|
<mat-icon *ngIf="item?.icon" class="adf-array-item-icon">{{item.icon}}</mat-icon>
|
||||||
<span>{{item}}</span>
|
<span>{{item?.value}}</span>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
<mat-chip
|
<mat-chip
|
||||||
*ngIf="items.length > displayCount()"
|
*ngIf="items.length > displayCount()"
|
||||||
@@ -22,9 +21,9 @@
|
|||||||
<mat-chip
|
<mat-chip
|
||||||
*ngFor="let item of items"
|
*ngFor="let item of items"
|
||||||
(click)="clicked()"
|
(click)="clicked()"
|
||||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item">
|
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||||
<mat-icon *ngIf="hasIcon()" class="adf-array-item-icon">{{property.icon}}</mat-icon>
|
<mat-icon *ngIf="item?.icon" class="adf-array-item-icon">{{item.icon}}</mat-icon>
|
||||||
<span>{{item}}</span>
|
<span>{{item?.value}}</span>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
@@ -34,9 +33,9 @@
|
|||||||
<mat-chip-list>
|
<mat-chip-list>
|
||||||
<mat-chip (click)="clicked()"
|
<mat-chip (click)="clicked()"
|
||||||
*ngFor="let item of items.slice(displayCount(), items.length)"
|
*ngFor="let item of items.slice(displayCount(), items.length)"
|
||||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item">
|
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||||
<mat-icon *ngIf="hasIcon()" class="adf-array-item-icon">{{property.icon}}</mat-icon>
|
<mat-icon *ngIf="item?.icon" class="adf-array-item-icon">{{item.icon}}</mat-icon>
|
||||||
<span>{{item}}</span>
|
<span>{{item?.value}}</span>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
@@ -44,6 +43,13 @@
|
|||||||
</mat-menu>
|
</mat-menu>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #elseEmptyValueBlock>
|
<ng-template #elseEmptyValueBlock>
|
||||||
<span data-automation-id="card-arrayitem-default">{{ property.default | translate }}</span>
|
<span class="adf-card-array-item-default" data-automation-id="card-arrayitem-default">{{ property?.default | translate }}</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
<button mat-icon-button *ngIf="showClickableIcon()"
|
||||||
|
class="adf-array-item-action"
|
||||||
|
[attr.aria-label]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||||
|
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||||
|
[attr.data-automation-id]="'card-array-item-clickable-icon-' + property.key">
|
||||||
|
<mat-icon class="adf-array-item-icon">{{property.icon}}</mat-icon>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
@mixin adf-card-view-array-item-theme($theme) {
|
@mixin adf-card-view-array-item-theme($theme) {
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
.adf {
|
.adf {
|
||||||
&-array-item-icon {
|
&-array-item-icon {
|
||||||
@@ -6,6 +7,21 @@
|
|||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-array-item-action {
|
||||||
|
color: mat-color($foreground, text, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-array-item-action:hover, &-array-item-action:focus {
|
||||||
|
color: mat-color($foreground, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-card-array-item-default {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
&-array-item-more-chip-container {
|
&-array-item-more-chip-container {
|
||||||
&.mat-card {
|
&.mat-card {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@@ -29,5 +45,13 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-card-view-array-item-container {
|
||||||
|
flex-direction: row;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
place-content: center space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,20 +20,26 @@ import { of } from 'rxjs';
|
|||||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||||
import { CardViewArrayItemComponent } from './card-view-arrayitem.component';
|
import { CardViewArrayItemComponent } from './card-view-arrayitem.component';
|
||||||
import { CardViewArrayItemModel } from '../../models/card-view-arrayitem.model';
|
import { CardViewArrayItemModel, CardViewArrayItem } from '../../models/card-view-arrayitem.model';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
describe('CardViewArrayItemComponent', () => {
|
describe('CardViewArrayItemComponent', () => {
|
||||||
let component: CardViewArrayItemComponent;
|
let component: CardViewArrayItemComponent;
|
||||||
let fixture: ComponentFixture<CardViewArrayItemComponent>;
|
let fixture: ComponentFixture<CardViewArrayItemComponent>;
|
||||||
|
|
||||||
const mockData = ['Zlatan', 'Lionel Messi', 'Mohamed', 'Ronaldo'];
|
const mockData = <CardViewArrayItem[]> [
|
||||||
|
{ icon: 'person', value: 'Zlatan' },
|
||||||
|
{ icon: 'group', value: 'Lionel Messi' },
|
||||||
|
{ icon: 'person', value: 'Mohamed' },
|
||||||
|
{ icon: 'person', value: 'Ronaldo' }];
|
||||||
|
|
||||||
const mockDefaultProps = {
|
const mockDefaultProps = {
|
||||||
label: 'Array of items',
|
label: 'Array of items',
|
||||||
value: of(mockData),
|
value: of(mockData),
|
||||||
key: 'array',
|
key: 'array',
|
||||||
icon: 'person'
|
icon: 'edit'
|
||||||
};
|
};
|
||||||
|
|
||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [CoreTestingModule]
|
imports: [CoreTestingModule]
|
||||||
});
|
});
|
||||||
@@ -77,6 +83,47 @@ describe('CardViewArrayItemComponent', () => {
|
|||||||
expect(chip2.innerText).toEqual('Lionel Messi');
|
expect(chip2.innerText).toEqual('Lionel Messi');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render chip with defined icon', () => {
|
||||||
|
component.property = new CardViewArrayItemModel({
|
||||||
|
...mockDefaultProps,
|
||||||
|
editable: true
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const chiplistContainer = fixture.debugElement.query(By.css('[data-automation-id="card-arrayitem-chip-list-container"]'));
|
||||||
|
const chip1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-Zlatan"] span');
|
||||||
|
const chip1Icon = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-Zlatan"] mat-icon');
|
||||||
|
const chip2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-Lionel Messi"] span');
|
||||||
|
const chip2Icon = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-Lionel Messi"] mat-icon');
|
||||||
|
|
||||||
|
expect(chiplistContainer).not.toBeNull();
|
||||||
|
expect(chip1.innerText).toEqual('Zlatan');
|
||||||
|
expect(chip1Icon.innerText).toEqual('person');
|
||||||
|
expect(chip2.innerText).toEqual('Lionel Messi');
|
||||||
|
expect(chip2Icon.innerText).toEqual('group');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render defined icon if clickable set to true', () => {
|
||||||
|
component.property = new CardViewArrayItemModel({
|
||||||
|
...mockDefaultProps,
|
||||||
|
clickable: true
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
const editicon = fixture.nativeElement.querySelector('[data-automation-id="card-array-item-clickable-icon-array"]');
|
||||||
|
expect(editicon).toBeDefined();
|
||||||
|
expect(editicon.innerText).toBe('edit');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render defined icon if clickable set to false', () => {
|
||||||
|
component.property = new CardViewArrayItemModel({
|
||||||
|
...mockDefaultProps,
|
||||||
|
clickable: false
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
const editicon = fixture.nativeElement.querySelector('[data-automation-id="card-array-item-clickable-icon-array"]');
|
||||||
|
expect(editicon).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('should render all values if noOfItemsToDisplay is not defined', () => {
|
it('should render all values if noOfItemsToDisplay is not defined', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
@@ -33,7 +33,13 @@ export class CardViewArrayItemComponent {
|
|||||||
constructor(private cardViewUpdateService: CardViewUpdateService) {}
|
constructor(private cardViewUpdateService: CardViewUpdateService) {}
|
||||||
|
|
||||||
clicked(): void {
|
clicked(): void {
|
||||||
this.cardViewUpdateService.clicked(this.property);
|
if (this.isClickable()) {
|
||||||
|
this.cardViewUpdateService.clicked(this.property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showClickableIcon(): boolean {
|
||||||
|
return this.hasIcon() && this.isClickable();
|
||||||
}
|
}
|
||||||
|
|
||||||
hasIcon(): boolean {
|
hasIcon(): boolean {
|
||||||
@@ -43,4 +49,8 @@ export class CardViewArrayItemComponent {
|
|||||||
displayCount(): number {
|
displayCount(): number {
|
||||||
return this.property.noOfItemsToDisplay ? this.property.noOfItemsToDisplay : 0;
|
return this.property.noOfItemsToDisplay ? this.property.noOfItemsToDisplay : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isClickable(): boolean {
|
||||||
|
return !!this.property.clickable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,10 +21,15 @@ import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { CardViewArrayItemProperties } from '../interfaces/card-view-arrayitem-properties.interface';
|
import { CardViewArrayItemProperties } from '../interfaces/card-view-arrayitem-properties.interface';
|
||||||
|
|
||||||
|
export interface CardViewArrayItem {
|
||||||
|
icon: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class CardViewArrayItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
export class CardViewArrayItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||||
|
|
||||||
type: string = 'array';
|
type: string = 'array';
|
||||||
value: Observable<string[]>;
|
value: Observable<CardViewArrayItem[]>;
|
||||||
noOfItemsToDisplay: number;
|
noOfItemsToDisplay: number;
|
||||||
|
|
||||||
constructor(cardViewArrayItemProperties: CardViewArrayItemProperties) {
|
constructor(cardViewArrayItemProperties: CardViewArrayItemProperties) {
|
||||||
@@ -32,7 +37,7 @@ export class CardViewArrayItemModel extends CardViewBaseItemModel implements Car
|
|||||||
this.noOfItemsToDisplay = cardViewArrayItemProperties.noOfItemsToDisplay;
|
this.noOfItemsToDisplay = cardViewArrayItemProperties.noOfItemsToDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
get displayValue(): Observable<string[]> {
|
get displayValue(): Observable<CardViewArrayItem[]> {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,8 @@ import {
|
|||||||
AppConfigService,
|
AppConfigService,
|
||||||
UpdateNotification,
|
UpdateNotification,
|
||||||
CardViewUpdateService,
|
CardViewUpdateService,
|
||||||
CardViewDatetimeItemModel
|
CardViewDatetimeItemModel,
|
||||||
|
CardViewArrayItem
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { TaskDetailsCloudModel, TaskStatus } from '../../start-task/models/task-details-cloud.model';
|
import { TaskDetailsCloudModel, TaskStatus } from '../../start-task/models/task-details-cloud.model';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@@ -63,8 +64,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
|||||||
error: EventEmitter<any> = new EventEmitter<any>();
|
error: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
taskDetails: TaskDetailsCloudModel = {};
|
taskDetails: TaskDetailsCloudModel = {};
|
||||||
candidateUsers: string[] = [];
|
candidateUsers: CardViewArrayItem[] = [];
|
||||||
candidateGroups: string[] = [];
|
candidateGroups: CardViewArrayItem[] = [];
|
||||||
properties: CardViewItem[];
|
properties: CardViewItem[];
|
||||||
inEdit: boolean = false;
|
inEdit: boolean = false;
|
||||||
parentTaskName: string;
|
parentTaskName: string;
|
||||||
@@ -120,8 +121,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
|||||||
)
|
)
|
||||||
).subscribe(([taskDetails, candidateUsers, candidateGroups]) => {
|
).subscribe(([taskDetails, candidateUsers, candidateGroups]) => {
|
||||||
this.taskDetails = taskDetails;
|
this.taskDetails = taskDetails;
|
||||||
this.candidateGroups = candidateGroups;
|
this.candidateGroups = candidateGroups.map((user) => <CardViewArrayItem> { icon: 'group', value: user });
|
||||||
this.candidateUsers = candidateUsers;
|
this.candidateUsers = candidateUsers.map((group) => <CardViewArrayItem> { icon: 'person', value: group });
|
||||||
if (this.taskDetails.parentTaskId) {
|
if (this.taskDetails.parentTaskId) {
|
||||||
this.loadParentName(`${this.taskDetails.parentTaskId}`);
|
this.loadParentName(`${this.taskDetails.parentTaskId}`);
|
||||||
} else {
|
} else {
|
||||||
@@ -235,7 +236,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
|||||||
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS',
|
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS',
|
||||||
value: of(this.candidateUsers),
|
value: of(this.candidateUsers),
|
||||||
key: 'candidateUsers',
|
key: 'candidateUsers',
|
||||||
icon: 'person',
|
icon: 'edit',
|
||||||
|
clickable: false,
|
||||||
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT'),
|
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT'),
|
||||||
noOfItemsToDisplay: 2
|
noOfItemsToDisplay: 2
|
||||||
}
|
}
|
||||||
@@ -245,7 +247,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
|||||||
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS',
|
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS',
|
||||||
value: of(this.candidateGroups),
|
value: of(this.candidateGroups),
|
||||||
key: 'candidateGroups',
|
key: 'candidateGroups',
|
||||||
icon: 'group',
|
icon: 'edit',
|
||||||
|
clickable: false,
|
||||||
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT'),
|
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT'),
|
||||||
noOfItemsToDisplay: 2
|
noOfItemsToDisplay: 2
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user