mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
[ADF-5390] [ADF-5391] Add multivalue cardview for Date, Datetime, Integers and Decimal properties. (#6980)
* [ADF-5390] Addd multivalue cardview for Date, Datetime, Integers and Decimal properties * Fix unit test * Fix linting * Fix e2e tests * fix e2e Co-authored-by: Eugenio Romano <eugenio.romano@alfresco.com>
This commit is contained in:
parent
71cad4c287
commit
bd805cb34b
@ -125,6 +125,15 @@ export class CardViewComponent implements OnInit, OnDestroy {
|
|||||||
format: 'shortDate',
|
format: 'shortDate',
|
||||||
editable: this.isEditable
|
editable: this.isEditable
|
||||||
}),
|
}),
|
||||||
|
new CardViewDateItemModel({
|
||||||
|
label: 'CardView Date Item - Multivalue (chips)',
|
||||||
|
value: [new Date(1983, 11, 24, 10, 0, 30)],
|
||||||
|
key: 'date',
|
||||||
|
default: new Date(1983, 11, 24, 10, 0, 30),
|
||||||
|
format: 'shortDate',
|
||||||
|
editable: this.isEditable,
|
||||||
|
multivalued: true
|
||||||
|
}),
|
||||||
new CardViewDatetimeItemModel({
|
new CardViewDatetimeItemModel({
|
||||||
label: 'CardView Datetime Item',
|
label: 'CardView Datetime Item',
|
||||||
value: new Date(1983, 11, 24, 10, 0, 0),
|
value: new Date(1983, 11, 24, 10, 0, 0),
|
||||||
@ -133,6 +142,15 @@ export class CardViewComponent implements OnInit, OnDestroy {
|
|||||||
format: 'short',
|
format: 'short',
|
||||||
editable: this.isEditable
|
editable: this.isEditable
|
||||||
}),
|
}),
|
||||||
|
new CardViewDatetimeItemModel({
|
||||||
|
label: 'CardView Datetime Item - Multivalue (chips)',
|
||||||
|
value: [new Date(1983, 11, 24, 10, 0, 0)],
|
||||||
|
key: 'datetime',
|
||||||
|
default: new Date(1983, 11, 24, 10, 0, 0),
|
||||||
|
format: 'short',
|
||||||
|
editable: this.isEditable,
|
||||||
|
multivalued: true
|
||||||
|
}),
|
||||||
new CardViewBoolItemModel({
|
new CardViewBoolItemModel({
|
||||||
label: 'CardView Boolean Item',
|
label: 'CardView Boolean Item',
|
||||||
value: true,
|
value: true,
|
||||||
@ -162,6 +180,15 @@ export class CardViewComponent implements OnInit, OnDestroy {
|
|||||||
editable: this.isEditable,
|
editable: this.isEditable,
|
||||||
pipes: [{ pipe: this.decimalNumberPipe }]
|
pipes: [{ pipe: this.decimalNumberPipe }]
|
||||||
}),
|
}),
|
||||||
|
new CardViewFloatItemModel({
|
||||||
|
label: 'CardView Float Item - Multivalue (chips)',
|
||||||
|
value: [9.9],
|
||||||
|
key: 'float',
|
||||||
|
default: 0.0,
|
||||||
|
editable: this.isEditable,
|
||||||
|
multivalued: true,
|
||||||
|
pipes: [{ pipe: this.decimalNumberPipe }]
|
||||||
|
}),
|
||||||
new CardViewKeyValuePairsItemModel({
|
new CardViewKeyValuePairsItemModel({
|
||||||
label: 'CardView Key-Value Pairs Item',
|
label: 'CardView Key-Value Pairs Item',
|
||||||
value: [{ name: 'hey', value: 'you' }, { name: 'hey', value: 'you' }],
|
value: [{ name: 'hey', value: 'you' }, { name: 'hey', value: 'you' }],
|
||||||
|
@ -25,9 +25,9 @@ export class MetadataViewPage {
|
|||||||
aspectTitle: Locator = by.css(`mat-panel-title`);
|
aspectTitle: Locator = by.css(`mat-panel-title`);
|
||||||
name = element(by.css(`[data-automation-id='card-textitem-value-properties.cm:name']`));
|
name = element(by.css(`[data-automation-id='card-textitem-value-properties.cm:name']`));
|
||||||
creator = element(by.css(`[data-automation-id='card-textitem-value-createdByUser.displayName']`));
|
creator = element(by.css(`[data-automation-id='card-textitem-value-createdByUser.displayName']`));
|
||||||
createdDate = element(by.css(`span[data-automation-id='card-dateitem-createdAt'] span`));
|
createdDate = element(by.css(`span[data-automation-id='card-dateitem-createdAt']`));
|
||||||
modifier = element(by.css(`[data-automation-id='card-textitem-value-modifiedByUser.displayName']`));
|
modifier = element(by.css(`[data-automation-id='card-textitem-value-modifiedByUser.displayName']`));
|
||||||
modifiedDate = element(by.css(`span[data-automation-id='card-dateitem-modifiedAt'] span`));
|
modifiedDate = element(by.css(`span[data-automation-id='card-dateitem-modifiedAt']`));
|
||||||
mimetypeName = element(by.css(`[data-automation-id='card-textitem-value-content.mimeTypeName']`));
|
mimetypeName = element(by.css(`[data-automation-id='card-textitem-value-content.mimeTypeName']`));
|
||||||
size = element(by.css(`[data-automation-id='card-textitem-value-content.sizeInBytes']`));
|
size = element(by.css(`[data-automation-id='card-textitem-value-content.sizeInBytes']`));
|
||||||
description = element(by.css(`span[data-automation-id='card-textitem-value-properties.cm:description']`));
|
description = element(by.css(`span[data-automation-id='card-textitem-value-properties.cm:description']`));
|
||||||
|
@ -35,7 +35,7 @@ export class TaskDetailsPage {
|
|||||||
parentTaskIdField = element(by.css('[data-automation-id="card-textitem-value-parentTaskId"] '));
|
parentTaskIdField = element(by.css('[data-automation-id="card-textitem-value-parentTaskId"] '));
|
||||||
durationField = element(by.css('[data-automation-id="card-textitem-value-duration"] '));
|
durationField = element(by.css('[data-automation-id="card-textitem-value-duration"] '));
|
||||||
endDateField = element.all(by.css('span[data-automation-id*="endDate"] span')).first();
|
endDateField = element.all(by.css('span[data-automation-id*="endDate"] span')).first();
|
||||||
createdField = element(by.css('span[data-automation-id="card-dateitem-created"] span'));
|
createdField = element(by.css('span[data-automation-id="card-dateitem-created"]'));
|
||||||
idField = element.all(by.css('[data-automation-id="card-textitem-value-id"]')).first();
|
idField = element.all(by.css('[data-automation-id="card-textitem-value-id"]')).first();
|
||||||
descriptionField = element(by.css('[data-automation-id="card-textitem-value-description"]'));
|
descriptionField = element(by.css('[data-automation-id="card-textitem-value-description"]'));
|
||||||
dueDateField = element.all(by.css('span[data-automation-id*="dueDate"] span')).first();
|
dueDateField = element.all(by.css('span[data-automation-id*="dueDate"] span')).first();
|
||||||
|
@ -119,7 +119,7 @@ export class PropertyGroupTranslatorService {
|
|||||||
|
|
||||||
if (this.isListOfValues(propertyDefinition.constraints)) {
|
if (this.isListOfValues(propertyDefinition.constraints)) {
|
||||||
const options = propertyDefinition.constraints[0].parameters.allowedValues.map((value) => ({ key: value, label: value }));
|
const options = propertyDefinition.constraints[0].parameters.allowedValues.map((value) => ({ key: value, label: value }));
|
||||||
const properties = Object.assign(propertyDefinition, { options$: of(options) });
|
const properties = Object.assign(propertyDefinition, { options$: of(options) });
|
||||||
|
|
||||||
cardViewItemProperty = new CardViewSelectItemModel(properties);
|
cardViewItemProperty = new CardViewSelectItemModel(properties);
|
||||||
} else {
|
} else {
|
||||||
@ -132,22 +132,35 @@ export class PropertyGroupTranslatorService {
|
|||||||
|
|
||||||
case D_INT:
|
case D_INT:
|
||||||
case D_LONG:
|
case D_LONG:
|
||||||
cardViewItemProperty = new CardViewIntItemModel(propertyDefinition);
|
cardViewItemProperty = new CardViewIntItemModel(Object.assign(propertyDefinition, {
|
||||||
|
multivalued: isMultiValued,
|
||||||
|
pipes: [{ pipe: this.multiValuePipe, params: [this.valueSeparator] }]
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_FLOAT:
|
case D_FLOAT:
|
||||||
case D_DOUBLE:
|
case D_DOUBLE:
|
||||||
cardViewItemProperty = new CardViewFloatItemModel(Object.assign(propertyDefinition, {
|
cardViewItemProperty = new CardViewFloatItemModel(Object.assign(propertyDefinition, {
|
||||||
pipes: [{ pipe: this.decimalNumberPipe }]
|
multivalued: isMultiValued,
|
||||||
|
pipes: [
|
||||||
|
{ pipe: this.decimalNumberPipe },
|
||||||
|
{ pipe: this.multiValuePipe, params: [this.valueSeparator] }
|
||||||
|
]
|
||||||
}));
|
}));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_DATE:
|
case D_DATE:
|
||||||
cardViewItemProperty = new CardViewDateItemModel(propertyDefinition);
|
cardViewItemProperty = new CardViewDateItemModel(Object.assign(propertyDefinition, {
|
||||||
|
multivalued: isMultiValued,
|
||||||
|
pipes: [{ pipe: this.multiValuePipe, params: [this.valueSeparator] }]
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_DATETIME:
|
case D_DATETIME:
|
||||||
cardViewItemProperty = new CardViewDatetimeItemModel(propertyDefinition);
|
cardViewItemProperty = new CardViewDatetimeItemModel(Object.assign(propertyDefinition, {
|
||||||
|
multivalued: isMultiValued,
|
||||||
|
pipes: [{ pipe: this.multiValuePipe, params: [this.valueSeparator] }]
|
||||||
|
}));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_BOOLEAN:
|
case D_BOOLEAN:
|
||||||
@ -159,7 +172,7 @@ export class PropertyGroupTranslatorService {
|
|||||||
cardViewItemProperty = new CardViewTextItemModel(Object.assign(propertyDefinition, {
|
cardViewItemProperty = new CardViewTextItemModel(Object.assign(propertyDefinition, {
|
||||||
multivalued: isMultiValued,
|
multivalued: isMultiValued,
|
||||||
multiline: isMultiValued,
|
multiline: isMultiValued,
|
||||||
pipes: [{ pipe: this.multiValuePipe, params: [this.valueSeparator]}]
|
pipes: [{ pipe: this.multiValuePipe, params: [this.valueSeparator] }]
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,23 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="adf-property-value adf-property-value-padding-top">
|
<div class="adf-property-value adf-property-value-padding-top">
|
||||||
<span *ngIf="!isEditable()"
|
<span *ngIf="!isEditable() && !property.multivalued"
|
||||||
[attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">
|
[attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">
|
||||||
<span [attr.data-automation-id]="'card-dateitem-' + property.key">
|
<span *ngIf="showProperty()"
|
||||||
<span *ngIf="showProperty()"
|
[attr.data-automation-id]="'card-dateitem-' + property.key"
|
||||||
(dblclick)="copyToClipboard(property.displayValue)"
|
(dblclick)="copyToClipboard(property.displayValue)"
|
||||||
matTooltipShowDelay="1000"
|
matTooltipShowDelay="1000"
|
||||||
[matTooltip]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate">{{ property.displayValue }}</span>
|
[matTooltip]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate">{{ property.displayValue}}</span>
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
<div *ngIf="isEditable()"
|
<div *ngIf="isEditable() && !property.multivalued"
|
||||||
class="adf-dateitem-editable">
|
class="adf-dateitem-editable">
|
||||||
<div class="adf-dateitem-editable-controls">
|
<div class="adf-dateitem-editable-controls">
|
||||||
<span class="adf-datepicker-toggle"
|
<span class="adf-datepicker-toggle"
|
||||||
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
|
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
|
||||||
(click)="showDatePicker()">
|
(click)="showDatePicker()">
|
||||||
<span *ngIf="showProperty(); else elseEmptyValueBlock"
|
<span *ngIf="showProperty(); else elseEmptyValueBlock"
|
||||||
[attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">{{ property.displayValue }}</span>
|
[attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">
|
||||||
|
{{ property.displayValue }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<mat-icon *ngIf="showClearAction()"
|
<mat-icon *ngIf="showClearAction()"
|
||||||
@ -55,4 +55,42 @@
|
|||||||
<ng-template #elseEmptyValueBlock>
|
<ng-template #elseEmptyValueBlock>
|
||||||
{{ property.default | translate }}
|
{{ property.default | translate }}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
<div *ngIf="property.multivalued"
|
||||||
|
class="adf-property-field adf-dateitem-chip-list-container adf-dateitem-editable">
|
||||||
|
<mat-chip-list #chipList
|
||||||
|
class="adf-textitem-chip-list">
|
||||||
|
<mat-chip *ngFor="let propertyValue of property.displayValue let idx = index"
|
||||||
|
[removable]="isEditable"
|
||||||
|
(removed)="removeValueFromList(idx)">
|
||||||
|
{{ propertyValue }}
|
||||||
|
<mat-icon *ngIf="isEditable()"
|
||||||
|
matChipRemove>cancel</mat-icon>
|
||||||
|
</mat-chip>
|
||||||
|
</mat-chip-list>
|
||||||
|
|
||||||
|
<mat-form-field *ngIf="isEditable()"
|
||||||
|
class="adf-property-field adf-dateitem-editable-controls"
|
||||||
|
[floatLabel]="'never'"
|
||||||
|
(click)="showDatePicker()">
|
||||||
|
<input matInput
|
||||||
|
class="adf-invisible-date-input"
|
||||||
|
[attr.tabIndex]="-1"
|
||||||
|
[matDatetimepicker]="datetimePicker"
|
||||||
|
(dateChange)="addDateToList($event)">
|
||||||
|
<mat-datetimepicker-toggle [attr.tabindex]="-1"
|
||||||
|
matSuffix
|
||||||
|
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||||
|
[attr.data-automation-id]="'datepickertoggle-' + property.key"
|
||||||
|
[for]="datetimePicker">
|
||||||
|
</mat-datetimepicker-toggle>
|
||||||
|
|
||||||
|
<mat-datetimepicker #datetimePicker
|
||||||
|
[type]="property.type"
|
||||||
|
timeInterval="5"
|
||||||
|
[attr.data-automation-id]="'datepicker-' + property.key"
|
||||||
|
[startAt]="valueDate">
|
||||||
|
</mat-datetimepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,22 @@
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-dateitem-chip-list-container.adf-property-field {
|
||||||
|
margin-bottom: -7px !important;
|
||||||
|
border-bottom: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.adf-dateitem-editable-controls {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-datetimepicker-toggle {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: -20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-dateitem-editable {
|
&-dateitem-editable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-bottom: 1px solid mat-color($foreground, text, 0.42);
|
border-bottom: 1px solid mat-color($foreground, text, 0.42);
|
||||||
@ -53,6 +69,7 @@
|
|||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover mat-icon.adf-date-reset-icon {
|
&:hover mat-icon.adf-date-reset-icon {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import { CardViewDateItemComponent } from './card-view-dateitem.component';
|
|||||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||||
import { ClipboardService } from '../../../clipboard/clipboard.service';
|
import { ClipboardService } from '../../../clipboard/clipboard.service';
|
||||||
import { AppConfigService } from '@alfresco/adf-core';
|
import { AppConfigService } from '@alfresco/adf-core';
|
||||||
|
import { CardViewDatetimeItemModel } from './../../models/card-view-datetimeitem.model';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
describe('CardViewDateItemComponent', () => {
|
describe('CardViewDateItemComponent', () => {
|
||||||
@ -192,7 +193,7 @@ describe('CardViewDateItemComponent', () => {
|
|||||||
component.editable = true;
|
component.editable = true;
|
||||||
component.property.editable = true;
|
component.property.editable = true;
|
||||||
const cardViewUpdateService = TestBed.inject(CardViewUpdateService);
|
const cardViewUpdateService = TestBed.inject(CardViewUpdateService);
|
||||||
const expectedDate = moment('Jul 10 2017', 'MMM DD YY');
|
const expectedDate = moment('Jul 10 2017', 'MMM DD YYYY');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const property = { ...component.property };
|
const property = { ...component.property };
|
||||||
|
|
||||||
@ -231,7 +232,7 @@ describe('CardViewDateItemComponent', () => {
|
|||||||
component.editable = false;
|
component.editable = false;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const doubleClickEl = fixture.debugElement.query(By.css(`[data-automation-id="card-dateitem-${component.property.key}"] span`));
|
const doubleClickEl = fixture.debugElement.query(By.css(`[data-automation-id="card-dateitem-${component.property.key}"]`));
|
||||||
doubleClickEl.triggerEventHandler('dblclick', new MouseEvent('dblclick'));
|
doubleClickEl.triggerEventHandler('dblclick', new MouseEvent('dblclick'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -346,4 +347,42 @@ describe('CardViewDateItemComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.property.value).toEqual(expectedDate.toDate());
|
expect(component.property.value).toEqual(expectedDate.toDate());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render chips for multivalue dates when chips are enabled', async () => {
|
||||||
|
component.property = new CardViewDateItemModel({
|
||||||
|
label: 'Text label',
|
||||||
|
value: ['Jul 10 2017 00:01:00', 'Jul 11 2017 00:01:00', 'Jul 12 2017 00:01:00'],
|
||||||
|
key: 'textkey',
|
||||||
|
editable: true,
|
||||||
|
multivalued: true
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const valueChips = fixture.debugElement.queryAll(By.css(`mat-chip`));
|
||||||
|
expect(valueChips).not.toBeNull();
|
||||||
|
expect(valueChips.length).toBe(3);
|
||||||
|
expect(valueChips[0].nativeElement.innerText.trim()).toBe('Jul 10, 2017');
|
||||||
|
expect(valueChips[1].nativeElement.innerText.trim()).toBe('Jul 11, 2017');
|
||||||
|
expect(valueChips[2].nativeElement.innerText.trim()).toBe('Jul 12, 2017');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render chips for multivalue datetimes when chips are enabled', async () => {
|
||||||
|
component.property = new CardViewDatetimeItemModel({
|
||||||
|
label: 'Text label',
|
||||||
|
value: ['Jul 10 2017 00:01:00', 'Jul 11 2017 00:01:00', 'Jul 12 2017 00:01:00'],
|
||||||
|
key: 'textkey',
|
||||||
|
editable: true,
|
||||||
|
multivalued: true
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const valueChips = fixture.debugElement.queryAll(By.css(`mat-chip`));
|
||||||
|
expect(valueChips).not.toBeNull();
|
||||||
|
expect(valueChips.length).toBe(3);
|
||||||
|
expect(valueChips[0].nativeElement.innerText.trim()).toBe('Jul 10, 2017, 0:01');
|
||||||
|
expect(valueChips[1].nativeElement.innerText.trim()).toBe('Jul 11, 2017, 0:01');
|
||||||
|
expect(valueChips[2].nativeElement.innerText.trim()).toBe('Jul 12, 2017, 0:01');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -89,6 +89,8 @@ export class CardViewDateItemComponent extends BaseCardView<CardViewDateItemMode
|
|||||||
|
|
||||||
if (this.property.value) {
|
if (this.property.value) {
|
||||||
this.valueDate = moment(this.property.value, this.dateFormat);
|
this.valueDate = moment(this.property.value, this.dateFormat);
|
||||||
|
} else if (this.property.multivalued && !this.property.value) {
|
||||||
|
this.property.value = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,8 +120,8 @@ export class CardViewDateItemComponent extends BaseCardView<CardViewDateItemMode
|
|||||||
const momentDate = moment(newDateValue.value, this.dateFormat, true);
|
const momentDate = moment(newDateValue.value, this.dateFormat, true);
|
||||||
if (momentDate.isValid()) {
|
if (momentDate.isValid()) {
|
||||||
this.valueDate = momentDate;
|
this.valueDate = momentDate;
|
||||||
this.cardViewUpdateService.update(<CardViewDateItemModel> { ...this.property }, momentDate.toDate());
|
|
||||||
this.property.value = momentDate.toDate();
|
this.property.value = momentDate.toDate();
|
||||||
|
this.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,4 +137,24 @@ export class CardViewDateItemComponent extends BaseCardView<CardViewDateItemMode
|
|||||||
const clipboardMessage = this.translateService.instant('CORE.METADATA.ACCESSIBILITY.COPY_TO_CLIPBOARD_MESSAGE');
|
const clipboardMessage = this.translateService.instant('CORE.METADATA.ACCESSIBILITY.COPY_TO_CLIPBOARD_MESSAGE');
|
||||||
this.clipboardService.copyContentToClipboard(valueToCopy, clipboardMessage);
|
this.clipboardService.copyContentToClipboard(valueToCopy, clipboardMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addDateToList(newDateValue) {
|
||||||
|
if (newDateValue) {
|
||||||
|
const momentDate = moment(newDateValue.value, this.dateFormat, true);
|
||||||
|
if (momentDate.isValid()) {
|
||||||
|
this.property.value.push(momentDate.toDate());
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeValueFromList(itemIndex: number) {
|
||||||
|
this.property.value.splice(itemIndex, 1);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.cardViewUpdateService.update(<CardViewDateItemModel> { ...this.property }, this.property.value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
[floatLabel]="'never'">
|
[floatLabel]="'never'">
|
||||||
<input matInput
|
<input matInput
|
||||||
class="adf-property-value"
|
class="adf-property-value"
|
||||||
[placeholder]="property.default | translate"
|
[placeholder]="editedValue ? '' : property.default | translate"
|
||||||
[matChipInputFor]="chipList"
|
[matChipInputFor]="chipList"
|
||||||
[matChipInputAddOnBlur]="true"
|
[matChipInputAddOnBlur]="true"
|
||||||
(matChipInputTokenEnd)="addValueToList($event)"
|
(matChipInputTokenEnd)="addValueToList($event)"
|
||||||
|
@ -180,7 +180,48 @@ describe('CardViewTextItemComponent', () => {
|
|||||||
expect(valueChips[0].nativeElement.innerText.trim()).toBe('item1');
|
expect(valueChips[0].nativeElement.innerText.trim()).toBe('item1');
|
||||||
expect(valueChips[1].nativeElement.innerText.trim()).toBe('item2');
|
expect(valueChips[1].nativeElement.innerText.trim()).toBe('item2');
|
||||||
expect(valueChips[2].nativeElement.innerText.trim()).toBe('item3');
|
expect(valueChips[2].nativeElement.innerText.trim()).toBe('item3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render chips for multivalue integers when chips are enabled', async () => {
|
||||||
|
component.property = new CardViewIntItemModel({
|
||||||
|
label: 'Text label',
|
||||||
|
value: [1, 2, 3],
|
||||||
|
key: 'textkey',
|
||||||
|
editable: true,
|
||||||
|
multivalued: true
|
||||||
|
});
|
||||||
|
component.useChipsForMultiValueProperty = true;
|
||||||
|
component.ngOnChanges({ property: new SimpleChange(null, null, true) });
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const valueChips = fixture.debugElement.queryAll(By.css(`mat-chip`));
|
||||||
|
expect(valueChips).not.toBeNull();
|
||||||
|
expect(valueChips.length).toBe(3);
|
||||||
|
expect(valueChips[0].nativeElement.innerText.trim()).toBe('1');
|
||||||
|
expect(valueChips[1].nativeElement.innerText.trim()).toBe('2');
|
||||||
|
expect(valueChips[2].nativeElement.innerText.trim()).toBe('3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render chips for multivalue decimal numbers when chips are enabled', async () => {
|
||||||
|
component.property = new CardViewFloatItemModel({
|
||||||
|
label: 'Text label',
|
||||||
|
value: [1.1, 2.2, 3.3],
|
||||||
|
key: 'textkey',
|
||||||
|
editable: true,
|
||||||
|
multivalued: true
|
||||||
|
});
|
||||||
|
component.useChipsForMultiValueProperty = true;
|
||||||
|
component.ngOnChanges({ property: new SimpleChange(null, null, true) });
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await fixture.whenStable();
|
||||||
|
const valueChips = fixture.debugElement.queryAll(By.css(`mat-chip`));
|
||||||
|
expect(valueChips).not.toBeNull();
|
||||||
|
expect(valueChips.length).toBe(3);
|
||||||
|
expect(valueChips[0].nativeElement.innerText.trim()).toBe('1.1');
|
||||||
|
expect(valueChips[1].nativeElement.innerText.trim()).toBe('2.2');
|
||||||
|
expect(valueChips[2].nativeElement.innerText.trim()).toBe('3.3');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render string for multivalue properties when chips are disabled', async () => {
|
it('should render string for multivalue properties when chips are disabled', async () => {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
import { ChangeDetectorRef, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||||
import { CardViewTextItemModel } from '../../models/card-view-textitem.model';
|
import { CardViewTextItemModel } from '../../models/card-view-textitem.model';
|
||||||
import { CardViewUpdateService } from '../../services/card-view-update.service';
|
import { CardViewUpdateService } from '../../services/card-view-update.service';
|
||||||
import { BaseCardView } from '../base-card-view';
|
import { BaseCardView } from '../base-card-view';
|
||||||
@ -68,7 +68,8 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
|||||||
|
|
||||||
constructor(cardViewUpdateService: CardViewUpdateService,
|
constructor(cardViewUpdateService: CardViewUpdateService,
|
||||||
private clipboardService: ClipboardService,
|
private clipboardService: ClipboardService,
|
||||||
private translateService: TranslationService) {
|
private translateService: TranslationService,
|
||||||
|
private cd: ChangeDetectorRef) {
|
||||||
super(cardViewUpdateService);
|
super(cardViewUpdateService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
|||||||
if (changes.property && changes.property.firstChange) {
|
if (changes.property && changes.property.firstChange) {
|
||||||
this.textInput.valueChanges
|
this.textInput.valueChanges
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(textInputValue => textInputValue !== this.editedValue),
|
filter(textInputValue => textInputValue !== this.editedValue && textInputValue !== null),
|
||||||
debounceTime(50),
|
debounceTime(50),
|
||||||
takeUntil(this.onDestroy$)
|
takeUntil(this.onDestroy$)
|
||||||
)
|
)
|
||||||
@ -125,9 +126,8 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
|||||||
|
|
||||||
update(): void {
|
update(): void {
|
||||||
if (this.property.isValid(this.editedValue)) {
|
if (this.property.isValid(this.editedValue)) {
|
||||||
const updatedValue = this.prepareValueForUpload(this.property, this.editedValue);
|
this.property.value = this.prepareValueForUpload(this.property, this.editedValue);
|
||||||
this.cardViewUpdateService.update(<CardViewTextItemModel> { ...this.property }, updatedValue);
|
this.cardViewUpdateService.update(<CardViewTextItemModel> { ...this.property }, this.property.value);
|
||||||
this.property.value = updatedValue;
|
|
||||||
this.resetErrorMessages();
|
this.resetErrorMessages();
|
||||||
} else {
|
} else {
|
||||||
this.errors = this.property.getValidationErrors(this.editedValue);
|
this.errors = this.property.getValidationErrors(this.editedValue);
|
||||||
@ -143,9 +143,10 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeValueFromList(itemIndex: number) {
|
removeValueFromList(itemIndex: number) {
|
||||||
if (typeof this.editedValue !== 'string') {
|
if (Array.isArray(this.editedValue)) {
|
||||||
this.editedValue.splice(itemIndex, 1);
|
this.editedValue.splice(itemIndex, 1);
|
||||||
this.update();
|
this.update();
|
||||||
|
this.cd.detectChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,4 +29,5 @@ export interface CardViewItemProperties {
|
|||||||
validators?: CardViewItemValidator[];
|
validators?: CardViewItemValidator[];
|
||||||
data?: any;
|
data?: any;
|
||||||
constraints?: Constraint[];
|
constraints?: Constraint[];
|
||||||
|
multivalued?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ export abstract class CardViewBaseItemModel {
|
|||||||
validators?: CardViewItemValidator[];
|
validators?: CardViewItemValidator[];
|
||||||
data?: any;
|
data?: any;
|
||||||
type?: string;
|
type?: string;
|
||||||
|
multivalued?: boolean;
|
||||||
|
|
||||||
constructor(cardViewItemProperties: CardViewItemProperties) {
|
constructor(cardViewItemProperties: CardViewItemProperties) {
|
||||||
this.label = cardViewItemProperties.label || '';
|
this.label = cardViewItemProperties.label || '';
|
||||||
@ -40,6 +41,7 @@ export abstract class CardViewBaseItemModel {
|
|||||||
this.icon = cardViewItemProperties.icon || '';
|
this.icon = cardViewItemProperties.icon || '';
|
||||||
this.validators = cardViewItemProperties.validators || [];
|
this.validators = cardViewItemProperties.validators || [];
|
||||||
this.data = cardViewItemProperties.data || null;
|
this.data = cardViewItemProperties.data || null;
|
||||||
|
this.multivalued = !!cardViewItemProperties.multivalued;
|
||||||
|
|
||||||
if (cardViewItemProperties?.constraints?.length ?? 0) {
|
if (cardViewItemProperties?.constraints?.length ?? 0) {
|
||||||
for (const constraint of cardViewItemProperties.constraints) {
|
for (const constraint of cardViewItemProperties.constraints) {
|
||||||
@ -51,7 +53,7 @@ export abstract class CardViewBaseItemModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isEmpty(): boolean {
|
isEmpty(): boolean {
|
||||||
return this.value === undefined || this.value === null || this.value === '';
|
return this.value === undefined || this.value === null || this.value.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid(newValue: any): boolean {
|
isValid(newValue: any): boolean {
|
||||||
|
@ -42,11 +42,19 @@ export class CardViewDateItemModel extends CardViewBaseItemModel implements Card
|
|||||||
}
|
}
|
||||||
|
|
||||||
get displayValue() {
|
get displayValue() {
|
||||||
if (!this.value) {
|
if (this.multivalued) {
|
||||||
return this.default;
|
if (this.value) {
|
||||||
|
return this.value.map((date) => this.transformDate(date));
|
||||||
|
} else {
|
||||||
|
return this.default ? [this.default] : [];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.localizedDatePipe = new LocalizedDatePipe();
|
return this.value ? this.transformDate(this.value) : this.default;
|
||||||
return this.localizedDatePipe.transform(this.value, this.format, this.locale);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transformDate(value: any) {
|
||||||
|
this.localizedDatePipe = new LocalizedDatePipe();
|
||||||
|
return this.localizedDatePipe.transform(value, this.format, this.locale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,12 @@ export class CardViewFloatItemModel extends CardViewTextItemModel implements Car
|
|||||||
super(cardViewTextItemProperties);
|
super(cardViewTextItemProperties);
|
||||||
|
|
||||||
this.validators.push(new CardViewItemFloatValidator());
|
this.validators.push(new CardViewItemFloatValidator());
|
||||||
if (cardViewTextItemProperties.value) {
|
if (cardViewTextItemProperties.value && !cardViewTextItemProperties.multivalued) {
|
||||||
this.value = parseFloat(cardViewTextItemProperties.value);
|
this.value = parseFloat(cardViewTextItemProperties.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get displayValue(): string {
|
||||||
|
return this.applyPipes(this.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,12 @@ export class CardViewIntItemModel extends CardViewTextItemModel implements CardV
|
|||||||
super(cardViewTextItemProperties);
|
super(cardViewTextItemProperties);
|
||||||
|
|
||||||
this.validators.push(new CardViewItemIntValidator());
|
this.validators.push(new CardViewItemIntValidator());
|
||||||
if (cardViewTextItemProperties.value) {
|
if (cardViewTextItemProperties.value && !cardViewTextItemProperties.multivalued) {
|
||||||
this.value = parseInt(cardViewTextItemProperties.value, 10);
|
this.value = parseInt(cardViewTextItemProperties.value, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get displayValue(): string {
|
||||||
|
return this.applyPipes(this.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,12 @@ export class CardViewTextItemModel extends CardViewBaseItemModel implements Card
|
|||||||
type: string = 'text';
|
type: string = 'text';
|
||||||
inputType: string = 'text';
|
inputType: string = 'text';
|
||||||
multiline?: boolean;
|
multiline?: boolean;
|
||||||
multivalued?: boolean;
|
|
||||||
pipes?: CardViewTextItemPipeProperty[];
|
pipes?: CardViewTextItemPipeProperty[];
|
||||||
clickCallBack?: any;
|
clickCallBack?: any;
|
||||||
|
|
||||||
constructor(cardViewTextItemProperties: CardViewTextItemProperties) {
|
constructor(cardViewTextItemProperties: CardViewTextItemProperties) {
|
||||||
super(cardViewTextItemProperties);
|
super(cardViewTextItemProperties);
|
||||||
this.multiline = !!cardViewTextItemProperties.multiline;
|
this.multiline = !!cardViewTextItemProperties.multiline;
|
||||||
this.multivalued = !!cardViewTextItemProperties.multivalued;
|
|
||||||
this.pipes = cardViewTextItemProperties.pipes || [];
|
this.pipes = cardViewTextItemProperties.pipes || [];
|
||||||
this.clickCallBack = cardViewTextItemProperties.clickCallBack ? cardViewTextItemProperties.clickCallBack : null;
|
this.clickCallBack = cardViewTextItemProperties.clickCallBack ? cardViewTextItemProperties.clickCallBack : null;
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ export class CardViewTextItemModel extends CardViewBaseItemModel implements Card
|
|||||||
return this.applyPipes(this.value);
|
return this.applyPipes(this.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private applyPipes(displayValue) {
|
applyPipes(displayValue) {
|
||||||
if (this.pipes.length) {
|
if (this.pipes.length) {
|
||||||
displayValue = this.pipes.reduce((accumulator, { pipe, params = [] }) => {
|
displayValue = this.pipes.reduce((accumulator, { pipe, params = [] }) => {
|
||||||
return pipe.transform(accumulator, ...params);
|
return pipe.transform(accumulator, ...params);
|
||||||
|
@ -22,8 +22,13 @@ export class CardViewItemFloatValidator implements CardViewItemValidator {
|
|||||||
message = 'CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR';
|
message = 'CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR';
|
||||||
|
|
||||||
isValid(value: any): boolean {
|
isValid(value: any): boolean {
|
||||||
return value === ''
|
if (Array.isArray(value)) {
|
||||||
|| !isNaN(parseFloat(value))
|
return value.every(this.isDecimalNumber);
|
||||||
&& isFinite(value);
|
}
|
||||||
|
return value === '' || this.isDecimalNumber(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
isDecimalNumber(value: any): boolean {
|
||||||
|
return !isNaN(parseFloat(value)) && isFinite(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,15 @@ export class CardViewItemIntValidator implements CardViewItemValidator {
|
|||||||
message = 'CORE.CARDVIEW.VALIDATORS.INT_VALIDATION_ERROR';
|
message = 'CORE.CARDVIEW.VALIDATORS.INT_VALIDATION_ERROR';
|
||||||
|
|
||||||
isValid(value: any): boolean {
|
isValid(value: any): boolean {
|
||||||
return value === ''
|
if (Array.isArray(value)) {
|
||||||
|| !isNaN(value)
|
return value.every(this.isIntegerNumber);
|
||||||
&& this.isIntegerNumber(value);
|
}
|
||||||
|
|
||||||
|
return value === '' || !isNaN(value) && this.isIntegerNumber(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
isIntegerNumber(value: any): boolean {
|
isIntegerNumber(value: any): boolean {
|
||||||
const parsedNumber = parseFloat(value);
|
const parsedNumber = Number(value);
|
||||||
return (parsedNumber | 0) === parsedNumber;
|
return (parsedNumber | 0) === parsedNumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,8 @@ export class DecimalNumberPipe implements PipeTransform, OnDestroy {
|
|||||||
const actualDigitsInfo = `${actualMinIntegerDigits}.${actualMinFractionDigits}-${actualMaxFractionDigits}`;
|
const actualDigitsInfo = `${actualMinIntegerDigits}.${actualMinFractionDigits}-${actualMaxFractionDigits}`;
|
||||||
const actualLocale = locale || this.defaultLocale;
|
const actualLocale = locale || this.defaultLocale;
|
||||||
|
|
||||||
const datePipe: DecimalPipe = new DecimalPipe(actualLocale);
|
const decimalPipe: DecimalPipe = new DecimalPipe(actualLocale);
|
||||||
return datePipe.transform(value, actualDigitsInfo);
|
return decimalPipe.transform(value, actualDigitsInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -36,11 +36,16 @@ describe('FullNamePipe', () => {
|
|||||||
pipe = TestBed.inject(MultiValuePipe);
|
pipe = TestBed.inject(MultiValuePipe);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add the separator when a list is provided', () => {
|
it('should add the separator when a string list is provided', () => {
|
||||||
const values = ['cat', 'house', 'dog'];
|
const values = ['cat', 'house', 'dog'];
|
||||||
expect(pipe.transform(values)).toBe('cat, house, dog');
|
expect(pipe.transform(values)).toBe('cat, house, dog');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should add the separator when a number list is provided', () => {
|
||||||
|
const values = [1, 2, 3];
|
||||||
|
expect(pipe.transform(values)).toBe('1, 2, 3');
|
||||||
|
});
|
||||||
|
|
||||||
it('should add custom separator when set', () => {
|
it('should add custom separator when set', () => {
|
||||||
const values = ['cat', 'house', 'dog'];
|
const values = ['cat', 'house', 'dog'];
|
||||||
const customSeparator = ' - ';
|
const customSeparator = ' - ';
|
||||||
|
@ -22,13 +22,12 @@ export class MultiValuePipe implements PipeTransform {
|
|||||||
|
|
||||||
static DEFAULT_SEPARATOR = ', ';
|
static DEFAULT_SEPARATOR = ', ';
|
||||||
|
|
||||||
transform(values: string | string [], valueSeparator: string = MultiValuePipe.DEFAULT_SEPARATOR): string {
|
transform(values: any | any[], valueSeparator: string = MultiValuePipe.DEFAULT_SEPARATOR): string {
|
||||||
|
|
||||||
if (values && values instanceof Array) {
|
if (values && values instanceof Array) {
|
||||||
const valueList = values.map((value) => value.trim());
|
return values.join(valueSeparator);
|
||||||
return valueList.join(valueSeparator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <string> values;
|
return values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export class TaskHeaderCloudPage {
|
|||||||
priorityCardSelectItem = new CardSelectItemPage('priority');
|
priorityCardSelectItem = new CardSelectItemPage('priority');
|
||||||
dueDateField = element.all(by.css('span[data-automation-id*="dueDate"] span')).first();
|
dueDateField = element.all(by.css('span[data-automation-id*="dueDate"] span')).first();
|
||||||
categoryCardTextItem = new CardTextItemPage('category');
|
categoryCardTextItem = new CardTextItemPage('category');
|
||||||
createdField = element(by.css('span[data-automation-id="card-dateitem-created"] span'));
|
createdField = element(by.css('span[data-automation-id="card-dateitem-created"]'));
|
||||||
parentNameCardTextItem = new CardTextItemPage('parentName');
|
parentNameCardTextItem = new CardTextItemPage('parentName');
|
||||||
parentTaskIdCardTextItem = new CardTextItemPage('parentTaskId');
|
parentTaskIdCardTextItem = new CardTextItemPage('parentTaskId');
|
||||||
endDateField = element.all(by.css('span[data-automation-id*="endDate"] span')).first();
|
endDateField = element.all(by.css('span[data-automation-id*="endDate"] span')).first();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user