mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[AAE-9200] - Be able to customise task/process list and header date f… (#7711)
* [AAE-9200] - Be able to customise task/process list and header date formats * Update json schema * Revert schema changes * Update task and process name translation values * move task/process header date formats inside header config * Add documentation * Update documentation * Use a fixed timezone for unit tests of core and cloud * Fix e2e due to column rename * More e2e fixes due to column rename, remove test covered by unit test
This commit is contained in:
parent
46926ed818
commit
fa587510bd
@ -847,6 +847,16 @@ here is the sample resolver which merge the users property and status and it wil
|
||||
|
||||

|
||||
|
||||
# Tooltip
|
||||
|
||||
You can define the tooltip format for cells of type date using a configuration in `app.config.json`:
|
||||
|
||||
```json
|
||||
"dateValues": {
|
||||
"defaultTooltipDateFormat": "medium"
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Data column component](data-column.component.md)
|
||||
|
@ -50,6 +50,14 @@ However, you can also choose which properties to show using a configuration in `
|
||||
|
||||
With this configuration, only the four listed properties will be shown.
|
||||
|
||||
You can also define the date format of the date properties using a configuration in `app.config.json`:
|
||||
|
||||
```json
|
||||
"adf-cloud-process-header": {
|
||||
"defaultDateFormat": "full"
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Process header cloud service](../../process-services-cloud/services/process-header-cloud.service.md)
|
||||
|
@ -58,3 +58,11 @@ However, you can also choose which properties to show using a configuration in `
|
||||
```
|
||||
|
||||
With this configuration, only the four listed properties will be shown.
|
||||
|
||||
You can also define the date format of the date properties using a configuration in `app.config.json`:
|
||||
|
||||
```json
|
||||
"adf-cloud-task-header": {
|
||||
"defaultDateFormat": "full"
|
||||
}
|
||||
```
|
||||
|
@ -23,11 +23,11 @@ export class ProcessDetailsCloudDemoPage {
|
||||
dataTable: DataTableComponentPage = new DataTableComponentPage();
|
||||
|
||||
async checkTaskIsDisplayed(taskName: string): Promise<void> {
|
||||
await this.dataTable.checkContentIsDisplayed('Name', taskName);
|
||||
await this.dataTable.checkContentIsDisplayed('Task Name', taskName);
|
||||
}
|
||||
|
||||
async selectProcessTaskByName(taskName: string): Promise<void> {
|
||||
await this.dataTable.selectRow('Name', taskName);
|
||||
await this.dataTable.selectRow('Task Name', taskName);
|
||||
}
|
||||
|
||||
async checkListedSelectedProcessInstance(processInstanceId: string): Promise<void> {
|
||||
|
@ -156,11 +156,11 @@ describe('Process list cloud', () => {
|
||||
await setFilter({ sort: 'Name' });
|
||||
await setFilter({ order: SORT_DIRECTION.ASC });
|
||||
|
||||
await expect(await processList.getDataTable().checkListIsSorted(SORT_DIRECTION.ASC, 'Name')).toBe(true);
|
||||
await expect(await processList.getDataTable().checkListIsSorted(SORT_DIRECTION.ASC, 'Process Name')).toBe(true);
|
||||
|
||||
await setFilter({ order: SORT_DIRECTION.DESC});
|
||||
|
||||
await expect(await processList.getDataTable().checkListIsSorted(SORT_DIRECTION.DESC, 'Name')).toBe(true);
|
||||
await expect(await processList.getDataTable().checkListIsSorted(SORT_DIRECTION.DESC, 'Process Name')).toBe(true);
|
||||
});
|
||||
|
||||
it('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async () => {
|
||||
|
@ -266,7 +266,7 @@ describe('Start Task Form', () => {
|
||||
await processList.getDataTable().waitTillContentLoaded();
|
||||
await processList.checkContentIsDisplayedByName(startEventFormProcess);
|
||||
|
||||
await processList.getDataTable().selectRow('Name', startEventFormProcess);
|
||||
await processList.getDataTable().selectRow('Process Name', startEventFormProcess);
|
||||
await browser.actions().sendKeys(protractor.Key.ENTER).perform();
|
||||
|
||||
await processDetailsCloudDemoPage.checkTaskIsDisplayed('StartEventFormTask');
|
||||
|
@ -20,7 +20,6 @@ import { createApiService,
|
||||
AppListCloudPage,
|
||||
GroupIdentityService,
|
||||
IdentityService,
|
||||
LocalStorageUtil,
|
||||
LoginPage,
|
||||
StringUtil,
|
||||
TaskHeaderCloudPage,
|
||||
@ -68,7 +67,6 @@ describe('Task Header cloud component', () => {
|
||||
let subTask: any;
|
||||
let subTaskCreatedDate: string;
|
||||
let completedEndDate: string;
|
||||
let defaultDate: string;
|
||||
let groupInfo: any;
|
||||
let testUser: any;
|
||||
let unclaimedTask: any;
|
||||
@ -76,7 +74,6 @@ describe('Task Header cloud component', () => {
|
||||
const description = 'descriptionTask';
|
||||
const formatDate = 'MMM D, YYYY';
|
||||
const dateTimeFormat = 'MMM D, Y, H:mm';
|
||||
const defaultFormat = 'M/D/YY';
|
||||
|
||||
const createCompletedTask = async function () {
|
||||
const completedTaskId = await tasksService.createStandaloneTask(completedTaskName,
|
||||
@ -117,7 +114,6 @@ describe('Task Header cloud component', () => {
|
||||
completedCreatedDate = moment(completedTask.entry.createdDate).format(formatDate);
|
||||
dueDate = moment(completedTask.entry.dueDate).format(dateTimeFormat);
|
||||
completedEndDate = moment(completedTask.entry.endDate).format(formatDate);
|
||||
defaultDate = moment(completedTask.entry.createdDate).format(defaultFormat);
|
||||
|
||||
subTask = await createSubTask(createdTaskId);
|
||||
subTaskCreatedDate = moment(subTask.entry.createdDate).format(formatDate);
|
||||
@ -241,29 +237,4 @@ describe('Task Header cloud component', () => {
|
||||
await peopleCloudComponentPage.searchAssignee('modeler');
|
||||
await peopleCloudComponentPage.checkNoResultsFoundError();
|
||||
});
|
||||
|
||||
describe('Default Date format', () => {
|
||||
beforeEach(async () => {
|
||||
await LocalStorageUtil.setConfigField('dateValues', '{' +
|
||||
'"defaultDateFormat": "shortDate",' +
|
||||
'"defaultDateTimeFormat": "M/d/yy, h:mm a",' +
|
||||
'"defaultLocale": "uk"' +
|
||||
'}');
|
||||
await navigationBarPage.navigateToProcessServicesCloudPage();
|
||||
await appListCloudComponent.checkApsContainer();
|
||||
await appListCloudComponent.goToApp(simpleApp);
|
||||
});
|
||||
|
||||
it('[C311280] Should pick up the default date format from the app configuration', async () => {
|
||||
await taskFilter.clickTaskFilter('completed-tasks');
|
||||
await taskList.getDataTable().waitTillContentLoaded();
|
||||
|
||||
await taskList.checkContentIsDisplayedByName(completedTaskName);
|
||||
await taskList.selectRow(completedTaskName);
|
||||
await tasksCloudDemoPage.waitTillContentLoaded();
|
||||
|
||||
await taskHeaderCloudPage.checkTaskPropertyListIsDisplayed();
|
||||
await expect(await taskHeaderCloudPage.getCreated()).toEqual(defaultDate);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -142,10 +142,10 @@ describe('Edit task filters and task list properties', () => {
|
||||
await editTaskFilter.setSortFilterDropDown('name');
|
||||
await editTaskFilter.setOrderFilterDropDown(SORT_ORDER.ASC);
|
||||
|
||||
await expect(await taskList.getDataTable().checkListIsSorted(SORT_ORDER.ASC, 'Name')).toBe(true);
|
||||
await expect(await taskList.getDataTable().checkListIsSorted(SORT_ORDER.ASC, 'Task Name')).toBe(true);
|
||||
|
||||
await editTaskFilter.setOrderFilterDropDown(SORT_ORDER.DESC);
|
||||
await expect(await taskList.getDataTable().checkListIsSorted(SORT_ORDER.DESC, 'Name')).toBe(true);
|
||||
await expect(await taskList.getDataTable().checkListIsSorted(SORT_ORDER.DESC, 'Task Name')).toBe(true);
|
||||
});
|
||||
|
||||
it('[C290156] Should display tasks ordered by id when Id is selected from sort dropdown', async () => {
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { UserPreferencesService } from '../../../services';
|
||||
import { AppConfigService } from '../../../app-config';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { CoreTestingModule } from '../../../testing';
|
||||
import { DateCellComponent } from './date-cell.component';
|
||||
|
||||
describe('DateCellComponent', () => {
|
||||
let appConfigService: AppConfigService;
|
||||
let userPreferencesService: UserPreferencesService;
|
||||
let fixture: ComponentFixture<DateCellComponent>;
|
||||
let component: DateCellComponent;
|
||||
let getLocaleSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CoreTestingModule
|
||||
],
|
||||
declarations: [DateCellComponent]
|
||||
});
|
||||
appConfigService = TestBed.inject(AppConfigService);
|
||||
userPreferencesService = TestBed.inject(UserPreferencesService);
|
||||
|
||||
getLocaleSpy = spyOn(userPreferencesService, 'select').and.callThrough();
|
||||
appConfigService.config = {
|
||||
dateValues: {
|
||||
defaultDateFormat: 'mediumDate',
|
||||
defaultTooltipDateFormat: 'medium'
|
||||
}
|
||||
};
|
||||
fixture = TestBed.createComponent(DateCellComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should read locale from user preferences service', () => {
|
||||
expect(getLocaleSpy).toHaveBeenCalledWith('locale');
|
||||
expect(component.currentLocale).toEqual('en');
|
||||
});
|
||||
|
||||
it('should read date format values from app config service', () => {
|
||||
expect(component.format).toEqual('mediumDate');
|
||||
expect(component.tooltipDateFormat).toEqual('medium');
|
||||
});
|
||||
|
||||
it('should date values be formatted based on the formats defined in the app config', () => {
|
||||
component.value$.next('2022-07-14T11:50:45.973+0000');
|
||||
component.tooltip = '2022-07-14T11:50:45.973+0000';
|
||||
fixture.detectChanges();
|
||||
const dateCellValue = fixture.nativeElement.querySelector('.adf-datatable-cell-value');
|
||||
const tooltipValue = dateCellValue.attributes['title'].value;
|
||||
|
||||
expect(dateCellValue.textContent.trim()).toEqual('Jul 14, 2022');
|
||||
expect(dateCellValue.attributes['aria-label'].value).toEqual('Jul 14, 2022');
|
||||
expect(tooltipValue).toEqual('Jul 14, 2022, 11:50:45 AM');
|
||||
});
|
||||
});
|
@ -41,8 +41,7 @@ import { takeUntil } from 'rxjs/operators';
|
||||
<ng-template #standard_date>
|
||||
<span
|
||||
class="adf-datatable-cell-value"
|
||||
title="{{ tooltip | adfLocalizedDate: format }}"
|
||||
class="adf-datatable-cell-value"
|
||||
title="{{ tooltip | adfLocalizedDate: tooltipDateFormat }}"
|
||||
[attr.aria-label]="value$ | async | adfLocalizedDate: format">
|
||||
{{ value$ | async | adfLocalizedDate: format }}
|
||||
</span>
|
||||
@ -57,6 +56,7 @@ export class DateCellComponent extends DataTableCellComponent {
|
||||
|
||||
currentLocale: string;
|
||||
dateFormat: string;
|
||||
tooltipDateFormat: string;
|
||||
|
||||
get format(): string {
|
||||
if (this.column) {
|
||||
@ -73,6 +73,7 @@ export class DateCellComponent extends DataTableCellComponent {
|
||||
super(alfrescoApiService);
|
||||
|
||||
this.dateFormat = appConfig.get('dateValues.defaultDateFormat', DateCellComponent.DATE_FORMAT);
|
||||
this.tooltipDateFormat = appConfig.get('dateValues.defaultTooltipDateFormat', DateCellComponent.DATE_FORMAT);
|
||||
if (userPreferenceService) {
|
||||
userPreferenceService
|
||||
.select(UserPreferenceValues.Locale)
|
||||
|
@ -102,4 +102,5 @@ module.exports = function (config) {
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false
|
||||
});
|
||||
process.env.TZ = 'UTC';
|
||||
};
|
||||
|
@ -84,4 +84,5 @@ module.exports = function (config) {
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false
|
||||
});
|
||||
process.env.TZ = 'UTC';
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
"NONE": "No process instance filter selected."
|
||||
},
|
||||
"PROPERTIES": {
|
||||
"NAME": "Name",
|
||||
"NAME": "Process Name",
|
||||
"CREATED": "Created",
|
||||
"STATUS": "Status",
|
||||
"START_DATE": "Start Date",
|
||||
@ -83,7 +83,7 @@
|
||||
}
|
||||
},
|
||||
"PROPERTIES": {
|
||||
"NAME": "Name",
|
||||
"NAME": "Task Name",
|
||||
"ASSIGNEE": "Assignee",
|
||||
"ID": "Id",
|
||||
"STATUS": "Status",
|
||||
|
@ -34,7 +34,7 @@ export const processInstancePlaceholdersCloudMock: ProcessInstanceCloud = {
|
||||
businessKey: '',
|
||||
id: '00fcc4ab-4290-11e9-b133-0a586460016a',
|
||||
initiator: 'devopsuser',
|
||||
lastModified: new Date(1552152187081),
|
||||
lastModified: new Date(2022, 1, 1, 1, 30, 40),
|
||||
name: '',
|
||||
parentId: '',
|
||||
startDate: new Date(1552152187080),
|
||||
|
@ -206,4 +206,28 @@ describe('ProcessHeaderCloudComponent', () => {
|
||||
expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Date values format', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
appConfigService.config = {
|
||||
'adf-cloud-process-header': {
|
||||
defaultDateFormat: 'full'
|
||||
}
|
||||
};
|
||||
component.ngOnInit();
|
||||
component.ngOnChanges();
|
||||
});
|
||||
|
||||
it('should format the dates based on app config format configuration', async () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const startedDateElement = fixture.debugElement.query(By.css('[data-automation-id="header-startDate"] .adf-property-value'));
|
||||
const lastModifiedElement = fixture.debugElement.query(By.css('[data-automation-id="header-lastModified"] .adf-property-value'));
|
||||
|
||||
expect(component.dateFormat).toEqual('full');
|
||||
expect(startedDateElement.nativeElement.innerText.trim()).toBe('Saturday, March 9, 2019 at 5:23:07 PM GMT+00:00');
|
||||
expect(lastModifiedElement.nativeElement.innerText.trim()).toBe('Saturday, March 9, 2019 at 5:23:07 PM GMT+00:00');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -55,7 +55,7 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.dateFormat = this.appConfig.get('dateValues.defaultDateFormat');
|
||||
this.dateFormat = this.appConfig.get('adf-cloud-process-header.defaultDateFormat');
|
||||
this.dateLocale = this.appConfig.get('dateValues.defaultDateLocale');
|
||||
|
||||
this.processCloudService.dataChangesDetected
|
||||
|
@ -31,7 +31,6 @@ import {
|
||||
taskDetailsWithParentTaskIdMock,
|
||||
createdTaskDetailsCloudMock
|
||||
} from '../mocks/task-details-cloud.mock';
|
||||
import moment from 'moment-es6';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
@ -67,9 +66,14 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
appConfigService = TestBed.inject(AppConfigService);
|
||||
appConfigService.config = {
|
||||
'adf-cloud-task-header': {
|
||||
defaultDateFormat: 'full'
|
||||
}
|
||||
};
|
||||
fixture = TestBed.createComponent(TaskHeaderCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
appConfigService = TestBed.inject(AppConfigService);
|
||||
taskCloudService = TestBed.inject(TaskCloudService);
|
||||
alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
component.appName = 'mock-app-name';
|
||||
@ -103,7 +107,7 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
expect(taskTitle).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fectch task details when appName and taskId defined', async () => {
|
||||
it('should fetch task details when appName and taskId defined', async () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
expect(getTaskByIdSpy).toHaveBeenCalled();
|
||||
@ -149,7 +153,7 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value'));
|
||||
expect(valueEl.nativeElement.innerText.trim()).toBe(moment(assignedTaskDetailsCloudMock.dueDate, 'x').format('MMM D, Y, H:mm'));
|
||||
expect(valueEl.nativeElement.innerText.trim()).toBe('Monday, December 17, 2018 at 12:00:55 PM GMT+00:00');
|
||||
});
|
||||
|
||||
it('should display process instance id', async () => {
|
||||
@ -501,7 +505,13 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
describe('Config properties', () => {
|
||||
|
||||
it('should show only the properties from the configuration file', async () => {
|
||||
spyOn(appConfigService, 'get').and.returnValue(['assignee', 'status']);
|
||||
appConfigService.config = {
|
||||
'adf-cloud-task-header': {
|
||||
presets: {
|
||||
properties: ['assignee', 'status']
|
||||
}
|
||||
}
|
||||
};
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property'));
|
||||
@ -527,6 +537,18 @@ describe('TaskHeaderCloudComponent', () => {
|
||||
expect(propertyList[0].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE');
|
||||
expect(propertyList[1].nativeElement.textContent).toContain('ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS');
|
||||
});
|
||||
|
||||
it('should format the dates based on app config format configuration', async () => {
|
||||
component.ngOnInit();
|
||||
component.ngOnChanges();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const createdDateElement = fixture.debugElement.query(By.css('[data-automation-id="header-created"] .adf-property-value'));
|
||||
|
||||
expect(component.dateFormat).toEqual('full');
|
||||
expect(createdDateElement.nativeElement.innerText.trim()).toBe('Monday, December 17, 2018 at 12:00:55 PM GMT+00:00');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Task errors', () => {
|
||||
|
@ -74,7 +74,6 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
||||
inEdit: boolean = false;
|
||||
parentTaskName: string;
|
||||
dateFormat: string;
|
||||
dateTimeFormat: string;
|
||||
dateLocale: string;
|
||||
displayDateClearAction = false;
|
||||
isLoading = true;
|
||||
@ -88,9 +87,8 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
||||
private appConfig: AppConfigService,
|
||||
private cardViewUpdateService: CardViewUpdateService
|
||||
) {
|
||||
this.dateFormat = this.appConfig.get('dateValues.defaultDateFormat');
|
||||
this.dateFormat = this.appConfig.get('adf-cloud-task-header.defaultDateFormat');
|
||||
this.dateLocale = this.appConfig.get('dateValues.defaultDateLocale');
|
||||
this.dateTimeFormat = this.appConfig.get('dateValue.defaultDateTimeFormat');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -178,7 +176,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
|
||||
key: 'dueDate',
|
||||
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'),
|
||||
editable: true,
|
||||
format: this.dateTimeFormat,
|
||||
format: this.dateFormat,
|
||||
locale: this.dateLocale
|
||||
}
|
||||
),
|
||||
|
@ -49,7 +49,7 @@ export const assignedTaskDetailsCloudMock: TaskDetailsCloudModel = {
|
||||
name: 'This is a new task',
|
||||
description: 'This is the description ',
|
||||
createdDate: new Date(1545048055900),
|
||||
dueDate: new Date(),
|
||||
dueDate: new Date(1545048055900),
|
||||
claimedDate: null,
|
||||
priority: 1,
|
||||
category: null,
|
||||
|
@ -25,7 +25,7 @@ export class ProcessListCloudComponentPage {
|
||||
|
||||
columns = {
|
||||
id: 'Id',
|
||||
name: 'Name',
|
||||
name: 'Process Name',
|
||||
processDefinitionName: 'Process Definition Name'
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@ import { DataTableColumnSelector } from '../../core/pages/data-table/columns-sel
|
||||
|
||||
const column = {
|
||||
id: 'Id',
|
||||
name: 'Name',
|
||||
name: 'Task Name',
|
||||
processInstanceId: 'ProcessInstanceId',
|
||||
processDefinitionId: 'ProcessDefinitionId',
|
||||
assignee: 'Assignee',
|
||||
|
Loading…
x
Reference in New Issue
Block a user