Denys Vuika cd2b489100
[ADF-5146] Upgrade to Angular 10 (#5834)
* remove useless module

* upgrade to angular 8

* upgrade material to v8

* upgrade adf libs

* migrate demo shell to v8

* upgrade to angular 9

* upgrade material to v9

* remove hammer

* upgrade nx

* upgrade datetime picker

* upgrade flex layout

* update core api

* remove entry components

* code fixes

* upgrade testbed usage

* code fixes

* remove unnecessary core-js from tests

* upgrade CLI

* ts config fixes

* fix builds

* fix testing config

* compile fixes

* fix demo shell dev setup

* fix core tests

* fix card view import

* upgrade nx

* disable smart builds for now

* remove fdescribe

* restore smart builds

* fix issues

* unify tsconfigs and fix newly found issues

* fix configuration and cleanup package scripts

* improved production build from the same config

* use ADF libs directly instead of node_modules

* disable smart build

* single app configuration (angular)

* fix core build

* fix build scripts

* lint fixes

* fix linting setup

* fix linting rules

* various fixes

* disable affected libs for unit tests

* cleanup insights package.json

* simplify smart-build

* fix content tests

* fix tests

* test fixes

* fix tests

* fix test

* fix tests

* disable AppExtensionsModule (monaco example)

* remove monaco extension module

* upgrade bundle check rules

* fix insights tests and karma config

* fix protractor config

* e2e workaround

* upgrade puppeteer and split linting and build

* reusable resources config

* update protractor config

* fix after rebase

* fix protractor config

* fix e2e tsconfig

* update e2e setup

* Save demoshell artifact on S3 and remove travis cache

* Push the libs on S3 and fetch before releasing it

* Add deps

* Add dependencies among libs and run only affected unit test and build

* fix the travis stage name

* fix after renaming dev to demoshell

* force the order of the projects

* remove unused dependencies

* fix content e2e script

* exit codes fix

* add extra exit codes to core e2e

* postinstall hook and package cleanup

* cleanup packages

* remove deprecated code and dependency on router

* improve bundle analyzer script

* minor code fixes

* update spec

* fix code after rebase

* upgrade protractor after rebase

* fix e2e mapping lib

* Update tsconfig.e2e.json

* update e2e tsconfig

* fix angular config

* fix protractor runs

* cache dist folder for libs

* update material selectors for dropdowns

* selector fixes

* remove duplicated e2e that have unit tests already

* fix login selector

* fix e2e

* fix test

* fix import issues

* fix selector

* cleanup old monaco extension files

* cleanup demo shell login

* add protractor max retries

* disable customisations of protractor

* fix login validation

* fix after rebase

* fix after rebase, disable latest versions of libs

* Hide the report tab and rollback the localstorage

* rename protractor config back to js

* restore lint as part of build

* cleanup code

* do not copy anything to node_modules on dist test

* fix unit tests

* config fixes

* fix code

* fix code after rebase

* fix tests

* remove existing words from spellcheck

* remove useless directive decorators

* update package.json after rebase

* add js-api back

* code fixes

* add missing export

* update configs

* fix code

* try fix the sso login test

* fix

* remove puppeteer unit

* fix e2e script

* fix

* make provider easy

* fix routes module before upgrade

* fix unit tests

* upgrade angular cli

* upgrade to angular 10

Co-authored-by: maurizio vitale <maurizio.vitale@alfresco.com>
Co-authored-by: Eugenio Romano <eugenio.romano@alfresco.com>
Co-authored-by: Eugenio Romano <eromano@users.noreply.github.com>
2020-07-03 13:01:05 +01:00

331 lines
12 KiB
TypeScript

/*!
* @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 { Component, Input, EventEmitter, Output, OnDestroy, OnChanges, OnInit } from '@angular/core';
import { takeUntil, concatMap, catchError } from 'rxjs/operators';
import { Subject, of, forkJoin } from 'rxjs';
import {
CardViewDateItemModel,
CardViewItem,
CardViewTextItemModel,
CardViewBaseItemModel,
CardViewArrayItemModel,
TranslationService,
AppConfigService,
UpdateNotification,
CardViewUpdateService,
CardViewDatetimeItemModel,
CardViewArrayItem
} from '@alfresco/adf-core';
import { TaskDetailsCloudModel, TaskStatus } from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service';
import { NumericFieldValidator } from '../../../validators/numeric-field.validator';
@Component({
selector: 'adf-cloud-task-header',
templateUrl: './task-header-cloud.component.html',
styleUrls: ['./task-header-cloud.component.scss']
})
export class TaskHeaderCloudComponent implements OnInit, OnDestroy, OnChanges {
/** (Required) The name of the application. */
@Input()
appName: string = '';
/** (Required) The id of the task. */
@Input()
taskId: string;
/** Emitted when the task is claimed. */
@Output()
claim: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the task is unclaimed (ie, requeued). */
@Output()
unclaim: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the given task has errors. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
taskDetails: TaskDetailsCloudModel = {};
candidateUsers: CardViewArrayItem[] = [];
candidateGroups: CardViewArrayItem[] = [];
properties: CardViewItem[];
inEdit: boolean = false;
parentTaskName: string;
dateFormat: string;
dateTimeFormat: string;
dateLocale: string;
displayDateClearAction = false;
private onDestroy$ = new Subject<boolean>();
constructor(
private taskCloudService: TaskCloudService,
private translationService: TranslationService,
private appConfig: AppConfigService,
private cardViewUpdateService: CardViewUpdateService
) {
this.dateFormat = this.appConfig.get('dateValues.defaultDateFormat');
this.dateLocale = this.appConfig.get('dateValues.defaultDateLocale');
this.dateTimeFormat = this.appConfig.get('dateValue.defaultDateTimeFormat');
}
ngOnInit() {
this.taskCloudService.dataChangesDetected$
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => {
this.loadTaskDetailsById(this.appName, this.taskId);
});
this.cardViewUpdateService.itemUpdated$
.pipe(takeUntil(this.onDestroy$))
.subscribe(this.updateTaskDetails.bind(this)
);
}
ngOnChanges() {
this.taskDetails = {};
if ((this.appName || this.appName === '') && this.taskId) {
this.loadTaskDetailsById(this.appName, this.taskId);
} else {
this.error.emit('App Name and Task Id are mandatory');
}
}
loadTaskDetailsById(appName: string, taskId: string) {
this.taskCloudService.getTaskById(appName, taskId).pipe(
concatMap((task) =>
forkJoin(
of(task),
this.taskCloudService.getCandidateUsers(this.appName, this.taskId),
this.taskCloudService.getCandidateGroups(this.appName, this.taskId)
)
)
).subscribe(([taskDetails, candidateUsers, candidateGroups]) => {
this.taskDetails = taskDetails;
this.candidateGroups = candidateGroups.map((user) => <CardViewArrayItem> { icon: 'group', value: user });
this.candidateUsers = candidateUsers.map((group) => <CardViewArrayItem> { icon: 'person', value: group });
if (this.taskDetails.parentTaskId) {
this.loadParentName(`${this.taskDetails.parentTaskId}`);
} else {
this.refreshData();
}
},
(err) => this.error.emit(err));
}
private initDefaultProperties() {
return [
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE',
value: this.taskDetails.assignee,
key: 'assignee',
clickable: this.isClickable(),
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE_DEFAULT'),
icon: 'create'
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.STATUS',
value: this.taskDetails.status,
key: 'status'
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PRIORITY',
value: this.taskDetails.priority,
key: 'priority',
editable: true,
validators: [new NumericFieldValidator()]
}
),
new CardViewDatetimeItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE',
value: this.taskDetails.dueDate,
key: 'dueDate',
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'),
editable: true,
format: this.dateTimeFormat,
locale: this.dateLocale
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CATEGORY',
value: this.taskDetails.category,
key: 'category',
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CATEGORY_DEFAULT')
}
),
new CardViewDateItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CREATED',
value: this.taskDetails.createdDate,
key: 'created',
format: this.dateFormat,
locale: this.dateLocale
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME',
value: this.parentTaskName,
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME_DEFAULT'),
key: 'parentName',
clickable: true
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_TASK_ID',
value: this.taskDetails.parentTaskId,
key: 'parentTaskId',
clickable: true
}
),
new CardViewDateItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.END_DATE',
value: this.taskDetails.completedDate,
key: 'endDate',
format: this.dateFormat,
locale: this.dateLocale
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.ID',
value: this.taskDetails.id,
key: 'id'
}
),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.DESCRIPTION',
value: this.taskDetails.description,
key: 'description',
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DESCRIPTION_DEFAULT'),
multiline: true,
editable: true
}
),
new CardViewArrayItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS',
value: of(this.candidateUsers),
key: 'candidateUsers',
icon: 'edit',
clickable: false,
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_USERS_DEFAULT'),
noOfItemsToDisplay: 2
}
),
new CardViewArrayItemModel(
{
label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS',
value: of(this.candidateGroups),
key: 'candidateGroups',
icon: 'edit',
clickable: false,
default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.CANDIDATE_GROUPS_DEFAULT'),
noOfItemsToDisplay: 2
}
)
];
}
/**
* Refresh the card data
*/
refreshData() {
if (this.taskDetails) {
const defaultProperties = this.initDefaultProperties();
const filteredProperties: string[] = this.appConfig.get('adf-cloud-task-header.presets.properties');
this.properties = defaultProperties.filter((cardItem) => this.isValidSelection(filteredProperties, cardItem));
}
}
/**
* Save a task detail and update it after a successful response
*
* @param updateNotification
*/
private updateTaskDetails(updateNotification: UpdateNotification) {
this.taskCloudService.updateTask(this.appName, this.taskId, updateNotification.changed)
.pipe(catchError(() => {
this.cardViewUpdateService.updateElement(updateNotification.target);
return of(null);
}))
.subscribe((taskDetails) => {
if (taskDetails) {
this.taskDetails = taskDetails;
}
this.refreshData();
});
}
private loadParentName(taskId: string) {
this.taskCloudService.getTaskById(this.appName, taskId)
.subscribe(
(taskDetails) => {
this.parentTaskName = taskDetails.name;
this.refreshData();
}
);
}
isCompleted(): boolean {
return this.taskDetails && this.taskDetails.status === 'COMPLETED';
}
hasAssignee(): boolean {
return !!this.taskDetails.assignee ? true : false;
}
isTaskValid(): boolean {
return (this.appName || this.appName === '') && !!this.taskId;
}
isTaskAssigned(): boolean {
return this.taskDetails.assignee !== undefined;
}
isTaskEditable(): boolean {
return this.taskCloudService.isTaskEditable(this.taskDetails);
}
isClickable(): boolean {
const states: TaskStatus[] = ['ASSIGNED', 'CREATED'];
return states.includes(this.taskDetails.status);
}
private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean {
return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true;
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
}