[ADF-1698] Task Info Drawer should be localizable (#2495)

* Card component should provide the localization

* Fix unit test
This commit is contained in:
Maurizio Vitale 2017-10-18 19:21:18 +01:00 committed by Denys Vuika
parent 0bdd66e158
commit d5cd38b7ee
12 changed files with 276 additions and 48 deletions

View File

@ -80,7 +80,7 @@ describe('TaskHeaderComponent', () => {
component.ngOnChanges({});
fixture.detectChanges();
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-property-value'));
expect(valueEl.nativeElement.innerText).toBe('No assignee');
expect(valueEl.nativeElement.innerText).toBe('TASK_PROPERTIES.ASSIGNEE_DEFAULT');
});
it('should display created-by', () => {
@ -90,14 +90,6 @@ describe('TaskHeaderComponent', () => {
expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams');
});
it('should display placeholder if no created-by', () => {
component.taskDetails.assignee = null;
component.ngOnChanges({});
fixture.detectChanges();
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-created-by"] .adf-property-value'));
expect(valueEl.nativeElement.innerText).toBe('No assignee');
});
it('should set editable to false if the task has already completed', () => {
component.taskDetails.endDate = new Date('05/05/2002');
component.ngOnChanges({});
@ -180,7 +172,7 @@ describe('TaskHeaderComponent', () => {
component.ngOnChanges({});
fixture.detectChanges();
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value'));
expect(valueEl.nativeElement.innerText.trim()).toBe('No date');
expect(valueEl.nativeElement.innerText.trim()).toBe('TASK_PROPERTIES.DUE_DATE_DEFAULT');
});
it('should display form name', () => {
@ -196,7 +188,7 @@ describe('TaskHeaderComponent', () => {
component.ngOnChanges({});
fixture.detectChanges();
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value'));
expect(valueEl.nativeElement.innerText.trim()).toEqual('None');
expect(valueEl.nativeElement.innerText.trim()).toEqual('TASK_PROPERTIES.PARENT_NAME_DEFAULT');
});
it('should display the Parent name value', () => {
@ -212,7 +204,7 @@ describe('TaskHeaderComponent', () => {
component.ngOnChanges({});
fixture.detectChanges();
let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-property-value'));
expect(valueEl.nativeElement.innerText).toBe('No form');
expect(valueEl.nativeElement.innerText).toBe('TASK_PROPERTIES.FORM_NAME_DEFAULT');
});
});

View File

@ -57,23 +57,93 @@ export class TaskHeaderComponent implements OnChanges {
if (this.taskDetails) {
const parentInfoMap = this.getParentInfo();
this.properties = [
new CardViewTextItemModel({ label: 'Assignee', value: this.taskDetails.getFullName(), key: 'assignee', default: 'No assignee', clickable: !this.isCompleted() } ),
new CardViewTextItemModel({ label: 'Status', value: this.getTaskStatus(), key: 'status' }),
new CardViewDateItemModel({ label: 'Due Date', value: this.taskDetails.dueDate, key: 'dueDate', default: 'No date', editable: true }),
new CardViewTextItemModel({ label: 'Category', value: this.taskDetails.category, key: 'category', default: 'No category' }),
new CardViewMapItemModel({ label: 'Parent name', value: parentInfoMap, key: 'parentName', default: 'None', clickable: true }),
new CardViewTextItemModel({ label: 'Created By', value: this.taskDetails.getFullName(), key: 'created-by', default: 'No assignee' }),
new CardViewDateItemModel({ label: 'Created', value: this.taskDetails.created, key: 'created' }),
new CardViewTextItemModel({ label: 'Id', value: this.taskDetails.id, key: 'id' }),
new CardViewTextItemModel({
label: 'Description',
value: this.taskDetails.description,
key: 'description',
default: 'No description',
multiline: true,
editable: true
}),
new CardViewTextItemModel({ label: 'Form name', value: this.formName, key: 'formName', default: 'No form' })
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.ASSIGNEE',
value: this.taskDetails.getFullName(),
key: 'assignee',
default: 'TASK_PROPERTIES.ASSIGNEE_DEFAULT',
clickable: !this.isCompleted()
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.STATUS',
value: this.getTaskStatus(),
key: 'status'
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.PRIORITY',
value: this.taskDetails.priority,
key: 'priority'
}
),
new CardViewDateItemModel(
{
label: 'TASK_PROPERTIES.DUE_DATE',
value: this.taskDetails.dueDate,
key: 'dueDate',
default: 'TASK_PROPERTIES.DUE_DATE_DEFAULT',
editable: true
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.CATEGORY',
value: this.taskDetails.category,
key: 'category',
default: 'TASK_PROPERTIES.CATEGORY_DEFAULT'
}
),
new CardViewMapItemModel(
{
label: 'TASK_PROPERTIES.PARENT_NAME',
value: parentInfoMap, key: 'parentName',
default: 'TASK_PROPERTIES.PARENT_NAME_DEFAULT',
clickable: true
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.CREATED_BY',
value: this.taskDetails.getFullName(),
key: 'created-by'
}
),
new CardViewDateItemModel(
{
label: 'TASK_PROPERTIES.CREATED',
value: this.taskDetails.created,
key: 'created'
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.ID',
value: this.taskDetails.id,
key: 'id'
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.DESCRIPTION',
value: this.taskDetails.description,
key: 'description',
default: 'TASK_PROPERTIES.DESCRIPTION_DEFAULT',
multiline: true,
editable: true
}
),
new CardViewTextItemModel(
{
label: 'TASK_PROPERTIES.FORM_NAME',
value: this.formName,
key: 'formName',
default: 'TASK_PROPERTIES.FORM_NAME_DEFAULT'
}
)
];
}
}

View File

@ -8,6 +8,25 @@
"NONE": "No task lists found"
}
},
"TASK_PROPERTIES": {
"ASSIGNEE": "Assignee",
"ASSIGNEE_DEFAULT": "No assignee",
"PRIORITY": "Priority",
"DUE_DATE": "Due Date",
"DUE_DATE_DEFAULT": "No date",
"STATUS": "Status",
"CATEGORY": "Category",
"CATEGORY_DEFAULT": "No category",
"PARENT_NAME": "Parent name",
"PARENT_NAME_DEFAULT": "No parent",
"CREATED_BY": "Created By",
"CREATED": "Created",
"ID": "Id",
"DESCRIPTION": "Description",
"DESCRIPTION_DEFAULT": "No description",
"FORM_NAME": "Form Name",
"FORM_NAME_DEFAULT": "No form"
},
"TASK_DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Activities",

View File

@ -1,7 +1,9 @@
<div class="adf-property-label">{{ property.label }}</div>
<div class="adf-property-label">{{ property.label | translate }}</div>
<div class="adf-property-value">
<span *ngIf="!isEditable()">
<span [attr.data-automation-id]="'card-dateitem-' + property.key">{{ property.displayValue }}</span>
<span [attr.data-automation-id]="'card-dateitem-' + property.key">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
</span>
<span *ngIf="isEditable()" class="adf-dateitem-editable">
<input class="adf-invisible-date-input" [matDatepicker]="picker" [value]="valueDate"
@ -9,7 +11,8 @@
<span
class="adf-datepicker-toggle"
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
(click)="showDatePicker($event)">{{ property.displayValue }}
(click)="showDatePicker($event)">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
<mat-datepicker-toggle
[attr.data-automation-id]="'datepickertoggle-' + property.key"
@ -21,4 +24,7 @@
[touchUi]="true">
</mat-datepicker>
</span>
<ng-template #elseEmptyValueBlock>
{{ property.default | translate }}
</ng-template>
</div>

View File

@ -88,6 +88,38 @@ describe('CardViewDateItemComponent', () => {
expect(value.nativeElement.innerText.trim()).toBe('Jul 10 2017');
});
it('should render the default as value if the value is empty and editable:false', () => {
component.property = new CardViewDateItemModel ({
label: 'Date label',
value: '',
key: 'datekey',
default: 'FAKE-DEFAULT-KEY',
format: '',
editable: false
});
fixture.detectChanges();
let value = fixture.debugElement.query(By.css('.adf-property-value'));
expect(value).not.toBeNull();
expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY');
});
it('should render the default as value if the value is empty and editable:true', () => {
component.property = new CardViewDateItemModel ({
label: 'Date label',
value: '',
key: 'datekey',
default: 'FAKE-DEFAULT-KEY',
format: '',
editable: true
});
fixture.detectChanges();
let value = fixture.debugElement.query(By.css('.adf-property-value'));
expect(value).not.toBeNull();
expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY');
});
it('should render value when editable:true', () => {
component.editable = true;
component.property.editable = true;

View File

@ -1,9 +1,16 @@
<div class="adf-property-label">{{ property.label }}</div>
<div class="adf-property-label">{{ property.label | translate }}</div>
<div class="adf-property-value">
<div>
<span *ngIf="!isClickable(); else elseBlock" [attr.data-automation-id]="'card-mapitem-value-' + property.key">{{ property.displayValue }}</span>
<span *ngIf="!isClickable(); else elseBlock" [attr.data-automation-id]="'card-mapitem-value-' + property.key">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
<ng-template #elseBlock>
<span class="adf-mapitem-clickable-value" (click)="clicked()" [attr.data-automation-id]="'card-mapitem-value-' + property.key">{{ property.displayValue }}</span>
<span class="adf-mapitem-clickable-value" (click)="clicked()" [attr.data-automation-id]="'card-mapitem-value-' + property.key">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
</ng-template>
</div>
<ng-template #elseEmptyValueBlock>
{{ property.default | translate }}
</ng-template>
</div>

View File

@ -18,11 +18,16 @@
import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { MatDatepickerModule, MatIconModule, MatInputModule, MatNativeDateModule } from '@angular/material';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { CardViewMapItemModel } from '../../models/card-view-mapitem.model';
import { CardViewUpdateService } from '../../services/card-view-update.service';
import { LogService } from '../../services/log.service';
import { AlfrescoTranslateLoader } from '../../services/translate-loader.service';
import { CardViewMapItemComponent } from './card-view-mapitem.component';
describe('CardViewMapItemComponent', () => {
@ -36,18 +41,26 @@ describe('CardViewMapItemComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
HttpModule,
FormsModule,
NoopAnimationsModule,
MatDatepickerModule,
MatIconModule,
MatInputModule,
MatNativeDateModule
MatNativeDateModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: AlfrescoTranslateLoader
}
})
],
declarations: [
CardViewMapItemComponent
],
providers: [
CardViewUpdateService
CardViewUpdateService,
LogService
]
}).compileComponents();
}));

View File

@ -1,14 +1,20 @@
<div class="adf-property-label">{{ property.label }}</div>
<div class="adf-property-label">{{ property.label | translate }}</div>
<div class="adf-property-value">
<span *ngIf="!isEditble()">
<span *ngIf="!isClickable(); else elseBlock" [attr.data-automation-id]="'card-textitem-value-' + property.key">{{ property.displayValue }}</span>
<span *ngIf="!isClickable(); else elseBlock" [attr.data-automation-id]="'card-textitem-value-' + property.key">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
<ng-template #elseBlock>
<span class="adf-textitem-clickable-value" (click)="clicked()" [attr.data-automation-id]="'card-textitem-value-' + property.key">{{ property.displayValue }}</span>
<span class="adf-textitem-clickable-value" (click)="clicked()" [attr.data-automation-id]="'card-textitem-value-' + property.key">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
</ng-template>
</span>
<span *ngIf="isEditble()">
<div *ngIf="!inEdit" (click)="setEditMode(true)" class="adf-textitem-readonly" [attr.data-automation-id]="'card-textitem-edit-toggle-' + property.key">
<span [attr.data-automation-id]="'card-textitem-value-' + property.key">{{ property.displayValue }}</span>
<span [attr.data-automation-id]="'card-textitem-value-' + property.key">
<span *ngIf="!property.isEmpty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span>
<mat-icon [attr.data-automation-id]="'card-textitem-edit-icon-' + property.key" class="adf-textitem-icon">create</mat-icon>
</div>
<div *ngIf="inEdit" class="adf-textitem-editable">
@ -16,7 +22,7 @@
<input *ngIf="!property.multiline" #editorInput
matInput
class="adf-input"
[placeholder]="property.default"
[placeholder]="property.default | translate"
[(ngModel)]="editedValue"
[attr.data-automation-id]="'card-textitem-editinput-' + property.key">
<textarea *ngIf="property.multiline" #editorInput
@ -25,7 +31,7 @@
matAutosizeMaxRows="1"
matAutosizeMaxRows="5"
class="adf-textarea"
[placeholder]="property.default"
[placeholder]="property.default | translate"
[(ngModel)]="editedValue"
[attr.data-automation-id]="'card-textitem-edittextarea-' + property.key"></textarea>
</mat-form-field>
@ -39,4 +45,7 @@
[attr.data-automation-id]="'card-textitem-reset-' + property.key">clear</mat-icon>
</div>
</span>
<ng-template #elseEmptyValueBlock>
{{ property.default | translate }}
</ng-template>
</div>

View File

@ -17,11 +17,16 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { MatDatepickerModule, MatIconModule, MatInputModule, MatNativeDateModule } from '@angular/material';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { CardViewTextItemModel } from '../../models/card-view-textitem.model';
import { CardViewUpdateService } from '../../services/card-view-update.service';
import { LogService } from '../../services/log.service';
import { AlfrescoTranslateLoader } from '../../services/translate-loader.service';
import { CardViewTextItemComponent } from './card-view-textitem.component';
describe('CardViewTextItemComponent', () => {
@ -32,18 +37,26 @@ describe('CardViewTextItemComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
HttpModule,
FormsModule,
NoopAnimationsModule,
MatDatepickerModule,
MatIconModule,
MatInputModule,
MatNativeDateModule
MatNativeDateModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: AlfrescoTranslateLoader
}
})
],
declarations: [
CardViewTextItemComponent
],
providers: [
CardViewUpdateService
CardViewUpdateService,
LogService
]
}).compileComponents();
}));
@ -55,7 +68,7 @@ describe('CardViewTextItemComponent', () => {
label: 'Text label',
value: 'Lorem ipsum',
key: 'textkey',
default: '',
default: 'FAKE-DEFAULT-KEY',
editable: false
});
});
@ -77,6 +90,66 @@ describe('CardViewTextItemComponent', () => {
expect(value.nativeElement.innerText.trim()).toBe('Lorem ipsum');
});
it('should render the default as value if the value is empty and editable false', () => {
component.property = new CardViewTextItemModel ({
label: 'Text label',
value: '',
key: 'textkey',
default: 'FAKE-DEFAULT-KEY',
editable: false
});
fixture.detectChanges();
let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`));
expect(value).not.toBeNull();
expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY');
});
it('should render the default as value if the value is empty and editable true', () => {
component.property = new CardViewTextItemModel ({
label: 'Text label',
value: '',
key: 'textkey',
default: 'FAKE-DEFAULT-KEY',
editable: true
});
fixture.detectChanges();
let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`));
expect(value).not.toBeNull();
expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY');
});
it('should render the default as value if the value is empty and clickable false', () => {
component.property = new CardViewTextItemModel ({
label: 'Text label',
value: '',
key: 'textkey',
default: 'FAKE-DEFAULT-KEY',
clickable: false
});
fixture.detectChanges();
let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`));
expect(value).not.toBeNull();
expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY');
});
it('should render the default as value if the value is empty and clickable true', () => {
component.property = new CardViewTextItemModel ({
label: 'Text label',
value: '',
key: 'textkey',
default: 'FAKE-DEFAULT-KEY',
clickable: true
});
fixture.detectChanges();
let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`));
expect(value).not.toBeNull();
expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY');
});
it('should render value when editable:true', () => {
component.editable = true;
component.property.editable = true;

View File

@ -19,6 +19,7 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule, MatDatepickerModule, MatIconModule, MatInputModule, MatNativeDateModule } from '@angular/material';
import { TranslateModule } from '@ngx-translate/core';
import { CardViewContentProxyDirective } from './card-view-content-proxy.directive';
import { CardViewDateItemComponent } from './card-view-dateitem.component';
import { CardViewItemDispatcherComponent } from './card-view-item-dispatcher.component';
@ -34,7 +35,8 @@ import { CardViewComponent } from './card-view.component';
MatInputModule,
MatIconModule,
MatButtonModule,
FormsModule
FormsModule,
TranslateModule
],
declarations: [
CardViewComponent,

View File

@ -48,4 +48,8 @@ export abstract class CardViewBaseItemModel {
this.editable = !!obj.editable;
this.clickable = !!obj.clickable;
}
isEmpty(): boolean {
return this.value === undefined || this.value === null || this.value === '';
}
}

View File

@ -39,6 +39,7 @@ export class CardViewTextItemModel extends CardViewBaseItemModel implements Card
}
get displayValue() {
return this.value || this.default;
return this.value;
}
}