From 26c5982a1a9494991d649a2c6301f1bbb004ce83 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Mon, 25 Mar 2019 12:17:40 +0000 Subject: [PATCH 001/208] extensibility improvements (#4484) * add missing interfaces to extensions library * separate rule service * api enhancements * fix test * improve APIs --- demo-shell/src/assets/app.extensions.json | 10 +- .../viewer/components/viewer.component.html | 9 +- .../viewer/components/viewer.component.ts | 17 ++-- .../lib/config/document-list.extensions.ts | 29 ++++++ .../src/lib/config/icon.extensions.ts | 22 +++++ .../src/lib/config/rule.extensions.ts | 3 + .../src/lib/config/viewer.extensions.ts | 5 + .../src/lib/services/app-extension.service.ts | 25 +++++ .../lib/services/extension-loader.service.ts | 6 ++ .../lib/services/extension.service.spec.ts | 5 +- .../src/lib/services/extension.service.ts | 57 +++++------ .../src/lib/services/rule.service.ts | 94 +++++++++++++++++++ lib/extensions/src/public-api.ts | 2 + 13 files changed, 235 insertions(+), 49 deletions(-) create mode 100644 lib/extensions/src/lib/config/document-list.extensions.ts create mode 100644 lib/extensions/src/lib/config/icon.extensions.ts create mode 100644 lib/extensions/src/lib/services/rule.service.ts diff --git a/demo-shell/src/assets/app.extensions.json b/demo-shell/src/assets/app.extensions.json index a7e0183e9d..6b2338374f 100644 --- a/demo-shell/src/assets/app.extensions.json +++ b/demo-shell/src/assets/app.extensions.json @@ -1,9 +1,15 @@ { - "$schema": "../../lib/extensions/config/schema/app-extension.schema.json", + "$schema": "../../../lib/extensions/src/lib/config/schema/app-extension.schema.json", "$references": [ "plugin1.json", "plugin2.json", "monaco-extension.json" ], - "$dependencies": [] + "$dependencies": [], + + "features": { + "viewer": { + "content": [] + } + } } diff --git a/lib/core/viewer/components/viewer.component.html b/lib/core/viewer/components/viewer.component.html index a5755f2983..9a0513af79 100644 --- a/lib/core/viewer/components/viewer.component.html +++ b/lib/core/viewer/components/viewer.component.html @@ -196,7 +196,7 @@ - + - + diff --git a/lib/core/viewer/components/viewer.component.ts b/lib/core/viewer/components/viewer.component.ts index ddf16fe264..9afd1ec919 100644 --- a/lib/core/viewer/components/viewer.component.ts +++ b/lib/core/viewer/components/viewer.component.ts @@ -31,7 +31,7 @@ import { ViewerSidebarComponent } from './viewer-sidebar.component'; import { ViewerToolbarComponent } from './viewer-toolbar.component'; import { Subscription } from 'rxjs'; import { ViewUtilService } from '../services/view-util.service'; -import { ExtensionService, ViewerExtensionRef } from '@alfresco/adf-extensions'; +import { AppExtensionService, ViewerExtensionRef } from '@alfresco/adf-extensions'; @Component({ selector: 'adf-viewer', @@ -238,7 +238,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { private viewUtils: ViewUtilService, private logService: LogService, private location: Location, - private extensionService: ExtensionService, + private extensionService: AppExtensionService, private el: ElementRef) { } @@ -251,14 +251,15 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { this.apiService.nodeUpdated.subscribe((node) => this.onNodeUpdated(node)) ); - this.extensionLoad(); + this.loadExtensions(); } - private extensionLoad() { - this.viewerExtensions = this.extensionService.getFeature('viewer.content'); - this.viewerExtensions.forEach((currentViewerExtension: ViewerExtensionRef) => { - this.externalExtensions.push(currentViewerExtension.fileExtension); - }); + private loadExtensions() { + this.viewerExtensions = this.extensionService.getViewerExtensions(); + this.viewerExtensions + .forEach((extension: ViewerExtensionRef) => { + this.externalExtensions.push(extension.fileExtension); + }); } ngOnDestroy() { diff --git a/lib/extensions/src/lib/config/document-list.extensions.ts b/lib/extensions/src/lib/config/document-list.extensions.ts new file mode 100644 index 0000000000..d467d1082a --- /dev/null +++ b/lib/extensions/src/lib/config/document-list.extensions.ts @@ -0,0 +1,29 @@ +/*! + * @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 { ExtensionElement } from './extension-element'; + +export interface DocumentListPresetRef extends ExtensionElement { + key: string; + type: string; // text|image|date + title?: string; + format?: string; + class?: string; + sortable: boolean; + template: string; + desktopOnly: boolean; +} diff --git a/lib/extensions/src/lib/config/icon.extensions.ts b/lib/extensions/src/lib/config/icon.extensions.ts new file mode 100644 index 0000000000..be61309740 --- /dev/null +++ b/lib/extensions/src/lib/config/icon.extensions.ts @@ -0,0 +1,22 @@ +/*! + * @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 { ExtensionElement } from './extension-element'; + +export interface IconRef extends ExtensionElement { + value: string; +} diff --git a/lib/extensions/src/lib/config/rule.extensions.ts b/lib/extensions/src/lib/config/rule.extensions.ts index 10d8c16980..ccf06d8c21 100644 --- a/lib/extensions/src/lib/config/rule.extensions.ts +++ b/lib/extensions/src/lib/config/rule.extensions.ts @@ -19,10 +19,13 @@ import { SelectionState } from '../store/states/selection.state'; import { NavigationState } from '../store/states/navigation.state'; import { NodePermissions } from './permission.extensions'; import { ProfileState } from '../store/states/profile.state'; +import { RepositoryInfo } from '@alfresco/js-api'; export type RuleEvaluator = (context: RuleContext, ...args: any[]) => boolean; export interface RuleContext { + repository: RepositoryInfo; + auth: any; selection: SelectionState; navigation: NavigationState; profile: ProfileState; diff --git a/lib/extensions/src/lib/config/viewer.extensions.ts b/lib/extensions/src/lib/config/viewer.extensions.ts index 08ebba674f..6a4768dcdf 100644 --- a/lib/extensions/src/lib/config/viewer.extensions.ts +++ b/lib/extensions/src/lib/config/viewer.extensions.ts @@ -20,4 +20,9 @@ import { ExtensionElement } from './extension-element'; export interface ViewerExtensionRef extends ExtensionElement { fileExtension: string; component: string; + + rules?: { + visible?: string; + [key: string]: string; + }; } diff --git a/lib/extensions/src/lib/services/app-extension.service.ts b/lib/extensions/src/lib/services/app-extension.service.ts index 5599e975c5..9b83b7e253 100644 --- a/lib/extensions/src/lib/services/app-extension.service.ts +++ b/lib/extensions/src/lib/services/app-extension.service.ts @@ -19,6 +19,7 @@ import { Injectable } from '@angular/core'; import { ExtensionConfig, ExtensionRef } from '../config/extension.config'; import { ExtensionService } from '../services/extension.service'; import { Observable, BehaviorSubject } from 'rxjs'; +import { ViewerExtensionRef } from '../config/viewer.extensions'; @Injectable({ providedIn: 'root' @@ -47,4 +48,28 @@ export class AppExtensionService { .map((entry) => entry); this._references.next(references); } + + /** + * Provides a list of the Viewer content extensions, + * filtered by disabled state and rules. + */ + getViewerExtensions(): ViewerExtensionRef[] { + return this.extensionService + .getElements('features.viewer.content') + .filter((extension) => !this.isViewerExtensionDisabled(extension)); + } + + protected isViewerExtensionDisabled(extension: ViewerExtensionRef): boolean { + if (extension) { + if (extension.disabled) { + return true; + } + + if (extension.rules && extension.rules.disabled) { + return this.extensionService.evaluateRule(extension.rules.disabled); + } + } + + return false; + } } diff --git a/lib/extensions/src/lib/services/extension-loader.service.ts b/lib/extensions/src/lib/services/extension-loader.service.ts index 0e918a9ebd..d7f62adedd 100644 --- a/lib/extensions/src/lib/services/extension-loader.service.ts +++ b/lib/extensions/src/lib/services/extension-loader.service.ts @@ -105,6 +105,12 @@ export class ExtensionLoaderService { }); } + /** + * Retrieves configuration elements. + * Filters element by **enabled** and **order** attributes. + * Example: + * `getElements(config, 'features.viewer.content')` + */ getElements( config: ExtensionConfig, key: string, diff --git a/lib/extensions/src/lib/services/extension.service.spec.ts b/lib/extensions/src/lib/services/extension.service.spec.ts index 736f4bed54..029c4df1a0 100644 --- a/lib/extensions/src/lib/services/extension.service.spec.ts +++ b/lib/extensions/src/lib/services/extension.service.spec.ts @@ -22,6 +22,7 @@ import { RuleRef } from '../config/rule.extensions'; import { RouteRef } from '../config/routing.extensions'; import { ActionRef } from '../config/action.extensions'; import { ComponentRegisterService } from './component-register.service'; +import { RuleService } from './rule.service'; describe('ExtensionService', () => { const blankConfig: ExtensionConfig = { @@ -36,11 +37,13 @@ describe('ExtensionService', () => { let loader: ExtensionLoaderService; let componentRegister: ComponentRegisterService; let service: ExtensionService; + let ruleService: RuleService; beforeEach(() => { loader = new ExtensionLoaderService(null); componentRegister = new ComponentRegisterService(); - service = new ExtensionService(loader, componentRegister); + ruleService = new RuleService(loader); + service = new ExtensionService(loader, componentRegister, ruleService); }); it('should load and setup a config', async () => { diff --git a/lib/extensions/src/lib/services/extension.service.ts b/lib/extensions/src/lib/services/extension.service.ts index 0ac4de4263..4e4d1b114c 100644 --- a/lib/extensions/src/lib/services/extension.service.ts +++ b/lib/extensions/src/lib/services/extension.service.ts @@ -16,32 +16,35 @@ */ import { Injectable, Type } from '@angular/core'; -import { RuleEvaluator, RuleRef, RuleContext, RuleParameter } from '../config/rule.extensions'; +import { RuleEvaluator, RuleRef, RuleContext } from '../config/rule.extensions'; import { ExtensionConfig } from '../config/extension.config'; import { ExtensionLoaderService } from './extension-loader.service'; import { RouteRef } from '../config/routing.extensions'; import { ActionRef } from '../config/action.extensions'; import * as core from '../evaluators/core.evaluators'; import { ComponentRegisterService } from './component-register.service'; +import { RuleService } from './rule.service'; +import { ExtensionElement } from '../config/extension-element'; @Injectable({ providedIn: 'root' }) export class ExtensionService { + + protected config: ExtensionConfig = null; + configPath = 'assets/app.extensions.json'; pluginsPath = 'assets/plugins'; - rules: Array = []; routes: Array = []; actions: Array = []; features: Array = []; - authGuards: { [key: string]: Type<{}> } = {}; - evaluators: { [key: string]: RuleEvaluator } = {}; constructor( - private loader: ExtensionLoaderService, - private componentRegister: ComponentRegisterService + protected loader: ExtensionLoaderService, + protected componentRegister: ComponentRegisterService, + protected ruleService: RuleService ) { } @@ -68,16 +71,19 @@ export class ExtensionService { return; } + this.config = config; + this.setEvaluators({ 'core.every': core.every, 'core.some': core.some, 'core.not': core.not }); - this.rules = this.loader.getRules(config); this.actions = this.loader.getActions(config); this.routes = this.loader.getRoutes(config); this.features = this.loader.getFeatures(config); + + this.ruleService.setup(config); } /** @@ -90,14 +96,16 @@ export class ExtensionService { return properties.reduce((prev, curr) => prev && prev[curr], this.features) || []; } + getElements(key: string, fallback: Array = []): Array { + return this.loader.getElements(this.config, key, fallback); + } + /** * Adds one or more new rule evaluators to the existing set. * @param values The new evaluators to add */ setEvaluators(values: { [key: string]: RuleEvaluator }) { - if (values) { - this.evaluators = Object.assign({}, this.evaluators, values); - } + this.ruleService.setEvaluators(values); } /** @@ -153,36 +161,17 @@ export class ExtensionService { * @returns RuleEvaluator or null if not found */ getEvaluator(key: string): RuleEvaluator { - if (key && key.startsWith('!')) { - const fn = this.evaluators[key.substring(1)]; - return (context: RuleContext, ...args: RuleParameter[]): boolean => { - return !fn(context, ...args); - }; - } - return this.evaluators[key]; + return this.ruleService.getEvaluator(key); } /** * Evaluates a rule. * @param ruleId ID of the rule to evaluate - * @param context Parameter object for the evaluator with details of app state + * @param context (optional) Custom rule execution context. * @returns True if the rule passed, false otherwise */ - evaluateRule(ruleId: string, context: RuleContext): boolean { - const ruleRef = this.getRuleById(ruleId); - - if (ruleRef) { - const evaluator = this.getEvaluator(ruleRef.type); - if (evaluator) { - return evaluator(context, ...ruleRef.parameters); - } - } else { - const evaluator = this.getEvaluator(ruleId); - if (evaluator) { - return evaluator(context); - } - } - return false; + evaluateRule(ruleId: string, context?: RuleContext): boolean { + return this.ruleService.evaluateRule(ruleId, context); } /** @@ -200,7 +189,7 @@ export class ExtensionService { * @returns The rule or null if not found */ getRuleById(id: string): RuleRef { - return this.rules.find((ref) => ref.id === id); + return this.ruleService.getRuleById(id); } /** diff --git a/lib/extensions/src/lib/services/rule.service.ts b/lib/extensions/src/lib/services/rule.service.ts new file mode 100644 index 0000000000..91904142b0 --- /dev/null +++ b/lib/extensions/src/lib/services/rule.service.ts @@ -0,0 +1,94 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { RuleRef, RuleContext, RuleEvaluator, RuleParameter } from '../config/rule.extensions'; +import { ExtensionConfig } from '../config/extension.config'; +import { ExtensionLoaderService } from './extension-loader.service'; + +@Injectable({ + providedIn: 'root' +}) +export class RuleService { + context: RuleContext = null; + rules: Array = []; + evaluators: { [key: string]: RuleEvaluator } = {}; + + constructor(protected loader: ExtensionLoaderService) {} + + setup(config: ExtensionConfig) { + this.rules = this.loader.getRules(config); + } + + /** + * Adds one or more new rule evaluators to the existing set. + * @param values The new evaluators to add + */ + setEvaluators(values: { [key: string]: RuleEvaluator }) { + if (values) { + this.evaluators = Object.assign({}, this.evaluators, values); + } + } + + /** + * Retrieves a rule using its ID value. + * @param id The ID value to look for + * @returns The rule or null if not found + */ + getRuleById(id: string): RuleRef { + return this.rules.find((ref) => ref.id === id); + } + + /** + * Retrieves a RuleEvaluator function using its key name. + * @param key Key name to look for + * @returns RuleEvaluator or null if not found + */ + getEvaluator(key: string): RuleEvaluator { + if (key && key.startsWith('!')) { + const fn = this.evaluators[key.substring(1)]; + return (context: RuleContext, ...args: RuleParameter[]): boolean => { + return !fn(context, ...args); + }; + } + return this.evaluators[key]; + } + + /** + * Evaluates a rule. + * @param ruleId ID of the rule to evaluate + * @param context (optional) Custom rule execution context. + * @returns True if the rule passed, false otherwise + */ + evaluateRule(ruleId: string, context?: RuleContext): boolean { + const ruleRef = this.getRuleById(ruleId); + context = context || this.context; + + if (ruleRef) { + const evaluator = this.getEvaluator(ruleRef.type); + if (evaluator) { + return evaluator(context, ...ruleRef.parameters); + } + } else { + const evaluator = this.getEvaluator(ruleId); + if (evaluator) { + return evaluator(context); + } + } + return false; + } +} diff --git a/lib/extensions/src/public-api.ts b/lib/extensions/src/public-api.ts index c7acbcf4fb..b182f65c0d 100644 --- a/lib/extensions/src/public-api.ts +++ b/lib/extensions/src/public-api.ts @@ -18,9 +18,11 @@ export * from './lib/extensions.module'; export * from './lib/config/action.extensions'; +export * from './lib/config/document-list.extensions'; export * from './lib/config/extension-element'; export * from './lib/config/extension-utils'; export * from './lib/config/extension.config'; +export * from './lib/config/icon.extensions'; export * from './lib/config/navbar.extensions'; export * from './lib/config/permission.extensions'; export * from './lib/config/routing.extensions'; From a7a48e8b2b839b0d9a4ff8631c5f263b6228ca30 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Mon, 25 Mar 2019 12:19:33 +0000 Subject: [PATCH 002/208] enable prefer-const rule for tslint, fix issues (#4409) * enable prefer-const rule for tslint, fix issues * Update content-node-selector.component.spec.ts * Update content-node-selector.component.spec.ts * fix const * fix lint issues * update tests * update tests * update tests * fix code * fix page class --- .../nested-menu-position.directive.ts | 2 +- .../src/app/components/form/form.component.ts | 4 +- .../process-list-demo.component.ts | 2 +- .../task-list-demo.component.ts | 4 +- e2e/actions/ACS/node.actions.ts | 2 +- e2e/actions/ACS/upload.actions.ts | 16 +- e2e/actions/APS-cloud/roles.ts | 2 +- e2e/actions/APS-cloud/tasks.ts | 2 +- e2e/actions/APS/apps.actions.ts | 34 +- e2e/actions/APS/appsRuntime.actions.ts | 2 +- e2e/actions/drop.actions.ts | 32 +- e2e/actions/users.actions.ts | 16 +- .../comments/comment-component.e2e.ts | 18 +- .../directives/create-folder-directive.e2e.ts | 24 +- .../create-library-directive.e2e.ts | 60 +-- .../document-list-actions.e2e.ts | 12 +- .../document-list-component.e2e.ts | 84 ++-- .../document-list-pagination.e2e.ts | 32 +- e2e/content-services/lock-file.e2e.ts | 26 +- .../notifications-component.e2e.ts | 6 +- .../permissions/permissions-component.e2e.ts | 24 +- .../permissions/site-permissions.e2e.ts | 20 +- .../share-file/share-file.e2e.ts | 8 +- .../share-file/unshare-file.e2e.ts | 10 +- e2e/content-services/tag-component.e2e.ts | 30 +- .../trashcan-pagination.e2e.ts | 26 +- .../tree-view-component.e2e.ts | 6 +- .../upload/cancel-upload.e2e.ts | 22 +- .../upload/excluded-file.e2e.ts | 26 +- e2e/content-services/upload/upload-dialog.ts | 30 +- .../upload/uploader-component.e2e.ts | 44 +- .../upload/user-permission.e2e.ts | 28 +- .../version/version-actions.e2e.ts | 10 +- .../version/version-permissions.e2e.ts | 42 +- .../version/version-properties.e2e.ts | 10 +- .../version/version-smoke-tests.e2e.ts | 14 +- .../card-view/aspect-oriented-config.e2e.ts | 16 +- e2e/core/card-view/card-view-component.e2e.ts | 26 +- .../card-view/metadata-permissions.e2e.ts | 10 +- e2e/core/card-view/metadata-properties.e2e.ts | 18 +- .../card-view/metadata-smoke-tests.e2e.ts | 10 +- .../data-table-component-selection.e2e.ts | 10 +- e2e/core/error-component.e2e.ts | 6 +- e2e/core/header-component.e2e.ts | 12 +- e2e/core/icons-component.e2e.ts | 8 +- e2e/core/infinite-scrolling.e2e.ts | 17 +- e2e/core/login/login-component.e2e.ts | 26 +- e2e/core/login/login-sso/login-sso.e2e.ts | 4 +- e2e/core/login/redirection.e2e.ts | 18 +- e2e/core/login/remember-me.e2e.ts | 4 +- e2e/core/pagination-empty-current-page.e2e.ts | 36 +- e2e/core/settings-component.e2e.ts | 2 +- e2e/core/user-info-component.e2e.ts | 14 +- e2e/core/viewer/viewer-component.e2e.ts | 36 +- .../viewer-content-services-component.e2e.ts | 40 +- .../viewer-custom-toolbar-info-drawer.e2e.ts | 12 +- e2e/core/viewer/viewer-properties.e2e.ts | 20 +- e2e/insights/analytics-component.e2e.ts | 16 +- e2e/models/ACS/fileModel.ts | 4 +- e2e/pages/adf/cardViewComponentPage.ts | 28 +- e2e/pages/adf/configEditorPage.ts | 22 +- .../adf/content-services/documentListPage.ts | 10 +- .../search/components/dateRangeFilterPage.ts | 2 +- .../search/components/search-checkList.ts | 26 +- .../search/components/search-radio.ts | 6 +- .../components/search-sortingPicker.page.ts | 10 +- .../search/search-categories.ts | 2 +- .../adf/content-services/treeViewPage.ts | 12 +- e2e/pages/adf/contentServicesPage.ts | 64 +-- e2e/pages/adf/core/headerPage.ts | 8 +- e2e/pages/adf/dataTableComponentPage.ts | 42 +- e2e/pages/adf/demo-shell/customSourcesPage.ts | 6 +- e2e/pages/adf/demo-shell/dataTablePage.ts | 14 +- .../process-services/processListDemoPage.ts | 6 +- .../process-services/taskListDemoPage.ts | 8 +- .../process-services/tasksCloudDemoPage.ts | 2 +- e2e/pages/adf/dialog/createLibraryDialog.ts | 2 +- .../adf/dialog/editProcessFilterDialog.ts | 4 +- e2e/pages/adf/dialog/editTaskFilterDialog.ts | 4 +- e2e/pages/adf/dialog/shareDialog.ts | 2 +- e2e/pages/adf/dialog/uploadDialog.ts | 12 +- e2e/pages/adf/dialog/uploadToggles.ts | 10 +- e2e/pages/adf/filePreviewPage.ts | 48 +- e2e/pages/adf/material/datePickerPage.ts | 10 +- e2e/pages/adf/metadataViewPage.ts | 32 +- e2e/pages/adf/navigationBarPage.ts | 10 +- e2e/pages/adf/notificationPage.ts | 8 +- e2e/pages/adf/paginationPage.ts | 12 +- e2e/pages/adf/permissionsPage.ts | 14 +- .../editProcessFilterCloudComponent.ts | 34 +- .../editTaskFilterCloudComponent.ts | 18 +- .../adf/process-cloud/groupCloudComponent.ts | 6 +- .../adf/process-cloud/peopleCloudComponent.ts | 6 +- .../processFiltersCloudComponent.ts | 2 +- .../taskFiltersCloudComponent.ts | 2 +- .../process-cloud/taskListCloudComponent.ts | 4 +- .../adf/process-services/analyticsPage.ts | 2 +- .../process-services/attachmentListPage.ts | 6 +- .../dialog/startTaskDialog.ts | 4 +- e2e/pages/adf/process-services/filtersPage.ts | 2 +- e2e/pages/adf/process-services/formFields.ts | 26 +- .../process-services/processDetailsPage.ts | 2 +- .../process-services/processFiltersPage.ts | 14 +- .../process-services/processServicesPage.ts | 16 +- .../adf/process-services/startProcessPage.ts | 8 +- .../adf/process-services/taskDetailsPage.ts | 20 +- .../adf/process-services/taskFiltersPage.ts | 2 +- e2e/pages/adf/process-services/tasksPage.ts | 10 +- .../process-services/widgets/amountWidget.ts | 8 +- .../widgets/attachFileWidget.ts | 10 +- .../widgets/checkboxWidget.ts | 2 +- .../widgets/dateTimeWidget.ts | 14 +- .../process-services/widgets/dateWidget.ts | 10 +- .../widgets/dropdownWidget.ts | 2 +- .../widgets/dynamicTableWidget.ts | 12 +- .../widgets/hyperlinkWidget.ts | 2 +- .../process-services/widgets/numberWidget.ts | 6 +- .../process-services/widgets/peopleWidget.ts | 6 +- .../widgets/radioButtonsWidget.ts | 12 +- .../editTaskFilterCloudComponent.ts | 8 +- e2e/pages/adf/searchResultsPage.ts | 14 +- e2e/pages/adf/tagPage.ts | 30 +- e2e/pages/adf/versionManagerPage.ts | 22 +- e2e/pages/adf/viewerPage.ts | 20 +- .../edit-process-filters-component.e2e.ts | 6 +- .../edit-task-filters-component.e2e.ts | 4 +- .../process-custom-filters.e2e.ts | 20 +- .../process-filters-cloud.e2e.ts | 12 +- .../processList-cloud-component.e2e.ts | 8 +- .../start-task-custom-app-cloud.e2e.ts | 2 +- .../task-details-cloud.e2e.ts | 12 +- .../task-filters-cloud.e2e.ts | 8 +- .../task-list-properties.e2e.ts | 18 +- .../task-list-selection.e2e.ts | 9 +- .../tasks-custom-filters.e2e.ts | 19 +- e2e/process-services/apps-section.e2e.ts | 24 +- .../attach-file-widget.e2e.ts | 20 +- .../attach-form-component.e2e.ts | 22 +- .../checklist-component.e2e.ts | 22 +- .../comment-component-processes.e2e.ts | 30 +- .../comment-component-tasks.e2e.ts | 34 +- .../custom-process-filters-sorting.e2e.ts | 54 +- .../custom-process-filters.e2e.ts | 14 +- .../custom-tasks-filters.e2e.ts | 54 +- .../dynamic-table-date-picker.e2e.ts | 28 +- .../empty-process-list-component.e2e.ts | 22 +- e2e/process-services/form-component.e2e.ts | 6 +- .../form-people-widget.e2e.ts | 32 +- .../form-widgets-component.e2e.ts | 32 +- ...ination-processlist-addingProcesses.e2e.ts | 18 +- .../pagination-tasklist-addingTasks.e2e.ts | 20 +- e2e/process-services/people-component.e2e.ts | 20 +- .../process-attachmentList-actionMenu.e2e.ts | 28 +- .../process-filters-component.e2e.ts | 34 +- .../processList-component.e2e.ts | 18 +- .../processlist-pagination.e2e.ts | 28 +- .../sort-tasklist-pagination.e2e.ts | 21 +- e2e/process-services/standalone-task.e2e.ts | 20 +- .../start-process-component.e2e.ts | 32 +- .../start-task-custom-app.e2e.ts | 30 +- .../start-task-task-app.e2e.ts | 32 +- .../task-attachmentList-actionMenu.e2e.ts | 34 +- e2e/process-services/task-audit.e2e.ts | 20 +- e2e/process-services/task-details-form.e2e.ts | 24 +- .../task-details-no-form.e2e.ts | 16 +- e2e/process-services/task-details.e2e.ts | 60 +-- .../task-filters-component.e2e.ts | 80 +-- .../task-filters-sorting.e2e.ts | 56 +-- .../task-list-pagination.e2e.ts | 22 +- .../widgets/amount-widget.e2e.ts | 16 +- .../widgets/attach-folder-widget.e2e.ts | 16 +- .../widgets/checkbox-widget.e2e.ts | 16 +- .../widgets/date-time-widget.e2e.ts | 16 +- .../widgets/date-widget.e2e.ts | 16 +- .../widgets/document-template-widget.e2e.ts | 16 +- .../widgets/dropdown-widget.e2e.ts | 16 +- .../widgets/dynamic-table-widget.e2e.ts | 24 +- .../widgets/header-widget.e2e.ts | 16 +- .../widgets/hyperlink-widget.e2e.ts | 16 +- .../widgets/multi-line-widget.e2e.ts | 20 +- .../widgets/number-widget.e2e.ts | 16 +- .../widgets/people-widget.e2e.ts | 20 +- .../widgets/radio-buttons-widget.e2e.ts | 16 +- .../widgets/text-widget.e2e.ts | 20 +- e2e/search/components/search-checkList.e2e.ts | 14 +- .../components/search-date-range.e2e.ts | 34 +- .../components/search-number-range.e2e.ts | 66 +-- e2e/search/components/search-radio.e2e.ts | 14 +- e2e/search/components/search-slider.e2e.ts | 26 +- .../components/search-sorting-picker.e2e.ts | 24 +- e2e/search/components/search-text.e2e.ts | 12 +- e2e/search/search-component.e2e.ts | 38 +- e2e/search/search-filters.e2e.ts | 50 +- e2e/search/search-multiselect.e2e.ts | 34 +- e2e/search/search-page-component.e2e.ts | 29 +- e2e/util/util.ts | 43 +- .../breadcrumb/breadcrumb.component.spec.ts | 6 +- .../breadcrumb/breadcrumb.component.ts | 2 +- .../dropdown-breadcrumb.component.spec.ts | 10 +- .../dropdown-breadcrumb.component.ts | 2 +- .../content-metadata-card.component.spec.ts | 2 +- .../content-metadata.component.spec.ts | 2 +- .../config/layout-oriented-config.service.ts | 4 +- .../property-groups-translator.service.ts | 2 +- .../content-node-dialog.service.spec.ts | 2 +- .../content-node-dialog.service.ts | 2 +- ...tent-node-selector-panel.component.spec.ts | 32 +- .../content-node-selector.component.spec.ts | 12 +- .../content-node-selector.service.ts | 2 +- .../content-node-share.dialog.spec.ts | 2 +- .../dialogs/folder.dialog.spec.ts | 2 +- lib/content-services/dialogs/folder.dialog.ts | 4 +- .../dialogs/node-lock.dialog.spec.ts | 2 +- .../dialogs/node-lock.dialog.ts | 2 +- .../content-action-list.component.spec.ts | 8 +- .../content-action.component.spec.ts | 60 +-- .../content-column-list.component.spec.ts | 10 +- .../content-column-list.component.ts | 2 +- .../content-column.component.spec.ts | 8 +- .../document-list.component.spec.ts | 190 +++---- .../components/document-list.component.ts | 24 +- .../data/share-datatable-adapter.spec.ts | 220 ++++---- .../data/share-datatable-adapter.ts | 24 +- .../services/custom-resources.service.ts | 10 +- .../services/document-actions.service.spec.ts | 62 ++- .../services/document-actions.service.ts | 8 +- .../services/document-list.service.spec.ts | 14 +- .../services/document-list.service.ts | 12 +- .../services/folder-actions.service.spec.ts | 64 +-- .../services/folder-actions.service.ts | 8 +- .../services/node-actions.service.spec.ts | 2 +- .../add-permission-dialog.component.spec.ts | 2 +- .../add-permission-panel.component.spec.ts | 2 +- .../add-permission.component.spec.ts | 2 +- .../inherited-button.directive.spec.ts | 2 +- .../permission-list.component.spec.ts | 6 +- .../permission-list.component.ts | 10 +- .../node-permission-dialog.service.spec.ts | 2 +- .../node-permission-dialog.service.ts | 2 +- .../services/node-permission.service.spec.ts | 4 +- .../services/node-permission.service.ts | 14 +- .../search-control.component.spec.ts | 74 +-- .../components/search-control.component.ts | 6 +- .../search-date-range.component.spec.ts | 4 +- .../models/search-filter-list.model.ts | 2 +- .../search-filter.component.spec.ts | 2 +- .../search-filter/search-filter.component.ts | 6 +- .../components/search-trigger.directive.ts | 4 +- .../components/search.component.spec.ts | 10 +- .../search/search-query-builder.service.ts | 2 +- .../sites-dropdown.component.spec.ts | 12 +- .../site-dropdown/sites-dropdown.component.ts | 6 +- .../social/like.component.spec.ts | 4 +- .../social/rating.component.spec.ts | 2 +- .../social/rating.component.ts | 2 +- .../social/services/rating.service.spec.ts | 8 +- .../social/services/rating.service.ts | 2 +- .../tag/services/tag.service.ts | 2 +- .../tag/tag-actions.component.spec.ts | 16 +- .../tag/tag-list.component.spec.ts | 4 +- .../tag/tag-node-list.component.spec.ts | 10 +- .../components/tree-view.component.spec.ts | 22 +- .../services/tree-view.service.spec.ts | 4 +- .../components/base-upload/upload-base.ts | 2 +- .../file-uploading-dialog.component.ts | 2 +- .../file-uploading-list-row.component.spec.ts | 2 +- .../upload-button.component.spec.ts | 20 +- .../components/upload-button.component.ts | 8 +- .../upload-drag-area.component.spec.ts | 38 +- .../components/upload-drag-area.component.ts | 4 +- .../file-draggable.directive.spec.ts | 4 +- .../version-list.component.spec.ts | 28 +- .../version-manager.component.spec.ts | 6 +- .../webscript/webscript.component.spec.ts | 6 +- .../webscript/webscript.component.ts | 2 +- .../buttons-menu.component.spec.ts | 2 +- .../card-view-boolitem.component.spec.ts | 28 +- .../card-view-dateitem.component.spec.ts | 28 +- .../card-view-dateitem.component.ts | 2 +- ...d-view-keyvaluepairsitem.component.spec.ts | 10 +- .../card-view-mapitem.component.spec.ts | 16 +- .../card-view-textitem.component.spec.ts | 38 +- .../card-view/card-view.component.spec.ts | 22 +- .../comments/comment-list.component.spec.ts | 30 +- lib/core/comments/comments.component.spec.ts | 56 +-- lib/core/comments/comments.component.ts | 4 +- .../context-menu-holder.component.spec.ts | 4 +- .../datatable/datatable.component.spec.ts | 84 ++-- .../datatable/datatable.component.ts | 28 +- .../data/object-datatable-adapter.spec.ts | 86 ++-- .../data/object-datatable-adapter.ts | 12 +- lib/core/dialogs/download-zip.dialog.spec.ts | 6 +- ...heck-allowable-operation.directive.spec.ts | 4 +- .../check-allowable-operation.directive.ts | 2 +- .../node-favorite.directive.spec.ts | 12 +- lib/core/directives/node-restore.directive.ts | 2 +- lib/core/directives/upload.directive.spec.ts | 14 +- lib/core/directives/upload.directive.ts | 8 +- .../form-field/form-field.component.spec.ts | 12 +- .../form-field/form-field.component.ts | 22 +- .../form/components/form.component.spec.ts | 130 ++--- .../form.component.visibility.spec.ts | 36 +- .../form/components/start-form.component.ts | 4 +- .../container/container-column.model.spec.ts | 4 +- .../container/container.widget.model.spec.ts | 8 +- .../container/container.widget.spec.ts | 16 +- .../widgets/container/container.widget.ts | 2 +- .../widgets/content/content.widget.spec.ts | 36 +- .../widgets/core/container.model.spec.ts | 4 +- .../widgets/core/error-message.model.ts | 2 +- .../widgets/core/form-field-validator.spec.ts | 132 ++--- .../widgets/core/form-field-validator.ts | 22 +- .../widgets/core/form-field.model.spec.ts | 90 ++-- .../widgets/core/form-field.model.ts | 28 +- .../widgets/core/form-outcome.model.spec.ts | 12 +- .../widgets/core/form-widget.model.spec.ts | 8 +- .../widgets/core/form.model.spec.ts | 62 +-- .../components/widgets/core/form.model.ts | 34 +- .../components/widgets/core/tab.model.spec.ts | 20 +- .../date-time/date-time.widget.spec.ts | 16 +- .../widgets/date-time/date-time.widget.ts | 2 +- .../widgets/date/date.widget.spec.ts | 18 +- .../components/widgets/date/date.widget.ts | 2 +- .../widgets/dropdown/dropdown.widget.spec.ts | 20 +- .../widgets/dropdown/dropdown.widget.ts | 4 +- .../date-cell-validator-model.ts | 4 +- .../dynamic-table.widget.model.ts | 14 +- .../dynamic-table.widget.spec.ts | 64 +-- .../dynamic-table/dynamic-table.widget.ts | 6 +- .../editors/boolean/boolean.editor.spec.ts | 6 +- .../editors/boolean/boolean.editor.ts | 2 +- .../editors/date/date.editor.spec.ts | 4 +- .../dynamic-table/editors/date/date.editor.ts | 4 +- .../editors/datetime/datetime.editor.spec.ts | 4 +- .../editors/datetime/datetime.editor.ts | 2 +- .../editors/dropdown/dropdown.editor.spec.ts | 10 +- .../editors/dropdown/dropdown.editor.ts | 2 +- .../editors/text/text.editor.spec.ts | 6 +- .../dynamic-table/editors/text/text.editor.ts | 2 +- .../number-cell-validator.model.ts | 2 +- .../required-cell-validator.model.ts | 2 +- .../functional-group.widget.spec.ts | 24 +- .../functional-group.widget.ts | 8 +- .../widgets/people/people.widget.spec.ts | 22 +- .../widgets/people/people.widget.ts | 10 +- .../radio-buttons.widget.spec.ts | 16 +- .../widgets/tabs/tabs.widget.spec.ts | 6 +- .../widgets/text/text-mask.component.ts | 38 +- .../widgets/text/text.widget.spec.ts | 14 +- .../typeahead/typeahead.widget.spec.ts | 34 +- .../widgets/typeahead/typeahead.widget.ts | 18 +- .../upload-folder/upload-folder.widget.ts | 4 +- .../widgets/upload/upload.widget.spec.ts | 44 +- .../widgets/upload/upload.widget.ts | 4 +- .../widgets/widget.component.spec.ts | 8 +- lib/core/form/models/form-definition.model.ts | 4 +- .../services/activiti-alfresco.service.ts | 8 +- .../form/services/ecm-model.service.spec.ts | 18 +- lib/core/form/services/ecm-model.service.ts | 8 +- .../services/form-rendering.service.spec.ts | 24 +- lib/core/form/services/form.service.spec.ts | 24 +- lib/core/form/services/form.service.ts | 20 +- lib/core/form/services/node.service.spec.ts | 16 +- lib/core/form/services/node.service.ts | 14 +- .../services/process-content.service.spec.ts | 20 +- .../widget-visibility.service.spec.ts | 112 ++--- .../services/widget-visibility.service.ts | 20 +- .../info-drawer/info-drawer.component.spec.ts | 16 +- .../login/components/login.component.spec.ts | 4 +- lib/core/login/components/login.component.ts | 8 +- lib/core/mock/event.mock.ts | 4 +- .../infinite-pagination.component.spec.ts | 22 +- lib/core/pipes/format-space.pipe.spec.ts | 14 +- lib/core/pipes/node-name-tooltip.pipe.spec.ts | 16 +- lib/core/pipes/time-ago.pipe.spec.ts | 6 +- lib/core/pipes/user-initial.pipe.spec.ts | 10 +- lib/core/pipes/user-initial.pipe.ts | 2 +- lib/core/services/alfresco-api.service.ts | 2 +- .../services/auth-guard-sso-role.service.ts | 2 +- .../services/authentication.service.spec.ts | 28 +- lib/core/services/authentication.service.ts | 4 +- .../services/comment-process.service.spec.ts | 2 +- lib/core/services/comment-process.service.ts | 8 +- lib/core/services/content.service.spec.ts | 32 +- lib/core/services/content.service.ts | 8 +- .../services/discovery-api.service.spec.ts | 6 +- .../dynamic-component-mapper.service.ts | 4 +- .../services/external-alfresco-api.service.ts | 4 +- lib/core/services/jwt-helper.service.ts | 4 +- lib/core/services/log.service.ts | 4 +- .../services/login-dialog.service.spec.ts | 3 +- .../services/notification.service.spec.ts | 26 +- .../services/people-process.service.spec.ts | 2 +- lib/core/services/people-process.service.ts | 6 +- lib/core/services/renditions.service.ts | 4 +- .../services/search-configuration.service.ts | 2 +- lib/core/services/search.service.spec.ts | 4 +- lib/core/services/sites.service.spec.ts | 2 +- lib/core/services/sites.service.ts | 2 +- lib/core/services/storage.service.ts | 2 +- lib/core/services/thumbnail.service.ts | 4 +- lib/core/services/translate-loader.service.ts | 6 +- lib/core/services/translate-loader.spec.ts | 2 +- lib/core/services/translation.service.ts | 2 +- lib/core/services/upload.service.spec.ts | 56 +-- lib/core/services/upload.service.ts | 10 +- lib/core/services/user-preferences.service.ts | 4 +- lib/core/settings/host-settings.component.ts | 4 +- .../components/user-info.component.spec.ts | 78 +-- .../services/bpm-user.service.spec.ts | 2 +- .../services/ecm-user.service.spec.ts | 6 +- .../userinfo/services/ecm-user.service.ts | 2 +- .../services/identity-user.service.spec.ts | 2 +- lib/core/utils/file-utils.ts | 8 +- lib/core/utils/momentDateAdapter.ts | 10 +- lib/core/utils/object-utils.spec.ts | 8 +- lib/core/utils/object-utils.ts | 6 +- .../components/imgViewer.component.spec.ts | 8 +- .../viewer/components/imgViewer.component.ts | 2 +- .../components/mediaPlayer.component.spec.ts | 6 +- .../components/mediaPlayer.component.ts | 2 +- .../components/pdfViewer.component.spec.ts | 22 +- .../viewer/components/pdfViewer.component.ts | 20 +- .../components/txtViewer.component.spec.ts | 8 +- .../viewer/components/txtViewer.component.ts | 8 +- .../components/viewer.component.spec.ts | 30 +- .../viewer/components/viewer.component.ts | 12 +- .../services/rendering-queue.services.ts | 14 +- .../src/lib/services/extension.service.ts | 2 +- .../analytics-generator.component.ts | 2 +- ...nalytics-report-heat-map.component.spec.ts | 20 +- .../analytics-report-list.component.spec.ts | 8 +- .../analytics-report-list.component.ts | 2 +- ...lytics-report-parameters.component.spec.ts | 104 ++-- .../analytics-report-parameters.component.ts | 12 +- .../widgets/date-range/date-range.widget.ts | 16 +- .../widgets/dropdown/dropdown.widget.ts | 2 +- .../widgets/duration/duration.widget.ts | 4 +- .../components/widgets/widget.component.ts | 2 +- .../services/analytics.service.ts | 20 +- .../diagram.component.activities.spec.ts | 474 +++++++++--------- .../diagram.component.boundary.spec.ts | 262 +++++----- .../diagram.component.catching.events.spec.ts | 210 ++++---- .../diagram.component.events.spec.ts | 210 ++++---- .../diagram.component.flows.spec.ts | 14 +- .../diagram.component.gateways.spec.ts | 154 +++--- .../diagram.component.structural.spec.ts | 50 +- .../components/diagram.component.swim.spec.ts | 30 +- .../diagram.component.throw.spec.ts | 254 +++++----- .../diagram/components/diagram.component.ts | 4 +- ...raphael-icon-alfresco-publish.component.ts | 10 +- .../raphael-icon-box-publish.component.ts | 2 +- .../raphael-icon-business-rule.component.ts | 2 +- .../icons/raphael-icon-camel.component.ts | 2 +- .../icons/raphael-icon-error.component.ts | 2 +- ...ael-icon-google-drive-publish.component.ts | 2 +- .../icons/raphael-icon-manual.component.ts | 2 +- .../icons/raphael-icon-message.component.ts | 2 +- .../icons/raphael-icon-mule.component.ts | 2 +- .../icons/raphael-icon-receive.component.ts | 2 +- .../icons/raphael-icon-rest-call.component.ts | 2 +- .../icons/raphael-icon-script.component.ts | 2 +- .../icons/raphael-icon-send.component.ts | 2 +- .../icons/raphael-icon-service.component.ts | 2 +- .../icons/raphael-icon-signal.component.ts | 2 +- .../icons/raphael-icon-timer.component.ts | 2 +- .../icons/raphael-icon-user.component.ts | 2 +- .../raphael/raphael-circle.component.ts | 6 +- .../raphael/raphael-cross.component.ts | 6 +- .../raphael/raphael-flow-arrow.component.ts | 16 +- .../raphael-multiline-text.component.ts | 17 +- .../raphael/raphael-pentagon.component.ts | 2 +- .../raphael/raphael-plus.component.ts | 4 +- .../raphael/raphael-rect.component.ts | 4 +- .../raphael/raphael-rhombus.component.ts | 4 +- .../raphael/raphael-text.component.ts | 2 +- .../components/raphael/raphael.service.ts | 2 +- .../tooltip/diagram-tooltip.component.spec.ts | 22 +- .../tooltip/diagram-tooltip.component.ts | 6 +- .../diagram/models/chart/barChart.model.ts | 4 +- .../models/report/reportDefinition.model.ts | 2 +- .../diagram/services/diagram-color.service.ts | 4 +- .../diagram/services/diagrams.service.spec.ts | 2 +- .../components/group-cloud.component.spec.ts | 20 +- .../lib/group/pipe/group-initial.pipe.spec.ts | 4 +- .../edit-process-filter-cloud.component.ts | 2 +- ...cess-filter-dialog-cloud.component.spec.ts | 10 +- .../process-filters-cloud.component.spec.ts | 50 +- .../services/process-filter-cloud.service.ts | 4 +- .../services/process-header-cloud.service.ts | 2 +- .../process-list-cloud.component.spec.ts | 6 +- .../process-list-cloud.component.ts | 4 +- .../process-list-cloud.service.spec.ts | 10 +- .../services/process-list-cloud.service.ts | 12 +- .../start-process-cloud.component.spec.ts | 52 +- .../start-process-cloud.component.ts | 2 +- .../services/start-process-cloud.service.ts | 4 +- .../lib/task/services/task-cloud.service.ts | 8 +- .../people-cloud.component.spec.ts | 24 +- .../people-cloud/people-cloud.component.ts | 2 +- .../start-task-cloud.component.spec.ts | 36 +- .../components/start-task-cloud.component.ts | 2 +- .../services/start-task-cloud.service.ts | 2 +- .../edit-task-filter-cloud.component.spec.ts | 96 ++-- .../edit-task-filter-cloud.component.ts | 2 +- ...task-filter-dialog-cloud.component.spec.ts | 10 +- .../task-filters-cloud.component.spec.ts | 46 +- .../services/task-filter-cloud.service.ts | 14 +- .../task-header-cloud.component.spec.ts | 16 +- .../task-list-cloud.component.spec.ts | 6 +- .../components/task-list-cloud.component.ts | 4 +- .../services/task-list-cloud.service.spec.ts | 10 +- .../services/task-list-cloud.service.ts | 12 +- .../app-list/apps-list.component.spec.ts | 12 +- .../app-list/apps-list.component.ts | 2 +- .../select-apps-dialog-component.spec.ts | 2 +- ...reate-process-attachment.component.spec.ts | 14 +- .../create-process-attachment.component.ts | 8 +- .../create-task-attachment.component.spec.ts | 12 +- .../create-task-attachment.component.ts | 8 +- .../process-attachment-list.component.spec.ts | 38 +- .../process-attachment-list.component.ts | 12 +- .../task-attachment-list.component.spec.ts | 34 +- .../task-attachment-list.component.ts | 14 +- ...ttach-file-widget-dialog.component.spec.ts | 12 +- .../attach-file-widget-dialog.service.spec.ts | 3 +- .../attach-file-widget-dialog.service.ts | 2 +- .../attach-file-widget.component.ts | 10 +- .../attach-file-widget.components.spec.ts | 18 +- .../attach-folder-widget.component.ts | 2 +- .../mock/process/process.model.mock.ts | 2 +- .../people-list/people-list.component.spec.ts | 10 +- .../people-list/people-list.component.ts | 6 +- .../people-search-field.component.spec.ts | 4 +- .../people-search.component.spec.ts | 10 +- .../people/people.component.spec.ts | 12 +- .../process-comments.component.spec.ts | 16 +- .../process-comments.component.ts | 6 +- .../process-audit.directive.spec.ts | 12 +- .../process-filters.component.spec.ts | 38 +- ...process-instance-details.component.spec.ts | 14 +- .../process-instance-details.component.ts | 4 +- .../process-instance-header.component.spec.ts | 26 +- .../process-instance-tasks.component.spec.ts | 18 +- .../process-instance-tasks.component.ts | 6 +- .../components/process-list.component.spec.ts | 30 +- .../components/process-list.component.ts | 22 +- .../start-process.component.spec.ts | 54 +- .../components/start-process.component.ts | 12 +- .../services/process-filter.service.spec.ts | 2 +- .../services/process-filter.service.ts | 18 +- .../services/process.service.spec.ts | 14 +- .../process-list/services/process.service.ts | 6 +- .../components/attach-form.component.spec.ts | 6 +- .../components/checklist.component.spec.ts | 14 +- .../components/checklist.component.ts | 4 +- .../no-task-detail-template.directive.spec.ts | 2 +- .../components/start-task.component.spec.ts | 82 +-- .../components/task-audit.directive.spec.ts | 12 +- .../components/task-details.component.spec.ts | 18 +- .../components/task-details.component.ts | 6 +- .../components/task-filters.component.spec.ts | 58 +-- .../components/task-filters.component.ts | 2 +- .../components/task-header.component.spec.ts | 54 +- .../components/task-list.component.spec.ts | 52 +- .../components/task-list.component.ts | 8 +- .../task-list/models/task-details.model.ts | 4 +- .../services/process-upload.service.ts | 6 +- .../services/task-filter.service.spec.ts | 6 +- .../task-list/services/task-filter.service.ts | 18 +- .../task-list/services/task-upload.service.ts | 6 +- .../services/tasklist.service.spec.ts | 22 +- .../task-list/services/tasklist.service.ts | 10 +- .../src/lib/core/browser-visibility.ts | 2 +- lib/testing/src/lib/core/pages/header.page.ts | 8 +- .../src/lib/core/pages/user-info.page.ts | 6 +- lib/testing/src/lib/material/tabs.page.ts | 4 +- .../actions/testing-alfresco-api.service.ts | 2 +- .../app/app-list-cloud.page.ts | 6 +- .../pages/form-fields.page.ts | 26 +- tslint.json | 2 +- 581 files changed, 5435 insertions(+), 5402 deletions(-) diff --git a/demo-shell/src/app/components/app-layout/cloud/directives/nested-menu-position.directive.ts b/demo-shell/src/app/components/app-layout/cloud/directives/nested-menu-position.directive.ts index a823a6c2c4..9c803d6486 100644 --- a/demo-shell/src/app/components/app-layout/cloud/directives/nested-menu-position.directive.ts +++ b/demo-shell/src/app/components/app-layout/cloud/directives/nested-menu-position.directive.ts @@ -30,7 +30,7 @@ export class NestedMenuPositionDirective { @HostListener('click', ['$event']) onClick() { - let overlayContainer = (document.querySelector('.cdk-overlay-connected-position-bounding-box') as HTMLElement); + const overlayContainer = (document.querySelector('.cdk-overlay-connected-position-bounding-box') as HTMLElement); (document.querySelector('.cdk-overlay-pane') as HTMLElement).style.width = '100%'; if (!this.menuMinimized) { diff --git a/demo-shell/src/app/components/form/form.component.ts b/demo-shell/src/app/components/form/form.component.ts index 2ad4c117c5..f56a72baec 100644 --- a/demo-shell/src/app/components/form/form.component.ts +++ b/demo-shell/src/app/components/form/form.component.ts @@ -99,9 +99,9 @@ export class FormComponent implements OnInit, OnDestroy { } onConfigAdded($event: any): void { - let file = $event.currentTarget.files[0]; + const file = $event.currentTarget.files[0]; - let fileReader = new FileReader(); + const fileReader = new FileReader(); fileReader.onload = () => { this.formConfig = fileReader.result; }; diff --git a/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts b/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts index 3d1fd144e8..76d46f6892 100644 --- a/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts +++ b/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts @@ -112,7 +112,7 @@ export class ProcessListDemoComponent implements OnInit { this.size = parseInt(processFilter.processSize, 10); } if (processFilter.processPage) { - let pageValue = parseInt(processFilter.processPage, 10); + const pageValue = parseInt(processFilter.processPage, 10); this.page = pageValue > 0 ? pageValue - 1 : pageValue; } else { this.page = 0; diff --git a/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts b/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts index d3a44ca4c3..4bc4c16907 100644 --- a/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts +++ b/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts @@ -140,7 +140,7 @@ export class TaskListDemoComponent implements OnInit { } if (taskFilter.taskPage) { - let pageValue = parseInt(taskFilter.taskPage, 10); + const pageValue = parseInt(taskFilter.taskPage, 10); this.page = pageValue > 0 ? pageValue - 1 : pageValue; } else { this.page = 0; @@ -150,7 +150,7 @@ export class TaskListDemoComponent implements OnInit { } setDueAfterFilter(date): string { - let dueDateFilter = moment(date); + const dueDateFilter = moment(date); dueDateFilter.set({ hour: 23, minute: 59, diff --git a/e2e/actions/ACS/node.actions.ts b/e2e/actions/ACS/node.actions.ts index 493cda365d..37291abc24 100644 --- a/e2e/actions/ACS/node.actions.ts +++ b/e2e/actions/ACS/node.actions.ts @@ -27,7 +27,7 @@ export class NodeActions { async getNodesDisplayed(alfrescoJsApi, idList, numberOfElements) { - let promises = []; + const promises = []; let nodeList; for (let i = 0; i < (numberOfElements - 1); i++) { diff --git a/e2e/actions/ACS/upload.actions.ts b/e2e/actions/ACS/upload.actions.ts index 7b0da1536a..ae6495f050 100644 --- a/e2e/actions/ACS/upload.actions.ts +++ b/e2e/actions/ACS/upload.actions.ts @@ -22,8 +22,8 @@ import TestConfig = require('../../test.config'); export class UploadActions { async uploadFile(alfrescoJsApi, fileLocation, fileName, parentFolderId) { - let pathFile = path.join(TestConfig.main.rootPath + fileLocation); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + fileLocation); + const file = fs.createReadStream(pathFile); return alfrescoJsApi.upload.uploadFile( file, @@ -39,10 +39,10 @@ export class UploadActions { } async createEmptyFiles(alfrescoJsApi, emptyFileNames: string[], parentFolderId) { - let filesRequest = []; + const filesRequest = []; for (let i = 0; i < emptyFileNames.length; i++) { - let jsonItem = {}; + const jsonItem = {}; jsonItem['name'] = emptyFileNames[i]; jsonItem['nodeType'] = 'cm:content'; filesRequest.push(jsonItem); @@ -65,15 +65,15 @@ export class UploadActions { } async uploadFolder(alfrescoJsApi, sourcePath, folder) { - let absolutePath = '../../' + sourcePath; - let files = fs.readdirSync(path.join(__dirname, absolutePath)); + const absolutePath = '../../' + sourcePath; + const files = fs.readdirSync(path.join(__dirname, absolutePath)); let uploadedFiles; - let promises = []; + const promises = []; if (files && files.length > 0) { for (const fileName of files) { - let pathFile = path.join(sourcePath, fileName); + const pathFile = path.join(sourcePath, fileName); promises.push(this.uploadFile(alfrescoJsApi, pathFile, fileName, folder)); } uploadedFiles = await Promise.all(promises); diff --git a/e2e/actions/APS-cloud/roles.ts b/e2e/actions/APS-cloud/roles.ts index 3f0893c19c..3ee27fd39e 100644 --- a/e2e/actions/APS-cloud/roles.ts +++ b/e2e/actions/APS-cloud/roles.ts @@ -32,7 +32,7 @@ export class Roles { const queryParams = {}, postBody = {}; const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); - for (let key in data) { + for (const key in data) { if (data[key].name === roleName) { roleId = data[key].id; } diff --git a/e2e/actions/APS-cloud/tasks.ts b/e2e/actions/APS-cloud/tasks.ts index b22bf3e6e2..972955ab00 100644 --- a/e2e/actions/APS-cloud/tasks.ts +++ b/e2e/actions/APS-cloud/tasks.ts @@ -73,7 +73,7 @@ export class Tasks { } async createAndCompleteTask (taskName, appName) { - let task = await this.createStandaloneTask(taskName, appName); + const task = await this.createStandaloneTask(taskName, appName); await this.claimTask(task.entry.id, appName); await this.completeTask(task.entry.id, appName); return task; diff --git a/e2e/actions/APS/apps.actions.ts b/e2e/actions/APS/apps.actions.ts index 99459acb8c..c80c731280 100644 --- a/e2e/actions/APS/apps.actions.ts +++ b/e2e/actions/APS/apps.actions.ts @@ -25,7 +25,7 @@ import { browser } from 'protractor'; export class AppsActions { async getProcessTaskId(alfrescoJsApi, processId) { - let taskList = await alfrescoJsApi.activiti.taskApi.listTasks({}); + const taskList = await alfrescoJsApi.activiti.taskApi.listTasks({}); let taskId = -1; taskList.data.forEach((task) => { @@ -38,7 +38,7 @@ export class AppsActions { } async getAppDefinitionId(alfrescoJsApi, appModelId) { - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); let appDefinitionId = -1; appDefinitions.data.forEach((appDefinition) => { @@ -51,9 +51,9 @@ export class AppsActions { } async importPublishDeployApp(alfrescoJsApi, appFileLocation) { - let appCreated = await this.importApp(alfrescoJsApi, appFileLocation); + const appCreated = await this.importApp(alfrescoJsApi, appFileLocation); - let publishApp = await alfrescoJsApi.activiti.appsApi.publishAppDefinition(appCreated.id, new AppPublish()); + const publishApp = await alfrescoJsApi.activiti.appsApi.publishAppDefinition(appCreated.id, new AppPublish()); await alfrescoJsApi.activiti.appsApi.deployAppDefinitions({ appDefinitions: [{ id: publishApp.appDefinition.id }] }); @@ -63,8 +63,8 @@ export class AppsActions { async importApp(alfrescoJsApi, appFileLocation) { browser.setFileDetector(new remote.FileDetector()); - let pathFile = path.join(TestConfig.main.rootPath + appFileLocation); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + appFileLocation); + const file = fs.createReadStream(pathFile); return await alfrescoJsApi.activiti.appsApi.importAppDefinition(file); } @@ -72,7 +72,7 @@ export class AppsActions { async publishDeployApp(alfrescoJsApi, appId) { browser.setFileDetector(new remote.FileDetector()); - let publishApp = await alfrescoJsApi.activiti.appsApi.publishAppDefinition(appId, new AppPublish()); + const publishApp = await alfrescoJsApi.activiti.appsApi.publishAppDefinition(appId, new AppPublish()); await alfrescoJsApi.activiti.appsApi.deployAppDefinitions({ appDefinitions: [{ id: publishApp.appDefinition.id }] }); @@ -82,12 +82,12 @@ export class AppsActions { async importNewVersionAppDefinitionPublishDeployApp(alfrescoJsApi, appFileLocation, modelId) { browser.setFileDetector(new remote.FileDetector()); - let pathFile = path.join(TestConfig.main.rootPath + appFileLocation); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + appFileLocation); + const file = fs.createReadStream(pathFile); - let appCreated = await alfrescoJsApi.activiti.appsApi.importNewAppDefinition(modelId, file); + const appCreated = await alfrescoJsApi.activiti.appsApi.importNewAppDefinition(modelId, file); - let publishApp = await alfrescoJsApi.activiti.appsApi.publishAppDefinition(appCreated.id, new AppPublish()); + const publishApp = await alfrescoJsApi.activiti.appsApi.publishAppDefinition(appCreated.id, new AppPublish()); await alfrescoJsApi.activiti.appsApi.deployAppDefinitions({ appDefinitions: [{ id: publishApp.appDefinition.id }] }); @@ -97,21 +97,21 @@ export class AppsActions { async startProcess(alfrescoJsApi, app, processName?: string) { browser.setFileDetector(new remote.FileDetector()); - let appDefinitionsList = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitionsList = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); - let appDefinition = appDefinitionsList.data.filter((currentApp) => { + const appDefinition = appDefinitionsList.data.filter((currentApp) => { return currentApp.name === app.name; }); - let processDefinitionList = await alfrescoJsApi.activiti.processApi.getProcessDefinitions({ deploymentId: appDefinition.deploymentId }); + const processDefinitionList = await alfrescoJsApi.activiti.processApi.getProcessDefinitions({ deploymentId: appDefinition.deploymentId }); - let chosenProcess = processDefinitionList.data.find( (processDefinition) => { + const chosenProcess = processDefinitionList.data.find( (processDefinition) => { return processDefinition.name === processName; }); - let processDefinitionIdToStart = chosenProcess ? chosenProcess.id : processDefinitionList.data[0].id; + const processDefinitionIdToStart = chosenProcess ? chosenProcess.id : processDefinitionList.data[0].id; - let startProcessOptions: any = { processDefinitionId: processDefinitionIdToStart }; + const startProcessOptions: any = { processDefinitionId: processDefinitionIdToStart }; if (typeof processName !== 'undefined') { startProcessOptions.name = processName; diff --git a/e2e/actions/APS/appsRuntime.actions.ts b/e2e/actions/APS/appsRuntime.actions.ts index 745128ccbb..32249c1aa5 100644 --- a/e2e/actions/APS/appsRuntime.actions.ts +++ b/e2e/actions/APS/appsRuntime.actions.ts @@ -19,7 +19,7 @@ export class AppsRuntimeActions { async getRuntimeAppByName(alfrescoJsApi, appName) { - let runtimeApps = await this.getRuntimeAppDefinitions(alfrescoJsApi); + const runtimeApps = await this.getRuntimeAppDefinitions(alfrescoJsApi); let desiredApp; for (let i = 0; i < runtimeApps.data.length; i++) { diff --git a/e2e/actions/drop.actions.ts b/e2e/actions/drop.actions.ts index 5b49f6428b..c1732346a3 100644 --- a/e2e/actions/drop.actions.ts +++ b/e2e/actions/drop.actions.ts @@ -22,20 +22,20 @@ import path = require('path'); import TestConfig = require('../test.config'); import remote = require('selenium-webdriver/remote'); -let JS_BIND_INPUT = function (target) { - let input = document.createElement('input'); +const JS_BIND_INPUT = function (target) { + const input = document.createElement('input'); input.type = 'file'; input.style.display = 'none'; input.addEventListener('change', function (event) { target.scrollIntoView(true); - let rect = target.getBoundingClientRect(); - let x = rect.left + (rect.width >> 1); - let y = rect.top + (rect.height >> 1); - let data = { files: input.files }; + const rect = target.getBoundingClientRect(); + const x = rect.left + (rect.width >> 1); + const y = rect.top + (rect.height >> 1); + const data = { files: input.files }; ['dragenter', 'dragover', 'drop'].forEach(function (name) { - let mouseEvent: any = document.createEvent('MouseEvent'); + const mouseEvent: any = document.createEvent('MouseEvent'); mouseEvent.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null); mouseEvent.dataTransfer = data; target.dispatchEvent(mouseEvent); @@ -48,8 +48,8 @@ let JS_BIND_INPUT = function (target) { return input; }; -let JS_BIND_INPUT_FOLDER = function (target) { - let input: any = document.createElement('input'); +const JS_BIND_INPUT_FOLDER = function (target) { + const input: any = document.createElement('input'); input.type = 'file'; input.style.display = 'none'; input.multiple = true; @@ -57,13 +57,13 @@ let JS_BIND_INPUT_FOLDER = function (target) { input.addEventListener('change', function (event) { target.scrollIntoView(true); - let rect = target.getBoundingClientRect(); - let x = rect.left + (rect.width >> 1); - let y = rect.top + (rect.height >> 1); - let data = { files: input.files }; + const rect = target.getBoundingClientRect(); + const x = rect.left + (rect.width >> 1); + const y = rect.top + (rect.height >> 1); + const data = { files: input.files }; ['dragenter', 'dragover', 'drop'].forEach(function (name) { - let mouseEvent: any = document.createEvent('MouseEvent'); + const mouseEvent: any = document.createEvent('MouseEvent'); mouseEvent.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null); mouseEvent.dataTransfer = data; target.dispatchEvent(mouseEvent); @@ -81,7 +81,7 @@ export class DropActions { dropFile(dropArea, filePath) { browser.setFileDetector(new remote.FileDetector()); - let absolutePath = path.resolve(path.join(TestConfig.main.rootPath, filePath)); + const absolutePath = path.resolve(path.join(TestConfig.main.rootPath, filePath)); fs.accessSync(absolutePath, fs.constants.F_OK); return dropArea.getWebElement().then((element) => { @@ -95,7 +95,7 @@ export class DropActions { dropFolder(dropArea, folderPath) { browser.setFileDetector(new remote.FileDetector()); - let absolutePath = path.resolve(path.join(TestConfig.main.rootPath, folderPath)); + const absolutePath = path.resolve(path.join(TestConfig.main.rootPath, folderPath)); fs.accessSync(absolutePath, fs.constants.F_OK); return dropArea.getWebElement().then((element) => { diff --git a/e2e/actions/users.actions.ts b/e2e/actions/users.actions.ts index a251d8e4c4..1fd0be5fbf 100644 --- a/e2e/actions/users.actions.ts +++ b/e2e/actions/users.actions.ts @@ -26,9 +26,9 @@ import { browser } from 'protractor'; export class UsersActions { async createTenantAndUser(alfrescoJsApi) { - let newTenant = await alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); - let user = new User({ tenantId: newTenant.id }); + const user = new User({ tenantId: newTenant.id }); await alfrescoJsApi.activiti.adminUsersApi.createNewUser(user); @@ -36,7 +36,7 @@ export class UsersActions { } async createApsUser(alfrescoJsApi, tenantId) { - let user = new User({ tenantId: tenantId }); + const user = new User({ tenantId: tenantId }); await alfrescoJsApi.activiti.adminUsersApi.createNewUser(user); @@ -45,9 +45,9 @@ export class UsersActions { async getApsUserByEmail(alfrescoJsApi, email) { - let users = await alfrescoJsApi.activiti.adminUsersApi.getUsers(); + const users = await alfrescoJsApi.activiti.adminUsersApi.getUsers(); - let user = users.data.filter((currentUser) => { + const user = users.data.filter((currentUser) => { return currentUser.email === email; }); @@ -55,7 +55,7 @@ export class UsersActions { } async createApsUserWithName(alfrescoJsApi, tenantId, email, firstName, lastName) { - let user = new User({ tenantId: tenantId , email: email, firstName: firstName, lastName: lastName}); + const user = new User({ tenantId: tenantId , email: email, firstName: firstName, lastName: lastName}); await alfrescoJsApi.activiti.adminUsersApi.createNewUser(user); @@ -69,8 +69,8 @@ export class UsersActions { async changeProfilePictureAps(alfrescoJsApi, fileLocation) { browser.setFileDetector(new remote.FileDetector()); - let pathFile = path.join(TestConfig.main.rootPath + fileLocation); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + fileLocation); + const file = fs.createReadStream(pathFile); return alfrescoJsApi.activiti.profileApi.uploadProfilePicture(file); } diff --git a/e2e/content-services/comments/comment-component.e2e.ts b/e2e/content-services/comments/comment-component.e2e.ts index 966e15f973..6c68e9e274 100644 --- a/e2e/content-services/comments/comment-component.e2e.ts +++ b/e2e/content-services/comments/comment-component.e2e.ts @@ -35,22 +35,22 @@ import { browser } from 'protractor'; describe('Comment Component', () => { - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let viewerPage = new ViewerPage(); - let commentsPage = new CommentsPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const viewerPage = new ViewerPage(); + const commentsPage = new CommentsPage(); const navigationBar = new NavigationBarPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); let nodeId, userFullName; - let comments = { + const comments = { first: 'This is a comment', multiline: 'This is a comment\n' + 'with a new line', second: 'This is another comment', @@ -80,7 +80,7 @@ describe('Comment Component', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); nodeId = pngUploadedFile.entry.id; diff --git a/e2e/content-services/directives/create-folder-directive.e2e.ts b/e2e/content-services/directives/create-folder-directive.e2e.ts index e512df5f9b..ec2563576c 100644 --- a/e2e/content-services/directives/create-folder-directive.e2e.ts +++ b/e2e/content-services/directives/create-folder-directive.e2e.ts @@ -28,13 +28,13 @@ import { browser, Key } from 'protractor'; describe('Create folder directive', function () { - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let createFolderDialog = new CreateFolderDialog(); - let notificationPage = new NotificationPage(); - let metadataViewPage = new MetadataViewPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const createFolderDialog = new CreateFolderDialog(); + const notificationPage = new NotificationPage(); + const metadataViewPage = new MetadataViewPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -64,7 +64,7 @@ describe('Create folder directive', function () { }); it('[C260154] Should not create the folder if cancel button is clicked', () => { - let folderName = 'cancelFolder'; + const folderName = 'cancelFolder'; contentServicesPage.clickOnCreateNewFolder(); createFolderDialog.addFolderName(folderName); @@ -74,7 +74,7 @@ describe('Create folder directive', function () { }); it('[C260155] Should enable the Create button only when a folder name is present', () => { - let folderName = 'NotEnableFolder'; + const folderName = 'NotEnableFolder'; contentServicesPage.clickOnCreateNewFolder(); createFolderDialog.checkCreateBtnIsDisabled(); @@ -85,7 +85,7 @@ describe('Create folder directive', function () { }); it('[C260156] Should not be possible create two folder with the same name', () => { - let folderName = 'duplicate'; + const folderName = 'duplicate'; contentServicesPage.createNewFolder(folderName); contentServicesPage.checkContentIsDisplayed(folderName); @@ -96,7 +96,7 @@ describe('Create folder directive', function () { }); it('[C260157] Should be possible create a folder under a folder with the same name', () => { - let folderName = 'sameSubFolder'; + const folderName = 'sameSubFolder'; contentServicesPage.createNewFolder(folderName); contentServicesPage.checkContentIsDisplayed(folderName); @@ -108,8 +108,8 @@ describe('Create folder directive', function () { }); it('[C260158] Should be possible add a folder description when create a new folder', () => { - let folderName = 'folderDescription'; - let description = 'this is the description'; + const folderName = 'folderDescription'; + const description = 'this is the description'; contentServicesPage.clickOnCreateNewFolder(); diff --git a/e2e/content-services/directives/create-library-directive.e2e.ts b/e2e/content-services/directives/create-library-directive.e2e.ts index 47a52e595b..c97abf56e3 100644 --- a/e2e/content-services/directives/create-library-directive.e2e.ts +++ b/e2e/content-services/directives/create-library-directive.e2e.ts @@ -28,12 +28,12 @@ import { Util } from '../../util/util'; describe('Create library directive', function () { - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let createLibraryDialog = new CreateLibraryDialog(); - let customSourcesPage = new CustomSources(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const createLibraryDialog = new CreateLibraryDialog(); + const customSourcesPage = new CustomSources(); - let visibility = { + const visibility = { public: 'Public', private: 'Private', moderated: 'Moderated' @@ -41,7 +41,7 @@ describe('Create library directive', function () { let createSite; - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -88,7 +88,7 @@ describe('Create library directive', function () { }); it('[C290159] Should close the dialog when clicking Cancel button', () => { - let libraryName = 'cancelLibrary'; + const libraryName = 'cancelLibrary'; createLibraryDialog.typeLibraryName(libraryName); @@ -98,8 +98,8 @@ describe('Create library directive', function () { }); it('[C290160] Should create a public library', () => { - let libraryName = Util.generateRandomString(); - let libraryDescription = Util.generateRandomString(); + const libraryName = Util.generateRandomString(); + const libraryDescription = Util.generateRandomString(); createLibraryDialog.typeLibraryName(libraryName); createLibraryDialog.typeLibraryDescription(libraryDescription); createLibraryDialog.selectPublic(); @@ -119,8 +119,8 @@ describe('Create library directive', function () { }); it('[C290173] Should create a private library', () => { - let libraryName = Util.generateRandomString(); - let libraryDescription = Util.generateRandomString(); + const libraryName = Util.generateRandomString(); + const libraryDescription = Util.generateRandomString(); createLibraryDialog.typeLibraryName(libraryName); createLibraryDialog.typeLibraryDescription(libraryDescription); createLibraryDialog.selectPrivate(); @@ -140,9 +140,9 @@ describe('Create library directive', function () { }); it('[C290174, C290175] Should create a moderated library with a given Library ID', () => { - let libraryName = Util.generateRandomString(); - let libraryId = Util.generateRandomString(); - let libraryDescription = Util.generateRandomString(); + const libraryName = Util.generateRandomString(); + const libraryId = Util.generateRandomString(); + const libraryDescription = Util.generateRandomString(); createLibraryDialog.typeLibraryName(libraryName); createLibraryDialog.typeLibraryId(libraryId); createLibraryDialog.typeLibraryDescription(libraryDescription); @@ -163,7 +163,7 @@ describe('Create library directive', function () { }); it('[C290163] Should disable Create button when a mandatory field is not filled in', () => { - let inputValue = Util.generateRandomString(); + const inputValue = Util.generateRandomString(); createLibraryDialog.typeLibraryName(inputValue); createLibraryDialog.clearLibraryId(); @@ -179,8 +179,8 @@ describe('Create library directive', function () { }); it('[C290164] Should auto-fill in the Library Id built from library name', () => { - let name: string[] = ['abcd1234', 'ab cd 12 34', 'ab cd&12+34_@link/*']; - let libraryId: string[] = ['abcd1234', 'ab-cd-12-34', 'ab-cd1234link']; + const name: string[] = ['abcd1234', 'ab cd 12 34', 'ab cd&12+34_@link/*']; + const libraryId: string[] = ['abcd1234', 'ab-cd-12-34', 'ab-cd1234link']; for (let _i = 0; _i < 3; _i++) { createLibraryDialog.typeLibraryName(name[_i]); @@ -190,8 +190,8 @@ describe('Create library directive', function () { }); it('[C290176] Should not accept special characters for Library Id', () => { - let name = 'My Library'; - let libraryId: string[] = ['My New Library', 'My+New+Library123!', '<>']; + const name = 'My Library'; + const libraryId: string[] = ['My New Library', 'My+New+Library123!', '<>']; createLibraryDialog.typeLibraryName(name); @@ -203,8 +203,8 @@ describe('Create library directive', function () { }); it('[C291985] Should not accept less than one character name for Library name', () => { - let name = 'x'; - let libraryId = 'My New Library'; + const name = 'x'; + const libraryId = 'My New Library'; createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); @@ -213,8 +213,8 @@ describe('Create library directive', function () { }); it('[C291793] Should display error for Name field filled in with spaces only', () => { - let name = ' '; - let libraryId = Util.generateRandomString(); + const name = ' '; + const libraryId = Util.generateRandomString(); createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); @@ -224,8 +224,8 @@ describe('Create library directive', function () { }); it('[C290177] Should not accept a duplicate Library Id', () => { - let name = 'My Library'; - let libraryId = Util.generateRandomString(); + const name = 'My Library'; + const libraryId = Util.generateRandomString(); createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); @@ -241,8 +241,8 @@ describe('Create library directive', function () { }); it('[C290178] Should accept the same library name but different Library Ids', () => { - let name = createSite.entry.title; - let libraryId = Util.generateRandomString(); + const name = createSite.entry.title; + const libraryId = Util.generateRandomString(); createLibraryDialog.typeLibraryName(name.toUpperCase()); createLibraryDialog.typeLibraryId(libraryId); @@ -257,9 +257,9 @@ describe('Create library directive', function () { }); it('[C290179] Should not accept more than the expected characters for input fields', () => { - let name = Util.generateRandomString(257); - let libraryId = Util.generateRandomString(73); - let libraryDescription = Util.generateRandomString(513); + const name = Util.generateRandomString(257); + const libraryId = Util.generateRandomString(73); + const libraryDescription = Util.generateRandomString(513); createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); diff --git a/e2e/content-services/document-list/document-list-actions.e2e.ts b/e2e/content-services/document-list/document-list-actions.e2e.ts index 74f10b3872..c1f3e98284 100644 --- a/e2e/content-services/document-list/document-list-actions.e2e.ts +++ b/e2e/content-services/document-list/document-list-actions.e2e.ts @@ -28,19 +28,19 @@ import { Util } from '../../util/util'; describe('Document List Component - Actions', () => { - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let contentListPage = contentServicesPage.getDocumentList(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const contentListPage = contentServicesPage.getDocumentList(); let uploadedFolder, secondUploadedFolder; - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); let acsUser = null; let testFileNode; - let pdfFileModel = new FileModel({ + const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let testFileModel = new FileModel({ + const testFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); diff --git a/e2e/content-services/document-list/document-list-component.e2e.ts b/e2e/content-services/document-list/document-list-component.e2e.ts index ff35981cab..15ceebb10b 100644 --- a/e2e/content-services/document-list/document-list-component.e2e.ts +++ b/e2e/content-services/document-list/document-list-component.e2e.ts @@ -32,13 +32,13 @@ import moment from 'moment-es6'; describe('Document List Component', () => { - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let navBar = new NavigationBarPage(); - let errorPage = new ErrorPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const navBar = new NavigationBarPage(); + const errorPage = new ErrorPage(); let privateSite; let uploadedFolder, uploadedFolderExtra; - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); let acsUser = null; let testFileNode, pdfBFileNode; @@ -74,9 +74,9 @@ describe('Document List Component', () => { beforeAll(async (done) => { acsUser = new AcsUserModel(); - let siteName = `PRIVATE_TEST_SITE_${Util.generateRandomString(5)}`; - let folderName = `MEESEEKS_${Util.generateRandomString(5)}`; - let privateSiteBody = { visibility: 'PRIVATE', title: siteName }; + const siteName = `PRIVATE_TEST_SITE_${Util.generateRandomString(5)}`; + const folderName = `MEESEEKS_${Util.generateRandomString(5)}`; + const privateSiteBody = { visibility: 'PRIVATE', title: siteName }; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -125,19 +125,19 @@ describe('Document List Component', () => { describe('Custom Column', () => { let folderName; - let pdfFileModel = new FileModel({ + const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let docxFileModel = new FileModel({ + const docxFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - let timeAgoFileModel = new FileModel({ + const timeAgoFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - let mediumFileModel = new FileModel({ + const mediumFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF_B.file_location }); @@ -205,7 +205,7 @@ describe('Document List Component', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); timeAgoUploadedNode = await uploadActions.uploadFile(this.alfrescoJsApi, timeAgoFileModel.location, timeAgoFileModel.name, '-my-'); contentServicesPage.goToDocumentList(); - let dateValue = contentServicesPage.getColumnValueForRow(timeAgoFileModel.name, 'Created'); + const dateValue = contentServicesPage.getColumnValueForRow(timeAgoFileModel.name, 'Created'); expect(dateValue).toContain('ago'); done(); }); @@ -213,10 +213,10 @@ describe('Document List Component', () => { it('[C279929] Should be able to display the date with date type', async (done) => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); mediumDateUploadedNode = await uploadActions.uploadFile(this.alfrescoJsApi, mediumFileModel.location, mediumFileModel.name, '-my-'); - let createdDate = moment(mediumDateUploadedNode.createdAt).format('ll'); + const createdDate = moment(mediumDateUploadedNode.createdAt).format('ll'); contentServicesPage.goToDocumentList(); contentServicesPage.enableMediumTimeFormat(); - let dateValue = contentServicesPage.getColumnValueForRow(mediumFileModel.name, 'Created'); + const dateValue = contentServicesPage.getColumnValueForRow(mediumFileModel.name, 'Created'); expect(dateValue).toContain(createdDate); done(); }); @@ -224,17 +224,17 @@ describe('Document List Component', () => { describe('Column Sorting', () => { - let fakeFileA = new FileModel({ + const fakeFileA = new FileModel({ 'name': 'A', 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - let fakeFileB = new FileModel({ + const fakeFileB = new FileModel({ 'name': 'B', 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - let fakeFileC = new FileModel({ + const fakeFileC = new FileModel({ 'name': 'C', 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); @@ -243,7 +243,7 @@ describe('Document List Component', () => { beforeAll(async (done) => { - let user = new AcsUserModel(); + const user = new AcsUserModel(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -312,7 +312,7 @@ describe('Document List Component', () => { it('[C279959] Should display empty folder state for new folders', async (done) => { acsUser = new AcsUserModel(); - let folderName = 'BANANA'; + const folderName = 'BANANA'; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); loginPage.loginToContentServicesUsingUserModel(acsUser); @@ -325,13 +325,13 @@ describe('Document List Component', () => { }); it('[C272775] Should be able to upload a file in new folder', async (done) => { - let testFile = new FileModel({ + const testFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); acsUser = new AcsUserModel(); /* cspell:disable-next-line */ - let folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); @@ -352,7 +352,7 @@ describe('Document List Component', () => { loginPage.loginToContentServicesUsingUserModel(acsUser); contentServicesPage.clickOnContentServices(); contentServicesPage.checkRecentFileToBeShowed(); - let icon = await contentServicesPage.getRecentFileIcon(); + const icon = await contentServicesPage.getRecentFileIcon(); expect(icon).toBe('history'); contentServicesPage.expandRecentFiles(); contentServicesPage.checkEmptyRecentFileIsDisplayed(); @@ -362,8 +362,8 @@ describe('Document List Component', () => { it('[C279970] Should display Islocked field for folders', async (done) => { acsUser = new AcsUserModel(); - let folderNameA = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; - let folderNameB = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderNameA = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderNameB = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); @@ -379,11 +379,11 @@ describe('Document List Component', () => { }); it('[C269086] Should display Islocked field for files', async (done) => { - let testFileA = new FileModel({ + const testFileA = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - let testFileB = new FileModel({ + const testFileB = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF_B.file_location }); @@ -441,21 +441,21 @@ describe('Document List Component', () => { describe('Thumbnails and tooltips', () => { - let pdfFile = new FileModel({ + const pdfFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let testFile = new FileModel({ + const testFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - let docxFile = new FileModel({ + const docxFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - let folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; let filePdfNode, fileTestNode, fileDocxNode, folderNode; beforeAll(async (done) => { @@ -504,25 +504,25 @@ describe('Document List Component', () => { }); it('[C260119] Should have a specific thumbnail for folders', async (done) => { - let folderIconUrl = await contentServicesPage.getRowIconImageUrl(folderName); + const folderIconUrl = await contentServicesPage.getRowIconImageUrl(folderName); expect(folderIconUrl).toContain('/assets/images/ft_ic_folder.svg'); done(); }); it('[C280066] Should have a specific thumbnail PDF files', async (done) => { - let fileIconUrl = await contentServicesPage.getRowIconImageUrl(pdfFile.name); + const fileIconUrl = await contentServicesPage.getRowIconImageUrl(pdfFile.name); expect(fileIconUrl).toContain('/assets/images/ft_ic_pdf.svg'); done(); }); it('[C280067] Should have a specific thumbnail DOCX files', async (done) => { - let fileIconUrl = await contentServicesPage.getRowIconImageUrl(docxFile.name); + const fileIconUrl = await contentServicesPage.getRowIconImageUrl(docxFile.name); expect(fileIconUrl).toContain('/assets/images/ft_ic_ms_word.svg'); done(); }); it('[C280068] Should have a specific thumbnail files', async (done) => { - let fileIconUrl = await contentServicesPage.getRowIconImageUrl(testFile.name); + const fileIconUrl = await contentServicesPage.getRowIconImageUrl(testFile.name); expect(fileIconUrl).toContain('/assets/images/ft_ic_document.svg'); done(); }); @@ -530,7 +530,7 @@ describe('Document List Component', () => { it('[C274701] Should be able to enable thumbnails', async (done) => { contentServicesPage.enableThumbnails(); contentServicesPage.checkAcsContainer(); - let fileIconUrl = await contentServicesPage.getRowIconImageUrl(pdfFile.name); + const fileIconUrl = await contentServicesPage.getRowIconImageUrl(pdfFile.name); expect(fileIconUrl).toContain(`/versions/1/nodes/${filePdfNode.entry.id}/renditions`); done(); }); @@ -538,7 +538,7 @@ describe('Document List Component', () => { describe('Gallery View', () => { - let cardProperties = { + const cardProperties = { DISPLAY_NAME: 'Display name', SIZE: 'Size', LOCK: 'Lock', @@ -548,21 +548,21 @@ describe('Document List Component', () => { let funnyUser; - let pdfFile = new FileModel({ + const pdfFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let testFile = new FileModel({ + const testFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - let docxFile = new FileModel({ + const docxFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - let folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; let filePdfNode, fileTestNode, fileDocxNode, folderNode, filePDFSubNode; beforeAll(async (done) => { @@ -693,7 +693,7 @@ describe('Document List Component', () => { }); let file; - let viewer = new ViewerPage(); + const viewer = new ViewerPage(); beforeAll(async (done) => { acsUser = new AcsUserModel(); diff --git a/e2e/content-services/document-list/document-list-pagination.e2e.ts b/e2e/content-services/document-list/document-list-pagination.e2e.ts index cbf709a8ef..15f1238841 100644 --- a/e2e/content-services/document-list/document-list-pagination.e2e.ts +++ b/e2e/content-services/document-list/document-list-pagination.e2e.ts @@ -30,13 +30,13 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Document List - Pagination', function () { - let pagination = { + const pagination = { base: 'newFile', secondSetBase: 'secondSet', extension: '.txt' }; - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5, ten: '10', @@ -48,19 +48,23 @@ describe('Document List - Pagination', function () { default: '25' }; - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let paginationPage = new PaginationPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const paginationPage = new PaginationPage(); + const navigationBarPage = new NavigationBarPage(); - let acsUser = new AcsUserModel(); - let newFolderModel = new FolderModel({'name': 'newFolder'}); - let fileNames = [], nrOfFiles = 20, currentPage = 1, secondSetOfFiles = [], secondSetNumber = 25; - let folderTwoModel = new FolderModel({'name': 'folderTwo'}); - let folderThreeModel = new FolderModel({'name': 'folderThree'}); + const acsUser = new AcsUserModel(); + const newFolderModel = new FolderModel({'name': 'newFolder'}); + let fileNames = []; + const nrOfFiles = 20; + let currentPage = 1; + let secondSetOfFiles = []; + const secondSetNumber = 25; + const folderTwoModel = new FolderModel({'name': 'folderTwo'}); + const folderThreeModel = new FolderModel({'name': 'folderThree'}); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); fileNames = Util.generateSequenceFiles(10, nrOfFiles + 9, pagination.base, pagination.extension); secondSetOfFiles = Util.generateSequenceFiles(10, secondSetNumber + 9, pagination.secondSetBase, pagination.extension); @@ -76,8 +80,8 @@ describe('Document List - Pagination', function () { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let folderThreeUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, folderThreeModel.name, '-my-'); - let newFolderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, newFolderModel.name, '-my-'); + const folderThreeUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, folderThreeModel.name, '-my-'); + const newFolderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, newFolderModel.name, '-my-'); await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, newFolderUploadedModel.entry.id); diff --git a/e2e/content-services/lock-file.e2e.ts b/e2e/content-services/lock-file.e2e.ts index 2f3251373c..4e317f8768 100644 --- a/e2e/content-services/lock-file.e2e.ts +++ b/e2e/content-services/lock-file.e2e.ts @@ -40,16 +40,16 @@ describe('Lock File', () => { const lockFilePage = new LockFilePage(); const contentServices = new ContentServicesPage(); - let adminUser = new AcsUserModel(); - let managerUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const adminUser = new AcsUserModel(); + const managerUser = new AcsUserModel(); + const uploadActions = new UploadActions(); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let pngFileToLock = new FileModel({ + const pngFileToLock = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_B.file_location }); @@ -74,7 +74,7 @@ describe('Lock File', () => { visibility: 'PRIVATE' }); - let resultNode = await this.alfrescoJsApi.core.nodesApi.getNodeChildren(site.entry.guid); + const resultNode = await this.alfrescoJsApi.core.nodesApi.getNodeChildren(site.entry.guid); documentLibrary = resultNode.list.entries[0].entry.id; @@ -90,7 +90,7 @@ describe('Lock File', () => { describe('Lock file interaction with the UI', () => { beforeAll(async (done) => { - let pngLockedUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileToLock.location, pngFileToLock.name, documentLibrary); + const pngLockedUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileToLock.location, pngFileToLock.name, documentLibrary); lockedFileNodeId = pngLockedUploadedFile.entry.id; @@ -98,7 +98,7 @@ describe('Lock File', () => { }); beforeEach(async (done) => { - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); nodeId = pngUploadedFile.entry.id; @@ -177,7 +177,7 @@ describe('Lock File', () => { describe('Locked file without owner permissions', () => { beforeEach(async (done) => { - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); nodeId = pngUploadedFile.entry.id; @@ -275,7 +275,7 @@ describe('Lock File', () => { }); beforeEach(async (done) => { - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, documentLibrary); nodeId = pngUploadedFile.entry.id; @@ -303,7 +303,7 @@ describe('Lock File', () => { await lockFilePage.clickAllowOwnerCheckbox(); await lockFilePage.clickSaveButton(); - let response = await this.alfrescoJsApi.core.nodesApi.updateNode(nodeId, { name: 'My new name' }); + const response = await this.alfrescoJsApi.core.nodesApi.updateNode(nodeId, { name: 'My new name' }); expect(response.entry.name).toEqual('My new name'); }); @@ -316,7 +316,7 @@ describe('Lock File', () => { await lockFilePage.clickAllowOwnerCheckbox(); await lockFilePage.clickSaveButton(); - let response = await this.alfrescoJsApi.core.nodesApi.updateNodeContent(nodeId, 'NEW FILE CONTENT'); + const response = await this.alfrescoJsApi.core.nodesApi.updateNodeContent(nodeId, 'NEW FILE CONTENT'); expect(response.entry.modifiedAt).toBeGreaterThan(response.entry.createdAt); }); @@ -331,7 +331,7 @@ describe('Lock File', () => { await this.alfrescoJsApi.core.nodesApi.moveNode(nodeId, { targetParentId: '-my-' }); - let movedFile = await this.alfrescoJsApi.core.nodesApi.getNode(nodeId); + const movedFile = await this.alfrescoJsApi.core.nodesApi.getNode(nodeId); expect(movedFile.entry.parentId).not.toEqual(documentLibrary); diff --git a/e2e/content-services/notifications-component.e2e.ts b/e2e/content-services/notifications-component.e2e.ts index 21496ea342..e5792fa2df 100644 --- a/e2e/content-services/notifications-component.e2e.ts +++ b/e2e/content-services/notifications-component.e2e.ts @@ -24,10 +24,10 @@ import { browser } from 'protractor'; describe('Notifications Component', () => { - let loginPage = new LoginPage(); - let notificationPage = new NotificationPage(); + const loginPage = new LoginPage(); + const notificationPage = new NotificationPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); beforeAll(async (done) => { diff --git a/e2e/content-services/permissions/permissions-component.e2e.ts b/e2e/content-services/permissions/permissions-component.e2e.ts index b825f01ec5..3a4d6cb312 100644 --- a/e2e/content-services/permissions/permissions-component.e2e.ts +++ b/e2e/content-services/permissions/permissions-component.e2e.ts @@ -59,7 +59,7 @@ describe('Permissions Component', function () { const uploadActions = new UploadActions(); - let contentList = contentServicesPage.getDocumentList(); + const contentList = contentServicesPage.getDocumentList(); const searchDialog = new SearchDialog(); @@ -69,11 +69,11 @@ describe('Permissions Component', function () { const notificationPage = new NotificationPage(); - let uploadDialog = new UploadDialog(); + const uploadDialog = new UploadDialog(); let fileOwnerUser, filePermissionUser, file; - let fileModel = new FileModel({ + const fileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, @@ -81,7 +81,7 @@ describe('Permissions Component', function () { }); - let testFileModel = new FileModel({ + const testFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, @@ -89,7 +89,7 @@ describe('Permissions Component', function () { }); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, @@ -97,7 +97,7 @@ describe('Permissions Component', function () { }); - let groupBody = { + const groupBody = { id: Util.generateRandomString(), @@ -105,7 +105,7 @@ describe('Permissions Component', function () { }; - let alfrescoJsApi = new AlfrescoApi({ + const alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -113,15 +113,15 @@ describe('Permissions Component', function () { }); - let roleConsumerFolderModel = new FolderModel({'name': 'roleConsumer' + Util.generateRandomString()}); + const roleConsumerFolderModel = new FolderModel({'name': 'roleConsumer' + Util.generateRandomString()}); - let roleCoordinatorFolderModel = new FolderModel({'name': 'roleCoordinator' + Util.generateRandomString()}); + const roleCoordinatorFolderModel = new FolderModel({'name': 'roleCoordinator' + Util.generateRandomString()}); - let roleCollaboratorFolderModel = new FolderModel({'name': 'roleCollaborator' + Util.generateRandomString()}); + const roleCollaboratorFolderModel = new FolderModel({'name': 'roleCollaborator' + Util.generateRandomString()}); - let roleContributorFolderModel = new FolderModel({'name': 'roleContributor' + Util.generateRandomString()}); + const roleContributorFolderModel = new FolderModel({'name': 'roleContributor' + Util.generateRandomString()}); - let roleEditorFolderModel = new FolderModel({'name': 'roleEditor' + Util.generateRandomString()}); + const roleEditorFolderModel = new FolderModel({'name': 'roleEditor' + Util.generateRandomString()}); let roleConsumerFolder, roleCoordinatorFolder, roleContributorFolder, roleCollaboratorFolder, roleEditorFolder; diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index 73abd0eedf..28018959a2 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -61,7 +61,7 @@ describe('Permissions Component', function () { const uploadActions = new UploadActions(); - let contentList = contentServicesPage.getDocumentList(); + const contentList = contentServicesPage.getDocumentList(); const searchDialog = new SearchDialog(); @@ -73,13 +73,13 @@ describe('Permissions Component', function () { const versionManagePage = new VersionManagePage(); - let uploadDialog = new UploadDialog(); + const uploadDialog = new UploadDialog(); let folderOwnerUser, consumerUser, siteConsumerUser, contributorUser, managerUser, collaboratorUser; let publicSite, privateSite, folderName; - let fileModel = new FileModel({ + const fileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, @@ -87,7 +87,7 @@ describe('Permissions Component', function () { }); - let testFileModel = new FileModel({ + const testFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, @@ -95,7 +95,7 @@ describe('Permissions Component', function () { }); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, @@ -103,7 +103,7 @@ describe('Permissions Component', function () { }); - let alfrescoJsApi = new AlfrescoApi({ + const alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -143,15 +143,15 @@ describe('Permissions Component', function () { await alfrescoJsApi.login(folderOwnerUser.id, folderOwnerUser.password); - let publicSiteName = `PUBLIC_TEST_SITE_${Util.generateRandomString(5)}`; + const publicSiteName = `PUBLIC_TEST_SITE_${Util.generateRandomString(5)}`; - let privateSiteName = `PRIVATE_TEST_SITE_${Util.generateRandomString(5)}`; + const privateSiteName = `PRIVATE_TEST_SITE_${Util.generateRandomString(5)}`; folderName = `MEESEEKS_${Util.generateRandomString(5)}`; - let publicSiteBody = {visibility: 'PUBLIC', title: publicSiteName}; + const publicSiteBody = {visibility: 'PUBLIC', title: publicSiteName}; - let privateSiteBody = {visibility: 'PRIVATE', title: privateSiteName}; + const privateSiteBody = {visibility: 'PRIVATE', title: privateSiteName}; publicSite = await alfrescoJsApi.core.sitesApi.createSite(publicSiteBody); diff --git a/e2e/content-services/share-file/share-file.e2e.ts b/e2e/content-services/share-file/share-file.e2e.ts index 1f5ffab72b..3776365a97 100644 --- a/e2e/content-services/share-file/share-file.e2e.ts +++ b/e2e/content-services/share-file/share-file.e2e.ts @@ -40,10 +40,10 @@ describe('Share file', () => { const navigationBarPage = new NavigationBarPage(); const viewerPage = new ViewerPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); @@ -62,7 +62,7 @@ describe('Share file', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); nodeId = pngUploadedFile.entry.id; diff --git a/e2e/content-services/share-file/unshare-file.e2e.ts b/e2e/content-services/share-file/unshare-file.e2e.ts index 64483aa5f0..d9b8d96b7f 100644 --- a/e2e/content-services/share-file/unshare-file.e2e.ts +++ b/e2e/content-services/share-file/unshare-file.e2e.ts @@ -40,12 +40,12 @@ describe('Unshare file', () => { const shareDialog = new ShareDialog(); const siteName = `PRIVATE-TEST-SITE-${Util.generateRandomString(5)}`; - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); let nodeBody; let nodeId; let testSite; - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); @@ -97,7 +97,7 @@ describe('Unshare file', () => { await this.alfrescoJsApi.core.sharedlinksApi.addSharedLink({ nodeId: testFile1Id }); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); nodeId = pngUploadedFile.entry.id; loginPage.loginToContentServicesUsingUserModel(acsUser); @@ -149,7 +149,7 @@ describe('Unshare file', () => { contentListPage.selectRow(pngFileModel.name); contentServicesPage.clickShareButton(); shareDialog.checkDialogIsDisplayed(); - let sharedLink = await shareDialog.getShareLink(); + const sharedLink = await shareDialog.getShareLink(); shareDialog.clickUnShareFile(); shareDialog.confirmationDialogIsDisplayed(); shareDialog.clickConfirmationDialogRemoveButton(); diff --git a/e2e/content-services/tag-component.e2e.ts b/e2e/content-services/tag-component.e2e.ts index d5c6fda406..20f79b4611 100644 --- a/e2e/content-services/tag-component.e2e.ts +++ b/e2e/content-services/tag-component.e2e.ts @@ -33,23 +33,23 @@ import { browser } from 'protractor'; describe('Tag component', () => { - let loginPage = new LoginPage(); - let tagPage = new TagPage(); - let appNavigationBarPage = new AppNavigationBarPage(); + const loginPage = new LoginPage(); + const tagPage = new TagPage(); + const appNavigationBarPage = new AppNavigationBarPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); - let pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name }); - let deleteFile = new FileModel({ 'name': Util.generateRandomString() }); - let sameTag = Util.generateRandomStringToLowerCase(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); + const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name }); + const deleteFile = new FileModel({ 'name': Util.generateRandomString() }); + const sameTag = Util.generateRandomStringToLowerCase(); - let tagList = [ + const tagList = [ Util.generateRandomStringToLowerCase(), Util.generateRandomStringToLowerCase(), Util.generateRandomStringToLowerCase(), Util.generateRandomStringToLowerCase()]; - let tags = [ + const tags = [ { tag: 'test-tag-01' }, { tag: 'test-tag-02' }, { tag: 'test-tag-03' }, { tag: 'test-tag-04' }, { tag: 'test-tag-05' }, { tag: 'test-tag-06' }, { tag: 'test-tag-07' }, { tag: 'test-tag-08' }, { tag: 'test-tag-09' }, { tag: 'test-tag-10' }, { tag: 'test-tag-11' }, { tag: 'test-tag-12' }, { tag: 'test-tag-13' }, { tag: 'test-tag-14' }, { tag: 'test-tag-15' }, @@ -57,9 +57,9 @@ describe('Tag component', () => { { tag: 'test-tag-21' }, { tag: 'test-tag-22' }, { tag: 'test-tag-23' }, { tag: 'test-tag-24' }, { tag: 'test-tag-25' }, { tag: 'test-tag-26' }, { tag: 'test-tag-27' }, { tag: 'test-tag-28' }, { tag: 'test-tag-29' }, { tag: 'test-tag-30' }]; - let uppercaseTag = Util.generateRandomStringToUpperCase(); - let digitsTag = Util.generateRandomStringDigits(); - let nonLatinTag = Util.generateRandomStringNonLatin(); + const uppercaseTag = Util.generateRandomStringToUpperCase(); + const digitsTag = Util.generateRandomStringDigits(); + const nonLatinTag = Util.generateRandomStringNonLatin(); let pdfUploadedFile, nodeId; beforeAll(async (done) => { @@ -78,7 +78,7 @@ describe('Tag component', () => { nodeId = pdfUploadedFile.entry.id; - let uploadedDeleteFile = await uploadActions.uploadFile(this.alfrescoJsApi, deleteFile.location, deleteFile.name, '-my-'); + const uploadedDeleteFile = await uploadActions.uploadFile(this.alfrescoJsApi, deleteFile.location, deleteFile.name, '-my-'); Object.assign(pdfFileModel, pdfUploadedFile.entry); @@ -160,7 +160,7 @@ describe('Tag component', () => { }); it('[C260375] Should be possible to delete a tag', () => { - let deleteTag = Util.generateRandomStringToUpperCase(); + const deleteTag = Util.generateRandomStringToUpperCase(); tagPage.insertNodeId(deleteFile.id); diff --git a/e2e/content-services/trashcan-pagination.e2e.ts b/e2e/content-services/trashcan-pagination.e2e.ts index aa8af99d23..5657ac4521 100644 --- a/e2e/content-services/trashcan-pagination.e2e.ts +++ b/e2e/content-services/trashcan-pagination.e2e.ts @@ -32,12 +32,12 @@ import { UploadActions } from '../actions/ACS/upload.actions'; import { browser } from 'protractor'; describe('Trashcan - Pagination', () => { - let pagination = { + const pagination = { base: 'newFile', extension: '.txt' }; - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5, ten: '10', @@ -49,19 +49,19 @@ describe('Trashcan - Pagination', () => { default: '25' }; - let loginPage = new LoginPage(); - let trashcanPage = new TrashcanPage(); - let paginationPage = new PaginationPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const trashcanPage = new TrashcanPage(); + const paginationPage = new PaginationPage(); + const navigationBarPage = new NavigationBarPage(); - let acsUser = new AcsUserModel(); - let newFolderModel = new FolderModel({ 'name': 'newFolder' }); - let nrOfFiles = 20; + const acsUser = new AcsUserModel(); + const newFolderModel = new FolderModel({ 'name': 'newFolder' }); + const nrOfFiles = 20; beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); - let fileNames = Util.generateSequenceFiles(10, nrOfFiles + 9, pagination.base, pagination.extension); + const fileNames = Util.generateSequenceFiles(10, nrOfFiles + 9, pagination.base, pagination.extension); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -74,9 +74,9 @@ describe('Trashcan - Pagination', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let folderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, newFolderModel.name, '-my-'); + const folderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, newFolderModel.name, '-my-'); - let emptyFiles = await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, folderUploadedModel.entry.id); + const emptyFiles = await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, folderUploadedModel.entry.id); await emptyFiles.list.entries.forEach(async (node) => { await this.alfrescoJsApi.node.deleteNode(node.entry.id).then(() => { }, () => { diff --git a/e2e/content-services/tree-view-component.e2e.ts b/e2e/content-services/tree-view-component.e2e.ts index 69298ce622..5dbdb53c7f 100644 --- a/e2e/content-services/tree-view-component.e2e.ts +++ b/e2e/content-services/tree-view-component.e2e.ts @@ -32,12 +32,12 @@ describe('Tree View Component', () => { const navigationBarPage = new NavigationBarPage(); const treeViewPage = new TreeViewPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); let treeFolder, secondTreeFolder, thirdTreeFolder; - let nodeNames = { + const nodeNames = { folder: 'Folder1', secondFolder: 'Folder2', thirdFolder: 'Folder3', diff --git a/e2e/content-services/upload/cancel-upload.e2e.ts b/e2e/content-services/upload/cancel-upload.e2e.ts index 5194952e0a..7fecda8a48 100644 --- a/e2e/content-services/upload/cancel-upload.e2e.ts +++ b/e2e/content-services/upload/cancel-upload.e2e.ts @@ -33,22 +33,22 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Upload component', () => { - let contentServicesPage = new ContentServicesPage(); - let uploadDialog = new UploadDialog(); - let uploadToggles = new UploadToggles(); - let loginPage = new LoginPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const contentServicesPage = new ContentServicesPage(); + const uploadDialog = new UploadDialog(); + const uploadToggles = new UploadToggles(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); - let firstPdfFileModel = new FileModel({ + const firstPdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF_B.file_location }); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let largeFile = new FileModel({ + const largeFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.LARGE_FILE.file_name, 'location': resources.Files.ADF_DOCUMENTS.LARGE_FILE.file_location }); @@ -69,7 +69,7 @@ describe('Upload component', () => { contentServicesPage.goToDocumentList(); - let pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, '-my-'); + const pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, '-my-'); Object.assign(firstPdfFileModel, pdfUploadedFile.entry); @@ -81,7 +81,7 @@ describe('Upload component', () => { }); afterEach(async (done) => { - let nodesPromise = await contentServicesPage.getElementsDisplayedId(); + const nodesPromise = await contentServicesPage.getElementsDisplayedId(); nodesPromise.forEach(async (currentNode) => { if (currentNode && currentNode !== 'Node id') { diff --git a/e2e/content-services/upload/excluded-file.e2e.ts b/e2e/content-services/upload/excluded-file.e2e.ts index 596159365f..181d587dfa 100644 --- a/e2e/content-services/upload/excluded-file.e2e.ts +++ b/e2e/content-services/upload/excluded-file.e2e.ts @@ -36,30 +36,30 @@ import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; describe('Upload component - Excluded Files', () => { - let contentServicesPage = new ContentServicesPage(); - let uploadDialog = new UploadDialog(); - let uploadToggles = new UploadToggles(); - let loginPage = new LoginPage(); - let acsUser = new AcsUserModel(); - let navigationBarPage = new NavigationBarPage(); - let configEditorPage = new ConfigEditorPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadDialog = new UploadDialog(); + const uploadToggles = new UploadToggles(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const navigationBarPage = new NavigationBarPage(); + const configEditorPage = new ConfigEditorPage(); - let iniExcludedFile = new FileModel({ + const iniExcludedFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.INI.file_name, 'location': resources.Files.ADF_DOCUMENTS.INI.file_location }); - let folderWithExcludedFile = new FolderModel({ + const folderWithExcludedFile = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.FOLDER_EXCLUDED.folder_name, 'location': resources.Files.ADF_DOCUMENTS.FOLDER_EXCLUDED.folder_location }); - let txtFileModel = new FileModel({ + const txtFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location }); - let pngFile = new FileModel({ + const pngFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); @@ -91,9 +91,9 @@ describe('Upload component - Excluded Files', () => { it('[C279914] Should not allow upload default excluded files using D&D', () => { contentServicesPage.checkDragAndDropDIsDisplayed(); - let dragAndDropArea = element.all(by.css('adf-upload-drag-area div')).first(); + const dragAndDropArea = element.all(by.css('adf-upload-drag-area div')).first(); - let dragAndDrop = new DropActions(); + const dragAndDrop = new DropActions(); dragAndDrop.dropFile(dragAndDropArea, iniExcludedFile.location); diff --git a/e2e/content-services/upload/upload-dialog.ts b/e2e/content-services/upload/upload-dialog.ts index 37737ed837..fdab497c4b 100644 --- a/e2e/content-services/upload/upload-dialog.ts +++ b/e2e/content-services/upload/upload-dialog.ts @@ -31,35 +31,35 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Upload component', () => { - let contentServicesPage = new ContentServicesPage(); - let uploadDialog = new UploadDialog(); - let uploadToggles = new UploadToggles(); - let loginPage = new LoginPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const contentServicesPage = new ContentServicesPage(); + const uploadDialog = new UploadDialog(); + const uploadToggles = new UploadToggles(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); - let firstPdfFileModel = new FileModel({ + const firstPdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF_B.file_location }); - let docxFileModel = new FileModel({ + const docxFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - let pdfFileModel = new FileModel({ + const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let pngFileModelTwo = new FileModel({ + const pngFileModelTwo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_B.file_location }); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let filesLocation = [pdfFileModel.location, docxFileModel.location, pngFileModel.location, firstPdfFileModel.location]; - let filesName = [pdfFileModel.name, docxFileModel.name, pngFileModel.name, firstPdfFileModel.name]; + const filesLocation = [pdfFileModel.location, docxFileModel.location, pngFileModel.location, firstPdfFileModel.location]; + const filesName = [pdfFileModel.name, docxFileModel.name, pngFileModel.name, firstPdfFileModel.name]; beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -77,7 +77,7 @@ describe('Upload component', () => { contentServicesPage.goToDocumentList(); - let pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, '-my-'); + const pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, '-my-'); Object.assign(firstPdfFileModel, pdfUploadedFile.entry); @@ -89,7 +89,7 @@ describe('Upload component', () => { }); afterEach(async (done) => { - let nodesPromise = await contentServicesPage.getElementsDisplayedId(); + const nodesPromise = await contentServicesPage.getElementsDisplayedId(); nodesPromise.forEach(async (currentNodePromise) => { await currentNodePromise.then(async (currentNode) => { diff --git a/e2e/content-services/upload/uploader-component.e2e.ts b/e2e/content-services/upload/uploader-component.e2e.ts index a79d341cea..e23fb66c18 100644 --- a/e2e/content-services/upload/uploader-component.e2e.ts +++ b/e2e/content-services/upload/uploader-component.e2e.ts @@ -37,48 +37,48 @@ import { DropActions } from '../../actions/drop.actions'; describe('Upload component', () => { - let contentServicesPage = new ContentServicesPage(); - let uploadDialog = new UploadDialog(); - let uploadToggles = new UploadToggles(); - let loginPage = new LoginPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); - let navigationBarPage = new NavigationBarPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadDialog = new UploadDialog(); + const uploadToggles = new UploadToggles(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); + const navigationBarPage = new NavigationBarPage(); - let firstPdfFileModel = new FileModel({ + const firstPdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF_B.file_location }); - let docxFileModel = new FileModel({ + const docxFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - let pdfFileModel = new FileModel({ + const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let fileWithSpecificSize = new FileModel({ + const fileWithSpecificSize = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_400B.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT_400B.file_location }); - let emptyFile = new FileModel({ + const emptyFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location }); - let folderOne = new FolderModel({ + const folderOne = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.FOLDER_ONE.folder_name, 'location': resources.Files.ADF_DOCUMENTS.FOLDER_ONE.folder_location }); - let folderTwo = new FolderModel({ + const folderTwo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.FOLDER_TWO.folder_name, 'location': resources.Files.ADF_DOCUMENTS.FOLDER_TWO.folder_location }); - let uploadedFileInFolder = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.FILE_INSIDE_FOLDER_ONE.file_name }); - let uploadedFileInFolderTwo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.FILE_INSIDE_FOLDER_TWO.file_name }); + const uploadedFileInFolder = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.FILE_INSIDE_FOLDER_ONE.file_name }); + const uploadedFileInFolderTwo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.FILE_INSIDE_FOLDER_TWO.file_name }); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -96,7 +96,7 @@ describe('Upload component', () => { contentServicesPage.goToDocumentList(); - let pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, '-my-'); + const pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, '-my-'); Object.assign(firstPdfFileModel, pdfUploadedFile.entry); @@ -349,8 +349,8 @@ describe('Upload component', () => { browser.driver.sleep(1000); uploadToggles.addExtension('.docx'); - let dragAndDrop = new DropActions(); - let dragAndDropArea = element.all(by.css('adf-upload-drag-area div')).first(); + const dragAndDrop = new DropActions(); + const dragAndDropArea = element.all(by.css('adf-upload-drag-area div')).first(); dragAndDrop.dropFile(dragAndDropArea, docxFileModel.location); contentServicesPage.checkContentIsDisplayed(docxFileModel.name); @@ -365,9 +365,9 @@ describe('Upload component', () => { }); it('[C291921] Should display tooltip for uploading files on a not found location', async () => { - let folderName = Util.generateRandomString(8); + const folderName = Util.generateRandomString(8); - let folderUploadedModel = await browser.controlFlow().execute(async () => { + const folderUploadedModel = await browser.controlFlow().execute(async () => { return await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); }); diff --git a/e2e/content-services/upload/user-permission.e2e.ts b/e2e/content-services/upload/user-permission.e2e.ts index b2f651b11d..675cf5a1a9 100644 --- a/e2e/content-services/upload/user-permission.e2e.ts +++ b/e2e/content-services/upload/user-permission.e2e.ts @@ -39,31 +39,31 @@ import CONSTANTS = require('../../util/constants'); describe('Upload - User permission', () => { - let contentServicesPage = new ContentServicesPage(); - let uploadDialog = new UploadDialog(); - let uploadToggles = new UploadToggles(); - let loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadDialog = new UploadDialog(); + const uploadToggles = new UploadToggles(); + const loginPage = new LoginPage(); let acsUser; let acsUserTwo; - let navigationBarPage = new NavigationBarPage(); - let notificationPage = new NotificationPage(); + const navigationBarPage = new NavigationBarPage(); + const notificationPage = new NotificationPage(); - let emptyFile = new FileModel({ + const emptyFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location }); - let pngFile = new FileModel({ + const pngFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let pdfFile = new FileModel({ + const pdfFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location }); - let folder = new FolderModel({ + const folder = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.FOLDER_TWO.folder_name, 'location': resources.Files.ADF_DOCUMENTS.FOLDER_TWO.folder_location }); @@ -134,7 +134,7 @@ describe('Upload - User permission', () => { contentServicesPage.dragAndDropFile(emptyFile.location); contentServicesPage.dragAndDropFolder(folder.location); - let fileInTheUploadedFolder = 'share_profile_pic.png'; + const fileInTheUploadedFolder = 'share_profile_pic.png'; uploadDialog.fileIsError(emptyFile.name); uploadDialog.fileIsError(fileInTheUploadedFolder); @@ -180,7 +180,7 @@ describe('Upload - User permission', () => { contentServicesPage.uploadFolder(folder.location) .checkContentIsDisplayed(folder.name); - let fileInTheUploadedFolder = 'share_profile_pic.png'; + const fileInTheUploadedFolder = 'share_profile_pic.png'; uploadDialog.fileIsUploaded(fileInTheUploadedFolder); @@ -218,7 +218,7 @@ describe('Upload - User permission', () => { contentServicesPage.dragAndDropFolder(folder.location); contentServicesPage.checkContentIsDisplayed(folder.name); - let fileInTheUploadedFolder = 'share_profile_pic.png'; + const fileInTheUploadedFolder = 'share_profile_pic.png'; uploadDialog.fileIsUploaded(emptyFile.name); uploadDialog.fileIsUploaded(fileInTheUploadedFolder); @@ -239,7 +239,7 @@ describe('Upload - User permission', () => { contentServicesPage.checkContentIsDisplayed(folder.name); }); - let fileInTheUploadedFolder = 'share_profile_pic.png'; + const fileInTheUploadedFolder = 'share_profile_pic.png'; uploadDialog.fileIsUploaded(fileInTheUploadedFolder); }); diff --git a/e2e/content-services/version/version-actions.e2e.ts b/e2e/content-services/version/version-actions.e2e.ts index 78644f1f63..77ea27701f 100644 --- a/e2e/content-services/version/version-actions.e2e.ts +++ b/e2e/content-services/version/version-actions.e2e.ts @@ -40,21 +40,21 @@ describe('Version component actions', () => { const versionManagePage = new VersionManagePage(); const navigationBarPage = new NavigationBarPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let txtFileModel = new FileModel({ + const txtFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT.file_location }); - let fileModelVersionTwo = new FileModel({ + const fileModelVersionTwo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -67,7 +67,7 @@ describe('Version component actions', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let txtUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileModel.location, txtFileModel.name, '-my-'); + const txtUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileModel.location, txtFileModel.name, '-my-'); Object.assign(txtFileModel, txtUploadedFile.entry); diff --git a/e2e/content-services/version/version-permissions.e2e.ts b/e2e/content-services/version/version-permissions.e2e.ts index dd4d6deffb..02ffce4376 100644 --- a/e2e/content-services/version/version-permissions.e2e.ts +++ b/e2e/content-services/version/version-permissions.e2e.ts @@ -47,32 +47,32 @@ describe('Version component permissions', () => { const contentServices = new ContentServicesPage(); let site; - let acsUser = new AcsUserModel(); - let consumerUser = new AcsUserModel(); - let collaboratorUser = new AcsUserModel(); - let contributorUser = new AcsUserModel(); - let managerUser = new AcsUserModel(); - let fileCreatorUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); + const consumerUser = new AcsUserModel(); + const collaboratorUser = new AcsUserModel(); + const contributorUser = new AcsUserModel(); + const managerUser = new AcsUserModel(); + const fileCreatorUser = new AcsUserModel(); - let newVersionFile = new FileModel({ + const newVersionFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_B.file_location }); - let lockFileModel = new FileModel({ + const lockFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_C.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_C.file_location }); - let differentCreatorFile = new FileModel({ + const differentCreatorFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_D.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_D.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); - let nodeActions = new NodeActions(); + const uploadActions = new UploadActions(); + const nodeActions = new NodeActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -118,7 +118,7 @@ describe('Version component permissions', () => { role: CONSTANTS.CS_USER_ROLES.MANAGER }); - let lockFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, lockFileModel.location, lockFileModel.name, site.entry.guid); + const lockFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, lockFileModel.location, lockFileModel.name, site.entry.guid); Object.assign(lockFileModel, lockFileUploaded.entry); nodeActions.lockNode(this.alfrescoJsApi, lockFileModel.id); @@ -132,17 +132,17 @@ describe('Version component permissions', () => { describe('Manager', () => { - let sameCreatorFile = new FileModel({ + const sameCreatorFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); await this.alfrescoJsApi.login(managerUser.id, managerUser.password); - let sameCreatorFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, sameCreatorFile.location, sameCreatorFile.name, site.entry.guid); + const sameCreatorFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, sameCreatorFile.location, sameCreatorFile.name, site.entry.guid); Object.assign(sameCreatorFile, sameCreatorFileUploaded.entry); loginPage.loginToContentServicesUsingUserModel(managerUser); @@ -239,17 +239,17 @@ describe('Version component permissions', () => { }); describe('Contributor', () => { - let sameCreatorFile = new FileModel({ + const sameCreatorFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); await this.alfrescoJsApi.login(contributorUser.id, contributorUser.password); - let sameCreatorFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, sameCreatorFile.location, sameCreatorFile.name, site.entry.guid); + const sameCreatorFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, sameCreatorFile.location, sameCreatorFile.name, site.entry.guid); Object.assign(sameCreatorFile, sameCreatorFileUploaded.entry); loginPage.loginToContentServicesUsingUserModel(contributorUser); @@ -299,17 +299,17 @@ describe('Version component permissions', () => { }); describe('Collaborator', () => { - let sameCreatorFile = new FileModel({ + const sameCreatorFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); await this.alfrescoJsApi.login(collaboratorUser.id, collaboratorUser.password); - let sameCreatorFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, sameCreatorFile.location, sameCreatorFile.name, site.entry.guid); + const sameCreatorFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, sameCreatorFile.location, sameCreatorFile.name, site.entry.guid); Object.assign(sameCreatorFile, sameCreatorFileUploaded.entry); loginPage.loginToContentServicesUsingUserModel(collaboratorUser); diff --git a/e2e/content-services/version/version-properties.e2e.ts b/e2e/content-services/version/version-properties.e2e.ts index f649a73173..db897c9a20 100644 --- a/e2e/content-services/version/version-properties.e2e.ts +++ b/e2e/content-services/version/version-properties.e2e.ts @@ -39,21 +39,21 @@ describe('Version Properties', () => { const versionManagePage = new VersionManagePage(); const navigationBarPage = new NavigationBarPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let txtFileModel = new FileModel({ + const txtFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location }); - let fileModelVersionTwo = new FileModel({ + const fileModelVersionTwo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -66,7 +66,7 @@ describe('Version Properties', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let txtUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileModel.location, txtFileModel.name, '-my-'); + const txtUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileModel.location, txtFileModel.name, '-my-'); Object.assign(txtFileModel, txtUploadedFile.entry); diff --git a/e2e/content-services/version/version-smoke-tests.e2e.ts b/e2e/content-services/version/version-smoke-tests.e2e.ts index 49af53ec45..188c4d2d85 100644 --- a/e2e/content-services/version/version-smoke-tests.e2e.ts +++ b/e2e/content-services/version/version-smoke-tests.e2e.ts @@ -40,36 +40,36 @@ describe('Version component', () => { const navigationBarPage = new NavigationBarPage(); const versionManagePage = new VersionManagePage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let txtFileModel = new FileModel({ + const txtFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT.file_location }); - let fileModelVersionTwo = new FileModel({ + const fileModelVersionTwo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let fileModelVersionThree = new FileModel({ + const fileModelVersionThree = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_B.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_B.file_location }); - let fileModelVersionFor = new FileModel({ + const fileModelVersionFor = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_C.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_C.file_location }); - let fileModelVersionFive = new FileModel({ + const fileModelVersionFive = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG_D.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG_D.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', diff --git a/e2e/core/card-view/aspect-oriented-config.e2e.ts b/e2e/core/card-view/aspect-oriented-config.e2e.ts index 1ed8740e8e..83ab506542 100644 --- a/e2e/core/card-view/aspect-oriented-config.e2e.ts +++ b/e2e/core/card-view/aspect-oriented-config.e2e.ts @@ -41,20 +41,20 @@ describe('Aspect oriented config', () => { const metadataViewPage = new MetadataViewPage(); const navigationBarPage = new NavigationBarPage(); const configEditorPage = new ConfigEditorPage(); - let contentServicesPage = new ContentServicesPage(); - let modelOneName = 'modelOne', emptyAspectName = 'emptyAspect'; - let defaultModel = 'cm', defaultEmptyPropertiesAspect = 'taggable', aspectName = 'Taggable'; + const contentServicesPage = new ContentServicesPage(); + const modelOneName = 'modelOne', emptyAspectName = 'emptyAspect'; + const defaultModel = 'cm', defaultEmptyPropertiesAspect = 'taggable', aspectName = 'Taggable'; - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -77,11 +77,11 @@ describe('Aspect oriented config', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let uploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); + const uploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); loginPage.loginToContentServicesUsingUserModel(acsUser); - let aspects = await this.alfrescoJsApi.core.nodesApi.getNode(uploadedFile.entry.id); + const aspects = await this.alfrescoJsApi.core.nodesApi.getNode(uploadedFile.entry.id); aspects.entry.aspectNames.push(modelOneName.concat(':', emptyAspectName)); diff --git a/e2e/core/card-view/card-view-component.e2e.ts b/e2e/core/card-view/card-view-component.e2e.ts index 6c246f5ced..8524558eff 100644 --- a/e2e/core/card-view/card-view-component.e2e.ts +++ b/e2e/core/card-view/card-view-component.e2e.ts @@ -45,7 +45,7 @@ describe('CardView Component', () => { describe('key-value pair ', () => { it('[C279938] Should the label be present', () => { - let label = element(by.css('div[data-automation-id="card-key-value-pairs-label-key-value-pairs"]')); + const label = element(by.css('div[data-automation-id="card-key-value-pairs-label-key-value-pairs"]')); Util.waitUntilElementIsPresent(label); }); @@ -67,7 +67,7 @@ describe('CardView Component', () => { describe('SelectBox', () => { it('[C279939] Should the label be present', () => { - let label = element(by.css('div[data-automation-id="card-select-label-select"]')); + const label = element(by.css('div[data-automation-id="card-select-label-select"]')); Util.waitUntilElementIsPresent(label); }); @@ -84,7 +84,7 @@ describe('CardView Component', () => { describe('Text', () => { it('[C279937] Should the label be present', () => { - let label = element(by.css('div[data-automation-id="card-textitem-label-name"]')); + const label = element(by.css('div[data-automation-id="card-textitem-label-name"]')); Util.waitUntilElementIsPresent(label); }); @@ -115,7 +115,7 @@ describe('CardView Component', () => { describe('Int', () => { it('[C279940] Should the label be present', () => { - let label = element(by.css('div[data-automation-id="card-textitem-label-int"]')); + const label = element(by.css('div[data-automation-id="card-textitem-label-int"]')); Util.waitUntilElementIsPresent(label); }); @@ -189,7 +189,7 @@ describe('CardView Component', () => { describe('Float', () => { it('[C279941] Should the label be present', () => { - let label = element(by.css('div[data-automation-id="card-textitem-label-float"]')); + const label = element(by.css('div[data-automation-id="card-textitem-label-float"]')); Util.waitUntilElementIsPresent(label); }); @@ -239,7 +239,7 @@ describe('CardView Component', () => { describe('Boolean', () => { it('[C279942] Should the label be present', () => { - let label = element(by.css('div[data-automation-id="card-boolean-label-boolean"]')); + const label = element(by.css('div[data-automation-id="card-boolean-label-boolean"]')); Util.waitUntilElementIsPresent(label); }); @@ -258,11 +258,11 @@ describe('CardView Component', () => { describe('Date and DateTime', () => { it('[C279961] Should the label be present', () => { - let labelDate = element(by.css('div[data-automation-id="card-dateitem-label-date"]')); + const labelDate = element(by.css('div[data-automation-id="card-dateitem-label-date"]')); Util.waitUntilElementIsPresent(labelDate); - let labelDatetime = element(by.css('div[data-automation-id="card-dateitem-label-datetime"]')); + const labelDatetime = element(by.css('div[data-automation-id="card-dateitem-label-datetime"]')); Util.waitUntilElementIsPresent(labelDatetime); }); @@ -277,11 +277,11 @@ describe('CardView Component', () => { it('[C279936] Should not be possible edit any parameter when editable property is false', () => { cardViewPageComponent.disableEdit(); - let editIconText = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-name"]')); - let editIconInt = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-int"]')); - let editIconFloat = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-float"]')); - let editIconKey = element(by.css('mat-icon[data-automation-id="card-key-value-pairs-button-key-value-pairs"]')); - let editIconData = element(by.css('mat-datetimepicker-toggle')); + const editIconText = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-name"]')); + const editIconInt = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-int"]')); + const editIconFloat = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-float"]')); + const editIconKey = element(by.css('mat-icon[data-automation-id="card-key-value-pairs-button-key-value-pairs"]')); + const editIconData = element(by.css('mat-datetimepicker-toggle')); Util.waitUntilElementIsNotVisible(editIconText); Util.waitUntilElementIsNotVisible(editIconInt); diff --git a/e2e/core/card-view/metadata-permissions.e2e.ts b/e2e/core/card-view/metadata-permissions.e2e.ts index ff95461dd5..b688e7899d 100644 --- a/e2e/core/card-view/metadata-permissions.e2e.ts +++ b/e2e/core/card-view/metadata-permissions.e2e.ts @@ -52,19 +52,19 @@ describe('permissions', () => { const metadataViewPage = new MetadataViewPage(); const navigationBarPage = new NavigationBarPage(); - let consumerUser = new AcsUserModel(); - let collaboratorUser = new AcsUserModel(); - let contributorUser = new AcsUserModel(); + const consumerUser = new AcsUserModel(); + const collaboratorUser = new AcsUserModel(); + const contributorUser = new AcsUserModel(); let site; - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', diff --git a/e2e/core/card-view/metadata-properties.e2e.ts b/e2e/core/card-view/metadata-properties.e2e.ts index b087b87a30..abd670ce0d 100644 --- a/e2e/core/card-view/metadata-properties.e2e.ts +++ b/e2e/core/card-view/metadata-properties.e2e.ts @@ -33,7 +33,7 @@ import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; describe('CardView Component - properties', () => { - let METADATA = { + const METADATA = { DATA_FORMAT: 'mmm dd yyyy', TITLE: 'Details', COMMENTS_TAB: 'COMMENTS', @@ -46,22 +46,22 @@ describe('CardView Component - properties', () => { EDIT_BUTTON_TOOLTIP: 'Edit' }; - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let viewerPage = new ViewerPage(); - let metadataViewPage = new MetadataViewPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const viewerPage = new ViewerPage(); + const metadataViewPage = new MetadataViewPage(); const contentServicesPage = new ContentServicesPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -74,7 +74,7 @@ describe('CardView Component - properties', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); + const pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); Object.assign(pngFileModel, pdfUploadedFile.entry); diff --git a/e2e/core/card-view/metadata-smoke-tests.e2e.ts b/e2e/core/card-view/metadata-smoke-tests.e2e.ts index 623ce61199..5a1fee3d40 100644 --- a/e2e/core/card-view/metadata-smoke-tests.e2e.ts +++ b/e2e/core/card-view/metadata-smoke-tests.e2e.ts @@ -54,16 +54,16 @@ describe('Metadata component', () => { const metadataViewPage = new MetadataViewPage(); const navigationBarPage = new NavigationBarPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let folderName = 'Metadata Folder'; + const folderName = 'Metadata Folder'; - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); let fileUrl; @@ -80,7 +80,7 @@ describe('Metadata component', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); + const pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, '-my-'); Object.assign(pngFileModel, pngUploadedFile.entry); diff --git a/e2e/core/datatable/data-table-component-selection.e2e.ts b/e2e/core/datatable/data-table-component-selection.e2e.ts index 5cf971315a..6539cfd321 100644 --- a/e2e/core/datatable/data-table-component-selection.e2e.ts +++ b/e2e/core/datatable/data-table-component-selection.e2e.ts @@ -26,11 +26,11 @@ import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; describe('Datatable component - selection', () => { - let dataTablePage = new DataTablePage(); - let loginPage = new LoginPage(); - let acsUser = new AcsUserModel(); - let navigationBarPage = new NavigationBarPage(); - let dataTableComponent = new DataTableComponentPage(); + const dataTablePage = new DataTablePage(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const navigationBarPage = new NavigationBarPage(); + const dataTableComponent = new DataTableComponentPage(); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ diff --git a/e2e/core/error-component.e2e.ts b/e2e/core/error-component.e2e.ts index d2782b176e..d17f7d4f54 100644 --- a/e2e/core/error-component.e2e.ts +++ b/e2e/core/error-component.e2e.ts @@ -24,9 +24,9 @@ import { browser } from '../../node_modules/protractor'; describe('Error Component', () => { - let acsUser = new AcsUserModel(); - let loginPage = new LoginPage(); - let errorPage = new ErrorPage(); + const acsUser = new AcsUserModel(); + const loginPage = new LoginPage(); + const errorPage = new ErrorPage(); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ diff --git a/e2e/core/header-component.e2e.ts b/e2e/core/header-component.e2e.ts index bd3df3c73b..33078d107b 100644 --- a/e2e/core/header-component.e2e.ts +++ b/e2e/core/header-component.e2e.ts @@ -26,14 +26,14 @@ import { UsersActions } from '../actions/users.actions'; describe('Header Component', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let headerPage = new HeaderPage(); - let settingsPage = new SettingsPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const headerPage = new HeaderPage(); + const settingsPage = new SettingsPage(); let user, tenantId; - let names = { + const names = { app_title_default: 'ADF Demo Application', app_title_custom: 'New Test App', urlPath_default: './assets/images/logo.png', @@ -53,7 +53,7 @@ describe('Header Component', () => { hostBpm: TestConfig.adf.url }); - let users = new UsersActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); diff --git a/e2e/core/icons-component.e2e.ts b/e2e/core/icons-component.e2e.ts index 07a655d3ef..ba2cdfe174 100644 --- a/e2e/core/icons-component.e2e.ts +++ b/e2e/core/icons-component.e2e.ts @@ -25,10 +25,10 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; describe('Universal Icon component', function () { - let loginPage = new LoginPage(); - let acsUser = new AcsUserModel(); - let navigationBarPage = new NavigationBarPage(); - let iconsPage = new IconsPage(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const navigationBarPage = new NavigationBarPage(); + const iconsPage = new IconsPage(); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ diff --git a/e2e/core/infinite-scrolling.e2e.ts b/e2e/core/infinite-scrolling.e2e.ts index 3aacd5769f..c7417189d4 100644 --- a/e2e/core/infinite-scrolling.e2e.ts +++ b/e2e/core/infinite-scrolling.e2e.ts @@ -38,21 +38,24 @@ describe('Enable infinite scrolling', () => { const configEditorPage = new ConfigEditorPage(); const navigationBarPage = new NavigationBarPage(); - let acsUser = new AcsUserModel(); - let folderModel = new FolderModel({ 'name': 'folderOne' }); + const acsUser = new AcsUserModel(); + const folderModel = new FolderModel({ 'name': 'folderOne' }); - let fileNames = [], nrOfFiles = 30, deleteFileNames = [], nrOfDeletedFiles = 22; + let fileNames = []; + const nrOfFiles = 30; + let deleteFileNames = []; + const nrOfDeletedFiles = 22; let deleteUploaded; - let pageSize = 20; + const pageSize = 20; let emptyFolderModel; - let files = { + const files = { base: 'newFile', extension: '.txt' }; beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -70,7 +73,7 @@ describe('Enable infinite scrolling', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let folderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, folderModel.name, '-my-'); + const folderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, folderModel.name, '-my-'); emptyFolderModel = await uploadActions.createFolder(this.alfrescoJsApi, 'emptyFolder', '-my-'); await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, folderUploadedModel.entry.id); diff --git a/e2e/core/login/login-component.e2e.ts b/e2e/core/login/login-component.e2e.ts index 226ab74a62..21dc1db9a4 100644 --- a/e2e/core/login/login-component.e2e.ts +++ b/e2e/core/login/login-component.e2e.ts @@ -35,29 +35,29 @@ import { ErrorPage } from '../../pages/adf/errorPage'; describe('Login component', () => { - let settingsPage = new SettingsPage(); - let processServicesPage = new ProcessServicesPage(); - let navigationBarPage = new NavigationBarPage(); - let userInfoPage = new UserInfoPage(); - let contentServicesPage = new ContentServicesPage(); - let loginPage = new LoginPage(); - let errorPage = new ErrorPage(); - let adminUserModel = new AcsUserModel({ + const settingsPage = new SettingsPage(); + const processServicesPage = new ProcessServicesPage(); + const navigationBarPage = new NavigationBarPage(); + const userInfoPage = new UserInfoPage(); + const contentServicesPage = new ContentServicesPage(); + const loginPage = new LoginPage(); + const errorPage = new ErrorPage(); + const adminUserModel = new AcsUserModel({ 'id': TestConfig.adf.adminUser, 'password': TestConfig.adf.adminPassword }); - let userA = new AcsUserModel(); - let userB = new AcsUserModel(); + const userA = new AcsUserModel(); + const userB = new AcsUserModel(); - let errorMessages = { + const errorMessages = { username: 'Your username needs to be at least 2 characters.', invalid_credentials: 'You\'ve entered an unknown username or password', password: 'Enter your password to sign in', required: 'Required' }; - let invalidUsername = 'invaliduser'; - let invalidPassword = 'invalidpassword'; + const invalidUsername = 'invaliduser'; + const invalidPassword = 'invalidpassword'; beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ diff --git a/e2e/core/login/login-sso/login-sso.e2e.ts b/e2e/core/login/login-sso/login-sso.e2e.ts index 5d7a3a7466..3d7a1c6da7 100644 --- a/e2e/core/login/login-sso/login-sso.e2e.ts +++ b/e2e/core/login/login-sso/login-sso.e2e.ts @@ -28,7 +28,9 @@ describe('Login component - SSO', () => { const loginApsPage = new LoginSSOPage(); const loginPage = new LoginPage(); const navigationBarPage = new NavigationBarPage(); - let silentLogin, implicitFlow; + + const silentLogin = false; + let implicitFlow; describe('Login component - SSO implicit Flow', () => { diff --git a/e2e/core/login/redirection.e2e.ts b/e2e/core/login/redirection.e2e.ts index 3f464b445a..f5d51f0250 100644 --- a/e2e/core/login/redirection.e2e.ts +++ b/e2e/core/login/redirection.e2e.ts @@ -35,19 +35,19 @@ import { LogoutPage } from '../../pages/adf/demo-shell/logoutPage'; describe('Login component - Redirect', () => { - let settingsPage = new SettingsPage(); - let processServicesPage = new ProcessServicesPage(); - let navigationBarPage = new NavigationBarPage(); - let contentServicesPage = new ContentServicesPage(); - let loginPage = new LoginPage(); - let user = new AcsUserModel(); - let userFolderOwner = new AcsUserModel(); - let adminUserModel = new AcsUserModel({ + const settingsPage = new SettingsPage(); + const processServicesPage = new ProcessServicesPage(); + const navigationBarPage = new NavigationBarPage(); + const contentServicesPage = new ContentServicesPage(); + const loginPage = new LoginPage(); + const user = new AcsUserModel(); + const userFolderOwner = new AcsUserModel(); + const adminUserModel = new AcsUserModel({ 'id': TestConfig.adf.adminUser, 'password': TestConfig.adf.adminPassword }); let uploadedFolder; - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); const logoutPage = new LogoutPage(); beforeAll(async (done) => { diff --git a/e2e/core/login/remember-me.e2e.ts b/e2e/core/login/remember-me.e2e.ts index a72ab2335e..135e16de50 100644 --- a/e2e/core/login/remember-me.e2e.ts +++ b/e2e/core/login/remember-me.e2e.ts @@ -20,8 +20,8 @@ import { SettingsPage } from '../../pages/adf/settingsPage'; describe('Login component - Remember Me', () => { - let settingsPage = new SettingsPage(); - let loginPage = new LoginPage(); + const settingsPage = new SettingsPage(); + const loginPage = new LoginPage(); beforeAll((done) => { settingsPage.setProviderEcmBpm(); diff --git a/e2e/core/pagination-empty-current-page.e2e.ts b/e2e/core/pagination-empty-current-page.e2e.ts index ec2622d02e..a9169c2685 100644 --- a/e2e/core/pagination-empty-current-page.e2e.ts +++ b/e2e/core/pagination-empty-current-page.e2e.ts @@ -33,36 +33,40 @@ import TestConfig = require('../test.config'); describe('Pagination - returns to previous page when current is empty', () => { - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let paginationPage = new PaginationPage(); - let viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const paginationPage = new PaginationPage(); + const viewerPage = new ViewerPage(); - let acsUser = new AcsUserModel(); - let folderModel = new FolderModel({ 'name': 'folderOne' }); - let parentFolderModel = new FolderModel({ 'name': 'parentFolder' }); + const acsUser = new AcsUserModel(); + const folderModel = new FolderModel({ 'name': 'folderOne' }); + const parentFolderModel = new FolderModel({ 'name': 'parentFolder' }); - let fileNames = [], nrOfFiles = 6, nrOfFolders = 5; - let lastFile = 'newFile6.txt', lastFolderResponse, pngFileUploaded; - let folderNames = ['t1', 't2', 't3', 't4', 't5', 't6']; + let fileNames = []; + const nrOfFiles = 6; + const nrOfFolders = 5; + const lastFile = 'newFile6.txt'; + let lastFolderResponse; + let pngFileUploaded; + const folderNames = ['t1', 't2', 't3', 't4', 't5', 't6']; - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5 }; - let files = { + const files = { base: 'newFile', extension: '.txt' }; - let pngFileInfo = new FileModel({ + const pngFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -77,9 +81,9 @@ describe('Pagination - returns to previous page when current is empty', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let folderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, folderModel.name, '-my-'); + const folderUploadedModel = await uploadActions.createFolder(this.alfrescoJsApi, folderModel.name, '-my-'); - let parentFolderResponse = await uploadActions.createFolder(this.alfrescoJsApi, parentFolderModel.name, '-my-'); + const parentFolderResponse = await uploadActions.createFolder(this.alfrescoJsApi, parentFolderModel.name, '-my-'); for (let i = 0; i < nrOfFolders; i++) { await uploadActions.createFolder(this.alfrescoJsApi, folderNames[i], parentFolderResponse.entry.id); diff --git a/e2e/core/settings-component.e2e.ts b/e2e/core/settings-component.e2e.ts index 0f9897353d..ecbd392e4b 100644 --- a/e2e/core/settings-component.e2e.ts +++ b/e2e/core/settings-component.e2e.ts @@ -34,7 +34,7 @@ describe('Settings component', () => { const loginError = 'Request has been terminated ' + 'Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.'; - let adminUserModel = new AcsUserModel({ + const adminUserModel = new AcsUserModel({ 'id': TestConfig.adf.adminUser, 'password': TestConfig.adf.adminPassword }); diff --git a/e2e/core/user-info-component.e2e.ts b/e2e/core/user-info-component.e2e.ts index 619e1056c7..0dd4243b27 100644 --- a/e2e/core/user-info-component.e2e.ts +++ b/e2e/core/user-info-component.e2e.ts @@ -33,21 +33,21 @@ import { browser } from 'protractor'; describe('User Info component', () => { - let settingsPage = new SettingsPage(); - let loginPage = new LoginPage(); - let userInfoPage = new UserInfoPage(); + const settingsPage = new SettingsPage(); + const loginPage = new LoginPage(); + const userInfoPage = new UserInfoPage(); let processUserModel, contentUserModel; - let acsAvatarFileModel = new FileModel({ + const acsAvatarFileModel = new FileModel({ 'name': resources.Files.PROFILE_IMAGES.ECM.file_name, 'location': resources.Files.PROFILE_IMAGES.ECM.file_location }); - let apsAvatarFileModel = new FileModel({ + const apsAvatarFileModel = new FileModel({ 'name': resources.Files.PROFILE_IMAGES.BPM.file_name, 'location': resources.Files.PROFILE_IMAGES.BPM.file_location }); beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ALL', @@ -166,7 +166,7 @@ describe('User Info component', () => { }); it('[C260118] Should display UserInfo with profile image uploaded in APS', async () => { - let users = new UsersActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(contentUserModel.email, contentUserModel.password); await users.changeProfilePictureAps(this.alfrescoJsApi, apsAvatarFileModel.getLocation()); diff --git a/e2e/core/viewer/viewer-component.e2e.ts b/e2e/core/viewer/viewer-component.e2e.ts index 8f6c4eb104..be020f6a3c 100644 --- a/e2e/core/viewer/viewer-component.e2e.ts +++ b/e2e/core/viewer/viewer-component.e2e.ts @@ -38,59 +38,59 @@ import { browser } from 'protractor'; xdescribe('Viewer', () => { - let viewerPage = new ViewerPage(); - let navigationBarPage = new NavigationBarPage(); - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let uploadActions = new UploadActions(); + const viewerPage = new ViewerPage(); + const navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); let site; - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); let pngFileUploaded; const contentList = contentServicesPage.getDocumentList(); const shareDialog = new ShareDialog(); const about = new AboutPage(); - let pngFileInfo = new FileModel({ + const pngFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let archiveFolderInfo = new FolderModel({ + const archiveFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.ARCHIVE_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.ARCHIVE_FOLDER.folder_location }); - let excelFolderInfo = new FolderModel({ + const excelFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.EXCEL_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.EXCEL_FOLDER.folder_location }); - let otherFolderInfo = new FolderModel({ + const otherFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.OTHER_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.OTHER_FOLDER.folder_location }); - let pptFolderInfo = new FolderModel({ + const pptFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.PPT_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.PPT_FOLDER.folder_location }); - let textFolderInfo = new FolderModel({ + const textFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.TEXT_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.TEXT_FOLDER.folder_location }); - let wordFolderInfo = new FolderModel({ + const wordFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.WORD_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.WORD_FOLDER.folder_location }); - let imgFolderInfo = new FolderModel({ + const imgFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.IMG_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.IMG_FOLDER.folder_location }); - let imgRenditionFolderInfo = new FolderModel({ + const imgRenditionFolderInfo = new FolderModel({ 'name': resources.Files.ADF_DOCUMENTS.IMG_RENDITION_FOLDER.folder_name, 'location': resources.Files.ADF_DOCUMENTS.IMG_RENDITION_FOLDER.folder_location }); @@ -394,7 +394,7 @@ xdescribe('Viewer', () => { describe('Display files via API', () => { - let wordFileInfo = new FileModel({ + const wordFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_location }); @@ -439,7 +439,7 @@ xdescribe('Viewer', () => { shareDialog.checkDialogIsDisplayed(); shareDialog.clickShareLinkButton(); browser.controlFlow().execute(async () => { - let sharedLink = await shareDialog.getShareLink(); + const sharedLink = await shareDialog.getShareLink(); await browser.get(sharedLink); viewerPage.checkFileIsLoaded(); @@ -456,7 +456,7 @@ xdescribe('Viewer', () => { describe('Viewer - Code editor extension', () => { - let jsFileInfo = new FileModel({ + const jsFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.JS.file_name, 'location': resources.Files.ADF_DOCUMENTS.JS.file_location }); diff --git a/e2e/core/viewer/viewer-content-services-component.e2e.ts b/e2e/core/viewer/viewer-content-services-component.e2e.ts index e3b65f7d28..72c60c4f76 100644 --- a/e2e/core/viewer/viewer-content-services-component.e2e.ts +++ b/e2e/core/viewer/viewer-content-services-component.e2e.ts @@ -33,19 +33,19 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Content Services Viewer', () => { - let acsUser = new AcsUserModel(); - let viewerPage = new ViewerPage(); - let contentServicesPage = new ContentServicesPage(); - let loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + const viewerPage = new ViewerPage(); + const contentServicesPage = new ContentServicesPage(); + const loginPage = new LoginPage(); let zoom; - let pdfFile = new FileModel({ + const pdfFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, 'firstPageText': resources.Files.ADF_DOCUMENTS.PDF.first_page_text, 'secondPageText': resources.Files.ADF_DOCUMENTS.PDF.second_page_text, 'lastPageNumber': resources.Files.ADF_DOCUMENTS.PDF.last_page_number }); - let protectedFile = new FileModel({ + const protectedFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF_PROTECTED.file_name, 'firstPageText': resources.Files.ADF_DOCUMENTS.PDF_PROTECTED.first_page_text, 'secondPageText': resources.Files.ADF_DOCUMENTS.PDF_PROTECTED.second_page_text, @@ -53,31 +53,31 @@ describe('Content Services Viewer', () => { 'password': resources.Files.ADF_DOCUMENTS.PDF_PROTECTED.password, 'location': resources.Files.ADF_DOCUMENTS.PDF_PROTECTED.file_location }); - let docxFile = new FileModel({ + const docxFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_location, 'name': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_name, 'firstPageText': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.first_page_text }); - let jpgFile = new FileModel({ + const jpgFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': resources.Files.ADF_DOCUMENTS.JPG.file_name }); - let mp4File = new FileModel({ + const mp4File = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.MP4.file_location, 'name': resources.Files.ADF_DOCUMENTS.MP4.file_name }); - let unsupportedFile = new FileModel({ + const unsupportedFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.UNSUPPORTED.file_location, 'name': resources.Files.ADF_DOCUMENTS.UNSUPPORTED.file_name }); - let pptFile = new FileModel({ + const pptFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.PPT.file_location, 'name': resources.Files.ADF_DOCUMENTS.PPT.file_name, 'firstPageText': resources.Files.ADF_DOCUMENTS.PPT.first_page_text }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -90,25 +90,25 @@ describe('Content Services Viewer', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let pdfFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pdfFile.location, pdfFile.name, '-my-'); + const pdfFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pdfFile.location, pdfFile.name, '-my-'); Object.assign(pdfFile, pdfFileUploaded.entry); - let protectedFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, protectedFile.location, protectedFile.name, '-my-'); + const protectedFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, protectedFile.location, protectedFile.name, '-my-'); Object.assign(protectedFile, protectedFileUploaded.entry); - let docxFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, docxFile.location, docxFile.name, '-my-'); + const docxFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, docxFile.location, docxFile.name, '-my-'); Object.assign(docxFile, docxFileUploaded.entry); - let jpgFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, jpgFile.location, jpgFile.name, '-my-'); + const jpgFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, jpgFile.location, jpgFile.name, '-my-'); Object.assign(jpgFile, jpgFileUploaded.entry); - let mp4FileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, mp4File.location, mp4File.name, '-my-'); + const mp4FileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, mp4File.location, mp4File.name, '-my-'); Object.assign(mp4File, mp4FileUploaded.entry); - let pptFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pptFile.location, pptFile.name, '-my-'); + const pptFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pptFile.location, pptFile.name, '-my-'); Object.assign(pptFile, pptFileUploaded.entry); - let unsupportedFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, unsupportedFile.location, unsupportedFile.name, '-my-'); + const unsupportedFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, unsupportedFile.location, unsupportedFile.name, '-my-'); Object.assign(unsupportedFile, unsupportedFileUploaded.entry); loginPage.loginToContentServicesUsingUserModel(acsUser); @@ -119,7 +119,7 @@ describe('Content Services Viewer', () => { }); afterAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, pdfFile.getId()); await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, protectedFile.getId()); diff --git a/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts b/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts index 99fb46e612..08f1dcb524 100644 --- a/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts +++ b/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts @@ -31,14 +31,14 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Viewer', () => { - let viewerPage = new ViewerPage(); - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let uploadActions = new UploadActions(); - let acsUser = new AcsUserModel(); + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + const acsUser = new AcsUserModel(); let txtFileUploaded; - let txtFileInfo = new FileModel({ + const txtFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.TXT.file_name, 'location': resources.Files.ADF_DOCUMENTS.TXT.file_location }); diff --git a/e2e/core/viewer/viewer-properties.e2e.ts b/e2e/core/viewer/viewer-properties.e2e.ts index ebfca1aa6b..3ffe8a94e3 100644 --- a/e2e/core/viewer/viewer-properties.e2e.ts +++ b/e2e/core/viewer/viewer-properties.e2e.ts @@ -33,25 +33,25 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Viewer - properties', () => { - let acsUser = new AcsUserModel(); - let viewerPage = new ViewerPage(); - let contentServicesPage = new ContentServicesPage(); - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let dataTable = new DataTableComponentPage(); + const acsUser = new AcsUserModel(); + const viewerPage = new ViewerPage(); + const contentServicesPage = new ContentServicesPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const dataTable = new DataTableComponentPage(); - let pngFile = new FileModel({ + const pngFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let fileForOverlay = new FileModel({ + const fileForOverlay = new FileModel({ 'name': 'fileForOverlay.png', 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); beforeAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -85,7 +85,7 @@ describe('Viewer - properties', () => { }); afterAll(async (done) => { - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, pngFile.getId()); diff --git a/e2e/insights/analytics-component.e2e.ts b/e2e/insights/analytics-component.e2e.ts index 047eab0933..41c775ff5e 100644 --- a/e2e/insights/analytics-component.e2e.ts +++ b/e2e/insights/analytics-component.e2e.ts @@ -28,13 +28,13 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; describe('Analytics Smoke Test', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let analyticsPage = new AnalyticsPage(); - let processServicesPage = new ProcessServicesPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const analyticsPage = new AnalyticsPage(); + const processServicesPage = new ProcessServicesPage(); let tenantId; - let reportTitle = 'New Title'; + const reportTitle = 'New Title'; beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -44,10 +44,10 @@ describe('Analytics Smoke Test', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); tenantId = newTenant.id; - let procUserModel = new User({ tenantId: tenantId }); + const procUserModel = new User({ tenantId: tenantId }); await this.alfrescoJsApi.activiti.adminUsersApi.createNewUser(procUserModel); diff --git a/e2e/models/ACS/fileModel.ts b/e2e/models/ACS/fileModel.ts index fe826a127f..6dbe3f1914 100644 --- a/e2e/models/ACS/fileModel.ts +++ b/e2e/models/ACS/fileModel.ts @@ -53,8 +53,8 @@ export class FileModel { } getVersionName() { - let extension = this.name.split('.')[1]; - let name = this.name.split('.')[0]; + const extension = this.name.split('.')[1]; + const name = this.name.split('.')[0]; return name + this.version + '.' + extension; } diff --git a/e2e/pages/adf/cardViewComponentPage.ts b/e2e/pages/adf/cardViewComponentPage.ts index f4c690ec89..4e64f48d32 100644 --- a/e2e/pages/adf/cardViewComponentPage.ts +++ b/e2e/pages/adf/cardViewComponentPage.ts @@ -50,7 +50,7 @@ export class CardViewComponentPage { } clickOnTextField() { - let toggleText = element(by.css(`div[data-automation-id='card-textitem-edit-toggle-name']`)); + const toggleText = element(by.css(`div[data-automation-id='card-textitem-edit-toggle-name']`)); Util.waitUntilElementIsVisible(toggleText); toggleText.click(); Util.waitUntilElementIsVisible(this.textField); @@ -58,19 +58,19 @@ export class CardViewComponentPage { } clickOnTextClearIcon() { - let clearIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-reset-name"]`)); + const clearIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-reset-name"]`)); Util.waitUntilElementIsVisible(clearIcon); return clearIcon.click(); } clickOnTextSaveIcon() { - let saveIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-update-name"]`)); + const saveIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-update-name"]`)); Util.waitUntilElementIsVisible(saveIcon); return saveIcon.click(); } getTextFieldText() { - let textField = element(by.css(`span[data-automation-id="card-textitem-value-name"]`)); + const textField = element(by.css(`span[data-automation-id="card-textitem-value-name"]`)); Util.waitUntilElementIsVisible(textField); return textField.getText(); } @@ -84,7 +84,7 @@ export class CardViewComponentPage { } clickOnIntField() { - let toggleText = element(by.css('div[data-automation-id="card-textitem-edit-toggle-int"]')); + const toggleText = element(by.css('div[data-automation-id="card-textitem-edit-toggle-int"]')); Util.waitUntilElementIsVisible(toggleText); toggleText.click(); Util.waitUntilElementIsVisible(this.intField); @@ -92,13 +92,13 @@ export class CardViewComponentPage { } clickOnIntClearIcon() { - let clearIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-int"]')); + const clearIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-int"]')); Util.waitUntilElementIsVisible(clearIcon); return clearIcon.click(); } clickOnIntSaveIcon() { - let saveIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-int"]')); + const saveIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-int"]')); Util.waitUntilElementIsVisible(saveIcon); return saveIcon.click(); } @@ -112,19 +112,19 @@ export class CardViewComponentPage { } getIntFieldText() { - let textField = element(by.css('span[data-automation-id="card-textitem-value-int"]')); + const textField = element(by.css('span[data-automation-id="card-textitem-value-int"]')); Util.waitUntilElementIsVisible(textField); return textField.getText(); } getErrorInt() { - let errorElement = element(by.css('mat-error[data-automation-id="card-textitem-error-int"]')); + const errorElement = element(by.css('mat-error[data-automation-id="card-textitem-error-int"]')); Util.waitUntilElementIsVisible(errorElement); return errorElement.getText(); } clickOnFloatField() { - let toggleText = element(by.css('div[data-automation-id="card-textitem-edit-toggle-float"]')); + const toggleText = element(by.css('div[data-automation-id="card-textitem-edit-toggle-float"]')); Util.waitUntilElementIsVisible(toggleText); toggleText.click(); Util.waitUntilElementIsVisible(this.floatField); @@ -132,13 +132,13 @@ export class CardViewComponentPage { } clickOnFloatClearIcon() { - let clearIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-reset-float"]`)); + const clearIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-reset-float"]`)); Util.waitUntilElementIsVisible(clearIcon); return clearIcon.click(); } clickOnFloatSaveIcon() { - let saveIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-update-float"]`)); + const saveIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-update-float"]`)); Util.waitUntilElementIsVisible(saveIcon); return saveIcon.click(); } @@ -152,13 +152,13 @@ export class CardViewComponentPage { } getFloatFieldText() { - let textField = element(by.css('span[data-automation-id="card-textitem-value-float"]')); + const textField = element(by.css('span[data-automation-id="card-textitem-value-float"]')); Util.waitUntilElementIsVisible(textField); return textField.getText(); } getErrorFloat() { - let errorElement = element(by.css('mat-error[data-automation-id="card-textitem-error-float"]')); + const errorElement = element(by.css('mat-error[data-automation-id="card-textitem-error-float"]')); Util.waitUntilElementIsVisible(errorElement); return errorElement.getText(); } diff --git a/e2e/pages/adf/configEditorPage.ts b/e2e/pages/adf/configEditorPage.ts index f77e165655..aebf4585ae 100644 --- a/e2e/pages/adf/configEditorPage.ts +++ b/e2e/pages/adf/configEditorPage.ts @@ -21,14 +21,14 @@ import { Util } from '../../util/util'; export class ConfigEditorPage { enterConfiguration(text) { - let textField = element(by.css('#adf-code-configuration-editor div.overflow-guard > textarea')); + const textField = element(by.css('#adf-code-configuration-editor div.overflow-guard > textarea')); Util.waitUntilElementIsVisible(textField); textField.sendKeys(text); return this; } enterBigConfigurationText(text) { - let textField = element(by.css('#adf-code-configuration-editor div.overflow-guard > textarea')); + const textField = element(by.css('#adf-code-configuration-editor div.overflow-guard > textarea')); Util.waitUntilElementIsVisible(textField); browser.executeScript('this.monaco.editor.getModels()[0].setValue(`' + text + '`)'); @@ -36,63 +36,63 @@ export class ConfigEditorPage { } clickSaveButton() { - let saveButton = element(by.id('adf-configuration-save')); + const saveButton = element(by.id('adf-configuration-save')); Util.waitUntilElementIsVisible(saveButton); Util.waitUntilElementIsClickable(saveButton); return saveButton.click(); } clickClearButton() { - let clearButton = element(by.id('adf-configuration-clear')); + const clearButton = element(by.id('adf-configuration-clear')); Util.waitUntilElementIsVisible(clearButton); Util.waitUntilElementIsClickable(clearButton); return clearButton.click(); } clickFileConfiguration() { - let button = element(by.id('adf-file-conf')); + const button = element(by.id('adf-file-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); } clickSearchConfiguration() { - let button = element(by.id('adf-search-conf')); + const button = element(by.id('adf-search-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); } clickProcessListCloudConfiguration() { - let button = element(by.id('adf-process-list-cloud-conf')); + const button = element(by.id('adf-process-list-cloud-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); } clickEditProcessCloudConfiguration() { - let button = element(by.id('adf-edit-process-filter-conf')); + const button = element(by.id('adf-edit-process-filter-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); } clickEditTaskConfiguration() { - let button = element(by.id('adf-edit-task-filter-conf')); + const button = element(by.id('adf-edit-task-filter-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); } clickTaskListCloudConfiguration() { - let button = element(by.id('adf-task-list-cloud-conf')); + const button = element(by.id('adf-task-list-cloud-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); } clickInfinitePaginationConfiguration() { - let button = element(by.id('adf-infinite-pagination-conf')); + const button = element(by.id('adf-infinite-pagination-conf')); Util.waitUntilElementIsVisible(button); Util.waitUntilElementIsClickable(button); return button.click(); diff --git a/e2e/pages/adf/content-services/documentListPage.ts b/e2e/pages/adf/content-services/documentListPage.ts index 0d20e62ddb..13afd6e0b3 100644 --- a/e2e/pages/adf/content-services/documentListPage.ts +++ b/e2e/pages/adf/content-services/documentListPage.ts @@ -34,15 +34,15 @@ export class DocumentListPage { } checkLockedIcon(content) { - let row = this.dataTable.getRowParentElement('Display name', content); - let lockIcon = row.element(by.cssContainingText('div[title="Lock"] mat-icon', 'lock')); + const row = this.dataTable.getRowParentElement('Display name', content); + const lockIcon = row.element(by.cssContainingText('div[title="Lock"] mat-icon', 'lock')); Util.waitUntilElementIsVisible(lockIcon); return this; } checkUnlockedIcon(content) { - let row = this.dataTable.getRowParentElement('Display name', content); - let lockIcon = row.element(by.cssContainingText('div[title="Lock"] mat-icon', 'lock_open')); + const row = this.dataTable.getRowParentElement('Display name', content); + const lockIcon = row.element(by.cssContainingText('div[title="Lock"] mat-icon', 'lock_open')); Util.waitUntilElementIsVisible(lockIcon); return this; } @@ -64,7 +64,7 @@ export class DocumentListPage { } clickOnActionMenu(content) { - let row = this.dataTable.getRowParentElement('Display name', content); + const row = this.dataTable.getRowParentElement('Display name', content); row.element(this.optionButton).click(); Util.waitUntilElementIsVisible(this.actionMenu); browser.sleep(500); diff --git a/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts b/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts index e1091d6538..1af248d5cc 100644 --- a/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts +++ b/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts @@ -48,7 +48,7 @@ export class DateRangeFilterPage { } getFromCalendarSelectedDate() { - let selectedDate = this.openFromDatePicker().getSelectedDate(); + const selectedDate = this.openFromDatePicker().getSelectedDate(); new DatePickerPage().closeDatePicker(); return selectedDate; } diff --git a/e2e/pages/adf/content-services/search/components/search-checkList.ts b/e2e/pages/adf/content-services/search/components/search-checkList.ts index 2fbeea3512..e980b88239 100644 --- a/e2e/pages/adf/content-services/search/components/search-checkList.ts +++ b/e2e/pages/adf/content-services/search/components/search-checkList.ts @@ -32,7 +32,7 @@ export class SearchCheckListPage { clickCheckListOption(option) { Util.waitUntilElementIsVisible(this.filter); - let result = this.filter.all(by.css(`mat-checkbox[data-automation-id*='-${option}'] .mat-checkbox-inner-container`)).first(); + const result = this.filter.all(by.css(`mat-checkbox[data-automation-id*='-${option}'] .mat-checkbox-inner-container`)).first(); Util.waitUntilElementIsVisible(result); Util.waitUntilElementIsClickable(result); result.click(); @@ -49,7 +49,7 @@ export class SearchCheckListPage { } removeFilterOption(option) { - let cancelChipButton = element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon')); + const cancelChipButton = element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon')); Util.waitUntilElementIsClickable(cancelChipButton); cancelChipButton.click(); return this; @@ -69,7 +69,7 @@ export class SearchCheckListPage { searchInFilter(option) { Util.waitUntilElementIsClickable(this.filter); - let inputElement = this.filter.all(this.inputBy).first(); + const inputElement = this.filter.all(this.inputBy).first(); Util.waitUntilElementIsClickable(inputElement); inputElement.clear(); @@ -122,11 +122,11 @@ export class SearchCheckListPage { } getBucketNumberOfFilterType(option) { - let fileTypeFilter = this.filter.all(by.css('mat-checkbox[data-automation-id*=".' + option + '"] span')).first(); + const fileTypeFilter = this.filter.all(by.css('mat-checkbox[data-automation-id*=".' + option + '"] span')).first(); Util.waitUntilElementIsVisible(fileTypeFilter); - let bucketNumber = fileTypeFilter.getText().then((valueOfBucket) => { - let numberOfBucket = valueOfBucket.split('(')[1]; - let totalNumberOfBucket = numberOfBucket.split(')')[0]; + const bucketNumber = fileTypeFilter.getText().then((valueOfBucket) => { + const numberOfBucket = valueOfBucket.split('(')[1]; + const totalNumberOfBucket = numberOfBucket.split(')')[0]; return totalNumberOfBucket.trim(); }); @@ -135,38 +135,38 @@ export class SearchCheckListPage { checkCheckListOptionIsDisplayed(option) { Util.waitUntilElementIsVisible(this.filter); - let result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}']`)); + const result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}']`)); return Util.waitUntilElementIsVisible(result); } checkCheckListOptionIsNotSelected(option) { Util.waitUntilElementIsVisible(this.filter); - let result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`)); + const result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`)); return Util.waitUntilElementIsNotVisible(result); } checkCheckListOptionIsSelected(option) { Util.waitUntilElementIsVisible(this.filter); - let result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`)); + const result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`)); return Util.waitUntilElementIsVisible(result); } checkClearAllButtonIsDisplayed() { Util.waitUntilElementIsVisible(this.filter); - let result = this.filter.element(this.clearAllButton); + const result = this.filter.element(this.clearAllButton); return Util.waitUntilElementIsVisible(result); } clickClearAllButton() { Util.waitUntilElementIsVisible(this.filter); - let result = this.filter.element(this.clearAllButton); + const result = this.filter.element(this.clearAllButton); Util.waitUntilElementIsVisible(result); return result.click(); } getCheckListOptionsNumberOnPage() { Util.waitUntilElementIsVisible(this.filter); - let checkListOptions = this.filter.all(by.css('div[class="checklist"] mat-checkbox')); + const checkListOptions = this.filter.all(by.css('div[class="checklist"] mat-checkbox')); return checkListOptions.count(); } diff --git a/e2e/pages/adf/content-services/search/components/search-radio.ts b/e2e/pages/adf/content-services/search/components/search-radio.ts index 3bd1dbed37..251980bfd3 100644 --- a/e2e/pages/adf/content-services/search/components/search-radio.ts +++ b/e2e/pages/adf/content-services/search/components/search-radio.ts @@ -29,12 +29,12 @@ export class SearchRadioPage { } checkFilterRadioButtonIsDisplayed(filterName) { - let filterType = element(by.css('mat-radio-button[data-automation-id="search-radio-' + filterName + '"]')); + const filterType = element(by.css('mat-radio-button[data-automation-id="search-radio-' + filterName + '"]')); return Util.waitUntilElementIsVisible(filterType); } checkFilterRadioButtonIsChecked(filterName) { - let selectedFilterType = element(by.css('mat-radio-button[data-automation-id="search-radio-' + filterName + '"][class*="checked"]')); + const selectedFilterType = element(by.css('mat-radio-button[data-automation-id="search-radio-' + filterName + '"][class*="checked"]')); return Util.waitUntilElementIsVisible(selectedFilterType); } @@ -43,7 +43,7 @@ export class SearchRadioPage { } getRadioButtonsNumberOnPage() { - let radioButtons = element.all(by.css('mat-radio-button')); + const radioButtons = element.all(by.css('mat-radio-button')); return radioButtons.count(); } diff --git a/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts b/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts index fee3bd1760..3f18daea60 100644 --- a/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts +++ b/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts @@ -28,7 +28,7 @@ export class SearchSortingPickerPage { Util.waitUntilElementIsClickable(this.sortingSelector); this.sortingSelector.click(); - let selectedSortingOption = element(by.cssContainingText('span[class="mat-option-text"]', sortType)); + const selectedSortingOption = element(by.cssContainingText('span[class="mat-option-text"]', sortType)); Util.waitUntilElementIsClickable(selectedSortingOption); selectedSortingOption.click(); @@ -51,7 +51,7 @@ export class SearchSortingPickerPage { } clickSortingOption(option) { - let selectedSortingOption = element(by.cssContainingText('span[class="mat-option-text"]', option)); + const selectedSortingOption = element(by.cssContainingText('span[class="mat-option-text"]', option)); Util.waitUntilElementIsClickable(selectedSortingOption); selectedSortingOption.click(); return this; @@ -64,13 +64,13 @@ export class SearchSortingPickerPage { } checkOptionIsDisplayed(option) { - let optionSelector = this.optionsDropdown.element(by.cssContainingText('span[class="mat-option-text"]', option)); + const optionSelector = this.optionsDropdown.element(by.cssContainingText('span[class="mat-option-text"]', option)); Util.waitUntilElementIsVisible(optionSelector); return this; } checkOptionIsNotDisplayed(option) { - let optionSelector = this.optionsDropdown.element(by.cssContainingText('span[class="mat-option-text"]', option)); + const optionSelector = this.optionsDropdown.element(by.cssContainingText('span[class="mat-option-text"]', option)); Util.waitUntilElementIsNotVisible(optionSelector); return this; } @@ -86,7 +86,7 @@ export class SearchSortingPickerPage { } checkOrderArrowIsDownward() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); Util.waitUntilElementIsVisible(this.orderArrow); this.orderArrow.getText().then((result) => { deferred.fulfill(result !== 'arrow_upward'); diff --git a/e2e/pages/adf/content-services/search/search-categories.ts b/e2e/pages/adf/content-services/search/search-categories.ts index ce812e62c3..ce726733ec 100644 --- a/e2e/pages/adf/content-services/search/search-categories.ts +++ b/e2e/pages/adf/content-services/search/search-categories.ts @@ -62,7 +62,7 @@ export class SearchCategoriesPage { } clickFilterHeader(filter: ElementFinder) { - let fileSizeFilterHeader = filter.element(by.css('mat-expansion-panel-header')); + const fileSizeFilterHeader = filter.element(by.css('mat-expansion-panel-header')); Util.waitUntilElementIsClickable(fileSizeFilterHeader); fileSizeFilterHeader.click(); return this; diff --git a/e2e/pages/adf/content-services/treeViewPage.ts b/e2e/pages/adf/content-services/treeViewPage.ts index 33bd42e48d..42cb1d3ad4 100644 --- a/e2e/pages/adf/content-services/treeViewPage.ts +++ b/e2e/pages/adf/content-services/treeViewPage.ts @@ -35,28 +35,28 @@ export class TreeViewPage { } clickNode(nodeName) { - let node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"] button')); + const node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"] button')); Util.waitUntilElementIsClickable(node); return node.click(); } checkNodeIsDisplayedAsClosed(nodeName) { - let node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"][aria-expanded="false"]')); + const node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"][aria-expanded="false"]')); return Util.waitUntilElementIsVisible(node); } checkNodeIsDisplayedAsOpen(nodeName) { - let node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"][aria-expanded="true"]')); + const node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"][aria-expanded="true"]')); return Util.waitUntilElementIsVisible(node); } checkClickedNodeName(nodeName) { - let clickedNode = element(by.cssContainingText('span', ' CLICKED NODE: ' + nodeName + '')); + const clickedNode = element(by.cssContainingText('span', ' CLICKED NODE: ' + nodeName + '')); return Util.waitUntilElementIsVisible(clickedNode); } checkNodeIsNotDisplayed(nodeName) { - let node = element(by.id('' + nodeName + '-tree-child-node')); + const node = element(by.id('' + nodeName + '-tree-child-node')); return Util.waitUntilElementIsNotVisible(node); } @@ -82,7 +82,7 @@ export class TreeViewPage { } checkErrorMessageIsDisplayed() { - let clickedNode = element(by.cssContainingText('span', 'An Error Occurred ')); + const clickedNode = element(by.cssContainingText('span', 'An Error Occurred ')); return Util.waitUntilElementIsVisible(clickedNode); } diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index c95a4a7c98..ccf4e9291c 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -77,12 +77,12 @@ export class ContentServicesPage { siteListDropdown = element(by.css(`mat-select[data-automation-id='site-my-files-option']`)); pressContextMenuActionNamed(actionName) { - let actionButton = this.checkContextActionIsVisible(actionName); + const actionButton = this.checkContextActionIsVisible(actionName); actionButton.click(); } checkContextActionIsVisible(actionName) { - let actionButton = element(by.css(`button[data-automation-id="context-${actionName}"`)); + const actionButton = element(by.css(`button[data-automation-id="context-${actionName}"`)); Util.waitUntilElementIsVisible(actionButton); Util.waitUntilElementIsClickable(actionButton); return actionButton; @@ -103,7 +103,7 @@ export class ContentServicesPage { checkDeleteIsDisabled(content) { this.contentList.clickOnActionMenu(content); this.waitForContentOptions(); - let disabledDelete = element(by.css(`button[data-automation-id*='DELETE'][disabled='true']`)); + const disabledDelete = element(by.css(`button[data-automation-id*='DELETE'][disabled='true']`)); Util.waitUntilElementIsVisible(disabledDelete); } @@ -143,7 +143,7 @@ export class ContentServicesPage { } clickFileHyperlink(fileName) { - let hyperlink = this.contentList.dataTablePage().getFileHyperlink(fileName); + const hyperlink = this.contentList.dataTablePage().getFileHyperlink(fileName); Util.waitUntilElementIsClickable(hyperlink); hyperlink.click(); @@ -151,13 +151,13 @@ export class ContentServicesPage { } checkFileHyperlinkIsEnabled(fileName) { - let hyperlink = this.contentList.dataTablePage().getFileHyperlink(fileName); + const hyperlink = this.contentList.dataTablePage().getFileHyperlink(fileName); Util.waitUntilElementIsVisible(hyperlink); return this; } clickHyperlinkNavigationToggle() { - let hyperlinkToggle = element(by.cssContainingText('.mat-slide-toggle-content', 'Hyperlink navigation')); + const hyperlinkToggle = element(by.cssContainingText('.mat-slide-toggle-content', 'Hyperlink navigation')); Util.waitUntilElementIsVisible(hyperlinkToggle); hyperlinkToggle.click(); return this; @@ -300,7 +300,7 @@ export class ContentServicesPage { } currentFolderName() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); Util.waitUntilElementIsVisible(this.currentFolder); this.currentFolder.getText().then(function (result) { deferred.fulfill(result); @@ -326,7 +326,7 @@ export class ContentServicesPage { sortAndCheckListIsOrderedByName(sortOrder) { this.sortByName(sortOrder); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.checkListIsSortedByNameColumn(sortOrder).then((result) => { deferred.fulfill(result); }); @@ -351,7 +351,7 @@ export class ContentServicesPage { sortAndCheckListIsOrderedByAuthor(sortOrder) { this.sortByAuthor(sortOrder); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.checkListIsSortedByAuthorColumn(sortOrder).then((result) => { deferred.fulfill(result); }); @@ -360,7 +360,7 @@ export class ContentServicesPage { sortAndCheckListIsOrderedByCreated(sortOrder) { this.sortByCreated(sortOrder); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.checkListIsSortedByCreatedColumn(sortOrder).then((result) => { deferred.fulfill(result); }); @@ -468,7 +468,7 @@ export class ContentServicesPage { getErrorMessage() { Util.waitUntilElementIsVisible(this.errorSnackBar); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.errorSnackBar.getText().then(function (text) { deferred.fulfill(text); }); @@ -476,28 +476,28 @@ export class ContentServicesPage { } enableInfiniteScrolling() { - let infiniteScrollButton = element(by.cssContainingText('.mat-slide-toggle-content', 'Enable Infinite Scrolling')); + const infiniteScrollButton = element(by.cssContainingText('.mat-slide-toggle-content', 'Enable Infinite Scrolling')); Util.waitUntilElementIsVisible(infiniteScrollButton); infiniteScrollButton.click(); return this; } enableCustomPermissionMessage() { - let customPermissionMessage = element(by.cssContainingText('.mat-slide-toggle-content', 'Enable custom permission message')); + const customPermissionMessage = element(by.cssContainingText('.mat-slide-toggle-content', 'Enable custom permission message')); Util.waitUntilElementIsVisible(customPermissionMessage); customPermissionMessage.click(); return this; } enableMediumTimeFormat() { - let mediumTimeFormat = element(by.css('#enableMediumTimeFormat')); + const mediumTimeFormat = element(by.css('#enableMediumTimeFormat')); Util.waitUntilElementIsVisible(mediumTimeFormat); mediumTimeFormat.click(); return this; } enableThumbnails() { - let thumbnailSlide = element(by.id('adf-thumbnails-upload-switch')); + const thumbnailSlide = element(by.id('adf-thumbnails-upload-switch')); Util.waitUntilElementIsVisible(thumbnailSlide); thumbnailSlide.click(); return this; @@ -508,7 +508,7 @@ export class ContentServicesPage { } getDocumentListRowNumber() { - let documentList = element(by.css('adf-upload-drag-area adf-document-list')); + const documentList = element(by.css('adf-upload-drag-area adf-document-list')); Util.waitUntilElementIsVisible(documentList); return $$('adf-upload-drag-area adf-document-list .adf-datatable-row').count(); } @@ -544,7 +544,7 @@ export class ContentServicesPage { } checkLockIsDisplayedForElement(name) { - let lockButton = element(by.css(`div.adf-datatable-cell[filename="${name}"] button`)); + const lockButton = element(by.css(`div.adf-datatable-cell[filename="${name}"] button`)); Util.waitUntilElementIsVisible(lockButton); } @@ -553,7 +553,7 @@ export class ContentServicesPage { } async getStyleValueForRowText(rowName, styleName) { - let row = element(by.css(`div.adf-datatable-cell[filename="${rowName}"] span.adf-datatable-cell-value[title="${rowName}"]`)); + const row = element(by.css(`div.adf-datatable-cell[filename="${rowName}"] span.adf-datatable-cell-value[title="${rowName}"]`)); Util.waitUntilElementIsVisible(row); return row.getCssValue(styleName); } @@ -577,13 +577,13 @@ export class ContentServicesPage { } checkIconForRowIsDisplayed(fileName) { - let iconRow = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${fileName}"] img`)); + const iconRow = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${fileName}"] img`)); Util.waitUntilElementIsVisible(iconRow); return iconRow; } async getRowIconImageUrl(fileName) { - let iconRow = this.checkIconForRowIsDisplayed(fileName); + const iconRow = this.checkIconForRowIsDisplayed(fileName); return iconRow.getAttribute('src'); } @@ -602,54 +602,54 @@ export class ContentServicesPage { getCardElementShowedInPage() { this.checkCardViewContainerIsDisplayed(); - let actualCards = $$('div.adf-document-list-container div.adf-datatable-card div.adf-cell-value img').count(); + const actualCards = $$('div.adf-document-list-container div.adf-datatable-card div.adf-cell-value img').count(); return actualCards; } getDocumentCardIconForElement(elementName) { - let elementIcon = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"] img`)); + const elementIcon = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"] img`)); return elementIcon.getAttribute('src'); } checkDocumentCardPropertyIsShowed(elementName, propertyName) { - let elementProperty = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"][title="${propertyName}"]`)); + const elementProperty = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"][title="${propertyName}"]`)); Util.waitUntilElementIsVisible(elementProperty); } getAttributeValueForElement(elementName, propertyName) { - let elementSize = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"][title="${propertyName}"] span`)); + const elementSize = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"][title="${propertyName}"] span`)); return elementSize.getText(); } checkMenuIsShowedForElementIndex(elementIndex) { - let elementMenu = element(by.css(`button[data-automation-id="action_menu_${elementIndex}"]`)); + const elementMenu = element(by.css(`button[data-automation-id="action_menu_${elementIndex}"]`)); Util.waitUntilElementIsVisible(elementMenu); } navigateToCardFolder(folderName) { - let folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[filename="${folderName}"]`)); + const folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[filename="${folderName}"]`)); folderCard.click(); - let folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[filename="${folderName}"].adf-datatable-cell--image`)); + const folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[filename="${folderName}"].adf-datatable-cell--image`)); Util.waitUntilElementIsVisible(folderSelected); browser.actions().sendKeys(protractor.Key.ENTER).perform(); } getGridViewSortingDropdown() { - let sortingDropdown = element(by.css('mat-select[data-automation-id="grid-view-sorting"]')); + const sortingDropdown = element(by.css('mat-select[data-automation-id="grid-view-sorting"]')); Util.waitUntilElementIsVisible(sortingDropdown); return sortingDropdown; } selectGridSortingFromDropdown(sortingChosen) { - let dropdownSorting = this.getGridViewSortingDropdown(); + const dropdownSorting = this.getGridViewSortingDropdown(); dropdownSorting.click(); - let optionToClick = element(by.css(`mat-option[data-automation-id="grid-view-sorting-${sortingChosen}"]`)); + const optionToClick = element(by.css(`mat-option[data-automation-id="grid-view-sorting-${sortingChosen}"]`)); Util.waitUntilElementIsPresent(optionToClick); optionToClick.click(); } checkRowIsDisplayed(rowName) { - let row = this.contentList.dataTablePage().getRow('Display name', rowName); + const row = this.contentList.dataTablePage().getRow('Display name', rowName); Util.waitUntilElementIsVisible(row); } @@ -659,7 +659,7 @@ export class ContentServicesPage { } clickContentNodeSelectorResult(name) { - let resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[filename="${name}"`)).first(); + const resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[filename="${name}"`)).first(); Util.waitUntilElementIsVisible(resultElement); resultElement.click(); } diff --git a/e2e/pages/adf/core/headerPage.ts b/e2e/pages/adf/core/headerPage.ts index 71d36b840f..a94613a0c8 100644 --- a/e2e/pages/adf/core/headerPage.ts +++ b/e2e/pages/adf/core/headerPage.ts @@ -50,18 +50,18 @@ export class HeaderPage { } clickShowMenuButton() { - let checkBox = element.all(by.css('mat-checkbox')); + const checkBox = element.all(by.css('mat-checkbox')); Util.waitUntilElementIsVisible(checkBox); return checkBox.get(0).click(); } changeHeaderColor(color) { - let headerColor = element(by.css('option[value="' + color + '"]')); + const headerColor = element(by.css('option[value="' + color + '"]')); return headerColor.click(); } checkAppTitle(name) { - let title = element(by.cssContainingText('.adf-app-title', name)); + const title = element(by.cssContainingText('.adf-app-title', name)); return Util.waitUntilElementIsVisible(title); } @@ -73,7 +73,7 @@ export class HeaderPage { } checkIconIsDisplayed(url) { - let icon = element(by.css('img[src="' + url + '"]')); + const icon = element(by.css('img[src="' + url + '"]')); Util.waitUntilElementIsVisible(icon); } diff --git a/e2e/pages/adf/dataTableComponentPage.ts b/e2e/pages/adf/dataTableComponentPage.ts index 09ffdd04cf..286c761142 100644 --- a/e2e/pages/adf/dataTableComponentPage.ts +++ b/e2e/pages/adf/dataTableComponentPage.ts @@ -58,7 +58,7 @@ export class DataTableComponentPage { } clickCheckbox(columnName, columnValue) { - let checkbox = this.getRowCheckbox(columnName, columnValue); + const checkbox = this.getRowCheckbox(columnName, columnValue); Util.waitUntilElementIsClickable(checkbox); checkbox.click(); } @@ -68,7 +68,7 @@ export class DataTableComponentPage { } checkRowIsChecked(columnName, columnValue) { - let rowCheckbox = this.getRowCheckbox(columnName, columnValue); + const rowCheckbox = this.getRowCheckbox(columnName, columnValue); Util.waitUntilElementIsVisible(rowCheckbox.element(by.css('input[aria-checked="true"]'))); } @@ -86,33 +86,33 @@ export class DataTableComponentPage { } selectRowWithKeyboard(columnName, columnValue) { - let row = this.getRow(columnName, columnValue); + const row = this.getRow(columnName, columnValue); browser.actions().sendKeys(protractor.Key.COMMAND).click(row).perform(); } selectRow(columnName, columnValue) { - let row = this.getRow(columnName, columnValue); + const row = this.getRow(columnName, columnValue); Util.waitUntilElementIsClickable(row); row.click(); return this; } checkRowIsSelected(columnName, columnValue) { - let selectedRow = this.getRow(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + const selectedRow = this.getRow(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); Util.waitUntilElementIsVisible(selectedRow); return this; } checkRowIsNotSelected(columnName, columnValue) { - let selectedRow = this.getRow(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + const selectedRow = this.getRow(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); Util.waitUntilElementIsNotOnPage(selectedRow); return this; } getColumnValueForRow(identifyingColumn, identifyingValue, columnName) { - let row = this.getRow(identifyingColumn, identifyingValue).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]`)); + const row = this.getRow(identifyingColumn, identifyingValue).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]`)); Util.waitUntilElementIsVisible(row); - let rowColumn = row.element(by.css(`div[title="${columnName}"] span`)); + const rowColumn = row.element(by.css(`div[title="${columnName}"] span`)); Util.waitUntilElementIsVisible(rowColumn); return rowColumn.getText(); } @@ -125,10 +125,10 @@ export class DataTableComponentPage { * @return 'true' if the list is sorted as expected and 'false' if it isn't */ checkListIsSorted(sortOrder, locator) { - let deferred = protractor.promise.defer(); - let column = element.all(by.css(`div[title='${locator}'] span`)); + const deferred = protractor.promise.defer(); + const column = element.all(by.css(`div[title='${locator}'] span`)); Util.waitUntilElementIsVisible(column.first()); - let initialList = []; + const initialList = []; column.each(function (currentElement) { currentElement.getText().then(function (text) { initialList.push(text); @@ -145,7 +145,7 @@ export class DataTableComponentPage { } rightClickOnRow(columnName, columnValue) { - let row = this.getRow(columnName, columnValue); + const row = this.getRow(columnName, columnValue); browser.actions().click(row, protractor.Button.RIGHT).perform(); Util.waitUntilElementIsVisible(element(by.id('adf-context-menu-content'))); } @@ -163,20 +163,20 @@ export class DataTableComponentPage { } async getAllRowsColumnValues(column) { - let columnLocator = by.css("adf-datatable div[class*='adf-datatable-body'] div[class*='adf-datatable-row'] div[title='" + column + "'] span"); + const columnLocator = by.css("adf-datatable div[class*='adf-datatable-body'] div[class*='adf-datatable-row'] div[title='" + column + "'] span"); Util.waitUntilElementIsVisible(element.all(columnLocator).first()); - let initialList: any = await element.all(columnLocator).getText(); + const initialList: any = await element.all(columnLocator).getText(); return initialList.filter((el) => el); } async getRowsWithSameColumnValues(columnName, columnValue) { - let columnLocator = by.css(`div[title='${columnName}'] div[data-automation-id="text_${columnValue}"] span`); + const columnLocator = by.css(`div[title='${columnName}'] div[data-automation-id="text_${columnValue}"] span`); Util.waitUntilElementIsVisible(this.rootElement.all(columnLocator).first()); return this.rootElement.all(columnLocator).getText(); } doubleClickRow(columnName, columnValue) { - let row = this.getRow(columnName, columnValue); + const row = this.getRow(columnName, columnValue); Util.waitUntilElementIsVisible(row); Util.waitUntilElementIsClickable(row); row.click(); @@ -190,7 +190,7 @@ export class DataTableComponentPage { } getFirstElementDetail(detail) { - let firstNode = element.all(by.css(`adf-datatable div[title="${detail}"] span`)).first(); + const firstNode = element.all(by.css(`adf-datatable div[title="${detail}"] span`)).first(); return firstNode.getText(); } @@ -199,7 +199,7 @@ export class DataTableComponentPage { } sortByColumn(sortOrder, column) { - let locator = by.css(`div[data-automation-id="auto_id_${column}"]`); + const locator = by.css(`div[data-automation-id="auto_id_${column}"]`); Util.waitUntilElementIsVisible(element(locator)); return element(locator).getAttribute('class').then(function (result) { if (sortOrder === true) { @@ -222,13 +222,13 @@ export class DataTableComponentPage { } checkContentIsDisplayed(columnName, columnValue) { - let row = this.getRow(columnName, columnValue); + const row = this.getRow(columnName, columnValue); Util.waitUntilElementIsVisible(row); return this; } checkContentIsNotDisplayed(columnName, columnValue) { - let row = this.getRow(columnName, columnValue); + const row = this.getRow(columnName, columnValue); Util.waitUntilElementIsNotOnPage(row); return this; } @@ -239,7 +239,7 @@ export class DataTableComponentPage { } getRowParentElement(columnName, columnValue) { - let row = this.rootElement.all(by.css(`div[title="${columnName}"] div[data-automation-id="text_${columnValue}"]`)).first() + const row = this.rootElement.all(by.css(`div[title="${columnName}"] div[data-automation-id="text_${columnValue}"]`)).first() .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]`)); Util.waitUntilElementIsVisible(row); return row; diff --git a/e2e/pages/adf/demo-shell/customSourcesPage.ts b/e2e/pages/adf/demo-shell/customSourcesPage.ts index 7e339a2b91..af5cfac0f2 100644 --- a/e2e/pages/adf/demo-shell/customSourcesPage.ts +++ b/e2e/pages/adf/demo-shell/customSourcesPage.ts @@ -20,7 +20,7 @@ import { element, by } from 'protractor'; import { DataTableComponentPage } from '../dataTableComponentPage'; import { NavigationBarPage } from '../navigationBarPage'; -let source = { +const source = { favorites: 'Favorites', recent: 'Recent', sharedLinks: 'Shared Links', @@ -32,7 +32,7 @@ let source = { shared: 'Shared' }; -let column = { +const column = { status: 'Status' }; @@ -71,7 +71,7 @@ export class CustomSources { } getStatusCell(rowName) { - let cell = this.dataTable.getCellByRowAndColumn('Name', rowName, column.status); + const cell = this.dataTable.getCellByRowAndColumn('Name', rowName, column.status); Util.waitUntilElementIsVisible(cell); return cell.getText(); } diff --git a/e2e/pages/adf/demo-shell/dataTablePage.ts b/e2e/pages/adf/demo-shell/dataTablePage.ts index 25f52e2ce0..4495491fc8 100644 --- a/e2e/pages/adf/demo-shell/dataTablePage.ts +++ b/e2e/pages/adf/demo-shell/dataTablePage.ts @@ -35,7 +35,7 @@ export class DataTablePage { createdOnColumn = element(by.css(`div[data-automation-id='auto_id_createdOn']`)); insertFilter(filterText) { - let inputFilter = element(by.css(`#adf-datatable-filter-input`)); + const inputFilter = element(by.css(`#adf-datatable-filter-input`)); inputFilter.clear(); return inputFilter.sendKeys(filterText); } @@ -46,7 +46,7 @@ export class DataTablePage { } replaceRows(id) { - let rowID = this.dataTable.getRow('Id', id); + const rowID = this.dataTable.getRow('Id', id); Util.waitUntilElementIsVisible(rowID); this.replaceRowsElement.click(); Util.waitUntilElementIsNotVisible(rowID); @@ -69,7 +69,7 @@ export class DataTablePage { } checkRowIsNotSelected(rowNumber) { - let isRowSelected = this.dataTable.getRow('Id', rowNumber) + const isRowSelected = this.dataTable.getRow('Id', rowNumber) .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row custom-row-style ng-star-inserted is-selected')]`)); Util.waitUntilElementIsNotOnPage(isRowSelected); } @@ -96,13 +96,13 @@ export class DataTablePage { } clickCheckbox(rowNumber) { - let checkbox = this.dataTable.getRow('Id', rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); + const checkbox = this.dataTable.getRow('Id', rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); Util.waitUntilElementIsVisible(checkbox); checkbox.click(); } selectRow(rowNumber) { - let locator = this.dataTable.getRow('Id', rowNumber); + const locator = this.dataTable.getRow('Id', rowNumber); Util.waitUntilElementIsVisible(locator); Util.waitUntilElementIsClickable(locator); locator.click(); @@ -110,12 +110,12 @@ export class DataTablePage { } selectRowWithKeyboard(rowNumber) { - let row = this.dataTable.getRow('Id', rowNumber); + const row = this.dataTable.getRow('Id', rowNumber); browser.actions().sendKeys(protractor.Key.COMMAND).click(row).perform(); } selectSelectionMode(selectionMode) { - let selectMode = element(by.cssContainingText(`span[class='mat-option-text']`, selectionMode)); + const selectMode = element(by.cssContainingText(`span[class='mat-option-text']`, selectionMode)); this.selectionButton.click(); Util.waitUntilElementIsVisible(this.selectionDropDown); selectMode.click(); diff --git a/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts index eed496f175..bfa5395f37 100644 --- a/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts @@ -38,7 +38,7 @@ export class ProcessListDemoPage { selectSorting(sort) { Util.waitUntilElementIsVisible(this.stateSelector); this.sortSelector.click(); - let sortLocator = element(by.cssContainingText('mat-option span', sort)); + const sortLocator = element(by.cssContainingText('mat-option span', sort)); Util.waitUntilElementIsVisible(sortLocator); sortLocator.click(); return this; @@ -47,7 +47,7 @@ export class ProcessListDemoPage { selectStateFilter(state) { Util.waitUntilElementIsVisible(this.stateSelector); this.stateSelector.click(); - let stateLocator = element(by.cssContainingText('mat-option span', state)); + const stateLocator = element(by.cssContainingText('mat-option span', state)); Util.waitUntilElementIsVisible(stateLocator); stateLocator.click(); return this; @@ -67,7 +67,7 @@ export class ProcessListDemoPage { } checkErrorMessageIsDisplayed(error) { - let errorMessage = element(by.cssContainingText('mat-error', error)); + const errorMessage = element(by.cssContainingText('mat-error', error)); Util.waitUntilElementIsVisible(errorMessage); } diff --git a/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts index c795f2c4f0..4be5673fa7 100644 --- a/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts @@ -128,7 +128,7 @@ export class TaskListDemoPage { getItemsPerPageFieldErrorMessage() { Util.waitUntilElementIsVisible(this.itemsPerPageForm); - let errorMessage = this.itemsPerPageForm.element(by.css('mat-error')); + const errorMessage = this.itemsPerPageForm.element(by.css('mat-error')); Util.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } @@ -147,7 +147,7 @@ export class TaskListDemoPage { getPageFieldErrorMessage() { Util.waitUntilElementIsVisible(this.pageForm); - let errorMessage = this.pageForm.element(by.css('mat-error')); + const errorMessage = this.pageForm.element(by.css('mat-error')); Util.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } @@ -179,7 +179,7 @@ export class TaskListDemoPage { selectSort(sort) { this.clickOnSortDropDownArrow(); - let sortElement = element.all(by.cssContainingText('mat-option span', sort)).first(); + const sortElement = element.all(by.cssContainingText('mat-option span', sort)).first(); Util.waitUntilElementIsClickable(sortElement); Util.waitUntilElementIsVisible(sortElement); sortElement.click(); @@ -195,7 +195,7 @@ export class TaskListDemoPage { selectState(state) { this.clickOnStateDropDownArrow(); - let stateElement = element.all(by.cssContainingText('mat-option span', state)).first(); + const stateElement = element.all(by.cssContainingText('mat-option span', state)).first(); Util.waitUntilElementIsClickable(stateElement); Util.waitUntilElementIsVisible(stateElement); stateElement.click(); diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index 360c25dd37..5bcf7cff62 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -144,7 +144,7 @@ export class TasksCloudDemoPage { selectSelectionMode(mode) { this.clickOnSelectionModeDropDownArrow(); - let modeElement = element.all(by.cssContainingText('mat-option span', mode)).first(); + const modeElement = element.all(by.cssContainingText('mat-option span', mode)).first(); Util.waitUntilElementIsClickable(modeElement); Util.waitUntilElementIsVisible(modeElement); modeElement.click(); diff --git a/e2e/pages/adf/dialog/createLibraryDialog.ts b/e2e/pages/adf/dialog/createLibraryDialog.ts index 26515b69d0..6d567f5bb2 100644 --- a/e2e/pages/adf/dialog/createLibraryDialog.ts +++ b/e2e/pages/adf/dialog/createLibraryDialog.ts @@ -34,7 +34,7 @@ export class CreateLibraryDialog { libraryNameHint = element(by.css('adf-library-dialog .mat-hint')); getSelectedRadio() { - let radio = element(by.css('.mat-radio-button[class*="checked"]')); + const radio = element(by.css('.mat-radio-button[class*="checked"]')); Util.waitUntilElementIsVisible(radio); return radio.getText(); } diff --git a/e2e/pages/adf/dialog/editProcessFilterDialog.ts b/e2e/pages/adf/dialog/editProcessFilterDialog.ts index 47250b6377..077f2f0513 100644 --- a/e2e/pages/adf/dialog/editProcessFilterDialog.ts +++ b/e2e/pages/adf/dialog/editProcessFilterDialog.ts @@ -27,7 +27,7 @@ export class EditProcessFilterDialog { cancelButtonLocator = by.id('adf-cancel-button-id'); clickOnSaveButton() { - let saveButton = this.componentElement.element(this.saveButtonLocator); + const saveButton = this.componentElement.element(this.saveButtonLocator); Util.waitUntilElementIsVisible(saveButton); saveButton.click(); Util.waitUntilElementIsNotVisible(this.componentElement); @@ -40,7 +40,7 @@ export class EditProcessFilterDialog { } clickOnCancelButton() { - let cancelButton = this.componentElement.element(this.cancelButtonLocator); + const cancelButton = this.componentElement.element(this.cancelButtonLocator); Util.waitUntilElementIsVisible(cancelButton); cancelButton.click(); Util.waitUntilElementIsNotVisible(this.componentElement); diff --git a/e2e/pages/adf/dialog/editTaskFilterDialog.ts b/e2e/pages/adf/dialog/editTaskFilterDialog.ts index 4ae99bed12..0599e79cd0 100644 --- a/e2e/pages/adf/dialog/editTaskFilterDialog.ts +++ b/e2e/pages/adf/dialog/editTaskFilterDialog.ts @@ -27,7 +27,7 @@ export class EditTaskFilterDialog { cancelButtonLocator = by.id('adf-cancel-button-id'); clickOnSaveButton() { - let saveButton = this.componentElement.element(this.saveButtonLocator); + const saveButton = this.componentElement.element(this.saveButtonLocator); Util.waitUntilElementIsVisible(saveButton); saveButton.click(); Util.waitUntilElementIsNotVisible(this.componentElement); @@ -40,7 +40,7 @@ export class EditTaskFilterDialog { } clickOnCancelButton() { - let cancelButton = this.componentElement.element(this.cancelButtonLocator); + const cancelButton = this.componentElement.element(this.cancelButtonLocator); Util.waitUntilElementIsVisible(cancelButton); cancelButton.click(); Util.waitUntilElementIsNotVisible(this.componentElement); diff --git a/e2e/pages/adf/dialog/shareDialog.ts b/e2e/pages/adf/dialog/shareDialog.ts index a9d3acf92d..21a0165bc0 100644 --- a/e2e/pages/adf/dialog/shareDialog.ts +++ b/e2e/pages/adf/dialog/shareDialog.ts @@ -118,7 +118,7 @@ export class ShareDialog { setDefaultDay() { const selector = '.mat-datetimepicker-calendar-body-cell:not(.mat-datetimepicker-calendar-body-disabled)'; Util.waitUntilElementIsVisible(this.dayPicker); - let tomorrow = new Date(new Date().getTime() + 48 * 60 * 60 * 1000).getDate().toString(); + const tomorrow = new Date(new Date().getTime() + 48 * 60 * 60 * 1000).getDate().toString(); this.dayPicker.element(by.cssContainingText(selector, tomorrow)).click(); } diff --git a/e2e/pages/adf/dialog/uploadDialog.ts b/e2e/pages/adf/dialog/uploadDialog.ts index 1e11c82ab1..fdbfde438e 100644 --- a/e2e/pages/adf/dialog/uploadDialog.ts +++ b/e2e/pages/adf/dialog/uploadDialog.ts @@ -65,7 +65,7 @@ export class UploadDialog { } getRowsName(content) { - let row = element.all(by.css(`div[class*='uploading-row'] span[title="${content}"]`)).first(); + const row = element.all(by.css(`div[class*='uploading-row'] span[title="${content}"]`)).first(); Util.waitUntilElementIsVisible(row); return row; } @@ -115,7 +115,7 @@ export class UploadDialog { getTitleText() { Util.waitUntilElementIsVisible(this.title); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.title.getText().then((text) => { deferred.fulfill(text); }); @@ -124,7 +124,7 @@ export class UploadDialog { getConfirmationDialogTitleText() { Util.waitUntilElementIsVisible(this.canUploadConfirmationTitle); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.canUploadConfirmationTitle.getText().then((text) => { deferred.fulfill(text); }); @@ -133,7 +133,7 @@ export class UploadDialog { getConfirmationDialogDescriptionText() { Util.waitUntilElementIsVisible(this.canUploadConfirmationDescription); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.canUploadConfirmationDescription.getText().then((text) => { deferred.fulfill(text); }); @@ -157,7 +157,7 @@ export class UploadDialog { } numberOfCurrentFilesUploaded() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.getTitleText().then((text: any) => { deferred.fulfill(text.split('Uploaded ')[1].split(' / ')[0]); }); @@ -165,7 +165,7 @@ export class UploadDialog { } numberOfInitialFilesUploaded() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.getTitleText().then((text: any) => { deferred.fulfill(text.split('Uploaded ')[1].split(' / ')[1]); }); diff --git a/e2e/pages/adf/dialog/uploadToggles.ts b/e2e/pages/adf/dialog/uploadToggles.ts index ef05555eb3..2b6742f3be 100644 --- a/e2e/pages/adf/dialog/uploadToggles.ts +++ b/e2e/pages/adf/dialog/uploadToggles.ts @@ -48,25 +48,25 @@ export class UploadToggles { } checkFolderUploadToggleIsEnabled() { - let enabledToggle = element(by.css('mat-slide-toggle[id="adf-folder-upload-switch"][class*="mat-checked"]')); + const enabledToggle = element(by.css('mat-slide-toggle[id="adf-folder-upload-switch"][class*="mat-checked"]')); Util.waitUntilElementIsVisible(enabledToggle); return this; } checkMultipleFileUploadToggleIsEnabled() { - let enabledToggle = element(by.css('mat-slide-toggle[id="adf-multiple-upload-switch"][class*="mat-checked"]')); + const enabledToggle = element(by.css('mat-slide-toggle[id="adf-multiple-upload-switch"][class*="mat-checked"]')); Util.waitUntilElementIsVisible(enabledToggle); return this; } checkMaxSizeToggleIsEnabled() { - let enabledToggle = element(by.css('mat-slide-toggle[id="adf-max-size-filter-upload-switch"][class*="mat-checked"]')); + const enabledToggle = element(by.css('mat-slide-toggle[id="adf-max-size-filter-upload-switch"][class*="mat-checked"]')); Util.waitUntilElementIsVisible(enabledToggle); return this; } checkVersioningToggleIsEnabled() { - let enabledToggle = element(by.css('mat-slide-toggle[id="adf-version-upload-switch"][class*="mat-checked"]')); + const enabledToggle = element(by.css('mat-slide-toggle[id="adf-version-upload-switch"][class*="mat-checked"]')); Util.waitUntilElementIsVisible(enabledToggle); return this; } @@ -122,7 +122,7 @@ export class UploadToggles { clearText() { Util.waitUntilElementIsVisible(this.maxSizeField); - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.maxSizeField.clear().then((value) => { this.maxSizeField.sendKeys(protractor.Key.ESCAPE); }); diff --git a/e2e/pages/adf/filePreviewPage.ts b/e2e/pages/adf/filePreviewPage.ts index 4672cd6733..0edef8d95a 100644 --- a/e2e/pages/adf/filePreviewPage.ts +++ b/e2e/pages/adf/filePreviewPage.ts @@ -35,7 +35,7 @@ export class FilePreviewPage { } getPDFTitleFromSearch() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); Util.waitUntilElementIsVisible(this.pdfTitleFromSearch); Util.waitUntilElementIsVisible(this.textLayer); this.pdfTitleFromSearch.getText().then((result) => { @@ -78,10 +78,10 @@ export class FilePreviewPage { } checkText(pageNumber, text) { - let allPages = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); - let pageLoaded = element(by.css(`div[id="pageContainer${pageNumber}"][data-loaded='true']`)); - let textLayerLoaded = element(by.css(`div[id="pageContainer${pageNumber}"] div[class='textLayer'] > div`)); - let specificText = element(by.cssContainingText(`div[id="pageContainer${pageNumber}"] div[class='textLayer'] > div`, text)); + const allPages = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); + const pageLoaded = element(by.css(`div[id="pageContainer${pageNumber}"][data-loaded='true']`)); + const textLayerLoaded = element(by.css(`div[id="pageContainer${pageNumber}"] div[class='textLayer'] > div`)); + const specificText = element(by.cssContainingText(`div[id="pageContainer${pageNumber}"] div[class='textLayer'] > div`, text)); Util.waitUntilElementIsVisible(allPages); Util.waitUntilElementIsVisible(pageLoaded); @@ -90,19 +90,19 @@ export class FilePreviewPage { } goToNextPage() { - let nextPageIcon = element(by.css(`div[id='viewer-next-page-button']`)); + const nextPageIcon = element(by.css(`div[id='viewer-next-page-button']`)); Util.waitUntilElementIsVisible(nextPageIcon); nextPageIcon.click(); } goToPreviousPage() { - let previousPageIcon = element(by.css(`div[id='viewer-previous-page-button']`)); + const previousPageIcon = element(by.css(`div[id='viewer-previous-page-button']`)); Util.waitUntilElementIsVisible(previousPageIcon); previousPageIcon.click(); } goToPage(page) { - let pageInput = element(by.css(`input[id='viewer-pagenumber-input']`)); + const pageInput = element(by.css(`input[id='viewer-pagenumber-input']`)); Util.waitUntilElementIsVisible(pageInput); pageInput.clear(); @@ -116,7 +116,7 @@ export class FilePreviewPage { } closePreviewWithEsc(fileName) { - let filePreview = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); + const filePreview = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); Util.waitUntilElementIsVisible(element(by.cssContainingText(`div[data-automation-id="text_${fileName}"]`, fileName))); @@ -124,28 +124,28 @@ export class FilePreviewPage { } clickDownload(fileName) { - let downloadButton = element(by.css(`button[id='viewer-download-button']`)); + const downloadButton = element(by.css(`button[id='viewer-download-button']`)); Util.waitUntilElementIsVisible(downloadButton); downloadButton.click(); } clickZoomIn() { - let zoomInButton = element(by.css(`div[id='viewer-zoom-in-button']`)); + const zoomInButton = element(by.css(`div[id='viewer-zoom-in-button']`)); Util.waitUntilElementIsVisible(zoomInButton); zoomInButton.click(); } clickZoomOut() { - let zoomOutButton = element(by.css(`div[id='viewer-zoom-out-button']`)); + const zoomOutButton = element(by.css(`div[id='viewer-zoom-out-button']`)); Util.waitUntilElementIsVisible(zoomOutButton); zoomOutButton.click(); } clickActualSize() { - let actualSizeButton = element(by.css(`div[id='viewer-scale-page-button']`)); + const actualSizeButton = element(by.css(`div[id='viewer-scale-page-button']`)); Util.waitUntilElementIsVisible(actualSizeButton); actualSizeButton.click(); @@ -164,8 +164,8 @@ export class FilePreviewPage { } zoomIn() { - let canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); - let textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); + const canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); + const textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); Util.waitUntilElementIsVisible(canvasLayer); Util.waitUntilElementIsVisible(textLayer); @@ -207,8 +207,8 @@ export class FilePreviewPage { } actualSize() { - let canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); - let textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); + const canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); + const textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); Util.waitUntilElementIsVisible(canvasLayer); Util.waitUntilElementIsVisible(textLayer); @@ -257,17 +257,18 @@ export class FilePreviewPage { }); } + /* zoomOut() { - let canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); - let textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); + const canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); + const textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); Util.waitUntilElementIsVisible(canvasLayer); Util.waitUntilElementIsVisible(textLayer); - let actualWidth, - zoomedOutWidth, - actualHeight, - zoomedOutHeight; + let actualWidth; + let zoomedOutWidth; + let actualHeight; + let zoomedOutHeight; this.checkCanvasWidth().then((width) => { actualWidth = width; @@ -298,4 +299,5 @@ export class FilePreviewPage { } }); } + */ } diff --git a/e2e/pages/adf/material/datePickerPage.ts b/e2e/pages/adf/material/datePickerPage.ts index 67c8ce8be9..6e0fa1c077 100644 --- a/e2e/pages/adf/material/datePickerPage.ts +++ b/e2e/pages/adf/material/datePickerPage.ts @@ -30,8 +30,8 @@ export class DatePickerPage { } checkDatesAfterDateAreDisabled(date) { - let afterDate = DateUtil.formatDate('DD-MM-YY', date, 1); - let afterCalendar = element(by.css(`td[class*="mat-calendar-body-cell"][aria-label="${afterDate}"]`)); + const afterDate = DateUtil.formatDate('DD-MM-YY', date, 1); + const afterCalendar = element(by.css(`td[class*="mat-calendar-body-cell"][aria-label="${afterDate}"]`)); browser.controlFlow().execute(async () => { if (await afterCalendar.isPresent()) { await expect(afterCalendar.getAttribute('aria-disabled')).toBe('true'); @@ -42,8 +42,8 @@ export class DatePickerPage { } checkDatesBeforeDateAreDisabled(date) { - let beforeDate = DateUtil.formatDate('DD-MM-YY', date, -1); - let beforeCalendar = element(by.css(`td[class*="mat-calendar-body-cell"][aria-label="${beforeDate}"]`)); + const beforeDate = DateUtil.formatDate('DD-MM-YY', date, -1); + const beforeCalendar = element(by.css(`td[class*="mat-calendar-body-cell"][aria-label="${beforeDate}"]`)); browser.controlFlow().execute(async () => { if (await beforeCalendar.isPresent()) { await expect(beforeCalendar.getAttribute('aria-disabled')).toBe('true'); @@ -55,7 +55,7 @@ export class DatePickerPage { selectTodayDate() { this.checkDatePickerIsDisplayed(); - let todayDate = element(by.css('.mat-calendar-body-today')); + const todayDate = element(by.css('.mat-calendar-body-today')); Util.waitUntilElementIsClickable(todayDate); todayDate.click(); return this; diff --git a/e2e/pages/adf/metadataViewPage.ts b/e2e/pages/adf/metadataViewPage.ts index 768c8ad422..d46de60f02 100644 --- a/e2e/pages/adf/metadataViewPage.ts +++ b/e2e/pages/adf/metadataViewPage.ts @@ -145,7 +145,7 @@ export class MetadataViewPage { } clickOnPropertiesTab(): MetadataViewPage { - let propertiesTab = element(by.cssContainingText(`.adf-info-drawer-layout-content div.mat-tab-labels div .mat-tab-label-content`, `Properties`)); + const propertiesTab = element(by.cssContainingText(`.adf-info-drawer-layout-content div.mat-tab-labels div .mat-tab-label-content`, `Properties`)); Util.waitUntilElementIsVisible(propertiesTab); propertiesTab.click(); return this; @@ -166,23 +166,23 @@ export class MetadataViewPage { } editPropertyIconIsDisplayed(propertyName: string) { - let editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); + const editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); Util.waitUntilElementIsVisible(editPropertyIcon); } updatePropertyIconIsDisplayed(propertyName: string) { - let updatePropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-' + propertyName + '"]')); + const updatePropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-' + propertyName + '"]')); Util.waitUntilElementIsVisible(updatePropertyIcon); } clickUpdatePropertyIcon(propertyName: string): promise.Promise { - let updatePropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-' + propertyName + '"]')); + const updatePropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-' + propertyName + '"]')); Util.waitUntilElementIsVisible(updatePropertyIcon); return updatePropertyIcon.click(); } clickClearPropertyIcon(propertyName: string): promise.Promise { - let clearPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-' + propertyName + '"]')); + const clearPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-' + propertyName + '"]')); Util.waitUntilElementIsVisible(clearPropertyIcon); return clearPropertyIcon.click(); } @@ -225,62 +225,62 @@ export class MetadataViewPage { } clearPropertyIconIsDisplayed(propertyName: string) { - let clearPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-' + propertyName + '"]')); + const clearPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-' + propertyName + '"]')); Util.waitUntilElementIsVisible(clearPropertyIcon); } clickEditPropertyIcons(propertyName: string) { - let editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); + const editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); Util.waitUntilElementIsClickable(editPropertyIcon); editPropertyIcon.click(); } getPropertyIconTooltip(propertyName: string): promise.Promise { - let editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); + const editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); return editPropertyIcon.getAttribute('title'); } clickMetadataGroup(groupName: string) { - let group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); + const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); Util.waitUntilElementIsVisible(group); group.click(); } checkMetadataGroupIsPresent(groupName: string): promise.Promise { - let group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); + const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); return Util.waitUntilElementIsVisible(group); } checkMetadataGroupIsNotPresent(groupName: string): promise.Promise { - let group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); + const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); return Util.waitUntilElementIsNotVisible(group); } checkMetadataGroupIsExpand(groupName: string) { - let group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); + const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); Util.waitUntilElementIsVisible(group); expect(group.getAttribute('class')).toContain('mat-expanded'); } checkMetadataGroupIsNotExpand(groupName: string) { - let group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); + const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); Util.waitUntilElementIsVisible(group); expect(group.getAttribute('class')).not.toContain('mat-expanded'); } getMetadataGroupTitle(groupName: string): promise.Promise { - let group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header > span > mat-panel-title')); + const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header > span > mat-panel-title')); Util.waitUntilElementIsVisible(group); return group.getText(); } checkPropertyIsVisible(propertyName: string, type: string) { - let property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); + const property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); Util.waitUntilElementIsVisible(property); } checkPropertyIsNotVisible(propertyName: string, type: string) { - let property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); + const property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); Util.waitUntilElementIsNotVisible(property); } diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index 8c630cc8d5..92d8e34f56 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -126,7 +126,7 @@ export class NavigationBarPage { } clickOnSpecificThemeButton(themeName) { - let themeElement = element(by.css(`button[data-automation-id="${themeName}"]`)); + const themeElement = element(by.css(`button[data-automation-id="${themeName}"]`)); Util.waitUntilElementIsVisible(themeElement); Util.waitUntilElementIsClickable(themeElement); themeElement.click(); @@ -147,7 +147,7 @@ export class NavigationBarPage { } chooseLanguage(language) { - let buttonLanguage = element(by.xpath(`//adf-language-menu//button[contains(text(), '${language}')]`)); + const buttonLanguage = element(by.xpath(`//adf-language-menu//button[contains(text(), '${language}')]`)); Util.waitUntilElementIsVisible(buttonLanguage); buttonLanguage.click(); } @@ -182,12 +182,12 @@ export class NavigationBarPage { } checkToolbarColor(color) { - let toolbarColor = element(by.css(`mat-toolbar[class*="mat-${color}"]`)); + const toolbarColor = element(by.css(`mat-toolbar[class*="mat-${color}"]`)); return Util.waitUntilElementIsVisible(toolbarColor); } clickAppLogo(logoTitle) { - let appLogo = element(by.css('a[title="' + logoTitle + '"]')); + const appLogo = element(by.css('a[title="' + logoTitle + '"]')); Util.waitUntilElementIsVisible(appLogo); appLogo.click(); } @@ -205,7 +205,7 @@ export class NavigationBarPage { } checkLogoTooltip(logoTooltipTitle) { - let logoTooltip = element(by.css('a[title="' + logoTooltipTitle + '"]')); + const logoTooltip = element(by.css('a[title="' + logoTooltipTitle + '"]')); Util.waitUntilElementIsVisible(logoTooltip); } diff --git a/e2e/pages/adf/notificationPage.ts b/e2e/pages/adf/notificationPage.ts index 804442c3a7..68e59bdd36 100644 --- a/e2e/pages/adf/notificationPage.ts +++ b/e2e/pages/adf/notificationPage.ts @@ -54,7 +54,7 @@ export class NotificationPage { } checkNotificationSnackBarIsDisplayedWithMessage(message) { - let notificationSnackBarMessage = element(by.cssContainingText('simple-snack-bar', message)); + const notificationSnackBarMessage = element(by.cssContainingText('simple-snack-bar', message)); Util.waitUntilElementIsVisible(notificationSnackBarMessage); return this; } @@ -77,21 +77,21 @@ export class NotificationPage { } selectHorizontalPosition(selectedItem) { - let selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); + const selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); this.horizontalPosition.click(); Util.waitUntilElementIsVisible(this.selectionDropDown); selectItem.click(); } selectVerticalPosition(selectedItem) { - let selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); + const selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); this.verticalPosition.click(); Util.waitUntilElementIsVisible(this.selectionDropDown); selectItem.click(); } selectDirection(selectedItem) { - let selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); + const selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); this.direction.click(); Util.waitUntilElementIsVisible(this.selectionDropDown); selectItem.click(); diff --git a/e2e/pages/adf/paginationPage.ts b/e2e/pages/adf/paginationPage.ts index a1d3a91007..dcadd67ce1 100644 --- a/e2e/pages/adf/paginationPage.ts +++ b/e2e/pages/adf/paginationPage.ts @@ -45,7 +45,7 @@ export class PaginationPage { this.itemsPerPageDropdown.click(); Util.waitUntilElementIsVisible(this.pageSelectorDropDown); - let itemsPerPage = element.all(by.cssContainingText('.mat-menu-item', numberOfItem)).first(); + const itemsPerPage = element.all(by.cssContainingText('.mat-menu-item', numberOfItem)).first(); Util.waitUntilElementIsClickable(itemsPerPage); Util.waitUntilElementIsVisible(itemsPerPage); itemsPerPage.click(); @@ -103,16 +103,16 @@ export class PaginationPage { clickOnPageDropdownOption(numberOfItemPerPage: string) { Util.waitUntilElementIsVisible(element.all(this.pageDropDownOptions).first()); - let option = element(by.cssContainingText('div[class*="mat-menu-content"] button', numberOfItemPerPage)); + const option = element(by.cssContainingText('div[class*="mat-menu-content"] button', numberOfItemPerPage)); Util.waitUntilElementIsVisible(option); option.click(); return this; } getPageDropdownOptions() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); Util.waitUntilElementIsVisible(element.all(this.pageDropDownOptions).first()); - let initialList = []; + const initialList = []; element.all(this.pageDropDownOptions).each(function (currentOption) { currentOption.getText().then(function (text) { if (text !== '') { @@ -143,8 +143,8 @@ export class PaginationPage { getTotalNumberOfFiles() { Util.waitUntilElementIsVisible(this.totalFiles); - let numberOfFiles = this.totalFiles.getText().then(function (totalNumber) { - let totalNumberOfFiles = totalNumber.split('of ')[1]; + const numberOfFiles = this.totalFiles.getText().then(function (totalNumber) { + const totalNumberOfFiles = totalNumber.split('of ')[1]; return totalNumberOfFiles; }); diff --git a/e2e/pages/adf/permissionsPage.ts b/e2e/pages/adf/permissionsPage.ts index 8c83a85c76..3772decb98 100644 --- a/e2e/pages/adf/permissionsPage.ts +++ b/e2e/pages/adf/permissionsPage.ts @@ -20,7 +20,7 @@ import { element, by } from 'protractor'; import { Util } from '../../util/util'; import { DataTableComponentPage } from './dataTableComponentPage'; -let column = { +const column = { role: 'Role' }; @@ -74,7 +74,7 @@ export class PermissionsPage { } clickUserOrGroup(name) { - let userOrGroupName = element(by.cssContainingText('mat-list-option .mat-list-text', name)); + const userOrGroupName = element(by.cssContainingText('mat-list-option .mat-list-text', name)); Util.waitUntilElementIsVisible(userOrGroupName); userOrGroupName.click(); Util.waitUntilElementIsVisible(this.addButton); @@ -82,12 +82,12 @@ export class PermissionsPage { } checkUserOrGroupIsAdded(name) { - let userOrGroupName = element(by.css('div[data-automation-id="text_' + name + '"]')); + const userOrGroupName = element(by.css('div[data-automation-id="text_' + name + '"]')); Util.waitUntilElementIsVisible(userOrGroupName); } checkUserOrGroupIsDeleted(name) { - let userOrGroupName = element(by.css('div[data-automation-id="text_' + name + '"]')); + const userOrGroupName = element(by.css('div[data-automation-id="text_' + name + '"]')); Util.waitUntilElementIsNotVisible(userOrGroupName); } @@ -119,7 +119,7 @@ export class PermissionsPage { } getRoleCellValue(rowName) { - let locator = new DataTableComponentPage().getCellByRowAndColumn('Authority ID', rowName, column.role); + const locator = new DataTableComponentPage().getCellByRowAndColumn('Authority ID', rowName, column.role); Util.waitUntilElementIsVisible(locator); return locator.getText(); } @@ -135,7 +135,7 @@ export class PermissionsPage { } selectOption(name) { - let selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); + const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); Util.waitUntilElementIsVisible(selectProcessDropdown); Util.waitUntilElementIsClickable(selectProcessDropdown); selectProcessDropdown.click(); @@ -152,7 +152,7 @@ export class PermissionsPage { } checkUserOrGroupIsDisplayed(name) { - let userOrGroupName = element(by.cssContainingText('mat-list-option .mat-list-text', name)); + const userOrGroupName = element(by.cssContainingText('mat-list-option .mat-list-text', name)); Util.waitUntilElementIsVisible(userOrGroupName); } } diff --git a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts b/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts index 3a081692f7..ed75cf0d72 100644 --- a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts @@ -39,9 +39,9 @@ export class EditProcessFilterCloudComponent { } checkCustomiseFilterHeaderIsExpanded() { - let expansionPanelExtended = element.all(by.css('mat-expansion-panel-header[class*="mat-expanded"]')).first(); + const expansionPanelExtended = element.all(by.css('mat-expansion-panel-header[class*="mat-expanded"]')).first(); Util.waitUntilElementIsVisible(expansionPanelExtended); - let content = element(by.css('div[class*="mat-expansion-panel-content "][style*="visible"]')); + const content = element(by.css('div[class*="mat-expansion-panel-content "][style*="visible"]')); Util.waitUntilElementIsVisible(content); return this; } @@ -49,7 +49,7 @@ export class EditProcessFilterCloudComponent { setStatusFilterDropDown(option) { this.clickOnDropDownArrow('status'); - let statusElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const statusElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(statusElement); Util.waitUntilElementIsVisible(statusElement); statusElement.click(); @@ -63,7 +63,7 @@ export class EditProcessFilterCloudComponent { setSortFilterDropDown(option) { this.clickOnDropDownArrow('sort'); - let sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(sortElement); Util.waitUntilElementIsVisible(sortElement); sortElement.click(); @@ -71,7 +71,7 @@ export class EditProcessFilterCloudComponent { } getSortFilterDropDownValue() { - let sortLocator = element.all(by.css("mat-form-field[data-automation-id='sort'] span")).first(); + const sortLocator = element.all(by.css("mat-form-field[data-automation-id='sort'] span")).first(); Util.waitUntilElementIsVisible(sortLocator); return sortLocator.getText(); } @@ -79,7 +79,7 @@ export class EditProcessFilterCloudComponent { setOrderFilterDropDown(option) { this.clickOnDropDownArrow('order'); - let orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(orderElement); Util.waitUntilElementIsVisible(orderElement); orderElement.click(); @@ -91,7 +91,7 @@ export class EditProcessFilterCloudComponent { } clickOnDropDownArrow(option) { - let dropDownArrow = element.all(by.css("mat-form-field[data-automation-id='" + option + "'] div[class='mat-select-arrow-wrapper']")).first(); + const dropDownArrow = element.all(by.css("mat-form-field[data-automation-id='" + option + "'] div[class='mat-select-arrow-wrapper']")).first(); Util.waitUntilElementIsVisible(dropDownArrow); Util.waitUntilElementIsClickable(dropDownArrow); dropDownArrow.click(); @@ -101,7 +101,7 @@ export class EditProcessFilterCloudComponent { setAppNameDropDown(option) { this.clickOnDropDownArrow('appName'); - let appNameElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const appNameElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(appNameElement); Util.waitUntilElementIsVisible(appNameElement); appNameElement.click(); @@ -109,10 +109,10 @@ export class EditProcessFilterCloudComponent { } async checkAppNamesAreUnique() { - let appNameList = element.all(by.css('mat-option[data-automation-id="adf-cloud-edit-process-property-optionsappName"] span')); - let appTextList: any = await appNameList.getText(); - let uniqueArray = appTextList.filter((appName) => { - let sameAppNameArray = appTextList.filter((eachApp) => eachApp === appName); + const appNameList = element.all(by.css('mat-option[data-automation-id="adf-cloud-edit-process-property-optionsappName"] span')); + const appTextList: any = await appNameList.getText(); + const uniqueArray = appTextList.filter((appName) => { + const sameAppNameArray = appTextList.filter((eachApp) => eachApp === appName); return sameAppNameArray.length === 1; }); return uniqueArray.length === appTextList.length; @@ -120,7 +120,7 @@ export class EditProcessFilterCloudComponent { getNumberOfAppNameOptions() { this.clickOnDropDownArrow('appName'); - let dropdownOptions = element.all(by.css('.mat-select-panel mat-option')); + const dropdownOptions = element.all(by.css('.mat-select-panel mat-option')); return dropdownOptions.count(); } @@ -133,13 +133,13 @@ export class EditProcessFilterCloudComponent { } getProperty(property) { - let locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first(); + const locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first(); Util.waitUntilElementIsVisible(locator); return locator.getAttribute('value'); } setProperty(property, option) { - let locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first(); + const locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first(); Util.waitUntilElementIsVisible(locator); locator.clear(); locator.sendKeys(option); @@ -178,7 +178,7 @@ export class EditProcessFilterCloudComponent { } clickSaveAsButton() { - let disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); + const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); Util.waitUntilElementIsClickable(this.saveAsButton); Util.waitUntilElementIsVisible(this.saveAsButton); Util.waitUntilElementIsNotVisible(disabledButton); @@ -193,7 +193,7 @@ export class EditProcessFilterCloudComponent { } clickSaveButton() { - let disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); + const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); Util.waitUntilElementIsClickable(this.saveButton); Util.waitUntilElementIsVisible(this.saveButton); Util.waitUntilElementIsNotVisible(disabledButton); diff --git a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts b/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts index 101bf49bcd..c5484f2413 100644 --- a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts @@ -51,7 +51,7 @@ export class EditTaskFilterCloudComponent { setStatusFilterDropDown(option) { this.clickOnDropDownArrow('status'); - let statusElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const statusElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsVisible(statusElement); Util.waitUntilElementIsClickable(statusElement); statusElement.click(); @@ -65,7 +65,7 @@ export class EditTaskFilterCloudComponent { setSortFilterDropDown(option) { this.clickOnDropDownArrow('sort'); - let sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(sortElement); Util.waitUntilElementIsVisible(sortElement); sortElement.click(); @@ -73,7 +73,7 @@ export class EditTaskFilterCloudComponent { } getSortFilterDropDownValue() { - let elementSort = element.all(by.css("mat-select[data-automation-id='adf-cloud-edit-task-property-sort'] span")).first(); + const elementSort = element.all(by.css("mat-select[data-automation-id='adf-cloud-edit-task-property-sort'] span")).first(); Util.waitUntilElementIsVisible(elementSort); return elementSort.getText(); } @@ -81,7 +81,7 @@ export class EditTaskFilterCloudComponent { setOrderFilterDropDown(option) { this.clickOnDropDownArrow('order'); - let orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(orderElement); Util.waitUntilElementIsVisible(orderElement); orderElement.click(); @@ -93,7 +93,7 @@ export class EditTaskFilterCloudComponent { } clickOnDropDownArrow(option) { - let dropDownArrow = element.all(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")).first(); + const dropDownArrow = element.all(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")).first(); Util.waitUntilElementIsVisible(dropDownArrow); dropDownArrow.click(); Util.waitUntilElementIsVisible(this.selectedOption); @@ -180,7 +180,7 @@ export class EditTaskFilterCloudComponent { } clickSaveAsButton() { - let disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]"))); + const disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]"))); Util.waitUntilElementIsClickable(this.saveAsButton); Util.waitUntilElementIsVisible(this.saveAsButton); Util.waitUntilElementIsNotVisible(disabledButton); @@ -217,7 +217,7 @@ export class EditTaskFilterCloudComponent { setAppNameDropDown(option) { this.clickOnDropDownArrow('appName'); - let appNameElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const appNameElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(appNameElement); Util.waitUntilElementIsVisible(appNameElement); appNameElement.click(); @@ -225,7 +225,7 @@ export class EditTaskFilterCloudComponent { } getAppNameDropDownValue() { - let locator = element.all(by.css("mat-select[data-automation-id='adf-cloud-edit-task-property-appName'] span")).first(); + const locator = element.all(by.css("mat-select[data-automation-id='adf-cloud-edit-task-property-appName'] span")).first(); Util.waitUntilElementIsVisible(locator); return locator.getText(); } @@ -251,7 +251,7 @@ export class EditTaskFilterCloudComponent { } setProperty(property, option) { - let locator = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-' + property + '"]')); + const locator = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-' + property + '"]')); Util.waitUntilElementIsVisible(locator); locator.clear(); locator.sendKeys(option); diff --git a/e2e/pages/adf/process-cloud/groupCloudComponent.ts b/e2e/pages/adf/process-cloud/groupCloudComponent.ts index f262903dbf..da69613b33 100644 --- a/e2e/pages/adf/process-cloud/groupCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/groupCloudComponent.ts @@ -35,7 +35,7 @@ export class GroupCloudComponent { } selectGroupFromList(name) { - let groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); + const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); Util.waitUntilElementIsVisible(groupRow); groupRow.click(); Util.waitUntilElementIsNotVisible(groupRow); @@ -43,13 +43,13 @@ export class GroupCloudComponent { } checkGroupIsDisplayed(name) { - let groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); + const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); Util.waitUntilElementIsVisible(groupRow); return this; } checkGroupIsNotDisplayed(name) { - let groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); + const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); Util.waitUntilElementIsNotVisible(groupRow); return this; } diff --git a/e2e/pages/adf/process-cloud/peopleCloudComponent.ts b/e2e/pages/adf/process-cloud/peopleCloudComponent.ts index 6e802db453..939a414ea6 100644 --- a/e2e/pages/adf/process-cloud/peopleCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/peopleCloudComponent.ts @@ -43,7 +43,7 @@ export class PeopleCloudComponent { } selectAssigneeFromList(name) { - let assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); + const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); Util.waitUntilElementIsVisible(assigneeRow); assigneeRow.click(); Util.waitUntilElementIsNotVisible(assigneeRow); @@ -56,13 +56,13 @@ export class PeopleCloudComponent { } checkUserIsDisplayed(name) { - let assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); + const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); Util.waitUntilElementIsVisible(assigneeRow); return this; } checkUserIsNotDisplayed(name) { - let assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); + const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); Util.waitUntilElementIsNotVisible(assigneeRow); return this; } diff --git a/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts b/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts index 897286e4df..a4871f0fa4 100644 --- a/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts @@ -34,7 +34,7 @@ export class ProcessFiltersCloudComponent { getProcessFilterIcon() { Util.waitUntilElementIsVisible(this.filter); - let icon = this.filter.element(this.filterIcon); + const icon = this.filter.element(this.filterIcon); Util.waitUntilElementIsVisible(icon); return icon.getText(); } diff --git a/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts b/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts index 28741898fd..c0bc3ef967 100644 --- a/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts @@ -34,7 +34,7 @@ export class TaskFiltersCloudComponent { getTaskFilterIcon() { Util.waitUntilElementIsVisible(this.filter); - let icon = this.filter.element(this.taskIcon); + const icon = this.filter.element(this.taskIcon); Util.waitUntilElementIsVisible(icon); return icon.getText(); } diff --git a/e2e/pages/adf/process-cloud/taskListCloudComponent.ts b/e2e/pages/adf/process-cloud/taskListCloudComponent.ts index bb3bfffc94..55bdcdab20 100644 --- a/e2e/pages/adf/process-cloud/taskListCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/taskListCloudComponent.ts @@ -19,7 +19,7 @@ import { Util } from '../../../util/util'; import { DataTableComponentPage } from '../dataTableComponentPage'; import { element, by } from 'protractor'; -let column = { +const column = { id: 'Id' }; @@ -105,7 +105,7 @@ export class TaskListCloudComponent { } getIdCellValue(rowName) { - let locator = new DataTableComponentPage().getCellByRowAndColumn('Name', rowName, column.id); + const locator = new DataTableComponentPage().getCellByRowAndColumn('Name', rowName, column.id); Util.waitUntilElementIsVisible(locator); return locator.getText(); } diff --git a/e2e/pages/adf/process-services/analyticsPage.ts b/e2e/pages/adf/process-services/analyticsPage.ts index ff837660b5..c3afdcc4b8 100644 --- a/e2e/pages/adf/process-services/analyticsPage.ts +++ b/e2e/pages/adf/process-services/analyticsPage.ts @@ -26,7 +26,7 @@ export class AnalyticsPage { reportMessage = element(by.css('div[class="ng-star-inserted"] span')); getReport(title) { - let reportTitle = element(by.css(`mat-icon[data-automation-id="${title}_filter"]`)); + const reportTitle = element(by.css(`mat-icon[data-automation-id="${title}_filter"]`)); Util.waitUntilElementIsVisible(reportTitle); reportTitle.click(); } diff --git a/e2e/pages/adf/process-services/attachmentListPage.ts b/e2e/pages/adf/process-services/attachmentListPage.ts index 82a35f2c95..fdc5004df2 100644 --- a/e2e/pages/adf/process-services/attachmentListPage.ts +++ b/e2e/pages/adf/process-services/attachmentListPage.ts @@ -43,7 +43,7 @@ export class AttachmentListPage { } checkFileIsAttached(name) { - let fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); + const fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); Util.waitUntilElementIsVisible(fileAttached); } @@ -88,7 +88,7 @@ export class AttachmentListPage { doubleClickFile(name) { Util.waitUntilElementIsVisible(element.all(by.css('div[filename="' + name + '"]')).first()); - let fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); + const fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); Util.waitUntilElementIsVisible(fileAttached); Util.waitUntilElementIsClickable(fileAttached); fileAttached.click(); @@ -96,7 +96,7 @@ export class AttachmentListPage { } checkFileIsRemoved(name) { - let fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); + const fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); Util.waitUntilElementIsNotVisible(fileAttached); return this; } diff --git a/e2e/pages/adf/process-services/dialog/startTaskDialog.ts b/e2e/pages/adf/process-services/dialog/startTaskDialog.ts index f805f1665d..52d6435849 100644 --- a/e2e/pages/adf/process-services/dialog/startTaskDialog.ts +++ b/e2e/pages/adf/process-services/dialog/startTaskDialog.ts @@ -56,7 +56,7 @@ export class StartTaskDialog { } selectAssigneeFromList(name) { - let assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); + const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); Util.waitUntilElementIsVisible(assigneeRow); assigneeRow.click(); Util.waitUntilElementIsNotVisible(assigneeRow); @@ -75,7 +75,7 @@ export class StartTaskDialog { } selectForm(form) { - let option = element(by.cssContainingText('span[class*="mat-option-text"]', form)); + const option = element(by.cssContainingText('span[class*="mat-option-text"]', form)); Util.waitUntilElementIsVisible(option); Util.waitUntilElementIsClickable(option); option.click(); diff --git a/e2e/pages/adf/process-services/filtersPage.ts b/e2e/pages/adf/process-services/filtersPage.ts index c2fbf060f8..5e66ea05a7 100644 --- a/e2e/pages/adf/process-services/filtersPage.ts +++ b/e2e/pages/adf/process-services/filtersPage.ts @@ -30,7 +30,7 @@ export class FiltersPage { } goToFilter(filterName) { - let filter = element(by.css(`span[data-automation-id="${filterName}_filter"]`)); + const filter = element(by.css(`span[data-automation-id="${filterName}_filter"]`)); Util.waitUntilElementIsVisible(filter); filter.click(); return this; diff --git a/e2e/pages/adf/process-services/formFields.ts b/e2e/pages/adf/process-services/formFields.ts index a56bffb4bd..00bef9cdf0 100644 --- a/e2e/pages/adf/process-services/formFields.ts +++ b/e2e/pages/adf/process-services/formFields.ts @@ -34,7 +34,7 @@ export class FormFields { errorMessage = by.css('.adf-error-text-container .adf-error-text'); setFieldValue(locator, field, value) { - let fieldElement = element(locator(field)); + const fieldElement = element(locator(field)); Util.waitUntilElementIsVisible(fieldElement); fieldElement.clear(); fieldElement.sendKeys(value); @@ -42,46 +42,46 @@ export class FormFields { } checkWidgetIsVisible(fieldId) { - let fieldElement = element.all(by.css(`adf-form-field div[id='field-${fieldId}-container']`)).first(); + const fieldElement = element.all(by.css(`adf-form-field div[id='field-${fieldId}-container']`)).first(); Util.waitUntilElementIsVisible(fieldElement); } checkWidgetIsHidden(fieldId) { - let hiddenElement = element(by.css(`adf-form-field div[id='field-${fieldId}-container'][hidden]`)); + const hiddenElement = element(by.css(`adf-form-field div[id='field-${fieldId}-container'][hidden]`)); Util.waitUntilElementIsVisible(hiddenElement); } getWidget(fieldId) { - let widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); + const widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); Util.waitUntilElementIsVisible(widget); return widget; } getFieldValue(fieldId, valueLocatorParam?: any) { - let value = this.getWidget(fieldId).element(valueLocatorParam || this.valueLocator); + const value = this.getWidget(fieldId).element(valueLocatorParam || this.valueLocator); Util.waitUntilElementIsVisible(value); return value.getAttribute('value'); } getFieldLabel(fieldId, labelLocatorParam?: any) { - let label = this.getWidget(fieldId).all(labelLocatorParam || this.labelLocator).first(); + const label = this.getWidget(fieldId).all(labelLocatorParam || this.labelLocator).first(); Util.waitUntilElementIsVisible(label); return label.getText(); } getFieldErrorMessage(fieldId) { - let error = this.getWidget(fieldId).element(this.errorMessage); + const error = this.getWidget(fieldId).element(this.errorMessage); return error.getText(); } getFieldText(fieldId, labelLocatorParam?: any) { - let label = this.getWidget(fieldId).element(labelLocatorParam || this.labelLocator); + const label = this.getWidget(fieldId).element(labelLocatorParam || this.labelLocator); Util.waitUntilElementIsVisible(label); return label.getText(); } getFieldPlaceHolder(fieldId, locator = 'input') { - let placeHolderLocator = element(by.css(`${locator}#${fieldId}`)).getAttribute('placeholder'); + const placeHolderLocator = element(by.css(`${locator}#${fieldId}`)).getAttribute('placeholder'); Util.waitUntilElementIsVisible(placeHolderLocator); return placeHolderLocator; } @@ -139,14 +139,14 @@ export class FormFields { } selectFormFromDropDown(formName) { - let formNameElement = element(by.cssContainingText('span', formName)); + const formNameElement = element(by.cssContainingText('span', formName)); Util.waitUntilElementIsVisible(formNameElement); formNameElement.click(); } checkWidgetIsReadOnlyMode(fieldId) { - let widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); - let widgetReadOnly = widget.element(by.css('div[class*="adf-readonly"]')); + const widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); + const widgetReadOnly = widget.element(by.css('div[class*="adf-readonly"]')); Util.waitUntilElementIsVisible(widgetReadOnly); return widgetReadOnly; } @@ -157,7 +157,7 @@ export class FormFields { } setValueInInputById(fieldId, value) { - let input = element(by.id(fieldId)); + const input = element(by.id(fieldId)); Util.waitUntilElementIsVisible(input); input.clear(); input.sendKeys(value); diff --git a/e2e/pages/adf/process-services/processDetailsPage.ts b/e2e/pages/adf/process-services/processDetailsPage.ts index 82f272d19b..8e7ec3a943 100644 --- a/e2e/pages/adf/process-services/processDetailsPage.ts +++ b/e2e/pages/adf/process-services/processDetailsPage.ts @@ -137,7 +137,7 @@ export class ProcessDetailsPage { } checkCommentIsDisplayed(comment) { - let commentInserted = element(by.cssContainingText('div[id="comment-message"]', comment)); + const commentInserted = element(by.cssContainingText('div[id="comment-message"]', comment)); Util.waitUntilElementIsVisible(commentInserted); return this; } diff --git a/e2e/pages/adf/process-services/processFiltersPage.ts b/e2e/pages/adf/process-services/processFiltersPage.ts index 70df30722b..d906393228 100644 --- a/e2e/pages/adf/process-services/processFiltersPage.ts +++ b/e2e/pages/adf/process-services/processFiltersPage.ts @@ -82,13 +82,13 @@ export class ProcessFiltersPage { } selectFromProcessList(title) { - let processName = element.all(by.css(`div[data-automation-id="text_${title}"]`)).first(); + const processName = element.all(by.css(`div[data-automation-id="text_${title}"]`)).first(); Util.waitUntilElementIsVisible(processName); processName.click(); } checkFilterIsHighlighted(filterName) { - let processNameHighlighted = element(by.css(`mat-list-item.adf-active span[data-automation-id='${filterName}_filter']`)); + const processNameHighlighted = element(by.css(`mat-list-item.adf-active span[data-automation-id='${filterName}_filter']`)); Util.waitUntilElementIsVisible(processNameHighlighted); } @@ -114,26 +114,26 @@ export class ProcessFiltersPage { } checkFilterIsDisplayed(name) { - let filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); + const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); return Util.waitUntilElementIsVisible(filterName); } checkFilterHasNoIcon(name) { - let filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); + const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); Util.waitUntilElementIsVisible(filterName); return Util.waitUntilElementIsNotOnPage(filterName.element(this.processIcon)); } getFilterIcon(name) { - let filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); + const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); Util.waitUntilElementIsVisible(filterName); - let icon = filterName.element(this.processIcon); + const icon = filterName.element(this.processIcon); Util.waitUntilElementIsVisible(icon); return icon.getText(); } checkFilterIsNotDisplayed(name) { - let filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); + const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); return Util.waitUntilElementIsNotVisible(filterName); } diff --git a/e2e/pages/adf/process-services/processServicesPage.ts b/e2e/pages/adf/process-services/processServicesPage.ts index 3187b6c732..97ad72b21b 100644 --- a/e2e/pages/adf/process-services/processServicesPage.ts +++ b/e2e/pages/adf/process-services/processServicesPage.ts @@ -32,7 +32,7 @@ export class ProcessServicesPage { } goToApp(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); Util.waitUntilElementIsVisible(app); app.click(); return new AppNavigationBarPage(); @@ -45,34 +45,34 @@ export class ProcessServicesPage { } getAppIconType(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); Util.waitUntilElementIsVisible(app); - let iconType = app.element(this.iconTypeLocator); + const iconType = app.element(this.iconTypeLocator); Util.waitUntilElementIsVisible(iconType); return iconType.getText(); } getBackgroundColor(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); Util.waitUntilElementIsVisible(app); return app.getCssValue('background-color'); } getDescription(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); Util.waitUntilElementIsVisible(app); - let description = app.element(this.descriptionLocator); + const description = app.element(this.descriptionLocator); Util.waitUntilElementIsVisible(description); return description.getText(); } checkAppIsNotDisplayed(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); return Util.waitUntilElementIsNotOnPage(app); } checkAppIsDisplayed(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); return Util.waitUntilElementIsVisible(app); } diff --git a/e2e/pages/adf/process-services/startProcessPage.ts b/e2e/pages/adf/process-services/startProcessPage.ts index cec499039a..366de7f580 100644 --- a/e2e/pages/adf/process-services/startProcessPage.ts +++ b/e2e/pages/adf/process-services/startProcessPage.ts @@ -82,20 +82,20 @@ export class StartProcessPage { } checkOptionIsDisplayed(name) { - let selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); + const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); Util.waitUntilElementIsVisible(selectProcessDropdown); Util.waitUntilElementIsClickable(selectProcessDropdown); return this; } checkOptionIsNotDisplayed(name) { - let selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); + const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); Util.waitUntilElementIsNotOnPage(selectProcessDropdown); return this; } selectOption(name) { - let selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); + const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); Util.waitUntilElementIsVisible(selectProcessDropdown); Util.waitUntilElementIsClickable(selectProcessDropdown); selectProcessDropdown.click(); @@ -140,7 +140,7 @@ export class StartProcessPage { checkSelectProcessPlaceholderIsDisplayed() { Util.waitUntilElementIsVisible(this.processDefinition); - let processPlaceholder = this.processDefinition.getAttribute('value').then(((result) => { + const processPlaceholder = this.processDefinition.getAttribute('value').then(((result) => { return result; })); return processPlaceholder; diff --git a/e2e/pages/adf/process-services/taskDetailsPage.ts b/e2e/pages/adf/process-services/taskDetailsPage.ts index 484c5c5e08..8e7fe2c2d4 100644 --- a/e2e/pages/adf/process-services/taskDetailsPage.ts +++ b/e2e/pages/adf/process-services/taskDetailsPage.ts @@ -104,7 +104,7 @@ export class TaskDetailsPage { } selectAttachFormOption(option) { - let selectedOption = element(by.cssContainingText('mat-option[role="option"]', option)); + const selectedOption = element(by.cssContainingText('mat-option[role="option"]', option)); Util.waitUntilElementIsClickable(selectedOption); return selectedOption.click(); } @@ -218,13 +218,13 @@ export class TaskDetailsPage { } selectActivityTab() { - let tabsPage = new TabsPage; + const tabsPage = new TabsPage; tabsPage.clickTabByTitle('Activity'); return this; } selectDetailsTab() { - let tabsPage = new TabsPage; + const tabsPage = new TabsPage; tabsPage.clickTabByTitle('Details'); return this; } @@ -243,7 +243,7 @@ export class TaskDetailsPage { } checkCommentIsDisplayed(comment) { - let row = element(by.cssContainingText('div[id="comment-message"]', comment)); + const row = element(by.cssContainingText('div[id="comment-message"]', comment)); Util.waitUntilElementIsVisible(row); return this; } @@ -268,7 +268,7 @@ export class TaskDetailsPage { } checkUserIsSelected(user) { - let row = element(by.cssContainingText('div[class*="search-list-container"] div[class*="people-full-name"]', user)); + const row = element(by.cssContainingText('div[class*="search-list-container"] div[class*="people-full-name"]', user)); Util.waitUntilElementIsVisible(row); return this; } @@ -281,13 +281,13 @@ export class TaskDetailsPage { } getRowsUser(user) { - let row = element(by.cssContainingText('div[class*="people-full-name"]', user)); + const row = element(by.cssContainingText('div[class*="people-full-name"]', user)); Util.waitUntilElementIsVisible(row); return row; } removeInvolvedUser(user) { - let row = this.getRowsUser(user).element(by.xpath('ancestor::div[contains(@class, "adf-datatable-row")]')); + const row = this.getRowsUser(user).element(by.xpath('ancestor::div[contains(@class, "adf-datatable-row")]')); Util.waitUntilElementIsVisible(row); row.element(by.css('button[data-automation-id="action_menu_0"]')).click(); Util.waitUntilElementIsVisible(this.removeInvolvedPeople); @@ -295,13 +295,13 @@ export class TaskDetailsPage { } getInvolvedUserEmail(user) { - let email = this.getRowsUser(user).element(this.emailInvolvedUser); + const email = this.getRowsUser(user).element(this.emailInvolvedUser); Util.waitUntilElementIsVisible(email); return email.getText(); } getInvolvedUserEditAction(user) { - let edit = this.getRowsUser(user).element(this.editActionInvolvedUser); + const edit = this.getRowsUser(user).element(this.editActionInvolvedUser); Util.waitUntilElementIsVisible(edit); return edit.getText(); } @@ -367,7 +367,7 @@ export class TaskDetailsPage { } getInvolvedPeopleInitialImage(user) { - let pic = this.getRowsUser(user).element(this.involvedUserPic); + const pic = this.getRowsUser(user).element(this.involvedUserPic); Util.waitUntilElementIsVisible(pic); return pic.getText(); } diff --git a/e2e/pages/adf/process-services/taskFiltersPage.ts b/e2e/pages/adf/process-services/taskFiltersPage.ts index df15e0392f..19e167d081 100644 --- a/e2e/pages/adf/process-services/taskFiltersPage.ts +++ b/e2e/pages/adf/process-services/taskFiltersPage.ts @@ -34,7 +34,7 @@ export class TaskFiltersPage { getTaskFilterIcon() { Util.waitUntilElementIsVisible(this.filter); - let icon = this.filter.element(this.taskIcon); + const icon = this.filter.element(this.taskIcon); Util.waitUntilElementIsVisible(icon); return icon.getText(); } diff --git a/e2e/pages/adf/process-services/tasksPage.ts b/e2e/pages/adf/process-services/tasksPage.ts index 8320319422..c03f26b289 100644 --- a/e2e/pages/adf/process-services/tasksPage.ts +++ b/e2e/pages/adf/process-services/tasksPage.ts @@ -91,13 +91,13 @@ export class TasksPage { } getRowsName(name) { - let row = element(this.checklistContainer).element(by.cssContainingText('span', name)); + const row = element(this.checklistContainer).element(by.cssContainingText('span', name)); Util.waitUntilElementIsVisible(row); return row; } getChecklistByName(checklist) { - let row = this.getRowsName(checklist).element(this.rowByRowName); + const row = this.getRowsName(checklist).element(this.rowByRowName); Util.waitUntilElementIsVisible(row); return row; } @@ -114,7 +114,7 @@ export class TasksPage { checkTaskTitle(taskName) { Util.waitUntilElementIsVisible(element(by.css(this.taskTitle))); - let title = element(by.cssContainingText(this.taskTitle, taskName)); + const title = element(by.cssContainingText(this.taskTitle, taskName)); Util.waitUntilElementIsVisible(title); return this; } @@ -150,14 +150,14 @@ export class TasksPage { } removeChecklists(checklist) { - let row = this.getRowsName(checklist).element(this.rowByRowName); + const row = this.getRowsName(checklist).element(this.rowByRowName); Util.waitUntilElementIsVisible(row.element(by.css('mat-icon'))); row.element(by.css('mat-icon')).click(); return this; } checkChecklistsRemoveButtonIsNotDisplayed(checklist) { - let row = this.getRowsName(checklist).element(this.rowByRowName); + const row = this.getRowsName(checklist).element(this.rowByRowName); Util.waitUntilElementIsNotOnPage(row.element(by.css('mat-icon'))); return this; } diff --git a/e2e/pages/adf/process-services/widgets/amountWidget.ts b/e2e/pages/adf/process-services/widgets/amountWidget.ts index 9bec558abb..10813288df 100644 --- a/e2e/pages/adf/process-services/widgets/amountWidget.ts +++ b/e2e/pages/adf/process-services/widgets/amountWidget.ts @@ -25,7 +25,7 @@ export class AmountWidget { formFields = new FormFields(); getAmountFieldLabel(fieldId) { - let label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); + const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); Util.waitUntilElementIsVisible(label); return label.getText(); } @@ -41,7 +41,7 @@ export class AmountWidget { removeFromAmountWidget(fieldId) { Util.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); - let amountWidgetInput = element(by.id(fieldId)); + const amountWidgetInput = element(by.id(fieldId)); amountWidgetInput.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { amountWidgetInput.sendKeys(protractor.Key.BACK_SPACE); @@ -50,7 +50,7 @@ export class AmountWidget { } clearFieldValue(fieldId) { - let numberField = element(by.id(fieldId)); + const numberField = element(by.id(fieldId)); Util.waitUntilElementIsVisible(numberField); return numberField.clear(); } @@ -60,7 +60,7 @@ export class AmountWidget { } getErrorMessage(fieldId) { - let errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); + const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); Util.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } diff --git a/e2e/pages/adf/process-services/widgets/attachFileWidget.ts b/e2e/pages/adf/process-services/widgets/attachFileWidget.ts index c7e46cfbd8..5d54828c1a 100644 --- a/e2e/pages/adf/process-services/widgets/attachFileWidget.ts +++ b/e2e/pages/adf/process-services/widgets/attachFileWidget.ts @@ -31,8 +31,8 @@ export class AttachFileWidget { attachFile(fieldId, fileLocation) { browser.setFileDetector(new remote.FileDetector()); - let widget = this.formFields.getWidget(fieldId); - let uploadButton = widget.element(this.uploadLocator); + const widget = this.formFields.getWidget(fieldId); + const uploadButton = widget.element(this.uploadLocator); Util.waitUntilElementIsVisible(uploadButton); uploadButton.click(); @@ -42,14 +42,14 @@ export class AttachFileWidget { } checkFileIsAttached(fieldId, name) { - let widget = this.formFields.getWidget(fieldId); - let fileAttached = widget.element(this.filesListLocator).element(by.cssContainingText('mat-list-item span ', name)); + const widget = this.formFields.getWidget(fieldId); + const fileAttached = widget.element(this.filesListLocator).element(by.cssContainingText('mat-list-item span ', name)); Util.waitUntilElementIsVisible(fileAttached); return this; } viewFile(name) { - let fileView = element(this.filesListLocator).element(by.cssContainingText('mat-list-item span ', name)); + const fileView = element(this.filesListLocator).element(by.cssContainingText('mat-list-item span ', name)); Util.waitUntilElementIsVisible(fileView); fileView.click(); browser.actions().doubleClick(fileView).perform(); diff --git a/e2e/pages/adf/process-services/widgets/checkboxWidget.ts b/e2e/pages/adf/process-services/widgets/checkboxWidget.ts index 96af442851..7f5c8889a6 100644 --- a/e2e/pages/adf/process-services/widgets/checkboxWidget.ts +++ b/e2e/pages/adf/process-services/widgets/checkboxWidget.ts @@ -31,7 +31,7 @@ export class CheckboxWidget { } clickCheckboxInput(fieldId) { - let checkboxInput = element.all(by.css(`mat-checkbox[id="${fieldId}"] div`)).first(); + const checkboxInput = element.all(by.css(`mat-checkbox[id="${fieldId}"] div`)).first(); Util.waitUntilElementIsVisible(checkboxInput); return checkboxInput.click(); } diff --git a/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts b/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts index 4b1fd2cf51..f4241e6d6d 100644 --- a/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts @@ -33,7 +33,7 @@ export class DateTimeWidget { } getDateTimeLabel(fieldId) { - let label = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)); + const label = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)); Util.waitUntilElementIsVisible(label); return label.getText(); } @@ -43,13 +43,13 @@ export class DateTimeWidget { } clearDateTimeInput(fieldId) { - let dateInput = element(by.id(fieldId)); + const dateInput = element(by.id(fieldId)); Util.waitUntilElementIsVisible(dateInput); return dateInput.clear(); } clickOutsideWidget(fieldId) { - let form = this.formFields.getWidget(fieldId); + const form = this.formFields.getWidget(fieldId); Util.waitUntilElementIsVisible(form); return form.click(); } @@ -60,13 +60,13 @@ export class DateTimeWidget { } getErrorMessage(fieldId) { - let errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); + const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); Util.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } selectDay(day) { - let selectedDay = element(by.cssContainingText('div[class*="mat-datetimepicker-calendar-body-cell-content"]', day)); + const selectedDay = element(by.cssContainingText('div[class*="mat-datetimepicker-calendar-body-cell-content"]', day)); Util.waitUntilElementIsVisible(selectedDay); return selectedDay.click(); } @@ -76,7 +76,7 @@ export class DateTimeWidget { } private selectTime(time) { - let selectedTime = element(by.cssContainingText('div[class*="mat-datetimepicker-clock-cell"]', time)); + const selectedTime = element(by.cssContainingText('div[class*="mat-datetimepicker-clock-cell"]', time)); Util.waitUntilElementIsClickable(selectedTime); return selectedTime.click(); } @@ -96,7 +96,7 @@ export class DateTimeWidget { removeFromDatetimeWidget(fieldId) { Util.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); - let amountWidgetInput = element(by.id(fieldId)); + const amountWidgetInput = element(by.id(fieldId)); amountWidgetInput.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { amountWidgetInput.sendKeys(protractor.Key.BACK_SPACE); diff --git a/e2e/pages/adf/process-services/widgets/dateWidget.ts b/e2e/pages/adf/process-services/widgets/dateWidget.ts index 36274d0c19..c72c2db5d2 100644 --- a/e2e/pages/adf/process-services/widgets/dateWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dateWidget.ts @@ -32,7 +32,7 @@ export class DateWidget { } getDateLabel(fieldId) { - let label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); + const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); Util.waitUntilElementIsVisible(label); return label.getText(); } @@ -43,19 +43,19 @@ export class DateWidget { } clearDateInput(fieldId) { - let dateInput = element(by.id(fieldId)); + const dateInput = element(by.id(fieldId)); Util.waitUntilElementIsVisible(dateInput); return dateInput.clear(); } clickOutsideWidget(fieldId) { - let form = this.formFields.getWidget(fieldId); + const form = this.formFields.getWidget(fieldId); Util.waitUntilElementIsVisible(form); return form.click(); } getErrorMessage(fieldId) { - let errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); + const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); Util.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } @@ -63,7 +63,7 @@ export class DateWidget { removeFromDatetimeWidget(fieldId) { Util.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); - let dateWidgetInput = element(by.id(fieldId)); + const dateWidgetInput = element(by.id(fieldId)); dateWidgetInput.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { dateWidgetInput.sendKeys(protractor.Key.BACK_SPACE); diff --git a/e2e/pages/adf/process-services/widgets/dropdownWidget.ts b/e2e/pages/adf/process-services/widgets/dropdownWidget.ts index 9f57bd75d4..500572179f 100644 --- a/e2e/pages/adf/process-services/widgets/dropdownWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dropdownWidget.ts @@ -32,7 +32,7 @@ export class DropdownWidget { selectOption(option) { this.openDropdown(); - let row = element(by.cssContainingText('mat-option span', option)); + const row = element(by.cssContainingText('mat-option span', option)); return row.click(); } diff --git a/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts b/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts index 31fe69f206..0369bb98a7 100644 --- a/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts @@ -58,7 +58,7 @@ export class DynamicTableWidget { } clickTableRow(rowNumber) { - let tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); + const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); Util.waitUntilElementIsVisible(tableRowByIndex); return tableRowByIndex.click(); } @@ -80,18 +80,18 @@ export class DynamicTableWidget { } getTableRowText(rowNumber) { - let tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); + const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); Util.waitUntilElementIsVisible(tableRowByIndex); return tableRowByIndex.getText(); } checkTableRowIsVisible(rowNumber) { - let tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); + const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); return Util.waitUntilElementIsVisible(tableRowByIndex); } checkTableRowIsNotVisible(rowNumber) { - let tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); + const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); return Util.waitUntilElementIsNotVisible(tableRowByIndex); } @@ -138,8 +138,8 @@ export class DynamicTableWidget { } checkItemIsPresent(item) { - let row = element(by.cssContainingText('table tbody tr td span', item)); - let present = Util.waitUntilElementIsVisible(row); + const row = element(by.cssContainingText('table tbody tr td span', item)); + const present = Util.waitUntilElementIsVisible(row); expect(present).toBe(true); } } diff --git a/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts b/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts index bea2fa4c67..6f3ef56ddf 100644 --- a/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts +++ b/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts @@ -30,7 +30,7 @@ export class HyperlinkWidget { } getFieldLabel(fieldId) { - let label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); + const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); Util.waitUntilElementIsVisible(label); return label.getText(); } diff --git a/e2e/pages/adf/process-services/widgets/numberWidget.ts b/e2e/pages/adf/process-services/widgets/numberWidget.ts index 95f25b8ac4..dcf46b570d 100644 --- a/e2e/pages/adf/process-services/widgets/numberWidget.ts +++ b/e2e/pages/adf/process-services/widgets/numberWidget.ts @@ -24,7 +24,7 @@ export class NumberWidget { formFields = new FormFields(); getNumberFieldLabel(fieldId) { - let label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); + const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); Util.waitUntilElementIsVisible(label); return label.getText(); } @@ -34,7 +34,7 @@ export class NumberWidget { } clearFieldValue(fieldId) { - let numberField = element(by.id(fieldId)); + const numberField = element(by.id(fieldId)); Util.waitUntilElementIsVisible(numberField); return numberField.clear(); } @@ -44,7 +44,7 @@ export class NumberWidget { } getErrorMessage(fieldId) { - let errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); + const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); Util.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } diff --git a/e2e/pages/adf/process-services/widgets/peopleWidget.ts b/e2e/pages/adf/process-services/widgets/peopleWidget.ts index 32e978187a..78fa36aba4 100644 --- a/e2e/pages/adf/process-services/widgets/peopleWidget.ts +++ b/e2e/pages/adf/process-services/widgets/peopleWidget.ts @@ -52,17 +52,17 @@ export class PeopleWidget { } checkUserIsListed(userName) { - let user = element(by.cssContainingText('.adf-people-label-name', userName)); + const user = element(by.cssContainingText('.adf-people-label-name', userName)); return Util.waitUntilElementIsVisible(user); } checkUserNotListed(userName) { - let user = element(by.xpath('div[text()="' + userName + '"]')); + const user = element(by.xpath('div[text()="' + userName + '"]')); return Util.waitUntilElementIsNotVisible(user); } selectUserFromDropDown(userName) { - let user = element(by.cssContainingText('.adf-people-label-name', userName)); + const user = element(by.cssContainingText('.adf-people-label-name', userName)); user.click(); return this; } diff --git a/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts b/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts index cac2552117..317c28777e 100644 --- a/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts +++ b/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts @@ -26,28 +26,28 @@ export class RadioButtonsWidget { formFields = new FormFields(); getSpecificOptionLabel(fieldId, optionNumber) { - let optionLocator = by.css('label[for*="radiobuttons-option_' + optionNumber + '"]'); + const optionLocator = by.css('label[for*="radiobuttons-option_' + optionNumber + '"]'); - let option = this.formFields.getWidget(fieldId).element(optionLocator); + const option = this.formFields.getWidget(fieldId).element(optionLocator); Util.waitUntilElementIsVisible(option); return option.getText(); } selectOption(fieldId, optionNumber) { - let optionLocator = by.css(`label[for*="${fieldId}-option_${optionNumber}"]`); + const optionLocator = by.css(`label[for*="${fieldId}-option_${optionNumber}"]`); - let option = this.formFields.getWidget(fieldId).element(optionLocator); + const option = this.formFields.getWidget(fieldId).element(optionLocator); Util.waitUntilElementIsVisible(option); return option.click(); } isSelectionClean(fieldId) { - let option = this.formFields.getWidget(fieldId).element(this.selectedOption); + const option = this.formFields.getWidget(fieldId).element(this.selectedOption); return Util.waitUntilElementIsNotVisible(option); } getRadioWidgetLabel(fieldId) { - let label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); + const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); Util.waitUntilElementIsVisible(label); return label.getText(); } diff --git a/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts b/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts index f4e1c680a4..2df7b06424 100644 --- a/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts +++ b/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts @@ -43,7 +43,7 @@ export class EditTaskFilterCloudComponent { setStateFilterDropDown(option) { this.clickOnDropDownArrow('status'); - let stateElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const stateElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(stateElement); Util.waitUntilElementIsVisible(stateElement); stateElement.click(); @@ -57,7 +57,7 @@ export class EditTaskFilterCloudComponent { setSortFilterDropDown(option) { this.clickOnDropDownArrow('sort'); - let sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(sortElement); Util.waitUntilElementIsVisible(sortElement); sortElement.click(); @@ -71,7 +71,7 @@ export class EditTaskFilterCloudComponent { setOrderFilterDropDown(option) { this.clickOnDropDownArrow('order'); - let orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); + const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); Util.waitUntilElementIsClickable(orderElement); Util.waitUntilElementIsVisible(orderElement); orderElement.click(); @@ -83,7 +83,7 @@ export class EditTaskFilterCloudComponent { } clickOnDropDownArrow(option) { - let dropDownArrow = element(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")); + const dropDownArrow = element(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")); Util.waitUntilElementIsVisible(dropDownArrow); dropDownArrow.click(); Util.waitUntilElementIsVisible(this.selectedOption); diff --git a/e2e/pages/adf/searchResultsPage.ts b/e2e/pages/adf/searchResultsPage.ts index 35c10a7b8b..902fb94daf 100644 --- a/e2e/pages/adf/searchResultsPage.ts +++ b/e2e/pages/adf/searchResultsPage.ts @@ -37,7 +37,7 @@ export class SearchResultsPage { } closeActionButton() { - let container = element(by.css('div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing')); + const container = element(by.css('div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing')); Util.waitUntilElementIsVisible(container); container.click(); Util.waitUntilElementIsNotVisible(container); @@ -100,32 +100,32 @@ export class SearchResultsPage { } async checkListIsOrderedByNameAsc() { - let list = await this.contentServices.getElementsDisplayedName(); + const list = await this.contentServices.getElementsDisplayedName(); return this.contentServices.checkElementsSortedAsc(list); } async checkListIsOrderedByNameDesc() { - let list = await this.contentServices.getElementsDisplayedName(); + const list = await this.contentServices.getElementsDisplayedName(); return this.contentServices.checkElementsSortedDesc(list); } async checkListIsOrderedByAuthorAsc() { - let authorList = await this.dataTable.geCellElementDetail('Created by'); + const authorList = await this.dataTable.geCellElementDetail('Created by'); return this.contentServices.checkElementsSortedAsc(authorList); } async checkListIsOrderedByAuthorDesc() { - let authorList = await this.dataTable.geCellElementDetail('Created by'); + const authorList = await this.dataTable.geCellElementDetail('Created by'); return this.contentServices.checkElementsSortedDesc(authorList); } async checkListIsOrderedBySizeAsc() { - let list = await this.contentServices.getElementsDisplayedSize(); + const list = await this.contentServices.getElementsDisplayedSize(); return this.contentServices.checkElementsSortedAsc(list); } async checkListIsOrderedBySizeDesc() { - let list = await this.contentServices.getElementsDisplayedSize(); + const list = await this.contentServices.getElementsDisplayedSize(); return this.contentServices.checkElementsSortedDesc(list); } diff --git a/e2e/pages/adf/tagPage.ts b/e2e/pages/adf/tagPage.ts index 1cbdf0453b..1bd740a4bb 100644 --- a/e2e/pages/adf/tagPage.ts +++ b/e2e/pages/adf/tagPage.ts @@ -65,14 +65,14 @@ export class TagPage { } deleteTagFromTagListByNodeId(name) { - let deleteChip = element(by.id('tag_chips_delete_' + name)); + const deleteChip = element(by.id('tag_chips_delete_' + name)); Util.waitUntilElementIsVisible(deleteChip); deleteChip.click(); return this; } deleteTagFromTagList(name) { - let deleteChip = element(by.id('tag_chips_delete_' + name)); + const deleteChip = element(by.id('tag_chips_delete_' + name)); Util.waitUntilElementIsVisible(deleteChip); deleteChip.click(); return this; @@ -94,22 +94,22 @@ export class TagPage { } checkTagIsDisplayedInTagList(tagName) { - let tag = element(by.cssContainingText('div[id*="tag_name"]', tagName)); + const tag = element(by.cssContainingText('div[id*="tag_name"]', tagName)); return Util.waitUntilElementIsVisible(tag); } checkTagIsNotDisplayedInTagList(tagName) { - let tag = element(by.cssContainingText('div[id*="tag_name"]', tagName)); + const tag = element(by.cssContainingText('div[id*="tag_name"]', tagName)); return Util.waitUntilElementIsNotOnPage(tag); } checkTagIsNotDisplayedInTagListByNodeId(tagName) { - let tag = element(by.cssContainingText('span[id*="tag_name"]', tagName)); + const tag = element(by.cssContainingText('span[id*="tag_name"]', tagName)); return Util.waitUntilElementIsNotOnPage(tag); } checkTagIsDisplayedInTagListByNodeId(tagName) { - let tag = element(by.cssContainingText('span[id*="tag_name"]', tagName)); + const tag = element(by.cssContainingText('span[id*="tag_name"]', tagName)); return Util.waitUntilElementIsVisible(tag); } @@ -122,7 +122,7 @@ export class TagPage { } checkTagIsDisplayedInTagListContentServices(tagName) { - let tag = element(by.cssContainingText('div[class="adf-list-tag"][id*="tag_name"]', tagName)); + const tag = element(by.cssContainingText('div[class="adf-list-tag"][id*="tag_name"]', tagName)); return Util.waitUntilElementIsVisible(tag); } @@ -132,7 +132,7 @@ export class TagPage { } checkTagListIsOrderedAscending() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.checkListIsSorted(false, this.tagListRowLocator).then((result) => { deferred.fulfill(result); }); @@ -140,7 +140,7 @@ export class TagPage { } checkTagListByNodeIdIsOrderedAscending() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.checkListIsSorted(false, this.tagListByNodeIdRowLocator).then((result) => { deferred.fulfill(result); }); @@ -148,7 +148,7 @@ export class TagPage { } checkTagListContentServicesIsOrderedAscending() { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); this.checkListIsSorted(false, this.tagListContentServicesRowLocator).then((result) => { deferred.fulfill(result); }); @@ -156,10 +156,10 @@ export class TagPage { } checkListIsSorted(sortOrder, locator) { - let deferred = protractor.promise.defer(); - let tagList = element.all(locator); + const deferred = protractor.promise.defer(); + const tagList = element.all(locator); Util.waitUntilElementIsVisible(tagList.first()); - let initialList = []; + const initialList = []; tagList.each(function (currentElement) { currentElement.getText().then(function (text) { initialList.push(text); @@ -176,12 +176,12 @@ export class TagPage { } checkDeleteTagFromTagListByNodeIdIsDisplayed(name) { - let deleteChip = element(by.id('tag_chips_delete_' + name)); + const deleteChip = element(by.id('tag_chips_delete_' + name)); return Util.waitUntilElementIsVisible(deleteChip); } checkDeleteTagFromTagListByNodeIdIsNotDisplayed(name) { - let deleteChip = element(by.id('tag_chips_delete_' + name)); + const deleteChip = element(by.id('tag_chips_delete_' + name)); return Util.waitUntilElementIsNotVisible(deleteChip); } diff --git a/e2e/pages/adf/versionManagerPage.ts b/e2e/pages/adf/versionManagerPage.ts index 6b70c98a2f..6bd2c87e3f 100644 --- a/e2e/pages/adf/versionManagerPage.ts +++ b/e2e/pages/adf/versionManagerPage.ts @@ -77,29 +77,29 @@ export class VersionManagePage { } getFileVersionName(version) { - let fileElement = element(by.css(`[id="adf-version-list-item-name-${version}"]`)); + const fileElement = element(by.css(`[id="adf-version-list-item-name-${version}"]`)); Util.waitUntilElementIsVisible(fileElement); return fileElement.getText(); } checkFileVersionExist(version) { - let fileVersion = element(by.id(`adf-version-list-item-version-${version}`)); + const fileVersion = element(by.id(`adf-version-list-item-version-${version}`)); return Util.waitUntilElementIsVisible(fileVersion); } checkFileVersionNotExist(version) { - let fileVersion = element(by.id(`adf-version-list-item-version-${version}`)); + const fileVersion = element(by.id(`adf-version-list-item-version-${version}`)); return Util.waitUntilElementIsNotVisible(fileVersion); } getFileVersionComment(version) { - let fileComment = element(by.id(`adf-version-list-item-comment-${version}`)); + const fileComment = element(by.id(`adf-version-list-item-comment-${version}`)); Util.waitUntilElementIsVisible(fileComment); return fileComment.getText(); } getFileVersionDate(version) { - let fileDate = element(by.id(`adf-version-list-item-date-${version}`)); + const fileDate = element(by.id(`adf-version-list-item-date-${version}`)); Util.waitUntilElementIsVisible(fileDate); return fileDate.getText(); } @@ -113,13 +113,13 @@ export class VersionManagePage { } clickMajorChange() { - let radioMajor = element(by.id(`adf-new-version-major`)); + const radioMajor = element(by.id(`adf-new-version-major`)); Util.waitUntilElementIsVisible(radioMajor); radioMajor.click(); } clickMinorChange() { - let radioMinor = element(by.id(`adf-new-version-minor`)); + const radioMinor = element(by.id(`adf-new-version-minor`)); Util.waitUntilElementIsVisible(radioMinor); radioMinor.click(); } @@ -186,7 +186,7 @@ export class VersionManagePage { } closeActionButton() { - let container = element(by.css('div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing')); + const container = element(by.css('div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing')); Util.waitUntilElementIsVisible(container); container.click(); Util.waitUntilElementIsNotVisible(container); @@ -195,7 +195,7 @@ export class VersionManagePage { downloadFileVersion(version) { this.clickActionButton(version); - let downloadButton = element(by.id(`adf-version-list-action-download-${version}`)); + const downloadButton = element(by.id(`adf-version-list-action-download-${version}`)); Util.waitUntilElementIsVisible(downloadButton); browser.driver.sleep(500); downloadButton.click(); @@ -204,7 +204,7 @@ export class VersionManagePage { deleteFileVersion(version) { this.clickActionButton(version); - let deleteButton = element(by.id(`adf-version-list-action-delete-${version}`)); + const deleteButton = element(by.id(`adf-version-list-action-delete-${version}`)); Util.waitUntilElementIsVisible(deleteButton); browser.driver.sleep(500); deleteButton.click(); @@ -213,7 +213,7 @@ export class VersionManagePage { restoreFileVersion(version) { this.clickActionButton(version); - let restoreButton = element(by.id(`adf-version-list-action-restore-${version}`)); + const restoreButton = element(by.id(`adf-version-list-action-restore-${version}`)); Util.waitUntilElementIsVisible(restoreButton); browser.driver.sleep(500); restoreButton.click(); diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index 0d6798079c..51361a5bad 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -103,7 +103,7 @@ export class ViewerPage { } viewFile(fileName) { - let fileView = element.all(by.css(`#document-list-container div[filename="${fileName}"]`)).first(); + const fileView = element.all(by.css(`#document-list-container div[filename="${fileName}"]`)).first(); Util.waitUntilElementIsVisible(fileView); fileView.click(); browser.actions().sendKeys(protractor.Key.ENTER).perform(); @@ -120,7 +120,7 @@ export class ViewerPage { } exitFullScreen() { - let jsCode = 'document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen&&document.webkitExitFullscreen();'; + const jsCode = 'document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen&&document.webkitExitFullscreen();'; browser.executeScript(jsCode); } @@ -155,12 +155,12 @@ export class ViewerPage { } checkAllThumbnailsDisplayed(nbPages) { - let defaultThumbnailHeight = 143; + const defaultThumbnailHeight = 143; expect(this.thumbnailsContent.getAttribute('style')).toEqual('height: ' + nbPages * defaultThumbnailHeight + 'px; transform: translate(-50%, 0px);'); } checkCurrentThumbnailIsSelected() { - let selectedThumbnail = element(by.css('adf-pdf-thumb[class="adf-pdf-thumbnails__thumb ng-star-inserted adf-pdf-thumbnails__thumb--selected"] > img')); + const selectedThumbnail = element(by.css('adf-pdf-thumb[class="adf-pdf-thumbnails__thumb ng-star-inserted adf-pdf-thumbnails__thumb--selected"] > img')); this.pageSelectorInput.getAttribute('value').then((pageNumber) => { browser.controlFlow().execute(async () => { expect('Page ' + pageNumber).toEqual(await selectedThumbnail.getAttribute('title')); @@ -262,10 +262,10 @@ export class ViewerPage { } checkFileContent(pageNumber, text) { - let allPages = element.all(by.css('div[class="canvasWrapper"] > canvas')).first(); - let pageLoaded = element.all(by.css('div[data-page-number="' + pageNumber + '"][data-loaded="true"]')).first(); - let textLayerLoaded = element.all(by.css('div[data-page-number="' + pageNumber + '"] div[class="textLayer"] > div')).first(); - let specificText = element.all(by.cssContainingText('div[data-page-number="' + pageNumber + '"] div[class="textLayer"] > div', text)).first(); + const allPages = element.all(by.css('div[class="canvasWrapper"] > canvas')).first(); + const pageLoaded = element.all(by.css('div[data-page-number="' + pageNumber + '"][data-loaded="true"]')).first(); + const textLayerLoaded = element.all(by.css('div[data-page-number="' + pageNumber + '"] div[class="textLayer"] > div')).first(); + const specificText = element.all(by.cssContainingText('div[data-page-number="' + pageNumber + '"] div[class="textLayer"] > div', text)).first(); Util.waitUntilElementIsVisible(allPages); Util.waitUntilElementIsVisible(pageLoaded); @@ -306,7 +306,7 @@ export class ViewerPage { } checkRotation(text) { - let rotation = this.imgContainer.getAttribute('style'); + const rotation = this.imgContainer.getAttribute('style'); expect(rotation).toEqual(text); } @@ -337,7 +337,7 @@ export class ViewerPage { } checkTabIsActive(tabName) { - let tab = element(by.cssContainingText('.adf-info-drawer-layout-content div.mat-tab-labels div.mat-tab-label-active .mat-tab-label-content', tabName)); + const tab = element(by.cssContainingText('.adf-info-drawer-layout-content div.mat-tab-labels div.mat-tab-label-active .mat-tab-label-content', tabName)); Util.waitUntilElementIsVisible(tab); return this; } diff --git a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts index f87cdc78c5..5f123bd4c4 100644 --- a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts @@ -31,9 +31,9 @@ describe('Edit process filters cloud', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); - let processCloudDemoPage = new ProcessCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); let silentLogin; const simpleApp = 'simple-app'; diff --git a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts index efcf177f36..68fe1fc39f 100644 --- a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts @@ -33,8 +33,8 @@ describe('Edit task filters cloud', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); const tasksService: Tasks = new Tasks(); let silentLogin; diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index ae48e12fc0..0a8eee4a8f 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -38,9 +38,9 @@ describe('Process list cloud', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let processCloudDemoPage = new ProcessCloudDemoPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); const tasksService: Tasks = new Tasks(); const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); @@ -70,7 +70,7 @@ describe('Process list cloud', () => { configEditorPage.clickSaveButton(); await processDefinitionService.init(user, password); - let processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); await processInstancesService.init(user, password); await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); runningProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); @@ -78,9 +78,9 @@ describe('Process list cloud', () => { completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); await queryService.init(user, password); - let task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); + const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); await tasksService.init(user, password); - let claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); + const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); await tasksService.completeTask(claimedTask.entry.id, simpleApp); }); @@ -97,14 +97,14 @@ describe('Process list cloud', () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('RUNNING') .setSortFilterDropDown('Name').setOrderFilterDropDown('ASC'); processCloudDemoPage.processListCloudComponent().getAllRowsNameColumn().then(function (list) { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(); expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); }); processCloudDemoPage.editProcessFilterCloudComponent().setOrderFilterDropDown('DESC'); processCloudDemoPage.processListCloudComponent().getAllRowsNameColumn().then(function (list) { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(); list.reverse(); expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); @@ -116,7 +116,7 @@ describe('Process list cloud', () => { .setSortFilterDropDown('Id').setOrderFilterDropDown('ASC'); processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); processCloudDemoPage.getAllRowsByIdColumn().then(function (list) { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(function (firstStr, secondStr) { return firstStr.localeCompare(secondStr); }); @@ -126,7 +126,7 @@ describe('Process list cloud', () => { processCloudDemoPage.editProcessFilterCloudComponent().setOrderFilterDropDown('DESC'); processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); processCloudDemoPage.getAllRowsByIdColumn().then(function (list) { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(function (firstStr, secondStr) { return firstStr.localeCompare(secondStr); }); diff --git a/e2e/process-services-cloud/process-filters-cloud.e2e.ts b/e2e/process-services-cloud/process-filters-cloud.e2e.ts index e9c6731cd4..8360e86f7b 100644 --- a/e2e/process-services-cloud/process-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-filters-cloud.e2e.ts @@ -36,9 +36,9 @@ describe('Process filters cloud', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let processCloudDemoPage = new ProcessCloudDemoPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); const tasksService: Tasks = new Tasks(); const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); @@ -58,15 +58,15 @@ describe('Process filters cloud', () => { loginSSOPage.loginSSOIdentityService(user, password); await processDefinitionService.init(user, password); - let processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); await processInstancesService.init(user, password); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); await queryService.init(user, password); - let task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); + const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); await tasksService.init(user, password); - let claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); + const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); await tasksService.completeTask(claimedTask.entry.id, simpleApp); }); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index 763f945a5c..b733379589 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -35,8 +35,8 @@ describe('Process list cloud', () => { const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); const configEditor = new ConfigEditorPage(); - let appListCloudComponent = new AppListCloudPage(); - let processCloudDemoPage = new ProcessCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); const processInstancesService: ProcessInstances = new ProcessInstances(); @@ -55,14 +55,14 @@ describe('Process list cloud', () => { loginSSOPage.loginSSOIdentityService(user, password); await processDefinitionService.init(user, password); - let processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); await processInstancesService.init(user, password); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); }); beforeEach(async (done) => { - let processListCloudConfiguration = new ProcessListCloudConfiguration(); + const processListCloudConfiguration = new ProcessListCloudConfiguration(); jsonFile = processListCloudConfiguration.getConfiguration(); done(); navigationBarPage.clickConfigEditorButton(); diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 388f0bdea5..84a232ced4 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -156,7 +156,7 @@ describe('Start Task', () => { .setStatusFilterDropDown('CREATED'); tasksCloudDemoPage.taskListCloudComponent().getDataTable().waitForTableBody(); tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(unassignedTaskName); - let taskId = tasksCloudDemoPage.taskListCloudComponent().getIdCellValue(unassignedTaskName); + const taskId = tasksCloudDemoPage.taskListCloudComponent().getIdCellValue(unassignedTaskName); tasksCloudDemoPage.taskListCloudComponent().selectRow(unassignedTaskName); expect(taskHeaderCloudPage.getTaskDetailsHeader()).toContain(taskId); expect(taskHeaderCloudPage.getAssignee()).toBe('No assignee'); diff --git a/e2e/process-services-cloud/task-details-cloud.e2e.ts b/e2e/process-services-cloud/task-details-cloud.e2e.ts index ec6f5a5b4f..e9168e2382 100644 --- a/e2e/process-services-cloud/task-details-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-details-cloud.e2e.ts @@ -33,12 +33,12 @@ import { browser } from 'protractor'; describe('Task Header cloud component', () => { const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - let basicCreatedTaskName = Util.generateRandomString(), completedTaskName = Util.generateRandomString(); + const basicCreatedTaskName = Util.generateRandomString(), completedTaskName = Util.generateRandomString(); let basicCreatedTask, basicCreatedDate, completedTask, completedCreatedDate, subTask, subTaskCreatedDate; const simpleApp = 'simple-app'; - let priority = 30, description = 'descriptionTask', formatDate = 'MMM DD YYYY'; + const priority = 30, description = 'descriptionTask', formatDate = 'MMM DD YYYY'; - let taskHeaderCloudPage = new TaskHeaderCloudPage(); + const taskHeaderCloudPage = new TaskHeaderCloudPage(); const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); @@ -57,19 +57,19 @@ describe('Task Header cloud component', () => { loginSSOPage.loginSSOIdentityService(user, password); await tasksService.init(user, password); - let createdTaskId = await tasksService.createStandaloneTask(basicCreatedTaskName, simpleApp); + const createdTaskId = await tasksService.createStandaloneTask(basicCreatedTaskName, simpleApp); await tasksService.claimTask(createdTaskId.entry.id, simpleApp); basicCreatedTask = await tasksService.getTask(createdTaskId.entry.id, simpleApp); basicCreatedDate = moment(basicCreatedTask.entry.createdDate).format(formatDate); - let completedTaskId = await tasksService.createStandaloneTask(completedTaskName, + const completedTaskId = await tasksService.createStandaloneTask(completedTaskName, simpleApp, {priority: priority, description: description, dueDate: basicCreatedTask.entry.createdDate}); await tasksService.claimTask(completedTaskId.entry.id, simpleApp); await tasksService.completeTask(completedTaskId.entry.id, simpleApp); completedTask = await tasksService.getTask(completedTaskId.entry.id, simpleApp); completedCreatedDate = moment(completedTask.entry.createdDate).format(formatDate); - let subTaskId = await tasksService.createStandaloneSubtask(createdTaskId.entry.id, simpleApp, Util.generateRandomString()); + const subTaskId = await tasksService.createStandaloneSubtask(createdTaskId.entry.id, simpleApp, Util.generateRandomString()); await tasksService.claimTask(subTaskId.entry.id, simpleApp); subTask = await tasksService.getTask(subTaskId.entry.id, simpleApp); subTaskCreatedDate = moment(subTask.entry.createdDate).format(formatDate); diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index 78f02c74f8..304c2d0a87 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -32,8 +32,8 @@ describe('Task filters cloud', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); const tasksService: Tasks = new Tasks(); const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; @@ -63,7 +63,7 @@ describe('Task filters cloud', () => { it('[C290009] Should display default filters and created task', async () => { await tasksService.init(user, password); - let task = await tasksService.createStandaloneTask(newTask, simpleApp); + const task = await tasksService.createStandaloneTask(newTask, simpleApp); await tasksService.claimTask(task.entry.id, simpleApp); tasksCloudDemoPage.completedTasksFilter().clickTaskFilter(); @@ -78,7 +78,7 @@ describe('Task filters cloud', () => { it('[C289955] Should display task in Complete Tasks List when task is completed', async () => { await tasksService.init(user, password); - let task = await tasksService.createStandaloneTask(completedTask, simpleApp); + const task = await tasksService.createStandaloneTask(completedTask, simpleApp); await tasksService.claimTask(task.entry.id, simpleApp); await tasksService.completeTask(task.entry.id, simpleApp); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index 3428bc06b7..cd73ae7cfc 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -42,29 +42,29 @@ describe('Edit task filters and task list properties', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); const tasksService: Tasks = new Tasks(); const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); const processInstancesService: ProcessInstances = new ProcessInstances(); - let notificationPage = new NotificationPage(); + const notificationPage = new NotificationPage(); let silentLogin; const simpleApp = 'simple-app'; const candidateUserApp = 'candidateuserapp'; - let noTasksFoundMessage = 'No Tasks Found'; + const noTasksFoundMessage = 'No Tasks Found'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let createdTask, notAssigned, notDisplayedTask, processDefinition, processInstance, priorityTask, subTask; - let priority = 30; + const priority = 30; - let beforeDate = moment().add(-1, 'days').format('DD/MM/YYYY'); - let currentDate = DateUtil.formatDate('DD/MM/YYYY'); - let afterDate = moment().add(1, 'days').format('DD/MM/YYYY'); + const beforeDate = moment().add(-1, 'days').format('DD/MM/YYYY'); + const currentDate = DateUtil.formatDate('DD/MM/YYYY'); + const afterDate = moment().add(1, 'days').format('DD/MM/YYYY'); beforeAll(async (done) => { silentLogin = false; - let jsonFile = new TaskListCloudConfiguration().getConfiguration(); + const jsonFile = new TaskListCloudConfiguration().getConfiguration(); settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); browser.ignoreSynchronization = true; diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index 7d184a9b84..b2c9c14af9 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -32,16 +32,17 @@ describe('Task list cloud - selection', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - let appListCloudComponent = new AppListCloudPage(); - let tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); const tasksService: Tasks = new Tasks(); let silentLogin; const simpleApp = 'simple-app'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - let noOfTasks = 3, response; - let tasks = []; + const noOfTasks = 3; + let response; + const tasks = []; beforeAll(async (done) => { silentLogin = false; diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index acdda666c3..b92b12db77 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -49,8 +49,9 @@ describe('Task filters cloud', () => { const simpleApp = 'simple-app'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let assignedTask, deletedTask, suspendedTasks; - let orderByNameAndPriority = ['cCreatedTask', 'dCreatedTask', 'eCreatedTask']; - let priority = 30, nrOfTasks = 3; + const orderByNameAndPriority = ['cCreatedTask', 'dCreatedTask', 'eCreatedTask']; + let priority = 30; + const nrOfTasks = 3; beforeAll(async () => { silentLogin = false; @@ -73,10 +74,10 @@ describe('Task filters cloud', () => { } await processDefinitionService.init(user, password); - let processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); await processInstancesService.init(user, password); - let processInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - let secondProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + const processInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + const secondProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); await queryService.init(user, password); suspendedTasks = await queryService.getProcessInstanceTasks(processInstance.entry.id, simpleApp); await queryService.getProcessInstanceTasks(secondProcessInstance.entry.id, simpleApp); @@ -147,7 +148,7 @@ describe('Task filters cloud', () => { tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); tasksCloudDemoPage.taskListCloudComponent().getAllRowsNameColumn().then( (list) => { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(function (firstStr, secondStr) { return firstStr.localeCompare(secondStr); }); @@ -158,7 +159,7 @@ describe('Task filters cloud', () => { tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); tasksCloudDemoPage.taskListCloudComponent().getAllRowsNameColumn().then( (list) => { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(function (firstStr, secondStr) { return firstStr.localeCompare(secondStr); }); @@ -174,7 +175,7 @@ describe('Task filters cloud', () => { tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); tasksCloudDemoPage.getAllRowsByIdColumn().then((list) => { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(function (firstStr, secondStr) { return firstStr.localeCompare(secondStr); }); @@ -185,7 +186,7 @@ describe('Task filters cloud', () => { tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); tasksCloudDemoPage.getAllRowsByIdColumn().then((list) => { - let initialList = list.slice(0); + const initialList = list.slice(0); list.sort(function (firstStr, secondStr) { return firstStr.localeCompare(secondStr); }); diff --git a/e2e/process-services/apps-section.e2e.ts b/e2e/process-services/apps-section.e2e.ts index 81f41ea622..48af7cc2f4 100644 --- a/e2e/process-services/apps-section.e2e.ts +++ b/e2e/process-services/apps-section.e2e.ts @@ -32,18 +32,18 @@ import { ModelsActions } from '../actions/APS/models.actions'; describe('Modify applications', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let app = resources.Files.APP_WITH_PROCESSES; - let appToBeDeleted = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let replacingApp = resources.Files.WIDGETS_SMOKE_TEST; - let apps = new AppsActions(); - let modelActions = new ModelsActions(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const app = resources.Files.APP_WITH_PROCESSES; + const appToBeDeleted = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const replacingApp = resources.Files.WIDGETS_SMOKE_TEST; + const apps = new AppsActions(); + const modelActions = new ModelsActions(); let firstApp, appVersionToBeDeleted; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -52,7 +52,7 @@ describe('Modify applications', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let user = await users.createTenantAndUser(this.alfrescoJsApi); + const user = await users.createTenantAndUser(this.alfrescoJsApi); await this.alfrescoJsApi.login(user.email, user.password); @@ -145,7 +145,7 @@ describe('Modify applications', () => { }); it('[C260207] Should the app be updated when is edited in APS', async () => { - let newDescription = 'new description'; + const newDescription = 'new description'; navigationBarPage.navigateToProcessServicesPage(); processServicesPage.checkApsContainer(); @@ -154,7 +154,7 @@ describe('Modify applications', () => { expect(processServicesPage.getBackgroundColor(appToBeDeleted.title)).toEqual(CONSTANTS.APP_COLOR.ORANGE); expect(processServicesPage.getDescription(appToBeDeleted.title)).toEqual(appToBeDeleted.description); - let appDefinition = {'appDefinition': {'id': appVersionToBeDeleted.id, 'name': appToBeDeleted.title, + const appDefinition = {'appDefinition': {'id': appVersionToBeDeleted.id, 'name': appToBeDeleted.title, 'description': newDescription, 'definition': {'models': [firstApp.definition.models[0]], 'theme': 'theme-4', 'icon': 'glyphicon-user'}}, 'publish': true}; diff --git a/e2e/process-services/attach-file-widget.e2e.ts b/e2e/process-services/attach-file-widget.e2e.ts index 078c0cba16..7eaa724f31 100644 --- a/e2e/process-services/attach-file-widget.e2e.ts +++ b/e2e/process-services/attach-file-widget.e2e.ts @@ -35,20 +35,20 @@ import { UsersActions } from '../actions/users.actions'; describe('Start Task - Task App', () => { - let loginPage = new LoginPage(); - let viewerPage = new ViewerPage(); - let widget = new Widget(); - let taskPage = new TasksPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const viewerPage = new ViewerPage(); + const widget = new Widget(); + const taskPage = new TasksPage(); + const navigationBarPage = new NavigationBarPage(); let processUserModel; - let app = resources.Files.WIDGETS_SMOKE_TEST; - let pdfFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name }); - let appFields = app.form_fields; + const app = resources.Files.WIDGETS_SMOKE_TEST; + const pdfFile = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name }); + const appFields = app.form_fields; beforeAll(async (done) => { - let users = new UsersActions(); - let apps = new AppsActions(); + const users = new UsersActions(); + const apps = new AppsActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/attach-form-component.e2e.ts b/e2e/process-services/attach-form-component.e2e.ts index 0593698dce..31730e5b36 100644 --- a/e2e/process-services/attach-form-component.e2e.ts +++ b/e2e/process-services/attach-form-component.e2e.ts @@ -33,17 +33,17 @@ import { by } from 'protractor'; describe('Attach Form Component', () => { - let loginPage = new LoginPage(); - let taskPage = new TasksPage(); - let attachFormPage = new AttachFormPage(); - let formFields = new FormFields(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const attachFormPage = new AttachFormPage(); + const formFields = new FormFields(); + const navigationBarPage = new NavigationBarPage(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let formTextField = app.form_fields.form_fieldId; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const formTextField = app.form_fields.form_fieldId; let user, tenantId, appId; - let testNames = { + const testNames = { taskName: 'Test Task', formTitle: 'Select Form To Attach', formName: 'Simple form', @@ -62,8 +62,8 @@ describe('Attach Form Component', () => { }); beforeEach(async (done) => { - let users = new UsersActions(); - let appsActions = new AppsActions(); + const users = new UsersActions(); + const appsActions = new AppsActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -73,7 +73,7 @@ describe('Attach Form Component', () => { await this.alfrescoJsApi.login(user.email, user.password); - let appModel = await appsActions.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const appModel = await appsActions.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = appModel.id; diff --git a/e2e/process-services/checklist-component.e2e.ts b/e2e/process-services/checklist-component.e2e.ts index bf7d649b35..822035851e 100644 --- a/e2e/process-services/checklist-component.e2e.ts +++ b/e2e/process-services/checklist-component.e2e.ts @@ -35,20 +35,20 @@ import { browser } from 'protractor'; describe('Checklist component', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let taskPage = new TasksPage(); + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const taskPage = new TasksPage(); const processServices = new ProcessServicesPage(); const checklistDialog = new ChecklistDialog(); - let tasks = ['no checklist created task', 'checklist number task', 'remove running checklist', 'remove completed checklist', 'hierarchy']; - let checklists = ['cancelCheckList', 'dialogChecklist', 'addFirstChecklist', 'addSecondChecklist']; - let removeChecklist = ['removeFirstRunningChecklist', 'removeSecondRunningChecklist', 'removeFirstCompletedChecklist', 'removeSecondCompletedChecklist']; - let hierarchyChecklist = ['checklistOne', 'checklistTwo', 'checklistOneChild', 'checklistTwoChild']; + const tasks = ['no checklist created task', 'checklist number task', 'remove running checklist', 'remove completed checklist', 'hierarchy']; + const checklists = ['cancelCheckList', 'dialogChecklist', 'addFirstChecklist', 'addSecondChecklist']; + const removeChecklist = ['removeFirstRunningChecklist', 'removeSecondRunningChecklist', 'removeFirstCompletedChecklist', 'removeSecondCompletedChecklist']; + const hierarchyChecklist = ['checklistOne', 'checklistTwo', 'checklistOneChild', 'checklistTwoChild']; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -57,12 +57,12 @@ describe('Checklist component', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); - let pathFile = path.join(TestConfig.main.rootPath + app.file_location); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + app.file_location); + const file = fs.createReadStream(pathFile); await this.alfrescoJsApi.login(processUserModel.email, processUserModel.password); diff --git a/e2e/process-services/comment-component-processes.e2e.ts b/e2e/process-services/comment-component-processes.e2e.ts index 7b8d1f0045..ea3b883321 100644 --- a/e2e/process-services/comment-component-processes.e2e.ts +++ b/e2e/process-services/comment-component-processes.e2e.ts @@ -30,12 +30,12 @@ import { AppsActions } from '../actions/APS/apps.actions'; describe('Comment component for Processes', () => { - let loginPage = new LoginPage(); - let processFiltersPage = new ProcessFiltersPage(); - let commentsPage = new CommentsPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const processFiltersPage = new ProcessFiltersPage(); + const commentsPage = new CommentsPage(); + const navigationBarPage = new NavigationBarPage(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; let user, tenantId, appId, processInstanceId, comment, taskComment, addedComment; beforeAll(async(done) => { @@ -44,8 +44,8 @@ describe('Comment component for Processes', () => { hostBpm: TestConfig.adf.url }); - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -55,10 +55,10 @@ describe('Comment component for Processes', () => { await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; - let processWithComment = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Comment APS'); + const processWithComment = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Comment APS'); processInstanceId = processWithComment.id; await loginPage.loginToProcessServicesUsingUserModel(user); @@ -113,20 +113,20 @@ describe('Comment component for Processes', () => { processFiltersPage.selectFromProcessList('Comment APS'); browser.controlFlow().execute(async() => { - let taskQuery = await this.alfrescoJsApi.activiti.taskApi.listTasks({processInstanceId: processInstanceId}); + const taskQuery = await this.alfrescoJsApi.activiti.taskApi.listTasks({processInstanceId: processInstanceId}); - let taskId = taskQuery.data[0].id; + const taskId = taskQuery.data[0].id; - let taskComments = await this.alfrescoJsApi.activiti.commentsApi.getTaskComments(taskId, {'latestFirst': true}); + const taskComments = await this.alfrescoJsApi.activiti.commentsApi.getTaskComments(taskId, {'latestFirst': true}); expect(taskComments.total).toEqual(0); }); }); it('[C260466] Should be able to display comments from Task on the related Process', () => { browser.controlFlow().execute(async() => { - let taskQuery = await this.alfrescoJsApi.activiti.taskApi.listTasks({processInstanceId: processInstanceId}); + const taskQuery = await this.alfrescoJsApi.activiti.taskApi.listTasks({processInstanceId: processInstanceId}); - let taskId = taskQuery.data[0].id; + const taskId = taskQuery.data[0].id; taskComment = {message: 'Task Comment'}; @@ -139,7 +139,7 @@ describe('Comment component for Processes', () => { processFiltersPage.selectFromProcessList('Comment APS'); browser.controlFlow().execute(async() => { - let addedTaskComment = await this.alfrescoJsApi.activiti.commentsApi.getProcessInstanceComments(processInstanceId, {'latestFirst': true}); + const addedTaskComment = await this.alfrescoJsApi.activiti.commentsApi.getProcessInstanceComments(processInstanceId, {'latestFirst': true}); commentsPage.checkUserIconIsDisplayed(0); diff --git a/e2e/process-services/comment-component-tasks.e2e.ts b/e2e/process-services/comment-component-tasks.e2e.ts index 3463827786..9084373e67 100644 --- a/e2e/process-services/comment-component-tasks.e2e.ts +++ b/e2e/process-services/comment-component-tasks.e2e.ts @@ -33,15 +33,15 @@ import { AppsActions } from '../actions/APS/apps.actions'; describe('Comment component for Processes', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let taskPage = new TasksPage(); - let commentsPage = new CommentsPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const taskPage = new TasksPage(); + const commentsPage = new CommentsPage(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; let user, tenantId, appId, secondUser, newTaskId; - let taskName = { + const taskName = { completed_task: 'Test Completed', multiple_users: 'Test Comment multiple users' }; @@ -53,8 +53,8 @@ describe('Comment component for Processes', () => { hostBpm: TestConfig.adf.url }); - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -66,7 +66,7 @@ describe('Comment component for Processes', () => { await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; await loginPage.loginToProcessServicesUsingUserModel(user); @@ -86,9 +86,9 @@ describe('Comment component for Processes', () => { it('[C260237] Should not be able to add a comment on a completed task', () => { browser.controlFlow().execute(async() => { - let newTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask({name: taskName.completed_task}); + const newTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask({name: taskName.completed_task}); - let taskId = newTask.id; + const taskId = newTask.id; this.alfrescoJsApi.activiti.taskActionsApi.completeTask(taskId); }); @@ -103,14 +103,14 @@ describe('Comment component for Processes', () => { it('[C212864] Should be able to add multiple comments on a single task using different users', () => { browser.controlFlow().execute(async() => { - let newTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask({name: taskName.multiple_users}); + const newTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask({name: taskName.multiple_users}); newTaskId = newTask.id; await this.alfrescoJsApi.activiti.taskApi.involveUser(newTaskId, {email: secondUser.email}); - let taskComment = {message: 'Task Comment'}; - let secondTaskComment = {message: 'Second Task Comment'}; + const taskComment = {message: 'Task Comment'}; + const secondTaskComment = {message: 'Second Task Comment'}; await this.alfrescoJsApi.activiti.taskApi.addTaskComment(taskComment, newTaskId); await this.alfrescoJsApi.activiti.taskApi.addTaskComment(secondTaskComment, newTaskId); @@ -123,9 +123,9 @@ describe('Comment component for Processes', () => { taskPage.taskDetails().selectActivityTab(); browser.controlFlow().execute(async() => { - let totalComments = await this.alfrescoJsApi.activiti.taskApi.getTaskComments(newTaskId, {'latestFirst': true}); + const totalComments = await this.alfrescoJsApi.activiti.taskApi.getTaskComments(newTaskId, {'latestFirst': true}); - let thirdTaskComment = {message: 'Third Task Comment'}; + const thirdTaskComment = {message: 'Third Task Comment'}; await commentsPage.checkUserIconIsDisplayed(0); await commentsPage.checkUserIconIsDisplayed(1); @@ -153,7 +153,7 @@ describe('Comment component for Processes', () => { taskPage.taskDetails().selectActivityTab(); browser.controlFlow().execute(async() => { - let totalComments = await this.alfrescoJsApi.activiti.taskApi.getTaskComments(newTaskId, {'latestFirst': true}); + const totalComments = await this.alfrescoJsApi.activiti.taskApi.getTaskComments(newTaskId, {'latestFirst': true}); await commentsPage.checkUserIconIsDisplayed(0); await commentsPage.checkUserIconIsDisplayed(1); diff --git a/e2e/process-services/custom-process-filters-sorting.e2e.ts b/e2e/process-services/custom-process-filters-sorting.e2e.ts index 1d06b82313..c383d5e635 100644 --- a/e2e/process-services/custom-process-filters-sorting.e2e.ts +++ b/e2e/process-services/custom-process-filters-sorting.e2e.ts @@ -31,17 +31,17 @@ import { AppsActions } from '../actions/APS/apps.actions'; describe('Sorting for process filters', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processFiltersPage = new ProcessFiltersPage(); - let filtersPage = new FiltersPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processFiltersPage = new ProcessFiltersPage(); + const filtersPage = new FiltersPage(); - let apps = new AppsActions(); + const apps = new AppsActions(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; let tenantId, appId, user, processesQuery; - let processFilter = { + const processFilter = { running_old_first: 'Running - Oldest first', completed_old_first: 'Completed - Oldest first', all_old_first: 'All - Oldest first', @@ -62,7 +62,7 @@ describe('Sorting for process filters', () => { }); beforeEach(async(done) => { - let users = new UsersActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -71,7 +71,7 @@ describe('Sorting for process filters', () => { await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; loginPage.loginToProcessServicesUsingUserModel(user); @@ -122,9 +122,9 @@ describe('Sorting for process filters', () => { 'filter': {'sort': 'created-asc', 'name': '', 'state': 'completed'} }); - let firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); - let secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); - let thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); + const firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); + const secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); + const thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(firstProc.id); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(secondProc.id); @@ -163,9 +163,9 @@ describe('Sorting for process filters', () => { await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); - let firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 4'); - let secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 5'); - let thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 6'); + const firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 4'); + const secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 5'); + const thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 6'); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(firstProc.id); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(secondProc.id); @@ -236,9 +236,9 @@ describe('Sorting for process filters', () => { 'filter': {'sort': 'created-desc', 'name': '', 'state': 'completed'} }); - let firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); - let secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); - let thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); + const firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); + const secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); + const thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(firstProc.id); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(secondProc.id); @@ -277,9 +277,9 @@ describe('Sorting for process filters', () => { await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); - let firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 4'); - let secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 5'); - let thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 6'); + const firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 4'); + const secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 5'); + const thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 6'); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(firstProc.id); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(secondProc.id); @@ -317,9 +317,9 @@ describe('Sorting for process filters', () => { 'filter': {'sort': 'ended-asc', 'name': '', 'state': 'completed'} }); - let firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); - let secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); - let thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); + const firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); + const secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); + const thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(secondProc.id); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(firstProc.id); @@ -354,9 +354,9 @@ describe('Sorting for process filters', () => { 'filter': {'sort': 'ended-desc', 'name': '', 'state': 'completed'} }); - let firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); - let secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); - let thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); + const firstProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 1'); + const secondProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 2'); + const thirdProc = await apps.startProcess(this.alfrescoJsApi, 'Task App', 'Process 3'); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(secondProc.id); await this.alfrescoJsApi.activiti.processInstancesApi.deleteProcessInstance(firstProc.id); diff --git a/e2e/process-services/custom-process-filters.e2e.ts b/e2e/process-services/custom-process-filters.e2e.ts index 1c70e05501..8e403f8ddf 100644 --- a/e2e/process-services/custom-process-filters.e2e.ts +++ b/e2e/process-services/custom-process-filters.e2e.ts @@ -30,15 +30,15 @@ import { UsersActions } from '../actions/users.actions'; describe('New Process Filters', () => { - let loginPage = new LoginPage(); - let processFiltersPage = new ProcessFiltersPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let appSettingsToggles = new AppSettingsToggles(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const processFiltersPage = new ProcessFiltersPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const appSettingsToggles = new AppSettingsToggles(); + const navigationBarPage = new NavigationBarPage(); let tenantId, user, filterId, customProcessFilter; - let processFilter = { + const processFilter = { running: 'Running', all: 'All', completed: 'Completed', @@ -50,7 +50,7 @@ describe('New Process Filters', () => { }; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/custom-tasks-filters.e2e.ts b/e2e/process-services/custom-tasks-filters.e2e.ts index 5bd1d32cbe..298326c2ca 100644 --- a/e2e/process-services/custom-tasks-filters.e2e.ts +++ b/e2e/process-services/custom-tasks-filters.e2e.ts @@ -35,31 +35,33 @@ import { DateUtil } from '../util/dateUtil'; describe('Start Task - Custom App', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let taskListSinglePage = new TaskListDemoPage(); - let paginationPage = new PaginationPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const taskListSinglePage = new TaskListDemoPage(); + const paginationPage = new PaginationPage(); let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; let appRuntime, secondAppRuntime; - let secondApp = resources.Files.WIDGETS_SMOKE_TEST; + const secondApp = resources.Files.WIDGETS_SMOKE_TEST; let appModel, secondAppModel; - let completedTasks = []; - let paginationTasksName = ['t01', 't02', 't03', 't04', 't05', 't06', 't07', 't08', 't09', 't10', 't11', 't12', 't13', 'taskOne', 'taskTwo', 'taskOne']; - let completedTasksName = ['completed01', 'completed02', 'completed03']; - let allTasksName = ['t01', 'taskOne', 'taskTwo', 'taskOne', 't13', 't12', 't11', 't10', 't09', 't08', 't07', 't06', 't05', 't04', 't03', 't02', + const completedTasks = []; + const paginationTasksName = ['t01', 't02', 't03', 't04', 't05', 't06', 't07', 't08', 't09', 't10', 't11', 't12', 't13', 'taskOne', 'taskTwo', 'taskOne']; + const completedTasksName = ['completed01', 'completed02', 'completed03']; + const allTasksName = ['t01', 'taskOne', 'taskTwo', 'taskOne', 't13', 't12', 't11', 't10', 't09', 't08', 't07', 't06', 't05', 't04', 't03', 't02', 'User Task', 'User Task', 'User Task', 'User Task']; - let invalidAppId = '1234567890', invalidName = 'invalidName', invalidTaskId = '0000'; - let noTasksFoundMessage = 'No Tasks Found'; - let nrOfTasks = 20, currentPage = 1, totalNrOfPages = 'of 4'; - let currentDateStandardFormat = DateUtil.formatDate('YYYY-MM-DDTHH:mm:ss.SSSZ'); - let currentDate = DateUtil.formatDate('MM/DD/YYYY'); - let beforeDate = moment().add(-1, 'days').format('MM/DD/YYYY'); - let afterDate = moment().add(1, 'days').format('MM/DD/YYYY'); + const invalidAppId = '1234567890', invalidName = 'invalidName', invalidTaskId = '0000'; + const noTasksFoundMessage = 'No Tasks Found'; + const nrOfTasks = 20; + let currentPage = 1; + const totalNrOfPages = 'of 4'; + const currentDateStandardFormat = DateUtil.formatDate('YYYY-MM-DDTHH:mm:ss.SSSZ'); + const currentDate = DateUtil.formatDate('MM/DD/YYYY'); + const beforeDate = moment().add(-1, 'days').format('MM/DD/YYYY'); + const afterDate = moment().add(1, 'days').format('MM/DD/YYYY'); let taskWithDueDate; let processDefinitionId; - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5, ten: '10', @@ -72,9 +74,9 @@ describe('Start Task - Custom App', () => { }; beforeAll(async (done) => { - let apps = new AppsActions(); - let appsRuntime = new AppsRuntimeActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const appsRuntime = new AppsRuntimeActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -83,7 +85,7 @@ describe('Start Task - Custom App', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); @@ -516,7 +518,7 @@ describe('Start Task - Custom App', () => { // failing due to ADF-3667, blocked by ACTIVITI-1975 xit('[C286599] Should be able to sort tasks ascending by due date when choosing due(asc) from sort drop down', () => { - let sortAscByDueDate = [taskWithDueDate.name, completedTasks[0].name, completedTasks[1].name, completedTasks[2].name]; + const sortAscByDueDate = [taskWithDueDate.name, completedTasks[0].name, completedTasks[1].name, completedTasks[2].name]; navigationBarPage.clickTaskListButton(); taskListSinglePage.clickResetButton(); @@ -542,7 +544,7 @@ describe('Start Task - Custom App', () => { // failing due to ADF-3667, blocked by ACTIVITI-1975 xit('[C286600] Should be able to sort tasks descending by due date when choosing due(desc) from sort drop down', () => { - let sortDescByDueDate = [completedTasks[2].name, completedTasks[1].name, completedTasks[0].name, taskWithDueDate.name]; + const sortDescByDueDate = [completedTasks[2].name, completedTasks[1].name, completedTasks[0].name, taskWithDueDate.name]; navigationBarPage.clickTaskListButton(); taskListSinglePage.clickResetButton(); @@ -567,7 +569,7 @@ describe('Start Task - Custom App', () => { }); it('[C286622] Should be able to see only tasks that are part of a specific process when processDefinitionId is set', () => { - let processDefinitionIds = [processDefinitionId.processDefinitionId, processDefinitionId.processDefinitionId, + const processDefinitionIds = [processDefinitionId.processDefinitionId, processDefinitionId.processDefinitionId, processDefinitionId.processDefinitionId, processDefinitionId.processDefinitionId]; navigationBarPage.clickTaskListButton(); @@ -591,7 +593,7 @@ describe('Start Task - Custom App', () => { }); it('[C286622] Should be able to see only tasks that are part of a specific process when processInstanceId is set', () => { - let processInstanceIds = [processDefinitionId.id]; + const processInstanceIds = [processDefinitionId.id]; navigationBarPage.clickTaskListButton(); taskListSinglePage.clickResetButton(); diff --git a/e2e/process-services/dynamic-table-date-picker.e2e.ts b/e2e/process-services/dynamic-table-date-picker.e2e.ts index b2f0bcfbe0..2a8987158f 100644 --- a/e2e/process-services/dynamic-table-date-picker.e2e.ts +++ b/e2e/process-services/dynamic-table-date-picker.e2e.ts @@ -32,12 +32,12 @@ import { UsersActions } from '../actions/users.actions'; describe('Dynamic Table', () => { - let loginPage = new LoginPage(); - let processFiltersPage = new ProcessFiltersPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let dynamicTable = new DynamicTableWidget(); - let datePicker = new DatePickerPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const processFiltersPage = new ProcessFiltersPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const dynamicTable = new DynamicTableWidget(); + const datePicker = new DatePickerPage(); + const navigationBarPage = new NavigationBarPage(); let user, tenantId, appId, apps, users; beforeAll(async(done) => { @@ -67,20 +67,20 @@ describe('Dynamic Table', () => { }); describe('Date Picker', () => { - let app = resources.Files.DYNAMIC_TABLE_APP; + const app = resources.Files.DYNAMIC_TABLE_APP; - let randomText = { + const randomText = { date: 'HELLO WORLD', dateTime: 'Test', error: `Field 'columnDate' is required.` }; - let rowPosition = 0; + const rowPosition = 0; beforeAll(async(done) => { await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; await loginPage.loginToProcessServicesUsingUserModel(user); @@ -128,14 +128,14 @@ describe('Dynamic Table', () => { }); describe('Required Dropdown', () => { - let app = resources.Files.APP_DYNAMIC_TABLE_DROPDOWN; - let dropdown = new DropdownWidget(); + const app = resources.Files.APP_DYNAMIC_TABLE_DROPDOWN; + const dropdown = new DropdownWidget(); beforeAll(async(done) => { await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; await loginPage.loginToProcessServicesUsingUserModel(user); @@ -161,7 +161,7 @@ describe('Dynamic Table', () => { }); it('[C286519] Should be able to save row with required dropdown column', () => { - let dropdownOption = 'Option 1'; + const dropdownOption = 'Option 1'; dynamicTable.clickAddButton(); dropdown.selectOption(dropdownOption); dynamicTable.clickSaveButton(); diff --git a/e2e/process-services/empty-process-list-component.e2e.ts b/e2e/process-services/empty-process-list-component.e2e.ts index a741cd0ecc..b682d04caa 100644 --- a/e2e/process-services/empty-process-list-component.e2e.ts +++ b/e2e/process-services/empty-process-list-component.e2e.ts @@ -31,22 +31,22 @@ import { UsersActions } from '../actions/users.actions'; describe('Empty Process List Test', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let processFiltersPage = new ProcessFiltersPage(); - let processDetailsPage = new ProcessDetailsPage(); - let processListPage = new ProcessListPage(); - let startProcessPage = new StartProcessPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const processFiltersPage = new ProcessFiltersPage(); + const processDetailsPage = new ProcessDetailsPage(); + const processListPage = new ProcessListPage(); + const startProcessPage = new StartProcessPage(); - let appA = resources.Files.APP_WITH_PROCESSES; - let appB = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const appA = resources.Files.APP_WITH_PROCESSES; + const appB = resources.Files.SIMPLE_APP_WITH_USER_FORM; let user; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/form-component.e2e.ts b/e2e/process-services/form-component.e2e.ts index c1147093c9..21972bb5ad 100644 --- a/e2e/process-services/form-component.e2e.ts +++ b/e2e/process-services/form-component.e2e.ts @@ -37,13 +37,13 @@ describe('Form Component', () => { let tenantId, user; - let fields = { + const fields = { dateWidgetId: 'label7', numberWidgetId: 'label4', amountWidgetId: 'label11' }; - let message = { + const message = { test: 'Text Test', warningNumberAndAmount: 'Use a different number format', warningDate: 'D-M-YYYY', @@ -59,7 +59,7 @@ describe('Form Component', () => { hostBpm: TestConfig.adf.url }); - let users = new UsersActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); diff --git a/e2e/process-services/form-people-widget.e2e.ts b/e2e/process-services/form-people-widget.e2e.ts index f80945ea6a..83b45cc6ca 100644 --- a/e2e/process-services/form-people-widget.e2e.ts +++ b/e2e/process-services/form-people-widget.e2e.ts @@ -34,21 +34,21 @@ import { browser } from 'protractor'; describe('Form widgets - People', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let app = resources.Files.APP_WITH_USER_WIDGET; - let processFiltersPage = new ProcessFiltersPage(); + const app = resources.Files.APP_WITH_USER_WIDGET; + const processFiltersPage = new ProcessFiltersPage(); let appModel; let alfrescoJsApi; - let widget = new Widget(); - let startProcess = new StartProcessPage(); - let processDetailsPage = new ProcessDetailsPage(); - let taskDetails = new TaskDetailsPage(); - let appNavigationBar = new AppNavigationBarPage(); + const widget = new Widget(); + const startProcess = new StartProcessPage(); + const processDetailsPage = new ProcessDetailsPage(); + const taskDetails = new TaskDetailsPage(); + const appNavigationBar = new AppNavigationBarPage(); beforeAll(async (done) => { - let users = new UsersActions(); - let appsActions = new AppsActions(); + const users = new UsersActions(); + const appsActions = new AppsActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -94,9 +94,9 @@ describe('Form widgets - People', () => { processDetailsPage.clickOnActiveTask(); browser.controlFlow().execute(async () => { - let taskId = await taskDetails.getId(); - let taskForm = await alfrescoJsApi.activiti.taskApi.getTaskForm(taskId); - let userEmail = taskForm['fields'][0].fields['1'][0].value.email; + const taskId = await taskDetails.getId(); + const taskForm = await alfrescoJsApi.activiti.taskApi.getTaskForm(taskId); + const userEmail = taskForm['fields'][0].fields['1'][0].value.email; expect(userEmail).toEqual(processUserModel.email); }); }); @@ -117,9 +117,9 @@ describe('Form widgets - People', () => { processDetailsPage.clickOnCompletedTask(); browser.controlFlow().execute(async () => { - let taskId = await taskDetails.getId(); - let taskForm = await alfrescoJsApi.activiti.taskApi.getTaskForm(taskId); - let userEmail = taskForm['fields'][0].fields['1'][0].value.email; + const taskId = await taskDetails.getId(); + const taskForm = await alfrescoJsApi.activiti.taskApi.getTaskForm(taskId); + const userEmail = taskForm['fields'][0].fields['1'][0].value.email; expect(userEmail).toEqual(processUserModel.email); }); }); diff --git a/e2e/process-services/form-widgets-component.e2e.ts b/e2e/process-services/form-widgets-component.e2e.ts index 6b7fef4e94..07ad107a41 100644 --- a/e2e/process-services/form-widgets-component.e2e.ts +++ b/e2e/process-services/form-widgets-component.e2e.ts @@ -33,24 +33,24 @@ import { AppsActions } from '../actions/APS/apps.actions'; import { UsersActions } from '../actions/users.actions'; import { browser } from 'protractor'; -let formInstance = new FormDefinitionModel(); +const formInstance = new FormDefinitionModel(); describe('Form widgets', () => { let alfrescoJsApi; - let taskPage = new TasksPage(); - let newTask = 'First task'; - let loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const newTask = 'First task'; + const loginPage = new LoginPage(); let processUserModel; let appModel; - let widget = new Widget(); + const widget = new Widget(); describe('Form widgets', () => { - let app = resources.Files.WIDGETS_SMOKE_TEST; - let appFields = app.form_fields; + const app = resources.Files.WIDGETS_SMOKE_TEST; + const appFields = app.form_fields; beforeAll(async (done) => { - let users = new UsersActions(); - let appsActions = new AppsActions(); + const users = new UsersActions(); + const appsActions = new AppsActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -178,7 +178,7 @@ describe('Form widgets', () => { }); it('[C272785] Should display checkbox and radio button in form', () => { - let radioOption = 1; + const radioOption = 1; expect(taskPage.formFields().getFieldLabel(appFields.checkbox_id)) .toContain(formInstance.getWidgetBy('id', appFields.checkbox_id).name); @@ -211,13 +211,13 @@ describe('Form widgets', () => { describe('with fields involving other people', () => { - let appsActions = new AppsActions(); - let app = resources.Files.FORM_ADF; + const appsActions = new AppsActions(); + const app = resources.Files.FORM_ADF; let deployedApp, process; - let appFields = app.form_fields; + const appFields = app.form_fields; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -231,7 +231,7 @@ describe('Form widgets', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, app.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -241,7 +241,7 @@ describe('Form widgets', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts b/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts index 90fc71def3..71db5dc9a9 100644 --- a/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts +++ b/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts @@ -31,26 +31,26 @@ import { browser } from 'protractor'; describe('Process List - Pagination when adding processes', () => { - let itemsPerPage = { + const itemsPerPage = { fifteen: '15', fifteenValue: 15 }; - let loginPage = new LoginPage(); - let paginationPage = new PaginationPage(); - let processFiltersPage = new ProcessFiltersPage(); - let processDetailsPage = new ProcessDetailsPage(); + const loginPage = new LoginPage(); + const paginationPage = new PaginationPage(); + const processFiltersPage = new ProcessFiltersPage(); + const processDetailsPage = new ProcessDetailsPage(); let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let nrOfProcesses = 25; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const nrOfProcesses = 25; let page, totalPages; let i; - let apps = new AppsActions(); + const apps = new AppsActions(); let resultApp; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts b/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts index 385bf8d31b..0516b6fcd5 100644 --- a/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts +++ b/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts @@ -32,23 +32,27 @@ import { browser } from 'protractor'; describe('Items per page set to 15 and adding of tasks', () => { - let loginPage = new LoginPage(); - let taskPage = new TasksPage(); - let paginationPage = new PaginationPage(); + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const paginationPage = new PaginationPage(); let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let currentPage = 1, nrOfTasks = 25, totalPages = 2, i, resultApp; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + let currentPage = 1; + const nrOfTasks = 25; + const totalPages = 2; + let i; + let resultApp; - let apps = new AppsActions(); + const apps = new AppsActions(); - let itemsPerPage = { + const itemsPerPage = { fifteen: '15', fifteenValue: 15 }; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/people-component.e2e.ts b/e2e/process-services/people-component.e2e.ts index 0da1fbf159..cb9f11c0e7 100644 --- a/e2e/process-services/people-component.e2e.ts +++ b/e2e/process-services/people-component.e2e.ts @@ -35,18 +35,18 @@ import { browser } from 'protractor'; describe('People component', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); let processUserModel, assigneeUserModel, secondAssigneeUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let taskPage = new TasksPage(); - let peopleTitle = 'People this task is shared with '; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const taskPage = new TasksPage(); + const peopleTitle = 'People this task is shared with '; const processServices = new ProcessServicesPage(); - let tasks = ['no people involved task', 'remove people task', 'can not complete task', 'multiple users', 'completed filter']; + const tasks = ['no people involved task', 'remove people task', 'can not complete task', 'multiple users', 'completed filter']; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -55,7 +55,7 @@ describe('People component', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); assigneeUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); @@ -63,8 +63,8 @@ describe('People component', () => { processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); - let pathFile = path.join(TestConfig.main.rootPath + app.file_location); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + app.file_location); + const file = fs.createReadStream(pathFile); await this.alfrescoJsApi.login(processUserModel.email, processUserModel.password); diff --git a/e2e/process-services/process-attachmentList-actionMenu.e2e.ts b/e2e/process-services/process-attachmentList-actionMenu.e2e.ts index 0ef2d1bae0..edfeb6e9fa 100644 --- a/e2e/process-services/process-attachmentList-actionMenu.e2e.ts +++ b/e2e/process-services/process-attachmentList-actionMenu.e2e.ts @@ -36,21 +36,21 @@ import { browser } from 'protractor'; describe('Attachment list action menu for processes', () => { - let loginPage = new LoginPage(); - let processFiltersPage = new ProcessFiltersPage(); - let processDetailsPage = new ProcessDetailsPage(); - let attachmentListPage = new AttachmentListPage(); - let navigationBarPage = new NavigationBarPage(); - let viewerPage = new ViewerPage(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let pngFile = new FileModel({ + const loginPage = new LoginPage(); + const processFiltersPage = new ProcessFiltersPage(); + const processDetailsPage = new ProcessDetailsPage(); + const attachmentListPage = new AttachmentListPage(); + const navigationBarPage = new NavigationBarPage(); + const viewerPage = new ViewerPage(); + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const pngFile = new FileModel({ location: resources.Files.ADF_DOCUMENTS.PNG.file_location, name: resources.Files.ADF_DOCUMENTS.PNG.file_name }); - let downloadedPngFile = path.join(__dirname, 'downloads', pngFile.name); + const downloadedPngFile = path.join(__dirname, 'downloads', pngFile.name); let tenantId, appId; - let processName = { + const processName = { active: 'Active Process', completed: 'Completed Process', taskApp: 'Task App Name', @@ -59,8 +59,8 @@ describe('Attachment list action menu for processes', () => { }; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -69,13 +69,13 @@ describe('Attachment list action menu for processes', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let user = await users.createTenantAndUser(this.alfrescoJsApi); + const user = await users.createTenantAndUser(this.alfrescoJsApi); tenantId = user.tenantId; await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; await apps.startProcess(this.alfrescoJsApi, importedApp, processName.completed); diff --git a/e2e/process-services/process-filters-component.e2e.ts b/e2e/process-services/process-filters-component.e2e.ts index 67f0df957f..a052ee2467 100644 --- a/e2e/process-services/process-filters-component.e2e.ts +++ b/e2e/process-services/process-filters-component.e2e.ts @@ -35,31 +35,31 @@ import { browser } from 'protractor'; describe('Process Filters Test', () => { - let loginPage = new LoginPage(); - let processListPage = new ProcessListPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let startProcessPage = new StartProcessPage(); - let processFiltersPage = new ProcessFiltersPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let processDetailsPage = new ProcessDetailsPage(); + const loginPage = new LoginPage(); + const processListPage = new ProcessListPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const startProcessPage = new StartProcessPage(); + const processFiltersPage = new ProcessFiltersPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const processDetailsPage = new ProcessDetailsPage(); let appModel; - let app = resources.Files.APP_WITH_DATE_FIELD_FORM; + const app = resources.Files.APP_WITH_DATE_FIELD_FORM; - let processTitle = { + const processTitle = { running: 'Test_running', completed: 'Test_completed' }; - let processFilter = { + const processFilter = { running: 'Running', all: 'All', completed: 'Completed' }; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -68,7 +68,7 @@ describe('Process Filters Test', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let user = await users.createTenantAndUser(this.alfrescoJsApi); + const user = await users.createTenantAndUser(this.alfrescoJsApi); await this.alfrescoJsApi.login(user.email, user.password); @@ -132,12 +132,12 @@ describe('Process Filters Test', () => { it('[C280407] Should be able to access the filters with URL', async () => { - let defaultFiltersNumber = 3; + const defaultFiltersNumber = 3; let deployedApp, processFilterUrl; - let taskAppFilters = await browser.controlFlow().execute(async() => { + const taskAppFilters = await browser.controlFlow().execute(async() => { - let appDefinitions = await this.alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await this.alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { diff --git a/e2e/process-services/processList-component.e2e.ts b/e2e/process-services/processList-component.e2e.ts index 670f12cc63..19e8179ce4 100644 --- a/e2e/process-services/processList-component.e2e.ts +++ b/e2e/process-services/processList-component.e2e.ts @@ -31,20 +31,20 @@ describe('Process List Test', () => { const loginPage = new LoginPage(); const processListDemoPage = new ProcessListDemoPage(); - let appWithDateField = resources.Files.APP_WITH_DATE_FIELD_FORM; - let appWithUserWidget = resources.Files.APP_WITH_USER_WIDGET; + const appWithDateField = resources.Files.APP_WITH_DATE_FIELD_FORM; + const appWithUserWidget = resources.Files.APP_WITH_USER_WIDGET; let appDateModel, appUserWidgetModel, user; - let processList = ['Process With Date', 'Process With Date 2', 'Process With User Widget', 'Process With User Widget 2']; + const processList = ['Process With Date', 'Process With Date 2', 'Process With User Widget', 'Process With User Widget 2']; - let processName = { + const processName = { procWithDate: 'Process With Date', completedProcWithDate: 'Process With Date 2', procWithUserWidget: 'Process With User Widget', completedProcWithUserWidget: 'Process With User Widget 2' }; - let errorMessages = { + const errorMessages = { appIdNumber: 'App ID must be a number', insertAppId: 'Insert App ID' }; @@ -53,8 +53,8 @@ describe('Process List Test', () => { let procWithDate, completedProcWithDate, completedProcWithUserWidget; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -79,8 +79,8 @@ describe('Process List Test', () => { appWithDateFieldId = await apps.getAppDefinitionId(this.alfrescoJsApi, appDateModel.id); - let procWithDateTaskId = await apps.getProcessTaskId(this.alfrescoJsApi, completedProcWithDate.id); - let procWithUserWidgetTaskId = await apps.getProcessTaskId(this.alfrescoJsApi, completedProcWithUserWidget.id); + const procWithDateTaskId = await apps.getProcessTaskId(this.alfrescoJsApi, completedProcWithDate.id); + const procWithUserWidgetTaskId = await apps.getProcessTaskId(this.alfrescoJsApi, completedProcWithUserWidget.id); await this.alfrescoJsApi.activiti.taskApi.completeTaskForm(procWithDateTaskId, {values: {label: null }}); await this.alfrescoJsApi.activiti.taskFormsApi.completeTaskForm(procWithUserWidgetTaskId, {values: {label: null }}); diff --git a/e2e/process-services/processlist-pagination.e2e.ts b/e2e/process-services/processlist-pagination.e2e.ts index 336d773e49..0b9344c47e 100644 --- a/e2e/process-services/processlist-pagination.e2e.ts +++ b/e2e/process-services/processlist-pagination.e2e.ts @@ -30,7 +30,7 @@ import { UsersActions } from '../actions/users.actions'; describe('Process List - Pagination', function () { - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5, ten: '10', @@ -42,22 +42,24 @@ describe('Process List - Pagination', function () { default: '25' }; - let processFilterRunning = 'Running'; + const processFilterRunning = 'Running'; - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let paginationPage = new PaginationPage(); - let processFiltersPage = new ProcessFiltersPage(); - let processDetailsPage = new ProcessDetailsPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const paginationPage = new PaginationPage(); + const processFiltersPage = new ProcessFiltersPage(); + const processDetailsPage = new ProcessDetailsPage(); let deployedTestApp; let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let nrOfProcesses = 20; - let page, totalPages, processNameBase = 'process'; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const nrOfProcesses = 20; + let page; + let totalPages; + const processNameBase = 'process'; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -89,7 +91,7 @@ describe('Process List - Pagination', function () { describe('With processes Pagination', function () { beforeAll(async (done) => { - let apps = new AppsActions(); + const apps = new AppsActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/sort-tasklist-pagination.e2e.ts b/e2e/process-services/sort-tasklist-pagination.e2e.ts index e5919a711a..ac7205b20b 100644 --- a/e2e/process-services/sort-tasklist-pagination.e2e.ts +++ b/e2e/process-services/sort-tasklist-pagination.e2e.ts @@ -32,16 +32,17 @@ import { UsersActions } from '../actions/users.actions'; describe('Task List Pagination - Sorting', () => { - let loginPage = new LoginPage(); - let taskPage = new TasksPage(); - let paginationPage = new PaginationPage(); + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); + const paginationPage = new PaginationPage(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let nrOfTasks = 20, processUserModel; - let taskNameBase = 'Task'; - let taskNames = Util.generateSequenceFiles(10, nrOfTasks + 9, taskNameBase, ''); + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const nrOfTasks = 20; + let processUserModel; + const taskNameBase = 'Task'; + const taskNames = Util.generateSequenceFiles(10, nrOfTasks + 9, taskNameBase, ''); - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5, ten: '10', @@ -51,8 +52,8 @@ describe('Task List Pagination - Sorting', () => { }; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/process-services/standalone-task.e2e.ts b/e2e/process-services/standalone-task.e2e.ts index 0e77fd077e..56cd579b67 100644 --- a/e2e/process-services/standalone-task.e2e.ts +++ b/e2e/process-services/standalone-task.e2e.ts @@ -36,16 +36,16 @@ import path = require('path'); describe('Start Task - Task App', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let taskPage = new TasksPage(); - let tasks = ['Standalone task', 'Completed standalone task', 'Add a form', 'Remove form']; - let noFormMessage = 'No forms attached'; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const taskPage = new TasksPage(); + const tasks = ['Standalone task', 'Completed standalone task', 'Add a form', 'Remove form']; + const noFormMessage = 'No forms attached'; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -54,12 +54,12 @@ describe('Start Task - Task App', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); - let pathFile = path.join(TestConfig.main.rootPath + app.file_location); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + app.file_location); + const file = fs.createReadStream(pathFile); await this.alfrescoJsApi.login(processUserModel.email, processUserModel.password); diff --git a/e2e/process-services/start-process-component.e2e.ts b/e2e/process-services/start-process-component.e2e.ts index 715bfad82a..be45253e7f 100644 --- a/e2e/process-services/start-process-component.e2e.ts +++ b/e2e/process-services/start-process-component.e2e.ts @@ -41,26 +41,26 @@ import path = require('path'); describe('Start Process Component', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let startProcessPage = new StartProcessPage(); - let processFiltersPage = new ProcessFiltersPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let processDetailsPage = new ProcessDetailsPage(); - let attachmentListPage = new AttachmentListPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const startProcessPage = new StartProcessPage(); + const processFiltersPage = new ProcessFiltersPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const processDetailsPage = new ProcessDetailsPage(); + const attachmentListPage = new AttachmentListPage(); const apps = new AppsActions(); - let app = resources.Files.APP_WITH_PROCESSES; - let simpleApp = resources.Files.WIDGETS_SMOKE_TEST; + const app = resources.Files.APP_WITH_PROCESSES; + const simpleApp = resources.Files.WIDGETS_SMOKE_TEST; let appId, procUserModel, secondProcUserModel, tenantId, simpleAppCreated; - let processModelWithSe = 'process_with_se', processModelWithoutSe = 'process_without_se'; + const processModelWithSe = 'process_with_se', processModelWithoutSe = 'process_without_se'; const processName255Characters = Util.generateRandomString(255); const processNameBiggerThen255Characters = Util.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; - let auditLogFile = path.join('../e2e/download/', 'Audit.pdf'); + const auditLogFile = path.join('../e2e/download/', 'Audit.pdf'); - let jpgFile = new FileModel({ + const jpgFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': resources.Files.ADF_DOCUMENTS.JPG.file_name }); @@ -73,7 +73,7 @@ describe('Start Process Component', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); tenantId = newTenant.id; procUserModel = new User({ tenantId: tenantId }); @@ -89,7 +89,7 @@ describe('Start Process Component', () => { await this.alfrescoJsApiUserTwo.login(secondProcUserModel.email, secondProcUserModel.password); - let appCreated = await apps.importPublishDeployApp(this.alfrescoJsApiUserTwo, app.file_location); + const appCreated = await apps.importPublishDeployApp(this.alfrescoJsApiUserTwo, app.file_location); simpleAppCreated = await apps.importPublishDeployApp(this.alfrescoJsApiUserTwo, simpleApp.file_location); @@ -197,7 +197,7 @@ describe('Start Process Component', () => { startProcessPage.clickFormStartProcessButton(); processDetailsPage.checkDetailsAreDisplayed(); browser.controlFlow().execute(async () => { - let processId = await processDetailsPage.getId(); + const processId = await processDetailsPage.getId(); await this.alfrescoJsApi.activiti.processApi.getProcessInstance(processId).then(function (response) { expect(processDetailsPage.getProcessStatus()).toEqual(CONSTANTS.PROCESS_STATUS.RUNNING); expect(processDetailsPage.getEndDate()).toEqual(CONSTANTS.PROCESS_END_DATE); diff --git a/e2e/process-services/start-task-custom-app.e2e.ts b/e2e/process-services/start-task-custom-app.e2e.ts index 34ba464179..240bae6944 100644 --- a/e2e/process-services/start-task-custom-app.e2e.ts +++ b/e2e/process-services/start-task-custom-app.e2e.ts @@ -38,28 +38,28 @@ import CONSTANTS = require('../util/constants'); describe('Start Task - Custom App', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let attachmentListPage = new AttachmentListPage(); - let appNavigationBarPage = new AppNavigationBarPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const attachmentListPage = new AttachmentListPage(); + const appNavigationBarPage = new AppNavigationBarPage(); let processUserModel, assigneeUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let formTextField = app.form_fields.form_fieldId; - let formFieldValue = 'First value '; - let taskPage = new TasksPage(); - let firstComment = 'comm1', firstChecklist = 'checklist1'; - let tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File', 'Spinner']; - let showHeaderTask = 'Show Header'; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const formTextField = app.form_fields.form_fieldId; + const formFieldValue = 'First value '; + const taskPage = new TasksPage(); + const firstComment = 'comm1', firstChecklist = 'checklist1'; + const tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File', 'Spinner']; + const showHeaderTask = 'Show Header'; let appModel; - let pngFile = new FileModel({ + const pngFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location, 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name }); beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -68,7 +68,7 @@ describe('Start Task - Custom App', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); assigneeUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); diff --git a/e2e/process-services/start-task-task-app.e2e.ts b/e2e/process-services/start-task-task-app.e2e.ts index 1b12c915fd..fbe87390ff 100644 --- a/e2e/process-services/start-task-task-app.e2e.ts +++ b/e2e/process-services/start-task-task-app.e2e.ts @@ -39,29 +39,29 @@ import path = require('path'); describe('Start Task - Task App', () => { - let loginPage = new LoginPage(); - let attachmentListPage = new AttachmentListPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const attachmentListPage = new AttachmentListPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const navigationBarPage = new NavigationBarPage(); let processUserModel, assigneeUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let formTextField = app.form_fields.form_fieldId; - let formFieldValue = 'First value '; - let taskPage = new TasksPage(); - let firstComment = 'comm1', firstChecklist = 'checklist1'; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const formTextField = app.form_fields.form_fieldId; + const formFieldValue = 'First value '; + const taskPage = new TasksPage(); + const firstComment = 'comm1', firstChecklist = 'checklist1'; const taskName255Characters = Util.generateRandomString(255); const taskNameBiggerThen255Characters = Util.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; - let tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File']; - let showHeaderTask = 'Show Header'; - let jpgFile = new FileModel({ + const tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File']; + const showHeaderTask = 'Show Header'; + const jpgFile = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': resources.Files.ADF_DOCUMENTS.JPG.file_name }); beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -70,14 +70,14 @@ describe('Start Task - Task App', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); assigneeUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); - let pathFile = path.join(TestConfig.main.rootPath + app.file_location); - let file = fs.createReadStream(pathFile); + const pathFile = path.join(TestConfig.main.rootPath + app.file_location); + const file = fs.createReadStream(pathFile); await this.alfrescoJsApi.login(processUserModel.email, processUserModel.password); diff --git a/e2e/process-services/task-attachmentList-actionMenu.e2e.ts b/e2e/process-services/task-attachmentList-actionMenu.e2e.ts index fa99f0b788..c20dcb1134 100644 --- a/e2e/process-services/task-attachmentList-actionMenu.e2e.ts +++ b/e2e/process-services/task-attachmentList-actionMenu.e2e.ts @@ -39,19 +39,19 @@ import { FileModel } from '../models/ACS/fileModel'; describe('Attachment list action menu for tasks', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let taskPage = new TasksPage(); - let attachmentListPage = new AttachmentListPage(); - let viewerPage = new ViewerPage(); - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let pngFile = new FileModel({ + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const taskPage = new TasksPage(); + const attachmentListPage = new AttachmentListPage(); + const viewerPage = new ViewerPage(); + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const pngFile = new FileModel({ location: resources.Files.ADF_DOCUMENTS.PNG.file_location, name: resources.Files.ADF_DOCUMENTS.PNG.file_name }); - let downloadedPngFile = path.join(__dirname, 'downloads', pngFile.name); + const downloadedPngFile = path.join(__dirname, 'downloads', pngFile.name); let tenantId, appId, relatedContent, relatedContentId; - let taskName = { + const taskName = { active: 'Active Task', completed: 'Completed Task', taskApp: 'Task App Name', @@ -59,8 +59,8 @@ describe('Attachment list action menu for tasks', () => { }; beforeAll(async(done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -69,13 +69,13 @@ describe('Attachment list action menu for tasks', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let user = await users.createTenantAndUser(this.alfrescoJsApi); + const user = await users.createTenantAndUser(this.alfrescoJsApi); tenantId = user.tenantId; await this.alfrescoJsApi.login(user.email, user.password); - let importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = importedApp.id; await loginPage.loginToProcessServicesUsingUserModel(user); @@ -179,13 +179,13 @@ describe('Attachment list action menu for tasks', () => { it('[C260234] Should be able to attache a file on a task on APS and check on ADF', () => { browser.controlFlow().execute(async() => { - let newTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask({name: 'SHARE KNOWLEDGE'}); + const newTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask({name: 'SHARE KNOWLEDGE'}); - let newTaskId = newTask.id; + const newTaskId = newTask.id; - let filePath = path.join(TestConfig.main.rootPath + pngFile.location); + const filePath = path.join(TestConfig.main.rootPath + pngFile.location); - let file = fs.createReadStream(filePath); + const file = fs.createReadStream(filePath); relatedContent = await this.alfrescoJsApi.activiti.contentApi.createRelatedContentOnTask(newTaskId, file, {'isRelatedContent': true}); relatedContentId = relatedContent.id; diff --git a/e2e/process-services/task-audit.e2e.ts b/e2e/process-services/task-audit.e2e.ts index 1f6c50acfb..7e2f87cf95 100644 --- a/e2e/process-services/task-audit.e2e.ts +++ b/e2e/process-services/task-audit.e2e.ts @@ -36,20 +36,20 @@ import { browser } from 'protractor'; describe('Task Audit', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let taskPage = new TasksPage(); + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const taskPage = new TasksPage(); const processServices = new ProcessServicesPage(); - let taskTaskApp = 'Audit task task app'; - let taskCustomApp = 'Audit task custom app'; - let taskCompleteCustomApp = 'Audit completed task custom app'; - let auditLogFile = path.join('./e2e/download/', 'Audit.pdf'); + const taskTaskApp = 'Audit task task app'; + const taskCustomApp = 'Audit task custom app'; + const taskCompleteCustomApp = 'Audit completed task custom app'; + const auditLogFile = path.join('./e2e/download/', 'Audit.pdf'); let appModel; beforeAll(async (done) => { - let users = new UsersActions(); - let apps = new AppsActions(); + const users = new UsersActions(); + const apps = new AppsActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -58,7 +58,7 @@ describe('Task Audit', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); diff --git a/e2e/process-services/task-details-form.e2e.ts b/e2e/process-services/task-details-form.e2e.ts index 8bc686ff9d..b77a7bd348 100644 --- a/e2e/process-services/task-details-form.e2e.ts +++ b/e2e/process-services/task-details-form.e2e.ts @@ -32,28 +32,28 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UsersActions } from '../actions/users.actions'; describe('Task Details - Form', () => { - let loginPage = new LoginPage(); - let tasksListPage = new TasksListPage(); - let taskDetailsPage = new TaskDetailsPage(); - let filtersPage = new FiltersPage(); + const loginPage = new LoginPage(); + const tasksListPage = new TasksListPage(); + const taskDetailsPage = new TaskDetailsPage(); + const filtersPage = new FiltersPage(); let task, otherTask, user, newForm, attachedForm, otherAttachedForm; beforeAll(async (done) => { - let users = new UsersActions(); - let attachedFormModel = { + const users = new UsersActions(); + const attachedFormModel = { 'name': Util.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; - let otherTaskModel = new StandaloneTask(); - let otherAttachedFormModel = { + const otherTaskModel = new StandaloneTask(); + const otherAttachedFormModel = { 'name': Util.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; - let newFormModel = { 'name': Util.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; + const newFormModel = { 'name': Util.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -70,7 +70,7 @@ describe('Task Details - Form', () => { newForm = await this.alfrescoJsApi.activiti.modelsApi.createModel(newFormModel); - let otherEmptyTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask(otherTaskModel); + const otherEmptyTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask(otherTaskModel); otherAttachedForm = await this.alfrescoJsApi.activiti.modelsApi.createModel(otherAttachedFormModel); @@ -84,9 +84,9 @@ describe('Task Details - Form', () => { }); beforeEach(async (done) => { - let taskModel = new StandaloneTask(); + const taskModel = new StandaloneTask(); - let emptyTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask(taskModel); + const emptyTask = await this.alfrescoJsApi.activiti.taskApi.createNewTask(taskModel); await this.alfrescoJsApi.activiti.taskApi.attachForm(emptyTask.id, { 'formId': attachedForm.id }); diff --git a/e2e/process-services/task-details-no-form.e2e.ts b/e2e/process-services/task-details-no-form.e2e.ts index cb62537167..e1cd4d886b 100644 --- a/e2e/process-services/task-details-no-form.e2e.ts +++ b/e2e/process-services/task-details-no-form.e2e.ts @@ -32,17 +32,17 @@ import { AppsActions } from '../actions/APS/apps.actions'; describe('Task Details - No form', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); let processUserModel; - let app = resources.Files.NO_FORM_APP; - let taskPage = new TasksPage(); - let noFormMessage = 'No forms attached'; - let apps = new AppsActions(); + const app = resources.Files.NO_FORM_APP; + const taskPage = new TasksPage(); + const noFormMessage = 'No forms attached'; + const apps = new AppsActions(); let importedApp; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -51,7 +51,7 @@ describe('Task Details - No form', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); diff --git a/e2e/process-services/task-details.e2e.ts b/e2e/process-services/task-details.e2e.ts index ff00e21aef..4f3029c24a 100644 --- a/e2e/process-services/task-details.e2e.ts +++ b/e2e/process-services/task-details.e2e.ts @@ -38,17 +38,17 @@ describe('Task Details component', () => { const processServices = new ProcessServicesPage(); let processUserModel, appModel; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File']; - let TASK_DATA_FORMAT = 'mmm dd yyyy'; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File']; + const TASK_DATA_FORMAT = 'mmm dd yyyy'; let formModel; let apps; - let loginPage = new LoginPage(); - let taskPage = new TasksPage(); + const loginPage = new LoginPage(); + const taskPage = new TasksPage(); beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); apps = new AppsActions(); this.alfrescoJsApi = new AlfrescoApi({ @@ -58,7 +58,7 @@ describe('Task Details component', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); + const newTenant = await this.alfrescoJsApi.activiti.adminTenantsApi.createTenant(new Tenant()); processUserModel = await users.createApsUser(this.alfrescoJsApi, newTenant.id); @@ -86,11 +86,11 @@ describe('Task Details component', () => { .clickStartButton(); expect(taskPage.taskDetails().getTitle()).toEqual('Activities'); - let allTasks = await browser.controlFlow().execute(async () => { + const allTasks = await browser.controlFlow().execute(async () => { return this.alfrescoJsApi.activiti.taskApi.listTasks(new Task({ sort: 'created-desc' })); }); - let taskModel = new TaskModel(allTasks.data[0]); + const taskModel = new TaskModel(allTasks.data[0]); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); expect(taskPage.taskDetails().getId()).toEqual(taskModel.getId()); @@ -104,7 +104,7 @@ describe('Task Details component', () => { expect(taskPage.taskDetails().getEndDate()).toEqual(''); expect(taskPage.taskDetails().getStatus()).toEqual(CONSTANTS.TASK_STATUS.RUNNING); - let taskForm = await browser.controlFlow().execute(async () => { + const taskForm = await browser.controlFlow().execute(async () => { return await this.alfrescoJsApi.activiti.taskFormsApi.getTaskForm(allTasks.data[0].id); }); @@ -123,11 +123,11 @@ describe('Task Details component', () => { .clickStartButton(); expect(taskPage.taskDetails().getTitle()).toEqual('Activities'); - let allTasks = await browser.controlFlow().execute(async () => { + const allTasks = await browser.controlFlow().execute(async () => { return this.alfrescoJsApi.activiti.taskApi.listTasks(new Task({ sort: 'created-desc' })); }); - let taskModel = new TaskModel(allTasks.data[0]); + const taskModel = new TaskModel(allTasks.data[0]); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); @@ -142,7 +142,7 @@ describe('Task Details component', () => { expect(taskPage.taskDetails().getParentTaskId()).toEqual(''); expect(taskPage.taskDetails().getStatus()).toEqual(CONSTANTS.TASK_STATUS.RUNNING); - let taskForm = await browser.controlFlow().execute(async () => { + const taskForm = await browser.controlFlow().execute(async () => { return await this.alfrescoJsApi.activiti.taskFormsApi.getTaskForm(allTasks.data[0].id); }); @@ -161,11 +161,11 @@ describe('Task Details component', () => { expect(taskPage.taskDetails().getTitle()).toEqual('Activities'); - let allTasks = await browser.controlFlow().execute(async () => { + const allTasks = await browser.controlFlow().execute(async () => { return await this.alfrescoJsApi.activiti.taskApi.listTasks(new Task({sort: 'created-desc'})); }); - let taskModel = new TaskModel(allTasks.data[0]); + const taskModel = new TaskModel(allTasks.data[0]); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); @@ -180,7 +180,7 @@ describe('Task Details component', () => { expect(taskPage.taskDetails().getParentTaskId()).toEqual(''); expect(taskPage.taskDetails().getStatus()).toEqual(CONSTANTS.TASK_STATUS.RUNNING); - let taskForm = await browser.controlFlow().execute(async () => { + const taskForm = await browser.controlFlow().execute(async () => { return await this.alfrescoJsApi.activiti.taskFormsApi.getTaskForm(allTasks.data[0].id); }); @@ -200,11 +200,11 @@ describe('Task Details component', () => { expect(taskPage.taskDetails().getTitle()).toEqual('Activities'); - let allTasks = await browser.controlFlow().execute(async () => { + const allTasks = await browser.controlFlow().execute(async () => { return await this.alfrescoJsApi.activiti.taskApi.listTasks(new Task({sort: 'created-desc'})); }); - let taskModel = new TaskModel(allTasks.data[0]); + const taskModel = new TaskModel(allTasks.data[0]); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); @@ -219,7 +219,7 @@ describe('Task Details component', () => { expect(taskPage.taskDetails().getParentTaskId()).toEqual(''); expect(taskPage.taskDetails().getStatus()).toEqual(CONSTANTS.TASK_STATUS.RUNNING); - let taskForm = await browser.controlFlow().execute(async () => { + const taskForm = await browser.controlFlow().execute(async () => { return await this.alfrescoJsApi.activiti.taskFormsApi.getTaskForm(allTasks.data[0].id); }); @@ -230,8 +230,8 @@ describe('Task Details component', () => { }); it('[C286708] Should display task details for subtask - Task App', async() => { - let taskName = 'TaskAppSubtask'; - let checklistName = 'TaskAppChecklist'; + const taskName = 'TaskAppSubtask'; + const checklistName = 'TaskAppChecklist'; browser.controlFlow().execute(async () => { await this.alfrescoJsApi.activiti.taskApi.createNewTask({'name': taskName}); }); @@ -247,11 +247,11 @@ describe('Task Details component', () => { taskPage.tasksListPage().checkContentIsDisplayed(checklistName); taskPage.tasksListPage().selectRow(checklistName); - let allTasks = await browser.controlFlow().execute(async () => { + const allTasks = await browser.controlFlow().execute(async () => { return this.alfrescoJsApi.activiti.taskApi.listTasks(new Task({ sort: 'created-desc' })); }); - let taskModel = new TaskModel(allTasks.data[0]); + const taskModel = new TaskModel(allTasks.data[0]); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); expect(taskPage.taskDetails().getId()).toEqual(taskModel.getId()); @@ -267,7 +267,7 @@ describe('Task Details component', () => { }); it('[C286707] Should display task details for subtask - Custom App', async() => { - let checklistName = 'CustomAppChecklist'; + const checklistName = 'CustomAppChecklist'; browser.controlFlow().execute(async () => { await apps.startProcess(this.alfrescoJsApi, appModel); @@ -284,11 +284,11 @@ describe('Task Details component', () => { taskPage.tasksListPage().checkContentIsDisplayed(checklistName); taskPage.tasksListPage().selectRow(checklistName); - let allTasks = await browser.controlFlow().execute(async () => { + const allTasks = await browser.controlFlow().execute(async () => { return this.alfrescoJsApi.activiti.taskApi.listTasks(new Task({ sort: 'created-desc' })); }); - let taskModel = new TaskModel(allTasks.data[0]); + const taskModel = new TaskModel(allTasks.data[0]); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); expect(taskPage.taskDetails().getId()).toEqual(taskModel.getId()); @@ -304,8 +304,8 @@ describe('Task Details component', () => { }); it('[C286709] Should display task details for completed task - Task App', async() => { - let taskName = 'TaskAppCompleted'; - let taskId = await browser.controlFlow().execute(async () => { + const taskName = 'TaskAppCompleted'; + const taskId = await browser.controlFlow().execute(async () => { return this.alfrescoJsApi.activiti.taskApi.createNewTask({'name': taskName}); }); @@ -317,11 +317,11 @@ describe('Task Details component', () => { taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.COMPLETED_TASKS); taskPage.tasksListPage().selectRow(taskName); - let getTaskResponse = await browser.controlFlow().execute(async () => { + const getTaskResponse = await browser.controlFlow().execute(async () => { return this.alfrescoJsApi.activiti.taskApi.getTask(taskId.id); }); - let taskModel = new TaskModel(getTaskResponse); + const taskModel = new TaskModel(getTaskResponse); taskPage.tasksListPage().checkContentIsDisplayed(taskModel.getName()); expect(taskPage.taskDetails().getCreated()).toEqual(dateFormat(taskModel.getCreated(), TASK_DATA_FORMAT)); expect(taskPage.taskDetails().getId()).toEqual(taskModel.getId()); diff --git a/e2e/process-services/task-filters-component.e2e.ts b/e2e/process-services/task-filters-component.e2e.ts index 060873cd77..1cafd90540 100644 --- a/e2e/process-services/task-filters-component.e2e.ts +++ b/e2e/process-services/task-filters-component.e2e.ts @@ -37,15 +37,15 @@ describe('Task', () => { describe('Filters', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let tasksPage = new TasksPage(); - let tasksListPage = new TasksListPage(); - let taskDetailsPage = new TaskDetailsPage(); - let taskFiltersDemoPage = new TaskFiltersDemoPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const tasksPage = new TasksPage(); + const tasksListPage = new TasksListPage(); + const taskDetailsPage = new TaskDetailsPage(); + const taskFiltersDemoPage = new TaskFiltersDemoPage(); - let app = resources.Files.APP_WITH_DATE_FIELD_FORM; + const app = resources.Files.APP_WITH_DATE_FIELD_FORM; let appId, tenantId; beforeAll(async (done) => { @@ -60,18 +60,18 @@ describe('Task', () => { beforeEach(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - let user = await users.createTenantAndUser(this.alfrescoJsApi); + const user = await users.createTenantAndUser(this.alfrescoJsApi); tenantId = user.tenantId; await this.alfrescoJsApi.login(user.email, user.password); - let appModel = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const appModel = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); appId = appModel.id; @@ -201,12 +201,12 @@ describe('Task', () => { describe('Custom Filters', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let appNavigationBarPage = new AppNavigationBarPage(); - let appSettingsToggles = new AppSettingsToggles(); - let taskFiltersDemoPage = new TaskFiltersDemoPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const appSettingsToggles = new AppSettingsToggles(); + const taskFiltersDemoPage = new TaskFiltersDemoPage(); let user; let appId; @@ -214,11 +214,11 @@ describe('Task', () => { let taskFilterId; - let app = resources.Files.APP_WITH_PROCESSES; + const app = resources.Files.APP_WITH_PROCESSES; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -233,7 +233,7 @@ describe('Task', () => { importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); - let appDefinitions = await this.alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await this.alfrescoJsApi.activiti.appsApi.getAppDefinitions(); appId = appDefinitions.data.find((currentApp) => { return currentApp.modelId === importedApp.id; @@ -253,13 +253,13 @@ describe('Task', () => { it('[C260350] Should display a new filter when a filter is added', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'New Task Filter'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); taskFilterId = result.id; return result; @@ -270,20 +270,20 @@ describe('Task', () => { taskFiltersDemoPage.customTaskFilter('New Task Filter').checkTaskFilterIsDisplayed(); browser.controlFlow().execute(() => { - let result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); + const result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); return result; }); }); it('[C286447] Should display the task filter icon when a custom filter is added', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'New Task Filter with icon'; newFilter.appId = appId; newFilter.icon = 'glyphicon-cloud'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); taskFilterId = result.id; return result; @@ -299,7 +299,7 @@ describe('Task', () => { expect(taskFiltersDemoPage.customTaskFilter('New Task Filter with icon').getTaskFilterIcon()).toEqual('cloud'); browser.controlFlow().execute(() => { - let result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); + const result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); return result; }); }); @@ -317,13 +317,13 @@ describe('Task', () => { it('[C260353] Should display changes on a filter when this filter is edited', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'New Task Filter'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); taskFilterId = result.id; return result; @@ -334,13 +334,13 @@ describe('Task', () => { taskFiltersDemoPage.customTaskFilter('New Task Filter').checkTaskFilterIsDisplayed(); browser.controlFlow().execute(() => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Task Filter Edited'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = this.alfrescoJsApi.activiti.userFiltersApi.updateUserTaskFilter(taskFilterId, newFilter); + const result = this.alfrescoJsApi.activiti.userFiltersApi.updateUserTaskFilter(taskFilterId, newFilter); return result; }); @@ -349,20 +349,20 @@ describe('Task', () => { taskFiltersDemoPage.customTaskFilter('Task Filter Edited').checkTaskFilterIsDisplayed(); browser.controlFlow().execute(() => { - let result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); + const result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); return result; }); }); it('[C286448] Should display changes on a task filter when this filter icon is edited', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Task Filter Edited icon'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); taskFilterId = result.id; return result; @@ -373,13 +373,13 @@ describe('Task', () => { taskFiltersDemoPage.customTaskFilter('Task Filter Edited icon').checkTaskFilterIsDisplayed(); browser.controlFlow().execute(() => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Task Filter Edited icon'; newFilter.appId = appId; newFilter.icon = 'glyphicon-cloud'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = this.alfrescoJsApi.activiti.userFiltersApi.updateUserTaskFilter(taskFilterId, newFilter); + const result = this.alfrescoJsApi.activiti.userFiltersApi.updateUserTaskFilter(taskFilterId, newFilter); return result; }); @@ -397,13 +397,13 @@ describe('Task', () => { it('[C260354] Should not display task filter when this filter is deleted', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'New Task Filter'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); taskFilterId = result.id; return result; @@ -414,7 +414,7 @@ describe('Task', () => { taskFiltersDemoPage.customTaskFilter('New Task Filter').checkTaskFilterIsDisplayed(); browser.controlFlow().execute(() => { - let result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); + const result = this.alfrescoJsApi.activiti.userFiltersApi.deleteUserTaskFilter(taskFilterId); return result; }); diff --git a/e2e/process-services/task-filters-sorting.e2e.ts b/e2e/process-services/task-filters-sorting.e2e.ts index 5c8003d607..ae21785790 100644 --- a/e2e/process-services/task-filters-sorting.e2e.ts +++ b/e2e/process-services/task-filters-sorting.e2e.ts @@ -32,21 +32,21 @@ import { browser } from 'protractor'; describe('Task Filters Sorting', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let processServicesPage = new ProcessServicesPage(); - let tasksPage = new TasksPage(); - let tasksListPage = new TasksListPage(); - let taskDetailsPage = new TaskDetailsPage(); - let taskFiltersDemoPage = new TaskFiltersDemoPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const tasksPage = new TasksPage(); + const tasksListPage = new TasksListPage(); + const taskDetailsPage = new TaskDetailsPage(); + const taskFiltersDemoPage = new TaskFiltersDemoPage(); let user; let appId; let importedApp; - let app = resources.Files.APP_WITH_PROCESSES; + const app = resources.Files.APP_WITH_PROCESSES; - let tasks = [ + const tasks = [ { name: 'Task 1 Completed', dueDate: '01/01/2019' }, { name: 'Task 2 Completed', dueDate: '02/01/2019' }, { name: 'Task 3 Completed', dueDate: '03/01/2019' }, @@ -55,8 +55,8 @@ describe('Task Filters Sorting', () => { { name: 'Task 6', dueDate: '03/01/2019' }]; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -71,7 +71,7 @@ describe('Task Filters Sorting', () => { importedApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); - let appDefinitions = await this.alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await this.alfrescoJsApi.activiti.appsApi.getAppDefinitions(); appId = appDefinitions.data.find((currentApp) => { return currentApp.modelId === importedApp.id; @@ -102,13 +102,13 @@ describe('Task Filters Sorting', () => { it('[C277254] Should display tasks under new filter from newest to oldest when they are completed', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Newest first'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -125,13 +125,13 @@ describe('Task Filters Sorting', () => { it('[C277255] Should display tasks under new filter from oldest to newest when they are completed', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Newest last'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-asc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -147,13 +147,13 @@ describe('Task Filters Sorting', () => { it('[C277256] Should display tasks under new filter from closest due date to farthest when they are completed', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Due first'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'due-desc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -169,13 +169,13 @@ describe('Task Filters Sorting', () => { it('[C277257] Should display tasks under new filter from farthest due date to closest when they are completed', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Due last'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'due-asc', state: 'completed', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -191,13 +191,13 @@ describe('Task Filters Sorting', () => { it('[C277258] Should display tasks under new filter from newest to oldest when they are open ', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Newest first Open'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-desc', state: 'open', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -213,13 +213,13 @@ describe('Task Filters Sorting', () => { it('[C277259] Should display tasks under new filter from oldest to newest when they are open', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Newest last Open'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'created-asc', state: 'open', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -235,13 +235,13 @@ describe('Task Filters Sorting', () => { it('[C277260] Should display tasks under new filter from closest due date to farthest when they are open', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Due first Open'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'due-desc', state: 'open', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); @@ -257,13 +257,13 @@ describe('Task Filters Sorting', () => { it('[C277261] Should display tasks under new filter from farthest due date to closest when they are open', () => { browser.controlFlow().execute(async () => { - let newFilter: any = new UserProcessInstanceFilterRepresentation(); + const newFilter: any = new UserProcessInstanceFilterRepresentation(); newFilter.name = 'Due last Open'; newFilter.appId = appId; newFilter.icon = 'glyphicon-filter'; newFilter.filter = { sort: 'due-asc', state: 'open', assignment: 'involved' }; - let result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); + const result = await this.alfrescoJsApi.activiti.userFiltersApi.createUserTaskFilter(newFilter); return result; }); diff --git a/e2e/process-services/task-list-pagination.e2e.ts b/e2e/process-services/task-list-pagination.e2e.ts index 4d79b24446..b65f420b75 100644 --- a/e2e/process-services/task-list-pagination.e2e.ts +++ b/e2e/process-services/task-list-pagination.e2e.ts @@ -31,16 +31,18 @@ import { UsersActions } from '../actions/users.actions'; describe('Task List Pagination', () => { - let loginPage = new LoginPage(); - let navigationBarPage = new NavigationBarPage(); - let taskPage = new TasksPage(); - let paginationPage = new PaginationPage(); + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const taskPage = new TasksPage(); + const paginationPage = new PaginationPage(); let processUserModel, processUserModelEmpty; - let app = resources.Files.SIMPLE_APP_WITH_USER_FORM; - let currentPage = 1, nrOfTasks = 20, totalPages; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + let currentPage = 1; + const nrOfTasks = 20; + let totalPages; - let itemsPerPage = { + const itemsPerPage = { five: '5', fiveValue: 5, ten: '10', @@ -53,8 +55,8 @@ describe('Task List Pagination', () => { }; beforeAll(async (done) => { - let apps = new AppsActions(); - let users = new UsersActions(); + const apps = new AppsActions(); + const users = new UsersActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -68,7 +70,7 @@ describe('Task List Pagination', () => { await this.alfrescoJsApi.login(processUserModel.email, processUserModel.password); - let resultApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const resultApp = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); for (let i = 0; i < nrOfTasks; i++) { await apps.startProcess(this.alfrescoJsApi, resultApp); diff --git a/e2e/process-services/widgets/amount-widget.e2e.ts b/e2e/process-services/widgets/amount-widget.e2e.ts index 877b6707a3..de643d7f88 100644 --- a/e2e/process-services/widgets/amount-widget.e2e.ts +++ b/e2e/process-services/widgets/amount-widget.e2e.ts @@ -29,19 +29,19 @@ import resources = require('../../util/resources'); describe('Amount Widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.AMOUNT; + const app = resources.Files.WIDGET_CHECK_APP.AMOUNT; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -55,7 +55,7 @@ describe('Amount Widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -65,7 +65,7 @@ describe('Amount Widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/attach-folder-widget.e2e.ts b/e2e/process-services/widgets/attach-folder-widget.e2e.ts index 96bee87462..4e525f947f 100644 --- a/e2e/process-services/widgets/attach-folder-widget.e2e.ts +++ b/e2e/process-services/widgets/attach-folder-widget.e2e.ts @@ -27,18 +27,18 @@ import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); describe('Attach Folder widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.ATTACH_FOLDER; + const app = resources.Files.WIDGET_CHECK_APP.ATTACH_FOLDER; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -52,7 +52,7 @@ describe('Attach Folder widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -62,7 +62,7 @@ describe('Attach Folder widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/checkbox-widget.e2e.ts b/e2e/process-services/widgets/checkbox-widget.e2e.ts index 210e578222..d219301e2e 100644 --- a/e2e/process-services/widgets/checkbox-widget.e2e.ts +++ b/e2e/process-services/widgets/checkbox-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Checkbox Widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.CHECKBOX; + const app = resources.Files.WIDGET_CHECK_APP.CHECKBOX; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Checkbox Widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Checkbox Widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/date-time-widget.e2e.ts b/e2e/process-services/widgets/date-time-widget.e2e.ts index 5a98f527df..38b298ccbf 100644 --- a/e2e/process-services/widgets/date-time-widget.e2e.ts +++ b/e2e/process-services/widgets/date-time-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Date and time widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.DATETIME; + const app = resources.Files.WIDGET_CHECK_APP.DATETIME; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Date and time widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Date and time widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/date-widget.e2e.ts b/e2e/process-services/widgets/date-widget.e2e.ts index 53f063f669..bbb05992f0 100644 --- a/e2e/process-services/widgets/date-widget.e2e.ts +++ b/e2e/process-services/widgets/date-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Date widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.DATE; + const app = resources.Files.WIDGET_CHECK_APP.DATE; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Date widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Date widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/document-template-widget.e2e.ts b/e2e/process-services/widgets/document-template-widget.e2e.ts index 4394594e57..dbb1362504 100644 --- a/e2e/process-services/widgets/document-template-widget.e2e.ts +++ b/e2e/process-services/widgets/document-template-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Document Template widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.FILE_FORM_ADF; + const app = resources.Files.FILE_FORM_ADF; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Document Template widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, app.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Document Template widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/dropdown-widget.e2e.ts b/e2e/process-services/widgets/dropdown-widget.e2e.ts index e7508c37f1..f6b70432ff 100644 --- a/e2e/process-services/widgets/dropdown-widget.e2e.ts +++ b/e2e/process-services/widgets/dropdown-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Dropdown widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.DROPDOWN; + const app = resources.Files.WIDGET_CHECK_APP.DROPDOWN; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Dropdown widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Dropdown widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/dynamic-table-widget.e2e.ts b/e2e/process-services/widgets/dynamic-table-widget.e2e.ts index f3b04f0809..dce1b407f3 100644 --- a/e2e/process-services/widgets/dynamic-table-widget.e2e.ts +++ b/e2e/process-services/widgets/dynamic-table-widget.e2e.ts @@ -28,20 +28,20 @@ import resources = require('../../util/resources'); describe('Dynamic Table widget ', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; let deployedApp, process; describe('with Date Time Widget App', () => { - let app = resources.Files.WIDGET_CHECK_APP.DYNAMIC_TABLE; + const app = resources.Files.WIDGET_CHECK_APP.DYNAMIC_TABLE; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -55,7 +55,7 @@ describe('Dynamic Table widget ', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -65,7 +65,7 @@ describe('Dynamic Table widget ', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); @@ -99,10 +99,10 @@ describe('Dynamic Table widget ', () => { describe('with People Widget App', () => { - let app = resources.Files.WIDGET_CHECK_APP.DYNAMIC_TABLE_USERS; + const app = resources.Files.WIDGET_CHECK_APP.DYNAMIC_TABLE_USERS; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -116,7 +116,7 @@ describe('Dynamic Table widget ', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -126,7 +126,7 @@ describe('Dynamic Table widget ', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/header-widget.e2e.ts b/e2e/process-services/widgets/header-widget.e2e.ts index ce98f1bbbe..4db48bb3ac 100644 --- a/e2e/process-services/widgets/header-widget.e2e.ts +++ b/e2e/process-services/widgets/header-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Header widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.HEADER; + const app = resources.Files.WIDGET_CHECK_APP.HEADER; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Header widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Header widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/hyperlink-widget.e2e.ts b/e2e/process-services/widgets/hyperlink-widget.e2e.ts index cb0d6ccdbf..ac32b0a821 100644 --- a/e2e/process-services/widgets/hyperlink-widget.e2e.ts +++ b/e2e/process-services/widgets/hyperlink-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Hyperlink widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.HYPERLINK; + const app = resources.Files.WIDGET_CHECK_APP.HYPERLINK; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Hyperlink widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Hyperlink widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/multi-line-widget.e2e.ts b/e2e/process-services/widgets/multi-line-widget.e2e.ts index e407db01a2..17a2c7c498 100644 --- a/e2e/process-services/widgets/multi-line-widget.e2e.ts +++ b/e2e/process-services/widgets/multi-line-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Multi-line Widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.MULTILINE_TEXT; + const app = resources.Files.WIDGET_CHECK_APP.MULTILINE_TEXT; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Multi-line Widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Multi-line Widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); @@ -77,10 +77,10 @@ describe('Multi-line Widget', () => { }); it('[C268182] Should be able to set general properties for Multi-line Text Widget', () => { - let label = widget.multilineTextWidget().getFieldLabel(app.FIELD.multiSimple); + const label = widget.multilineTextWidget().getFieldLabel(app.FIELD.multiSimple); expect(label).toBe('multiSimple*'); expect(taskPage.formFields().isCompleteFormButtonDisabled()).toBeTruthy(); - let placeHolder = widget.multilineTextWidget().getFieldPlaceHolder(app.FIELD.multiSimple); + const placeHolder = widget.multilineTextWidget().getFieldPlaceHolder(app.FIELD.multiSimple); expect(placeHolder).toBe('Type something...'); widget.multilineTextWidget().setValue(app.FIELD.multiSimple, 'TEST'); expect(taskPage.formFields().isCompleteFormButtonDisabled()).toBeFalsy(); diff --git a/e2e/process-services/widgets/number-widget.e2e.ts b/e2e/process-services/widgets/number-widget.e2e.ts index ebb05d3647..1eceff1581 100644 --- a/e2e/process-services/widgets/number-widget.e2e.ts +++ b/e2e/process-services/widgets/number-widget.e2e.ts @@ -29,18 +29,18 @@ import resources = require('../../util/resources'); describe('Number widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.NUMBER; + const app = resources.Files.WIDGET_CHECK_APP.NUMBER; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -54,7 +54,7 @@ describe('Number widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -64,7 +64,7 @@ describe('Number widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/people-widget.e2e.ts b/e2e/process-services/widgets/people-widget.e2e.ts index 0f9c4822e4..c699259f09 100644 --- a/e2e/process-services/widgets/people-widget.e2e.ts +++ b/e2e/process-services/widgets/people-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('People widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.ADD_PEOPLE; + const app = resources.Files.WIDGET_CHECK_APP.ADD_PEOPLE; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('People widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('People widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); @@ -81,7 +81,7 @@ describe('People widget', () => { widget.checkboxWidget().clickCheckboxInput(app.FIELD.checkbox_id); taskPage.formFields().checkWidgetIsVisible(app.FIELD.widget_id); - let admin = processUserModel.firstName + ' ' + processUserModel.lastName; + const admin = processUserModel.firstName + ' ' + processUserModel.lastName; widget.peopleWidget().insertUser(app.FIELD.widget_id, admin.charAt(0)); widget.peopleWidget().checkDropDownListIsDisplayed(); widget.peopleWidget().checkUserIsListed(admin); @@ -93,7 +93,7 @@ describe('People widget', () => { widget.checkboxWidget().clickCheckboxInput(app.FIELD.checkbox_id); taskPage.formFields().checkWidgetIsVisible(app.FIELD.widget_id); - let admin = processUserModel.firstName + ' ' + processUserModel.lastName; + const admin = processUserModel.firstName + ' ' + processUserModel.lastName; widget.peopleWidget().insertUser(app.FIELD.widget_id, admin.charAt(0)); widget.peopleWidget().checkDropDownListIsDisplayed(); widget.peopleWidget().checkUserIsListed(admin); diff --git a/e2e/process-services/widgets/radio-buttons-widget.e2e.ts b/e2e/process-services/widgets/radio-buttons-widget.e2e.ts index 72dfceadfd..9334770a86 100644 --- a/e2e/process-services/widgets/radio-buttons-widget.e2e.ts +++ b/e2e/process-services/widgets/radio-buttons-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Radio Buttons Widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.RADIO_BUTTONS; + const app = resources.Files.WIDGET_CHECK_APP.RADIO_BUTTONS; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Radio Buttons Widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -65,7 +65,7 @@ describe('Radio Buttons Widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); diff --git a/e2e/process-services/widgets/text-widget.e2e.ts b/e2e/process-services/widgets/text-widget.e2e.ts index e0bc6abdc3..43095cd11e 100644 --- a/e2e/process-services/widgets/text-widget.e2e.ts +++ b/e2e/process-services/widgets/text-widget.e2e.ts @@ -28,18 +28,18 @@ import resources = require('../../util/resources'); describe('Text widget', () => { - let loginPage = new LoginPage(); + const loginPage = new LoginPage(); let processUserModel; - let taskPage = new TasksPage(); - let widget = new Widget(); + const taskPage = new TasksPage(); + const widget = new Widget(); let alfrescoJsApi; - let appsActions = new AppsActions(); + const appsActions = new AppsActions(); let appModel; - let app = resources.Files.WIDGET_CHECK_APP.TEXT; + const app = resources.Files.WIDGET_CHECK_APP.TEXT; let deployedApp, process; beforeAll(async (done) => { - let users = new UsersActions(); + const users = new UsersActions(); alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', @@ -53,7 +53,7 @@ describe('Text widget', () => { await alfrescoJsApi.login(processUserModel.email, processUserModel.password); appModel = await appsActions.importPublishDeployApp(alfrescoJsApi, resources.Files.WIDGET_CHECK_APP.file_location); - let appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); + const appDefinitions = await alfrescoJsApi.activiti.appsApi.getAppDefinitions(); deployedApp = appDefinitions.data.find((currentApp) => { return currentApp.modelId === appModel.id; }); @@ -63,7 +63,7 @@ describe('Text widget', () => { }); beforeEach(() => { - let urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; + const urlToNavigateTo = `${TestConfig.adf.url}/activiti/apps/${deployedApp.id}/tasks/`; browser.get(urlToNavigateTo); taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.formFields().checkFormIsDisplayed(); @@ -77,10 +77,10 @@ describe('Text widget', () => { }); it('[C268157] Should be able to set general properties for Text widget', async () => { - let label = widget.textWidget().getFieldLabel(app.FIELD.simpleText); + const label = widget.textWidget().getFieldLabel(app.FIELD.simpleText); expect(label).toBe('textSimple*'); expect(taskPage.formFields().isCompleteFormButtonDisabled()).toBeTruthy(); - let placeHolder = widget.textWidget().getFieldPlaceHolder(app.FIELD.simpleText); + const placeHolder = widget.textWidget().getFieldPlaceHolder(app.FIELD.simpleText); expect(placeHolder).toBe('Type something...'); widget.textWidget().setValue(app.FIELD.simpleText, 'TEST'); expect(taskPage.formFields().isCompleteFormButtonDisabled()).toBeFalsy(); diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index d970c7d760..f4a0b2139d 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -42,17 +42,17 @@ describe('Search Checklist Component', () => { const searchDialog = new SearchDialog(); const searchResults = new SearchResultsPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); - let filterType = { + const filterType = { folder: 'Folder', document: 'Document', custom: 'TEST_NAME' }; - let randomName = Util.generateRandomString(); - let nodeNames = { + const randomName = Util.generateRandomString(); + const nodeNames = { document: `${randomName}.txt`, folder: `${randomName}Folder` }; @@ -135,7 +135,7 @@ describe('Search Checklist Component', () => { let jsonFile; beforeEach(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); @@ -299,7 +299,7 @@ describe('Search Checklist Component', () => { let jsonFile; beforeEach(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); diff --git a/e2e/search/components/search-date-range.e2e.ts b/e2e/search/components/search-date-range.e2e.ts index fd26c93720..5751f72eca 100644 --- a/e2e/search/components/search-date-range.e2e.ts +++ b/e2e/search/components/search-date-range.e2e.ts @@ -33,15 +33,15 @@ import { DateUtil } from '../../util/dateUtil'; describe('Search Date Range Filter', () => { - let loginPage = new LoginPage(); - let searchDialog = new SearchDialog(); - let searchFilters = new SearchFiltersPage(); - let dateRangeFilter = searchFilters.createdDateRangeFilterPage(); - let searchResults = new SearchResultsPage(); - let datePicker = new DatePickerPage(); - let navigationBar = new NavigationBarPage(); - let configEditor = new ConfigEditorPage(); - let dataTable = new DataTableComponentPage(); + const loginPage = new LoginPage(); + const searchDialog = new SearchDialog(); + const searchFilters = new SearchFiltersPage(); + const dateRangeFilter = searchFilters.createdDateRangeFilterPage(); + const searchResults = new SearchResultsPage(); + const datePicker = new DatePickerPage(); + const navigationBar = new NavigationBarPage(); + const configEditor = new ConfigEditorPage(); + const dataTable = new DataTableComponentPage(); beforeAll(async (done) => { @@ -89,7 +89,7 @@ describe('Search Date Range Filter', () => { }); it('[C277105] Should be able to type a date', () => { - let date = '01-May-18'; + const date = '01-May-18'; dateRangeFilter.putFromDate(date); browser.controlFlow().execute(async () => { await expect(dateRangeFilter.getFromCalendarSelectedDate()).toEqual(dateRangeFilter.getFromDate()); @@ -138,11 +138,11 @@ describe('Search Date Range Filter', () => { searchResults.sortByCreated(true); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Created'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Created'); + for (const currentResult of results) { currentResult.getAttribute('title').then(async (currentDate) => { - let currentDateFormatted = DateUtil.parse(currentDate, 'MMM DD, YYYY, h:mm:ss a'); + const currentDateFormatted = DateUtil.parse(currentDate, 'MMM DD, YYYY, h:mm:ss a'); await expect(currentDateFormatted <= DateUtil.parse(toDate, 'DD-MM-YY')).toBe(true); await expect(currentDateFormatted >= DateUtil.parse(fromDate, 'DD-MM-YY')).toBe(true); @@ -162,8 +162,8 @@ describe('Search Date Range Filter', () => { }); it('[C277114] Should display warning message if user doesn\'t set the date range properly', () => { - let toDate = '01-May-18'; - let fromDate = '16-May-18'; + const toDate = '01-May-18'; + const fromDate = '16-May-18'; dateRangeFilter.checkToFieldIsDisplayed() .putToDate(toDate) @@ -193,7 +193,7 @@ describe('Search Date Range Filter', () => { let jsonFile; beforeAll(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); @@ -213,7 +213,7 @@ describe('Search Date Range Filter', () => { dateRangeFilter.checkFromFieldIsDisplayed() .openFromDatePicker(); - let todayDate = DateUtil.formatDate('MM-DD-YY'); + const todayDate = DateUtil.formatDate('MM-DD-YY'); datePicker.selectTodayDate(); browser.controlFlow().execute(async () => { diff --git a/e2e/search/components/search-number-range.e2e.ts b/e2e/search/components/search-number-range.e2e.ts index 88f80a4705..dd6426da91 100644 --- a/e2e/search/components/search-number-range.e2e.ts +++ b/e2e/search/components/search-number-range.e2e.ts @@ -114,7 +114,7 @@ describe('Search Number Range Filter', () => { }); it('[C276922] Should be keep value when Number Range widget is collapsed', () => { - let size = 5; + const size = 5; sizeRangeFilter.putFromNumber(size); sizeRangeFilter.putToNumber(size); searchFilters.clickSizeRangeFilterHeader() @@ -159,8 +159,8 @@ describe('Search Number Range Filter', () => { }); it('[C276943] Should be able to put a big value in To field', () => { - let toSize = 999999999; - let fromSize = 0; + const toSize = 999999999; + const fromSize = 0; sizeRangeFilter.checkToFieldIsDisplayed() .putToNumber(toSize) .putFromNumber(fromSize); @@ -172,10 +172,10 @@ describe('Search Number Range Filter', () => { searchResults.sortBySize(false); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) <= toSize).toBe(true); } @@ -186,9 +186,9 @@ describe('Search Number Range Filter', () => { }); it('[C276944] Should be able to filter by name when size range filter is applied', () => { - let nameFilter = searchFilters.textFiltersPage(); - let toSize = 40; - let fromSize = 0; + const nameFilter = searchFilters.textFiltersPage(); + const toSize = 40; + const fromSize = 0; searchFilters.checkNameFilterIsDisplayed() .checkNameFilterIsExpanded(); nameFilter.searchByName('*'); @@ -203,10 +203,10 @@ describe('Search Number Range Filter', () => { searchResults.sortBySize(false); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) <= toSize).toBe(true); } @@ -221,10 +221,10 @@ describe('Search Number Range Filter', () => { searchResults.sortBySize(false); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) <= toSize).toBe(true); } @@ -234,10 +234,10 @@ describe('Search Number Range Filter', () => { }); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Display name'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Display name'); + for (const currentResult of results) { try { - let name = await currentResult.getAttribute('title'); + const name = await currentResult.getAttribute('title'); if (name && name.trim() !== '') { await expect(/z*/i.test(name)).toBe(true); } @@ -277,10 +277,10 @@ describe('Search Number Range Filter', () => { searchResults.sortBySize(false); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(currentSize === '0').toBe(true); } @@ -315,11 +315,11 @@ describe('Search Number Range Filter', () => { searchResults.sortBySize(false); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) <= 1000).toBe(true); } @@ -334,11 +334,11 @@ describe('Search Number Range Filter', () => { expect(sizeRangeFilter.getToNumber()).toEqual(''); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) >= 1000).toBe(true); } @@ -394,7 +394,7 @@ describe('Search Number Range Filter', () => { let jsonFile; beforeEach(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); @@ -414,8 +414,8 @@ describe('Search Number Range Filter', () => { .clickSizeRangeFilterHeader() .checkSizeRangeFilterIsExpanded(); - let fromYear = (new Date()).getFullYear(); - let toYear = fromYear + 1; + const fromYear = (new Date()).getFullYear(); + const toYear = fromYear + 1; sizeRangeFilter.checkToFieldIsDisplayed() .putToNumber(toYear) @@ -427,10 +427,10 @@ describe('Search Number Range Filter', () => { searchResults.sortByCreated(false); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Created'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Created'); + for (const currentResult of results) { currentResult.getAttribute('title').then(async (currentDate) => { - let currentDateFormatted = DateUtil.parse(currentDate, 'MMM DD, YYYY, h:mm:ss a'); + const currentDateFormatted = DateUtil.parse(currentDate, 'MMM DD, YYYY, h:mm:ss a'); await expect(currentDateFormatted.getFullYear() <= toYear).toBe(true); await expect(currentDateFormatted.getFullYear() >= fromYear).toBe(true); diff --git a/e2e/search/components/search-radio.e2e.ts b/e2e/search/components/search-radio.e2e.ts index 52f69681c5..6f86234e75 100644 --- a/e2e/search/components/search-radio.e2e.ts +++ b/e2e/search/components/search-radio.e2e.ts @@ -42,10 +42,10 @@ describe('Search Radio Component', () => { const searchDialog = new SearchDialog(); const searchResults = new SearchResultsPage(); - let acsUser = new AcsUserModel(); - let uploadActions = new UploadActions(); + const acsUser = new AcsUserModel(); + const uploadActions = new UploadActions(); - let filterType = { + const filterType = { none: 'None', all: 'All', folder: 'Folder', @@ -53,8 +53,8 @@ describe('Search Radio Component', () => { custom: 'TEST_NAME' }; - let randomName = Util.generateRandomString(); - let nodeNames = { + const randomName = Util.generateRandomString(); + const nodeNames = { document: `${randomName}.txt`, folder: `${randomName}Folder` }; @@ -137,7 +137,7 @@ describe('Search Radio Component', () => { let jsonFile; beforeEach(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); @@ -281,7 +281,7 @@ describe('Search Radio Component', () => { let jsonFile; beforeEach(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); diff --git a/e2e/search/components/search-slider.e2e.ts b/e2e/search/components/search-slider.e2e.ts index 1f31aa657c..edad2a798f 100644 --- a/e2e/search/components/search-slider.e2e.ts +++ b/e2e/search/components/search-slider.e2e.ts @@ -106,7 +106,7 @@ describe('Search Number Range Filter', () => { }); it('[C276972] Should be keep value when Search Size Slider is collapsed', () => { - let size = 5; + const size = 5; sizeSliderFilter.checkSliderIsDisplayed().setValue(size); searchFilters.clickSizeSliderFilterHeader() .checkSizeSliderFilterIsCollapsed() @@ -117,16 +117,16 @@ describe('Search Number Range Filter', () => { }); it('[C276981] Should be able to clear value in Search Size Slider', () => { - let size = 5; + const size = 5; sizeSliderFilter.checkSliderIsDisplayed().setValue(size); searchResults.sortBySize(false) .tableIsLoaded(); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) <= 5000).toBe(true); } @@ -142,11 +142,11 @@ describe('Search Number Range Filter', () => { .tableIsLoaded(); browser.controlFlow().execute(async () => { - let results = await dataTable.geCellElementDetail('Size'); - for (let currentResult of results) { + const results = await dataTable.geCellElementDetail('Size'); + for (const currentResult of results) { try { - let currentSize = await currentResult.getAttribute('title'); + const currentSize = await currentResult.getAttribute('title'); if (currentSize && currentSize.trim() !== '') { await expect(parseInt(currentSize, 10) >= 5000).toBe(true); } @@ -160,7 +160,7 @@ describe('Search Number Range Filter', () => { let jsonFile; beforeEach(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); @@ -184,7 +184,7 @@ describe('Search Number Range Filter', () => { }); it('[C276985] Should be able to set min value for Search Size Slider', () => { - let minSize = 3; + const minSize = 3; jsonFile.categories[2].component.settings.min = minSize; navigationBar.clickConfigEditorButton(); @@ -206,7 +206,7 @@ describe('Search Number Range Filter', () => { }); it('[C276986] Should be able to set max value for Search Size Slider', () => { - let maxSize = 50; + const maxSize = 50; jsonFile.categories[2].component.settings.max = maxSize; navigationBar.clickConfigEditorButton(); @@ -228,7 +228,7 @@ describe('Search Number Range Filter', () => { }); it('[C276987] Should be able to set steps for Search Size Slider', () => { - let step = 10; + const step = 10; jsonFile.categories[2].component.settings.step = step; navigationBar.clickConfigEditorButton(); @@ -244,7 +244,7 @@ describe('Search Number Range Filter', () => { .clickSizeSliderFilterHeader() .checkSizeSliderFilterIsExpanded(); - let randomValue = 5; + const randomValue = 5; sizeSliderFilter.checkSliderIsDisplayed() .setValue(randomValue); expect(sizeSliderFilter.getValue()).toEqual(`0`); diff --git a/e2e/search/components/search-sorting-picker.e2e.ts b/e2e/search/components/search-sorting-picker.e2e.ts index fdec031ef5..9ee4513dcf 100644 --- a/e2e/search/components/search-sorting-picker.e2e.ts +++ b/e2e/search/components/search-sorting-picker.e2e.ts @@ -113,7 +113,7 @@ describe('Search Sorting Picker', () => { }); it('[C277271] Should be able to add a custom search sorter in the "sort by" option', () => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); @@ -133,12 +133,12 @@ describe('Search Sorting Picker', () => { }); it('[C277272] Should be able to exclude a standard search sorter from the sorting option', () => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); configEditor.clickClearButton(); - let removedOption = jsonFile.sorting.options.splice(0, 1); + const removedOption = jsonFile.sorting.options.splice(0, 1); configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); configEditor.clickSaveButton(); @@ -153,7 +153,7 @@ describe('Search Sorting Picker', () => { }); it('[C277273] Should be able to set a default order for a search sorting option', () => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); @@ -200,7 +200,7 @@ describe('Search Sorting Picker', () => { it('[C277286] Should be able to sort the search results by "Created Date" ASC', () => { searchResults.sortByCreated(true); browser.controlFlow().execute(async () => { - let results = await searchResults. dataTable.geCellElementDetail('Created'); + const results = await searchResults. dataTable.geCellElementDetail('Created'); expect(contentServices.checkElementsDateSortedAsc(results)).toBe(true); }); }); @@ -208,13 +208,13 @@ describe('Search Sorting Picker', () => { it('[C277287] Should be able to sort the search results by "Created Date" DESC', () => { searchResults.sortByCreated(false); browser.controlFlow().execute(async () => { - let results = await searchResults. dataTable.geCellElementDetail('Created'); + const results = await searchResults. dataTable.geCellElementDetail('Created'); expect(contentServices.checkElementsDateSortedDesc(results)).toBe(true); }); }); it('[C277288] Should be able to sort the search results by "Modified Date" ASC', () => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); @@ -231,11 +231,11 @@ describe('Search Sorting Picker', () => { .sortBy(true, 'Modified Date'); browser.controlFlow().execute(async () => { - let idList = await contentServices.getElementsDisplayedId(); - let numberOfElements = await contentServices.numberOfResultsDisplayed(); + const idList = await contentServices.getElementsDisplayedId(); + const numberOfElements = await contentServices.numberOfResultsDisplayed(); - let nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements); - let modifiedDateList = []; + const nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements); + const modifiedDateList = []; for (let i = 0; i < nodeList.length; i++) { modifiedDateList.push(new Date(nodeList[i].entry.modifiedAt)); } @@ -254,7 +254,7 @@ describe('Search Sorting Picker', () => { }); it('[C277301] Should be able to change default sorting option for the search results', () => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); diff --git a/e2e/search/components/search-text.e2e.ts b/e2e/search/components/search-text.e2e.ts index 6b2b82eaab..25359fd54f 100644 --- a/e2e/search/components/search-text.e2e.ts +++ b/e2e/search/components/search-text.e2e.ts @@ -39,12 +39,12 @@ describe('Search component - Text widget', () => { const navigationBarPage = new NavigationBarPage(); const searchFiltersPage = new SearchFiltersPage(); - let loginPage = new LoginPage(); - let searchDialog = new SearchDialog(); - let searchResultPage = new SearchResultsPage(); + const loginPage = new LoginPage(); + const searchDialog = new SearchDialog(); + const searchResultPage = new SearchResultsPage(); - let acsUser = new AcsUserModel(); - let newFolderModel = new FolderModel({'name': 'newFolder', 'description': 'newDescription'}); + const acsUser = new AcsUserModel(); + const newFolderModel = new FolderModel({'name': 'newFolder', 'description': 'newDescription'}); beforeAll(async (done) => { @@ -88,7 +88,7 @@ describe('Search component - Text widget', () => { let jsonFile; beforeAll(() => { - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); }); diff --git a/e2e/search/search-component.e2e.ts b/e2e/search/search-component.e2e.ts index 6b66e2af70..ff3063fd7f 100644 --- a/e2e/search/search-component.e2e.ts +++ b/e2e/search/search-component.e2e.ts @@ -38,7 +38,7 @@ import { SearchConfiguration } from './search.config'; describe('Search component - Search Bar', () => { - let search = { + const search = { inactive: { firstChar: 'x', secondChar: 'y', @@ -47,32 +47,36 @@ describe('Search component - Search Bar', () => { } }; - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let searchDialog = new SearchDialog(); - let searchResultPage = new SearchResultsPage(); - let filePreviewPage = new FilePreviewPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const searchDialog = new SearchDialog(); + const searchResultPage = new SearchResultsPage(); + const filePreviewPage = new FilePreviewPage(); - let acsUser = new AcsUserModel(); + const searchDialog = new SearchDialog(); + const searchResultPage = new SearchResultsPage(); + const filePreviewPage = new FilePreviewPage(); + + const acsUser = new AcsUserModel(); const uploadActions = new UploadActions(); - let filename = Util.generateRandomString(16); - let firstFolderName = Util.generateRandomString(16); - let secondFolderName = Util.generateRandomString(16); - let thirdFolderName = Util.generateRandomString(16); - let filesToDelete = []; + const filename = Util.generateRandomString(16); + const firstFolderName = Util.generateRandomString(16); + const secondFolderName = Util.generateRandomString(16); + const thirdFolderName = Util.generateRandomString(16); + const filesToDelete = []; - let firstFileModel = new FileModel({ + const firstFileModel = new FileModel({ 'name': filename, 'shortName': filename.substring(0, 8) }); - let firstFolderModel = new FolderModel({ + const firstFolderModel = new FolderModel({ 'name': firstFolderName, 'shortName': firstFolderName.substring(0, 8) }); - let secondFolder = new FolderModel({ + const secondFolder = new FolderModel({ 'name': secondFolderName, 'shortName': secondFolderName.substring(0, 8) }); - let thirdFolder = new FolderModel({ + const thirdFolder = new FolderModel({ 'name': thirdFolderName, 'shortName': thirdFolderName.substring(0, 8) }); @@ -93,7 +97,7 @@ describe('Search component - Search Bar', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - let firstFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, firstFileModel.location, firstFileModel.name, '-my-'); + const firstFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, firstFileModel.location, firstFileModel.name, '-my-'); Object.assign(firstFileModel, firstFileUploaded.entry); fileHighlightUploaded = await this.alfrescoJsApi.nodes.addNode('-my-', { diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index 022bbd1d98..72395d6edb 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -38,51 +38,51 @@ import { SearchConfiguration } from './search.config'; describe('Search Filters', () => { - let loginPage = new LoginPage(); - let searchDialog = new SearchDialog(); - let searchFiltersPage = new SearchFiltersPage(); - let uploadActions = new UploadActions(); - let paginationPage = new PaginationPage(); - let contentList = new DocumentListPage(); - let navigationBar = new NavigationBarPage(); - let configEditor = new ConfigEditorPage(); - let searchResults = new SearchResultsPage(); + const loginPage = new LoginPage(); + const searchDialog = new SearchDialog(); + const searchFiltersPage = new SearchFiltersPage(); + const uploadActions = new UploadActions(); + const paginationPage = new PaginationPage(); + const contentList = new DocumentListPage(); + const navigationBar = new NavigationBarPage(); + const configEditor = new ConfigEditorPage(); + const searchResults = new SearchResultsPage(); - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let filename = Util.generateRandomString(16); - let fileNamePrefix = Util.generateRandomString(5); - let uniqueFileName1 = fileNamePrefix + Util.generateRandomString(5); - let uniqueFileName2 = fileNamePrefix + Util.generateRandomString(5); - let uniqueFileName3 = fileNamePrefix + Util.generateRandomString(5); + const filename = Util.generateRandomString(16); + const fileNamePrefix = Util.generateRandomString(5); + const uniqueFileName1 = fileNamePrefix + Util.generateRandomString(5); + const uniqueFileName2 = fileNamePrefix + Util.generateRandomString(5); + const uniqueFileName3 = fileNamePrefix + Util.generateRandomString(5); - let fileModel = new FileModel({ + const fileModel = new FileModel({ 'name': filename, 'shortName': filename.substring(0, 8) }); - let pngFileModel = new FileModel({ + const pngFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); - let txtFileModel1 = new FileModel({ + const txtFileModel1 = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location, 'name': `${uniqueFileName1}.txt` }); - let jpgFileModel = new FileModel({ + const jpgFileModel = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': `${uniqueFileName2}.jpg` }); - let txtFileModel2 = new FileModel({ + const txtFileModel2 = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location, 'name': `${uniqueFileName3}.txt` }); let fileUploaded, fileTypePng, fileTypeTxt1, fileTypeJpg, fileTypeTxt2; - let filter = { type: 'TYPE-PNG Image' }; + const filter = { type: 'TYPE-PNG Image' }; let jsonFile; @@ -116,7 +116,7 @@ describe('Search Filters', () => { searchDialog.checkSearchIconIsVisible(); searchDialog.clickOnSearchIcon(); - let searchConfiguration = new SearchConfiguration(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); done(); @@ -139,7 +139,7 @@ describe('Search Filters', () => { searchFiltersPage.checkSearchFiltersIsDisplayed(); - let userOption = `${acsUser.firstName} ${acsUser.lastName}`; + const userOption = `${acsUser.firstName} ${acsUser.lastName}`; searchFiltersPage.creatorCheckListFiltersPage().filterBy(userOption) .checkChipIsDisplayed(userOption) .removeFilterOption(userOption) @@ -175,9 +175,9 @@ describe('Search Filters', () => { searchFiltersPage.fileTypeCheckListFiltersPage().clickCheckListOption('PNG Image'); - let bucketNumberForFilter = searchFiltersPage.fileTypeCheckListFiltersPage().getBucketNumberOfFilterType(filter.type); + const bucketNumberForFilter = searchFiltersPage.fileTypeCheckListFiltersPage().getBucketNumberOfFilterType(filter.type); - let resultFileNames = contentList.getAllRowsColumnValues('Display name'); + const resultFileNames = contentList.getAllRowsColumnValues('Display name'); expect(bucketNumberForFilter).not.toEqual('0'); diff --git a/e2e/search/search-multiselect.e2e.ts b/e2e/search/search-multiselect.e2e.ts index daa2a5e70b..8d19614bcf 100644 --- a/e2e/search/search-multiselect.e2e.ts +++ b/e2e/search/search-multiselect.e2e.ts @@ -33,11 +33,11 @@ import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FileModel } from '../models/ACS/fileModel'; describe('Search Component - Multi-Select Facet', () => { - let loginPage = new LoginPage(); - let searchDialog = new SearchDialog(); - let searchResultsPage = new SearchResultsPage(); - let uploadActions = new UploadActions(); - let searchFiltersPage = new SearchFiltersPage(); + const loginPage = new LoginPage(); + const searchDialog = new SearchDialog(); + const searchResultsPage = new SearchResultsPage(); + const uploadActions = new UploadActions(); + const searchFiltersPage = new SearchFiltersPage(); let site, userOption; beforeAll(() => { @@ -49,14 +49,14 @@ describe('Search Component - Multi-Select Facet', () => { describe('', () => { let jpgFile, jpgFileSite, txtFile, txtFileSite; - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let randomName = Util.generateRandomString(); - let jpgFileInfo = new FileModel({ + const randomName = Util.generateRandomString(); + const jpgFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': `${randomName}.jpg` }); - let txtFileInfo = new FileModel({ + const txtFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location, 'name': `${randomName}.txt` }); @@ -129,15 +129,15 @@ describe('Search Component - Multi-Select Facet', () => { describe('', () => { let jpgFile, txtFile; - let userUploadingTxt = new AcsUserModel(); - let userUploadingImg = new AcsUserModel(); + const userUploadingTxt = new AcsUserModel(); + const userUploadingImg = new AcsUserModel(); - let randomName = Util.generateRandomString(); - let jpgFileInfo = new FileModel({ + const randomName = Util.generateRandomString(); + const jpgFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': `${randomName}.jpg` }); - let txtFileInfo = new FileModel({ + const txtFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location, 'name': `${randomName}.txt` }); @@ -199,10 +199,10 @@ describe('Search Component - Multi-Select Facet', () => { describe('', () => { let txtFile; - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); - let randomName = Util.generateRandomString(); - let txtFileInfo = new FileModel({ + const randomName = Util.generateRandomString(); + const txtFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location, 'name': `${randomName}.txt` }); diff --git a/e2e/search/search-page-component.e2e.ts b/e2e/search/search-page-component.e2e.ts index 3c19795c81..24c5fba447 100644 --- a/e2e/search/search-page-component.e2e.ts +++ b/e2e/search/search-page-component.e2e.ts @@ -36,7 +36,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; describe('Search component - Search Page', () => { - let search = { + const search = { active: { firstFile: null, secondFile: null, @@ -49,17 +49,20 @@ describe('Search component - Search Page', () => { } }; - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let searchDialog = new SearchDialog(); - let searchResultPage = new SearchResultsPage(); - let filePreviewPage = new FilePreviewPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const searchDialog = new SearchDialog(); + const searchResultPage = new SearchResultsPage(); + const filePreviewPage = new FilePreviewPage(); - let acsUser = new AcsUserModel(); - let emptyFolderModel = new FolderModel({ 'name': 'search' + Util.generateRandomString() }); + const acsUser = new AcsUserModel(); + const emptyFolderModel = new FolderModel({ 'name': 'search' + Util.generateRandomString() }); let firstFileModel; - let newFolderModel = new FolderModel({ 'name': 'newFolder' }); - let fileNames = [], adminFileNames = [], nrOfFiles = 15, adminNrOfFiles = 5; + const newFolderModel = new FolderModel({ 'name': 'newFolder' }); + let fileNames = []; + let adminFileNames = []; + const nrOfFiles = 15; + const adminNrOfFiles = 5; beforeAll(async (done) => { fileNames = Util.generateSequenceFiles(1, nrOfFiles, search.active.base, search.active.extension); @@ -73,7 +76,7 @@ describe('Search component - Search Page', () => { 'location': resources.Files.ADF_DOCUMENTS.TXT.file_location }); - let uploadActions = new UploadActions(); + const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', @@ -87,7 +90,7 @@ describe('Search component - Search Page', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); await uploadActions.createFolder(this.alfrescoJsApi, emptyFolderModel.name, '-my-'); - let newFolderModelUploaded = await uploadActions.createFolder(this.alfrescoJsApi, newFolderModel.name, '-my-'); + const newFolderModelUploaded = await uploadActions.createFolder(this.alfrescoJsApi, newFolderModel.name, '-my-'); await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, newFolderModelUploaded.entry.id); @@ -105,7 +108,7 @@ describe('Search component - Search Page', () => { }); it('[C260264] Should display message when no results are found', () => { - let notExistentFileName = Util.generateRandomString(); + const notExistentFileName = Util.generateRandomString(); searchDialog.checkSearchBarIsNotVisible().checkSearchIconIsVisible().clickOnSearchIcon() .enterTextAndPressEnter(notExistentFileName); searchResultPage.checkNoResultMessageIsDisplayed(); diff --git a/e2e/util/util.ts b/e2e/util/util.ts index ab25fc7ff7..27a7272c35 100644 --- a/e2e/util/util.ts +++ b/e2e/util/util.ts @@ -20,8 +20,8 @@ import fs = require('fs'); import path = require('path'); import TestConfig = require('../test.config'); -let until = protractor.ExpectedConditions; -let DEFAULT_TIMEOUT = parseInt(TestConfig.main.timeout, 10); +const until = protractor.ExpectedConditions; +const DEFAULT_TIMEOUT = parseInt(TestConfig.main.timeout, 10); export class Util { @@ -29,7 +29,7 @@ export class Util { * creates an absolute path string if multiple file uploads are required */ static uploadParentFolder(filePath) { - let parentFolder = path.resolve(path.join(__dirname, 'test')); + const parentFolder = path.resolve(path.join(__dirname, 'test')); return path.resolve(path.join(parentFolder, filePath)); } @@ -42,7 +42,7 @@ export class Util { */ static generateRandomString(length: number = 8): string { let text = ''; - let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); @@ -53,9 +53,9 @@ export class Util { static generatePasswordString(length: number = 8): string { let text = ''; - let possibleUpperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - let possibleLowerCase = 'abcdefghijklmnopqrstuvwxyz'; - let lowerCaseLimit = Math.floor(length / 2); + const possibleUpperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const possibleLowerCase = 'abcdefghijklmnopqrstuvwxyz'; + const lowerCaseLimit = Math.floor(length / 2); for (let i = 0; i < lowerCaseLimit; i++) { text += possibleLowerCase.charAt(Math.floor(Math.random() * possibleLowerCase.length)); @@ -77,7 +77,7 @@ export class Util { */ static generateRandomStringDigits(length: number = 8): string { let text = ''; - let possible = '0123456789'; + const possible = '0123456789'; for (let i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); @@ -95,7 +95,7 @@ export class Util { */ static generateRandomStringNonLatin(length: number = 3): string { let text = ''; - let possible = '密码你好𠮷'; + const possible = '密码你好𠮷'; for (let i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); @@ -137,7 +137,7 @@ export class Util { * @method generateSequenceFiles */ static generateSequenceFiles(startIndex, endIndex, baseName, extension) { - let fileNames = []; + const fileNames = []; for (let i = startIndex; i <= endIndex; i++) { fileNames.push(baseName + i + extension); } @@ -165,7 +165,7 @@ export class Util { */ static generateRandomEmail(length: number = 5): string { let email = ''; - let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < length; i++) { email += possible.charAt(Math.floor(Math.random() * possible.length)); @@ -181,9 +181,9 @@ export class Util { * @method generateRandomDateFormat */ static generateRandomDateFormat(): string { - let day = Math.floor(Math.random() * (29 - 1) + 1); - let month = Math.floor(Math.random() * (12 - 1) + 1); - let year = Math.floor(Math.random() * (2100 - 1990) + 1990); + const day = Math.floor(Math.random() * (29 - 1) + 1); + const month = Math.floor(Math.random() * (12 - 1) + 1); + const year = Math.floor(Math.random() * (2100 - 1990) + 1990); return day + '.' + month + '.' + year; } @@ -194,17 +194,18 @@ export class Util { * @method generateRandomDate */ static generateRandomDate(): string { - let dayText, monthText; + let dayText; + let monthText; - let day = (Math.floor(Math.random() * (29 - 1) + 1)); + const day = (Math.floor(Math.random() * (29 - 1) + 1)); if (day < 10) { dayText = '0' + day.toString(); } - let month = Math.floor(Math.random() * (12 - 1) + 1); + const month = Math.floor(Math.random() * (12 - 1) + 1); if (month < 10) { monthText = '0' + month.toString(); } - let year = Math.floor(Math.random() * (2100 - 1990) + 1990); + const year = Math.floor(Math.random() * (2100 - 1990) + 1990); return dayText + '-' + monthText + '-' + year.toString(); } @@ -235,7 +236,7 @@ export class Util { * @method readFile */ static readFile(filePath, callback) { - let absolutePath = path.join(TestConfig.main.rootPath + filePath); + const absolutePath = path.join(TestConfig.main.rootPath + filePath); fs.readFile(absolutePath, { encoding: 'utf8' }, function (err, data) { if (err) { throw err; @@ -333,7 +334,7 @@ export class Util { */ static waitForPage() { browser.wait(function () { - let deferred = protractor.promise.defer(); + const deferred = protractor.promise.defer(); browser.executeScript('return document.readyState').then((text) => { deferred.fulfill(() => { return text === 'complete'; @@ -363,7 +364,7 @@ export class Util { static fileExists(filePath, retries) { let tries = 0; return new Promise(function (resolve, reject) { - let checkExist = setInterval(() => { + const checkExist = setInterval(() => { fs.stat(filePath, function (error, stats) { tries++; diff --git a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts index 7f6320c268..3a1f4292de 100644 --- a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts @@ -46,7 +46,7 @@ describe('Breadcrumb', () => { }); it('should prevent default click behavior', () => { - let event = jasmine.createSpyObj('event', ['preventDefault']); + const event = jasmine.createSpyObj('event', ['preventDefault']); component.onRoutePathClick(null, event); expect(event.preventDefault).toHaveBeenCalled(); }); @@ -60,7 +60,7 @@ describe('Breadcrumb', () => { }); it('should emit navigation event', (done) => { - let node = { id: '-id-', name: 'name' }; + const node = { id: '-id-', name: 'name' }; component.navigate.subscribe((val) => { expect(val).toBe(node); done(); @@ -72,7 +72,7 @@ describe('Breadcrumb', () => { it('should update document list on click', (done) => { spyOn(documentList, 'loadFolderByNodeId').and.stub(); - let node = { id: '-id-', name: 'name' }; + const node = { id: '-id-', name: 'name' }; component.target = documentList; component.onRoutePathClick(node, null); diff --git a/lib/content-services/breadcrumb/breadcrumb.component.ts b/lib/content-services/breadcrumb/breadcrumb.component.ts index cb68cc0925..f152ac87b7 100644 --- a/lib/content-services/breadcrumb/breadcrumb.component.ts +++ b/lib/content-services/breadcrumb/breadcrumb.component.ts @@ -108,7 +108,7 @@ export class BreadcrumbComponent implements OnInit, OnChanges { } protected recalculateNodes(): void { - let node: Node = this.transform ? this.transform(this.folderNode) : this.folderNode; + const node: Node = this.transform ? this.transform(this.folderNode) : this.folderNode; this.route = this.parseRoute(node); diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts index 4ba7612337..12983a1385 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts @@ -63,7 +63,7 @@ describe('DropdownBreadcrumb', () => { } it('should display only the current folder name if there is no previous folders', (done) => { - let fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); + const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = []; triggerComponentChange(fakeNodeWithCreatePermissionInstance); @@ -83,7 +83,7 @@ describe('DropdownBreadcrumb', () => { }); it('should display only the path in the selectBox', (done) => { - let fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); + const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = [ { id: '1', name: 'Stark Industries' }, { id: '2', name: 'User Homes' }, @@ -105,7 +105,7 @@ describe('DropdownBreadcrumb', () => { }); xit('should display the path in reverse order', (done) => { - let fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); + const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = [ { id: '1', name: 'Stark Industries' }, { id: '2', name: 'User Homes' }, @@ -130,7 +130,7 @@ describe('DropdownBreadcrumb', () => { }); it('should emit navigation event when clicking on an option', (done) => { - let fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); + const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = [{ id: '1', name: 'Stark Industries' }]; triggerComponentChange(fakeNodeWithCreatePermissionInstance); @@ -153,7 +153,7 @@ describe('DropdownBreadcrumb', () => { it('should update document list when clicking on an option', (done) => { spyOn(documentList, 'loadFolderByNodeId').and.stub(); component.target = documentList; - let fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); + const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = [{ id: '1', name: 'Stark Industries' }]; triggerComponentChange(fakeNodeWithCreatePermissionInstance); diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts index a5ad0ebbb6..aab5f4dec0 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.ts @@ -41,7 +41,7 @@ export class DropdownBreadcrumbComponent extends BreadcrumbComponent implements * Calculate the current and previous nodes from the route array */ protected recalculateNodes(): void { - let node: Node = this.transform ? this.transform(this.folderNode) : this.folderNode; + const node: Node = this.transform ? this.transform(this.folderNode) : this.folderNode; this.route = this.parseRoute(node); this.currentNode = this.route[this.route.length - 1]; diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts index 4e6265c1dc..7c1f730fa1 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts @@ -28,7 +28,7 @@ describe('ContentMetadataCardComponent', () => { let component: ContentMetadataCardComponent; let fixture: ComponentFixture; let node: Node; - let preset = 'custom-preset'; + const preset = 'custom-preset'; setupTestBed({ imports: [ContentTestingModule] diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts index 64d6b78b9c..ac6bfd0dec 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -33,7 +33,7 @@ describe('ContentMetadataComponent', () => { let fixture: ComponentFixture; let node: Node; let folderNode: Node; - let preset = 'custom-preset'; + const preset = 'custom-preset'; setupTestBed({ imports: [ContentTestingModule], diff --git a/lib/content-services/content-metadata/services/config/layout-oriented-config.service.ts b/lib/content-services/content-metadata/services/config/layout-oriented-config.service.ts index 680135cb31..d9a867318e 100644 --- a/lib/content-services/content-metadata/services/config/layout-oriented-config.service.ts +++ b/lib/content-services/content-metadata/services/config/layout-oriented-config.service.ts @@ -37,7 +37,7 @@ export class LayoutOrientedConfigService implements ContentMetadataConfig { public reorganiseByConfig(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] { const layoutBlocks = this.config.filter((itemsGroup) => itemsGroup.items); - let organisedPropertyGroup = layoutBlocks.map((layoutBlock) => { + const organisedPropertyGroup = layoutBlocks.map((layoutBlock) => { const flattenedItems = this.flattenItems(layoutBlock.items), properties = flattenedItems.reduce((props, explodedItem) => { const property = getProperty(propertyGroups, explodedItem.groupName, explodedItem.propertyName) || []; @@ -82,7 +82,7 @@ export class LayoutOrientedConfigService implements ContentMetadataConfig { } public isIncludeAllEnabled() { - let includeAllProperty = this.config + const includeAllProperty = this.config .map((config) => config.includeAll) .find((includeAll) => includeAll !== undefined); diff --git a/lib/content-services/content-metadata/services/property-groups-translator.service.ts b/lib/content-services/content-metadata/services/property-groups-translator.service.ts index 8f35d7dcb4..2833552aba 100644 --- a/lib/content-services/content-metadata/services/property-groups-translator.service.ts +++ b/lib/content-services/content-metadata/services/property-groups-translator.service.ts @@ -73,7 +73,7 @@ export class PropertyGroupTranslatorService { const prefix = 'properties.'; - let propertyDefinition: CardViewItemProperties = { + const propertyDefinition: CardViewItemProperties = { label: property.title || property.name, value: propertyValue, key: `${prefix}${property.name}`, diff --git a/lib/content-services/content-node-selector/content-node-dialog.service.spec.ts b/lib/content-services/content-node-selector/content-node-dialog.service.spec.ts index c11321aaa9..95d14a43fb 100644 --- a/lib/content-services/content-node-selector/content-node-dialog.service.spec.ts +++ b/lib/content-services/content-node-selector/content-node-dialog.service.spec.ts @@ -71,7 +71,7 @@ describe('ContentNodeDialogService', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; service = TestBed.get(ContentNodeDialogService); diff --git a/lib/content-services/content-node-selector/content-node-dialog.service.ts b/lib/content-services/content-node-selector/content-node-dialog.service.ts index 5cc98ab687..b1ef6e41ce 100644 --- a/lib/content-services/content-node-selector/content-node-dialog.service.ts +++ b/lib/content-services/content-node-selector/content-node-dialog.service.ts @@ -151,7 +151,7 @@ export class ContentNodeDialogService { return select; } else { - let errors = new Error(JSON.stringify({ error: { statusCode: 403 } })); + const errors = new Error(JSON.stringify({ error: { statusCode: 403 } })); return throwError(errors); } } diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts b/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts index 693dddee91..06eaf1aed0 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.spec.ts @@ -60,7 +60,7 @@ describe('ContentNodeSelectorComponent', () => { let _observer: Observer; function typeToSearchBox(searchTerm = 'string-to-search') { - let searchInput = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-input"]')); + const searchInput = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-input"]')); searchInput.nativeElement.value = searchTerm; component.searchInput.setValue(searchTerm); fixture.detectChanges(); @@ -323,11 +323,11 @@ describe('ContentNodeSelectorComponent', () => { describe('Search functionality', () => { let getCorrespondingNodeIdsSpy; - let defaultSearchOptions = (searchTerm, rootNodeId = undefined, skipCount = 0) => { + const defaultSearchOptions = (searchTerm, rootNodeId = undefined, skipCount = 0) => { const parentFiltering = rootNodeId ? [{ query: `ANCESTOR:'workspace://SpacesStore/${rootNodeId}'` }] : []; - let defaultSearchNode: any = { + const defaultSearchNode: any = { query: { query: searchTerm ? `${searchTerm}* OR name:${searchTerm}*` : searchTerm }, @@ -507,8 +507,8 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); tick(debounceSearch); - let searchIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-icon"]')); - let clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]')); + const searchIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-icon"]')); + const clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]')); expect(searchIcon).not.toBeNull('Search icon should be in the DOM'); expect(clearIcon).toBeNull('Clear icon should NOT be in the DOM'); @@ -521,8 +521,8 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); - let searchIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-icon"]')); - let clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]')); + const searchIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-icon"]')); + const clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]')); expect(searchIcon).toBeNull('Search icon should NOT be in the DOM'); expect(clearIcon).not.toBeNull('Clear icon should be in the DOM'); @@ -602,13 +602,13 @@ describe('ContentNodeSelectorComponent', () => { })); it('should show the current folder\'s content instead of search results if search was not performed', () => { - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku'); }); it('should pass through the rowFilter to the documentList', () => { - let filter = (shareDataRow: ShareDataRow) => { + const filter = (shareDataRow: ShareDataRow) => { if (shareDataRow.node.entry.name === 'impossible-name') { return true; } @@ -618,7 +618,7 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.rowFilter({ node: { @@ -643,7 +643,7 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.rowFilter).toBeTruthy('Document list should have had a rowFilter'); @@ -658,7 +658,7 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.imageResolver).toBe(resolver); }); @@ -670,7 +670,7 @@ describe('ContentNodeSelectorComponent', () => { respondWithSearchResults(ONE_FOLDER_RESULT); fixture.detectChanges(); - let documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]')); + const documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]')); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.currentFolderId).toBeNull(); done(); @@ -700,12 +700,12 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let clearButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]')); + const clearButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]')); expect(clearButton).not.toBeNull('Clear button should be in DOM'); clearButton.triggerEventHandler('click', {}); fixture.detectChanges(); - let documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]')); + const documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]')); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku'); done(); @@ -726,7 +726,7 @@ describe('ContentNodeSelectorComponent', () => { fixture.detectChanges(); - let documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]')); + const documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]')); expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku'); })); diff --git a/lib/content-services/content-node-selector/content-node-selector.component.spec.ts b/lib/content-services/content-node-selector/content-node-selector.component.spec.ts index 75ede2ffe0..260d2a3edf 100644 --- a/lib/content-services/content-node-selector/content-node-selector.component.spec.ts +++ b/lib/content-services/content-node-selector/content-node-selector.component.spec.ts @@ -33,7 +33,7 @@ describe('ContentNodeSelectorDialogComponent', () => { let component: ContentNodeSelectorComponent; let fixture: ComponentFixture; - let data: any = { + const data: any = { title: 'Move along citizen...', actionName: 'move', select: new EventEmitter(), @@ -87,13 +87,13 @@ describe('ContentNodeSelectorDialogComponent', () => { }); it('should pass through the injected currentFolderId to the documentList', () => { - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku'); }); it('should pass through the injected rowFilter to the documentList', () => { - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.rowFilter({ node: { @@ -114,7 +114,7 @@ describe('ContentNodeSelectorDialogComponent', () => { }); it('should pass through the injected imageResolver to the documentList', () => { - let documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); + const documentList = fixture.debugElement.query(By.directive(DocumentListComponent)); expect(documentList).not.toBeNull('Document list should be shown'); expect(documentList.componentInstance.imageResolver).toBe(data.imageResolver); }); @@ -150,7 +150,7 @@ describe('ContentNodeSelectorDialogComponent', () => { it('should be disabled by default', () => { fixture.detectChanges(); - let actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]')); + const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]')); expect(actionButton.nativeElement.disabled).toBeTruthy(); }); @@ -158,7 +158,7 @@ describe('ContentNodeSelectorDialogComponent', () => { component.onSelect([new Node({ id: 'fake' })]); fixture.detectChanges(); - let actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]')); + const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]')); expect(actionButton.nativeElement.disabled).toBeFalsy(); }); diff --git a/lib/content-services/content-node-selector/content-node-selector.service.ts b/lib/content-services/content-node-selector/content-node-selector.service.ts index 147dd9b513..a725d6cf67 100644 --- a/lib/content-services/content-node-selector/content-node-selector.service.ts +++ b/lib/content-services/content-node-selector/content-node-selector.service.ts @@ -56,7 +56,7 @@ export class ContentNodeSelectorService { const parentFiltering = rootNodeId ? [{ query: `ANCESTOR:'workspace://SpacesStore/${rootNodeId}'${extraParentFiltering}` }] : []; - let defaultSearchNode: any = { + const defaultSearchNode: any = { query: { query: `${searchTerm}* OR name:${searchTerm}*` }, diff --git a/lib/content-services/content-node-share/content-node-share.dialog.spec.ts b/lib/content-services/content-node-share/content-node-share.dialog.spec.ts index 73b16865c6..3df697907e 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.spec.ts +++ b/lib/content-services/content-node-share/content-node-share.dialog.spec.ts @@ -34,7 +34,7 @@ import moment from 'moment-es6'; describe('ShareDialogComponent', () => { let node; let matDialog: MatDialog; - let notificationServiceMock = { + const notificationServiceMock = { openSnackMessage: jasmine.createSpy('openSnackMessage') }; let sharedLinksApiService: SharedLinksApiService; diff --git a/lib/content-services/dialogs/folder.dialog.spec.ts b/lib/content-services/dialogs/folder.dialog.spec.ts index 5676939a34..d68a05bdf7 100644 --- a/lib/content-services/dialogs/folder.dialog.spec.ts +++ b/lib/content-services/dialogs/folder.dialog.spec.ts @@ -29,7 +29,7 @@ describe('FolderDialogComponent', () => { let fixture: ComponentFixture; let component: FolderDialogComponent; let nodesApi: NodesApiService; - let dialogRef = { + const dialogRef = { close: jasmine.createSpy('close') }; diff --git a/lib/content-services/dialogs/folder.dialog.ts b/lib/content-services/dialogs/folder.dialog.ts index 1daddd116d..c1aeea14a5 100644 --- a/lib/content-services/dialogs/folder.dialog.ts +++ b/lib/content-services/dialogs/folder.dialog.ts @@ -99,13 +99,13 @@ export class FolderDialogComponent implements OnInit { } get name(): string { - let { name } = this.form.value; + const { name } = this.form.value; return (name || '').trim(); } get description(): string { - let { description } = this.form.value; + const { description } = this.form.value; return (description || '').trim(); } diff --git a/lib/content-services/dialogs/node-lock.dialog.spec.ts b/lib/content-services/dialogs/node-lock.dialog.spec.ts index 03548d0432..40fa07162c 100644 --- a/lib/content-services/dialogs/node-lock.dialog.spec.ts +++ b/lib/content-services/dialogs/node-lock.dialog.spec.ts @@ -83,7 +83,7 @@ describe('NodeLockDialogComponent', () => { }); it('should update form inputs', () => { - let newTime = moment(); + const newTime = moment(); component.form.controls['isLocked'].setValue(false); component.form.controls['allowOwner'].setValue(false); component.form.controls['isTimeLock'].setValue(false); diff --git a/lib/content-services/dialogs/node-lock.dialog.ts b/lib/content-services/dialogs/node-lock.dialog.ts index d5f2e0b375..fa4875ef3b 100644 --- a/lib/content-services/dialogs/node-lock.dialog.ts +++ b/lib/content-services/dialogs/node-lock.dialog.ts @@ -59,7 +59,7 @@ export class NodeLockDialogComponent implements OnInit { private get lockTimeInSeconds(): number { if (this.form.value.isTimeLock) { - let duration = moment.duration(moment(this.form.value.time).diff(moment())); + const duration = moment.duration(moment(this.form.value.time).diff(moment())); return duration.asSeconds(); } diff --git a/lib/content-services/document-list/components/content-action/content-action-list.component.spec.ts b/lib/content-services/document-list/components/content-action/content-action-list.component.spec.ts index e32c336012..fa130a5f0c 100644 --- a/lib/content-services/document-list/components/content-action/content-action-list.component.spec.ts +++ b/lib/content-services/document-list/components/content-action/content-action-list.component.spec.ts @@ -41,8 +41,8 @@ describe('ContentColumnList', () => { it('should register action', () => { spyOn(documentList.actions, 'push').and.callThrough(); - let action = new ContentActionModel(); - let result = actionList.registerAction(action); + const action = new ContentActionModel(); + const result = actionList.registerAction(action); expect(result).toBeTruthy(); expect(documentList.actions.push).toHaveBeenCalledWith(action); @@ -50,13 +50,13 @@ describe('ContentColumnList', () => { it('should require document list instance to register action', () => { actionList = new ContentActionListComponent(null); - let action = new ContentActionModel(); + const action = new ContentActionModel(); expect(actionList.registerAction(action)).toBeFalsy(); }); it('should require action instance to register', () => { spyOn(documentList.actions, 'push').and.callThrough(); - let result = actionList.registerAction(null); + const result = actionList.registerAction(null); expect(result).toBeFalsy(); expect(documentList.actions.push).not.toHaveBeenCalled(); diff --git a/lib/content-services/document-list/components/content-action/content-action.component.spec.ts b/lib/content-services/document-list/components/content-action/content-action.component.spec.ts index 9c35e0bd7f..91d47c6ba9 100644 --- a/lib/content-services/document-list/components/content-action/content-action.component.spec.ts +++ b/lib/content-services/document-list/components/content-action/content-action.component.spec.ts @@ -58,14 +58,14 @@ describe('ContentAction', () => { it('should register within parent actions list', () => { spyOn(actionList, 'registerAction').and.stub(); - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); action.ngOnInit(); expect(actionList.registerAction).toHaveBeenCalled(); }); it('should setup and register model', () => { - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); action.target = 'document'; action.title = ''; action.icon = '<icon>'; @@ -75,14 +75,14 @@ describe('ContentAction', () => { expect(documentList.actions.length).toBe(1); - let model = documentList.actions[0]; + const model = documentList.actions[0]; expect(model.target).toBe(action.target); expect(model.title).toBe(action.title); expect(model.icon).toBe(action.icon); }); it('should update visibility binding', () => { - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); action.target = 'document'; action.title = '<title>'; action.icon = '<icon>'; @@ -101,11 +101,11 @@ describe('ContentAction', () => { it('should get action handler from document actions service', () => { - let handler = function () { + const handler = function () { }; spyOn(documentActions, 'getHandler').and.returnValue(handler); - let action = new ContentActionComponent(actionList, documentActions, null); + const action = new ContentActionComponent(actionList, documentActions, null); action.target = 'document'; action.handler = '<handler>'; action.ngOnInit(); @@ -113,16 +113,16 @@ describe('ContentAction', () => { expect(documentActions.getHandler).toHaveBeenCalledWith(action.handler); expect(documentList.actions.length).toBe(1); - let model = documentList.actions[0]; + const model = documentList.actions[0]; expect(model.handler).toBe(handler); }); it('should get action handler from folder actions service', () => { - let handler = function () { + const handler = function () { }; spyOn(folderActions, 'getHandler').and.returnValue(handler); - let action = new ContentActionComponent(actionList, null, folderActions); + const action = new ContentActionComponent(actionList, null, folderActions); action.target = 'folder'; action.handler = '<handler>'; action.ngOnInit(); @@ -130,7 +130,7 @@ describe('ContentAction', () => { expect(folderActions.getHandler).toHaveBeenCalledWith(action.handler); expect(documentList.actions.length).toBe(1); - let model = documentList.actions[0]; + const model = documentList.actions[0]; expect(model.handler).toBe(handler); }); @@ -138,7 +138,7 @@ describe('ContentAction', () => { spyOn(folderActions, 'getHandler').and.stub(); spyOn(documentActions, 'getHandler').and.stub(); - let action = new ContentActionComponent(actionList, documentActions, folderActions); + const action = new ContentActionComponent(actionList, documentActions, folderActions); action.handler = '<handler>'; action.ngOnInit(); @@ -151,7 +151,7 @@ describe('ContentAction', () => { spyOn(folderActions, 'getHandler').and.stub(); spyOn(documentActions, 'getHandler').and.stub(); - let action = new ContentActionComponent(actionList, documentActions, folderActions); + const action = new ContentActionComponent(actionList, documentActions, folderActions); action.handler = '<handler>'; action.target = 'document'; @@ -165,7 +165,7 @@ describe('ContentAction', () => { spyOn(folderActions, 'getHandler').and.stub(); spyOn(documentActions, 'getHandler').and.stub(); - let action = new ContentActionComponent(actionList, documentActions, folderActions); + const action = new ContentActionComponent(actionList, documentActions, folderActions); action.handler = '<handler>'; action.target = 'folder'; @@ -178,7 +178,7 @@ describe('ContentAction', () => { it('should be case insensitive for document target', () => { spyOn(documentActions, 'getHandler').and.stub(); - let action = new ContentActionComponent(actionList, documentActions, null); + const action = new ContentActionComponent(actionList, documentActions, null); action.target = 'DoCuMeNt'; action.handler = '<handler>'; @@ -189,7 +189,7 @@ describe('ContentAction', () => { it('should be case insensitive for folder target', () => { spyOn(folderActions, 'getHandler').and.stub(); - let action = new ContentActionComponent(actionList, null, folderActions); + const action = new ContentActionComponent(actionList, null, folderActions); action.target = 'FoLdEr'; action.handler = '<handler>'; @@ -198,46 +198,46 @@ describe('ContentAction', () => { }); it('should use custom "execute" emitter', (done) => { - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); emitter.subscribe((e) => { expect(e.value).toBe('<obj>'); done(); }); - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); action.target = 'document'; action.execute = emitter; action.ngOnInit(); expect(documentList.actions.length).toBe(1); - let model = documentList.actions[0]; + const model = documentList.actions[0]; model.execute('<obj>'); }); it('should not find document action handler with missing service', () => { - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); expect(action.getSystemHandler('document', 'name')).toBeNull(); }); it('should not find folder action handler with missing service', () => { - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); expect(action.getSystemHandler('folder', 'name')).toBeNull(); }); it('should find document action handler via service', () => { - let handler = <ContentActionHandler> function (obj: any, target?: any) { + const handler = <ContentActionHandler> function (obj: any, target?: any) { }; - let action = new ContentActionComponent(actionList, documentActions, null); + const action = new ContentActionComponent(actionList, documentActions, null); spyOn(documentActions, 'getHandler').and.returnValue(handler); expect(action.getSystemHandler('document', 'name')).toBe(handler); }); it('should find folder action handler via service', () => { - let handler = <ContentActionHandler> function (obj: any, target?: any) { + const handler = <ContentActionHandler> function (obj: any, target?: any) { }; - let action = new ContentActionComponent(actionList, null, folderActions); + const action = new ContentActionComponent(actionList, null, folderActions); spyOn(folderActions, 'getHandler').and.returnValue(handler); expect(action.getSystemHandler('folder', 'name')).toBe(handler); }); @@ -246,7 +246,7 @@ describe('ContentAction', () => { spyOn(folderActions, 'getHandler').and.stub(); spyOn(documentActions, 'getHandler').and.stub(); - let action = new ContentActionComponent(actionList, documentActions, folderActions); + const action = new ContentActionComponent(actionList, documentActions, folderActions); expect(action.getSystemHandler('unknown', 'name')).toBeNull(); expect(folderActions.getHandler).not.toHaveBeenCalled(); @@ -255,10 +255,10 @@ describe('ContentAction', () => { }); it('should wire model with custom event handler', async(() => { - let action = new ContentActionComponent(actionList, documentActions, folderActions); - let file = new FileNode(); + const action = new ContentActionComponent(actionList, documentActions, folderActions); + const file = new FileNode(); - let handler = new EventEmitter(); + const handler = new EventEmitter(); handler.subscribe((e) => { expect(e.value).toBe(file); }); @@ -270,7 +270,7 @@ describe('ContentAction', () => { })); it('should allow registering model without handler', () => { - let action = new ContentActionComponent(actionList, documentActions, folderActions); + const action = new ContentActionComponent(actionList, documentActions, folderActions); spyOn(actionList, 'registerAction').and.callThrough(); action.execute = null; @@ -282,7 +282,7 @@ describe('ContentAction', () => { }); it('should register on init', () => { - let action = new ContentActionComponent(actionList, null, null); + const action = new ContentActionComponent(actionList, null, null); spyOn(action, 'register').and.callThrough(); action.ngOnInit(); diff --git a/lib/content-services/document-list/components/content-column/content-column-list.component.spec.ts b/lib/content-services/document-list/components/content-column/content-column-list.component.spec.ts index fad9274365..80babccd6b 100644 --- a/lib/content-services/document-list/components/content-column/content-column-list.component.spec.ts +++ b/lib/content-services/document-list/components/content-column/content-column-list.component.spec.ts @@ -43,11 +43,11 @@ describe('ContentColumnList', () => { }); it('should register column within parent document list', () => { - let columns = documentList.data.getColumns(); + const columns = documentList.data.getColumns(); expect(columns.length).toBe(0); - let column = <DataColumn> {}; - let result = columnList.registerColumn(column); + const column = <DataColumn> {}; + const result = columnList.registerColumn(column); expect(result).toBeTruthy(); expect(columns.length).toBe(1); @@ -56,13 +56,13 @@ describe('ContentColumnList', () => { it('should require document list instance to register action', () => { columnList = new ContentColumnListComponent(null, logService); - let col = <DataColumn> {}; + const col = <DataColumn> {}; expect(columnList.registerColumn(col)).toBeFalsy(); }); it('should require action instance to register', () => { spyOn(documentList.actions, 'push').and.callThrough(); - let result = columnList.registerColumn(null); + const result = columnList.registerColumn(null); expect(result).toBeFalsy(); expect(documentList.actions.push).not.toHaveBeenCalled(); diff --git a/lib/content-services/document-list/components/content-column/content-column-list.component.ts b/lib/content-services/document-list/components/content-column/content-column-list.component.ts index 98894c2605..b1bc665692 100644 --- a/lib/content-services/document-list/components/content-column/content-column-list.component.ts +++ b/lib/content-services/document-list/components/content-column/content-column-list.component.ts @@ -39,7 +39,7 @@ export class ContentColumnListComponent { */ registerColumn(column: DataColumn): boolean { if (this.documentList && column) { - let columns = this.documentList.data.getColumns(); + const columns = this.documentList.data.getColumns(); columns.push(column); return true; } diff --git a/lib/content-services/document-list/components/content-column/content-column.component.spec.ts b/lib/content-services/document-list/components/content-column/content-column.component.spec.ts index 14f8100a4e..d657efd697 100644 --- a/lib/content-services/document-list/components/content-column/content-column.component.spec.ts +++ b/lib/content-services/document-list/components/content-column/content-column.component.spec.ts @@ -45,18 +45,18 @@ describe('ContentColumn', () => { it('should register model within parent column list', () => { spyOn(columnList, 'registerColumn').and.callThrough(); - let column = new ContentColumnComponent(columnList, logService); + const column = new ContentColumnComponent(columnList, logService); column.ngAfterContentInit(); expect(columnList.registerColumn).toHaveBeenCalled(); - let columns = documentList.data.getColumns(); + const columns = documentList.data.getColumns(); expect(columns.length).toBe(1); expect(columns[0]).toBe(column); }); it('should setup screen reader title for thumbnail column', () => { - let column = new ContentColumnComponent(columnList, logService); + const column = new ContentColumnComponent(columnList, logService); column.key = '$thumbnail'; column.ngOnInit(); @@ -64,7 +64,7 @@ describe('ContentColumn', () => { }); it('should register on init', () => { - let column = new ContentColumnComponent(columnList, logService); + const column = new ContentColumnComponent(columnList, logService); spyOn(column, 'register').and.callThrough(); column.ngAfterContentInit(); diff --git a/lib/content-services/document-list/components/document-list.component.spec.ts b/lib/content-services/document-list/components/document-list.component.spec.ts index 6a6989a9db..a563bbcd20 100644 --- a/lib/content-services/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/document-list/components/document-list.component.spec.ts @@ -107,7 +107,7 @@ describe('DocumentList', () => { it('should add the custom columns', () => { fixture.detectChanges(); - let column = <DataColumn> { + const column = <DataColumn> { title: 'title', key: 'source', cssClass: 'css', @@ -116,7 +116,7 @@ describe('DocumentList', () => { format: '' }; - let columns = documentList.data.getColumns(); + const columns = documentList.data.getColumns(); columns.push(column); documentList.ngAfterContentInit(); @@ -125,8 +125,8 @@ describe('DocumentList', () => { }); it('should call action\'s handler with node', () => { - let node = new FileNode(); - let action = new ContentActionModel(); + const node = new FileNode(); + const action = new ContentActionModel(); action.handler = () => { }; @@ -138,8 +138,8 @@ describe('DocumentList', () => { }); it('should call action\'s handler with node and permission', () => { - let node = new FileNode(); - let action = new ContentActionModel(); + const node = new FileNode(); + const action = new ContentActionModel(); action.handler = () => { }; action.permission = 'fake-permission'; @@ -151,8 +151,8 @@ describe('DocumentList', () => { }); it('should call action\'s execute with node if it is defined', () => { - let node = new FileNode(); - let action = new ContentActionModel(); + const node = new FileNode(); + const action = new ContentActionModel(); action.execute = () => { }; spyOn(action, 'execute').and.stub(); @@ -164,8 +164,8 @@ describe('DocumentList', () => { it('should call action\'s execute only after the handler has been executed', () => { const deleteObservable: Subject<any> = new Subject<any>(); - let node = new FileNode(); - let action = new ContentActionModel(); + const node = new FileNode(); + const action = new ContentActionModel(); action.handler = () => deleteObservable; action.execute = () => { }; @@ -260,7 +260,7 @@ describe('DocumentList', () => { }); it('should not execute action without node provided', () => { - let action = new ContentActionModel(); + const action = new ContentActionModel(); action.handler = function () { }; @@ -270,15 +270,15 @@ describe('DocumentList', () => { }); it('should not give node actions for empty target', () => { - let actions = documentList.getNodeActions(null); + const actions = documentList.getNodeActions(null); expect(actions.length).toBe(0); }); it('should filter content actions for various targets', () => { - let folderMenu = new ContentActionModel(); + const folderMenu = new ContentActionModel(); folderMenu.target = 'folder'; - let documentMenu = new ContentActionModel(); + const documentMenu = new ContentActionModel(); documentMenu.target = 'document'; documentList.actions = [ @@ -297,7 +297,7 @@ describe('DocumentList', () => { it('should disable the action if there is no permission for the file and disableWithNoPermission true', () => { documentList.currentFolderId = 'fake-node-id'; - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ disableWithNoPermission: true, permission: 'delete', target: 'document', @@ -308,9 +308,9 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + const nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBe(true); @@ -382,7 +382,7 @@ describe('DocumentList', () => { }); it('should not disable the action if there is copy permission', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ disableWithNoPermission: true, permission: 'copy', target: 'document', @@ -393,9 +393,9 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + const nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeFalsy(); @@ -403,7 +403,7 @@ describe('DocumentList', () => { }); it('should disable the action if there is no permission for the folder and disableWithNoPermission true', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ disableWithNoPermission: true, permission: 'delete', target: 'folder', @@ -414,9 +414,9 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; + const nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update'] } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FolderAction'); expect(actions[0].disabled).toBe(true); @@ -424,7 +424,7 @@ describe('DocumentList', () => { }); it('should not disable the action if there is the right permission for the file', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ disableWithNoPermission: true, permission: 'delete', target: 'document', @@ -435,16 +435,16 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } }; + const nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeFalsy(); }); it('should not disable the action if there is the right permission for the folder', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ disableWithNoPermission: true, permission: 'delete', target: 'folder', @@ -455,16 +455,16 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } }; + const nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FolderAction'); expect(actions[0].disabled).toBeFalsy(); }); it('should not disable the action if there are no permissions for the file and disable with no permission is false', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'document', title: 'FileAction', @@ -475,16 +475,16 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: null } }; + const nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: null } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeFalsy(); }); it('should not disable the action if there are no permissions for the folder and disable with no permission is false', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'folder', title: 'FolderAction', @@ -495,16 +495,16 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: null } }; + const nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: null } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FolderAction'); expect(actions[0].disabled).toBeFalsy(); }); it('should disable the action if there are no permissions for the file and disable with no permission is true', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'document', title: 'FileAction', @@ -515,9 +515,9 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: null } }; + const nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: null } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeDefined(); @@ -525,7 +525,7 @@ describe('DocumentList', () => { }); it('should disable the action if there are no permissions for the folder and disable with no permission is true', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'folder', title: 'FolderAction', @@ -536,9 +536,9 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: null } }; + const nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: null } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FolderAction'); expect(actions[0].disabled).toBeDefined(); @@ -546,7 +546,7 @@ describe('DocumentList', () => { }); it('should find no content actions', () => { - let documentButton = new ContentActionModel(); + const documentButton = new ContentActionModel(); documentButton.target = 'document'; documentList.actions = [documentButton]; @@ -560,8 +560,8 @@ describe('DocumentList', () => { }); it('should emit nodeClick event', (done) => { - let node = new FileNode(); - let disposableClick = documentList.nodeClick.subscribe((e) => { + const node = new FileNode(); + const disposableClick = documentList.nodeClick.subscribe((e) => { expect(e.value).toBe(node); disposableClick.unsubscribe(); done(); @@ -570,7 +570,7 @@ describe('DocumentList', () => { }); it('should display folder content on click', () => { - let node = new FolderNode('<display name>'); + const node = new FolderNode('<display name>'); spyOn(documentList, 'loadFolder').and.returnValue(Promise.resolve(true)); @@ -593,7 +593,7 @@ describe('DocumentList', () => { expect(documentList.navigate).toBe(true); spyOn(documentList, 'loadFolder').and.stub(); - let node = new FileNode(); + const node = new FileNode(); documentList.onNodeClick(node); expect(documentList.loadFolder).not.toHaveBeenCalled(); @@ -602,7 +602,7 @@ describe('DocumentList', () => { it('should not display folder content on click when navigation is off', () => { spyOn(documentList, 'loadFolder').and.stub(); - let node = new FolderNode('<display name>'); + const node = new FolderNode('<display name>'); documentList.navigate = false; documentList.onNodeClick(node); @@ -610,7 +610,7 @@ describe('DocumentList', () => { }); it('should execute context action on callback', () => { - let action = { + const action = { node: {}, model: {} }; @@ -629,7 +629,7 @@ describe('DocumentList', () => { it('should subscribe to context action handler', () => { spyOn(documentList, 'loadFolder').and.stub(); spyOn(documentList, 'contextActionCallback').and.stub(); - let value = {}; + const value = {}; documentList.ngOnInit(); documentList.contextActionHandler.next(value); expect(documentList.contextActionCallback).toHaveBeenCalledWith(value); @@ -650,8 +650,8 @@ describe('DocumentList', () => { }); it('should emit file preview event on single click', (done) => { - let file = new FileNode(); - let disposablePreview = documentList.preview.subscribe((e) => { + const file = new FileNode(); + const disposablePreview = documentList.preview.subscribe((e) => { expect(e.value).toBe(file); disposablePreview.unsubscribe(); done(); @@ -661,8 +661,8 @@ describe('DocumentList', () => { }); it('should emit file preview event on double click', (done) => { - let file = new FileNode(); - let disposablePreview = documentList.preview.subscribe((e) => { + const file = new FileNode(); + const disposablePreview = documentList.preview.subscribe((e) => { expect(e.value).toBe(file); disposablePreview.unsubscribe(); done(); @@ -672,7 +672,7 @@ describe('DocumentList', () => { }); it('should perform folder navigation on single click', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; @@ -681,7 +681,7 @@ describe('DocumentList', () => { }); it('should perform folder navigation on double click', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.DOUBLE_CLICK_NAVIGATION; @@ -690,7 +690,7 @@ describe('DocumentList', () => { }); it('should not perform folder navigation on double click when single mode', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); spyOn(documentList, 'navigateTo').and.stub(); documentList.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; @@ -700,7 +700,7 @@ describe('DocumentList', () => { }); it('should not perform folder navigation on double click when navigation off', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); spyOn(documentList, 'navigateTo').and.stub(); documentList.navigate = false; @@ -711,8 +711,8 @@ describe('DocumentList', () => { }); it('should perform navigation for folder node only', () => { - let folder = new FolderNode(); - let file = new FileNode(); + const folder = new FolderNode(); + const file = new FileNode(); spyOn(documentList, 'loadFolder').and.stub(); @@ -722,7 +722,7 @@ describe('DocumentList', () => { }); it('should perform navigation through corret linked folder', () => { - let linkFolder = new FolderNode(); + const linkFolder = new FolderNode(); linkFolder.entry.id = 'link-folder'; linkFolder.entry.nodeType = 'app:folderlink'; linkFolder.entry.properties['cm:destination'] = 'normal-folder'; @@ -734,7 +734,7 @@ describe('DocumentList', () => { }); it('should require valid node for file preview', () => { - let file = new FileNode(); + const file = new FileNode(); file.entry = null; let called = false; @@ -750,7 +750,7 @@ describe('DocumentList', () => { }); it('should require valid node for folder navigation', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); folder.entry = null; spyOn(documentList, 'navigateTo').and.stub(); @@ -781,18 +781,18 @@ describe('DocumentList', () => { it('should require node to resolve context menu actions', () => { expect(documentList.getContextActions(null)).toBeNull(); - let file = new FileNode(); + const file = new FileNode(); file.entry = null; expect(documentList.getContextActions(file)).toBeNull(); }); it('should fetch context menu actions for a file node', () => { - let actionModel: any = {}; + const actionModel: any = {}; spyOn(documentList, 'getNodeActions').and.returnValue([actionModel]); - let file = new FileNode(); - let actions = documentList.getContextActions(file); + const file = new FileNode(); + const actions = documentList.getContextActions(file); expect(documentList.getNodeActions).toHaveBeenCalledWith(file); expect(actions.length).toBe(1); @@ -802,11 +802,11 @@ describe('DocumentList', () => { }); it('should fetch context menu actions for a folder node', () => { - let actionModel: any = {}; + const actionModel: any = {}; spyOn(documentList, 'getNodeActions').and.returnValue([actionModel]); - let folder = new FolderNode(); - let actions = documentList.getContextActions(folder); + const folder = new FolderNode(); + const actions = documentList.getContextActions(folder); expect(documentList.getNodeActions).toHaveBeenCalledWith(folder); expect(actions.length).toBe(1); @@ -818,19 +818,19 @@ describe('DocumentList', () => { it('should fetch no context menu actions for unknown type', () => { spyOn(documentList, 'getNodeActions').and.stub(); - let node = new FileNode(); + const node = new FileNode(); node.entry.isFile = false; node.entry.isFolder = false; - let actions = documentList.getContextActions(node); + const actions = documentList.getContextActions(node); expect(actions).toBeNull(); }); it('should return null value when no content actions found', () => { spyOn(documentList, 'getNodeActions').and.returnValue([]); - let file = new FileNode(); - let actions = documentList.getContextActions(file); + const file = new FileNode(); + const actions = documentList.getContextActions(file); expect(actions).toBeNull(); expect(documentList.getNodeActions).toHaveBeenCalled(); @@ -872,7 +872,7 @@ describe('DocumentList', () => { it('should set row filter and reload contents if currentFolderId is set when setting rowFilter', () => { fixture.detectChanges(); - let filter = <RowFilter> {}; + const filter = <RowFilter> {}; documentList.currentFolderId = 'id'; spyOn(documentList.data, 'setFilter').and.callThrough(); spyOn(documentListService, 'getFolder').and.callThrough(); @@ -894,7 +894,7 @@ describe('DocumentList', () => { it('should set image resolver for underlying adapter', () => { fixture.detectChanges(); - let resolver = <ImageResolver> {}; + const resolver = <ImageResolver> {}; spyOn(documentList.data, 'setImageResolver').and.callThrough(); documentList.ngOnChanges({ imageResolver: new SimpleChange(null, resolver, true) }); @@ -903,7 +903,7 @@ describe('DocumentList', () => { }); it('should emit [nodeClick] event on row click', () => { - let node = new NodeMinimalEntry(); + const node = new NodeMinimalEntry(); spyOn(documentList, 'onNodeClick').and.callThrough(); documentList.onNodeClick(node); @@ -911,7 +911,7 @@ describe('DocumentList', () => { }); it('should emit node-click DOM event', (done) => { - let node = new NodeMinimalEntry(); + const node = new NodeMinimalEntry(); document.addEventListener('node-click', (customEvent: CustomEvent) => { done(); @@ -921,7 +921,7 @@ describe('DocumentList', () => { }); it('should emit [nodeDblClick] event on row double-click', () => { - let node = new NodeMinimalEntry(); + const node = new NodeMinimalEntry(); spyOn(documentList, 'onNodeDblClick').and.callThrough(); documentList.onNodeDblClick(node); @@ -929,7 +929,7 @@ describe('DocumentList', () => { }); it('should emit node-dblclick DOM event', (done) => { - let node = new NodeMinimalEntry(); + const node = new NodeMinimalEntry(); document.addEventListener('node-dblclick', (customEvent: CustomEvent) => { done(); @@ -952,7 +952,7 @@ describe('DocumentList', () => { const error = { message: '{ "error": { "statusCode": 501 } }' }; spyOn(documentListService, 'getFolder').and.returnValue(throwError(error)); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe(error); disposableError.unsubscribe(); done(); @@ -975,7 +975,7 @@ describe('DocumentList', () => { const error = { message: '{ "error": { "statusCode": 403 } }' }; spyOn(documentListService, 'getFolder').and.returnValue(throwError(error)); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe(error); expect(documentList.noPermission).toBe(true); disposableError.unsubscribe(); @@ -1020,7 +1020,7 @@ describe('DocumentList', () => { spyOn(documentListService, 'getFolder').and.returnValue(throwError(error)); documentList.loadFolder(); - let clickedFolderNode = new FolderNode('fake-folder-node'); + const clickedFolderNode = new FolderNode('fake-folder-node'); documentList.onNodeDblClick(clickedFolderNode); expect(documentList.noPermission).toBeTruthy(); @@ -1049,7 +1049,7 @@ describe('DocumentList', () => { it('should emit error when fetch trashcan fails', (done) => { spyOn(apiService.nodesApi, 'getDeletedNodes').and.returnValue(Promise.reject('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1070,7 +1070,7 @@ describe('DocumentList', () => { spyOn(apiService.getInstance().core.sharedlinksApi, 'findSharedLinks') .and.returnValue(Promise.reject('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1089,7 +1089,7 @@ describe('DocumentList', () => { it('should emit error when fetch sites fails', (done) => { spyGetSites.and.returnValue(Promise.reject('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1101,7 +1101,7 @@ describe('DocumentList', () => { it('should assure that sites have name property set', (done) => { fixture.detectChanges(); - let disposableReady = documentList.ready.subscribe((page) => { + const disposableReady = documentList.ready.subscribe((page) => { const entriesWithoutName = page.list.entries.filter((item) => !item.entry.name); expect(entriesWithoutName.length).toBe(0); disposableReady.unsubscribe(); @@ -1114,7 +1114,7 @@ describe('DocumentList', () => { it('should assure that sites have name property set correctly', (done) => { fixture.detectChanges(); - let disposableReady = documentList.ready.subscribe((page) => { + const disposableReady = documentList.ready.subscribe((page) => { const wrongName = page.list.entries.filter((item) => (item.entry.name !== item.entry.title)); expect(wrongName.length).toBe(0); disposableReady.unsubscribe(); @@ -1136,7 +1136,7 @@ describe('DocumentList', () => { spyOn(apiService.getInstance().core.peopleApi, 'listSiteMembershipsForPerson') .and.returnValue(Promise.reject('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1153,7 +1153,7 @@ describe('DocumentList', () => { documentList.loadFolderByNodeId('-mysites-'); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); - let disposableReady = documentList.ready.subscribe((page) => { + const disposableReady = documentList.ready.subscribe((page) => { const entriesWithoutName = page.list.entries.filter((item) => !item.entry.name); expect(entriesWithoutName.length).toBe(0); disposableReady.unsubscribe(); @@ -1169,7 +1169,7 @@ describe('DocumentList', () => { documentList.loadFolderByNodeId('-mysites-'); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); - let disposableReady = documentList.ready.subscribe((page) => { + const disposableReady = documentList.ready.subscribe((page) => { const wrongName = page.list.entries.filter((item) => (item.entry.name !== item.entry.title)); expect(wrongName.length).toBe(0); disposableReady.unsubscribe(); @@ -1188,7 +1188,7 @@ describe('DocumentList', () => { it('should emit error when fetch favorites fails', (done) => { spyFavorite.and.returnValue(Promise.reject('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1200,7 +1200,7 @@ describe('DocumentList', () => { it('should fetch recent', () => { const person = { entry: { id: 'person ' } }; - let getPersonSpy = spyOn(apiService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(person)); + const getPersonSpy = spyOn(apiService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(person)); documentList.loadFolderByNodeId('-recent-'); @@ -1210,7 +1210,7 @@ describe('DocumentList', () => { it('should emit error when fetch recent fails on getPerson call', (done) => { spyOn(apiService.peopleApi, 'getPerson').and.returnValue(Promise.reject('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1222,7 +1222,7 @@ describe('DocumentList', () => { it('should emit error when fetch recent fails on search call', (done) => { spyOn(customResourcesService, 'loadFolderByNodeId').and.returnValue(throwError('error')); - let disposableError = documentList.error.subscribe((val) => { + const disposableError = documentList.error.subscribe((val) => { expect(val).toBe('error'); disposableError.unsubscribe(); done(); @@ -1297,7 +1297,7 @@ describe('DocumentList', () => { }); it('should reset the pagination when enter in a new folder', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); documentList.navigationMode = DocumentListComponent.SINGLE_CLICK_NAVIGATION; documentList.updatePagination({ maxItems: 10, diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index 41dd8ee3d3..35f23419e6 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -334,7 +334,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte getContextActions(node: NodeEntry) { if (node && node.entry) { - let actions = this.getNodeActions(node); + const actions = this.getNodeActions(node); if (actions && actions.length > 0) { return actions.map((currentAction: ContentActionModel) => { return { @@ -419,7 +419,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.data.setColumns(schema); } - let columns = this.data.getColumns(); + const columns = this.data.getColumns(); if (!columns || columns.length === 0) { this.setupDefaultColumns(this._currentFolderId); } @@ -445,7 +445,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte if (this.data) { if (changes.node && changes.node.currentValue) { - let merge = this._pagination ? this._pagination.merge : false; + const merge = this._pagination ? this._pagination.merge : false; this.data.loadPage(changes.node.currentValue, merge); this.onDataReady(changes.node.currentValue); @@ -492,7 +492,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte return actions; } - let actionsByTarget = this.actions + const actionsByTarget = this.actions .filter((entry) => { const isVisible = (typeof entry.visible === 'function') ? entry.visible(node) @@ -653,7 +653,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } getSourceNodeWithPath(nodeId: string): Observable<NodeEntry> { - let getSourceObservable = this.documentListService.getFolderNode(nodeId, this.includeFields); + const getSourceObservable = this.documentListService.getFolderNode(nodeId, this.includeFields); getSourceObservable.subscribe((nodeEntry: NodeEntry) => { this.folderNode = nodeEntry.entry; @@ -784,8 +784,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte onShowRowContextMenu(event: DataCellEvent) { if (this.contextMenuActions) { - let args = event.value; - let node = (<ShareDataRow> args.row).node; + const args = event.value; + const node = (<ShareDataRow> args.row).node; if (node) { args.actions = this.getContextActions(node) || []; } @@ -794,8 +794,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte onShowRowActionsMenu(event: DataCellEvent) { if (this.contentActions) { - let args = event.value; - let node = (<ShareDataRow> args.row).node; + const args = event.value; + const node = (<ShareDataRow> args.row).node; if (node) { args.actions = this.getNodeActions(node) || []; } @@ -804,9 +804,9 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte onExecuteRowAction(event: DataRowActionEvent) { if (this.contentActions) { - let args = event.value; - let node = (<ShareDataRow> args.row).node; - let action = (<ContentActionModel> args.action); + const args = event.value; + const node = (<ShareDataRow> args.row).node; + const action = (<ContentActionModel> args.action); this.executeContentAction(node, action); } } diff --git a/lib/content-services/document-list/data/share-datatable-adapter.spec.ts b/lib/content-services/document-list/data/share-datatable-adapter.spec.ts index 125b8c0fef..40cf06bfd2 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.spec.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.spec.ts @@ -27,7 +27,7 @@ describe('ShareDataTableAdapter', () => { let contentService: ContentService; beforeEach(() => { - let imageUrl: string = 'http://<addresss>'; + const imageUrl: string = 'http://<addresss>'; contentService = new ContentService(null, null, null, null); documentListService = new DocumentListService(null, contentService, null, null, null); spyOn(documentListService, 'getDocumentThumbnailUrl').and.returnValue(imageUrl); @@ -59,8 +59,8 @@ describe('ShareDataTableAdapter', () => { }); it('should setup rows and columns with constructor', () => { - let schema = [<DataColumn> {}]; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, schema); + const schema = [<DataColumn> {}]; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, schema); expect(adapter.getRows()).toEqual([]); expect(adapter.getColumns()).toEqual(schema); @@ -72,15 +72,15 @@ describe('ShareDataTableAdapter', () => { }); it('should set new columns', () => { - let columns = [<DataColumn> {}, <DataColumn> {}]; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const columns = [<DataColumn> {}, <DataColumn> {}]; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); adapter.setColumns(columns); expect(adapter.getColumns()).toEqual(columns); }); it('should reset columns', () => { - let columns = [<DataColumn> {}, <DataColumn> {}]; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, columns); + const columns = [<DataColumn> {}, <DataColumn> {}]; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, columns); expect(adapter.getColumns()).toEqual(columns); adapter.setColumns(null); @@ -88,8 +88,8 @@ describe('ShareDataTableAdapter', () => { }); it('should set new rows', () => { - let rows = [<DataRow> {}, <DataRow> {}]; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const rows = [<DataRow> {}, <DataRow> {}]; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); expect(adapter.getRows()).toEqual([]); adapter.setRows(rows); @@ -97,8 +97,8 @@ describe('ShareDataTableAdapter', () => { }); it('should reset rows', () => { - let rows = [<DataRow> {}, <DataRow> {}]; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const rows = [<DataRow> {}, <DataRow> {}]; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); adapter.setRows(rows); expect(adapter.getRows()).toEqual(rows); @@ -108,61 +108,61 @@ describe('ShareDataTableAdapter', () => { }); it('should sort new rows', () => { - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); spyOn(adapter, 'sort').and.callThrough(); - let rows = [<DataRow> {}]; + const rows = [<DataRow> {}]; adapter.setRows(rows); expect(adapter.sort).toHaveBeenCalled(); }); it('should fail when getting value for missing row', () => { - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let check = () => { + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const check = () => { return adapter.getValue(null, <DataColumn> {}); }; expect(check).toThrowError(adapter.ERR_ROW_NOT_FOUND); }); it('should fail when getting value for missing column', () => { - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let check = () => { + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const check = () => { return adapter.getValue(<DataRow> {}, null); }; expect(check).toThrowError(adapter.ERR_COL_NOT_FOUND); }); it('should return date value as string', () => { - let rawValue = new Date(2015, 6, 15, 21, 43, 11); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST); + const rawValue = new Date(2015, 6, 15, 21, 43, 11); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST); - let file = new FileNode(); + const file = new FileNode(); file.entry.createdAt = rawValue; - let col = <DataColumn> { + const col = <DataColumn> { key: 'createdAt', type: 'string' }; - let row = new ShareDataRow(file, contentService, null); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const row = new ShareDataRow(file, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toBe(rawValue); }); it('should generate fallback icon for a file thumbnail with missing mime type', () => { spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let file = new FileNode(); + const file = new FileNode(); file.entry.content.mimeType = null; - let row = new ShareDataRow(file, contentService, null); - let col = <DataColumn> { type: 'image', key: '$thumbnail' }; + const row = new ShareDataRow(file, contentService, null); + const col = <DataColumn> { type: 'image', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_miscellaneous`); expect(value).toContain(`svg`); }); @@ -170,42 +170,42 @@ describe('ShareDataTableAdapter', () => { it('should generate fallback icon for a file with no content entry', () => { spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let file = new FileNode(); + const file = new FileNode(); file.entry.content = null; - let row = new ShareDataRow(file, contentService, null); - let col = <DataColumn> { type: 'image', key: '$thumbnail' }; + const row = new ShareDataRow(file, contentService, null); + const col = <DataColumn> { type: 'image', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_miscellaneous`); expect(value).toContain(`svg`); }); it('should return image value unmodified', () => { - let imageUrl = 'http://<address>'; + const imageUrl = 'http://<address>'; - let file = new FileNode(); + const file = new FileNode(); file.entry['icon'] = imageUrl; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let row = new ShareDataRow(file, contentService, null); - let col = <DataColumn> { type: 'image', key: 'icon' }; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const row = new ShareDataRow(file, contentService, null); + const col = <DataColumn> { type: 'image', key: 'icon' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toBe(imageUrl); }); it('should resolve folder icon', () => { spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let row = new ShareDataRow(new FolderNode(), contentService, null); - let col = <DataColumn> { type: 'image', key: '$thumbnail' }; + const row = new ShareDataRow(new FolderNode(), contentService, null); + const col = <DataColumn> { type: 'image', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_folder`); expect(value).toContain(`svg`); }); @@ -213,12 +213,12 @@ describe('ShareDataTableAdapter', () => { it('should resolve smart folder icon', () => { spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_smart_folder.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let row = new ShareDataRow(new SmartFolderNode(), contentService, null); - let col = <DataColumn> { type: 'folder', key: '$thumbnail' }; + const row = new ShareDataRow(new SmartFolderNode(), contentService, null); + const col = <DataColumn> { type: 'folder', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_smart_folder`); expect(value).toContain(`svg`); }); @@ -226,12 +226,12 @@ describe('ShareDataTableAdapter', () => { it('should resolve link folder icon', () => { spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_shortcut_link.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let row = new ShareDataRow(new LinkFolderNode(), contentService, null); - let col = <DataColumn> { type: 'folder', key: '$thumbnail' }; + const row = new ShareDataRow(new LinkFolderNode(), contentService, null); + const col = <DataColumn> { type: 'folder', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_folder_shortcut_link`); expect(value).toContain(`svg`); }); @@ -239,26 +239,26 @@ describe('ShareDataTableAdapter', () => { it('should resolve rule folder icon', () => { spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_rule.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let row = new ShareDataRow(new RuleFolderNode(), contentService, null); - let col = <DataColumn> { type: 'folder', key: '$thumbnail' }; + const row = new ShareDataRow(new RuleFolderNode(), contentService, null); + const col = <DataColumn> { type: 'folder', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_folder_rule`); expect(value).toContain(`svg`); }); it('should resolve file thumbnail', () => { - let imageUrl = 'http://<addresss>'; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const imageUrl = 'http://<addresss>'; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); adapter.thumbnails = true; - let file = new FileNode(); - let row = new ShareDataRow(file, contentService, null); - let col = <DataColumn> { type: 'image', key: '$thumbnail' }; + const file = new FileNode(); + const row = new ShareDataRow(file, contentService, null); + const col = <DataColumn> { type: 'image', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toBe(imageUrl); expect(documentListService.getDocumentThumbnailUrl).toHaveBeenCalledWith(file); }); @@ -266,45 +266,45 @@ describe('ShareDataTableAdapter', () => { it('should resolve fallback file icon for unknown node', () => { spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let file = new FileNode(); + const file = new FileNode(); file.entry.isFile = false; file.entry.isFolder = false; file.entry.content = null; - let row = new ShareDataRow(file, contentService, null); - let col = <DataColumn> { type: 'image', key: '$thumbnail' }; + const row = new ShareDataRow(file, contentService, null); + const col = <DataColumn> { type: 'image', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_miscellaneous`); expect(value).toContain(`svg`); }); it('should resolve file icon for content type', () => { spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_raster_image.svg`); - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); - let file = new FileNode(); + const file = new FileNode(); file.entry.isFile = false; file.entry.isFolder = false; file.entry.content.mimeType = 'image/png'; - let row = new ShareDataRow(file, contentService, null); - let col = <DataColumn> { type: 'image', key: '$thumbnail' }; + const row = new ShareDataRow(file, contentService, null); + const col = <DataColumn> { type: 'image', key: '$thumbnail' }; - let value = adapter.getValue(row, col); + const value = adapter.getValue(row, col); expect(value).toContain(`assets/images/ft_ic_raster_image`); expect(value).toContain(`svg`); }); it('should put folders on top upon sort', () => { - let file1 = new FileNode('file1'); - let file2 = new FileNode('file2'); - let folder = new FolderNode(); + const file1 = new FileNode('file1'); + const file2 = new FileNode('file2'); + const folder = new FolderNode(); - let col = <DataColumn> { key: 'name' }; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const col = <DataColumn> { key: 'name' }; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); adapter.setSorting(new DataSorting('name', 'asc')); adapter.setRows([ @@ -313,21 +313,21 @@ describe('ShareDataTableAdapter', () => { new ShareDataRow(folder, contentService, null) ]); - let sorted = adapter.getRows(); + const sorted = adapter.getRows(); expect((<ShareDataRow> sorted[0]).node).toBe(folder); expect((<ShareDataRow> sorted[1]).node).toBe(file1); expect((<ShareDataRow> sorted[2]).node).toBe(file2); }); it('should sort by dates up to ms', () => { - let file1 = new FileNode('file1'); + const file1 = new FileNode('file1'); file1.entry['dateProp'] = new Date(2016, 6, 30, 13, 14, 1); - let file2 = new FileNode('file2'); + const file2 = new FileNode('file2'); file2.entry['dateProp'] = new Date(2016, 6, 30, 13, 14, 2); - let col = <DataColumn> { key: 'dateProp' }; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const col = <DataColumn> { key: 'dateProp' }; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); adapter.setRows([ new ShareDataRow(file2, contentService, null), @@ -336,7 +336,7 @@ describe('ShareDataTableAdapter', () => { adapter.sort('dateProp', 'asc'); - let rows = adapter.getRows(); + const rows = adapter.getRows(); expect((<ShareDataRow> rows[0]).node).toBe(file1); expect((<ShareDataRow> rows[1]).node).toBe(file2); @@ -346,18 +346,18 @@ describe('ShareDataTableAdapter', () => { }); it('should sort by file size', () => { - let file1 = new FileNode('file1'); - let file2 = new FileNode('file2'); - let file3 = new FileNode('file3'); - let file4 = new FileNode('file4'); + const file1 = new FileNode('file1'); + const file2 = new FileNode('file2'); + const file3 = new FileNode('file3'); + const file4 = new FileNode('file4'); file1.entry.content.sizeInBytes = 146; // 146 bytes file2.entry.content.sizeInBytes = 10075; // 9.84 KB file3.entry.content.sizeInBytes = 4224120; // 4.03 MB file4.entry.content.sizeInBytes = 2852791665; // 2.66 GB - let col = <DataColumn> { key: 'content.sizeInBytes' }; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const col = <DataColumn> { key: 'content.sizeInBytes' }; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); adapter.setRows([ new ShareDataRow(file3, contentService, null), @@ -367,7 +367,7 @@ describe('ShareDataTableAdapter', () => { ]); adapter.sort('content.sizeInBytes', 'asc'); - let rows = adapter.getRows(); + const rows = adapter.getRows(); expect((<ShareDataRow> rows[0]).node).toBe(file1); expect((<ShareDataRow> rows[1]).node).toBe(file2); @@ -382,15 +382,15 @@ describe('ShareDataTableAdapter', () => { }); it('should sort by name', () => { - let file1 = new FileNode('file1'); - let file2 = new FileNode('file11'); - let file3 = new FileNode('file20'); - let file4 = new FileNode('file11-1'); // auto rename - let file5 = new FileNode('a'); - let file6 = new FileNode('b'); + const file1 = new FileNode('file1'); + const file2 = new FileNode('file11'); + const file3 = new FileNode('file20'); + const file4 = new FileNode('file11-1'); // auto rename + const file5 = new FileNode('a'); + const file6 = new FileNode('b'); - let col = <DataColumn> { key: 'name' }; - let adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const col = <DataColumn> { key: 'name' }; + const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); adapter.setRows([ new ShareDataRow(file4, contentService, null), @@ -402,7 +402,7 @@ describe('ShareDataTableAdapter', () => { ]); adapter.sort('name', 'asc'); - let rows = adapter.getRows(); + const rows = adapter.getRows(); expect((<ShareDataRow> rows[0]).node).toBe(file5); expect((<ShareDataRow> rows[1]).node).toBe(file6); @@ -423,8 +423,8 @@ describe('ShareDataTableAdapter', () => { describe('ShareDataRow', () => { it('should wrap node', () => { - let file = new FileNode(); - let row = new ShareDataRow(file, contentService, null); + const file = new FileNode(); + const row = new ShareDataRow(file, contentService, null); expect(row.node).toBe(file); }); @@ -435,37 +435,37 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve value from node entry', () => { - let file = new FileNode('test'); - let row = new ShareDataRow(file, contentService, null); + const file = new FileNode('test'); + const row = new ShareDataRow(file, contentService, null); expect(row.getValue('name')).toBe('test'); }); it('should check value', () => { - let file = new FileNode('test'); - let row = new ShareDataRow(file, contentService, null); + const file = new FileNode('test'); + const row = new ShareDataRow(file, contentService, null); expect(row.hasValue('name')).toBeTruthy(); expect(row.hasValue('missing')).toBeFalsy(); }); it('should be set as drop target when user has permission for that node', () => { - let file = new FolderNode('test'); + const file = new FolderNode('test'); file.entry['allowableOperations'] = ['create']; - let row = new ShareDataRow(file, contentService, null); + const row = new ShareDataRow(file, contentService, null); expect(row.isDropTarget).toBeTruthy(); }); it('should not be set as drop target when user has permission for that node', () => { - let file = new FolderNode('test'); - let row = new ShareDataRow(file, contentService, null); + const file = new FolderNode('test'); + const row = new ShareDataRow(file, contentService, null); expect(row.isDropTarget).toBeFalsy(); }); it('should not be set as drop target when element is not a Folder', () => { - let file = new FileNode('test'); - let row = new ShareDataRow(file, contentService, null); + const file = new FileNode('test'); + const row = new ShareDataRow(file, contentService, null); expect(row.isDropTarget).toBeFalsy(); }); diff --git a/lib/content-services/document-list/data/share-datatable-adapter.ts b/lib/content-services/document-list/data/share-datatable-adapter.ts index d76db1ea58..4e2b2eeb13 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.ts @@ -96,8 +96,8 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (!col) { throw new Error(this.ERR_COL_NOT_FOUND); } - let dataRow: ShareDataRow = <ShareDataRow> row; - let value: any = row.getValue(col.key); + const dataRow: ShareDataRow = <ShareDataRow> row; + const value: any = row.getValue(col.key); if (dataRow.cache[col.key] !== undefined) { return dataRow.cache[col.key]; } @@ -105,7 +105,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (col.key === '$thumbnail') { if (this.imageResolver) { - let resolved = this.imageResolver(row, col); + const resolved = this.imageResolver(row, col); if (resolved) { return resolved; } @@ -136,7 +136,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (col.type === 'image') { if (this.imageResolver) { - let resolved = this.imageResolver(row, col); + const resolved = this.imageResolver(row, col); if (resolved) { return resolved; } @@ -157,7 +157,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { } sort(key?: string, direction?: string): void { - let sorting = this.sorting || new DataSorting(); + const sorting = this.sorting || new DataSorting(); if (key) { sorting.key = key; sorting.direction = direction || 'asc'; @@ -186,13 +186,13 @@ export class ShareDataTableAdapter implements DataTableAdapter { } isSmartFolder(node: any) { - let nodeAspects = this.getNodeAspectNames(node); + const nodeAspects = this.getNodeAspectNames(node); return nodeAspects.indexOf('smf:customConfigSmartFolder') > -1 || (nodeAspects.indexOf('smf:systemConfigSmartFolder') > -1); } isRuleFolder(node: any) { - let nodeAspects = this.getNodeAspectNames(node); + const nodeAspects = this.getNodeAspectNames(node); return nodeAspects.indexOf('rule:rules') > -1 || (nodeAspects.indexOf('rule:rules') > -1); } @@ -249,7 +249,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { let shareDataRows: ShareDataRow[] = []; if (nodePaging && nodePaging.list) { - let nodeEntries: NodeEntry[] = nodePaging.list.entries; + const nodeEntries: NodeEntry[] = nodePaging.list.entries; if (nodeEntries && nodeEntries.length > 0) { shareDataRows = nodeEntries.map((item) => new ShareDataRow(item, this.contentService, this.permissionsStyle, this.thumbnailService)); @@ -260,11 +260,11 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (this.sortingMode !== 'server') { // Sort by first sortable or just first column if (this.columns && this.columns.length > 0) { - let sorting = this.getSorting(); + const sorting = this.getSorting(); if (sorting) { this.sortRows(shareDataRows, sorting); } else { - let sortable = this.columns.filter((c) => c.sortable); + const sortable = this.columns.filter((c) => c.sortable); if (sortable.length > 0) { this.sort(sortable[0].key, 'asc'); } else { @@ -277,8 +277,8 @@ export class ShareDataTableAdapter implements DataTableAdapter { } if (merge) { - let listPrunedDuplicate = shareDataRows.filter((elementToFilter: any) => { - let isPresent = this.rows.find((currentRow: any) => { + const listPrunedDuplicate = shareDataRows.filter((elementToFilter: any) => { + const isPresent = this.rows.find((currentRow: any) => { return currentRow.obj.entry.id === elementToFilter.obj.entry.id; }); diff --git a/lib/content-services/document-list/services/custom-resources.service.ts b/lib/content-services/document-list/services/custom-resources.service.ts index a983f117ef..237ae11936 100644 --- a/lib/content-services/document-list/services/custom-resources.service.ts +++ b/lib/content-services/document-list/services/custom-resources.service.ts @@ -103,7 +103,7 @@ export class CustomResourcesService { * @returns List of favorite files */ loadFavorites(pagination: PaginationModel, includeFields: string[] = []): Observable<NodePaging> { - let includeFieldsRequest = this.getIncludesFields(includeFields); + const includeFieldsRequest = this.getIncludesFields(includeFields); const options = { maxItems: pagination.maxItems, @@ -115,7 +115,7 @@ export class CustomResourcesService { return new Observable((observer) => { this.apiService.favoritesApi.getFavorites('-me-', options) .then((result: FavoritePaging) => { - let page: FavoritePaging = { + const page: FavoritePaging = { list: { entries: result.list.entries .map(({ entry: { target } }: any) => ({ @@ -157,7 +157,7 @@ export class CustomResourcesService { return new Observable((observer) => { this.apiService.peopleApi.listSiteMembershipsForPerson('-me-', options) .then((result: SiteRolePaging) => { - let page: SiteMemberPaging = new SiteMemberPaging( { + const page: SiteMemberPaging = new SiteMemberPaging( { list: { entries: result.list.entries .map(({ entry: { site } }: any) => { @@ -219,7 +219,7 @@ export class CustomResourcesService { * @returns List of deleted items */ loadTrashcan(pagination: PaginationModel, includeFields: string[] = []): Observable<DeletedNodesPaging> { - let includeFieldsRequest = this.getIncludesFields(includeFields); + const includeFieldsRequest = this.getIncludesFields(includeFields); const options = { include: includeFieldsRequest, @@ -239,7 +239,7 @@ export class CustomResourcesService { * @returns List of shared links */ loadSharedLinks(pagination: PaginationModel, includeFields: string[] = []): Observable<SharedLinkPaging> { - let includeFieldsRequest = this.getIncludesFields(includeFields); + const includeFieldsRequest = this.getIncludesFields(includeFields); const options = { include: includeFieldsRequest, diff --git a/lib/content-services/document-list/services/document-actions.service.spec.ts b/lib/content-services/document-list/services/document-actions.service.spec.ts index 080b4d3e10..e28a6562c6 100644 --- a/lib/content-services/document-list/services/document-actions.service.spec.ts +++ b/lib/content-services/document-list/services/document-actions.service.spec.ts @@ -22,14 +22,12 @@ import { FileNode, FolderNode } from '../../mock'; import { ContentActionHandler } from '../models/content-action.model'; import { DocumentActionsService } from './document-actions.service'; import { DocumentListService } from './document-list.service'; -import { NodeActionsService } from './node-actions.service'; import { of } from 'rxjs'; describe('DocumentActionsService', () => { let service: DocumentActionsService; let documentListService: DocumentListService; - let nodeActionsService: NodeActionsService; setupTestBed({ imports: [ @@ -38,8 +36,8 @@ describe('DocumentActionsService', () => { }); beforeEach(() => { - let contentService = new ContentService(null, null, null, null); - let alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + const contentService = new ContentService(null, null, null, null); + const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null); service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService); @@ -54,7 +52,7 @@ describe('DocumentActionsService', () => { }); it('should register custom action handler', () => { - let handler: ContentActionHandler = function (obj: any) { + const handler: ContentActionHandler = function (obj: any) { }; service.setHandler('<key>', handler); expect(service.getHandler('<key>')).toBe(handler); @@ -65,7 +63,7 @@ describe('DocumentActionsService', () => { }); it('should be case insensitive for keys', () => { - let handler: ContentActionHandler = function (obj: any) { + const handler: ContentActionHandler = function (obj: any) { }; service.setHandler('<key>', handler); expect(service.getHandler('<KEY>')).toBe(handler); @@ -77,10 +75,10 @@ describe('DocumentActionsService', () => { }); it('should allow action execution only when service available', () => { - let file = new FileNode(); + const file = new FileNode(); expect(service.canExecuteAction(file)).toBeTruthy(); - service = new DocumentActionsService(nodeActionsService, null, null); + service = new DocumentActionsService(null, null, null); expect(service.canExecuteAction(file)).toBeFalsy(); }); @@ -91,7 +89,7 @@ describe('DocumentActionsService', () => { }); it('should set new handler only by key', () => { - let handler: ContentActionHandler = function (obj: any) { + const handler: ContentActionHandler = function (obj: any) { }; expect(service.setHandler(null, handler)).toBeFalsy(); expect(service.setHandler('', handler)).toBeFalsy(); @@ -112,7 +110,7 @@ describe('DocumentActionsService', () => { done(); }); - let file = new FileNode(); + const file = new FileNode(); service.getHandler('delete')(file); }); @@ -120,7 +118,7 @@ describe('DocumentActionsService', () => { it('should call the error on the returned Observable if there are no permissions', (done) => { spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let file = new FileNode(); + const file = new FileNode(); const deleteObservable = service.getHandler('delete')(file); deleteObservable.subscribe({ @@ -134,9 +132,9 @@ describe('DocumentActionsService', () => { it('should delete the file node if there is the delete permission', () => { spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let permission = 'delete'; - let file = new FileNode(); - let fileWithPermission: any = file; + const permission = 'delete'; + const file = new FileNode(); + const fileWithPermission: any = file; fileWithPermission.entry.allowableOperations = [permission]; service.getHandler('delete')(fileWithPermission, null, permission); @@ -153,9 +151,9 @@ describe('DocumentActionsService', () => { done(); }); - let permission = 'delete'; - let file = new FileNode(); - let fileWithPermission: any = file; + const permission = 'delete'; + const file = new FileNode(); + const fileWithPermission: any = file; fileWithPermission.entry.allowableOperations = ['create', 'update']; service.getHandler('delete')(fileWithPermission, null, permission); }); @@ -163,9 +161,9 @@ describe('DocumentActionsService', () => { it('should delete the file node if there is the delete and others permission ', () => { spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let permission = 'delete'; - let file = new FileNode(); - let fileWithPermission: any = file; + const permission = 'delete'; + const file = new FileNode(); + const fileWithPermission: any = file; fileWithPermission.entry.allowableOperations = ['create', 'update', permission]; service.getHandler('delete')(fileWithPermission, null, permission); @@ -179,9 +177,9 @@ describe('DocumentActionsService', () => { it('should delete file node', () => { spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let permission = 'delete'; - let file = new FileNode(); - let fileWithPermission: any = file; + const permission = 'delete'; + const file = new FileNode(); + const fileWithPermission: any = file; fileWithPermission.entry.allowableOperations = [permission]; const deleteObservable = service.getHandler('delete')(fileWithPermission, null, permission); @@ -192,13 +190,13 @@ describe('DocumentActionsService', () => { it('should support deletion only file node', () => { spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let folder = new FolderNode(); + const folder = new FolderNode(); service.getHandler('delete')(folder); expect(documentListService.deleteNode).not.toHaveBeenCalled(); - let permission = 'delete'; - let file = new FileNode(); - let fileWithPermission: any = file; + const permission = 'delete'; + const file = new FileNode(); + const fileWithPermission: any = file; fileWithPermission.entry.allowableOperations = [permission]; service.getHandler('delete')(fileWithPermission, null, permission); expect(documentListService.deleteNode).toHaveBeenCalled(); @@ -207,7 +205,7 @@ describe('DocumentActionsService', () => { it('should require node id to delete', () => { spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let file = new FileNode(); + const file = new FileNode(); file.entry.id = null; service.getHandler('delete')(file); @@ -221,10 +219,10 @@ describe('DocumentActionsService', () => { }); spyOn(documentListService, 'deleteNode').and.returnValue(of(true)); - let target = jasmine.createSpyObj('obj', ['reload']); - let permission = 'delete'; - let file = new FileNode(); - let fileWithPermission: any = file; + const target = jasmine.createSpyObj('obj', ['reload']); + const permission = 'delete'; + const file = new FileNode(); + const fileWithPermission: any = file; fileWithPermission.entry.allowableOperations = [permission]; service.getHandler('delete')(fileWithPermission, target, permission); diff --git a/lib/content-services/document-list/services/document-actions.service.ts b/lib/content-services/document-list/services/document-actions.service.ts index 11c971e338..b3c0ea72f4 100644 --- a/lib/content-services/document-list/services/document-actions.service.ts +++ b/lib/content-services/document-list/services/document-actions.service.ts @@ -51,7 +51,7 @@ export class DocumentActionsService { */ getHandler(key: string): ContentActionHandler { if (key) { - let lKey = key.toLowerCase(); + const lKey = key.toLowerCase(); return this.handlers[lKey] || null; } return null; @@ -65,7 +65,7 @@ export class DocumentActionsService { */ setHandler(key: string, handler: ContentActionHandler): boolean { if (key) { - let lKey = key.toLowerCase(); + const lKey = key.toLowerCase(); this.handlers[lKey] = handler; return true; } @@ -125,10 +125,10 @@ export class DocumentActionsService { if (this.contentService.hasAllowableOperations(node.entry, permission)) { handlerObservable = this.documentListService.deleteNode(node.entry.id); handlerObservable.subscribe(() => { - let message = this.translation.instant('CORE.DELETE_NODE.SINGULAR', { name: node.entry.name }); + const message = this.translation.instant('CORE.DELETE_NODE.SINGULAR', { name: node.entry.name }); this.success.next(message); }, () => { - let message = this.translation.instant('CORE.DELETE_NODE.ERROR_SINGULAR', { name: node.entry.name }); + const message = this.translation.instant('CORE.DELETE_NODE.ERROR_SINGULAR', { name: node.entry.name }); this.error.next(message); }); return handlerObservable; diff --git a/lib/content-services/document-list/services/document-list.service.spec.ts b/lib/content-services/document-list/services/document-list.service.spec.ts index 615a05f51b..b97d7dfc3d 100644 --- a/lib/content-services/document-list/services/document-list.service.spec.ts +++ b/lib/content-services/document-list/services/document-list.service.spec.ts @@ -26,7 +26,7 @@ describe('DocumentListService', () => { let service: DocumentListService; let alfrescoApiService: AlfrescoApiService; - let fakeFolder = { + const fakeFolder = { 'list': { 'pagination': { 'count': 1, 'hasMoreItems': false, 'totalItems': 1, 'skipCount': 0, 'maxItems': 20 }, 'entries': [{ @@ -67,8 +67,8 @@ describe('DocumentListService', () => { }); beforeEach(() => { - let logService = new LogService(new AppConfigServiceMock(null)); - let contentService = new ContentService(null, null, null, null); + const logService = new LogService(new AppConfigServiceMock(null)); + const contentService = new ContentService(null, null, null, null); alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); service = new DocumentListService(null, contentService, alfrescoApiService, logService, null); jasmine.Ajax.install(); @@ -98,7 +98,7 @@ describe('DocumentListService', () => { }); it('should add the includeTypes in the request Node Children if required', () => { - let spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNodeChildren').and.callThrough(); + const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNodeChildren').and.callThrough(); service.getFolder('/fake-root/fake-name', {}, ['isLocked']); @@ -110,7 +110,7 @@ describe('DocumentListService', () => { }); it('should not add the includeTypes in the request Node Children if is duplicated', () => { - let spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNodeChildren').and.callThrough(); + const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNodeChildren').and.callThrough(); service.getFolder('/fake-root/fake-name', {}, ['allowableOperations']); @@ -122,7 +122,7 @@ describe('DocumentListService', () => { }); it('should add the includeTypes in the request getFolderNode if required', () => { - let spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNode').and.callThrough(); + const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNode').and.callThrough(); service.getFolderNode('test-id', ['isLocked']); @@ -133,7 +133,7 @@ describe('DocumentListService', () => { }); it('should not add the includeTypes in the request getFolderNode if is duplicated', () => { - let spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNode').and.callThrough(); + const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNode').and.callThrough(); service.getFolderNode('test-id', ['allowableOperations']); diff --git a/lib/content-services/document-list/services/document-list.service.ts b/lib/content-services/document-list/services/document-list.service.ts index 578341a66c..7507d49fbe 100644 --- a/lib/content-services/document-list/services/document-list.service.ts +++ b/lib/content-services/document-list/services/document-list.service.ts @@ -86,10 +86,10 @@ export class DocumentListService { rootNodeId = opts.rootFolderId; } - let includeFieldsRequest = ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields] + const includeFieldsRequest = ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields] .filter((element, index, array) => index === array.indexOf(element)); - let params: any = { + const params: any = { includeSource: true, include: includeFieldsRequest }; @@ -123,10 +123,10 @@ export class DocumentListService { */ getNode(nodeId: string, includeFields: string[] = []): Observable<NodeEntry> { - let includeFieldsRequest = ['path', 'properties', 'allowableOperations', 'permissions', ...includeFields] + const includeFieldsRequest = ['path', 'properties', 'allowableOperations', 'permissions', ...includeFields] .filter((element, index, array) => index === array.indexOf(element)); - let opts: any = { + const opts: any = { includeSource: true, include: includeFieldsRequest }; @@ -142,10 +142,10 @@ export class DocumentListService { */ getFolderNode(nodeId: string, includeFields: string[] = []): Observable<NodeEntry> { - let includeFieldsRequest = ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields] + const includeFieldsRequest = ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields] .filter((element, index, array) => index === array.indexOf(element)); - let opts: any = { + const opts: any = { includeSource: true, include: includeFieldsRequest }; diff --git a/lib/content-services/document-list/services/folder-actions.service.spec.ts b/lib/content-services/document-list/services/folder-actions.service.spec.ts index d249b66a3c..b73253c080 100644 --- a/lib/content-services/document-list/services/folder-actions.service.spec.ts +++ b/lib/content-services/document-list/services/folder-actions.service.spec.ts @@ -35,17 +35,17 @@ describe('FolderActionsService', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; - let contentService = new ContentService(null, null, null, null); - let alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + const contentService = new ContentService(null, null, null, null); + const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null); service = new FolderActionsService(null, documentListService, contentService, new TranslationMock()); }); it('should register custom action handler', () => { - let handler: ContentActionHandler = function () { + const handler: ContentActionHandler = function () { }; service.setHandler('<key>', handler); expect(service.getHandler('<key>')).toBe(handler); @@ -56,7 +56,7 @@ describe('FolderActionsService', () => { }); it('should be case insensitive for keys', () => { - let handler: ContentActionHandler = function () { + const handler: ContentActionHandler = function () { }; service.setHandler('<key>', handler); expect(service.getHandler('<KEY>')).toBe(handler); @@ -68,7 +68,7 @@ describe('FolderActionsService', () => { }); it('should allow action execution only when service available', () => { - let folder = new FolderNode(); + const folder = new FolderNode(); expect(service.canExecuteAction(folder)).toBeTruthy(); }); @@ -79,7 +79,7 @@ describe('FolderActionsService', () => { }); it('should set new handler only by key', () => { - let handler: ContentActionHandler = function () { + const handler: ContentActionHandler = function () { }; expect(service.setHandler(null, handler)).toBeFalsy(); expect(service.setHandler('', handler)).toBeFalsy(); @@ -100,7 +100,7 @@ describe('FolderActionsService', () => { done(); }); - let folder = new FolderNode(); + const folder = new FolderNode(); service.getHandler('delete')(folder); }); @@ -113,9 +113,9 @@ describe('FolderActionsService', () => { }); }); - let permission = 'delete'; - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const permission = 'delete'; + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = [permission]; const deleteObservable = service.getHandler('delete')(folderWithPermission, null, permission); @@ -138,8 +138,8 @@ describe('FolderActionsService', () => { done(); }); - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = ['create', 'update']; service.getHandler('delete')(folderWithPermission); }); @@ -152,8 +152,8 @@ describe('FolderActionsService', () => { }); }); - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = ['create', 'update']; const deleteObservable = service.getHandler('delete')(folderWithPermission); @@ -174,9 +174,9 @@ describe('FolderActionsService', () => { }); }); - let permission = 'delete'; - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const permission = 'delete'; + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = ['create', 'update', permission]; service.getHandler('delete')(folderWithPermission, null, permission); @@ -191,13 +191,13 @@ describe('FolderActionsService', () => { }); }); - let permission = 'delete'; - let file = new FileNode(); + const permission = 'delete'; + const file = new FileNode(); service.getHandler('delete')(file); expect(documentListService.deleteNode).not.toHaveBeenCalled(); - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = [permission]; service.getHandler('delete')(folderWithPermission, null, permission); expect(documentListService.deleteNode).toHaveBeenCalled(); @@ -211,7 +211,7 @@ describe('FolderActionsService', () => { }); }); - let folder = new FolderNode(); + const folder = new FolderNode(); folder.entry.id = null; service.getHandler('delete')(folder); @@ -226,13 +226,13 @@ describe('FolderActionsService', () => { }); }); - let permission = 'delete'; - let target = jasmine.createSpyObj('obj', ['reload']); - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const permission = 'delete'; + const target = jasmine.createSpyObj('obj', ['reload']); + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = [permission]; - let deleteHandler = service.getHandler('delete')(folderWithPermission, target, permission); + const deleteHandler = service.getHandler('delete')(folderWithPermission, target, permission); deleteHandler.subscribe(() => { expect(target.reload).toHaveBeenCalled(); @@ -255,10 +255,10 @@ describe('FolderActionsService', () => { done(); }); - let permission = 'delete'; - let target = jasmine.createSpyObj('obj', ['reload']); - let folder = new FolderNode(); - let folderWithPermission: any = folder; + const permission = 'delete'; + const target = jasmine.createSpyObj('obj', ['reload']); + const folder = new FolderNode(); + const folderWithPermission: any = folder; folderWithPermission.entry.allowableOperations = [permission]; service.getHandler('delete')(folderWithPermission, target, permission); diff --git a/lib/content-services/document-list/services/folder-actions.service.ts b/lib/content-services/document-list/services/folder-actions.service.ts index 8778846dbf..b2ad36f5b0 100644 --- a/lib/content-services/document-list/services/folder-actions.service.ts +++ b/lib/content-services/document-list/services/folder-actions.service.ts @@ -49,7 +49,7 @@ export class FolderActionsService { */ getHandler(key: string): ContentActionHandler { if (key) { - let lKey = key.toLowerCase(); + const lKey = key.toLowerCase(); return this.handlers[lKey] || null; } return null; @@ -63,7 +63,7 @@ export class FolderActionsService { */ setHandler(key: string, handler: ContentActionHandler): boolean { if (key) { - let lKey = key.toLowerCase(); + const lKey = key.toLowerCase(); this.handlers[lKey] = handler; return true; } @@ -125,10 +125,10 @@ export class FolderActionsService { target.reload(); } - let message = this.translation.instant('CORE.DELETE_NODE.SINGULAR', { name: node.entry.name }); + const message = this.translation.instant('CORE.DELETE_NODE.SINGULAR', { name: node.entry.name }); this.success.next(message); }, () => { - let message = this.translation.instant('CORE.DELETE_NODE.ERROR_SINGULAR', { name: node.entry.name }); + const message = this.translation.instant('CORE.DELETE_NODE.ERROR_SINGULAR', { name: node.entry.name }); this.error.next(message); }); diff --git a/lib/content-services/document-list/services/node-actions.service.spec.ts b/lib/content-services/document-list/services/node-actions.service.spec.ts index 0191729bae..9f8be1d42e 100644 --- a/lib/content-services/document-list/services/node-actions.service.spec.ts +++ b/lib/content-services/document-list/services/node-actions.service.spec.ts @@ -52,7 +52,7 @@ describe('NodeActionsService', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; service = TestBed.get(NodeActionsService); diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts index 4b931b6b81..05505dc80f 100644 --- a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts +++ b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts @@ -32,7 +32,7 @@ describe('AddPermissionDialog', () => { let fixture: ComponentFixture<AddPermissionDialogComponent>; let element: HTMLElement; - let data: AddPermissionDialogData = { + const data: AddPermissionDialogData = { title: 'dead or alive you are coming with me', nodeId: 'fake-node-id', confirm: new Subject<NodeEntry[]> () diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts index 20ce655fc2..3a12a5dd5f 100644 --- a/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts +++ b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts @@ -50,7 +50,7 @@ describe('AddPermissionPanelComponent', () => { }); function typeWordIntoSearchInput(word: string): void { - let inputDebugElement = debugElement.query(By.css('#searchInput')); + const inputDebugElement = debugElement.query(By.css('#searchInput')); inputDebugElement.nativeElement.value = word; inputDebugElement.nativeElement.focus(); inputDebugElement.nativeElement.dispatchEvent(new Event('input')); diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts b/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts index 06e0625417..14da20323b 100644 --- a/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts +++ b/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts @@ -104,7 +104,7 @@ describe('AddPermissionComponent', () => { fixture.componentInstance.currentNode = new Node({ id: 'fake-node-id' }); spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(of({ id: 'fake-node-id' })); - let spySuccess = spyOn(fixture.componentInstance, 'success'); + const spySuccess = spyOn(fixture.componentInstance, 'success'); fixture.componentInstance.applySelection(); expect(spySuccess).not.toHaveBeenCalled(); }); diff --git a/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts b/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts index 4fa9fab89d..3e7fb50416 100644 --- a/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts +++ b/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts @@ -98,7 +98,7 @@ describe('InheritPermissionDirective', () => { it('should not update the node when node has no permission', async(() => { spyOn(nodeService, 'getNode').and.returnValue(of(fakeNodeWithInheritNoPermission)); - let spyUpdateNode = spyOn(nodeService, 'updateNode'); + const spyUpdateNode = spyOn(nodeService, 'updateNode'); component.updatedNode = true; fixture.detectChanges(); const buttonPermission: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#sample-button-permission'); diff --git a/lib/content-services/permission-manager/components/permission-list/permission-list.component.spec.ts b/lib/content-services/permission-manager/components/permission-list/permission-list.component.spec.ts index 3db55f6da5..322e6cc664 100644 --- a/lib/content-services/permission-manager/components/permission-list/permission-list.component.spec.ts +++ b/lib/content-services/permission-manager/components/permission-list/permission-list.component.spec.ts @@ -120,7 +120,7 @@ describe('PermissionDisplayComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let options: any = fixture.debugElement.queryAll(By.css('mat-option')); + const options: any = fixture.debugElement.queryAll(By.css('mat-option')); expect(options).not.toBeNull(); expect(options.length).toBe(4); expect(options[0].nativeElement.innerText).toContain('SiteCollaborator'); @@ -145,7 +145,7 @@ describe('PermissionDisplayComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let options: any = fixture.debugElement.queryAll(By.css('mat-option')); + const options: any = fixture.debugElement.queryAll(By.css('mat-option')); expect(options).not.toBeNull(); expect(options.length).toBe(5); expect(options[0].nativeElement.innerText).toContain('Contributor'); @@ -178,7 +178,7 @@ describe('PermissionDisplayComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let options: any = fixture.debugElement.queryAll(By.css('mat-option')); + const options: any = fixture.debugElement.queryAll(By.css('mat-option')); expect(options).not.toBeNull(); expect(options.length).toBe(5); options[3].triggerEventHandler('click', {}); diff --git a/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts b/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts index 0332670b4f..fc3f0380cc 100644 --- a/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts +++ b/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts @@ -69,16 +69,16 @@ export class PermissionListComponent implements OnInit { } private getPermissionList(node: Node): PermissionDisplayModel[] { - let allPermissions: PermissionDisplayModel[] = []; + const allPermissions: PermissionDisplayModel[] = []; if (node.permissions.locallySet) { node.permissions.locallySet.map((permissionElement: PermissionElement) => { - let permission = new PermissionDisplayModel(permissionElement); + const permission = new PermissionDisplayModel(permissionElement); allPermissions.push(permission); }); } if (node.permissions.inherited) { node.permissions.inherited.map((permissionElement: PermissionElement) => { - let permissionInherited = new PermissionDisplayModel(permissionElement); + const permissionInherited = new PermissionDisplayModel(permissionElement); permissionInherited.isInherited = true; allPermissions.push(permissionInherited); }); @@ -87,7 +87,7 @@ export class PermissionListComponent implements OnInit { } saveNewRole(event: any, permissionRow: PermissionDisplayModel) { - let updatedPermissionRole: PermissionElement = this.buildUpdatedPermission(event.value, permissionRow); + const updatedPermissionRole: PermissionElement = this.buildUpdatedPermission(event.value, permissionRow); this.nodePermissionService.updatePermissionRole(this.actualNode, updatedPermissionRole) .subscribe((node: Node) => { this.update.emit(updatedPermissionRole); @@ -95,7 +95,7 @@ export class PermissionListComponent implements OnInit { } private buildUpdatedPermission(newRole: string, permissionRow: PermissionDisplayModel): PermissionElement { - let permissionRole: PermissionElement = {}; + const permissionRole: PermissionElement = {}; permissionRole.accessStatus = permissionRow.accessStatus; permissionRole.name = newRole; permissionRole.authorityId = permissionRow.authorityId; diff --git a/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts b/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts index 7e3e3df3bf..a2555bd108 100644 --- a/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts +++ b/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts @@ -39,7 +39,7 @@ describe('NodePermissionDialogService', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; service = TestBed.get(NodePermissionDialogService); materialDialog = TestBed.get(MatDialog); diff --git a/lib/content-services/permission-manager/services/node-permission-dialog.service.ts b/lib/content-services/permission-manager/services/node-permission-dialog.service.ts index 8195534aca..2d8b61366c 100644 --- a/lib/content-services/permission-manager/services/node-permission-dialog.service.ts +++ b/lib/content-services/permission-manager/services/node-permission-dialog.service.ts @@ -58,7 +58,7 @@ export class NodePermissionDialogService { this.openDialog(data, 'adf-add-permission-dialog', '630px'); return confirm; } else { - let errors = new Error(JSON.stringify({ error: { statusCode: 403 } })); + const errors = new Error(JSON.stringify({ error: { statusCode: 403 } })); errors.message = 'PERMISSION_MANAGER.ERROR.NOT-ALLOWED'; return throwError(errors); } diff --git a/lib/content-services/permission-manager/services/node-permission.service.spec.ts b/lib/content-services/permission-manager/services/node-permission.service.spec.ts index 09bb3d8359..c14a9b2696 100644 --- a/lib/content-services/permission-manager/services/node-permission.service.spec.ts +++ b/lib/content-services/permission-manager/services/node-permission.service.spec.ts @@ -52,7 +52,7 @@ describe('NodePermissionService', () => { }); function returnUpdatedNode(nodeId, nodeBody) { - let fakeNode: Node = new Node({}); + const fakeNode: Node = new Node({}); fakeNode.id = 'fake-updated-node'; fakeNode.permissions = nodeBody.permissions; return of(fakeNode); @@ -149,7 +149,7 @@ describe('NodePermissionService', () => { })); it('should be able to update locally permissions on the node without locally set permissions', async(() => { - let fakeNodeCopy = JSON.parse(JSON.stringify(fakeNodeWithoutPermissions)); + const fakeNodeCopy = JSON.parse(JSON.stringify(fakeNodeWithoutPermissions)); fakeNodeCopy.permissions.locallySet = undefined; spyOn(nodeService, 'updateNode').and.callFake((nodeId, permissionBody) => returnUpdatedNode(nodeId, permissionBody)); diff --git a/lib/content-services/permission-manager/services/node-permission.service.ts b/lib/content-services/permission-manager/services/node-permission.service.ts index 3d726b8470..683377bd2c 100644 --- a/lib/content-services/permission-manager/services/node-permission.service.ts +++ b/lib/content-services/permission-manager/services/node-permission.service.ts @@ -43,7 +43,7 @@ export class NodePermissionService { .pipe( switchMap((siteNodeList: any) => { if ( siteNodeList.list.entries.length > 0 ) { - let siteName = siteNodeList.list.entries[0].entry.name; + const siteName = siteNodeList.list.entries[0].entry.name; return this.getGroupMembersBySiteName(siteName); } else { return of(node.permissions.settable); @@ -59,7 +59,7 @@ export class NodePermissionService { * @returns Node with updated permission */ updatePermissionRole(node: Node, updatedPermissionRole: PermissionElement): Observable<Node> { - let permissionBody = { permissions: { locallySet: []} }; + const permissionBody = { permissions: { locallySet: []} }; const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(updatedPermissionRole.authorityId); permissionBody.permissions.locallySet = permissionBody.permissions.locallySet.concat(node.permissions.locallySet); if (index !== -1) { @@ -95,7 +95,7 @@ export class NodePermissionService { * @returns Node with updated permissions */ updateLocallySetPermissions(node: Node, nodes: NodeEntry[], nodeRole: string[]): Observable<Node> { - let permissionBody = { permissions: { locallySet: []} }; + const permissionBody = { permissions: { locallySet: []} }; const permissionList = this.transformNodeToPermissionElement(nodes, nodeRole[0]); const duplicatedPermissions = this.getDuplicatedPermissions(node.permissions.locallySet, permissionList); if (duplicatedPermissions.length > 0) { @@ -108,7 +108,7 @@ export class NodePermissionService { } private getDuplicatedPermissions(nodeLocallySet: PermissionElement[], permissionListAdded: PermissionElement[]): PermissionElement[] { - let duplicatePermissions: PermissionElement[] = []; + const duplicatePermissions: PermissionElement[] = []; if (nodeLocallySet) { permissionListAdded.forEach((permission: PermissionElement) => { const duplicate = nodeLocallySet.find((localPermission) => this.isEqualPermission(localPermission, permission)); @@ -128,7 +128,7 @@ export class NodePermissionService { private transformNodeToPermissionElement(nodes: NodeEntry[], nodeRole: any): PermissionElement[] { return nodes.map((node) => { - let newPermissionElement: PermissionElement = <PermissionElement> { + const newPermissionElement: PermissionElement = <PermissionElement> { 'authorityId': node.entry.properties['cm:authorityName'] ? node.entry.properties['cm:authorityName'] : node.entry.properties['cm:userName'], @@ -146,7 +146,7 @@ export class NodePermissionService { * @returns Node with modified permissions */ removePermission(node: Node, permissionToRemove: PermissionElement): Observable<Node> { - let permissionBody = { permissions: { locallySet: [] } }; + const permissionBody = { permissions: { locallySet: [] } }; const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(permissionToRemove.authorityId); if (index !== -1) { node.permissions.locallySet.splice(index, 1); @@ -160,7 +160,7 @@ export class NodePermissionService { return this.getGroupMemberByGroupName(groupName) .pipe( map((groupMemberPaging: GroupMemberPaging) => { - let displayResult: string[] = []; + const displayResult: string[] = []; groupMemberPaging.list.entries.forEach((member: GroupMemberEntry) => { displayResult.push(this.formattedRoleName(member.entry.displayName, 'site_' + siteName)); }); diff --git a/lib/content-services/search/components/search-control.component.spec.ts b/lib/content-services/search/components/search-control.component.spec.ts index aedecf6f86..4e727becde 100644 --- a/lib/content-services/search/components/search-control.component.spec.ts +++ b/lib/content-services/search/components/search-control.component.spec.ts @@ -103,7 +103,7 @@ describe('SearchControlComponent', () => { }); function typeWordIntoSearchInput(word: string): void { - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); inputDebugElement.nativeElement.value = word; inputDebugElement.nativeElement.focus(); inputDebugElement.nativeElement.dispatchEvent(new Event('input')); @@ -120,7 +120,7 @@ describe('SearchControlComponent', () => { of({ entry: { list: [] } }) ); - let searchDisposable = component.searchChange.subscribe((value) => { + const searchDisposable = component.searchChange.subscribe((value) => { expect(value).toBe('customSearchTerm'); searchDisposable.unsubscribe(); done(); @@ -161,7 +161,7 @@ describe('SearchControlComponent', () => { it('should still fire an event when user inputs a search term less than 3 characters', (done) => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); - let searchDisposable = component.searchChange.subscribe((value) => { + const searchDisposable = component.searchChange.subscribe((value) => { expect(value).toBe('cu'); searchDisposable.unsubscribe(); }); @@ -182,7 +182,7 @@ describe('SearchControlComponent', () => { }); it('search button should be hide', () => { - let searchButton: any = element.querySelector('#adf-search-button'); + const searchButton: any = element.querySelector('#adf-search-button'); expect(searchButton).toBe(null); }); @@ -202,7 +202,7 @@ describe('SearchControlComponent', () => { it('should set browser autocomplete to off by default', async(() => { fixture.detectChanges(); - let attr = element.querySelector('#adf-control-input').getAttribute('autocomplete'); + const attr = element.querySelector('#adf-control-input').getAttribute('autocomplete'); expect(attr).toBe('off'); })); @@ -219,7 +219,7 @@ describe('SearchControlComponent', () => { })); xit('should fire a search when a enter key is pressed', (done) => { - let searchDisposable = component.submit.subscribe((value) => { + const searchDisposable = component.submit.subscribe((value) => { expect(value).toBe('TEST'); searchDisposable.unsubscribe(); done(); @@ -229,9 +229,9 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('TEST'); - let enterKeyEvent: any = new Event('keyup'); + const enterKeyEvent: any = new Event('keyup'); enterKeyEvent.keyCode = '13'; inputDebugElement.nativeElement.dispatchEvent(enterKeyEvent); }); @@ -253,7 +253,7 @@ describe('SearchControlComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let resultElement: Element = element.querySelector('#autocomplete-search-result-list'); + const resultElement: Element = element.querySelector('#autocomplete-search-result-list'); expect(resultElement).not.toBe(null); done(); }); @@ -268,7 +268,7 @@ describe('SearchControlComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let noResultElement: Element = element.querySelector('#search_no_result'); + const noResultElement: Element = element.querySelector('#search_no_result'); expect(noResultElement).not.toBe(null); done(); }); @@ -279,7 +279,7 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('NO RES'); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -300,12 +300,12 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('TEST'); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let resultElement: HTMLElement = <HTMLElement> element.querySelector('#result_option_0'); + const resultElement: HTMLElement = <HTMLElement> element.querySelector('#result_option_0'); resultElement.focus(); expect(resultElement).not.toBe(null); inputDebugElement.nativeElement.dispatchEvent(new KeyboardEvent('keypress', { key: 'TAB' })); @@ -321,14 +321,14 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('TEST'); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); let resultElement: HTMLElement = <HTMLElement> element.querySelector('#result_option_0'); expect(resultElement).not.toBeNull(); - let escapeEvent: any = new Event('ESCAPE'); + const escapeEvent: any = new Event('ESCAPE'); escapeEvent.keyCode = 27; inputDebugElement.triggerEventHandler('keydown', escapeEvent); fixture.whenStable().then(() => { @@ -345,14 +345,14 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('TEST'); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); let resultElement: HTMLElement = <HTMLElement> element.querySelector('#result_option_0'); expect(resultElement).not.toBeNull(); - let escapeEvent: any = new Event('ENTER'); + const escapeEvent: any = new Event('ENTER'); escapeEvent.keyCode = 13; inputDebugElement.triggerEventHandler('keydown', escapeEvent); fixture.whenStable().then(() => { @@ -369,8 +369,8 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); - let escapeEvent: any = new Event('ESCAPE'); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const escapeEvent: any = new Event('ESCAPE'); escapeEvent.keyCode = 27; inputDebugElement.nativeElement.focus(); inputDebugElement.nativeElement.dispatchEvent(escapeEvent); @@ -399,7 +399,7 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); typeWordIntoSearchInput('TEST'); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -415,7 +415,7 @@ describe('SearchControlComponent', () => { xit('should select the second item on autocomplete list when ARROW DOWN is pressed on list', (done) => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('TEST'); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -426,7 +426,7 @@ describe('SearchControlComponent', () => { fixture.detectChanges(); expect(document.activeElement.id).toBe('result_option_0'); - let firstElement = debugElement.query(By.css('#result_option_0')); + const firstElement = debugElement.query(By.css('#result_option_0')); firstElement.triggerEventHandler('keyup.arrowdown', { target: firstElement.nativeElement }); fixture.detectChanges(); expect(document.activeElement.id).toBe('result_option_1'); @@ -437,7 +437,7 @@ describe('SearchControlComponent', () => { xit('should focus the input search when ARROW UP is pressed on the first list item', (done) => { searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); fixture.detectChanges(); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); typeWordIntoSearchInput('TEST'); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -448,7 +448,7 @@ describe('SearchControlComponent', () => { fixture.detectChanges(); expect(document.activeElement.id).toBe('result_option_0'); - let firstElement = debugElement.query(By.css('#result_option_0')); + const firstElement = debugElement.query(By.css('#result_option_0')); firstElement.triggerEventHandler('keyup.arrowup', { target: firstElement.nativeElement }); fixture.detectChanges(); expect(document.activeElement.id).toBe('adf-control-input'); @@ -465,7 +465,7 @@ describe('SearchControlComponent', () => { tick(100); - let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); + const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); component.subscriptAnimationState = 'active'; fixture.detectChanges(); @@ -490,7 +490,7 @@ describe('SearchControlComponent', () => { tick(100); - let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); + const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); tick(100); @@ -506,10 +506,10 @@ describe('SearchControlComponent', () => { fixture.detectChanges(); tick(100); - let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); + const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); searchButton.triggerEventHandler('click', null); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); tick(100); fixture.detectChanges(); @@ -525,7 +525,7 @@ describe('SearchControlComponent', () => { tick(100); - let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); + const searchButton: DebugElement = debugElement.query(By.css('#adf-search-button')); component.subscriptAnimationState = 'active'; fixture.detectChanges(); @@ -554,7 +554,7 @@ describe('SearchControlComponent', () => { tick(100); - let inputDebugElement = debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = debugElement.query(By.css('#adf-control-input')); component.subscriptAnimationState = 'active'; fixture.detectChanges(); @@ -579,7 +579,7 @@ describe('SearchControlComponent', () => { it('should emit a option clicked event when item is clicked', (done) => { spyOn(component, 'isSearchBarActive').and.returnValue(true); searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); - let clickDisposable = component.optionClicked.subscribe((item) => { + const clickDisposable = component.optionClicked.subscribe((item) => { expect(item.entry.id).toBe('123'); clickDisposable.unsubscribe(); done(); @@ -589,7 +589,7 @@ describe('SearchControlComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let firstOption: DebugElement = debugElement.query(By.css('#result_name_0')); + const firstOption: DebugElement = debugElement.query(By.css('#result_name_0')); firstOption.nativeElement.click(); }); }); @@ -597,7 +597,7 @@ describe('SearchControlComponent', () => { it('should set deactivate the search after element is clicked', (done) => { spyOn(component, 'isSearchBarActive').and.returnValue(true); searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); - let clickDisposable = component.optionClicked.subscribe((item) => { + const clickDisposable = component.optionClicked.subscribe((item) => { expect(component.subscriptAnimationState).toBe('inactive'); clickDisposable.unsubscribe(); done(); @@ -608,7 +608,7 @@ describe('SearchControlComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let firstOption: DebugElement = debugElement.query(By.css('#result_name_0')); + const firstOption: DebugElement = debugElement.query(By.css('#result_name_0')); firstOption.nativeElement.click(); }); }); @@ -616,7 +616,7 @@ describe('SearchControlComponent', () => { it('should NOT reset the search term after element is clicked', (done) => { spyOn(component, 'isSearchBarActive').and.returnValue(true); searchServiceSpy.and.returnValue(of(JSON.parse(JSON.stringify(results)))); - let clickDisposable = component.optionClicked.subscribe((item) => { + const clickDisposable = component.optionClicked.subscribe((item) => { expect(component.searchTerm).not.toBeFalsy(); expect(component.searchTerm).toBe('TEST'); clickDisposable.unsubscribe(); @@ -628,7 +628,7 @@ describe('SearchControlComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let firstOption: DebugElement = debugElement.query(By.css('#result_name_0')); + const firstOption: DebugElement = debugElement.query(By.css('#result_name_0')); firstOption.nativeElement.click(); }); }); @@ -649,7 +649,7 @@ describe('SearchControlComponent', () => { searchServiceSpy.and.returnValue(of(noResult)); fixtureCustom.detectChanges(); - let inputDebugElement = fixtureCustom.debugElement.query(By.css('#adf-control-input')); + const inputDebugElement = fixtureCustom.debugElement.query(By.css('#adf-control-input')); inputDebugElement.nativeElement.value = 'SOMETHING'; inputDebugElement.nativeElement.focus(); inputDebugElement.nativeElement.dispatchEvent(new Event('input')); diff --git a/lib/content-services/search/components/search-control.component.ts b/lib/content-services/search/components/search-control.component.ts index d06bd05897..e0602c00bb 100644 --- a/lib/content-services/search/components/search-control.component.ts +++ b/lib/content-services/search/components/search-control.component.ts @@ -217,20 +217,20 @@ export class SearchControlComponent implements OnInit, OnDestroy { selectFirstResult() { if ( this.listResultElement && this.listResultElement.length > 0) { - let firstElement: MatListItem = <MatListItem> this.listResultElement.first; + const firstElement: MatListItem = <MatListItem> this.listResultElement.first; firstElement._getHostElement().focus(); } } onRowArrowDown($event: KeyboardEvent): void { - let nextElement: any = this.getNextElementSibling(<Element> $event.target); + const nextElement: any = this.getNextElementSibling(<Element> $event.target); if (nextElement) { nextElement.focus(); } } onRowArrowUp($event: KeyboardEvent): void { - let previousElement: any = this.getPreviousElementSibling(<Element> $event.target); + const previousElement: any = this.getPreviousElementSibling(<Element> $event.target); if (previousElement) { previousElement.focus(); } else { diff --git a/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts b/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts index 6c6c0dd168..21c4d49c43 100644 --- a/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts +++ b/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts @@ -29,8 +29,8 @@ describe('SearchDateRangeComponent', () => { describe('component class', () => { let component: SearchDateRangeComponent; - let fromDate = '2016-10-16'; - let toDate = '2017-10-16'; + const fromDate = '2016-10-16'; + const toDate = '2017-10-16'; const localeFixture = 'it'; const dateFormatFixture = 'DD-MMM-YY'; diff --git a/lib/content-services/search/components/search-filter/models/search-filter-list.model.ts b/lib/content-services/search/components/search-filter/models/search-filter-list.model.ts index 75a1591ec1..dfb0db729b 100644 --- a/lib/content-services/search/components/search-filter/models/search-filter-list.model.ts +++ b/lib/content-services/search/components/search-filter/models/search-filter-list.model.ts @@ -127,7 +127,7 @@ export class SearchFilterList<T> implements Iterable<T> { [Symbol.iterator](): Iterator<T> { let pointer = 0; - let items = this.visibleItems; + const items = this.visibleItems; return { next(): IteratorResult<T> { diff --git a/lib/content-services/search/components/search-filter/search-filter.component.spec.ts b/lib/content-services/search/components/search-filter/search-filter.component.spec.ts index 265b7adf3c..20a5a89da9 100644 --- a/lib/content-services/search/components/search-filter/search-filter.component.spec.ts +++ b/lib/content-services/search/components/search-filter/search-filter.component.spec.ts @@ -589,7 +589,7 @@ describe('SearchFilterComponent', () => { expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledTimes(3); expect(queryBuilder.update).toHaveBeenCalled(); - for (let entry of component.responseFacets[0].buckets.items) { + for (const entry of component.responseFacets[0].buckets.items) { expect(entry.checked).toBeFalsy(); } }); diff --git a/lib/content-services/search/components/search-filter/search-filter.component.ts b/lib/content-services/search/components/search-filter/search-filter.component.ts index 178323e9aa..b41762b6ff 100644 --- a/lib/content-services/search/components/search-filter/search-filter.component.ts +++ b/lib/content-services/search/components/search-filter/search-filter.component.ts @@ -93,7 +93,7 @@ export class SearchFilterComponent implements OnInit, OnDestroy { private updateSelectedBuckets() { if (this.responseFacets) { this.selectedBuckets = []; - for (let field of this.responseFacets) { + for (const field of this.responseFacets) { if (field.buckets) { this.selectedBuckets.push( ...this.queryBuilder.getUserFacetBuckets(field.field) @@ -146,7 +146,7 @@ export class SearchFilterComponent implements OnInit, OnDestroy { resetSelectedBuckets(field: FacetField) { if (field && field.buckets) { - for (let bucket of field.buckets.items) { + for (const bucket of field.buckets.items) { bucket.checked = false; this.queryBuilder.removeUserFacetBucket(field, bucket); } @@ -158,7 +158,7 @@ export class SearchFilterComponent implements OnInit, OnDestroy { resetAllSelectedBuckets() { this.responseFacets.forEach((field) => { if (field && field.buckets) { - for (let bucket of field.buckets.items) { + for (const bucket of field.buckets.items) { bucket.checked = false; this.queryBuilder.removeUserFacetBucket(field, bucket); } diff --git a/lib/content-services/search/components/search-trigger.directive.ts b/lib/content-services/search/components/search-trigger.directive.ts index c8532cd1f3..519bbd6cc1 100644 --- a/lib/content-services/search/components/search-trigger.directive.ts +++ b/lib/content-services/search/components/search-trigger.directive.ts @@ -162,7 +162,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy { handleInput(event: KeyboardEvent): void { if (document.activeElement === event.target) { - let inputValue: string = (event.target as HTMLInputElement).value; + const inputValue: string = (event.target as HTMLInputElement).value; this.onChange(inputValue); if (inputValue) { this.searchPanel.keyPressedStream.next(inputValue); @@ -177,7 +177,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy { private isPanelOptionClicked(event: MouseEvent) { let isPanelOption: boolean = false; if ( event ) { - let clickTarget = event.target as HTMLElement; + const clickTarget = event.target as HTMLElement; isPanelOption = !this.isNoResultOption(event) && !!this.searchPanel.panel && !!this.searchPanel.panel.nativeElement.contains(clickTarget); diff --git a/lib/content-services/search/components/search.component.spec.ts b/lib/content-services/search/components/search.component.spec.ts index d300285f9b..b570033260 100644 --- a/lib/content-services/search/components/search.component.spec.ts +++ b/lib/content-services/search/components/search.component.spec.ts @@ -87,7 +87,7 @@ describe('SearchComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let message: HTMLElement = <HTMLElement> element.querySelector('#component-result-message'); + const message: HTMLElement = <HTMLElement> element.querySelector('#component-result-message'); expect(message.textContent).toBe('ERROR'); done(); }); @@ -103,13 +103,13 @@ describe('SearchComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let optionShowed = element.querySelectorAll('#autocomplete-search-result-list'); + const optionShowed = element.querySelectorAll('#autocomplete-search-result-list'); expect(optionShowed).not.toBeNull(); component.forceHidePanel(); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let elementList = element.querySelector('#adf-search-results-content'); + const elementList = element.querySelector('#adf-search-results-content'); expect(elementList.classList).toContain('adf-search-hide'); done(); }); @@ -125,9 +125,9 @@ describe('SearchComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let optionShowed = element.querySelectorAll('#autocomplete-search-result-list > li').length; + const optionShowed = element.querySelectorAll('#autocomplete-search-result-list > li').length; expect(optionShowed).toBe(1); - let folderOption: HTMLElement = <HTMLElement> element.querySelector('#result_option_0'); + const folderOption: HTMLElement = <HTMLElement> element.querySelector('#result_option_0'); expect(folderOption.textContent.trim()).toBe('MyDoc'); done(); }); diff --git a/lib/content-services/search/search-query-builder.service.ts b/lib/content-services/search/search-query-builder.service.ts index eb92866766..b0ae03c1b0 100644 --- a/lib/content-services/search/search-query-builder.service.ts +++ b/lib/content-services/search/search-query-builder.service.ts @@ -208,7 +208,7 @@ export class SearchQueryBuilderService { * @returns The finished query */ buildQuery(): QueryBody { - let query = this.getFinalQuery(); + const query = this.getFinalQuery(); const include = this.config.include || []; if (include.length === 0) { diff --git a/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts b/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts index 5103eb976f..d57769e849 100644 --- a/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts +++ b/lib/content-services/site-dropdown/sites-dropdown.component.spec.ts @@ -216,7 +216,7 @@ describe('DropdownSitesComponent', () => { fixture.detectChanges(); debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null); fixture.detectChanges(); - let options: any = debug.queryAll(By.css('mat-option')); + const options: any = debug.queryAll(By.css('mat-option')); expect(options[0].nativeElement.innerText).toContain('DROPDOWN.MY_FILES_OPTION'); }); })); @@ -229,7 +229,7 @@ describe('DropdownSitesComponent', () => { fixture.detectChanges(); debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null); fixture.detectChanges(); - let options: any = debug.queryAll(By.css('mat-option')); + const options: any = debug.queryAll(By.css('mat-option')); expect(options[0].nativeElement.innerText).not.toContain('DROPDOWN.MY_FILES_OPTION'); }); })); @@ -304,7 +304,7 @@ describe('DropdownSitesComponent', () => { fixture.detectChanges(); debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null); fixture.detectChanges(); - let options: any = debug.queryAll(By.css('mat-option')); + const options: any = debug.queryAll(By.css('mat-option')); expect(options[1].nativeElement.innerText).toContain('fake-test-site'); expect(options[2].nativeElement.innerText).toContain('fake-test-2'); }); @@ -317,7 +317,7 @@ describe('DropdownSitesComponent', () => { fixture.detectChanges(); debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null); fixture.detectChanges(); - let options: any = debug.queryAll(By.css('mat-option')); + const options: any = debug.queryAll(By.css('mat-option')); options[1].nativeElement.click(); fixture.detectChanges(); }); @@ -489,7 +489,7 @@ describe('DropdownSitesComponent', () => { debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null); fixture.detectChanges(); fixture.whenStable().then(() => { - let options: any = debug.queryAll(By.css('mat-option')); + const options: any = debug.queryAll(By.css('mat-option')); expect(options[1].nativeElement.innerText).toContain('FAKE-SITE-PUBLIC'); expect(options[2].nativeElement.innerText).toContain('FAKE-PRIVATE-SITE-MEMBER'); expect(options[3]).toBeUndefined(); @@ -513,7 +513,7 @@ describe('DropdownSitesComponent', () => { debug.query(By.css('.mat-select-trigger')).triggerEventHandler('click', null); fixture.detectChanges(); fixture.whenStable().then(() => { - let options: any = debug.queryAll(By.css('mat-option')); + const options: any = debug.queryAll(By.css('mat-option')); expect(options[1].nativeElement.innerText).toContain('FAKE-MODERATED-SITE'); expect(options[2].nativeElement.innerText).toContain('FAKE-SITE-PUBLIC'); expect(options[3].nativeElement.innerText).toContain('FAKE-PRIVATE-SITE-MEMBER'); diff --git a/lib/content-services/site-dropdown/sites-dropdown.component.ts b/lib/content-services/site-dropdown/sites-dropdown.component.ts index d77d29dea4..fbc0954949 100644 --- a/lib/content-services/site-dropdown/sites-dropdown.component.ts +++ b/lib/content-services/site-dropdown/sites-dropdown.component.ts @@ -114,7 +114,7 @@ export class DropdownSitesComponent implements OnInit { } private loadSiteList() { - let extendedOptions: any = { + const extendedOptions: any = { skipCount: this.skipCount, maxItems: this.MAX_ITEMS }; @@ -131,7 +131,7 @@ export class DropdownSitesComponent implements OnInit { this.siteList = this.relations === Relations.Members ? this.filteredResultsByMember(sitePaging) : sitePaging; if (!this.hideMyFiles) { - let siteEntry = new SiteEntry({ + const siteEntry = new SiteEntry({ entry: { id: '-my-', guid: '-my-', @@ -147,7 +147,7 @@ export class DropdownSitesComponent implements OnInit { } } else { - let siteList: SitePaging = this.relations === Relations.Members ? this.filteredResultsByMember(sitePaging) : sitePaging; + const siteList: SitePaging = this.relations === Relations.Members ? this.filteredResultsByMember(sitePaging) : sitePaging; this.siteList.list.entries = this.siteList.list.entries.concat(siteList.list.entries); this.siteList.list.pagination = sitePaging.list.pagination; diff --git a/lib/content-services/social/like.component.spec.ts b/lib/content-services/social/like.component.spec.ts index c3f4ef642c..a32c4d958e 100644 --- a/lib/content-services/social/like.component.spec.ts +++ b/lib/content-services/social/like.component.spec.ts @@ -67,7 +67,7 @@ describe('Like component', () => { } })); - let likeButton: any = element.querySelector('#adf-like-test-id'); + const likeButton: any = element.querySelector('#adf-like-test-id'); likeButton.click(); fixture.whenStable().then(() => { @@ -81,7 +81,7 @@ describe('Like component', () => { component.isLike = true; - let likeButton: any = element.querySelector('#adf-like-test-id'); + const likeButton: any = element.querySelector('#adf-like-test-id'); likeButton.click(); fixture.whenStable().then(() => { diff --git a/lib/content-services/social/rating.component.spec.ts b/lib/content-services/social/rating.component.spec.ts index 62294780b2..c110319405 100644 --- a/lib/content-services/social/rating.component.spec.ts +++ b/lib/content-services/social/rating.component.spec.ts @@ -125,7 +125,7 @@ describe('Rating component', () => { done(); }); - let starThree: any = element.querySelector('#adf-colored-star-3'); + const starThree: any = element.querySelector('#adf-colored-star-3'); starThree.click(); }); diff --git a/lib/content-services/social/rating.component.ts b/lib/content-services/social/rating.component.ts index b4bbdc2d1f..32e2614668 100644 --- a/lib/content-services/social/rating.component.ts +++ b/lib/content-services/social/rating.component.ts @@ -45,7 +45,7 @@ export class RatingComponent implements OnChanges { } ngOnChanges() { - let ratingObserver = this.ratingService.getRating(this.nodeId, this.ratingType); + const ratingObserver = this.ratingService.getRating(this.nodeId, this.ratingType); ratingObserver.subscribe( (ratingEntry: RatingEntry) => { diff --git a/lib/content-services/social/services/rating.service.spec.ts b/lib/content-services/social/services/rating.service.spec.ts index 48fcbc16e0..5e236019fa 100644 --- a/lib/content-services/social/services/rating.service.spec.ts +++ b/lib/content-services/social/services/rating.service.spec.ts @@ -43,8 +43,8 @@ describe('Rating service', () => { }); it('Should get rating return an Observable', (done) => { - let ratingType: string = 'fiveStar'; - let nodeId: string = 'fake-node-id'; + const ratingType: string = 'fiveStar'; + const nodeId: string = 'fake-node-id'; service.getRating(nodeId, ratingType).subscribe((data) => { expect(data.entry.myRating).toBe('1'); @@ -66,8 +66,8 @@ describe('Rating service', () => { }); it('Should post rating return an Observable', (done) => { - let ratingType: string = 'fiveStar'; - let nodeId: string = 'fake-node-id'; + const ratingType: string = 'fiveStar'; + const nodeId: string = 'fake-node-id'; service.postRating(nodeId, ratingType, 3).subscribe((data) => { expect(data.entry.myRating).toBe('3'); diff --git a/lib/content-services/social/services/rating.service.ts b/lib/content-services/social/services/rating.service.ts index 2e53bfbb09..9d8734de75 100644 --- a/lib/content-services/social/services/rating.service.ts +++ b/lib/content-services/social/services/rating.service.ts @@ -51,7 +51,7 @@ export class RatingService { * @returns Details about the rating, including the new value */ postRating(nodeId: string, ratingType: string, vote: any): Observable<RatingEntry | {}> { - let ratingBody: RatingBody = new RatingBody({ + const ratingBody: RatingBody = new RatingBody({ 'id': ratingType, 'myRating': vote }); diff --git a/lib/content-services/tag/services/tag.service.ts b/lib/content-services/tag/services/tag.service.ts index 667c0f04ee..ad1b845818 100644 --- a/lib/content-services/tag/services/tag.service.ts +++ b/lib/content-services/tag/services/tag.service.ts @@ -65,7 +65,7 @@ export class TagService { const tagBody = new TagBody(); tagBody.tag = tagName; - let observableAdd = from(this.apiService.getInstance().core.tagsApi.addTag(nodeId, tagBody)); + const observableAdd = from(this.apiService.getInstance().core.tagsApi.addTag(nodeId, tagBody)); observableAdd.subscribe((tagEntry: TagEntry) => { this.refresh.emit(tagEntry); diff --git a/lib/content-services/tag/tag-actions.component.spec.ts b/lib/content-services/tag/tag-actions.component.spec.ts index 02797e29c0..303401d741 100644 --- a/lib/content-services/tag/tag-actions.component.spec.ts +++ b/lib/content-services/tag/tag-actions.component.spec.ts @@ -44,7 +44,7 @@ describe('TagActionsComponent', () => { fixture.destroy(); }); - let dataTag = { + const dataTag = { 'list': { 'pagination': { 'count': 3, @@ -103,7 +103,7 @@ describe('TagActionsComponent', () => { component.result.subscribe(() => { fixture.detectChanges(); - let deleteButton: any = element.querySelector('#tag_delete_test1'); + const deleteButton: any = element.querySelector('#tag_delete_test1'); deleteButton.click(); expect(jasmine.Ajax.requests.at(1).url) @@ -140,7 +140,7 @@ describe('TagActionsComponent', () => { component.result.subscribe(() => { fixture.detectChanges(); - let addButton: any = element.querySelector('#add-tag'); + const addButton: any = element.querySelector('#add-tag'); addButton.click(); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -172,7 +172,7 @@ describe('TagActionsComponent', () => { component.result.subscribe(() => { fixture.detectChanges(); - let addButton: any = element.querySelector('#add-tag'); + const addButton: any = element.querySelector('#add-tag'); addButton.click(); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -195,7 +195,7 @@ describe('TagActionsComponent', () => { fixture.detectChanges(); - let addButton: any = element.querySelector('#add-tag'); + const addButton: any = element.querySelector('#add-tag'); expect(addButton.disabled).toEqual(true); }); @@ -212,7 +212,7 @@ describe('TagActionsComponent', () => { component.result.subscribe(() => { fixture.detectChanges(); - let addButton: any = element.querySelector('#add-tag'); + const addButton: any = element.querySelector('#add-tag'); addButton.click(); }); @@ -230,7 +230,7 @@ describe('TagActionsComponent', () => { component.newTagName = 'fake-tag-name'; component.result.subscribe(() => { - let addButton: any = element.querySelector('#add-tag'); + const addButton: any = element.querySelector('#add-tag'); expect(addButton.disabled).toEqual(true); done(); }); @@ -249,7 +249,7 @@ describe('TagActionsComponent', () => { component.result.subscribe(() => { fixture.detectChanges(); - let addButton: any = element.querySelector('#add-tag'); + const addButton: any = element.querySelector('#add-tag'); expect(addButton.disabled).toEqual(false); done(); }); diff --git a/lib/content-services/tag/tag-list.component.spec.ts b/lib/content-services/tag/tag-list.component.spec.ts index 86b89b41c1..0155dbaf77 100644 --- a/lib/content-services/tag/tag-list.component.spec.ts +++ b/lib/content-services/tag/tag-list.component.spec.ts @@ -24,7 +24,7 @@ import { ContentTestingModule } from '../testing/content.testing.module'; describe('TagList', () => { - let dataTag = { + const dataTag = { 'list': { 'pagination': { 'count': 3, @@ -51,7 +51,7 @@ describe('TagList', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; tagService = TestBed.get(TagService); diff --git a/lib/content-services/tag/tag-node-list.component.spec.ts b/lib/content-services/tag/tag-node-list.component.spec.ts index 5c25a41163..62124986ae 100644 --- a/lib/content-services/tag/tag-node-list.component.spec.ts +++ b/lib/content-services/tag/tag-node-list.component.spec.ts @@ -24,7 +24,7 @@ import { ContentTestingModule } from '../testing/content.testing.module'; describe('TagNodeList', () => { - let dataTag = { + const dataTag = { 'list': { 'pagination': { 'count': 3, @@ -51,7 +51,7 @@ describe('TagNodeList', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; fixture = TestBed.createComponent(TagNodeListComponent); @@ -94,7 +94,7 @@ describe('TagNodeList', () => { component.results.subscribe(() => { fixture.detectChanges(); - let deleteButton: any = element.querySelector('#tag_chips_delete_test1'); + const deleteButton: any = element.querySelector('#tag_chips_delete_test1'); deleteButton.click(); expect(tagService.removeTag).toHaveBeenCalledWith('fake-node-id', '0ee933fa-57fc-4587-8a77-b787e814f1d2'); @@ -111,7 +111,7 @@ describe('TagNodeList', () => { component.results.subscribe(() => { fixture.detectChanges(); - let deleteButton: any = element.querySelector('#tag_chips_delete_test1'); + const deleteButton: any = element.querySelector('#tag_chips_delete_test1'); expect(deleteButton).toBeNull(); done(); }); @@ -126,7 +126,7 @@ describe('TagNodeList', () => { component.results.subscribe(() => { fixture.detectChanges(); - let deleteButton: any = element.querySelector('#tag_chips_delete_test1'); + const deleteButton: any = element.querySelector('#tag_chips_delete_test1'); expect(deleteButton).not.toBeNull(); done(); }); diff --git a/lib/content-services/tree-view/components/tree-view.component.spec.ts b/lib/content-services/tree-view/components/tree-view.component.spec.ts index 2a8cea3bf9..7786e84c48 100644 --- a/lib/content-services/tree-view/components/tree-view.component.spec.ts +++ b/lib/content-services/tree-view/components/tree-view.component.spec.ts @@ -32,19 +32,19 @@ describe('TreeViewComponent', () => { let treeService: TreeViewService; let component: any; - let fakeNodeList: TreeBaseNode[] = [ + const fakeNodeList: TreeBaseNode[] = [ <TreeBaseNode> { nodeId: 'fake-node-id', name: 'fake-node-name', level: 0, expandable: true, node: { entry: { name: 'fake-node-name', id: 'fake-node-id' } } } ]; - let fakeChildrenList: TreeBaseNode[] = [ + const fakeChildrenList: TreeBaseNode[] = [ <TreeBaseNode> { nodeId: 'fake-child-id', name: 'fake-child-name', level: 0, expandable: true, node: {} }, <TreeBaseNode> { nodeId: 'fake-second-id', name: 'fake-second-name', level: 0, expandable: true, node: {} } ]; - let fakeNextChildrenList: TreeBaseNode[] = [ + const fakeNextChildrenList: TreeBaseNode[] = [ <TreeBaseNode> { nodeId: 'fake-next-child-id', name: 'fake-next-child-name', @@ -61,7 +61,7 @@ describe('TreeViewComponent', () => { } ]; - let returnRootOrChildrenNode = function (nodeId: string) { + const returnRootOrChildrenNode = function (nodeId: string) { if (nodeId === '9999999') { return of(fakeNodeList); } else if (nodeId === 'fake-second-id') { @@ -101,7 +101,7 @@ describe('TreeViewComponent', () => { })); it('should show the subfolders when the folder is clicked', async(() => { - let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); + const rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); expect(rootFolderButton).not.toBeNull(); rootFolderButton.click(); fixture.detectChanges(); @@ -117,7 +117,7 @@ describe('TreeViewComponent', () => { component.ngOnChanges({ 'nodeId': changeNodeId }); fixture.detectChanges(); fixture.whenStable().then(() => { - let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-next-child-name'); + const rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-next-child-name'); expect(rootFolderButton).not.toBeNull(); rootFolderButton.click(); fixture.detectChanges(); @@ -137,13 +137,13 @@ describe('TreeViewComponent', () => { expect(nodeClicked.entry.id).toBe('fake-node-id'); done(); }); - let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); + const rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); expect(rootFolderButton).not.toBeNull(); rootFolderButton.click(); }); it('should change the icon of the opened folders', async(() => { - let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); + const rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); expect(rootFolderButton).not.toBeNull(); expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder'); rootFolderButton.click(); @@ -154,13 +154,13 @@ describe('TreeViewComponent', () => { })); it('should show the subfolders of a subfolder if there are any', async(() => { - let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); + const rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); expect(rootFolderButton).not.toBeNull(); rootFolderButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { expect(element.querySelector('#fake-second-name-tree-child-node')).not.toBeNull(); - let childButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-second-name'); + const childButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-second-name'); expect(childButton).not.toBeNull(); childButton.click(); fixture.detectChanges(); @@ -172,7 +172,7 @@ describe('TreeViewComponent', () => { })); it('should hide the subfolders when clicked again', async(() => { - let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); + const rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name'); expect(rootFolderButton).not.toBeNull(); rootFolderButton.click(); fixture.detectChanges(); diff --git a/lib/content-services/tree-view/services/tree-view.service.spec.ts b/lib/content-services/tree-view/services/tree-view.service.spec.ts index 85e2dd7cd8..863f93f636 100644 --- a/lib/content-services/tree-view/services/tree-view.service.spec.ts +++ b/lib/content-services/tree-view/services/tree-view.service.spec.ts @@ -27,11 +27,11 @@ describe('TreeViewService', () => { let service: TreeViewService; let nodeService: NodesApiService; - let fakeNodeList = { list: { entries: [ + const fakeNodeList = { list: { entries: [ { entry: { id: 'fake-node-id', name: 'fake-node-name', isFolder: true } } ] } }; - let fakeMixedNodeList = { list: { entries: [ + const fakeMixedNodeList = { list: { entries: [ { entry: { id: 'fake-node-id', name: 'fake-node-name', isFolder: true } }, { entry: { id: 'fake-file-id', name: 'fake-file-name', isFolder: false } } ] } }; diff --git a/lib/content-services/upload/components/base-upload/upload-base.ts b/lib/content-services/upload/components/base-upload/upload-base.ts index 71e67ce144..737bc077c4 100644 --- a/lib/content-services/upload/components/base-upload/upload-base.ts +++ b/lib/content-services/upload/components/base-upload/upload-base.ts @@ -116,7 +116,7 @@ export abstract class UploadBase implements OnInit, OnDestroy { } private uploadQueue(files: FileModel[]) { - let filteredFiles = files + const filteredFiles = files .filter(this.isFileAcceptable.bind(this)) .filter(this.isFileSizeAcceptable.bind(this)); diff --git a/lib/content-services/upload/components/file-uploading-dialog.component.ts b/lib/content-services/upload/components/file-uploading-dialog.component.ts index 69d3b35a12..3542806280 100644 --- a/lib/content-services/upload/components/file-uploading-dialog.component.ts +++ b/lib/content-services/upload/components/file-uploading-dialog.component.ts @@ -88,7 +88,7 @@ export class FileUploadingDialogComponent implements OnInit, OnDestroy { this.uploadService.fileDeleted.subscribe((objId) => { if (this.filesUploadingList) { - let file = this.filesUploadingList.find((item) => { + const file = this.filesUploadingList.find((item) => { return item.data.entry.id === objId; }); if (file) { diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts b/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts index 20462505e1..97460b2e79 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts +++ b/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts @@ -23,7 +23,7 @@ import { FileUploadingListRowComponent } from './file-uploading-list-row.compone describe('FileUploadingListRowComponent', () => { let fixture: ComponentFixture<FileUploadingListRowComponent>; let component: FileUploadingListRowComponent; - let file = new FileModel(<File> { name: 'fake-name' }); + const file = new FileModel(<File> { name: 'fake-name' }); beforeEach(() => { TestBed.configureTestingModule({ diff --git a/lib/content-services/upload/components/upload-button.component.spec.ts b/lib/content-services/upload/components/upload-button.component.spec.ts index 8d15a2e816..fbb35d6433 100644 --- a/lib/content-services/upload/components/upload-button.component.spec.ts +++ b/lib/content-services/upload/components/upload-button.component.spec.ts @@ -26,15 +26,15 @@ import { NodeEntry } from '@alfresco/js-api'; describe('UploadButtonComponent', () => { - let file = { name: 'fake-name-1', size: 10, webkitRelativePath: 'fake-folder1/fake-name-1.json' }; - let fakeEvent = { + const file = { name: 'fake-name-1', size: 10, webkitRelativePath: 'fake-folder1/fake-name-1.json' }; + const fakeEvent = { currentTarget: { files: [file] }, target: { value: 'fake-name-1' } }; - let fakeFolderNodeWithPermission = new NodeEntry({ + const fakeFolderNodeWithPermission = new NodeEntry({ entry: { allowableOperations: [ 'create', @@ -82,21 +82,21 @@ describe('UploadButtonComponent', () => { it('should render upload-single-file button as default', () => { component.multipleFiles = false; - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; fixture.detectChanges(); expect(compiled.querySelector('#upload-single-file')).toBeDefined(); }); it('should render upload-multiple-file button if multipleFiles is true', () => { component.multipleFiles = true; - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; fixture.detectChanges(); expect(compiled.querySelector('#upload-multiple-files')).toBeDefined(); }); it('should render an uploadFolder button if uploadFolder is true', () => { component.uploadFolders = true; - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; fixture.detectChanges(); expect(compiled.querySelector('#uploadFolder')).toBeDefined(); }); @@ -104,7 +104,7 @@ describe('UploadButtonComponent', () => { it('should disable uploadFolder button if disabled is true', () => { component.disabled = true; component.uploadFolders = true; - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; fixture.detectChanges(); expect(compiled.querySelector('#uploadFolder').getAttribute('disabled')).toBe('true'); }); @@ -112,7 +112,7 @@ describe('UploadButtonComponent', () => { it('should disable upload-single-file button if disabled is true', () => { component.disabled = true; component.multipleFiles = false; - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; fixture.detectChanges(); expect(compiled.querySelector('#upload-single-file').getAttribute('disabled')).toBe('true'); }); @@ -182,7 +182,7 @@ describe('UploadButtonComponent', () => { }); it('should by default the title of the button get from the JSON file', () => { - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; fixture.detectChanges(); component.uploadFolders = false; component.multipleFiles = false; @@ -199,7 +199,7 @@ describe('UploadButtonComponent', () => { }); it('should staticTitle properties change the title of the upload buttons', () => { - let compiled = fixture.debugElement.nativeElement; + const compiled = fixture.debugElement.nativeElement; component.staticTitle = 'test-text'; component.uploadFolders = false; component.multipleFiles = false; diff --git a/lib/content-services/upload/components/upload-button.component.ts b/lib/content-services/upload/components/upload-button.component.ts index 1b1244b162..8159eb6658 100644 --- a/lib/content-services/upload/components/upload-button.component.ts +++ b/lib/content-services/upload/components/upload-button.component.ts @@ -78,7 +78,7 @@ export class UploadButtonComponent extends UploadBase implements OnInit, OnChang } ngOnChanges(changes: SimpleChanges) { - let rootFolderId = changes['rootFolderId']; + const rootFolderId = changes['rootFolderId']; if (rootFolderId && rootFolderId.currentValue) { this.checkPermission(); } @@ -89,7 +89,7 @@ export class UploadButtonComponent extends UploadBase implements OnInit, OnChang } onFilesAdded($event: any): void { - let files: File[] = FileUtils.toFileArray($event.currentTarget.files); + const files: File[] = FileUtils.toFileArray($event.currentTarget.files); if (this.hasAllowableOperations) { this.uploadFiles(files); @@ -102,7 +102,7 @@ export class UploadButtonComponent extends UploadBase implements OnInit, OnChang onDirectoryAdded($event: any): void { if (this.hasAllowableOperations) { - let files: File[] = FileUtils.toFileArray($event.currentTarget.files); + const files: File[] = FileUtils.toFileArray($event.currentTarget.files); this.uploadFiles(files); } else { this.permissionEvent.emit(new PermissionModel({ type: 'content', action: 'upload', permission: 'create' })); @@ -113,7 +113,7 @@ export class UploadButtonComponent extends UploadBase implements OnInit, OnChang checkPermission() { if (this.rootFolderId) { - let opts: any = { + const opts: any = { includeSource: true, include: ['allowableOperations'] }; diff --git a/lib/content-services/upload/components/upload-drag-area.component.spec.ts b/lib/content-services/upload/components/upload-drag-area.component.spec.ts index 7e6a958221..2a67c93c6e 100644 --- a/lib/content-services/upload/components/upload-drag-area.component.spec.ts +++ b/lib/content-services/upload/components/upload-drag-area.component.spec.ts @@ -163,7 +163,7 @@ describe('UploadDragAreaComponent', () => { spyOn(uploadService, 'uploadFilesInTheQueue'); fixture.detectChanges(); - let itemEntity = { + const itemEntity = { isDirectory: true, createReader: () => { return { @@ -187,20 +187,20 @@ describe('UploadDragAreaComponent', () => { spyOn(uploadService, 'addToQueue'); spyOn(uploadService, 'uploadFilesInTheQueue'); - let fakeItem = { + const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, isFile: true, relativeFolder: '/', name: 'file-fake.png', file: (callbackFile) => { - let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); callbackFile(fileFake); } }; fixture.detectChanges(); - let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { detail: { data: getFakeShareDataRow([]), files: [fakeItem] } }); component.onUploadFiles(fakeCustomEvent); @@ -288,19 +288,19 @@ describe('UploadDragAreaComponent', () => { })); it('should upload a file when user has create permission on target folder', async(() => { - let fakeItem = { + const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, isFile: true, name: 'file-fake.png', relativeFolder: '/', file: (callbackFile) => { - let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); callbackFile(fileFake); } }; - let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { detail: { data: getFakeShareDataRow(), files: [fakeItem] @@ -313,14 +313,14 @@ describe('UploadDragAreaComponent', () => { it('should upload a file to a specific target folder when dropped onto one', async(() => { - let fakeItem = { + const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, isFile: true, name: 'file-fake.png', relativeFolder: '/', file: (callbackFile) => { - let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); callbackFile(fileFake); } }; @@ -330,7 +330,7 @@ describe('UploadDragAreaComponent', () => { expect(fileList.options.path).toBe('pippo/'); }); - let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { detail: { data: getFakeShareDataRow(), files: [fakeItem] @@ -342,14 +342,14 @@ describe('UploadDragAreaComponent', () => { it('should upload a folder to a specific target folder when dropped onto one', async(() => { - let fakeItem = { + const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, isFile: true, name: 'file-fake.png', relativeFolder: '/super', file: (callbackFile) => { - let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); callbackFile(fileFake); } }; @@ -359,7 +359,7 @@ describe('UploadDragAreaComponent', () => { expect(fileList.options.path).toBe('pippo/super'); }); - let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { detail: { data: getFakeShareDataRow(), files: [fakeItem] @@ -371,14 +371,14 @@ describe('UploadDragAreaComponent', () => { it('should upload the file in the current folder when the target is file', async(() => { - let fakeItem = { + const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, isFile: true, name: 'file-fake.png', relativeFolder: '/', file: (callbackFile) => { - let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); callbackFile(fileFake); } }; @@ -388,7 +388,7 @@ describe('UploadDragAreaComponent', () => { expect(fileList.options.path).toBe('/'); }); - let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { detail: { data: getFakeFileShareRow(), files: [fakeItem] @@ -404,14 +404,14 @@ describe('UploadDragAreaComponent', () => { it('should raise an error if upload a file goes wrong', (done) => { spyOn(uploadService, 'getUploadPromise').and.callThrough(); - let fakeItem = { + const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, isFile: true, relativeFolder: '/', name: 'file-fake.png', file: (callbackFile) => { - let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); callbackFile(fileFake); } }; @@ -424,7 +424,7 @@ describe('UploadDragAreaComponent', () => { done(); }); - let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { detail: { data: getFakeShareDataRow(), files: [fakeItem] diff --git a/lib/content-services/upload/components/upload-drag-area.component.ts b/lib/content-services/upload/components/upload-drag-area.component.ts index 1010505009..ab95aa0a17 100644 --- a/lib/content-services/upload/components/upload-drag-area.component.ts +++ b/lib/content-services/upload/components/upload-drag-area.component.ts @@ -94,9 +94,9 @@ export class UploadDragAreaComponent extends UploadBase implements NodeAllowable onUploadFiles(event: CustomEvent) { event.stopPropagation(); event.preventDefault(); - let isAllowed: boolean = this.contentService.hasAllowableOperations(event.detail.data.obj.entry, AllowableOperationsEnum.CREATE); + const isAllowed: boolean = this.contentService.hasAllowableOperations(event.detail.data.obj.entry, AllowableOperationsEnum.CREATE); if (isAllowed) { - let fileInfo: FileInfo[] = event.detail.files; + const fileInfo: FileInfo[] = event.detail.files; if (this.isTargetNodeFolder(event)) { const destinationFolderName = event.detail.data.obj.entry.name; fileInfo.map((file) => file.relativeFolder = destinationFolderName ? destinationFolderName.concat(file.relativeFolder) : file.relativeFolder); diff --git a/lib/content-services/upload/directives/file-draggable.directive.spec.ts b/lib/content-services/upload/directives/file-draggable.directive.spec.ts index 18a2712e98..5420bc6ae6 100644 --- a/lib/content-services/upload/directives/file-draggable.directive.spec.ts +++ b/lib/content-services/upload/directives/file-draggable.directive.spec.ts @@ -23,7 +23,7 @@ describe('FileDraggableDirective', () => { let component: FileDraggableDirective; beforeEach( () => { - let el = new ElementRef(null); + const el = new ElementRef(null); component = new FileDraggableDirective(el, null); }); @@ -33,7 +33,7 @@ describe('FileDraggableDirective', () => { it('should not allow drag and drop when disabled', () => { component.enabled = false; - let event = new CustomEvent('custom-event'); + const event = new CustomEvent('custom-event'); spyOn(event, 'preventDefault').and.stub(); component.onDropFiles(event); component.onDragEnter(event); diff --git a/lib/content-services/version-manager/version-list.component.spec.ts b/lib/content-services/version-manager/version-list.component.spec.ts index 4984ef09eb..08350edfa4 100644 --- a/lib/content-services/version-manager/version-list.component.spec.ts +++ b/lib/content-services/version-manager/version-list.component.spec.ts @@ -176,9 +176,9 @@ describe('VersionListComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let versionFileName = fixture.debugElement.query(By.css('.adf-version-list-item-name')).nativeElement.innerText; - let versionIdText = fixture.debugElement.query(By.css('.adf-version-list-item-version')).nativeElement.innerText; - let versionComment = fixture.debugElement.query(By.css('.adf-version-list-item-comment')).nativeElement.innerText; + const versionFileName = fixture.debugElement.query(By.css('.adf-version-list-item-name')).nativeElement.innerText; + const versionIdText = fixture.debugElement.query(By.css('.adf-version-list-item-version')).nativeElement.innerText; + const versionComment = fixture.debugElement.query(By.css('.adf-version-list-item-comment')).nativeElement.innerText; expect(versionFileName).toBe('test-file-name'); expect(versionIdText).toBe('1.0'); @@ -208,7 +208,7 @@ describe('VersionListComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let versionCommentEl = fixture.debugElement.query(By.css('.adf-version-list-item-comment')); + const versionCommentEl = fixture.debugElement.query(By.css('.adf-version-list-item-comment')); expect(versionCommentEl).toBeNull(); done(); @@ -332,7 +332,7 @@ describe('VersionListComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.0"]'); + const menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.0"]'); expect(menuButton).not.toBeNull(); done(); @@ -345,7 +345,7 @@ describe('VersionListComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.0"]'); + const menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.0"]'); expect(menuButton).toBeNull(); done(); @@ -379,10 +379,10 @@ describe('VersionListComponent', () => { it('should disable delete action if is not allowed', (done) => { fixture.whenStable().then(() => { fixture.detectChanges(); - let menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); + const menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); menuButton.click(); - let deleteButton: any = document.querySelector('[id="adf-version-list-action-delete-1.1"]'); + const deleteButton: any = document.querySelector('[id="adf-version-list-action-delete-1.1"]'); expect(deleteButton.disabled).toBe(true); done(); @@ -392,10 +392,10 @@ describe('VersionListComponent', () => { it('should disable restore action if is not allowed', (done) => { fixture.whenStable().then(() => { fixture.detectChanges(); - let menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); + const menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); menuButton.click(); - let restoreButton: any = document.querySelector('[id="adf-version-list-action-restore-1.1"]'); + const restoreButton: any = document.querySelector('[id="adf-version-list-action-restore-1.1"]'); expect(restoreButton.disabled).toBe(true); done(); @@ -429,10 +429,10 @@ describe('VersionListComponent', () => { it('should enable delete action if is allowed', (done) => { fixture.whenStable().then(() => { fixture.detectChanges(); - let menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); + const menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); menuButton.click(); - let deleteButton: any = document.querySelector('[id="adf-version-list-action-delete-1.1"]'); + const deleteButton: any = document.querySelector('[id="adf-version-list-action-delete-1.1"]'); expect(deleteButton.disabled).toBe(false); done(); @@ -442,10 +442,10 @@ describe('VersionListComponent', () => { it('should enable restore action if is allowed', (done) => { fixture.whenStable().then(() => { fixture.detectChanges(); - let menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); + const menuButton = fixture.nativeElement.querySelector('[id="adf-version-list-action-menu-button-1.1"]'); menuButton.click(); - let restoreButton: any = document.querySelector('[id="adf-version-list-action-restore-1.1"]'); + const restoreButton: any = document.querySelector('[id="adf-version-list-action-restore-1.1"]'); expect(restoreButton.disabled).toBe(false); done(); diff --git a/lib/content-services/version-manager/version-manager.component.spec.ts b/lib/content-services/version-manager/version-manager.component.spec.ts index 8aeacef8e9..1d25d7a64a 100644 --- a/lib/content-services/version-manager/version-manager.component.spec.ts +++ b/lib/content-services/version-manager/version-manager.component.spec.ts @@ -78,7 +78,7 @@ describe('VersionManagerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let versionCommentEl = fixture.debugElement.query(By.css('.adf-version-list-item-comment')); + const versionCommentEl = fixture.debugElement.query(By.css('.adf-version-list-item-comment')); expect(versionCommentEl).not.toBeNull(); expect(versionCommentEl.nativeElement.innerText).toBe(expectedComment); @@ -91,7 +91,7 @@ describe('VersionManagerComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let versionCommentEl = fixture.debugElement.query(By.css('.adf-version-list-item-comment')); + const versionCommentEl = fixture.debugElement.query(By.css('.adf-version-list-item-comment')); expect(versionCommentEl).toBeNull(); }); @@ -128,7 +128,7 @@ describe('VersionManagerComponent', () => { it('should upload button be visible after click on add new version button', () => { fixture.detectChanges(); - let showUploadButton = fixture.debugElement.query(By.css('#adf-show-version-upload-button')); + const showUploadButton = fixture.debugElement.query(By.css('#adf-show-version-upload-button')); showUploadButton.nativeElement.click(); diff --git a/lib/content-services/webscript/webscript.component.spec.ts b/lib/content-services/webscript/webscript.component.spec.ts index 6385c6a67e..ad19f6b8a4 100644 --- a/lib/content-services/webscript/webscript.component.spec.ts +++ b/lib/content-services/webscript/webscript.component.spec.ts @@ -37,7 +37,7 @@ describe('WebscriptComponent', () => { }); beforeEach(async(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; fixture = TestBed.createComponent(WebscriptComponent); @@ -162,7 +162,7 @@ describe('WebscriptComponent', () => { done(); }); - let dataTable = { + const dataTable = { data: [ {id: 1, name: 'Name 1'}, {id: 2, name: 'Name 2'} @@ -200,7 +200,7 @@ describe('WebscriptComponent', () => { done(); }); - let dataTable = { + const dataTable = { data: [ {id: 1, name: 'Name 1'}, {id: 2, name: 'Name 2'} diff --git a/lib/content-services/webscript/webscript.component.ts b/lib/content-services/webscript/webscript.component.ts index 3dfe87d760..e8c396f5e7 100644 --- a/lib/content-services/webscript/webscript.component.ts +++ b/lib/content-services/webscript/webscript.component.ts @@ -119,7 +119,7 @@ export class WebscriptComponent implements OnChanges { * @returns the data as datatable */ showDataAsDataTable(data: any) { - let datatableData: any = null; + const datatableData: any = null; try { if (!data.schema) { diff --git a/lib/core/buttons-menu/buttons-menu.component.spec.ts b/lib/core/buttons-menu/buttons-menu.component.spec.ts index e83a05a8e2..aa5784018d 100644 --- a/lib/core/buttons-menu/buttons-menu.component.spec.ts +++ b/lib/core/buttons-menu/buttons-menu.component.spec.ts @@ -92,7 +92,7 @@ describe('ButtonsMenuComponent', () => { it('should trigger event when a specific button is clicked', async(() => { expect(component.value).toBeUndefined(); - let button = element.querySelector('button'); + const button = element.querySelector('button'); button.click(); fixture.detectChanges(); fixture.whenStable().then(() => { diff --git a/lib/core/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts b/lib/core/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts index 847d674fac..f97b6ac4c7 100644 --- a/lib/core/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-boolitem/card-view-boolitem.component.spec.ts @@ -56,11 +56,11 @@ describe('CardViewBoolItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let label = fixture.debugElement.query(By.css('.adf-property-label')); + const label = fixture.debugElement.query(By.css('.adf-property-label')); expect(label).not.toBeNull(); expect(label.nativeElement.innerText).toBe('Boolean label'); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); }); @@ -70,10 +70,10 @@ describe('CardViewBoolItemComponent', () => { component.property.editable = false; fixture.detectChanges(); - let label = fixture.debugElement.query(By.css('.adf-property-label')); + const label = fixture.debugElement.query(By.css('.adf-property-label')); expect(label).toBeNull(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).toBeNull(); }); @@ -83,10 +83,10 @@ describe('CardViewBoolItemComponent', () => { component.property.editable = false; fixture.detectChanges(); - let label = fixture.debugElement.query(By.css('.adf-property-label')); + const label = fixture.debugElement.query(By.css('.adf-property-label')); expect(label).not.toBeNull(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); }); @@ -94,7 +94,7 @@ describe('CardViewBoolItemComponent', () => { component.property.value = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.checked).toBe(true); }); @@ -106,7 +106,7 @@ describe('CardViewBoolItemComponent', () => { component.property.default = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.checked).toBe(true); }); @@ -115,7 +115,7 @@ describe('CardViewBoolItemComponent', () => { component.property.value = false; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.checked).toBe(false); }); @@ -127,7 +127,7 @@ describe('CardViewBoolItemComponent', () => { component.property.default = false; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.checked).toBe(false); }); @@ -138,7 +138,7 @@ describe('CardViewBoolItemComponent', () => { component.property.value = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.hasAttribute('disabled')).toBe(false); }); @@ -149,7 +149,7 @@ describe('CardViewBoolItemComponent', () => { component.property.value = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.hasAttribute('disabled')).toBe(true); }); @@ -160,7 +160,7 @@ describe('CardViewBoolItemComponent', () => { component.property.value = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value input[type="checkbox"]')); expect(value).not.toBeNull(); expect(value.nativeElement.hasAttribute('disabled')).toBe(true); }); @@ -199,7 +199,7 @@ describe('CardViewBoolItemComponent', () => { component.property.value = false; fixture.detectChanges(); - let disposableUpdate = cardViewUpdateService.itemUpdated$.subscribe( + const disposableUpdate = cardViewUpdateService.itemUpdated$.subscribe( (updateNotification) => { expect(updateNotification.target).toBe(component.property); expect(updateNotification.changed).toEqual({ boolkey: true }); diff --git a/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts b/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts index 8ebe92cf5d..79610ec324 100644 --- a/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts @@ -53,11 +53,11 @@ describe('CardViewDateItemComponent', () => { it('should render the label and value', () => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('Date label'); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('Jul 10 2017'); }); @@ -75,7 +75,7 @@ describe('CardViewDateItemComponent', () => { component.displayEmpty = false; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe(''); }); @@ -93,7 +93,7 @@ describe('CardViewDateItemComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY'); }); @@ -110,7 +110,7 @@ describe('CardViewDateItemComponent', () => { component.editable = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY'); }); @@ -120,7 +120,7 @@ describe('CardViewDateItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('Jul 10 2017'); }); @@ -130,8 +130,8 @@ describe('CardViewDateItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); - let datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); + const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); + const datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); expect(datePicker).not.toBeNull('Datepicker should be in DOM'); expect(datePickerToggle).not.toBeNull('Datepicker toggle should be shown'); }); @@ -140,8 +140,8 @@ describe('CardViewDateItemComponent', () => { component.property.editable = false; fixture.detectChanges(); - let datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); - let datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); + const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); + const datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); expect(datePicker).toBeNull('Datepicker should NOT be in DOM'); expect(datePickerToggle).toBeNull('Datepicker toggle should NOT be shown'); }); @@ -151,8 +151,8 @@ describe('CardViewDateItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); - let datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); + const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-${component.property.key}"]`)); + const datePickerToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepickertoggle-${component.property.key}"]`)); expect(datePicker).toBeNull('Datepicker should NOT be in DOM'); expect(datePickerToggle).toBeNull('Datepicker toggle should NOT be shown'); }); @@ -163,7 +163,7 @@ describe('CardViewDateItemComponent', () => { fixture.detectChanges(); spyOn(component.datepicker, 'open'); - let datePickerLabelToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-label-toggle-${component.property.key}"]`)); + const datePickerLabelToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-label-toggle-${component.property.key}"]`)); datePickerLabelToggle.triggerEventHandler('click', {}); expect(component.datepicker.open).toHaveBeenCalled(); @@ -176,7 +176,7 @@ describe('CardViewDateItemComponent', () => { const expectedDate = moment('Jul 10 2017', 'MMM DD YY'); fixture.detectChanges(); - let disposableUpdate = cardViewUpdateService.itemUpdated$.subscribe( + const disposableUpdate = cardViewUpdateService.itemUpdated$.subscribe( (updateNotification) => { expect(updateNotification.target).toBe(component.property); expect(updateNotification.changed).toEqual({ dateKey: expectedDate.toDate() }); diff --git a/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.ts b/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.ts index c8560a0b6b..33174b3737 100644 --- a/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.ts +++ b/lib/core/card-view/components/card-view-dateitem/card-view-dateitem.component.ts @@ -87,7 +87,7 @@ export class CardViewDateItemComponent implements OnInit { onDateChanged(newDateValue) { if (newDateValue) { - let momentDate = moment(newDateValue.value, this.SHOW_FORMAT, true); + const momentDate = moment(newDateValue.value, this.SHOW_FORMAT, true); if (momentDate.isValid()) { this.valueDate = momentDate; this.cardViewUpdateService.update(this.property, momentDate.toDate()); diff --git a/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts index 7bcdc3e7da..c68a73dac7 100644 --- a/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts @@ -92,8 +92,8 @@ describe('CardViewKeyValuePairsItemComponent', () => { const content = fixture.debugElement.query(By.css('.adf-card-view__key-value-pairs')); expect(content).not.toBeNull(); - let nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`)); - let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); + const nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`)); + const valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); expect(nameInput).not.toBeNull(); expect(valueInput).not.toBeNull(); @@ -129,8 +129,8 @@ describe('CardViewKeyValuePairsItemComponent', () => { addButton.triggerEventHandler('click', null); fixture.detectChanges(); - let nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`)); - let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); + const nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`)); + const valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); nameInput.nativeElement.value = mockData[0].name; nameInput.nativeElement.dispatchEvent(new Event('input')); @@ -157,7 +157,7 @@ describe('CardViewKeyValuePairsItemComponent', () => { addButton.triggerEventHandler('click', null); fixture.detectChanges(); - let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); + const valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`)); valueInput.nativeElement.value = mockData[0].value; valueInput.nativeElement.dispatchEvent(new Event('input')); diff --git a/lib/core/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts b/lib/core/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts index 0d2cea634c..d730457272 100644 --- a/lib/core/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts @@ -59,11 +59,11 @@ describe('CardViewMapItemComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - let labelValue = debug.query(By.css('.adf-property-label')); + const labelValue = debug.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('Map label'); - let value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); + const value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('Fake default'); }); @@ -79,10 +79,10 @@ describe('CardViewMapItemComponent', () => { component.displayEmpty = false; fixture.detectChanges(); - let labelValue = debug.query(By.css('.adf-property-label')); + const labelValue = debug.query(By.css('.adf-property-label')); expect(labelValue).toBeNull(); - let value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); + const value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe(''); }); @@ -97,11 +97,11 @@ describe('CardViewMapItemComponent', () => { fixture.detectChanges(); - let labelValue = debug.query(By.css('.adf-property-label')); + const labelValue = debug.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('Map label'); - let value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); + const value = debug.query(By.css(`[data-automation-id="card-mapitem-value-${component.property.key}"]`)); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('fakeProcessName'); }); @@ -116,9 +116,9 @@ describe('CardViewMapItemComponent', () => { }); fixture.detectChanges(); - let value: any = element.querySelector('.adf-mapitem-clickable-value'); + const value: any = element.querySelector('.adf-mapitem-clickable-value'); - let disposableUpdate = service.itemClicked$.subscribe((response) => { + const disposableUpdate = service.itemClicked$.subscribe((response) => { expect(response.target).not.toBeNull(); expect(response.target.type).toEqual('map'); expect(response.target.clickable).toBeTruthy(); diff --git a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts index 2d1a5153e4..598aff93ff 100644 --- a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts @@ -53,11 +53,11 @@ describe('CardViewTextItemComponent', () => { it('should render the label and value', () => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('Text label'); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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('Lorem ipsum'); }); @@ -73,7 +73,7 @@ describe('CardViewTextItemComponent', () => { component.displayEmpty = false; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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(''); }); @@ -89,7 +89,7 @@ describe('CardViewTextItemComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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'); }); @@ -105,7 +105,7 @@ describe('CardViewTextItemComponent', () => { component.editable = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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'); }); @@ -121,7 +121,7 @@ describe('CardViewTextItemComponent', () => { component.displayEmpty = false; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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(''); }); @@ -137,7 +137,7 @@ describe('CardViewTextItemComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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'); }); @@ -152,7 +152,7 @@ describe('CardViewTextItemComponent', () => { }); fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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'); }); @@ -168,7 +168,7 @@ describe('CardViewTextItemComponent', () => { }); fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); + const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('FAKE-ICON'); }); @@ -183,7 +183,7 @@ describe('CardViewTextItemComponent', () => { }); fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); + const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); expect(value).toBeNull('Edit icon should NOT be shown'); }); @@ -198,7 +198,7 @@ describe('CardViewTextItemComponent', () => { }); fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); + const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); expect(value).toBeNull('Edit icon should NOT be shown'); }); @@ -207,7 +207,7 @@ describe('CardViewTextItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`)); + const 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('Lorem ipsum'); }); @@ -217,7 +217,7 @@ describe('CardViewTextItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); + const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); expect(editIcon).not.toBeNull('Edit icon should be shown'); }); @@ -225,7 +225,7 @@ describe('CardViewTextItemComponent', () => { component.editable = false; fixture.detectChanges(); - let editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); + const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); expect(editIcon).toBeNull('Edit icon should NOT be shown'); }); @@ -234,7 +234,7 @@ describe('CardViewTextItemComponent', () => { component.property.editable = true; fixture.detectChanges(); - let editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); + const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.key}"]`)); expect(editIcon).toBeNull('Edit icon should NOT be shown'); }); }); @@ -314,7 +314,7 @@ describe('CardViewTextItemComponent', () => { const expectedText = 'changed text'; fixture.detectChanges(); - let disposableUpdate = cardViewUpdateService.itemUpdated$.subscribe( + const disposableUpdate = cardViewUpdateService.itemUpdated$.subscribe( (updateNotification) => { expect(updateNotification.target).toBe(component.property); expect(updateNotification.changed).toEqual({ textkey: expectedText }); @@ -323,16 +323,16 @@ describe('CardViewTextItemComponent', () => { } ); - let editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-toggle-${component.property.key}"]`)); + const editIcon = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-toggle-${component.property.key}"]`)); editIcon.triggerEventHandler('click', null); fixture.detectChanges(); - let editInput = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-editinput-${component.property.key}"]`)); + const editInput = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-editinput-${component.property.key}"]`)); editInput.nativeElement.value = expectedText; editInput.nativeElement.dispatchEvent(new Event('input')); fixture.detectChanges(); - let updateInput = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-update-${component.property.key}"]`)); + const updateInput = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-update-${component.property.key}"]`)); updateInput.triggerEventHandler('click', null); }); }); diff --git a/lib/core/card-view/components/card-view/card-view.component.spec.ts b/lib/core/card-view/components/card-view/card-view.component.spec.ts index 8c8760b2d7..dd7517b0cb 100644 --- a/lib/core/card-view/components/card-view/card-view.component.spec.ts +++ b/lib/core/card-view/components/card-view/card-view.component.spec.ts @@ -47,11 +47,11 @@ describe('CardViewComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('My label'); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText).toBe('My value'); }); @@ -68,7 +68,7 @@ describe('CardViewComponent', () => { fixture.detectChanges(); - let datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-some-key"]`)); + const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-some-key"]`)); expect(datePicker).not.toBeNull('Datepicker should be in DOM'); }); @@ -81,11 +81,11 @@ describe('CardViewComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('My date label'); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText).toBe('Jun 14 2017'); }); @@ -106,10 +106,10 @@ describe('CardViewComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).toBeNull(); - let value = fixture.debugElement.query(By.css('.adf-property-value')); + const value = fixture.debugElement.query(By.css('.adf-property-value')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe(''); }); @@ -130,11 +130,11 @@ describe('CardViewComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('My default label'); - let value = fixture.debugElement.query(By.css('.adf-property-value [data-automation-id="card-textitem-value-some-key"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value [data-automation-id="card-textitem-value-some-key"]')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('default value'); }); @@ -155,11 +155,11 @@ describe('CardViewComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let labelValue = fixture.debugElement.query(By.css('.adf-property-label')); + const labelValue = fixture.debugElement.query(By.css('.adf-property-label')); expect(labelValue).not.toBeNull(); expect(labelValue.nativeElement.innerText).toBe('My default label'); - let value = fixture.debugElement.query(By.css('.adf-property-value [data-automation-id="card-textitem-value-some-key"]')); + const value = fixture.debugElement.query(By.css('.adf-property-value [data-automation-id="card-textitem-value-some-key"]')); expect(value).not.toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('default value'); }); diff --git a/lib/core/comments/comment-list.component.spec.ts b/lib/core/comments/comment-list.component.spec.ts index ba300ec949..fd23166c78 100644 --- a/lib/core/comments/comment-list.component.spec.ts +++ b/lib/core/comments/comment-list.component.spec.ts @@ -144,28 +144,28 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let comment = fixture.debugElement.query(By.css('#adf-comment-1')); + const comment = fixture.debugElement.query(By.css('#adf-comment-1')); comment.triggerEventHandler('click', null); }); })); it('should deselect the previous selected comment when a new one is clicked', async(() => { processCommentOne.isSelected = true; - let commentOne = Object.assign({}, processCommentOne); - let commentTwo = Object.assign({}, processCommentTwo); + const commentOne = Object.assign({}, processCommentOne); + const commentTwo = Object.assign({}, processCommentTwo); commentList.selectedComment = commentOne; commentList.comments = [commentOne, commentTwo]; commentList.clickRow.subscribe((selectedComment) => { fixture.detectChanges(); - let commentSelectedList = fixture.nativeElement.querySelectorAll('.adf-is-selected'); + const commentSelectedList = fixture.nativeElement.querySelectorAll('.adf-is-selected'); expect(commentSelectedList.length).toBe(1); expect(commentSelectedList[0].textContent).toContain('2nd Test Comment'); }); fixture.detectChanges(); fixture.whenStable().then(() => { - let comment = fixture.debugElement.query(By.css('#adf-comment-2')); + const comment = fixture.debugElement.query(By.css('#adf-comment-2')); comment.triggerEventHandler('click', null); }); })); @@ -183,7 +183,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('#comment-message'); + const elements = fixture.nativeElement.querySelectorAll('#comment-message'); expect(elements.length).toBe(1); expect(elements[0].innerText).toBe(processCommentOne.message); expect(fixture.nativeElement.querySelector('#comment-message:empty')).toBeNull(); @@ -195,7 +195,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('#comment-user'); + const elements = fixture.nativeElement.querySelectorAll('#comment-user'); expect(elements.length).toBe(1); expect(elements[0].innerText).toBe(processCommentOne.createdBy.firstName + ' ' + processCommentOne.createdBy.lastName); expect(fixture.nativeElement.querySelector('#comment-user:empty')).toBeNull(); @@ -203,7 +203,7 @@ describe('CommentListComponent', () => { })); it('comment date time should start with few seconds ago when comment date is few seconds ago', async(() => { - let commentFewSecond = Object.assign({}, processCommentOne); + const commentFewSecond = Object.assign({}, processCommentOne); commentFewSecond.created = new Date(); commentList.comments = [commentFewSecond]; @@ -216,7 +216,7 @@ describe('CommentListComponent', () => { })); it('comment date time should start with Yesterday when comment date is yesterday', async(() => { - let commentOld = Object.assign({}, processCommentOne); + const commentOld = Object.assign({}, processCommentOne); commentOld.created = new Date((Date.now() - 24 * 3600 * 1000)); commentList.comments = [commentOld]; fixture.detectChanges(); @@ -228,7 +228,7 @@ describe('CommentListComponent', () => { })); it('comment date time should not start with Today/Yesterday when comment date is before yesterday', async(() => { - let commentOld = Object.assign({}, processCommentOne); + const commentOld = Object.assign({}, processCommentOne); commentOld.created = new Date((Date.now() - 24 * 3600 * 1000 * 2)); commentList.comments = [commentOld]; fixture.detectChanges(); @@ -245,7 +245,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('#comment-user-icon'); + const elements = fixture.nativeElement.querySelectorAll('#comment-user-icon'); expect(elements.length).toBe(1); expect(elements[0].innerText).toContain(commentList.getUserShortName(processCommentOne.createdBy)); expect(fixture.nativeElement.querySelector('#comment-user-icon:empty')).toBeNull(); @@ -257,7 +257,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('.adf-people-img'); + const elements = fixture.nativeElement.querySelectorAll('.adf-people-img'); expect(elements.length).toBe(1); expect(fixture.nativeElement.getElementsByClassName('adf-people-img')[0].src).toContain('content-user-image'); }); @@ -268,7 +268,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('.adf-people-img'); + const elements = fixture.nativeElement.querySelectorAll('.adf-people-img'); expect(elements.length).toBe(1); expect(fixture.nativeElement.getElementsByClassName('adf-people-img')[0].src).toContain('process-user-image'); }); @@ -279,7 +279,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-icon'); + const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-icon'); expect(elements.length).toBe(1); }); })); @@ -289,7 +289,7 @@ describe('CommentListComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-icon'); + const elements = fixture.nativeElement.querySelectorAll('.adf-comment-user-icon'); expect(elements.length).toBe(1); }); })); diff --git a/lib/core/comments/comments.component.spec.ts b/lib/core/comments/comments.component.spec.ts index 3bbd9baa8c..0267d63dac 100644 --- a/lib/core/comments/comments.component.spec.ts +++ b/lib/core/comments/comments.component.spec.ts @@ -77,24 +77,24 @@ describe('CommentsComponent', () => { }); it('should load comments when taskId specified', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); expect(getProcessCommentsSpy).toHaveBeenCalled(); }); it('should load comments when nodeId specified', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'nodeId': change}); expect(getContentCommentsSpy).toHaveBeenCalled(); }); it('should emit an error when an error occurs loading comments', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); getProcessCommentsSpy.and.returnValue(throwError({})); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); expect(emitSpy).toHaveBeenCalled(); @@ -106,7 +106,7 @@ describe('CommentsComponent', () => { }); it('should display comments when the task has comments', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); fixture.whenStable().then(() => { @@ -117,11 +117,11 @@ describe('CommentsComponent', () => { })); it('should display comments count when the task has comments', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); fixture.whenStable().then(() => { fixture.detectChanges(); - let element = fixture.nativeElement.querySelector('#comment-header'); + const element = fixture.nativeElement.querySelector('#comment-header'); expect(element.innerText).toBe('COMMENTS.HEADER'); }); })); @@ -136,7 +136,7 @@ describe('CommentsComponent', () => { })); it('should display comments input by default', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -155,8 +155,8 @@ describe('CommentsComponent', () => { describe('change detection taskId', () => { - let change = new SimpleChange('123', '456', true); - let nullChange = new SimpleChange('123', null, true); + const change = new SimpleChange('123', '456', true); + const nullChange = new SimpleChange('123', null, true); beforeEach(async(() => { component.taskId = '123'; @@ -184,8 +184,8 @@ describe('CommentsComponent', () => { describe('change detection node', () => { - let change = new SimpleChange('123', '456', true); - let nullChange = new SimpleChange('123', null, true); + const change = new SimpleChange('123', '456', true); + const nullChange = new SimpleChange('123', null, true); beforeEach(async(() => { component.nodeId = '123'; @@ -220,7 +220,7 @@ describe('CommentsComponent', () => { })); it('should sanitize comment when user input contains html elements', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = '<div class="text-class"><button onclick=""><h1>action</h1></button></div>'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -231,7 +231,7 @@ describe('CommentsComponent', () => { })); it('should normalize comment when user input contains spaces sequence', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'test comment'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -242,7 +242,7 @@ describe('CommentsComponent', () => { })); it('should add break lines to comment when user input contains new line characters', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'these\nare\nparagraphs\n'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -253,21 +253,21 @@ describe('CommentsComponent', () => { })); it('should call service to add a comment when add button is pressed', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'Test Comment'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); expect(addProcessCommentSpy).toHaveBeenCalled(); - let elements = fixture.nativeElement.querySelectorAll('#comment-message'); + const elements = fixture.nativeElement.querySelectorAll('#comment-message'); expect(elements.length).toBe(1); expect(elements[0].innerText).toBe('Test Comment'); }); })); it('should not call service to add a comment when comment is empty', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = ''; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -278,7 +278,7 @@ describe('CommentsComponent', () => { })); it('should clear comment when escape key is pressed', async(() => { - let event = new KeyboardEvent('keyup', {'key': 'Escape'}); + const event = new KeyboardEvent('keyup', {'key': 'Escape'}); let element = fixture.nativeElement.querySelector('#comment-input'); element.dispatchEvent(event); fixture.detectChanges(); @@ -290,7 +290,7 @@ describe('CommentsComponent', () => { })); it('should emit an error when an error occurs adding the comment', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); addProcessCommentSpy.and.returnValue(throwError({})); component.message = 'Test comment'; component.add(); @@ -308,21 +308,21 @@ describe('CommentsComponent', () => { })); it('should call service to add a comment when add button is pressed', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'Test Comment'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); expect(addContentCommentSpy).toHaveBeenCalled(); - let elements = fixture.nativeElement.querySelectorAll('#comment-message'); + const elements = fixture.nativeElement.querySelectorAll('#comment-message'); expect(elements.length).toBe(1); expect(elements[0].innerText).toBe('Test Comment'); }); })); it('should sanitize comment when user input contains html elements', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = '<div class="text-class"><button onclick=""><h1>action</h1></button></div>'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -333,7 +333,7 @@ describe('CommentsComponent', () => { })); it('should normalize comment when user input contains spaces sequence', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'test comment'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -344,7 +344,7 @@ describe('CommentsComponent', () => { })); it('should add break lines to comment when user input contains new line characters', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = 'these\nare\nparagraphs\n'; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -355,7 +355,7 @@ describe('CommentsComponent', () => { })); it('should not call service to add a comment when comment is empty', async(() => { - let element = fixture.nativeElement.querySelector('.adf-comments-input-add'); + const element = fixture.nativeElement.querySelector('.adf-comments-input-add'); component.message = ''; element.dispatchEvent(new Event('click')); fixture.detectChanges(); @@ -366,7 +366,7 @@ describe('CommentsComponent', () => { })); it('should clear comment when escape key is pressed', async(() => { - let event = new KeyboardEvent('keyup', {'key': 'Escape'}); + const event = new KeyboardEvent('keyup', {'key': 'Escape'}); let element = fixture.nativeElement.querySelector('#comment-input'); element.dispatchEvent(event); fixture.detectChanges(); @@ -378,7 +378,7 @@ describe('CommentsComponent', () => { })); it('should emit an error when an error occurs adding the comment', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); addContentCommentSpy.and.returnValue(throwError({})); component.message = 'Test comment'; component.add(); diff --git a/lib/core/comments/comments.component.ts b/lib/core/comments/comments.component.ts index dbe6da3492..9f1082a3ee 100644 --- a/lib/core/comments/comments.component.ts +++ b/lib/core/comments/comments.component.ts @@ -83,8 +83,8 @@ export class CommentsComponent implements OnChanges { (comments: CommentModel[]) => { if (comments && comments instanceof Array) { comments = comments.sort((comment1: CommentModel, comment2: CommentModel) => { - let date1 = new Date(comment1.created); - let date2 = new Date(comment2.created); + const date1 = new Date(comment1.created); + const date2 = new Date(comment2.created); return date1 > date2 ? -1 : date1 < date2 ? 1 : 0; }); comments.forEach((currentComment) => { diff --git a/lib/core/context-menu/context-menu-holder.component.spec.ts b/lib/core/context-menu/context-menu-holder.component.spec.ts index 4fec934ba6..e64cef1407 100644 --- a/lib/core/context-menu/context-menu-holder.component.spec.ts +++ b/lib/core/context-menu/context-menu-holder.component.spec.ts @@ -28,7 +28,7 @@ describe('ContextMenuHolderComponent', () => { let fixture: ComponentFixture<ContextMenuHolderComponent>; let component: ContextMenuHolderComponent; let contextMenuService: ContextMenuService; - let overlayContainer = { + const overlayContainer = { getContainerElement: () => ({ addEventListener: () => {}, querySelector: (val) => ({ @@ -46,7 +46,7 @@ describe('ContextMenuHolderComponent', () => { }) }; - let getViewportRect = { + const getViewportRect = { getViewportRect: () => ({ left: 0, top: 0, width: 1014, height: 686, bottom: 0, right: 0 }) diff --git a/lib/core/datatable/components/datatable/datatable.component.spec.ts b/lib/core/datatable/components/datatable/datatable.component.spec.ts index a9fc3ea7af..07ee637dc6 100644 --- a/lib/core/datatable/components/datatable/datatable.component.spec.ts +++ b/lib/core/datatable/components/datatable/datatable.component.spec.ts @@ -105,7 +105,7 @@ describe('DataTable', () => { })); it('should use the cardview style if cardview is true', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( [ { name: '1' }, { name: '2' } @@ -125,7 +125,7 @@ describe('DataTable', () => { }); it('should use the cardview style if cardview is false', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( [ { name: '1' }, { name: '2' } @@ -144,7 +144,7 @@ describe('DataTable', () => { }); it('should hide the header if showHeader is false', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( [ { name: '1' }, { name: '2' } @@ -164,7 +164,7 @@ describe('DataTable', () => { }); it('should hide the header if there are no elements inside', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( ); dataTable.ngOnChanges({ @@ -177,7 +177,7 @@ describe('DataTable', () => { }); it('should hide the header if noPermission is true', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( ); dataTable.noPermission = true; @@ -193,7 +193,7 @@ describe('DataTable', () => { }); it('should show the header if showHeader is true', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( [ { name: '1' }, { name: '2' } @@ -234,7 +234,7 @@ describe('DataTable', () => { }); it('should change the rows on changing of the data', () => { - let newData = new ObjectDataTableAdapter( + const newData = new ObjectDataTableAdapter( [ { name: 'TEST' }, { name: 'FAKE' } @@ -531,7 +531,7 @@ describe('DataTable', () => { dataTable.actions = true; fixture.detectChanges(); - let actions = element.querySelectorAll('[id^=action_menu_right]'); + const actions = element.querySelectorAll('[id^=action_menu_right]'); expect(actions.length).toBe(4); }); @@ -550,26 +550,26 @@ describe('DataTable', () => { dataTable.actionsPosition = 'left'; fixture.detectChanges(); - let actions = element.querySelectorAll('[id^=action_menu_left]'); + const actions = element.querySelectorAll('[id^=action_menu_left]'); expect(actions.length).toBe(4); }); it('should initialize default adapter', () => { - let table = new DataTableComponent(null, null); + const table = new DataTableComponent(null, null); expect(table.data).toBeUndefined(); table.ngOnChanges({ 'data': new SimpleChange('123', {}, true) }); expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter)); }); it('should initialize with custom data', () => { - let data = new ObjectDataTableAdapter([], []); + const data = new ObjectDataTableAdapter([], []); dataTable.data = data; dataTable.ngAfterContentInit(); expect(dataTable.data).toBe(data); }); it('should emit row click event', (done) => { - let row = <DataRow> {}; + const row = <DataRow> {}; dataTable.rowClick.subscribe((e) => { expect(e.value).toBe(row); @@ -582,7 +582,7 @@ describe('DataTable', () => { it('should emit double click if there are two single click in 250ms', (done) => { - let row = <DataRow> {}; + const row = <DataRow> {}; dataTable.ngOnChanges({}); dataTable.rowDblClick.subscribe(() => { @@ -599,7 +599,7 @@ describe('DataTable', () => { it('should emit double click if there are more than two single click in 250ms', (done) => { - let row = <DataRow> {}; + const row = <DataRow> {}; dataTable.ngOnChanges({}); dataTable.rowDblClick.subscribe(() => { @@ -618,7 +618,7 @@ describe('DataTable', () => { it('should emit single click if there are two single click in more than 250ms', (done) => { - let row = <DataRow> {}; + const row = <DataRow> {}; let clickCount = 0; dataTable.ngOnChanges({}); @@ -638,7 +638,7 @@ describe('DataTable', () => { }); it('should emit row-click dom event', (done) => { - let row = <DataRow> {}; + const row = <DataRow> {}; fixture.nativeElement.addEventListener('row-click', (e) => { expect(e.detail.value).toBe(row); @@ -650,7 +650,7 @@ describe('DataTable', () => { }); it('should emit row-dblclick dom event', (done) => { - let row = <DataRow> {}; + const row = <DataRow> {}; fixture.nativeElement.addEventListener('row-dblclick', (e) => { expect(e.detail.value).toBe(row); @@ -662,14 +662,14 @@ describe('DataTable', () => { }); it('should prevent default behaviour on row click event', () => { - let e = jasmine.createSpyObj('event', ['preventDefault']); + const e = jasmine.createSpyObj('event', ['preventDefault']); dataTable.ngAfterContentInit(); dataTable.onRowClick(null, e); expect(e.preventDefault).toHaveBeenCalled(); }); it('should prevent default behaviour on row double-click event', () => { - let e = jasmine.createSpyObj('event', ['preventDefault']); + const e = jasmine.createSpyObj('event', ['preventDefault']); dataTable.ngOnChanges({}); dataTable.ngAfterContentInit(); dataTable.onRowDblClick(null, e); @@ -678,7 +678,7 @@ describe('DataTable', () => { it('should not sort if column is missing', () => { dataTable.ngOnChanges({ 'data': new SimpleChange('123', {}, true) }); - let adapter = dataTable.data; + const adapter = dataTable.data; spyOn(adapter, 'setSorting').and.callThrough(); dataTable.onColumnHeaderClick(null); expect(adapter.setSorting).not.toHaveBeenCalled(); @@ -686,10 +686,10 @@ describe('DataTable', () => { it('should not sort upon clicking non-sortable column header', () => { dataTable.ngOnChanges({ 'data': new SimpleChange('123', {}, true) }); - let adapter = dataTable.data; + const adapter = dataTable.data; spyOn(adapter, 'setSorting').and.callThrough(); - let column = new ObjectDataColumn({ + const column = new ObjectDataColumn({ key: 'column_1' }); @@ -699,10 +699,10 @@ describe('DataTable', () => { it('should set sorting upon column header clicked', () => { dataTable.ngOnChanges({ 'data': new SimpleChange('123', {}, true) }); - let adapter = dataTable.data; + const adapter = dataTable.data; spyOn(adapter, 'setSorting').and.callThrough(); - let column = new ObjectDataColumn({ + const column = new ObjectDataColumn({ key: 'column_1', sortable: true }); @@ -719,12 +719,12 @@ describe('DataTable', () => { it('should invert sorting upon column header clicked', () => { dataTable.ngOnChanges({ 'data': new SimpleChange('123', {}, true) }); - let adapter = dataTable.data; - let sorting = new DataSorting('column_1', 'asc'); + const adapter = dataTable.data; + const sorting = new DataSorting('column_1', 'asc'); spyOn(adapter, 'setSorting').and.callThrough(); spyOn(adapter, 'getSorting').and.returnValue(sorting); - let column = new ObjectDataColumn({ + const column = new ObjectDataColumn({ key: 'column_1', sortable: true }); @@ -759,7 +759,7 @@ describe('DataTable', () => { }); it('should reset selection upon data rows change', () => { - let data = new ObjectDataTableAdapter([{}, {}, {}], []); + const data = new ObjectDataTableAdapter([{}, {}, {}], []); dataTable.data = data; dataTable.multiselect = true; @@ -775,8 +775,8 @@ describe('DataTable', () => { }); it('should update rows on "select all" click', () => { - let data = new ObjectDataTableAdapter([{}, {}, {}], []); - let rows = data.getRows(); + const data = new ObjectDataTableAdapter([{}, {}, {}], []); + const rows = data.getRows(); dataTable.data = data; dataTable.multiselect = true; @@ -804,8 +804,8 @@ describe('DataTable', () => { }); it('should require multiselect option to toggle row state', () => { - let data = new ObjectDataTableAdapter([{}, {}, {}], []); - let rows = data.getRows(); + const data = new ObjectDataTableAdapter([{}, {}, {}], []); + const rows = data.getRows(); dataTable.data = data; dataTable.multiselect = false; @@ -825,9 +825,9 @@ describe('DataTable', () => { }); it('should use special material url scheme', () => { - let column = <DataColumn> {}; + const column = <DataColumn> {}; - let row = { + const row = { getValue: function (key: string) { return 'material-icons://android'; } @@ -837,9 +837,9 @@ describe('DataTable', () => { }); it('should not use special material url scheme', () => { - let column = <DataColumn> {}; + const column = <DataColumn> {}; - let row = { + const row = { getValue: function (key: string) { return 'http://www.google.com'; } @@ -849,9 +849,9 @@ describe('DataTable', () => { }); it('should parse icon value', () => { - let column = <DataColumn> {}; + const column = <DataColumn> {}; - let row = { + const row = { getValue: function (key: string) { return 'material-icons://android'; } @@ -861,9 +861,9 @@ describe('DataTable', () => { }); it('should not parse icon value', () => { - let column = <DataColumn> {}; + const column = <DataColumn> {}; - let row = { + const row = { getValue: function (key: string) { return 'http://www.google.com'; } @@ -898,7 +898,7 @@ describe('DataTable', () => { }); it('should replace image source with fallback thumbnail on error', () => { - let event = <any> { + const event = <any> { target: { src: 'missing-image' } @@ -911,7 +911,7 @@ describe('DataTable', () => { it('should replace image source with miscellaneous icon when fallback is not available', () => { const originalSrc = 'missing-image'; - let event = <any> { + const event = <any> { target: { src: originalSrc } diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 123360db92..5f4568eea6 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -239,7 +239,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, } ngDoCheck() { - let changes = this.differ.diff(this.rows); + const changes = this.differ.diff(this.rows); if (changes) { this.setTableRows(this.rows); } @@ -261,7 +261,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, private initAndSubscribeClickStream() { this.unsubscribeClickStream(); - let singleClickStream = this.click$ + const singleClickStream = this.click$ .pipe( buffer( this.click$.pipe( @@ -273,7 +273,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, ); this.singleClickStreamSub = singleClickStream.subscribe((dataRowEvents: DataRowEvent[]) => { - let event: DataRowEvent = dataRowEvents[0]; + const event: DataRowEvent = dataRowEvents[0]; this.handleRowSelection(event.value, <MouseEvent | KeyboardEvent> event.event); this.rowClick.emit(event); if (!event.defaultPrevented) { @@ -286,7 +286,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, } }); - let multiClickStream = this.click$ + const multiClickStream = this.click$ .pipe( buffer( this.click$.pipe( @@ -298,7 +298,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, ); this.multiClickStreamSub = multiClickStream.subscribe((dataRowEvents: DataRowEvent[]) => { - let event: DataRowEvent = dataRowEvents[0]; + const event: DataRowEvent = dataRowEvents[0]; this.rowDblClick.emit(event); if (!event.defaultPrevented) { this.elementRef.nativeElement.dispatchEvent( @@ -428,7 +428,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, if (event) { event.preventDefault(); } - let dataRowEvent = new DataRowEvent(row, event, this); + const dataRowEvent = new DataRowEvent(row, event, this); this.clickObserver.next(dataRowEvent); } @@ -471,7 +471,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, onColumnHeaderClick(column: DataColumn) { if (column && column.sortable) { - let current = this.data.getSorting(); + const current = this.data.getSorting(); let newDirection = 'asc'; if (current && column.key === current.key) { newDirection = current.direction === 'asc' ? 'desc' : 'asc'; @@ -485,7 +485,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, this.isSelectAllChecked = matCheckboxChange.checked; if (this.multiselect) { - let rows = this.data.getRows(); + const rows = this.data.getRows(); if (rows && rows.length > 0) { for (let i = 0; i < rows.length; i++) { this.selectRow(rows[i], matCheckboxChange.checked); @@ -510,7 +510,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, onImageLoadingError(event: Event, row: DataRow) { if (event) { - let element = <any> event.target; + const element = <any> event.target; if (this.fallbackThumbnail) { element.src = this.fallbackThumbnail; @@ -522,7 +522,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, isIconValue(row: DataRow, col: DataColumn): boolean { if (row && col) { - let value = row.getValue(col.key); + const value = row.getValue(col.key); return value && value.startsWith('material-icons://'); } return false; @@ -530,7 +530,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, asIconValue(row: DataRow, col: DataColumn): string { if (this.isIconValue(row, col)) { - let value = row.getValue(col.key) || ''; + const value = row.getValue(col.key) || ''; return value.replace('material-icons://', ''); } return null; @@ -542,14 +542,14 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, isColumnSorted(col: DataColumn, direction: string): boolean { if (col && direction) { - let sorting = this.data.getSorting(); + const sorting = this.data.getSorting(); return sorting && sorting.key === col.key && sorting.direction === direction; } return false; } getContextMenuActions(row: DataRow, col: DataColumn): any[] { - let event = new DataCellEvent(row, col, []); + const event = new DataCellEvent(row, col, []); this.showRowContextMenu.emit(event); return event.value.actions; } @@ -558,7 +558,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, const id = row.getValue('id'); if (!this.rowMenuCache[id]) { - let event = new DataCellEvent(row, col, []); + const event = new DataCellEvent(row, col, []); this.showRowActionsMenu.emit(event); if (!this.rowMenuCacheEnabled) { return event.value.actions; diff --git a/lib/core/datatable/data/object-datatable-adapter.spec.ts b/lib/core/datatable/data/object-datatable-adapter.spec.ts index 0055e2112f..b9c9784a67 100644 --- a/lib/core/datatable/data/object-datatable-adapter.spec.ts +++ b/lib/core/datatable/data/object-datatable-adapter.spec.ts @@ -25,20 +25,20 @@ import { ObjectDataColumn } from './object-datacolumn.model'; describe('ObjectDataTableAdapter', () => { it('should init with empty row collection', () => { - let adapter = new ObjectDataTableAdapter(null, []); + const adapter = new ObjectDataTableAdapter(null, []); expect(adapter.getRows()).toBeDefined(); expect(adapter.getRows().length).toBe(0); }); it('should init with empty column collection', () => { - let adapter = new ObjectDataTableAdapter([], null); + const adapter = new ObjectDataTableAdapter([], null); expect(adapter.getColumns()).toBeDefined(); expect(adapter.getColumns().length).toBeDefined(); }); it('should map rows', () => { - let adapter = new ObjectDataTableAdapter([{}, {}], null); - let rows = adapter.getRows(); + const adapter = new ObjectDataTableAdapter([{}, {}], null); + const rows = adapter.getRows(); expect(rows.length).toBe(2); expect(rows[0] instanceof ObjectDataRow).toBe(true); @@ -46,11 +46,11 @@ describe('ObjectDataTableAdapter', () => { }); it('should map columns without rows', () => { - let adapter = new ObjectDataTableAdapter(null, [ + const adapter = new ObjectDataTableAdapter(null, [ <DataColumn> {}, <DataColumn> {} ]); - let columns = adapter.getColumns(); + const columns = adapter.getColumns(); expect(columns.length).toBe(2); expect(columns[0] instanceof ObjectDataColumn).toBe(true); @@ -58,13 +58,13 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort by first column if column is available', () => { - let adapter = new ObjectDataTableAdapter(null, null); + const adapter = new ObjectDataTableAdapter(null, null); expect(adapter.getSorting()).toBeUndefined(); }); it('should apply new rows array', () => { - let adapter = new ObjectDataTableAdapter([], []); - let newRows = [ + const adapter = new ObjectDataTableAdapter([], []); + const newRows = [ <DataRow> {}, <DataRow> {} ]; @@ -74,7 +74,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should accept null for new rows array', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); expect(adapter.getRows()).toBeDefined(); expect(adapter.getRows().length).toBe(0); @@ -84,7 +84,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should reset rows by null value', () => { - let adapter = new ObjectDataTableAdapter([{}, {}], []); + const adapter = new ObjectDataTableAdapter([{}, {}], []); expect(adapter.getRows()).toBeDefined(); expect(adapter.getRows().length).toBe(2); @@ -94,15 +94,15 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort new row collection', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); spyOn(adapter, 'sort').and.callThrough(); adapter.setRows([]); expect(adapter.sort).toHaveBeenCalled(); }); it('should apply new columns array', () => { - let adapter = new ObjectDataTableAdapter([], []); - let columns = [ + const adapter = new ObjectDataTableAdapter([], []); + const columns = [ <DataColumn> {}, <DataColumn> {} ]; @@ -112,7 +112,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should accept null for new columns array', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); expect(adapter.getColumns()).toBeDefined(); expect(adapter.getColumns().length).toBe(0); @@ -122,7 +122,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should reset columns by null value', () => { - let adapter = new ObjectDataTableAdapter([], [ + const adapter = new ObjectDataTableAdapter([], [ <DataColumn> {}, <DataColumn> {} ]); @@ -135,31 +135,31 @@ describe('ObjectDataTableAdapter', () => { }); it('should fail getting value with row not defined', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); expect(() => { adapter.getValue(null, null); }).toThrowError('Row not found'); }); it('should fail getting value with column not defined', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); expect(() => { adapter.getValue(<DataRow> {}, null); }).toThrowError('Column not found'); }); it('should get value from row with column key', () => { - let value = 'hello world'; + const value = 'hello world'; - let row = jasmine.createSpyObj('row', ['getValue']); + const row = jasmine.createSpyObj('row', ['getValue']); row.getValue.and.returnValue(value); - let adapter = new ObjectDataTableAdapter([], []); - let result = adapter.getValue(row, <DataColumn> { key: 'col1' }); + const adapter = new ObjectDataTableAdapter([], []); + const result = adapter.getValue(row, <DataColumn> { key: 'col1' }); expect(row.getValue).toHaveBeenCalledWith('col1'); expect(result).toBe(value); }); it('should set new sorting', () => { - let sorting = new DataSorting('key', 'direction'); - let adapter = new ObjectDataTableAdapter([], []); + const sorting = new DataSorting('key', 'direction'); + const adapter = new ObjectDataTableAdapter([], []); adapter.setSorting(sorting); expect(adapter.getSorting()).toBe(sorting); @@ -169,7 +169,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort rows with new sorting value', () => { - let adapter = new ObjectDataTableAdapter([{}, {}], []); + const adapter = new ObjectDataTableAdapter([{}, {}], []); spyOn(adapter.getRows(), 'sort').and.stub(); adapter.setSorting(new DataSorting('key', 'direction')); @@ -177,7 +177,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort rows only when sorting key provided', () => { - let adapter = new ObjectDataTableAdapter([{}, {}], []); + const adapter = new ObjectDataTableAdapter([{}, {}], []); spyOn(adapter.getRows(), 'sort').and.stub(); adapter.setSorting(new DataSorting()); @@ -185,7 +185,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort by first column by default', () => { - let adapter = new ObjectDataTableAdapter( + const adapter = new ObjectDataTableAdapter( [ { id: 2, name: 'abs' }, { id: 1, name: 'xyz' } @@ -195,13 +195,13 @@ describe('ObjectDataTableAdapter', () => { ] ); - let rows = adapter.getRows(); + const rows = adapter.getRows(); expect(rows[0].getValue('id')).toBe(1); expect(rows[1].getValue('id')).toBe(2); }); it('should take first sortable column by default', () => { - let adapter = new ObjectDataTableAdapter([], [ + const adapter = new ObjectDataTableAdapter([], [ <DataColumn> { key: 'icon' }, new ObjectDataColumn({ key: 'id', sortable: true }) ]); @@ -215,7 +215,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort by dates', () => { - let adapter = new ObjectDataTableAdapter( + const adapter = new ObjectDataTableAdapter( [ { id: 1, created: new Date(2016, 7, 6, 15, 7, 2) }, { id: 2, created: new Date(2016, 7, 6, 15, 7, 1) } @@ -228,13 +228,13 @@ describe('ObjectDataTableAdapter', () => { adapter.setSorting(new DataSorting('created', 'asc')); - let rows = adapter.getRows(); + const rows = adapter.getRows(); expect(rows[0].getValue('id')).toBe(2); expect(rows[1].getValue('id')).toBe(1); }); it('should be sorting undefined if no sortable found', () => { - let adapter = new ObjectDataTableAdapter( + const adapter = new ObjectDataTableAdapter( [ { id: 2, name: 'abs' }, { id: 1, name: 'xyz' } @@ -249,7 +249,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should sort asc and desc', () => { - let adapter = new ObjectDataTableAdapter( + const adapter = new ObjectDataTableAdapter( [ { id: 2, name: 'abs' }, { id: 1, name: 'xyz' } @@ -269,7 +269,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should use asc for sort command by default', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); adapter.setSorting(null); expect(adapter.getSorting()).toBe(null); @@ -283,7 +283,7 @@ describe('ObjectDataTableAdapter', () => { }); it('should use direction for sort command', () => { - let adapter = new ObjectDataTableAdapter([], []); + const adapter = new ObjectDataTableAdapter([], []); adapter.setSorting(null); expect(adapter.getSorting()).toBe(null); @@ -305,19 +305,19 @@ describe('ObjectDataRow', () => { }); it('should get top level property value', () => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ id: 1 }); expect(row.getValue('id')).toBe(1); }); it('should not get top level property value', () => { - let row = new ObjectDataRow({}); + const row = new ObjectDataRow({}); expect(row.getValue('missing')).toBeUndefined(); }); it('should get nested property value', () => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ name: { firstName: 'John', lastName: 'Doe' @@ -328,19 +328,19 @@ describe('ObjectDataRow', () => { }); it('should not get nested property value', () => { - let row = new ObjectDataRow({}); + const row = new ObjectDataRow({}); expect(row.getValue('some.missing.property')).toBeUndefined(); }); it('should check top level value exists', () => { - let row = new ObjectDataRow({ id: 1 }); + const row = new ObjectDataRow({ id: 1 }); expect(row.hasValue('id')).toBeTruthy(); expect(row.hasValue('other')).toBeFalsy(); }); it('should check nested value exists', () => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ name: { firstName: 'John', lastName: 'Doe' @@ -353,12 +353,12 @@ describe('ObjectDataRow', () => { }); it('should generateSchema generate a schema from data', () => { - let data = [ + const data = [ { id: 2, name: 'abs' }, { id: 1, name: 'xyz' } ]; - let schema = ObjectDataTableAdapter.generateSchema(data); + const schema = ObjectDataTableAdapter.generateSchema(data); expect(schema.length).toBe(2); expect(schema[0].title).toBe('id'); diff --git a/lib/core/datatable/data/object-datatable-adapter.ts b/lib/core/datatable/data/object-datatable-adapter.ts index 3578cc3396..a34042a045 100644 --- a/lib/core/datatable/data/object-datatable-adapter.ts +++ b/lib/core/datatable/data/object-datatable-adapter.ts @@ -34,13 +34,13 @@ export class ObjectDataTableAdapter implements DataTableAdapter { rowsChanged: Subject<Array<DataRow>>; static generateSchema(data: any[]) { - let schema = []; + const schema = []; if (data && data.length) { - let rowToExaminate = data[0]; + const rowToExaminate = data[0]; if (typeof rowToExaminate === 'object') { - for (let key in rowToExaminate) { + for (const key in rowToExaminate) { if (rowToExaminate.hasOwnProperty(key)) { schema.push({ type: 'text', @@ -72,7 +72,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter { }); // Sort by first sortable or just first column - let sortable = this._columns.filter((column) => column.sortable); + const sortable = this._columns.filter((column) => column.sortable); if (sortable.length > 0) { this.sort(sortable[0].key, 'asc'); } @@ -107,7 +107,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter { throw new Error('Column not found'); } - let value = row.getValue(col.key); + const value = row.getValue(col.key); if (col.type === 'icon') { const icon = row.getValue(col.key); @@ -148,7 +148,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter { } sort(key?: string, direction?: string): void { - let sorting = this._sorting || new DataSorting(); + const sorting = this._sorting || new DataSorting(); if (key) { sorting.key = key; sorting.direction = direction || 'asc'; diff --git a/lib/core/dialogs/download-zip.dialog.spec.ts b/lib/core/dialogs/download-zip.dialog.spec.ts index 48504e42ce..4c20f1b956 100755 --- a/lib/core/dialogs/download-zip.dialog.spec.ts +++ b/lib/core/dialogs/download-zip.dialog.spec.ts @@ -30,17 +30,17 @@ describe('DownloadZipDialogComponent', () => { let component: DownloadZipDialogComponent; let element: HTMLElement; let downloadZipService: DownloadZipService; - let dialogRef = { + const dialogRef = { close: jasmine.createSpy('close') }; - let dataMock = { + const dataMock = { nodeIds: [ '123' ] }; - let pendingDownloadEntry = { + const pendingDownloadEntry = { entry: { bytesAdded: 0, filesAdded: 0, diff --git a/lib/core/directives/check-allowable-operation.directive.spec.ts b/lib/core/directives/check-allowable-operation.directive.spec.ts index d65a0fdcf5..31af2a930a 100644 --- a/lib/core/directives/check-allowable-operation.directive.spec.ts +++ b/lib/core/directives/check-allowable-operation.directive.spec.ts @@ -134,7 +134,7 @@ describe('CheckAllowableOperationDirective', () => { spyOn(contentService, 'hasAllowableOperations').and.returnValue(false); spyOn(changeDetectorMock, 'detectChanges'); - let testComponent = new TestComponent(); + const testComponent = new TestComponent(); testComponent.disabled = false; const directive = new CheckAllowableOperationDirective(null, null, contentService, changeDetectorMock, testComponent); directive.nodes = <any> [{}, {}]; @@ -150,7 +150,7 @@ describe('CheckAllowableOperationDirective', () => { spyOn(contentService, 'hasAllowableOperations').and.returnValue(true); spyOn(changeDetectorMock, 'detectChanges'); - let testComponent = new TestComponent(); + const testComponent = new TestComponent(); testComponent.disabled = true; const directive = new CheckAllowableOperationDirective(null, null, contentService, changeDetectorMock, testComponent); directive.nodes = <any> [{}, {}]; diff --git a/lib/core/directives/check-allowable-operation.directive.ts b/lib/core/directives/check-allowable-operation.directive.ts index c2476d65c2..fd400061c5 100644 --- a/lib/core/directives/check-allowable-operation.directive.ts +++ b/lib/core/directives/check-allowable-operation.directive.ts @@ -63,7 +63,7 @@ export class CheckAllowableOperationDirective implements OnChanges { * @memberof CheckAllowableOperationDirective */ updateElement(): boolean { - let enable = this.hasAllowableOperations(this.nodes, this.permission); + const enable = this.hasAllowableOperations(this.nodes, this.permission); if (enable) { this.enable(); diff --git a/lib/core/directives/node-favorite.directive.spec.ts b/lib/core/directives/node-favorite.directive.spec.ts index fb2ebb4725..94c27e9f46 100644 --- a/lib/core/directives/node-favorite.directive.spec.ts +++ b/lib/core/directives/node-favorite.directive.spec.ts @@ -72,7 +72,7 @@ describe('NodeFavoriteDirective', () => { it('should reset favorites if selection is empty', fakeAsync(() => { spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'getFavorite').and.returnValue(Promise.resolve()); - let selection = [ + const selection = [ { entry: { id: '1', name: 'name1' } } ]; @@ -104,7 +104,7 @@ describe('NodeFavoriteDirective', () => { { entry: { id: '2', name: 'name2' } } ]; - let change = new SimpleChange(null, selection, true); + const change = new SimpleChange(null, selection, true); directive.ngOnChanges({'selection': change}); tick(); @@ -185,7 +185,7 @@ describe('NodeFavoriteDirective', () => { }); it('should not perform action if favorites collection is empty', fakeAsync(() => { - let change = new SimpleChange(null, [], true); + const change = new SimpleChange(null, [], true); directive.ngOnChanges({'selection': change}); tick(); @@ -330,7 +330,7 @@ describe('NodeFavoriteDirective', () => { { entry: { id: '1', name: 'name1', isFavorite: true } } ]; - let change = new SimpleChange(null, selection, true); + const change = new SimpleChange(null, selection, true); directive.ngOnChanges({'selection': change}); tick(); @@ -345,7 +345,7 @@ describe('NodeFavoriteDirective', () => { { entry: { id: '1', name: 'name1' } } ]; - let change = new SimpleChange(null, selection, true); + const change = new SimpleChange(null, selection, true); directive.ngOnChanges({'selection': change}); tick(); @@ -359,7 +359,7 @@ describe('NodeFavoriteDirective', () => { { entry: { id: '1', name: 'name1' } } ]; - let change = new SimpleChange(null, selection, true); + const change = new SimpleChange(null, selection, true); directive.ngOnChanges({'selection': change}); tick(); diff --git a/lib/core/directives/node-restore.directive.ts b/lib/core/directives/node-restore.directive.ts index 6e2358034e..55cef30615 100644 --- a/lib/core/directives/node-restore.directive.ts +++ b/lib/core/directives/node-restore.directive.ts @@ -238,7 +238,7 @@ export class NodeRestoreDirective { private notification(): void { const status = Object.assign({}, this.restoreProcessStatus); - let message = this.getRestoreMessage(); + const message = this.getRestoreMessage(); this.reset(); const action = (status.oneSucceeded && !status.someFailed) ? this.translation.instant('CORE.RESTORE_NODE.VIEW') : ''; diff --git a/lib/core/directives/upload.directive.spec.ts b/lib/core/directives/upload.directive.spec.ts index 11f90f3b34..cdeed6fbf8 100644 --- a/lib/core/directives/upload.directive.spec.ts +++ b/lib/core/directives/upload.directive.spec.ts @@ -58,7 +58,7 @@ describe('UploadDirective', () => { }); it('should prevent default event on dragover', () => { - let event = new Event('dom-event'); + const event = new Event('dom-event'); spyOn(event, 'preventDefault').and.stub(); directive.enabled = true; directive.onDragOver(event); @@ -88,28 +88,28 @@ describe('UploadDirective', () => { it('should prevent default event on drop', () => { directive.enabled = true; - let event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); + const event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); directive.onDrop(<DragEvent> event); expect(event.preventDefault).toHaveBeenCalled(); }); it('should stop default event propagation on drop', () => { directive.enabled = true; - let event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); + const event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); directive.onDrop(<DragEvent> event); expect(event.stopPropagation).toHaveBeenCalled(); }); it('should not prevent default event on drop when disabled', () => { directive.enabled = false; - let event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); + const event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); directive.onDrop(<DragEvent> event); expect(event.preventDefault).not.toHaveBeenCalled(); }); it('should raise upload-files event on files drop', (done) => { directive.enabled = true; - let event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); + const event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); spyOn(directive, 'getDataTransfer').and.returnValue({}); spyOn(directive, 'getFilesDropped').and.returnValue(Promise.resolve([ <FileInfo> {}, @@ -123,10 +123,10 @@ describe('UploadDirective', () => { it('should provide dropped files in upload-files event', (done) => { directive.enabled = true; - let files = [ + const files = [ <FileInfo> {} ]; - let event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); + const event = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); spyOn(directive, 'getDataTransfer').and.returnValue({}); spyOn(directive, 'getFilesDropped').and.returnValue(Promise.resolve(files)); diff --git a/lib/core/directives/upload.directive.ts b/lib/core/directives/upload.directive.ts index 33151a2743..5021e7f734 100644 --- a/lib/core/directives/upload.directive.ts +++ b/lib/core/directives/upload.directive.ts @@ -63,7 +63,7 @@ export class UploadDirective implements OnInit, OnDestroy { ngOnInit() { if (this.isClickMode() && this.renderer) { - let inputUpload = this.renderer.createElement('input'); + const inputUpload = this.renderer.createElement('input'); this.upload = this.el.nativeElement.parentElement.appendChild(inputUpload); this.upload.type = 'file'; @@ -153,7 +153,7 @@ export class UploadDirective implements OnInit, OnDestroy { onUploadFiles(files: FileInfo[]) { if (this.enabled && files.length > 0) { - let customEvent = new CustomEvent('upload-files', { + const customEvent = new CustomEvent('upload-files', { detail: { sender: this, data: this.data, @@ -201,7 +201,7 @@ export class UploadDirective implements OnInit, OnDestroy { if (items) { for (let i = 0; i < items.length; i++) { if (typeof items[i].webkitGetAsEntry !== 'undefined') { - let item = items[i].webkitGetAsEntry(); + const item = items[i].webkitGetAsEntry(); if (item) { if (item.isFile) { iterations.push(Promise.resolve(<FileInfo> { @@ -225,7 +225,7 @@ export class UploadDirective implements OnInit, OnDestroy { } } else { // safari or FF - let files = FileUtils + const files = FileUtils .toFileArray(dataTransfer.files) .map((file) => <FileInfo> { entry: null, diff --git a/lib/core/form/components/form-field/form-field.component.spec.ts b/lib/core/form/components/form-field/form-field.component.spec.ts index fee77cac19..6f8b0c76aa 100644 --- a/lib/core/form/components/form-field/form-field.component.spec.ts +++ b/lib/core/form/components/form-field/form-field.component.spec.ts @@ -51,7 +51,7 @@ describe('FormFieldComponent', () => { }); it('should create default component instance', (done) => { - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { type: FormFieldTypes.TEXT, id: 'FAKE-TXT-WIDGET' }); @@ -69,7 +69,7 @@ describe('FormFieldComponent', () => { it('should create custom component instance', (done) => { formRenderingService.setComponentTypeResolver(FormFieldTypes.AMOUNT, () => CheckboxWidgetComponent, true); - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { type: FormFieldTypes.AMOUNT, id: 'FAKE-TXT-WIDGET' }); @@ -85,7 +85,7 @@ describe('FormFieldComponent', () => { }); it('should require component type to be resolved', (done) => { - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { type: FormFieldTypes.TEXT, id: 'FAKE-TXT-WIDGET' }); @@ -102,7 +102,7 @@ describe('FormFieldComponent', () => { }); it('should hide the field when it is not visible', (done) => { - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { type: FormFieldTypes.TEXT, id: 'FAKE-TXT-WIDGET' }); @@ -117,7 +117,7 @@ describe('FormFieldComponent', () => { }); it('should show the field when it is visible', (done) => { - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { type: FormFieldTypes.TEXT, id: 'FAKE-TXT-WIDGET' }); @@ -132,7 +132,7 @@ describe('FormFieldComponent', () => { }); it('should hide a visible element', () => { - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { type: FormFieldTypes.TEXT, id: 'FAKE-TXT-WIDGET' }); diff --git a/lib/core/form/components/form-field/form-field.component.ts b/lib/core/form/components/form-field/form-field.component.ts index 835638f6f6..1488733856 100644 --- a/lib/core/form/components/form-field/form-field.component.ts +++ b/lib/core/form/components/form-field/form-field.component.ts @@ -78,22 +78,22 @@ export class FormFieldComponent implements OnInit, OnDestroy { if (w.adf === undefined) { w.adf = {}; } - let originalField = this.getField(); + const originalField = this.getField(); if (originalField) { - let customTemplate = this.field.form.customFieldTemplates[originalField.type]; + const customTemplate = this.field.form.customFieldTemplates[originalField.type]; if (customTemplate && this.hasController(originalField.type)) { - let factory = this.getComponentFactorySync(originalField.type, customTemplate); + const factory = this.getComponentFactorySync(originalField.type, customTemplate); this.componentRef = this.container.createComponent(factory); - let instance: any = this.componentRef.instance; + const instance: any = this.componentRef.instance; if (instance) { instance.field = originalField; } } else { - let componentType = this.formRenderingService.resolveComponentType(originalField); + const componentType = this.formRenderingService.resolveComponentType(originalField); if (componentType) { - let factory = this.componentFactoryResolver.resolveComponentFactory(componentType); + const factory = this.componentFactoryResolver.resolveComponentFactory(componentType); this.componentRef = this.container.createComponent(factory); - let instance = <WidgetComponent> this.componentRef.instance; + const instance = <WidgetComponent> this.componentRef.instance; instance.field = this.field; instance.fieldChanged.subscribe((field) => { if (field && this.field.form) { @@ -128,18 +128,18 @@ export class FormFieldComponent implements OnInit, OnDestroy { } private getComponentFactorySync(type: string, template: string): ComponentFactory<any> { - let componentInfo = adf.components[type]; + const componentInfo = adf.components[type]; if (componentInfo.factory) { return componentInfo.factory; } - let metadata = { + const metadata = { selector: `runtime-component-${type}`, template: template }; - let factory = this.createComponentFactorySync(this.compiler, metadata, componentInfo.class); + const factory = this.createComponentFactorySync(this.compiler, metadata, componentInfo.class); componentInfo.factory = factory; return factory; } @@ -153,7 +153,7 @@ export class FormFieldComponent implements OnInit, OnDestroy { class RuntimeComponentModule { } - let module: ModuleWithComponentFactories<any> = compiler.compileModuleAndAllComponentsSync(RuntimeComponentModule); + const module: ModuleWithComponentFactories<any> = compiler.compileModuleAndAllComponentsSync(RuntimeComponentModule); return module.componentFactories.find((x) => x.componentType === decoratedCmp); } diff --git a/lib/core/form/components/form.component.spec.ts b/lib/core/form/components/form.component.spec.ts index 56d1e44d22..5e01552d86 100644 --- a/lib/core/form/components/form.component.spec.ts +++ b/lib/core/form/components/form.component.spec.ts @@ -50,7 +50,7 @@ describe('FormComponent', () => { }); it('should allow title if task name available', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formComponent.form = formModel; expect(formComponent.showTitle).toBeTruthy(); @@ -69,7 +69,7 @@ describe('FormComponent', () => { }); it('should not allow title', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formComponent.form = formModel; formComponent.showTitle = false; @@ -87,16 +87,16 @@ describe('FormComponent', () => { }); it('should enable custom outcome buttons', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formComponent.form = formModel; - let outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' }); + const outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' }); expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); }); it('should allow controlling [complete] button visibility', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formComponent.form = formModel; - let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); + const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); formComponent.showSaveButton = true; expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); @@ -106,27 +106,27 @@ describe('FormComponent', () => { }); it('should show only [complete] button with readOnly form ', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formModel.readOnly = true; formComponent.form = formModel; - let outcome = new FormOutcomeModel(formModel, { id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION }); + const outcome = new FormOutcomeModel(formModel, { id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION }); formComponent.showCompleteButton = true; expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); }); it('should not show [save] button with readOnly form ', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formModel.readOnly = true; formComponent.form = formModel; - let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); + const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); formComponent.showSaveButton = true; expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy(); }); it('should show [custom-outcome] button with readOnly form and selected custom-outcome', () => { - let formModel = new FormModel({ selectedOutcome: 'custom-outcome' }); + const formModel = new FormModel({ selectedOutcome: 'custom-outcome' }); formModel.readOnly = true; formComponent.form = formModel; let outcome = new FormOutcomeModel(formModel, { id: '$customoutome', name: 'custom-outcome' }); @@ -140,10 +140,10 @@ describe('FormComponent', () => { }); it('should allow controlling [save] button visibility', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formModel.readOnly = false; formComponent.form = formModel; - let outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION }); + const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION }); formComponent.showCompleteButton = true; expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); @@ -251,7 +251,7 @@ describe('FormComponent', () => { spyOn(formComponent, 'getFormByTaskId').and.stub(); const taskId = '<task id>'; - let change = new SimpleChange(null, taskId, true); + const change = new SimpleChange(null, taskId, true); formComponent.ngOnChanges({ 'taskId': change }); expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId); @@ -261,7 +261,7 @@ describe('FormComponent', () => { spyOn(formComponent, 'getFormDefinitionByFormId').and.stub(); const formId = '123'; - let change = new SimpleChange(null, formId, true); + const change = new SimpleChange(null, formId, true); formComponent.ngOnChanges({ 'formId': change }); expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId); @@ -271,7 +271,7 @@ describe('FormComponent', () => { spyOn(formComponent, 'getFormDefinitionByFormName').and.stub(); const formName = '<form>'; - let change = new SimpleChange(null, formName, true); + const change = new SimpleChange(null, formName, true); formComponent.ngOnChanges({ 'formName': change }); expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName); @@ -305,24 +305,24 @@ describe('FormComponent', () => { }); it('should complete form on custom outcome click', () => { - let formModel = new FormModel(); - let outcomeName = 'Custom Action'; - let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); + const formModel = new FormModel(); + const outcomeName = 'Custom Action'; + const outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); let saved = false; formComponent.form = formModel; formComponent.formSaved.subscribe((v) => saved = true); spyOn(formComponent, 'completeTaskForm').and.stub(); - let result = formComponent.onOutcomeClicked(outcome); + const result = formComponent.onOutcomeClicked(outcome); expect(result).toBeTruthy(); expect(saved).toBeTruthy(); expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcomeName); }); it('should save form on [save] outcome click', () => { - let formModel = new FormModel(); - let outcome = new FormOutcomeModel(formModel, { + const formModel = new FormModel(); + const outcome = new FormOutcomeModel(formModel, { id: FormComponent.SAVE_OUTCOME_ID, name: 'Save', isSystem: true @@ -331,14 +331,14 @@ describe('FormComponent', () => { formComponent.form = formModel; spyOn(formComponent, 'saveTaskForm').and.stub(); - let result = formComponent.onOutcomeClicked(outcome); + const result = formComponent.onOutcomeClicked(outcome); expect(result).toBeTruthy(); expect(formComponent.saveTaskForm).toHaveBeenCalled(); }); it('should complete form on [complete] outcome click', () => { - let formModel = new FormModel(); - let outcome = new FormOutcomeModel(formModel, { + const formModel = new FormModel(); + const outcome = new FormOutcomeModel(formModel, { id: FormComponent.COMPLETE_OUTCOME_ID, name: 'Complete', isSystem: true @@ -347,14 +347,14 @@ describe('FormComponent', () => { formComponent.form = formModel; spyOn(formComponent, 'completeTaskForm').and.stub(); - let result = formComponent.onOutcomeClicked(outcome); + const result = formComponent.onOutcomeClicked(outcome); expect(result).toBeTruthy(); expect(formComponent.completeTaskForm).toHaveBeenCalled(); }); it('should emit form saved event on custom outcome click', () => { - let formModel = new FormModel(); - let outcome = new FormOutcomeModel(formModel, { + const formModel = new FormModel(); + const outcome = new FormOutcomeModel(formModel, { id: FormComponent.CUSTOM_OUTCOME_ID, name: 'Custom', isSystem: true @@ -364,15 +364,15 @@ describe('FormComponent', () => { formComponent.form = formModel; formComponent.formSaved.subscribe((v) => saved = true); - let result = formComponent.onOutcomeClicked(outcome); + const result = formComponent.onOutcomeClicked(outcome); expect(result).toBeTruthy(); expect(saved).toBeTruthy(); }); it('should do nothing when clicking outcome for readonly form', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); const outcomeName = 'Custom Action'; - let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); + const outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); formComponent.form = formModel; spyOn(formComponent, 'completeTaskForm').and.stub(); @@ -389,9 +389,9 @@ describe('FormComponent', () => { }); it('should require loaded form when clicking outcome', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); const outcomeName = 'Custom Action'; - let outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); + const outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName }); formComponent.readOnly = false; formComponent.form = null; @@ -399,15 +399,15 @@ describe('FormComponent', () => { }); it('should not execute unknown system outcome', () => { - let formModel = new FormModel(); - let outcome = new FormOutcomeModel(formModel, { id: 'unknown', name: 'Unknown', isSystem: true }); + const formModel = new FormModel(); + const outcome = new FormOutcomeModel(formModel, { id: 'unknown', name: 'Unknown', isSystem: true }); formComponent.form = formModel; expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); }); it('should require custom action name to complete form', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); let outcome = new FormOutcomeModel(formModel, { id: 'custom' }); formComponent.form = formModel; @@ -544,7 +544,7 @@ describe('FormComponent', () => { savedForm = form; }); - let formModel = new FormModel({ + const formModel = new FormModel({ taskId: '123', fields: [ { id: 'field1' }, @@ -606,7 +606,7 @@ describe('FormComponent', () => { let completed = false; formComponent.formCompleted.subscribe(() => completed = true); - let formModel = new FormModel({ + const formModel = new FormModel({ taskId: '123', fields: [ { id: 'field1' }, @@ -626,7 +626,7 @@ describe('FormComponent', () => { }); it('should parse form from json', () => { - let form = formComponent.parseForm({ + const form = formComponent.parseForm({ id: 1, fields: [ { id: 'field1', type: FormFieldTypes.CONTAINER } @@ -642,13 +642,13 @@ describe('FormComponent', () => { it('should provide outcomes for form definition', () => { spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough(); - let form = formComponent.parseForm({ id: 1 }); + const form = formComponent.parseForm({ id: 1 }); expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form); }); it('should prevent default outcome execution', () => { - let outcome = new FormOutcomeModel(new FormModel(), { + const outcome = new FormOutcomeModel(new FormModel(), { id: FormComponent.CUSTOM_OUTCOME_ID, name: 'Custom' }); @@ -660,12 +660,12 @@ describe('FormComponent', () => { expect(event.defaultPrevented).toBeTruthy(); }); - let result = formComponent.onOutcomeClicked(outcome); + const result = formComponent.onOutcomeClicked(outcome); expect(result).toBeFalsy(); }); it('should not prevent default outcome execution', () => { - let outcome = new FormOutcomeModel(new FormModel(), { + const outcome = new FormOutcomeModel(new FormModel(), { id: FormComponent.CUSTOM_OUTCOME_ID, name: 'Custom' }); @@ -678,7 +678,7 @@ describe('FormComponent', () => { spyOn(formComponent, 'completeTaskForm').and.callThrough(); - let result = formComponent.onOutcomeClicked(outcome); + const result = formComponent.onOutcomeClicked(outcome); expect(result).toBeTruthy(); expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcome.name); @@ -699,7 +699,7 @@ describe('FormComponent', () => { }); it('should load form for ecm node', () => { - let metadata = {}; + const metadata = {}; spyOn(nodeService, 'getNodeMetadata').and.returnValue( new Observable((observer) => { observer.next({ metadata: metadata }); @@ -709,7 +709,7 @@ describe('FormComponent', () => { spyOn(formComponent, 'loadFormFromActiviti').and.stub(); const nodeId = '<id>'; - let change = new SimpleChange(null, nodeId, false); + const change = new SimpleChange(null, nodeId, false); formComponent.ngOnChanges({ 'nodeId': change }); expect(nodeService.getNodeMetadata).toHaveBeenCalledWith(nodeId); @@ -718,11 +718,11 @@ describe('FormComponent', () => { }); it('should disable outcome buttons for readonly form', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formModel.readOnly = true; formComponent.form = formModel; - let outcome = new FormOutcomeModel(new FormModel(), { + const outcome = new FormOutcomeModel(new FormModel(), { id: FormComponent.CUSTOM_OUTCOME_ID, name: 'Custom' }); @@ -736,22 +736,22 @@ describe('FormComponent', () => { }); it('should always enable save outcome for writeable form', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); - let field = new FormFieldModel(formModel, { + const field = new FormFieldModel(formModel, { type: 'text', value: null, required: true }); - let containerModel = new ContainerModel(field); + const containerModel = new ContainerModel(field); formModel.fields.push(containerModel); formComponent.form = formModel; formModel.onFormFieldChanged(field); expect(formModel.isValid).toBeFalsy(); - let outcome = new FormOutcomeModel(new FormModel(), { + const outcome = new FormOutcomeModel(new FormModel(), { id: FormComponent.SAVE_OUTCOME_ID, name: FormOutcomeModel.SAVE_ACTION }); @@ -761,21 +761,21 @@ describe('FormComponent', () => { }); it('should disable outcome buttons for invalid form', () => { - let formModel = new FormModel(); - let field = new FormFieldModel(formModel, { + const formModel = new FormModel(); + const field = new FormFieldModel(formModel, { type: 'text', value: null, required: true }); - let containerModel = new ContainerModel(field); + const containerModel = new ContainerModel(field); formModel.fields.push(containerModel); formComponent.form = formModel; formModel.onFormFieldChanged(field); expect(formModel.isValid).toBeFalsy(); - let outcome = new FormOutcomeModel(new FormModel(), { + const outcome = new FormOutcomeModel(new FormModel(), { id: FormComponent.CUSTOM_OUTCOME_ID, name: 'Custom' }); @@ -784,23 +784,23 @@ describe('FormComponent', () => { }); it('should disable complete outcome button when disableCompleteButton is true', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formComponent.form = formModel; formComponent.disableCompleteButton = true; expect(formModel.isValid).toBeTruthy(); - let completeOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.COMPLETE_ACTION); + const completeOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.COMPLETE_ACTION); expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy(); }); it('should disable start process outcome button when disableStartProcessButton is true', () => { - let formModel = new FormModel(); + const formModel = new FormModel(); formComponent.form = formModel; formComponent.disableStartProcessButton = true; expect(formModel.isValid).toBeTruthy(); - let startProcessOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.START_PROCESS_ACTION); + const startProcessOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.START_PROCESS_ACTION); expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy(); }); @@ -810,7 +810,7 @@ describe('FormComponent', () => { done(); }); - let outcome = new FormOutcomeModel(new FormModel(), { + const outcome = new FormOutcomeModel(new FormModel(), { id: FormComponent.CUSTOM_OUTCOME_ID, name: 'Custom' }); @@ -828,13 +828,13 @@ describe('FormComponent', () => { expect(labelField.value).toBe('empty'); expect(radioField.value).toBeNull(); - let formValues: any = {}; + const formValues: any = {}; formValues.label = { id: 'option_2', name: 'test2' }; formValues.radio = { id: 'option_2', name: 'Option 2' }; - let change = new SimpleChange(null, formValues, false); + const change = new SimpleChange(null, formValues, false); formComponent.data = formValues; formComponent.ngOnChanges({ 'data': change }); @@ -850,9 +850,9 @@ describe('FormComponent', () => { let formFields = formComponent.form.getFormFields(); let radioFieldById = formFields.find((field) => field.id === 'radio'); - let formValues: any = {}; + const formValues: any = {}; formValues.radio = 'option_3'; - let change = new SimpleChange(null, formValues, false); + const change = new SimpleChange(null, formValues, false); formComponent.data = formValues; formComponent.ngOnChanges({ 'data': change }); diff --git a/lib/core/form/components/form.component.visibility.spec.ts b/lib/core/form/components/form.component.visibility.spec.ts index 1097999108..8d5b18f4d2 100644 --- a/lib/core/form/components/form.component.visibility.spec.ts +++ b/lib/core/form/components/form.component.visibility.spec.ts @@ -78,7 +78,7 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeDefined(); @@ -90,7 +90,7 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionRequiredField)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeNull(); @@ -102,7 +102,7 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); component.showValidationIcon = false; fixture.detectChanges(); @@ -117,15 +117,15 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); - let firstNameEl = fixture.debugElement.query(By.css('#firstname')); + const firstNameEl = fixture.debugElement.query(By.css('#firstname')); expect(firstNameEl).not.toBeNull(); expect(firstNameEl).toBeDefined(); - let lastNameEl = fixture.debugElement.query(By.css('#lastname')); + const lastNameEl = fixture.debugElement.query(By.css('#lastname')); expect(lastNameEl).not.toBeNull(); expect(lastNameEl).toBeDefined(); }); @@ -134,7 +134,7 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionDropdownField)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); @@ -165,14 +165,14 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnNextOne)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); - let firstEl = fixture.debugElement.query(By.css('#field-country-container')); + const firstEl = fixture.debugElement.query(By.css('#field-country-container')); expect(firstEl.nativeElement.hidden).toBeTruthy(); - let secondEl = fixture.debugElement.query(By.css('#name')); + const secondEl = fixture.debugElement.query(By.css('#name')); expect(secondEl).not.toBeNull(); expect(secondEl).toBeDefined(); expect(fixture.nativeElement.querySelector('#field-name-container').hidden).toBeFalsy(); @@ -182,16 +182,16 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnPreviousOne)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); - let firstEl = fixture.debugElement.query(By.css('#name')); + const firstEl = fixture.debugElement.query(By.css('#name')); expect(firstEl).not.toBeNull(); expect(firstEl).toBeDefined(); expect(fixture.nativeElement.querySelector('#field-name-container').hidden).toBeFalsy(); - let secondEl = fixture.debugElement.query(By.css('#field-country-container')); + const secondEl = fixture.debugElement.query(By.css('#field-country-container')); expect(secondEl.nativeElement.hidden).toBeTruthy(); }); @@ -199,7 +199,7 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnNextOne)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); @@ -209,7 +209,7 @@ describe('FormComponent UI and visibility', () => { const secondEl = fixture.debugElement.query(By.css('#field-name-container')); expect(secondEl.nativeElement.hidden).toBeFalsy(); - let inputElement = fixture.nativeElement.querySelector('#name'); + const inputElement = fixture.nativeElement.querySelector('#name'); inputElement.value = 'italy'; inputElement.dispatchEvent(new Event('input')); fixture.detectChanges(); @@ -224,16 +224,16 @@ describe('FormComponent UI and visibility', () => { spyOn(service, 'getTask').and.returnValue(of({})); spyOn(service, 'getTaskForm').and.returnValue(of(formReadonlyTwoTextFields)); - let change = new SimpleChange(null, 1, true); + const change = new SimpleChange(null, 1, true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); - let firstNameEl = fixture.debugElement.query(By.css('#firstname')); + const firstNameEl = fixture.debugElement.query(By.css('#firstname')); expect(firstNameEl).not.toBeNull(); expect(firstNameEl).toBeDefined(); expect(firstNameEl.nativeElement.value).toEqual('fakeFirstName'); - let lastNameEl = fixture.debugElement.query(By.css('#lastname')); + const lastNameEl = fixture.debugElement.query(By.css('#lastname')); expect(lastNameEl).not.toBeNull(); expect(lastNameEl).toBeDefined(); expect(lastNameEl.nativeElement.value).toEqual('fakeLastName'); diff --git a/lib/core/form/components/start-form.component.ts b/lib/core/form/components/start-form.component.ts index 27127ce780..ed97a64fe4 100644 --- a/lib/core/form/components/start-form.component.ts +++ b/lib/core/form/components/start-form.component.ts @@ -99,14 +99,14 @@ export class StartFormComponent extends FormComponent implements OnChanges, OnIn } ngOnChanges(changes: SimpleChanges) { - let processDefinitionId = changes['processDefinitionId']; + const processDefinitionId = changes['processDefinitionId']; if (processDefinitionId && processDefinitionId.currentValue) { this.visibilityService.cleanProcessVariable(); this.getStartFormDefinition(processDefinitionId.currentValue); return; } - let processId = changes['processId']; + const processId = changes['processId']; if (processId && processId.currentValue) { this.visibilityService.cleanProcessVariable(); this.loadStartForm(processId.currentValue); diff --git a/lib/core/form/components/widgets/container/container-column.model.spec.ts b/lib/core/form/components/widgets/container/container-column.model.spec.ts index 0ec5bec2d1..0dff52ef7d 100644 --- a/lib/core/form/components/widgets/container/container-column.model.spec.ts +++ b/lib/core/form/components/widgets/container/container-column.model.spec.ts @@ -22,12 +22,12 @@ import { FormModel } from './../core/form.model'; describe('ContainerColumnModel', () => { it('should have max size by default', () => { - let column = new ContainerColumnModel(); + const column = new ContainerColumnModel(); expect(column.size).toBe(12); }); it('should check fields', () => { - let column = new ContainerColumnModel(); + const column = new ContainerColumnModel(); column.fields = null; expect(column.hasFields()).toBeFalsy(); diff --git a/lib/core/form/components/widgets/container/container.widget.model.spec.ts b/lib/core/form/components/widgets/container/container.widget.model.spec.ts index 65c844c638..0ed357cd21 100644 --- a/lib/core/form/components/widgets/container/container.widget.model.spec.ts +++ b/lib/core/form/components/widgets/container/container.widget.model.spec.ts @@ -23,9 +23,9 @@ import { ContainerWidgetComponentModel } from './container.widget.model'; describe('ContainerWidgetComponentModel', () => { it('should store the form reference', () => { - let form = new FormModel(); - let field = new FormFieldModel(form); - let model = new ContainerWidgetComponentModel(field); + const form = new FormModel(); + const field = new FormFieldModel(form); + const model = new ContainerWidgetComponentModel(field); expect(model.form).toBe(form); }); @@ -64,7 +64,7 @@ describe('ContainerWidgetComponentModel', () => { }); it('should be collapsed by default', () => { - let container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { + const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true, diff --git a/lib/core/form/components/widgets/container/container.widget.spec.ts b/lib/core/form/components/widgets/container/container.widget.spec.ts index d1d2749787..9a98ebc028 100644 --- a/lib/core/form/components/widgets/container/container.widget.spec.ts +++ b/lib/core/form/components/widgets/container/container.widget.spec.ts @@ -49,7 +49,7 @@ describe('ContainerWidgetComponent', () => { }); it('should wrap field with model instance', () => { - let field = new FormFieldModel(null); + const field = new FormFieldModel(null); widget.field = field; widget.ngOnInit(); expect(widget.content).toBeDefined(); @@ -57,7 +57,7 @@ describe('ContainerWidgetComponent', () => { }); it('should toggle underlying group container', () => { - let container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { + const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP, params: { allowCollapse: true @@ -74,7 +74,7 @@ describe('ContainerWidgetComponent', () => { }); it('should toggle only collapsible container', () => { - let container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { + const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.GROUP })); @@ -87,7 +87,7 @@ describe('ContainerWidgetComponent', () => { it('should toggle only group container', () => { - let container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { + const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { type: FormFieldTypes.CONTAINER, params: { allowCollapse: true @@ -102,8 +102,8 @@ describe('ContainerWidgetComponent', () => { }); it('should send an event when a value is changed in the form', (done) => { - let fakeForm = new FormModel(); - let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); + const fakeForm = new FormModel(); + const fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); widget.fieldChanged.subscribe((field) => { expect(field).not.toBe(null); expect(field.id).toBe('fakeField'); @@ -124,7 +124,7 @@ describe('ContainerWidgetComponent', () => { field5 = <FormFieldModel> {id: '5'}, field6 = <FormFieldModel> {id: '6'}; - let container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel())); + const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel())); container.columns = [ <ContainerColumnModel> { fields: [ field1, @@ -157,7 +157,7 @@ describe('ContainerWidgetComponent', () => { describe('getColumnWith', () => { it('should calculate the column width based on the numberOfColumns and current field\'s colspan property', () => { - let container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { numberOfColumns: 4 })); + const container = new ContainerWidgetComponentModel(new FormFieldModel(new FormModel(), { numberOfColumns: 4 })); widget.content = container; expect(widget.getColumnWith(undefined)).toBe('25%'); diff --git a/lib/core/form/components/widgets/container/container.widget.ts b/lib/core/form/components/widgets/container/container.widget.ts index 18cf60ae1a..74bacbffd7 100644 --- a/lib/core/form/components/widgets/container/container.widget.ts +++ b/lib/core/form/components/widgets/container/container.widget.ts @@ -62,7 +62,7 @@ export class ContainerWidgetComponent extends WidgetComponent implements OnInit, while (rowContainsElement) { rowContainsElement = false; for (let i = 0; i < this.content.columns.length; i++ ) { - let field = this.content.columns[i].fields[rowIndex]; + const field = this.content.columns[i].fields[rowIndex]; if (field) { rowContainsElement = true; } diff --git a/lib/core/form/components/widgets/content/content.widget.spec.ts b/lib/core/form/components/widgets/content/content.widget.spec.ts index 422db01b82..6703d5d8d1 100644 --- a/lib/core/form/components/widgets/content/content.widget.spec.ts +++ b/lib/core/form/components/widgets/content/content.widget.spec.ts @@ -41,12 +41,12 @@ describe('ContentWidgetComponent', () => { let serviceContent: ContentService; function createFakeImageBlob() { - let data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); + const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); return new Blob([data], {type: 'image/png'}); } function createFakePdfBlob(): Blob { - let pdfData = atob( + const pdfData = atob( 'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' + 'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' + 'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' + @@ -99,12 +99,12 @@ describe('ContentWidgetComponent', () => { component.content = new ContentLinkModel(); fixture.detectChanges(); - let content = fixture.debugElement.query(By.css('div.upload-widget__content-thumbnail')); + const content = fixture.debugElement.query(By.css('div.upload-widget__content-thumbnail')); expect(content).toBeDefined(); }); it('should load the thumbnail preview of the png image', (done) => { - let blob = createFakeImageBlob(); + const blob = createFakeImageBlob(); spyOn(processContentService, 'getFileRawContent').and.returnValue(of(blob)); component.thumbnailLoaded.subscribe((res) => { @@ -114,14 +114,14 @@ describe('ContentWidgetComponent', () => { expect(res.changingThisBreaksApplicationSecurity).toContain('blob'); fixture.whenStable() .then(() => { - let thumbnailPreview: any = element.querySelector('#thumbnailPreview'); + const thumbnailPreview: any = element.querySelector('#thumbnailPreview'); expect(thumbnailPreview.src).toContain('blob'); }); done(); }); - let contentId = 1; - let change = new SimpleChange(null, contentId, true); + const contentId = 1; + const change = new SimpleChange(null, contentId, true); component.ngOnChanges({ 'id': change }); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -147,7 +147,7 @@ describe('ContentWidgetComponent', () => { }); it('should load the thumbnail preview of a pdf', (done) => { - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(processContentService, 'getContentThumbnail').and.returnValue(of(blob)); component.thumbnailLoaded.subscribe((res) => { @@ -157,14 +157,14 @@ describe('ContentWidgetComponent', () => { expect(res.changingThisBreaksApplicationSecurity).toContain('blob'); fixture.whenStable() .then(() => { - let thumbnailPreview: any = element.querySelector('#thumbnailPreview'); + const thumbnailPreview: any = element.querySelector('#thumbnailPreview'); expect(thumbnailPreview.src).toContain('blob'); }); done(); }); - let contentId = 1; - let change = new SimpleChange(null, contentId, true); + const contentId = 1; + const change = new SimpleChange(null, contentId, true); component.ngOnChanges({'id': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -191,15 +191,15 @@ describe('ContentWidgetComponent', () => { it('should show unsupported preview with unsupported file', (done) => { - let contentId = 1; - let change = new SimpleChange(null, contentId, true); + const contentId = 1; + const change = new SimpleChange(null, contentId, true); component.ngOnChanges({'id': change}); component.contentLoaded.subscribe((res) => { fixture.detectChanges(); fixture.whenStable() .then(() => { - let thumbnailPreview: any = element.querySelector('#unsupported-thumbnail'); + const thumbnailPreview: any = element.querySelector('#unsupported-thumbnail'); expect(thumbnailPreview).toBeDefined(); expect(element.querySelector('div.upload-widget__content-text').innerHTML).toEqual('FakeBlob.zip'); }); @@ -229,7 +229,7 @@ describe('ContentWidgetComponent', () => { }); it('should open the viewer when the view button is clicked', (done) => { - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(processContentService, 'getContentPreview').and.returnValue(of(blob)); spyOn(processContentService, 'getFileRawContent').and.returnValue(of(blob)); @@ -258,12 +258,12 @@ describe('ContentWidgetComponent', () => { }); fixture.detectChanges(); - let viewButton: any = element.querySelector('#view'); + const viewButton: any = element.querySelector('#view'); viewButton.click(); }); it('should download the pdf when the download button is clicked', () => { - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(processContentService, 'getFileRawContent').and.returnValue(of(blob)); spyOn(serviceContent, 'downloadBlob').and.callThrough(); @@ -285,7 +285,7 @@ describe('ContentWidgetComponent', () => { }); fixture.detectChanges(); - let downloadButton: any = element.querySelector('#download'); + const downloadButton: any = element.querySelector('#download'); downloadButton.click(); fixture.whenStable() diff --git a/lib/core/form/components/widgets/core/container.model.spec.ts b/lib/core/form/components/widgets/core/container.model.spec.ts index 6c7909c7dc..c5c0d37d24 100644 --- a/lib/core/form/components/widgets/core/container.model.spec.ts +++ b/lib/core/form/components/widgets/core/container.model.spec.ts @@ -22,8 +22,8 @@ import { FormModel } from './form.model'; describe('ContainerModel', () => { it('should store the form reference', () => { - let form = new FormModel(); - let model = new ContainerModel(new FormFieldModel(form)); + const form = new FormModel(); + const model = new ContainerModel(new FormFieldModel(form)); expect(model.form).toBe(form); }); diff --git a/lib/core/form/components/widgets/core/error-message.model.ts b/lib/core/form/components/widgets/core/error-message.model.ts index be5fa7af00..63b62d9bbf 100644 --- a/lib/core/form/components/widgets/core/error-message.model.ts +++ b/lib/core/form/components/widgets/core/error-message.model.ts @@ -34,7 +34,7 @@ export class ErrorMessageModel { getAttributesAsJsonObj() { let result = {}; if (this.attributes.size > 0) { - let obj = Object.create(null); + const obj = Object.create(null); this.attributes.forEach((value, key) => { obj[key] = value; }); diff --git a/lib/core/form/components/widgets/core/form-field-validator.spec.ts b/lib/core/form/components/widgets/core/form-field-validator.spec.ts index cd9524046a..e701b80456 100644 --- a/lib/core/form/components/widgets/core/form-field-validator.spec.ts +++ b/lib/core/form/components/widgets/core/form-field-validator.spec.ts @@ -45,7 +45,7 @@ describe('FormFieldValidator', () => { }); it('should require [required] setting', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, value: '<value>' }); @@ -60,12 +60,12 @@ describe('FormFieldValidator', () => { }); it('should skip unsupported type', () => { - let field = new FormFieldModel(new FormModel(), { type: 'wrong-type' }); + const field = new FormFieldModel(new FormModel(), { type: 'wrong-type' }); expect(validator.validate(field)).toBeTruthy(); }); it('should fail for dropdown with empty value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DROPDOWN, value: '<empty>', hasEmptyValue: true, @@ -80,7 +80,7 @@ describe('FormFieldValidator', () => { }); it('should fail for radio buttons', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.RADIO_BUTTONS, required: true, options: [{ id: 'two', name: 'two' }] @@ -91,7 +91,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for radio buttons', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.RADIO_BUTTONS, required: true, value: 'two', @@ -102,7 +102,7 @@ describe('FormFieldValidator', () => { }); it('should fail for upload', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: null, required: true @@ -116,7 +116,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for upload', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.UPLOAD, value: [{}], required: true @@ -126,7 +126,7 @@ describe('FormFieldValidator', () => { }); it('should fail for text', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, value: null, required: true @@ -140,7 +140,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for date', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATE, value: '2016-12-31', required: true @@ -150,7 +150,7 @@ describe('FormFieldValidator', () => { }); it('should fail for date', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATE, value: null, required: true @@ -164,7 +164,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for text', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, value: '<value>', required: true @@ -174,7 +174,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for check box', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.BOOLEAN, required: true, value: true, @@ -185,7 +185,7 @@ describe('FormFieldValidator', () => { }); it('should fail for check box', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.BOOLEAN, required: true, value: false, @@ -224,7 +224,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty number value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: null }); @@ -233,7 +233,7 @@ describe('FormFieldValidator', () => { }); it('should allow number value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: 44 }); @@ -242,7 +242,7 @@ describe('FormFieldValidator', () => { }); it('should allow zero number value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: 0 }); @@ -251,7 +251,7 @@ describe('FormFieldValidator', () => { }); it('should fail for wrong number value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: '<value>' }); @@ -272,7 +272,7 @@ describe('FormFieldValidator', () => { }); it('should require minLength defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); @@ -283,7 +283,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, minLength: 10, value: null @@ -293,7 +293,7 @@ describe('FormFieldValidator', () => { }); it('should succeed text validation', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, minLength: 3, value: '1234' @@ -303,7 +303,7 @@ describe('FormFieldValidator', () => { }); it('should fail text validation', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, minLength: 3, value: '12' @@ -325,7 +325,7 @@ describe('FormFieldValidator', () => { }); it('should require maxLength defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); @@ -336,7 +336,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, maxLength: 10, value: null @@ -346,7 +346,7 @@ describe('FormFieldValidator', () => { }); it('should succeed text validation', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, maxLength: 3, value: '123' @@ -356,7 +356,7 @@ describe('FormFieldValidator', () => { }); it('should fail text validation', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, maxLength: 3, value: '1234' @@ -377,7 +377,7 @@ describe('FormFieldValidator', () => { }); it('should require minValue defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER }); expect(validator.isSupported(field)).toBeFalsy(); @@ -387,7 +387,7 @@ describe('FormFieldValidator', () => { }); it('should support numeric widgets only', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, minValue: '1' }); @@ -399,7 +399,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: null, minValue: '1' @@ -409,7 +409,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for unsupported types', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); @@ -417,7 +417,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: '10', minValue: '10' @@ -427,7 +427,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: '9', minValue: '10' @@ -449,7 +449,7 @@ describe('FormFieldValidator', () => { }); it('should require maxValue defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER }); expect(validator.isSupported(field)).toBeFalsy(); @@ -459,7 +459,7 @@ describe('FormFieldValidator', () => { }); it('should support numeric widgets only', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, maxValue: '1' }); @@ -471,7 +471,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: null, maxValue: '1' @@ -481,7 +481,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for unsupported types', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); @@ -489,7 +489,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: '10', maxValue: '10' @@ -499,7 +499,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.NUMBER, value: '11', maxValue: '10' @@ -521,7 +521,7 @@ describe('FormFieldValidator', () => { }); it('should require regex pattern to be defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); expect(validator.isSupported(field)).toBeFalsy(); @@ -531,7 +531,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, value: null, regexPattern: 'pattern' @@ -541,7 +541,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating regex', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, value: 'pattern', regexPattern: 'pattern' @@ -551,7 +551,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating regex', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT, value: 'some value', regexPattern: 'pattern' @@ -584,7 +584,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TYPEAHEAD, value: null, regexPattern: 'pattern' @@ -594,7 +594,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for a valid input value in options', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TYPEAHEAD, value: '1', options: [{id: '1', name: 'Leanne Graham'}, {id: '2', name: 'Ervin Howell'}] @@ -604,7 +604,7 @@ describe('FormFieldValidator', () => { }); it('should fail for an invalid input value in options', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TYPEAHEAD, value: 'Lean', options: [{id: '1', name: 'Leanne Graham'}, {id: '2', name: 'Ervin Howell'}] @@ -624,7 +624,7 @@ describe('FormFieldValidator', () => { }); it('should require maxValue defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME }); expect(validator.isSupported(field)).toBeFalsy(); @@ -634,7 +634,7 @@ describe('FormFieldValidator', () => { }); it('should support date time widgets only', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, maxValue: '9999-02-08 10:10 AM' }); @@ -646,7 +646,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: null, maxValue: '9999-02-08 10:10 AM' @@ -656,7 +656,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for unsupported types', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); @@ -669,7 +669,7 @@ describe('FormFieldValidator', () => { const localValidValue = '2018-3-30 11:59 PM'; - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: localValidValue, maxValue: maxValueSavedInForm @@ -682,9 +682,9 @@ describe('FormFieldValidator', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; const maxValueSavedInForm = moment(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').utc().format(); - let localInvalidValue = '2018-3-31 12:01 AM'; + const localInvalidValue = '2018-3-31 12:01 AM'; - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: localInvalidValue, maxValue: maxValueSavedInForm @@ -697,7 +697,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating value checking the time', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '08-02-9999 09:10 AM', maxValue: '9999-02-08 10:10 AM' @@ -707,7 +707,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating value checking the time', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '08-02-9999 11:10 AM', maxValue: '9999-02-08 10:10 AM' @@ -719,7 +719,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating value checking the date', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '08-02-9999 09:10 AM', maxValue: '9999-02-08 10:10 AM' @@ -729,7 +729,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating value checking the date', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '08-02-9999 12:10 AM', maxValue: '9999-02-07 10:10 AM' @@ -751,7 +751,7 @@ describe('FormFieldValidator', () => { }); it('should require minValue defined', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME }); expect(validator.isSupported(field)).toBeFalsy(); @@ -761,7 +761,7 @@ describe('FormFieldValidator', () => { }); it('should support date time widgets only', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, minValue: '9999-02-08 09:10 AM' }); @@ -773,7 +773,7 @@ describe('FormFieldValidator', () => { }); it('should allow empty values', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: null, minValue: '9999-02-08 09:10 AM' @@ -783,7 +783,7 @@ describe('FormFieldValidator', () => { }); it('should succeed for unsupported types', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.TEXT }); @@ -796,7 +796,7 @@ describe('FormFieldValidator', () => { const localValidValue = '2018-3-02 06:01 AM'; - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: localValidValue, minValue: minValueSavedInForm @@ -809,9 +809,9 @@ describe('FormFieldValidator', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; const minValueSavedInForm = moment(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').utc().format(); - let localInvalidValue = '2018-3-02 05:59 AM'; + const localInvalidValue = '2018-3-02 05:59 AM'; - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: localInvalidValue, minValue: minValueSavedInForm @@ -824,7 +824,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating value by time', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '08-02-9999 09:10 AM', minValue: '9999-02-08 09:00 AM' @@ -834,7 +834,7 @@ describe('FormFieldValidator', () => { }); it('should succeed validating value by date', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '09-02-9999 09:10 AM', minValue: '9999-02-08 09:10 AM' @@ -844,7 +844,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating value by time', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '08-02-9999 09:00 AM', minValue: '9999-02-08 09:10 AM' @@ -856,7 +856,7 @@ describe('FormFieldValidator', () => { }); it('should fail validating value by date', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, value: '07-02-9999 09:10 AM', minValue: '9999-02-08 09:10 AM' diff --git a/lib/core/form/components/widgets/core/form-field-validator.ts b/lib/core/form/components/widgets/core/form-field-validator.ts index 4e3e1a59f7..8795a03846 100644 --- a/lib/core/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/form/components/widgets/core/form-field-validator.ts @@ -66,7 +66,7 @@ export class RequiredFieldValidator implements FormFieldValidator { } if (field.type === FormFieldTypes.RADIO_BUTTONS) { - let option = field.options.find((opt) => opt.id === field.value); + const option = field.options.find((opt) => opt.id === field.value); return !!option; } @@ -117,7 +117,7 @@ export class NumberFieldValidator implements FormFieldValidator { field.value === '') { return true; } - let valueStr = '' + field.value; + const valueStr = '' + field.value; let pattern = new RegExp(/^-?\d+$/); if (field.enableFractions) { pattern = new RegExp(/^-?[0-9]+(\.[0-9]{1,2})?$/); @@ -141,7 +141,7 @@ export class DateFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as <dateFormat> (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean { if (inputDate) { - let d = moment(inputDate, dateFormat, true); + const d = moment(inputDate, dateFormat, true); return d.isValid(); } @@ -200,7 +200,7 @@ export class MinDateFieldValidator implements FormFieldValidator { } else { fieldValueData = field.value; } - let min = moment(field.minValue, MIN_DATE_FORMAT); + const min = moment(field.minValue, MIN_DATE_FORMAT); if (fieldValueData.isBefore(min)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; @@ -240,7 +240,7 @@ export class MaxDateFieldValidator implements FormFieldValidator { } else { d = field.value; } - let max = moment(field.maxValue, this.MAX_DATE_FORMAT); + const max = moment(field.maxValue, this.MAX_DATE_FORMAT); if (d.isAfter(max)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; @@ -287,7 +287,7 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { } else { fieldValueDate = field.value; } - let min = moment(field.minValue, this.MIN_DATETIME_FORMAT); + const min = moment(field.minValue, this.MIN_DATETIME_FORMAT); if (fieldValueDate.isBefore(min)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; @@ -334,7 +334,7 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { } else { fieldValueDate = field.value; } - let max = moment(field.maxValue, this.MAX_DATETIME_FORMAT); + const max = moment(field.maxValue, this.MAX_DATETIME_FORMAT); if (fieldValueDate.isAfter(max)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; @@ -412,8 +412,8 @@ export class MinValueFieldValidator implements FormFieldValidator { validate(field: FormFieldModel): boolean { if (this.isSupported(field) && field.value && field.isVisible) { - let value: number = +field.value; - let minValue: number = +field.minValue; + const value: number = +field.value; + const minValue: number = +field.minValue; if (value >= minValue) { return true; @@ -442,8 +442,8 @@ export class MaxValueFieldValidator implements FormFieldValidator { validate(field: FormFieldModel): boolean { if (this.isSupported(field) && field.value && field.isVisible) { - let value: number = +field.value; - let maxValue: number = +field.maxValue; + const value: number = +field.value; + const maxValue: number = +field.maxValue; if (value <= maxValue) { return true; diff --git a/lib/core/form/components/widgets/core/form-field.model.spec.ts b/lib/core/form/components/widgets/core/form-field.model.spec.ts index 27f1a866c5..69d0c99e46 100644 --- a/lib/core/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/form/components/widgets/core/form-field.model.spec.ts @@ -22,19 +22,19 @@ import { FormModel } from './form.model'; describe('FormFieldModel', () => { it('should store the form reference', () => { - let form = new FormModel(); - let model = new FormFieldModel(form); + const form = new FormModel(); + const model = new FormFieldModel(form); expect(model.form).toBe(form); }); it('should store original json', () => { - let json = {}; - let model = new FormFieldModel(new FormModel(), json); + const json = {}; + const model = new FormFieldModel(new FormModel(), json); expect(model.json).toBe(json); }); it('should setup with json config', () => { - let json = { + const json = { fieldType: '<fieldType>', id: '<id>', name: '<name>', @@ -57,7 +57,7 @@ describe('FormFieldModel', () => { displayText: '<text>', value: '<value>' }; - let field = new FormFieldModel(new FormModel(), json); + const field = new FormFieldModel(new FormModel(), json); Object.keys(json).forEach((key) => { expect(field[key]).toBe(json[key]); }); @@ -82,9 +82,9 @@ describe('FormFieldModel', () => { }); it('should update form on every value change', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, {id: 'field1'}); - let value = 10; + const form = new FormModel(); + const field = new FormFieldModel(form, {id: 'field1'}); + const value = 10; spyOn(field, 'updateForm').and.callThrough(); field.value = value; @@ -95,8 +95,8 @@ describe('FormFieldModel', () => { }); it('should get form readonly state', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, null); + const form = new FormModel(); + const field = new FormFieldModel(form, null); expect(field.readOnly).toBeFalsy(); form.readOnly = true; @@ -104,15 +104,15 @@ describe('FormFieldModel', () => { }); it('should take own readonly state if form is writable', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, {readOnly: true}); + const form = new FormModel(); + const field = new FormFieldModel(form, {readOnly: true}); expect(form.readOnly).toBeFalsy(); expect(field.readOnly).toBeTruthy(); }); it('should parse and leave dropdown value as is', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DROPDOWN, options: [], value: 'deferred' @@ -122,8 +122,8 @@ describe('FormFieldModel', () => { }); it('should parse the date with the default format (D-M-YYYY) if the display format is missing', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { fieldType: 'FormFieldRepresentation', id: 'mmddyyyy', name: 'MM-DD-YYYY', @@ -147,8 +147,8 @@ describe('FormFieldModel', () => { }); it('should parse the date with the format MM-DD-YYYY', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { fieldType: 'FormFieldRepresentation', id: 'mmddyyyy', name: 'MM-DD-YYYY', @@ -173,8 +173,8 @@ describe('FormFieldModel', () => { }); it('should parse the date with the format MM-YY-DD', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { fieldType: 'FormFieldRepresentation', id: 'mmyydd', name: 'MM-YY-DD', @@ -199,8 +199,8 @@ describe('FormFieldModel', () => { }); it('should parse the date with the format DD-MM-YYYY', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { fieldType: 'FormFieldRepresentation', id: 'ddmmyyy', name: 'DD-MM-YYYY', @@ -225,8 +225,8 @@ describe('FormFieldModel', () => { }); it('should parse the date with the format DD-MM-YYYY when it is readonly', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { fieldType: 'FormFieldRepresentation', id: 'ddmmyyy', name: 'DD-MM-YYYY', @@ -250,7 +250,7 @@ describe('FormFieldModel', () => { }); it('should return the label of selected dropdown value ', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DROPDOWN, options: [ {id: 'fake-option-1', name: 'fake label 1'}, @@ -263,7 +263,7 @@ describe('FormFieldModel', () => { }); it('should parse and resolve radio button value', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.RADIO_BUTTONS, options: [ {id: 'opt1', name: 'Option 1'}, @@ -276,7 +276,7 @@ describe('FormFieldModel', () => { }); it('should parse and leave radio button value as is', () => { - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.RADIO_BUTTONS, options: [], value: 'deferred-radio' @@ -285,8 +285,8 @@ describe('FormFieldModel', () => { }); it('should update form with empty dropdown value', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { id: 'dropdown-1', type: FormFieldTypes.DROPDOWN }); @@ -299,8 +299,8 @@ describe('FormFieldModel', () => { }); it('should update form with dropdown value', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { id: 'dropdown-2', type: FormFieldTypes.DROPDOWN, options: [ @@ -314,8 +314,8 @@ describe('FormFieldModel', () => { }); it('should update form with radio button value', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { id: 'radio-1', type: FormFieldTypes.RADIO_BUTTONS, options: [ @@ -329,8 +329,8 @@ describe('FormFieldModel', () => { }); it('radio button value should be null when no default is set', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { id: 'radio-2', type: FormFieldTypes.RADIO_BUTTONS, options: [ @@ -344,10 +344,10 @@ describe('FormFieldModel', () => { }); it('should not update form with display-only field value', () => { - let form = new FormModel(); + const form = new FormModel(); FormFieldTypes.READONLY_TYPES.forEach((typeName) => { - let field = new FormFieldModel(form, { + const field = new FormFieldModel(form, { id: typeName, type: typeName }); @@ -358,8 +358,8 @@ describe('FormFieldModel', () => { }); it('should be able to check if the field has options available', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { id: 'dropdown-happy', type: FormFieldTypes.DROPDOWN, options: [ @@ -372,8 +372,8 @@ describe('FormFieldModel', () => { }); it('should return false if field has no options', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { id: 'dropdown-sad', type: FormFieldTypes.DROPDOWN }); @@ -382,8 +382,8 @@ describe('FormFieldModel', () => { }); it('should calculate the columns in case of container type', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { type: FormFieldTypes.CONTAINER, numberOfColumns: 888 }); @@ -392,8 +392,8 @@ describe('FormFieldModel', () => { }); it('should calculate the columns in case of group type', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { type: FormFieldTypes.GROUP, numberOfColumns: 999 }); diff --git a/lib/core/form/components/widgets/core/form-field.model.ts b/lib/core/form/components/widgets/core/form-field.model.ts index 96f4c7f25c..56a6cc9e71 100644 --- a/lib/core/form/components/widgets/core/form-field.model.ts +++ b/lib/core/form/components/widgets/core/form-field.model.ts @@ -121,8 +121,8 @@ export class FormFieldModel extends FormWidgetModel { this.validationSummary = new ErrorMessageModel(); if (!this.readOnly) { - let validators = this.form.fieldValidators || []; - for (let validator of validators) { + const validators = this.form.fieldValidators || []; + for (const validator of validators) { if (!validator.validate(this)) { this._isValid = false; return this._isValid; @@ -229,7 +229,7 @@ export class FormFieldModel extends FormWidgetModel { } private getVariablesValue(variableName: string, form: FormModel) { - let variable = form.json.variables.find((currentVariable) => { + const variable = form.json.variables.find((currentVariable) => { return currentVariable.name === variableName; }); @@ -267,11 +267,11 @@ export class FormFieldModel extends FormWidgetModel { this.colspan = 1; if (json.fields) { - for (let currentField in json.fields) { + for (const currentField in json.fields) { if (json.fields.hasOwnProperty(currentField)) { - let col = new ContainerColumnModel(); + const col = new ContainerColumnModel(); - let fields: FormFieldModel[] = (json.fields[currentField] || []).map((f) => new FormFieldModel(form, f)); + const fields: FormFieldModel[] = (json.fields[currentField] || []).map((f) => new FormFieldModel(form, f)); col.fields = fields; col.rowspan = json.fields[currentField].length; @@ -295,9 +295,9 @@ export class FormFieldModel extends FormWidgetModel { */ if (json.type === FormFieldTypes.DROPDOWN) { if (json.hasEmptyValue && json.options) { - let options = <FormFieldOption[]> json.options || []; + const options = <FormFieldOption[]> json.options || []; if (options.length > 0) { - let emptyOption = json.options[0]; + const emptyOption = json.options[0]; if (value === '' || value === emptyOption.id || value === emptyOption.name) { value = emptyOption.id; } else if (value.id && value.name) { @@ -315,7 +315,7 @@ export class FormFieldModel extends FormWidgetModel { // Activiti has a bug with default radio button value where initial selection passed as `name` value // so try resolving current one with a fallback to first entry via name or id // TODO: needs to be reported and fixed at Activiti side - let entry: FormFieldOption[] = this.options.filter((opt) => + const entry: FormFieldOption[] = this.options.filter((opt) => opt.id === value || opt.name === value || (value && (opt.id === value.id || opt.name === value.name))); if (entry.length > 0) { value = entry[0].id; @@ -357,7 +357,7 @@ export class FormFieldModel extends FormWidgetModel { if (this.value === 'empty' || this.value === '') { this.form.values[this.id] = {}; } else { - let entry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value); + const entry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value); if (entry.length > 0) { this.form.values[this.id] = entry[0]; } @@ -368,7 +368,7 @@ export class FormFieldModel extends FormWidgetModel { This is needed due to Activiti issue related to reading radio button values as value string but saving back as object: { id: <id>, name: <name> } */ - let rbEntry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value); + const rbEntry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value); if (rbEntry.length > 0) { this.form.values[this.id] = rbEntry[0]; } @@ -381,7 +381,7 @@ export class FormFieldModel extends FormWidgetModel { } break; case FormFieldTypes.TYPEAHEAD: - let taEntry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value || opt.name === this.value); + const taEntry: FormFieldOption[] = this.options.filter((opt) => opt.id === this.value || opt.name === this.value); if (taEntry.length > 0) { this.form.values[this.id] = taEntry[0]; } else if (this.options.length > 0) { @@ -389,7 +389,7 @@ export class FormFieldModel extends FormWidgetModel { } break; case FormFieldTypes.DATE: - let dateValue = moment(this.value, this.dateDisplayFormat, true); + const dateValue = moment(this.value, this.dateDisplayFormat, true); if (dateValue && dateValue.isValid()) { this.form.values[this.id] = `${dateValue.format('YYYY-MM-DD')}T00:00:00.000Z`; } else { @@ -435,7 +435,7 @@ export class FormFieldModel extends FormWidgetModel { } getOptionName(): string { - let option: FormFieldOption = this.options.find((opt) => opt.id === this.value); + const option: FormFieldOption = this.options.find((opt) => opt.id === this.value); return option ? option.name : null; } diff --git a/lib/core/form/components/widgets/core/form-outcome.model.spec.ts b/lib/core/form/components/widgets/core/form-outcome.model.spec.ts index a9891a823c..4bcde60ba7 100644 --- a/lib/core/form/components/widgets/core/form-outcome.model.spec.ts +++ b/lib/core/form/components/widgets/core/form-outcome.model.spec.ts @@ -21,24 +21,24 @@ import { FormModel } from './form.model'; describe('FormOutcomeModel', () => { it('should setup with json config', () => { - let json = { + const json = { id: '<id>', name: '<name>' }; - let model = new FormOutcomeModel(null, json); + const model = new FormOutcomeModel(null, json); expect(model.id).toBe(json.id); expect(model.name).toBe(json.name); }); it('should store the form reference', () => { - let form = new FormModel(); - let model = new FormOutcomeModel(form); + const form = new FormModel(); + const model = new FormOutcomeModel(form); expect(model.form).toBe(form); }); it('should store original json', () => { - let json = {}; - let model = new FormOutcomeModel(null, json); + const json = {}; + const model = new FormOutcomeModel(null, json); expect(model.json).toBe(json); }); diff --git a/lib/core/form/components/widgets/core/form-widget.model.spec.ts b/lib/core/form/components/widgets/core/form-widget.model.spec.ts index 200fecb17a..293ae59b9d 100644 --- a/lib/core/form/components/widgets/core/form-widget.model.spec.ts +++ b/lib/core/form/components/widgets/core/form-widget.model.spec.ts @@ -27,14 +27,14 @@ describe('FormWidgetModel', () => { } it('should store the form reference', () => { - let form = new FormModel(); - let model = new FormWidgetModelMock(form, null); + const form = new FormModel(); + const model = new FormWidgetModelMock(form, null); expect(model.form).toBe(form); }); it('should store original json', () => { - let json = {}; - let model = new FormWidgetModelMock(null, json); + const json = {}; + const model = new FormWidgetModelMock(null, json); expect(model.json).toBe(json); }); diff --git a/lib/core/form/components/widgets/core/form.model.spec.ts b/lib/core/form/components/widgets/core/form.model.spec.ts index c925fcf5f6..5ada0ac272 100644 --- a/lib/core/form/components/widgets/core/form.model.spec.ts +++ b/lib/core/form/components/widgets/core/form.model.spec.ts @@ -35,19 +35,19 @@ describe('FormModel', () => { }); it('should store original json', () => { - let json = {}; - let form = new FormModel(json); + const json = {}; + const form = new FormModel(json); expect(form.json).toBe(json); }); it('should setup properties with json', () => { - let json = { + const json = { id: '<id>', name: '<name>', taskId: '<task-id>', taskName: '<task-name>' }; - let form = new FormModel(json); + const form = new FormModel(json); Object.keys(json).forEach((key) => { expect(form[key]).toEqual(form[key]); @@ -55,26 +55,26 @@ describe('FormModel', () => { }); it('should take form name when task name is missing', () => { - let json = { + const json = { id: '<id>', name: '<name>' }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.taskName).toBe(json.name); }); it('should use fallback value for task name', () => { - let form = new FormModel({}); + const form = new FormModel({}); expect(form.taskName).toBe(FormModel.UNSET_TASK_NAME); }); it('should set readonly state from params', () => { - let form = new FormModel({}, null, true); + const form = new FormModel({}, null, true); expect(form.readOnly).toBeTruthy(); }); it('should check tabs', () => { - let form = new FormModel(); + const form = new FormModel(); form.tabs = null; expect(form.hasTabs()).toBeFalsy(); @@ -87,7 +87,7 @@ describe('FormModel', () => { }); it('should check fields', () => { - let form = new FormModel(); + const form = new FormModel(); form.fields = null; expect(form.hasFields()).toBeFalsy(); @@ -95,13 +95,13 @@ describe('FormModel', () => { form.fields = []; expect(form.hasFields()).toBeFalsy(); - let field = new FormFieldModel(form); + const field = new FormFieldModel(form); form.fields = [new ContainerModel(field)]; expect(form.hasFields()).toBeTruthy(); }); it('should check outcomes', () => { - let form = new FormModel(); + const form = new FormModel(); form.outcomes = null; expect(form.hasOutcomes()).toBeFalsy(); @@ -114,21 +114,21 @@ describe('FormModel', () => { }); it('should parse tabs', () => { - let json = { + const json = { tabs: [ { id: 'tab1' }, { id: 'tab2' } ] }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.tabs.length).toBe(2); expect(form.tabs[0].id).toBe('tab1'); expect(form.tabs[1].id).toBe('tab2'); }); it('should parse fields', () => { - let json = { + const json = { fields: [ { id: 'field1', @@ -141,14 +141,14 @@ describe('FormModel', () => { ] }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.fields.length).toBe(2); expect(form.fields[0].id).toBe('field1'); expect(form.fields[1].id).toBe('field2'); }); it('should parse fields from the definition', () => { - let json = { + const json = { fields: null, formDefinition: { fields: [ @@ -164,24 +164,24 @@ describe('FormModel', () => { } }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.fields.length).toBe(2); expect(form.fields[0].id).toBe('field1'); expect(form.fields[1].id).toBe('field2'); }); it('should convert missing fields to empty collection', () => { - let json = { + const json = { fields: null }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.fields).toBeDefined(); expect(form.fields.length).toBe(0); }); it('should put fields into corresponding tabs', () => { - let json = { + const json = { tabs: [ { id: 'tab1' }, { id: 'tab2' } @@ -194,28 +194,28 @@ describe('FormModel', () => { ] }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.tabs.length).toBe(2); expect(form.fields.length).toBe(4); - let tab1 = form.tabs[0]; + const tab1 = form.tabs[0]; expect(tab1.fields.length).toBe(2); expect(tab1.fields[0].id).toBe('field1'); expect(tab1.fields[1].id).toBe('field3'); - let tab2 = form.tabs[1]; + const tab2 = form.tabs[1]; expect(tab2.fields.length).toBe(1); expect(tab2.fields[0].id).toBe('field2'); }); it('should create standard form outcomes', () => { - let json = { + const json = { fields: [ { id: 'container1' } ] }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.outcomes.length).toBe(3); expect(form.outcomes[0].id).toBe(FormModel.SAVE_OUTCOME); @@ -229,15 +229,15 @@ describe('FormModel', () => { }); it('should create outcomes only when fields available', () => { - let json = { + const json = { fields: null }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.outcomes.length).toBe(0); }); it('should use custom form outcomes', () => { - let json = { + const json = { fields: [ { id: 'container1' } ], @@ -246,7 +246,7 @@ describe('FormModel', () => { ] }; - let form = new FormModel(json); + const form = new FormModel(json); expect(form.outcomes.length).toBe(2); expect(form.outcomes[0].id).toBe(FormModel.SAVE_OUTCOME); @@ -381,7 +381,7 @@ describe('FormModel', () => { spyOn(form, 'getFormFields').and.returnValue([testField]); - let validator = <FormFieldValidator> { + const validator = <FormFieldValidator> { isSupported(field: FormFieldModel): boolean { return true; }, diff --git a/lib/core/form/components/widgets/core/form.model.ts b/lib/core/form/components/widgets/core/form.model.ts index 2b9f9c3097..e845a66dc6 100644 --- a/lib/core/form/components/widgets/core/form.model.ts +++ b/lib/core/form/components/widgets/core/form.model.ts @@ -95,12 +95,12 @@ export class FormModel { this.selectedOutcome = json.selectedOutcome || {}; this.className = json.className || ''; - let tabCache: FormWidgetModelCache<TabModel> = {}; + const tabCache: FormWidgetModelCache<TabModel> = {}; this.processVariables = json.processVariables; this.tabs = (json.tabs || []).map((t) => { - let model = new TabModel(this, t); + const model = new TabModel(this, t); tabCache[model.id] = model; return model; }); @@ -112,9 +112,9 @@ export class FormModel { } for (let i = 0; i < this.fields.length; i++) { - let field = this.fields[i]; + const field = this.fields[i]; if (field.tab) { - let tab = tabCache[field.tab]; + const tab = tabCache[field.tab]; if (tab) { tab.fields.push(field); } @@ -122,23 +122,23 @@ export class FormModel { } if (json.fields) { - let saveOutcome = new FormOutcomeModel(this, { + const saveOutcome = new FormOutcomeModel(this, { id: FormModel.SAVE_OUTCOME, name: 'SAVE', isSystem: true }); - let completeOutcome = new FormOutcomeModel(this, { + const completeOutcome = new FormOutcomeModel(this, { id: FormModel.COMPLETE_OUTCOME, name: 'COMPLETE', isSystem: true }); - let startProcessOutcome = new FormOutcomeModel(this, { + const startProcessOutcome = new FormOutcomeModel(this, { id: FormModel.START_PROCESS_OUTCOME, name: 'START PROCESS', isSystem: true }); - let customOutcomes = (json.outcomes || []).map((obj) => new FormOutcomeModel(this, obj)); + const customOutcomes = (json.outcomes || []).map((obj) => new FormOutcomeModel(this, obj)); this.outcomes = [saveOutcome].concat( customOutcomes.length > 0 ? customOutcomes : [completeOutcome, startProcessOutcome] @@ -162,13 +162,13 @@ export class FormModel { // TODO: consider evaluating and caching once the form is loaded getFormFields(): FormFieldModel[] { - let formFieldModel: FormFieldModel[] = []; + const formFieldModel: FormFieldModel[] = []; for (let i = 0; i < this.fields.length; i++) { - let field = this.fields[i]; + const field = this.fields[i]; if (field instanceof ContainerModel) { - let container = <ContainerModel> field; + const container = <ContainerModel> field; formFieldModel.push(container.field); container.field.columns.forEach((column) => { @@ -192,9 +192,9 @@ export class FormModel { validateForm(): void { const validateFormEvent: any = new ValidateFormEvent(this); - let errorsField: FormFieldModel[] = []; + const errorsField: FormFieldModel[] = []; - let fields = this.getFormFields(); + const fields = this.getFormFields(); for (let i = 0; i < fields.length; i++) { if (!fields[i].validate()) { errorsField.push(fields[i]); @@ -254,13 +254,13 @@ export class FormModel { fields = json.formDefinition.fields; } - let formWidgetModel: FormWidgetModel[] = []; + const formWidgetModel: FormWidgetModel[] = []; - for (let field of fields) { + for (const field of fields) { if (field.type === FormFieldTypes.DISPLAY_VALUE) { // workaround for dynamic table on a completed/readonly form if (field.params) { - let originalField = field.params['field']; + const originalField = field.params['field']; if (originalField.type === FormFieldTypes.DYNAMIC_TABLE) { formWidgetModel.push(new ContainerModel(new FormFieldModel(this, field))); } @@ -276,7 +276,7 @@ export class FormModel { // Loads external data and overrides field values // Typically used when form definition and form data coming from different sources private loadData(formValues: FormValues) { - for (let field of this.getFormFields()) { + for (const field of this.getFormFields()) { if (formValues[field.id]) { field.json.value = formValues[field.id]; field.value = field.parseValue(field.json); diff --git a/lib/core/form/components/widgets/core/tab.model.spec.ts b/lib/core/form/components/widgets/core/tab.model.spec.ts index 342f270418..f93f28a0eb 100644 --- a/lib/core/form/components/widgets/core/tab.model.spec.ts +++ b/lib/core/form/components/widgets/core/tab.model.spec.ts @@ -23,20 +23,20 @@ import { TabModel } from './tab.model'; describe('TabModel', () => { it('should setup with json config', () => { - let json = { + const json = { id: '<id>', title: '<title>', visibilityCondition: '<condition>' }; - let model = new TabModel(null, json); + const model = new TabModel(null, json); expect(model.id).toBe(json.id); expect(model.title).toBe(json.title); expect(model.isVisible).toBe(true); }); it('should not setup with json config', () => { - let model = new TabModel(null, null); + const model = new TabModel(null, null); expect(model.id).toBeUndefined(); expect(model.title).toBeUndefined(); expect(model.isVisible).toBeDefined(); @@ -45,7 +45,7 @@ describe('TabModel', () => { }); it('should evaluate content based on fields', () => { - let model = new TabModel(null, null); + const model = new TabModel(null, null); model.fields = null; expect(model.hasContent()).toBeFalsy(); @@ -53,21 +53,21 @@ describe('TabModel', () => { model.fields = []; expect(model.hasContent()).toBeFalsy(); - let form = new FormModel(); - let field = new FormFieldModel(form); + const form = new FormModel(); + const field = new FormFieldModel(form); model.fields = [new ContainerModel(field)]; expect(model.hasContent()).toBeTruthy(); }); it('should store the form reference', () => { - let form = new FormModel(); - let model = new TabModel(form); + const form = new FormModel(); + const model = new TabModel(form); expect(model.form).toBe(form); }); it('should store original json', () => { - let json = {}; - let model = new TabModel(null, json); + const json = {}; + const model = new TabModel(null, json); expect(model.json).toBe(json); }); diff --git a/lib/core/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/form/components/widgets/date-time/date-time.widget.spec.ts index 5fb66d8c20..18540602b5 100644 --- a/lib/core/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/form/components/widgets/date-time/date-time.widget.spec.ts @@ -50,7 +50,7 @@ describe('DateTimeWidgetComponent', () => { }); it('should setup min value for date picker', () => { - let minValue = '1982-03-13T10:00Z'; + const minValue = '1982-03-13T10:00Z'; widget.field = new FormFieldModel(null, { id: 'date-id', name: 'date-name', @@ -60,7 +60,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - let expected = moment(minValue, 'YYYY-MM-DDTHH:mm:ssZ'); + const expected = moment(minValue, 'YYYY-MM-DDTHH:mm:ssZ'); expect(widget.minDate.isSame(expected)).toBeTruthy(); }); @@ -77,20 +77,20 @@ describe('DateTimeWidgetComponent', () => { }); it('should setup max value for date picker', () => { - let maxValue = '1982-03-13T10:00Z'; + const maxValue = '1982-03-13T10:00Z'; widget.field = new FormFieldModel(null, { maxValue: maxValue }); fixture.detectChanges(); - let expected = moment(maxValue, 'YYYY-MM-DDTHH:mm:ssZ'); + const expected = moment(maxValue, 'YYYY-MM-DDTHH:mm:ssZ'); expect(widget.maxDate.isSame(expected)).toBeTruthy(); }); it('should eval visibility on date changed', () => { spyOn(widget, 'onFieldChanged').and.callThrough(); - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { id: 'date-field-id', name: 'date-name', value: '9-12-9999 10:00 AM', @@ -119,7 +119,7 @@ describe('DateTimeWidgetComponent', () => { .then(() => { expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); + const dateElement: any = element.querySelector('#date-field-id'); expect(dateElement.value).toBe('30-11-9999 10:30 AM'); }); })); @@ -141,7 +141,7 @@ describe('DateTimeWidgetComponent', () => { .then(() => { expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); + const dateElement: any = element.querySelector('#date-field-id'); expect(dateElement.value).toContain('11-29-9999 10:30 AM'); expect(element.querySelector('.adf-error-text').textContent).toBe('FORM.FIELD.VALIDATOR.NOT_LESS_THAN'); }); @@ -162,7 +162,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); + const dateElement: any = element.querySelector('#date-field-id'); expect(dateElement.value).toContain('12-30-9999 10:30 AM'); }); })); diff --git a/lib/core/form/components/widgets/date-time/date-time.widget.ts b/lib/core/form/components/widgets/date-time/date-time.widget.ts index c3bfa80876..2dfbdf1ad6 100644 --- a/lib/core/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/form/components/widgets/date-time/date-time.widget.ts @@ -58,7 +58,7 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit { this.dateAdapter.setLocale(locale); }); - let momentDateAdapter = <MomentDateAdapter> this.dateAdapter; + const momentDateAdapter = <MomentDateAdapter> this.dateAdapter; momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; if (this.field) { diff --git a/lib/core/form/components/widgets/date/date.widget.spec.ts b/lib/core/form/components/widgets/date/date.widget.spec.ts index c2d1bcfa58..9ea6977d58 100644 --- a/lib/core/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/form/components/widgets/date/date.widget.spec.ts @@ -45,7 +45,7 @@ describe('DateWidgetComponent', () => { }); it('should setup min value for date picker', () => { - let minValue = '13-03-1982'; + const minValue = '13-03-1982'; widget.field = new FormFieldModel(null, { id: 'date-id', name: 'date-name', @@ -54,12 +54,12 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - let expected = moment(minValue, widget.field.dateDisplayFormat); + const expected = moment(minValue, widget.field.dateDisplayFormat); expect(widget.minDate.isSame(expected)).toBeTruthy(); }); it('should date field be present', () => { - let minValue = '13-03-1982'; + const minValue = '13-03-1982'; widget.field = new FormFieldModel(null, { minValue: minValue }); @@ -71,20 +71,20 @@ describe('DateWidgetComponent', () => { }); it('should setup max value for date picker', () => { - let maxValue = '31-03-1982'; + const maxValue = '31-03-1982'; widget.field = new FormFieldModel(null, { maxValue: maxValue }); widget.ngOnInit(); - let expected = moment(maxValue, widget.field.dateDisplayFormat); + const expected = moment(maxValue, widget.field.dateDisplayFormat); expect(widget.maxDate.isSame(expected)).toBeTruthy(); }); it('should eval visibility on date changed', () => { spyOn(widget, 'onFieldChanged').and.callThrough(); - let field = new FormFieldModel(new FormModel(), { + const field = new FormFieldModel(new FormModel(), { id: 'date-field-id', name: 'date-name', value: '9-9-9999', @@ -119,7 +119,7 @@ describe('DateWidgetComponent', () => { fixture.whenStable().then(() => { expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); + const dateElement: any = element.querySelector('#date-field-id'); expect(dateElement.value).toContain('9-9-9999'); }); })); @@ -141,7 +141,7 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); + const dateElement: any = element.querySelector('#date-field-id'); expect(dateElement.value).toContain('11-30-9999'); expect(element.querySelector('.adf-error-text').textContent).toBe('FORM.FIELD.VALIDATOR.NOT_LESS_THAN'); }); @@ -163,7 +163,7 @@ describe('DateWidgetComponent', () => { .then(() => { expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); - let dateElement: any = element.querySelector('#date-field-id'); + const dateElement: any = element.querySelector('#date-field-id'); expect(dateElement.value).toContain('12-30-9999'); }); })); diff --git a/lib/core/form/components/widgets/date/date.widget.ts b/lib/core/form/components/widgets/date/date.widget.ts index b063c861d7..e9f3a75fe9 100644 --- a/lib/core/form/components/widgets/date/date.widget.ts +++ b/lib/core/form/components/widgets/date/date.widget.ts @@ -55,7 +55,7 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit { this.dateAdapter.setLocale(locale); }); - let momentDateAdapter = <MomentDateAdapter> this.dateAdapter; + const momentDateAdapter = <MomentDateAdapter> this.dateAdapter; momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; if (this.field) { diff --git a/lib/core/form/components/widgets/dropdown/dropdown.widget.spec.ts b/lib/core/form/components/widgets/dropdown/dropdown.widget.spec.ts index 460db169be..075cd70bf8 100644 --- a/lib/core/form/components/widgets/dropdown/dropdown.widget.spec.ts +++ b/lib/core/form/components/widgets/dropdown/dropdown.widget.spec.ts @@ -42,7 +42,7 @@ describe('DropdownWidgetComponent', () => { fixture.detectChanges(); } - let fakeOptionList: FormFieldOption[] = [ + const fakeOptionList: FormFieldOption[] = [ { id: 'opt_1', name: 'option_1' }, { id: 'opt_2', name: 'option_2' }, { id: 'opt_3', name: 'option_3' }]; @@ -79,7 +79,7 @@ describe('DropdownWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -99,7 +99,7 @@ describe('DropdownWidgetComponent', () => { }); it('should preserve empty option when loading fields', () => { - let restFieldValue: FormFieldOption = <FormFieldOption> { id: '1', name: 'Option1' }; + const restFieldValue: FormFieldOption = <FormFieldOption> { id: '1', name: 'Option1' }; spyOn(formService, 'getRestFieldValues').and.callFake(() => { return new Observable((observer) => { observer.next([restFieldValue]); @@ -107,8 +107,8 @@ describe('DropdownWidgetComponent', () => { }); }); - let form = new FormModel({ taskId: '<id>' }); - let emptyOption: FormFieldOption = <FormFieldOption> { id: 'empty', name: 'Empty' }; + const form = new FormModel({ taskId: '<id>' }); + const emptyOption: FormFieldOption = <FormFieldOption> { id: 'empty', name: 'Empty' }; widget.field = new FormFieldModel(form, { id: '<id>', restUrl: '/some/url/address', @@ -165,7 +165,7 @@ describe('DropdownWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable() .then(() => { - let dropDownElement: any = element.querySelector('#dropdown-id'); + const dropDownElement: any = element.querySelector('#dropdown-id'); expect(dropDownElement.attributes['ng-reflect-model'].value).toBe('option_2'); expect(dropDownElement.attributes['ng-reflect-model'].textContent).toBe('option_2'); }); @@ -182,7 +182,7 @@ describe('DropdownWidgetComponent', () => { fixture.whenStable() .then(() => { - let dropDownElement: any = element.querySelector('#dropdown-id'); + const dropDownElement: any = element.querySelector('#dropdown-id'); expect(dropDownElement.attributes['ng-reflect-model'].value).toBe('empty'); }); })); @@ -229,7 +229,7 @@ describe('DropdownWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable() .then(() => { - let dropDownElement: any = element.querySelector('#dropdown-id'); + const dropDownElement: any = element.querySelector('#dropdown-id'); expect(dropDownElement.attributes['ng-reflect-model'].value).toBe('option_2'); expect(dropDownElement.attributes['ng-reflect-model'].textContent).toBe('option_2'); }); @@ -246,7 +246,7 @@ describe('DropdownWidgetComponent', () => { fixture.whenStable() .then(() => { - let dropDownElement: any = element.querySelector('#dropdown-id'); + const dropDownElement: any = element.querySelector('#dropdown-id'); expect(dropDownElement.attributes['ng-reflect-model'].value).toBe('empty'); }); })); @@ -263,7 +263,7 @@ describe('DropdownWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable() .then(() => { - let dropDownElement: HTMLSelectElement = <HTMLSelectElement> element.querySelector('#dropdown-id'); + const dropDownElement: HTMLSelectElement = <HTMLSelectElement> element.querySelector('#dropdown-id'); expect(dropDownElement).not.toBeNull(); expect(dropDownElement.getAttribute('aria-disabled')).toBe('true'); }); diff --git a/lib/core/form/components/widgets/dropdown/dropdown.widget.ts b/lib/core/form/components/widgets/dropdown/dropdown.widget.ts index 365c876691..2df258a7f6 100644 --- a/lib/core/form/components/widgets/dropdown/dropdown.widget.ts +++ b/lib/core/form/components/widgets/dropdown/dropdown.widget.ts @@ -55,7 +55,7 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit { ) .subscribe( (formFieldOption: FormFieldOption[]) => { - let options = []; + const options = []; if (this.field.emptyOption) { options.push(this.field.emptyOption); } @@ -74,7 +74,7 @@ export class DropdownWidgetComponent extends WidgetComponent implements OnInit { ) .subscribe( (formFieldOption: FormFieldOption[]) => { - let options = []; + const options = []; if (this.field.emptyOption) { options.push(this.field.emptyOption); } diff --git a/lib/core/form/components/widgets/dynamic-table/date-cell-validator-model.ts b/lib/core/form/components/widgets/dynamic-table/date-cell-validator-model.ts index 430154c7ff..73a650b361 100644 --- a/lib/core/form/components/widgets/dynamic-table/date-cell-validator-model.ts +++ b/lib/core/form/components/widgets/dynamic-table/date-cell-validator-model.ts @@ -36,8 +36,8 @@ export class DateCellValidator implements CellValidator { validate(row: DynamicTableRow, column: DynamicTableColumn, summary?: DynamicRowValidationSummary): boolean { if (this.isSupported(column)) { - let value = row.value[column.id]; - let dateValue = moment(value, 'D-M-YYYY'); + const value = row.value[column.id]; + const dateValue = moment(value, 'D-M-YYYY'); if (!dateValue.isValid()) { if (summary) { summary.isValid = false; diff --git a/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.model.ts b/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.model.ts index 8d5c37abde..4ed690c53a 100644 --- a/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.model.ts +++ b/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.model.ts @@ -105,7 +105,7 @@ export class DynamicTableModel extends FormWidgetModel { } moveRow(row: DynamicTableRow, offset: number) { - let oldIndex = this.rows.indexOf(row); + const oldIndex = this.rows.indexOf(row); if (oldIndex > -1) { let newIndex = (oldIndex + offset); @@ -115,7 +115,7 @@ export class DynamicTableModel extends FormWidgetModel { newIndex = this.rows.length; } - let arr = this.rows.slice(); + const arr = this.rows.slice(); arr.splice(oldIndex, 1); arr.splice(newIndex, 0, row); this.rows = arr; @@ -129,7 +129,7 @@ export class DynamicTableModel extends FormWidgetModel { if (this.selectedRow === row) { this.selectedRow = null; } - let idx = this.rows.indexOf(row); + const idx = this.rows.indexOf(row); if (idx > -1) { this.rows.splice(idx, 1); this.flushValue(); @@ -158,8 +158,8 @@ export class DynamicTableModel extends FormWidgetModel { } if (row) { - for (let col of this.columns) { - for (let validator of this._validators) { + for (const col of this.columns) { + for (const validator of this._validators) { if (!validator.validate(row, col, summary)) { return summary; } @@ -171,7 +171,7 @@ export class DynamicTableModel extends FormWidgetModel { } getCellValue(row: DynamicTableRow, column: DynamicTableColumn): any { - let rowValue = row.value[column.id]; + const rowValue = row.value[column.id]; if (column.type === 'Dropdown') { if (rowValue) { @@ -195,7 +195,7 @@ export class DynamicTableModel extends FormWidgetModel { getDisplayText(column: DynamicTableColumn): string { let columnName = column.name; if (column.type === 'Amount') { - let currency = column.amountCurrency || '$'; + const currency = column.amountCurrency || '$'; columnName = `${column.name} (${currency})`; } return columnName; diff --git a/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.spec.ts b/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.spec.ts index 7851c84994..539b13e4ed 100644 --- a/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.spec.ts @@ -27,7 +27,7 @@ import { setupTestBed } from '../../../../testing/setupTestBed'; import { CoreModule } from '../../../../core.module'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -let fakeFormField = { +const fakeFormField = { id: 'fake-dynamic-table', name: 'fake-label', value: [{1: 1, 2: 2, 3: 4}], @@ -89,10 +89,10 @@ describe('DynamicTableWidgetComponent', () => { logService = TestBed.get(LogService); formService = TestBed.get(FormService); table = new DynamicTableModel(field, formService); - let changeDetectorSpy = jasmine.createSpyObj('cd', ['detectChanges']); - let nativeElementSpy = jasmine.createSpyObj('nativeElement', ['querySelector']); + const changeDetectorSpy = jasmine.createSpyObj('cd', ['detectChanges']); + const nativeElementSpy = jasmine.createSpyObj('nativeElement', ['querySelector']); changeDetectorSpy.nativeElement = nativeElementSpy; - let elementRefSpy = jasmine.createSpyObj('elementRef', ['']); + const elementRefSpy = jasmine.createSpyObj('elementRef', ['']); elementRefSpy.nativeElement = nativeElementSpy; fixture = TestBed.createComponent(DynamicTableWidgetComponent); @@ -107,7 +107,7 @@ describe('DynamicTableWidgetComponent', () => { }); it('should select row on click', () => { - let row = <DynamicTableRow> {selected: false}; + const row = <DynamicTableRow> {selected: false}; widget.onRowClicked(row); expect(row.selected).toBeTruthy(); @@ -115,7 +115,7 @@ describe('DynamicTableWidgetComponent', () => { }); it('should require table to select clicked row', () => { - let row = <DynamicTableRow> {selected: false}; + const row = <DynamicTableRow> {selected: false}; widget.content = null; widget.onRowClicked(row); @@ -123,7 +123,7 @@ describe('DynamicTableWidgetComponent', () => { }); it('should reset selected row', () => { - let row = <DynamicTableRow> {selected: false}; + const row = <DynamicTableRow> {selected: false}; widget.content.rows.push(row); widget.content.selectedRow = row; expect(widget.content.selectedRow).toBe(row); @@ -135,7 +135,7 @@ describe('DynamicTableWidgetComponent', () => { }); it('should check selection', () => { - let row = <DynamicTableRow> {selected: false}; + const row = <DynamicTableRow> {selected: false}; widget.content.rows.push(row); widget.content.selectedRow = row; expect(widget.hasSelection()).toBeTruthy(); @@ -153,8 +153,8 @@ describe('DynamicTableWidgetComponent', () => { }); it('should move selection up', () => { - let row1 = <DynamicTableRow> {}; - let row2 = <DynamicTableRow> {}; + const row1 = <DynamicTableRow> {}; + const row2 = <DynamicTableRow> {}; widget.content.rows.push(...[row1, row2]); widget.content.selectedRow = row2; @@ -168,8 +168,8 @@ describe('DynamicTableWidgetComponent', () => { }); it('should move selection down', () => { - let row1 = <DynamicTableRow> {}; - let row2 = <DynamicTableRow> {}; + const row1 = <DynamicTableRow> {}; + const row2 = <DynamicTableRow> {}; widget.content.rows.push(...[row1, row2]); widget.content.selectedRow = row1; @@ -183,7 +183,7 @@ describe('DynamicTableWidgetComponent', () => { }); it('should delete selected row', () => { - let row = <DynamicTableRow> {}; + const row = <DynamicTableRow> {}; widget.content.rows.push(row); widget.content.selectedRow = row; widget.deleteSelection(); @@ -213,7 +213,7 @@ describe('DynamicTableWidgetComponent', () => { expect(widget.editMode).toBeFalsy(); expect(widget.editRow).toBeFalsy(); - let row = <DynamicTableRow> {value: true}; + const row = <DynamicTableRow> {value: true}; widget.content.selectedRow = row; expect(widget.editSelection()).toBeTruthy(); @@ -223,8 +223,8 @@ describe('DynamicTableWidgetComponent', () => { }); it('should copy row', () => { - let row = <DynamicTableRow> {value: {opt: {key: '1', value: 1}}}; - let copy = widget.copyRow(row); + const row = <DynamicTableRow> {value: {opt: {key: '1', value: 1}}}; + const copy = widget.copyRow(row); expect(copy.value).toEqual(row.value); }); @@ -235,14 +235,14 @@ describe('DynamicTableWidgetComponent', () => { it('should retrieve cell value', () => { const value = '<value>'; - let row = <DynamicTableRow> {value: {key: value}}; - let column = <DynamicTableColumn> {id: 'key'}; + const row = <DynamicTableRow> {value: {key: value}}; + const column = <DynamicTableColumn> {id: 'key'}; expect(widget.getCellValue(row, column)).toBe(value); }); it('should save changes and add new row', () => { - let row = <DynamicTableRow> {isNew: true, value: {key: 'value'}}; + const row = <DynamicTableRow> {isNew: true, value: {key: 'value'}}; widget.editMode = true; widget.editRow = row; @@ -255,7 +255,7 @@ describe('DynamicTableWidgetComponent', () => { }); it('should save changes and update row', () => { - let row = <DynamicTableRow> {isNew: false, value: {key: 'value'}}; + const row = <DynamicTableRow> {isNew: false, value: {key: 'value'}}; widget.editMode = true; widget.editRow = row; widget.content.selectedRow = row; @@ -291,8 +291,8 @@ describe('DynamicTableWidgetComponent', () => { }); it('should take validation state from underlying field', () => { - let form = new FormModel(); - let field = new FormFieldModel(form, { + const form = new FormModel(); + const field = new FormFieldModel(form, { type: FormFieldTypes.DYNAMIC_TABLE, required: true, value: null @@ -312,16 +312,16 @@ describe('DynamicTableWidgetComponent', () => { }); it('should prepend default currency for amount columns', () => { - let row = <DynamicTableRow> {value: {key: '100'}}; - let column = <DynamicTableColumn> {id: 'key', type: 'Amount'}; - let actual = widget.getCellValue(row, column); + const row = <DynamicTableRow> {value: {key: '100'}}; + const column = <DynamicTableColumn> {id: 'key', type: 'Amount'}; + const actual = widget.getCellValue(row, column); expect(actual).toBe('$ 100'); }); it('should prepend custom currency for amount columns', () => { - let row = <DynamicTableRow> {value: {key: '100'}}; - let column = <DynamicTableColumn> {id: 'key', type: 'Amount', amountCurrency: 'GBP'}; - let actual = widget.getCellValue(row, column); + const row = <DynamicTableRow> {value: {key: '100'}}; + const column = <DynamicTableColumn> {id: 'key', type: 'Amount', amountCurrency: 'GBP'}; + const actual = widget.getCellValue(row, column); expect(actual).toBe('GBP 100'); }); @@ -340,25 +340,25 @@ describe('DynamicTableWidgetComponent', () => { }); it('should select a row when press space bar', async(() => { - let rowElement = element.querySelector('#fake-dynamic-table-row-0'); + const rowElement = element.querySelector('#fake-dynamic-table-row-0'); expect(element.querySelector('#dynamic-table-fake-dynamic-table')).not.toBeNull(); expect(rowElement).not.toBeNull(); expect(rowElement.className).not.toContain('adf-dynamic-table-widget__row-selected'); - let event: any = new Event('keyup'); + const event: any = new Event('keyup'); event.keyCode = 32; rowElement.dispatchEvent(event); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectedRow = element.querySelector('#fake-dynamic-table-row-0'); + const selectedRow = element.querySelector('#fake-dynamic-table-row-0'); expect(selectedRow.className).toContain('adf-dynamic-table-widget__row-selected'); }); })); it('should focus on add button when a new row is saved', async(() => { - let addNewRowButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#fake-dynamic-table-add-row'); + const addNewRowButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#fake-dynamic-table-add-row'); expect(element.querySelector('#dynamic-table-fake-dynamic-table')).not.toBeNull(); expect(addNewRowButton).not.toBeNull(); diff --git a/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.ts b/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.ts index 4048757e22..91476637c2 100644 --- a/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.ts +++ b/lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.ts @@ -62,7 +62,7 @@ export class DynamicTableWidgetComponent extends WidgetComponent implements OnIn forceFocusOnAddButton() { if (this.content) { this.cd.detectChanges(); - let buttonAddRow = <HTMLButtonElement> this.elementRef.nativeElement.querySelector('#' + this.content.id + '-add-row'); + const buttonAddRow = <HTMLButtonElement> this.elementRef.nativeElement.querySelector('#' + this.content.id + '-add-row'); if (this.isDynamicTableReady(buttonAddRow)) { buttonAddRow.focus(); } @@ -151,7 +151,7 @@ export class DynamicTableWidgetComponent extends WidgetComponent implements OnIn getCellValue(row: DynamicTableRow, column: DynamicTableColumn): any { if (this.content) { - let cellValue = this.content.getCellValue(row, column); + const cellValue = this.content.getCellValue(row, column); if (column.type === 'Amount') { return (column.amountCurrency || '$') + ' ' + (cellValue || 0); } @@ -163,7 +163,7 @@ export class DynamicTableWidgetComponent extends WidgetComponent implements OnIn onSaveChanges() { if (this.content) { if (this.editRow.isNew) { - let row = this.copyRow(this.editRow); + const row = this.copyRow(this.editRow); this.content.selectedRow = null; this.content.addRow(row); this.editRow.isNew = false; diff --git a/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts index 91c12c8573..94281ab8ef 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts @@ -29,9 +29,9 @@ describe('BooleanEditorComponent', () => { }); it('should update row value on change', () => { - let row = <DynamicTableRow> { value: {} }; - let column = <DynamicTableColumn> { id: 'key' }; - let event = { checked: true } ; + const row = <DynamicTableRow> { value: {} }; + const column = <DynamicTableColumn> { id: 'key' }; + const event = { checked: true } ; component.onValueChanged(row, column, event); expect(row.value[column.id]).toBeTruthy(); diff --git a/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts b/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts index f100b1a4b6..4203fabd5d 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts @@ -39,7 +39,7 @@ export class BooleanEditorComponent { column: DynamicTableColumn; onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: any) { - let value: boolean = (<HTMLInputElement> event).checked; + const value: boolean = (<HTMLInputElement> event).checked; row.value[column.id] = value; } diff --git a/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.spec.ts index 41675ed494..7c4b57a5cc 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.spec.ts @@ -61,7 +61,7 @@ describe('DateEditorComponent', () => { it('should update fow value on change', () => { component.ngOnInit(); - let newDate = moment('14-03-1879', 'DD-MM-YYYY'); + const newDate = moment('14-03-1879', 'DD-MM-YYYY'); component.onDateChanged(newDate); expect(row.value[column.id]).toBe('1879-03-14T00:00:00.000Z'); }); @@ -72,7 +72,7 @@ describe('DateEditorComponent', () => { component.ngOnInit(); component.onDateChanged(input); - let actual = row.value[column.id]; + const actual = row.value[column.id]; expect(actual).toBe('2016-03-14T00:00:00.000Z'); }); diff --git a/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.ts b/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.ts index 945ce685fe..23f29dc4c6 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/date/date.editor.ts @@ -63,7 +63,7 @@ export class DateEditorComponent implements OnInit { this.dateAdapter.setLocale(locale); }); - let momentDateAdapter = <MomentDateAdapter> this.dateAdapter; + const momentDateAdapter = <MomentDateAdapter> this.dateAdapter; momentDateAdapter.overrideDisplayFormat = this.DATE_FORMAT; this.value = moment(this.table.getCellValue(this.row, this.column), 'YYYY-MM-DD'); @@ -71,7 +71,7 @@ export class DateEditorComponent implements OnInit { onDateChanged(newDateValue) { if (newDateValue && newDateValue.value) { - let momentDate = moment(newDateValue.value, this.DATE_FORMAT, true); + const momentDate = moment(newDateValue.value, this.DATE_FORMAT, true); if (!momentDate.isValid()) { this.row.value[this.column.id] = ''; diff --git a/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.spec.ts index f496a36457..e1a0dfa3e0 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.spec.ts @@ -61,7 +61,7 @@ describe('DateTimeEditorComponent', () => { it('should update fow value on change', () => { component.ngOnInit(); - let newDate = moment('22-6-2018 04:20 AM', 'D-M-YYYY hh:mm A'); + const newDate = moment('22-6-2018 04:20 AM', 'D-M-YYYY hh:mm A'); component.onDateChanged(newDate); expect(moment(row.value[column.id]).isSame(newDate)).toBeTruthy(); }); @@ -72,7 +72,7 @@ describe('DateTimeEditorComponent', () => { component.ngOnInit(); component.onDateChanged(input); - let actual = row.value[column.id]; + const actual = row.value[column.id]; expect(actual).toBe('22-6-2018 04:20 AM'); }); diff --git a/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.ts b/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.ts index 5bf214c34c..4dbc70740f 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/datetime/datetime.editor.ts @@ -68,7 +68,7 @@ export class DateTimeEditorComponent implements OnInit { this.dateAdapter.setLocale(locale); }); - let momentDateAdapter = <MomentDateAdapter> this.dateAdapter; + const momentDateAdapter = <MomentDateAdapter> this.dateAdapter; momentDateAdapter.overrideDisplayFormat = this.DATE_FORMAT; this.value = moment(this.table.getCellValue(this.row, this.column), this.DATE_FORMAT); diff --git a/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts index 48485332d2..8c54da4e9a 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts @@ -92,7 +92,7 @@ describe('DropdownEditorComponent', () => { column.optionType = 'rest'; row.value[column.id] = 'twelve'; - let restResults = [ + const restResults = [ <DynamicTableColumnOption> {id: '11', name: 'eleven'}, <DynamicTableColumnOption> {id: '12', name: 'twelve'} ]; @@ -155,8 +155,8 @@ describe('DropdownEditorComponent', () => { it('should handle REST error getting option with processDefinitionId', () => { column.optionType = 'rest'; - let procForm = new FormModel({processDefinitionId: '<process-definition-id>'}); - let procTable = new DynamicTableModel(new FormFieldModel(procForm, {id: '<field-id>'}), formService); + const procForm = new FormModel({processDefinitionId: '<process-definition-id>'}); + const procTable = new DynamicTableModel(new FormFieldModel(procForm, {id: '<field-id>'}), formService); component.table = procTable; const error = 'error'; @@ -170,7 +170,7 @@ describe('DropdownEditorComponent', () => { }); it('should update row on value change', () => { - let event = {value: 'two'}; + const event = {value: 'two'}; component.onValueChanged(row, column, event); expect(row.value[column.id]).toBe(column.options[1]); }); @@ -180,7 +180,7 @@ describe('DropdownEditorComponent', () => { let fixture: ComponentFixture<DropdownEditorComponent>; let element: HTMLElement; let stubFormService; - let fakeOptionList: DynamicTableColumnOption[] = [{ + const fakeOptionList: DynamicTableColumnOption[] = [{ id: 'opt_1', name: 'option_1' }, { diff --git a/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts b/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts index cf53007c08..41deea0e65 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts @@ -49,7 +49,7 @@ export class DropdownEditorComponent implements OnInit { } ngOnInit() { - let field = this.table.field; + const field = this.table.field; if (field) { if (this.column.optionType === 'rest') { if (this.table.form && this.table.form.taskId) { diff --git a/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.spec.ts index 9ac9bcbb11..1b02fdbe5a 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.spec.ts @@ -28,11 +28,11 @@ describe('TextEditorComponent', () => { }); it('should update row value on change', () => { - let row = <DynamicTableRow> { value: {} }; - let column = <DynamicTableColumn> { id: 'key' }; + const row = <DynamicTableRow> { value: {} }; + const column = <DynamicTableColumn> { id: 'key' }; const value = '<value>'; - let event = { target: { value } }; + const event = { target: { value } }; editor.onValueChanged(row, column, event); expect(row.value[column.id]).toBe(value); diff --git a/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.ts b/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.ts index 6afcf58988..15bebcc3d4 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/text/text.editor.ts @@ -45,7 +45,7 @@ export class TextEditorComponent implements OnInit { } onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: any) { - let value: any = (<HTMLInputElement> event.target).value; + const value: any = (<HTMLInputElement> event.target).value; row.value[column.id] = value; } diff --git a/lib/core/form/components/widgets/dynamic-table/number-cell-validator.model.ts b/lib/core/form/components/widgets/dynamic-table/number-cell-validator.model.ts index b9432d67ed..cfe2a49a19 100644 --- a/lib/core/form/components/widgets/dynamic-table/number-cell-validator.model.ts +++ b/lib/core/form/components/widgets/dynamic-table/number-cell-validator.model.ts @@ -44,7 +44,7 @@ export class NumberCellValidator implements CellValidator { validate(row: DynamicTableRow, column: DynamicTableColumn, summary?: DynamicRowValidationSummary): boolean { if (this.isSupported(column)) { - let value = row.value[column.id]; + const value = row.value[column.id]; if (value === null || value === undefined || value === '' || diff --git a/lib/core/form/components/widgets/dynamic-table/required-cell-validator.model.ts b/lib/core/form/components/widgets/dynamic-table/required-cell-validator.model.ts index 1aafcb4759..bf7de85d8b 100644 --- a/lib/core/form/components/widgets/dynamic-table/required-cell-validator.model.ts +++ b/lib/core/form/components/widgets/dynamic-table/required-cell-validator.model.ts @@ -38,7 +38,7 @@ export class RequiredCellValidator implements CellValidator { validate(row: DynamicTableRow, column: DynamicTableColumn, summary?: DynamicRowValidationSummary): boolean { if (this.isSupported(column)) { - let value = row.value[column.id]; + const value = row.value[column.id]; if (column.required) { if (value === null || value === undefined || value === '') { if (summary) { diff --git a/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts b/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts index 8ba64b7bc1..2900bd9e4b 100644 --- a/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts +++ b/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts @@ -36,7 +36,7 @@ describe('FunctionalGroupWidgetComponent', () => { }); it('should setup text from underlying field on init', () => { - let group = new GroupModel({ name: 'group-1'}); + const group = new GroupModel({ name: 'group-1'}); widget.field.value = group; spyOn(formService, 'getWorkflowGroups').and.returnValue( @@ -75,13 +75,13 @@ describe('FunctionalGroupWidgetComponent', () => { }); it('should prevent default behaviour on option item click', () => { - let event = jasmine.createSpyObj('event', ['preventDefault']); + const event = jasmine.createSpyObj('event', ['preventDefault']); widget.onItemClick(null, event); expect(event.preventDefault).toHaveBeenCalled(); }); it('should update values on item click', () => { - let item = new GroupModel({ name: 'group-1' }); + const item = new GroupModel({ name: 'group-1' }); widget.onItemClick(item, null); expect(widget.field.value).toBe(item); @@ -95,7 +95,7 @@ describe('FunctionalGroupWidgetComponent', () => { }); it('should flush selected value', () => { - let groups: GroupModel[] = [ + const groups: GroupModel[] = [ new GroupModel({ id: '1', name: 'group 1' }), new GroupModel({ id: '2', name: 'group 2' }) ]; @@ -109,7 +109,7 @@ describe('FunctionalGroupWidgetComponent', () => { }); it('should be case insensitive when flushing value', () => { - let groups: GroupModel[] = [ + const groups: GroupModel[] = [ new GroupModel({ id: '1', name: 'group 1' }), new GroupModel({ id: '2', name: 'gRoUp 2' }) ]; @@ -123,7 +123,7 @@ describe('FunctionalGroupWidgetComponent', () => { }); it('should fetch groups and show popup on key up', () => { - let groups: GroupModel[] = [ + const groups: GroupModel[] = [ new GroupModel(), new GroupModel() ]; @@ -134,7 +134,7 @@ describe('FunctionalGroupWidgetComponent', () => { }) ); - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); widget.value = 'group'; widget.onKeyUp(keyboardEvent); @@ -143,7 +143,7 @@ describe('FunctionalGroupWidgetComponent', () => { }); it('should fetch groups with a group filter', () => { - let groups: GroupModel[] = [ + const groups: GroupModel[] = [ new GroupModel(), new GroupModel() ]; @@ -154,7 +154,7 @@ describe('FunctionalGroupWidgetComponent', () => { }) ); - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); widget.groupId = 'parentGroup'; widget.value = 'group'; widget.onKeyUp(keyboardEvent); @@ -171,7 +171,7 @@ describe('FunctionalGroupWidgetComponent', () => { }) ); - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); widget.value = 'group'; widget.onKeyUp(keyboardEvent); @@ -182,7 +182,7 @@ describe('FunctionalGroupWidgetComponent', () => { it('should not fetch groups when value is missing', () => { spyOn(formService, 'getWorkflowGroups').and.stub(); - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); widget.value = null; widget.onKeyUp(keyboardEvent); @@ -192,7 +192,7 @@ describe('FunctionalGroupWidgetComponent', () => { it('should not fetch groups when value violates constraints', () => { spyOn(formService, 'getWorkflowGroups').and.stub(); - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); widget.minTermLength = 4; widget.value = '123'; widget.onKeyUp(keyboardEvent); diff --git a/lib/core/form/components/widgets/functional-group/functional-group.widget.ts b/lib/core/form/components/widgets/functional-group/functional-group.widget.ts index 7c824aa63c..a0eb391c8c 100644 --- a/lib/core/form/components/widgets/functional-group/functional-group.widget.ts +++ b/lib/core/form/components/widgets/functional-group/functional-group.widget.ts @@ -45,14 +45,14 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O ngOnInit() { if (this.field) { - let group = this.field.value; + const group = this.field.value; if (group) { this.value = group.name; } - let params = this.field.params; + const params = this.field.params; if (params && params['restrictWithGroup']) { - let restrictWithGroup = <GroupModel> params['restrictWithGroup']; + const restrictWithGroup = <GroupModel> params['restrictWithGroup']; this.groupId = restrictWithGroup.id; } @@ -78,7 +78,7 @@ export class FunctionalGroupWidgetComponent extends WidgetComponent implements O } flushValue() { - let option = this.groups.find((item) => item.name.toLocaleLowerCase() === this.value.toLocaleLowerCase()); + const option = this.groups.find((item) => item.name.toLocaleLowerCase() === this.value.toLocaleLowerCase()); if (option) { this.field.value = option; diff --git a/lib/core/form/components/widgets/people/people.widget.spec.ts b/lib/core/form/components/widgets/people/people.widget.spec.ts index b3f32c1629..44ed1b36a7 100644 --- a/lib/core/form/components/widgets/people/people.widget.spec.ts +++ b/lib/core/form/components/widgets/people/people.widget.spec.ts @@ -63,7 +63,7 @@ describe('PeopleWidgetComponent', () => { }); it('should return full name for a given model', () => { - let model = new UserProcessModel({ + const model = new UserProcessModel({ firstName: 'John', lastName: 'Doe' }); @@ -71,12 +71,12 @@ describe('PeopleWidgetComponent', () => { }); it('should skip first name for display name', () => { - let model = new UserProcessModel({ firstName: null, lastName: 'Doe' }); + const model = new UserProcessModel({ firstName: null, lastName: 'Doe' }); expect(widget.getDisplayName(model)).toBe('Doe'); }); it('should skip last name for display name', () => { - let model = new UserProcessModel({ firstName: 'John', lastName: null }); + const model = new UserProcessModel({ firstName: 'John', lastName: null }); expect(widget.getDisplayName(model)).toBe('John'); }); @@ -129,7 +129,7 @@ describe('PeopleWidgetComponent', () => { widget.field.value = null; widget.ngOnInit(); fixture.detectChanges(); - let input = widget.input; + const input = widget.input; expect(input.nativeElement.value).toBe(''); expect(widget.groupId).toBeUndefined(); }); @@ -161,7 +161,7 @@ describe('PeopleWidgetComponent', () => { describe('when template is ready', () => { - let fakeUserResult = [ + const fakeUserResult = [ { id: 1001, firstName: 'Test01', lastName: 'Test01', email: 'test' }, { id: 1002, firstName: 'Test02', lastName: 'Test02', email: 'test2' }]; @@ -190,7 +190,7 @@ describe('PeopleWidgetComponent', () => { }); it('should show an error message if the user is invalid', async(() => { - let peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); peopleHTMLElement.focus(); peopleHTMLElement.value = 'K'; peopleHTMLElement.dispatchEvent(new Event('keyup')); @@ -203,7 +203,7 @@ describe('PeopleWidgetComponent', () => { })); it('should show the people if the typed result match', async(() => { - let peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); peopleHTMLElement.focus(); peopleHTMLElement.value = 'T'; peopleHTMLElement.dispatchEvent(new Event('keyup')); @@ -217,7 +217,7 @@ describe('PeopleWidgetComponent', () => { })); it('should hide result list if input is empty', () => { - let peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); peopleHTMLElement.focus(); peopleHTMLElement.value = ''; peopleHTMLElement.dispatchEvent(new Event('keyup')); @@ -230,7 +230,7 @@ describe('PeopleWidgetComponent', () => { }); it('should display two options if we tap one letter', async(() => { - let peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); peopleHTMLElement.focus(); peopleHTMLElement.value = 'T'; peopleHTMLElement.dispatchEvent(new Event('keyup')); @@ -244,8 +244,8 @@ describe('PeopleWidgetComponent', () => { })); it('should emit peopleSelected if option is valid', async() => { - let selectEmitSpy = spyOn(widget.peopleSelected, 'emit'); - let peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const selectEmitSpy = spyOn(widget.peopleSelected, 'emit'); + const peopleHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); peopleHTMLElement.focus(); peopleHTMLElement.value = 'Test01 Test01'; peopleHTMLElement.dispatchEvent(new Event('keyup')); diff --git a/lib/core/form/components/widgets/people/people.widget.ts b/lib/core/form/components/widgets/people/people.widget.ts index 5a247de1d7..6fe42de6ae 100644 --- a/lib/core/form/components/widgets/people/people.widget.ts +++ b/lib/core/form/components/widgets/people/people.widget.ts @@ -61,7 +61,7 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit { }), distinctUntilChanged(), switchMap((searchTerm) => { - let value = searchTerm.email ? this.getDisplayName(searchTerm) : searchTerm; + const value = searchTerm.email ? this.getDisplayName(searchTerm) : searchTerm; return this.formService.getWorkflowUsers(value, this.groupId) .pipe( catchError((err) => { @@ -71,7 +71,7 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit { ); }), map((list: UserProcessModel[]) => { - let value = this.searchTerm.value.email ? this.getDisplayName(this.searchTerm.value) : this.searchTerm.value; + const value = this.searchTerm.value.email ? this.getDisplayName(this.searchTerm.value) : this.searchTerm.value; this.checkUserAndValidateForm(list, value); return list; }) @@ -90,9 +90,9 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit { if (this.field.readOnly) { this.searchTerm.disable(); } - let params = this.field.params; + const params = this.field.params; if (params && params.restrictWithGroup) { - let restrictWithGroup = <GroupModel> params.restrictWithGroup; + const restrictWithGroup = <GroupModel> params.restrictWithGroup; this.groupId = restrictWithGroup.id; } } @@ -125,7 +125,7 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit { getDisplayName(model: UserProcessModel) { if (model) { - let displayName = `${model.firstName || ''} ${model.lastName || ''}`; + const displayName = `${model.firstName || ''} ${model.lastName || ''}`; return displayName.trim(); } return ''; diff --git a/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts b/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts index 2c55cb5785..02315a9c1d 100644 --- a/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts +++ b/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts @@ -50,7 +50,7 @@ describe('RadioButtonsWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -71,7 +71,7 @@ describe('RadioButtonsWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -79,7 +79,7 @@ describe('RadioButtonsWidgetComponent', () => { id: fieldId, restUrl: '<url>' }); - let field = widget.field; + const field = widget.field; spyOn(field, 'updateForm').and.stub(); spyOn(formService, 'getRestFieldValues').and.returnValue(new Observable((observer) => { @@ -94,7 +94,7 @@ describe('RadioButtonsWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -107,7 +107,7 @@ describe('RadioButtonsWidgetComponent', () => { observer.complete(); })); - let field = widget.field; + const field = widget.field; widget.field = null; widget.ngOnInit(); expect(formService.getRestFieldValues).not.toHaveBeenCalled(); @@ -134,7 +134,7 @@ describe('RadioButtonsWidgetComponent', () => { let fixture: ComponentFixture<RadioButtonsWidgetComponent>; let element: HTMLElement; let stubFormService: FormService; - let restOption: FormFieldOption[] = [{ id: 'opt-1', name: 'opt-name-1' }, { + const restOption: FormFieldOption[] = [{ id: 'opt-1', name: 'opt-name-1' }, { id: 'opt-2', name: 'opt-name-2' }]; @@ -161,7 +161,7 @@ describe('RadioButtonsWidgetComponent', () => { restUrl: 'rest-url' }); radioButtonWidget.field.isVisible = true; - let fakeContainer = new ContainerModel(radioButtonWidget.field); + const fakeContainer = new ContainerModel(radioButtonWidget.field); radioButtonWidget.field.form.fields.push(fakeContainer); fixture.detectChanges(); })); @@ -175,7 +175,7 @@ describe('RadioButtonsWidgetComponent', () => { })); it('should trigger field changed event on click', async(() => { - let option: HTMLElement = <HTMLElement> element.querySelector('#radio-id-opt-1-input'); + const option: HTMLElement = <HTMLElement> element.querySelector('#radio-id-opt-1-input'); expect(element.querySelector('#radio-id')).not.toBeNull(); expect(option).not.toBeNull(); option.click(); diff --git a/lib/core/form/components/widgets/tabs/tabs.widget.spec.ts b/lib/core/form/components/widgets/tabs/tabs.widget.spec.ts index 33b68e8a30..e43adde4ef 100644 --- a/lib/core/form/components/widgets/tabs/tabs.widget.spec.ts +++ b/lib/core/form/components/widgets/tabs/tabs.widget.spec.ts @@ -56,7 +56,7 @@ describe('TabsWidgetComponent', () => { }); it('should emit tab changed event', (done) => { - let field = new FormFieldModel(null); + const field = new FormFieldModel(null); widget.formTabChanged.subscribe((tab) => { expect(tab).toBe(field); done(); @@ -65,7 +65,7 @@ describe('TabsWidgetComponent', () => { }); it('should remove invisible tabs', () => { - let fakeTab = new TabModel(null, { id: 'fake-tab-id', title: 'fake-tab-title' }); + const fakeTab = new TabModel(null, { id: 'fake-tab-id', title: 'fake-tab-title' }); fakeTab.isVisible = false; widget.tabs.push(fakeTab); widget.ngAfterContentChecked(); @@ -74,7 +74,7 @@ describe('TabsWidgetComponent', () => { }); it('should leave visible tabs', () => { - let fakeTab = new TabModel(null, { id: 'fake-tab-id', title: 'fake-tab-title' }); + const fakeTab = new TabModel(null, { id: 'fake-tab-id', title: 'fake-tab-title' }); fakeTab.isVisible = true; widget.tabs.push(fakeTab); widget.ngAfterContentChecked(); diff --git a/lib/core/form/components/widgets/text/text-mask.component.ts b/lib/core/form/components/widgets/text/text-mask.component.ts index bc65345dae..41cf5febc6 100644 --- a/lib/core/form/components/widgets/text/text-mask.component.ts +++ b/lib/core/form/components/widgets/text/text-mask.component.ts @@ -101,8 +101,8 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor { private maskValue(actualValue, startCaret, maskToApply, isMaskReversed, keyCode) { if (this.byPassKeys.indexOf(keyCode) === -1) { - let value = this.getMasked(false, actualValue, maskToApply, isMaskReversed); - let calculatedCaret = this.calculateCaretPosition(startCaret, actualValue, keyCode); + const value = this.getMasked(false, actualValue, maskToApply, isMaskReversed); + const calculatedCaret = this.calculateCaretPosition(startCaret, actualValue, keyCode); this.render.setAttribute(this.el.nativeElement, 'value', value); this.el.nativeElement.value = value; this.setValue(value); @@ -117,9 +117,9 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor { } calculateCaretPosition(caretPosition, newValue, keyCode) { - let newValueLength = newValue.length; - let oldValue = this.getValue() || ''; - let oldValueLength = oldValue.length; + const newValueLength = newValue.length; + const oldValue = this.getValue() || ''; + const oldValueLength = oldValue.length; if (keyCode === 8 && oldValue !== newValue) { caretPosition = caretPosition - (newValue.slice(0, caretPosition).length - oldValue.slice(0, caretPosition).length); @@ -134,18 +134,18 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor { } getMasked(skipMaskChars, val, mask, isReversed = false) { - let buf = [], - value = val, - maskIndex = 0, - maskLen = mask.length, - valueIndex = 0, - valueLength = value.length, - offset = 1, - addMethod = 'push', - resetPos = -1, - lastMaskChar, - lastUntranslatedMaskChar, - check; + const buf = []; + const value = val; + let maskIndex = 0; + const maskLen = mask.length; + let valueIndex = 0; + const valueLength = value.length; + let offset = 1; + let addMethod = 'push'; + let resetPos = -1; + let lastMaskChar; + let lastUntranslatedMaskChar; + let check; if (isReversed) { addMethod = 'unshift'; @@ -158,7 +158,7 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor { } check = this.isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength); while (check) { - let maskDigit = mask.charAt(maskIndex), + const maskDigit = mask.charAt(maskIndex), valDigit = value.charAt(valueIndex), translation = this.translationMask[maskDigit]; @@ -203,7 +203,7 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor { check = this.isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength); } - let lastMaskCharDigit = mask.charAt(lastMaskChar); + const lastMaskCharDigit = mask.charAt(lastMaskChar); if (maskLen === valueLength + 1 && !this.translationMask[lastMaskCharDigit]) { buf.push(lastMaskCharDigit); } diff --git a/lib/core/form/components/widgets/text/text.widget.spec.ts b/lib/core/form/components/widgets/text/text.widget.spec.ts index 0c58ad72a9..4f3f2cc38f 100644 --- a/lib/core/form/components/widgets/text/text.widget.spec.ts +++ b/lib/core/form/components/widgets/text/text.widget.spec.ts @@ -151,7 +151,7 @@ describe('TextWidgetComponent', () => { inputElement.value = 'F'; widget.field.value = 'F'; - let event: any = new Event('keyup'); + const event: any = new Event('keyup'); event.keyCode = '70'; inputElement.dispatchEvent(event); fixture.detectChanges(); @@ -183,13 +183,13 @@ describe('TextWidgetComponent', () => { inputElement.value = '1'; widget.field.value = '1'; - let event: any = new Event('keyup'); + const event: any = new Event('keyup'); event.keyCode = '49'; inputElement.dispatchEvent(event); fixture.whenStable().then(() => { fixture.detectChanges(); - let textEle: HTMLInputElement = <HTMLInputElement> element.querySelector('#text-id'); + const textEle: HTMLInputElement = <HTMLInputElement> element.querySelector('#text-id'); expect(textEle.value).toBe('1'); }); })); @@ -199,13 +199,13 @@ describe('TextWidgetComponent', () => { inputElement.value = '12345678'; widget.field.value = '12345678'; - let event: any = new Event('keyup'); + const event: any = new Event('keyup'); event.keyCode = '49'; inputElement.dispatchEvent(event); fixture.whenStable().then(() => { fixture.detectChanges(); - let textEle: HTMLInputElement = <HTMLInputElement> element.querySelector('#text-id'); + const textEle: HTMLInputElement = <HTMLInputElement> element.querySelector('#text-id'); expect(textEle.value).toBe('12-345,67%'); }); })); @@ -239,13 +239,13 @@ describe('TextWidgetComponent', () => { inputElement.value = '1234'; widget.field.value = '1234'; - let event: any = new Event('keyup'); + const event: any = new Event('keyup'); event.keyCode = '49'; inputElement.dispatchEvent(event); fixture.whenStable().then(() => { fixture.detectChanges(); - let textEle: HTMLInputElement = <HTMLInputElement> element.querySelector('#text-id'); + const textEle: HTMLInputElement = <HTMLInputElement> element.querySelector('#text-id'); expect(textEle.value).toBe('12,34%'); }); })); diff --git a/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts b/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts index 07967f90d6..e577445192 100644 --- a/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts +++ b/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts @@ -58,7 +58,7 @@ describe('TypeaheadWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -79,7 +79,7 @@ describe('TypeaheadWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -96,7 +96,7 @@ describe('TypeaheadWidgetComponent', () => { const taskId = '<form-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ taskId: taskId }); @@ -118,7 +118,7 @@ describe('TypeaheadWidgetComponent', () => { const processDefinitionId = '<process-id>'; const fieldId = '<field-id>'; - let form = new FormModel({ + const form = new FormModel({ processDefinitionId: processDefinitionId }); @@ -170,7 +170,7 @@ describe('TypeaheadWidgetComponent', () => { }); it('should setup field options on load', () => { - let options: FormFieldOption[] = [ + const options: FormFieldOption[] = [ { id: '1', name: 'One' }, { id: '2', name: 'Two' } ]; @@ -197,27 +197,27 @@ describe('TypeaheadWidgetComponent', () => { }); it('should get filtered options', () => { - let options: FormFieldOption[] = [ + const options: FormFieldOption[] = [ { id: '1', name: 'Item one' }, { id: '2', name: 'Item two' } ]; widget.field.options = options; widget.value = 'tw'; - let filtered = widget.getOptions(); + const filtered = widget.getOptions(); expect(filtered.length).toBe(1); expect(filtered[0]).toEqual(options[1]); }); it('should be case insensitive when filtering options', () => { - let options: FormFieldOption[] = [ + const options: FormFieldOption[] = [ { id: '1', name: 'Item one' }, { id: '2', name: 'iTEM TWo' } ]; widget.field.options = options; widget.value = 'tW'; - let filtered = widget.getOptions(); + const filtered = widget.getOptions(); expect(filtered.length).toBe(1); expect(filtered[0]).toEqual(options[1]); }); @@ -227,7 +227,7 @@ describe('TypeaheadWidgetComponent', () => { let fixture: ComponentFixture<TypeaheadWidgetComponent>; let element: HTMLElement; let stubFormService; - let fakeOptionList: FormFieldOption[] = [{ + const fakeOptionList: FormFieldOption[] = [{ id: '1', name: 'Fake Name 1 ' }, { @@ -259,7 +259,7 @@ describe('TypeaheadWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let readonlyInput: HTMLInputElement = <HTMLInputElement> element.querySelector('#typeahead-id'); + const readonlyInput: HTMLInputElement = <HTMLInputElement> element.querySelector('#typeahead-id'); expect(readonlyInput.disabled).toBeTruthy(); expect(readonlyInput).not.toBeNull(); expect(readonlyInput.value).toBe('FakeProcessValue'); @@ -294,8 +294,8 @@ describe('TypeaheadWidgetComponent', () => { })); it('should show typeahead options', async(() => { - let typeaheadElement = fixture.debugElement.query(By.css('#typeahead-id')); - let typeaheadHTMLElement: HTMLInputElement = <HTMLInputElement> typeaheadElement.nativeElement; + const typeaheadElement = fixture.debugElement.query(By.css('#typeahead-id')); + const typeaheadHTMLElement: HTMLInputElement = <HTMLInputElement> typeaheadElement.nativeElement; typeaheadHTMLElement.focus(); typeaheadWidgetComponent.value = 'F'; typeaheadHTMLElement.value = 'F'; @@ -311,8 +311,8 @@ describe('TypeaheadWidgetComponent', () => { })); it('should hide the option when the value is empty', async(() => { - let typeaheadElement = fixture.debugElement.query(By.css('#typeahead-id')); - let typeaheadHTMLElement: HTMLInputElement = <HTMLInputElement> typeaheadElement.nativeElement; + const typeaheadElement = fixture.debugElement.query(By.css('#typeahead-id')); + const typeaheadHTMLElement: HTMLInputElement = <HTMLInputElement> typeaheadElement.nativeElement; typeaheadHTMLElement.focus(); typeaheadWidgetComponent.value = 'F'; typeaheadHTMLElement.value = 'F'; @@ -339,7 +339,7 @@ describe('TypeaheadWidgetComponent', () => { typeaheadWidgetComponent.field.value = 'Fake Name'; typeaheadWidgetComponent.field.options = fakeOptionList; expect(element.querySelector('.adf-error-text')).toBeNull(); - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); typeaheadWidgetComponent.onKeyUp(keyboardEvent); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -372,7 +372,7 @@ describe('TypeaheadWidgetComponent', () => { })); it('should show typeahead options', async(() => { - let keyboardEvent = new KeyboardEvent('keypress'); + const keyboardEvent = new KeyboardEvent('keypress'); typeaheadWidgetComponent.value = 'F'; typeaheadWidgetComponent.onKeyUp(keyboardEvent); fixture.detectChanges(); diff --git a/lib/core/form/components/widgets/typeahead/typeahead.widget.ts b/lib/core/form/components/widgets/typeahead/typeahead.widget.ts index ce43ffcf90..e24153db3c 100644 --- a/lib/core/form/components/widgets/typeahead/typeahead.widget.ts +++ b/lib/core/form/components/widgets/typeahead/typeahead.widget.ts @@ -62,12 +62,12 @@ export class TypeaheadWidgetComponent extends WidgetComponent implements OnInit ) .subscribe( (formFieldOption: FormFieldOption[]) => { - let options = formFieldOption || []; + const options = formFieldOption || []; this.field.options = options; - let fieldValue = this.field.value; + const fieldValue = this.field.value; if (fieldValue) { - let toSelect = options.find((item) => item.id === fieldValue || item.name.toLocaleLowerCase() === fieldValue.toLocaleLowerCase()); + const toSelect = options.find((item) => item.id === fieldValue || item.name.toLocaleLowerCase() === fieldValue.toLocaleLowerCase()); if (toSelect) { this.value = toSelect.name; } @@ -87,12 +87,12 @@ export class TypeaheadWidgetComponent extends WidgetComponent implements OnInit ) .subscribe( (formFieldOption: FormFieldOption[]) => { - let options = formFieldOption || []; + const options = formFieldOption || []; this.field.options = options; - let fieldValue = this.field.value; + const fieldValue = this.field.value; if (fieldValue) { - let toSelect = options.find((item) => item.id === fieldValue); + const toSelect = options.find((item) => item.id === fieldValue); if (toSelect) { this.value = toSelect.name; } @@ -105,15 +105,15 @@ export class TypeaheadWidgetComponent extends WidgetComponent implements OnInit } getOptions(): FormFieldOption[] { - let val = this.value.trim().toLocaleLowerCase(); + const val = this.value.trim().toLocaleLowerCase(); return this.field.options.filter((item) => { - let name = item.name.toLocaleLowerCase(); + const name = item.name.toLocaleLowerCase(); return name.indexOf(val) > -1; }); } isValidOptionName(optionName: string): boolean { - let option = this.field.options.find((item) => item.name && item.name.toLocaleLowerCase() === optionName.toLocaleLowerCase()); + const option = this.field.options.find((item) => item.name && item.name.toLocaleLowerCase() === optionName.toLocaleLowerCase()); return option ? true : false; } diff --git a/lib/core/form/components/widgets/upload-folder/upload-folder.widget.ts b/lib/core/form/components/widgets/upload-folder/upload-folder.widget.ts index 8d09b01b26..9ef17cd27a 100644 --- a/lib/core/form/components/widgets/upload-folder/upload-folder.widget.ts +++ b/lib/core/form/components/widgets/upload-folder/upload-folder.widget.ts @@ -67,7 +67,7 @@ export class UploadFolderWidgetComponent extends WidgetComponent implements OnIn } onFileChanged(event: any) { - let files = event.target.files; + const files = event.target.files; let filesSaved = []; if (this.field.json.value) { @@ -112,7 +112,7 @@ export class UploadFolderWidgetComponent extends WidgetComponent implements OnIn } private removeElementFromList(file) { - let index = this.field.value.indexOf(file); + const index = this.field.value.indexOf(file); if (index !== -1) { this.field.value.splice(index, 1); diff --git a/lib/core/form/components/widgets/upload/upload.widget.spec.ts b/lib/core/form/components/widgets/upload/upload.widget.spec.ts index c3eeea498b..15e45da58b 100644 --- a/lib/core/form/components/widgets/upload/upload.widget.spec.ts +++ b/lib/core/form/components/widgets/upload/upload.widget.spec.ts @@ -29,7 +29,7 @@ import { setupTestBed } from '../../../../testing/setupTestBed'; import { CoreModule } from '../../../../core.module'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -let fakePngAnswer = { +const fakePngAnswer = { 'id': 1155, 'name': 'a_png_file.png', 'created': '2017-07-25T17:17:37.099Z', @@ -43,7 +43,7 @@ let fakePngAnswer = { 'thumbnailStatus': 'queued' }; -let fakeJpgAnswer = { +const fakeJpgAnswer = { 'id': 1156, 'name': 'a_jpg_file.jpg', 'created': '2017-07-25T17:17:37.118Z', @@ -77,8 +77,8 @@ describe('UploadWidgetComponent', () => { let contentService: ProcessContentService; - let filePngFake = new File(['fakePng'], 'file-fake.png', { type: 'image/png' }); - let filJpgFake = new File(['fakeJpg'], 'file-fake.jpg', { type: 'image/jpg' }); + const filePngFake = new File(['fakePng'], 'file-fake.png', { type: 'image/png' }); + const filJpgFake = new File(['fakeJpg'], 'file-fake.jpg', { type: 'image/jpg' }); setupTestBed({ imports: [ @@ -193,10 +193,10 @@ describe('UploadWidgetComponent', () => { uploadWidgetComponent.field.params.multiple = false; fixture.detectChanges(); - let inputDebugElement = fixture.debugElement.query(By.css('#upload-id')); + const inputDebugElement = fixture.debugElement.query(By.css('#upload-id')); inputDebugElement.triggerEventHandler('change', { target: { files: [filJpgFake] } }); - let filesList = fixture.debugElement.query(By.css('#file-1156')); + const filesList = fixture.debugElement.query(By.css('#file-1156')); expect(filesList).toBeDefined(); })); @@ -216,12 +216,12 @@ describe('UploadWidgetComponent', () => { spyOn(uploadWidgetComponent.field, 'updateForm'); fixture.detectChanges(); - let inputDebugElement = fixture.debugElement.query(By.css('#upload-id')); + const inputDebugElement = fixture.debugElement.query(By.css('#upload-id')); inputDebugElement.triggerEventHandler('change', { target: { files: [filePngFake, filJpgFake] } }); fixture.whenStable().then(() => { fixture.detectChanges(); - let deleteButton = <HTMLInputElement> element.querySelector('#file-1155-remove'); + const deleteButton = <HTMLInputElement> element.querySelector('#file-1155-remove'); deleteButton.click(); expect(uploadWidgetComponent.field.updateForm).toHaveBeenCalled(); @@ -242,7 +242,7 @@ describe('UploadWidgetComponent', () => { uploadWidgetComponent.field.params.multiple = true; fixture.detectChanges(); - let inputDebugElement = fixture.debugElement.query(By.css('#upload-id')); + const inputDebugElement = fixture.debugElement.query(By.css('#upload-id')); inputDebugElement.triggerEventHandler('change', { target: { files: [filePngFake, filJpgFake] } }); fixture.whenStable().then(() => { @@ -266,8 +266,8 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-1156'); - let pngElement = element.querySelector('#file-1155'); + const jpegElement = element.querySelector('#file-1156'); + const pngElement = element.querySelector('#file-1155'); expect(jpegElement).not.toBeNull(); expect(pngElement).not.toBeNull(); expect(jpegElement.textContent).toBe('a_jpg_file.jpg'); @@ -281,20 +281,20 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-10'); + const jpegElement = element.querySelector('#file-10'); expect(jpegElement).not.toBeNull(); expect(jpegElement.textContent).toBe(`±!@#$%^&*()_+{}:”|<>?§™£-=[];’\\,./.jpg`); }); })); it('should show correctly the file name when is formed with Arabic characters', async(() => { - let name = 'غ ظ ض ذ خ ث ت ش ر ق ص ف ع س ن م ل ك ي ط ح ز و ه د ج ب ا.jpg'; + const name = 'غ ظ ض ذ خ ث ت ش ر ق ص ف ع س ن م ل ك ي ط ح ز و ه د ج ب ا.jpg'; uploadWidgetComponent.field.value.push(fakeCreationFile(name, 11)); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-11'); + const jpegElement = element.querySelector('#file-11'); expect(jpegElement).not.toBeNull(); expect(jpegElement.textContent).toBe('غ ظ ض ذ خ ث ت ش ر ق ص ف ع س ن م ل ك ي ط ح ز و ه د ج ب ا.jpg'); }); @@ -308,7 +308,7 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-12'); + const jpegElement = element.querySelector('#file-12'); expect(jpegElement).not.toBeNull(); // cspell: disable-next expect(jpegElement.textContent).toBe('Àâæçéèêëïîôœùûüÿ.jpg'); @@ -323,7 +323,7 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-13'); + const jpegElement = element.querySelector('#file-13'); expect(jpegElement).not.toBeNull(); // cspell: disable-next expect(jpegElement.textContent).toBe('άέήίϊϊΐόύϋΰώθωερτψυιοπασδφγηςκλζχξωβνμ.jpg'); @@ -336,7 +336,7 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-14'); + const jpegElement = element.querySelector('#file-14'); expect(jpegElement).not.toBeNull(); expect(jpegElement.textContent).toBe('Ą Ć Ę Ł Ń Ó Ś Ź Żą ć ę ł ń ó ś ź ż.jpg'); }); @@ -348,7 +348,7 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-15'); + const jpegElement = element.querySelector('#file-15'); expect(jpegElement).not.toBeNull(); expect(jpegElement.textContent).toBe('á, é, í, ó, ú, ñ, Ñ, ü, Ü, ¿, ¡. Á, É, Í, Ó, Ú.jpg'); }); @@ -361,7 +361,7 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let jpegElement = element.querySelector('#file-16'); + const jpegElement = element.querySelector('#file-16'); expect(jpegElement).not.toBeNull(); // cspell: disable-next expect(jpegElement.textContent).toBe('Äåéö.jpg'); @@ -376,10 +376,10 @@ describe('UploadWidgetComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let buttonElement = <HTMLButtonElement> element.querySelector('#file-1156-remove'); + const buttonElement = <HTMLButtonElement> element.querySelector('#file-1156-remove'); buttonElement.click(); fixture.detectChanges(); - let jpegElement = element.querySelector('#file-1156'); + const jpegElement = element.querySelector('#file-1156'); expect(jpegElement).toBeNull(); expect(uploadWidgetComponent.field.value.length).toBe(1); }); @@ -402,7 +402,7 @@ describe('UploadWidgetComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let fileJpegIcon = debugElement.query(By.css('#file-1156-icon')); + const fileJpegIcon = debugElement.query(By.css('#file-1156-icon')); fileJpegIcon.nativeElement.dispatchEvent(new MouseEvent('click')); }); diff --git a/lib/core/form/components/widgets/upload/upload.widget.ts b/lib/core/form/components/widgets/upload/upload.widget.ts index d33246528c..3f18a94f15 100644 --- a/lib/core/form/components/widgets/upload/upload.widget.ts +++ b/lib/core/form/components/widgets/upload/upload.widget.ts @@ -67,7 +67,7 @@ export class UploadWidgetComponent extends WidgetComponent implements OnInit { } onFileChanged(event: any) { - let files = event.target.files; + const files = event.target.files; let filesSaved = []; if (this.field.json.value) { @@ -109,7 +109,7 @@ export class UploadWidgetComponent extends WidgetComponent implements OnInit { } private removeElementFromList(file) { - let index = this.field.value.indexOf(file); + const index = this.field.value.indexOf(file); if (index !== -1) { this.field.value.splice(index, 1); diff --git a/lib/core/form/components/widgets/widget.component.spec.ts b/lib/core/form/components/widgets/widget.component.spec.ts index 9bfb274e21..97ff34825f 100644 --- a/lib/core/form/components/widgets/widget.component.spec.ts +++ b/lib/core/form/components/widgets/widget.component.spec.ts @@ -64,8 +64,8 @@ describe('WidgetComponent', () => { }); it('should send an event after view init', (done) => { - let fakeForm = new FormModel(); - let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); + const fakeForm = new FormModel(); + const fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); widget.field = fakeField; widget.fieldChanged.subscribe((field) => { @@ -79,8 +79,8 @@ describe('WidgetComponent', () => { }); it('should send an event when a field is changed', (done) => { - let fakeForm = new FormModel(); - let fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); + const fakeForm = new FormModel(); + const fakeField = new FormFieldModel(fakeForm, {id: 'fakeField', value: 'fakeValue'}); widget.fieldChanged.subscribe((field) => { expect(field).not.toBe(null); expect(field.id).toBe('fakeField'); diff --git a/lib/core/form/models/form-definition.model.ts b/lib/core/form/models/form-definition.model.ts index 09f7f45ef2..3160458748 100644 --- a/lib/core/form/models/form-definition.model.ts +++ b/lib/core/form/models/form-definition.model.ts @@ -62,11 +62,11 @@ export class FormDefinitionModel extends FormSaveRepresentation { } private metadataToFields(metadata: any): any[] { - let fields = []; + const fields = []; if (metadata) { metadata.forEach(function(property) { if (property) { - let field = { + const field = { type: 'text', id: property.name, name: property.name, diff --git a/lib/core/form/services/activiti-alfresco.service.ts b/lib/core/form/services/activiti-alfresco.service.ts index fec4f133e6..afb8af1a25 100644 --- a/lib/core/form/services/activiti-alfresco.service.ts +++ b/lib/core/form/services/activiti-alfresco.service.ts @@ -43,8 +43,8 @@ export class ActivitiContentService { * @param folderId */ getAlfrescoNodes(accountId: string, folderId: string): Observable<[ExternalContent]> { - let apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); - let accountShortId = accountId.replace('alfresco-', ''); + const apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); + const accountShortId = accountId.replace('alfresco-', ''); return from(apiService.activiti.alfrescoApi.getContentInFolder(accountShortId, folderId)) .pipe( map(this.toJsonArray), @@ -59,7 +59,7 @@ export class ActivitiContentService { * @param folderId */ getAlfrescoRepositories(tenantId: number, includeAccount: boolean): Observable<any> { - let apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); + const apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); const opts = { tenantId: tenantId, includeAccounts: includeAccount @@ -94,7 +94,7 @@ export class ActivitiContentService { } applyAlfrescoNode(node: MinimalNode, siteId: string, accountId: string) { - let apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); + const apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); const currentSideId = siteId ? siteId : this.getSiteNameFromNodePath(node); const params: RelatedContentRepresentation = { source: accountId, diff --git a/lib/core/form/services/ecm-model.service.spec.ts b/lib/core/form/services/ecm-model.service.spec.ts index 35e0bf5d4b..ca1664fb6c 100644 --- a/lib/core/form/services/ecm-model.service.spec.ts +++ b/lib/core/form/services/ecm-model.service.spec.ts @@ -63,7 +63,7 @@ describe('EcmModelService', () => { it('Should fetch ECM types', (done) => { - let modelName = 'modelTest'; + const modelName = 'modelTest'; service.getEcmType(modelName).subscribe(() => { expect(jasmine.Ajax.requests.mostRecent().url.endsWith('versions/1/cmm/' + modelName + '/types')).toBeTruthy(); @@ -79,7 +79,7 @@ describe('EcmModelService', () => { it('Should create ECM types', (done) => { - let typeName = 'typeTest'; + const typeName = 'typeTest'; service.createEcmType(typeName, EcmModelService.MODEL_NAME, EcmModelService.TYPE_MODEL).subscribe(() => { expect(jasmine.Ajax.requests.mostRecent().url.endsWith('versions/1/cmm/' + EcmModelService.MODEL_NAME + '/types')).toBeTruthy(); @@ -98,8 +98,8 @@ describe('EcmModelService', () => { it('Should create ECM types with a clean and preserve real name in the title', (done) => { - let typeName = 'typeTest:testName@#$*!'; - let cleanName = 'testName'; + const typeName = 'typeTest:testName@#$*!'; + const cleanName = 'testName'; service.createEcmType(typeName, EcmModelService.MODEL_NAME, EcmModelService.TYPE_MODEL).subscribe(() => { expect(jasmine.Ajax.requests.mostRecent().url.endsWith('versions/1/cmm/' + EcmModelService.MODEL_NAME + '/types')).toBeTruthy(); @@ -118,8 +118,8 @@ describe('EcmModelService', () => { it('Should add property to a type', (done) => { - let typeName = 'typeTest'; - let formFields = { + const typeName = 'typeTest'; + const formFields = { values: { test: 'test', test2: 'test2' @@ -157,9 +157,9 @@ describe('EcmModelService', () => { it('Should add property to a type and clean name type', (done) => { - let typeName = 'typeTest:testName@#$*!'; - let cleanName = 'testName'; - let formFields = { + const typeName = 'typeTest:testName@#$*!'; + const cleanName = 'testName'; + const formFields = { values: { test: 'test', test2: 'test2' diff --git a/lib/core/form/services/ecm-model.service.ts b/lib/core/form/services/ecm-model.service.ts index 323cdee17d..7d32a1b587 100644 --- a/lib/core/form/services/ecm-model.service.ts +++ b/lib/core/form/services/ecm-model.service.ts @@ -160,7 +160,7 @@ export class EcmModelService { } public createEcmType(typeName: string, modelName: string, parentType: string): Observable<any> { - let name = this.cleanNameType(typeName); + const name = this.cleanNameType(typeName); return from(this.apiService.getInstance().core.customModelApi.createCustomType(modelName, name, parentType, typeName, '')) .pipe( @@ -170,11 +170,11 @@ export class EcmModelService { } public addPropertyToAType(modelName: string, typeName: string, formFields: any) { - let name = this.cleanNameType(typeName); + const name = this.cleanNameType(typeName); - let properties = []; + const properties = []; if (formFields && formFields.values) { - for (let key in formFields.values) { + for (const key in formFields.values) { if (key) { properties.push({ name: key, diff --git a/lib/core/form/services/form-rendering.service.spec.ts b/lib/core/form/services/form-rendering.service.spec.ts index 861d31f8ad..5e08dba434 100644 --- a/lib/core/form/services/form-rendering.service.spec.ts +++ b/lib/core/form/services/form-rendering.service.spec.ts @@ -33,37 +33,37 @@ describe('FormRenderingService', () => { }); it('should resolve Upload field as Upload widget', () => { - let field = new FormFieldModel(null, { + const field = new FormFieldModel(null, { type: FormFieldTypes.UPLOAD, params: { link: null } }); - let type = service.resolveComponentType(field); + const type = service.resolveComponentType(field); expect(type).toBe(UploadWidgetComponent); }); it('should resolve Upload widget for Upload field', () => { - let resolver = service.getComponentTypeResolver(FormFieldTypes.UPLOAD); - let type = resolver(null); + const resolver = service.getComponentTypeResolver(FormFieldTypes.UPLOAD); + const type = resolver(null); expect(type).toBe(UploadWidgetComponent); }); it('should resolve Unknown widget for unknown field type', () => { - let resolver = service.getComponentTypeResolver('missing-type'); - let type = resolver(null); + const resolver = service.getComponentTypeResolver('missing-type'); + const type = resolver(null); expect(type).toBe(UnknownWidgetComponent); }); it('should fallback to default resolver when field type missing', () => { - let resolver = service.getComponentTypeResolver(null); - let type = resolver(null); + const resolver = service.getComponentTypeResolver(null); + const type = resolver(null); expect(type).toBe(UnknownWidgetComponent); }); it('should fallback to custom resolver when field type missing', () => { - let resolver = service.getComponentTypeResolver(null, UploadWidgetComponent); - let type = resolver(null); + const resolver = service.getComponentTypeResolver(null, UploadWidgetComponent); + const type = resolver(null); expect(type).toBe(UploadWidgetComponent); }); @@ -96,13 +96,13 @@ describe('FormRenderingService', () => { }); it('should override existing resolver with explicit flag', () => { - let customResolver = DynamicComponentResolver.fromType(UnknownWidgetComponent); + const customResolver = DynamicComponentResolver.fromType(UnknownWidgetComponent); service.setComponentTypeResolver(FormFieldTypes.TEXT, customResolver, true); expect(service.getComponentTypeResolver(FormFieldTypes.TEXT)).toBe(customResolver); }); it('should override existing resolver without explicit flag', () => { - let customResolver = DynamicComponentResolver.fromType(UnknownWidgetComponent); + const customResolver = DynamicComponentResolver.fromType(UnknownWidgetComponent); service.setComponentTypeResolver(FormFieldTypes.TEXT, customResolver); expect(service.getComponentTypeResolver(FormFieldTypes.TEXT)).toBe(customResolver); }); diff --git a/lib/core/form/services/form.service.spec.ts b/lib/core/form/services/form.service.spec.ts index aa543a73dc..2e31d2b953 100644 --- a/lib/core/form/services/form.service.spec.ts +++ b/lib/core/form/services/form.service.spec.ts @@ -26,7 +26,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; declare let jasmine: any; -let fakeGroupResponse = { +const fakeGroupResponse = { 'size': 2, 'total': 2, 'start': 0, @@ -39,7 +39,7 @@ let fakeGroupResponse = { }, { 'id': 2005, 'name': 'PEOPLE_GROUP_2', 'externalId': null, 'status': 'active', 'groups': null }] }; -let fakePeopleResponse = { +const fakePeopleResponse = { 'size': 3, 'total': 3, 'start': 0, @@ -78,19 +78,19 @@ describe('Form service', () => { describe('Content tests', () => { - let responseBody = { + const responseBody = { data: [ { id: '1' }, { id: '2' } ] }; - let values = { + const values = { field1: 'one', field2: 'two' }; - let simpleResponseBody = { id: 1, modelType: 'test' }; + const simpleResponseBody = { id: 1, modelType: 'test' }; it('should fetch and parse process definitions', (done) => { service.getProcessDefinitions().subscribe((result) => { @@ -211,7 +211,7 @@ describe('Form service', () => { it('should get form definition id by name', (done) => { const formName = 'form1'; const formId = 1; - let response = { + const response = { data: [ { id: formId } ] @@ -232,7 +232,7 @@ describe('Form service', () => { it('should get start form definition by process definition id', (done) => { - let processApiSpy = jasmine.createSpyObj(['getProcessDefinitionStartForm']); + const processApiSpy = jasmine.createSpyObj(['getProcessDefinitionStartForm']); spyOn(apiService, 'getInstance').and.returnValue({ activiti: { processApi: processApiSpy @@ -327,7 +327,7 @@ describe('Form service', () => { }); it('should search for Form with modelType=2', (done) => { - let response = { data: [{ id: 1, name: 'findMe' }, { id: 2, name: 'testForm' }] }; + const response = { data: [{ id: 1, name: 'findMe' }, { id: 2, name: 'testForm' }] }; service.searchFrom('findMe').subscribe((result) => { expect(jasmine.Ajax.requests.mostRecent().url.endsWith('models?modelType=2')).toBeTruthy(); @@ -360,7 +360,7 @@ describe('Form service', () => { it('should return list of people', (done) => { spyOn(service, 'getUserProfileImageApi').and.returnValue('/app/rest/users/2002/picture'); - let fakeFilter: string = 'whatever'; + const fakeFilter: string = 'whatever'; service.getWorkflowUsers(fakeFilter).subscribe((result) => { expect(result).toBeDefined(); @@ -378,7 +378,7 @@ describe('Form service', () => { }); it('should return list of groups', (done) => { - let fakeFilter: string = 'whatever'; + const fakeFilter: string = 'whatever'; service.getWorkflowGroups(fakeFilter).subscribe((result) => { expect(result).toBeDefined(); @@ -403,9 +403,9 @@ describe('Form service', () => { it('should create a Form form a Node', (done) => { - let nameForm = 'testNode'; + const nameForm = 'testNode'; - let formId = 100; + const formId = 100; stubCreateForm(); diff --git a/lib/core/form/services/form.service.ts b/lib/core/form/services/form.service.ts index 00fc1cade1..65f5a57d28 100644 --- a/lib/core/form/services/form.service.ts +++ b/lib/core/form/services/form.service.ts @@ -102,7 +102,7 @@ export class FormService { */ parseForm(json: any, data?: FormValues, readOnly: boolean = false): FormModel { if (json) { - let form = new FormModel(json, data, readOnly, this); + const form = new FormModel(json, data, readOnly, this); if (!json.fields) { form.outcomes = [ new FormOutcomeModel(form, { @@ -128,7 +128,7 @@ export class FormService { (form) => { this.ecmModelService.searchEcmType(formName, EcmModelService.MODEL_NAME).subscribe( (customType) => { - let formDefinitionModel = new FormDefinitionModel(form.id, form.name, form.lastUpdatedByFullName, form.lastUpdated, customType.entry.properties); + const formDefinitionModel = new FormDefinitionModel(form.id, form.name, form.lastUpdatedByFullName, form.lastUpdated, customType.entry.properties); from( this.editorApi.saveForm(form.id, formDefinitionModel) ).subscribe((formData) => { @@ -148,7 +148,7 @@ export class FormService { * @returns The new form */ createForm(formName: string): Observable<any> { - let dataModel = { + const dataModel = { name: formName, description: '', modelType: 2, @@ -178,7 +178,7 @@ export class FormService { * @returns Form model(s) matching the search name */ searchFrom(name: string): Observable<any> { - let opts = { + const opts = { 'modelType': 2 }; @@ -198,7 +198,7 @@ export class FormService { * @returns List of form models */ getForms(): Observable<any> { - let opts = { + const opts = { 'modelType': 2 }; @@ -266,7 +266,7 @@ export class FormService { * @returns Null response when the operation is complete */ saveTaskForm(taskId: string, formValues: FormValues): Observable<any> { - let saveFormRepresentation = <SaveFormRepresentation> { values: formValues }; + const saveFormRepresentation = <SaveFormRepresentation> { values: formValues }; return from(this.taskApi.saveTaskForm(taskId, saveFormRepresentation)) .pipe( @@ -282,7 +282,7 @@ export class FormService { * @returns Null response when the operation is complete */ completeTaskForm(taskId: string, formValues: FormValues, outcome?: string): Observable<any> { - let completeFormRepresentation: any = <CompleteFormRepresentation> { values: formValues }; + const completeFormRepresentation: any = <CompleteFormRepresentation> { values: formValues }; if (outcome) { completeFormRepresentation.outcome = outcome; } @@ -325,7 +325,7 @@ export class FormService { * @returns Form definition */ getFormDefinitionByName(name: string): Observable<any> { - let opts = { + const opts = { 'filter': 'myReusableForms', 'filterText': name, 'modelType': 2 @@ -447,7 +447,7 @@ export class FormService { * @returns Array of users */ getWorkflowUsers(filter: string, groupId?: string): Observable<UserProcessModel[]> { - let option: any = { filter: filter }; + const option: any = { filter: filter }; if (groupId) { option.groupId = groupId; } @@ -471,7 +471,7 @@ export class FormService { * @returns Array of groups */ getWorkflowGroups(filter: string, groupId?: string): Observable<GroupModel[]> { - let option: any = { filter: filter }; + const option: any = { filter: filter }; if (groupId) { option.groupId = groupId; } diff --git a/lib/core/form/services/node.service.spec.ts b/lib/core/form/services/node.service.spec.ts index 6579aaaadf..54503d9883 100644 --- a/lib/core/form/services/node.service.spec.ts +++ b/lib/core/form/services/node.service.spec.ts @@ -54,7 +54,7 @@ describe('NodeService', () => { }); it('Should fetch and node metadata', (done) => { - let responseBody = { + const responseBody = { entry: { id: '111-222-33-44-1123', nodeType: 'typeTest', @@ -67,7 +67,7 @@ describe('NodeService', () => { service.getNodeMetadata('-nodeid-').subscribe((result) => { expect(jasmine.Ajax.requests.mostRecent().url.endsWith('nodes/-nodeid-')).toBeTruthy(); - let node = new NodeMetadata({ + const node = new NodeMetadata({ test: 'test', testdata: 'testdata' }, 'typeTest'); @@ -83,7 +83,7 @@ describe('NodeService', () => { }); it('Should clean the metadata from :', (done) => { - let responseBody = { + const responseBody = { entry: { id: '111-222-33-44-1123', nodeType: 'typeTest', @@ -96,7 +96,7 @@ describe('NodeService', () => { service.getNodeMetadata('-nodeid-').subscribe((result) => { expect(jasmine.Ajax.requests.mostRecent().url.endsWith('nodes/-nodeid-')).toBeTruthy(); - let node = new NodeMetadata({ + const node = new NodeMetadata({ test: 'test', testdata: 'testdata' }, 'typeTest'); @@ -112,12 +112,12 @@ describe('NodeService', () => { }); it('Should create a node with metadata', (done) => { - let data = { + const data = { test: 'test', testdata: 'testdata' }; - let responseBody = { + const responseBody = { id: 'a74d91fb-ea8a-4812-ad98-ad878366b5be', isFile: false, isFolder: true @@ -136,7 +136,7 @@ describe('NodeService', () => { }); it('Should add activitiForms suffix to the metadata properties', (done) => { - let data = { + const data = { test: 'test', testdata: 'testdata' }; @@ -156,7 +156,7 @@ describe('NodeService', () => { }); it('Should assign an UUID to the name when name not passed', (done) => { - let data = { + const data = { test: 'test', testdata: 'testdata' }; diff --git a/lib/core/form/services/node.service.ts b/lib/core/form/services/node.service.ts index 83e887f919..be942956a1 100644 --- a/lib/core/form/services/node.service.ts +++ b/lib/core/form/services/node.service.ts @@ -50,8 +50,8 @@ export class NodeService { * @returns The created node */ public createNodeMetadata(nodeType: string, nameSpace: any, data: any, path: string, name?: string): Observable<NodeEntry> { - let properties = {}; - for (let key in data) { + const properties = {}; + for (const key in data) { if (data[key]) { properties[nameSpace + ':' + key] = data[key]; } @@ -69,29 +69,29 @@ export class NodeService { * @returns The created node */ public createNode(name: string, nodeType: string, properties: any, path: string): Observable<NodeEntry> { - let body = { + const body = { name: name, nodeType: nodeType, properties: properties, relativePath: path }; - let apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); + const apiService: AlfrescoApiCompatibility = this.apiService.getInstance(); return from(apiService.nodes.addNode('-root-', body, {})); } private generateUuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); + const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } private cleanMetadataFromSemicolon(nodeEntry: NodeEntry): NodeMetadata { - let metadata = {}; + const metadata = {}; if (nodeEntry && nodeEntry.entry.properties) { - for (let key in nodeEntry.entry.properties) { + for (const key in nodeEntry.entry.properties) { if (key) { if (key.indexOf(':') !== -1) { metadata [key.split(':')[1]] = nodeEntry.entry.properties[key]; diff --git a/lib/core/form/services/process-content.service.spec.ts b/lib/core/form/services/process-content.service.spec.ts index 3340e8987f..148048cf98 100644 --- a/lib/core/form/services/process-content.service.spec.ts +++ b/lib/core/form/services/process-content.service.spec.ts @@ -26,7 +26,7 @@ import { AlfrescoApiServiceMock } from '../../mock/alfresco-api.service.mock'; declare let jasmine: any; -let fileContentPdfResponseBody = { +const fileContentPdfResponseBody = { id: 999, name: 'fake-name.pdf', created: '2017-01-23T12:12:53.219+0000', @@ -40,7 +40,7 @@ let fileContentPdfResponseBody = { thumbnailStatus: 'created' }; -let fileContentJpgResponseBody = { +const fileContentJpgResponseBody = { id: 888, name: 'fake-name.jpg', created: '2017-01-23T12:12:53.219+0000', @@ -55,9 +55,9 @@ let fileContentJpgResponseBody = { }; function createFakeBlob() { - let data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; + const data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; - let bytes = new Uint8Array(data.length / 2); + const bytes = new Uint8Array(data.length / 2); for (let i = 0; i < data.length; i += 2) { bytes[i / 2] = parseInt(data.substring(i, i + 2), /* base = */ 16); @@ -144,7 +144,7 @@ describe('ProcessContentService', () => { }); it('should return the unsupported content when the file is an image', (done) => { - let contentId: number = 888; + const contentId: number = 888; service.getFileContent(contentId).subscribe((result) => { expect(result.id).toEqual(contentId); @@ -162,7 +162,7 @@ describe('ProcessContentService', () => { }); it('should return the supported content when the file is a pdf', (done) => { - let contentId: number = 999; + const contentId: number = 999; service.getFileContent(contentId).subscribe((result) => { expect(result.id).toEqual(contentId); @@ -180,14 +180,14 @@ describe('ProcessContentService', () => { }); it('should return the raw content URL', () => { - let contentId: number = 999; - let contentUrl = service.getFileRawContentUrl(contentId); + const contentId: number = 999; + const contentUrl = service.getFileRawContentUrl(contentId); expect(contentUrl).toContain(`/api/enterprise/content/${contentId}/raw`); }); it('should return a Blob as thumbnail', (done) => { - let contentId: number = 999; - let blob = createFakeBlob(); + const contentId: number = 999; + const blob = createFakeBlob(); spyOn(service, 'getContentThumbnail').and.returnValue(of(blob)); service.getContentThumbnail(contentId).subscribe((result) => { expect(result).toEqual(jasmine.any(Blob)); diff --git a/lib/core/form/services/widget-visibility.service.spec.ts b/lib/core/form/services/widget-visibility.service.spec.ts index f553e65a18..73449a2135 100644 --- a/lib/core/form/services/widget-visibility.service.spec.ts +++ b/lib/core/form/services/widget-visibility.service.spec.ts @@ -38,7 +38,7 @@ describe('WidgetVisibilityService', () => { let service: WidgetVisibilityService; let booleanResult: boolean; - let stubFormWithFields = new FormModel(fakeFormJson); + const stubFormWithFields = new FormModel(fakeFormJson); setupTestBed({ imports: [ @@ -186,9 +186,9 @@ describe('WidgetVisibilityService', () => { }); describe('should retrieve the process variables', () => { - let fakeFormWithField = new FormModel(fakeFormJson); + const fakeFormWithField = new FormModel(fakeFormJson); let visibilityObjTest: WidgetVisibilityModel; - let chainedVisibilityObj = new WidgetVisibilityModel(); + const chainedVisibilityObj = new WidgetVisibilityModel(); beforeEach(() => { visibilityObjTest = new WidgetVisibilityModel(); @@ -216,7 +216,7 @@ describe('WidgetVisibilityService', () => { service.getTaskProcessVariable('9999').subscribe( (res: TaskProcessVariableModel[]) => { expect(res).toBeDefined(); - let varValue = service.getVariableValue(formTest, 'TEST_VAR_1', res); + const varValue = service.getVariableValue(formTest, 'TEST_VAR_1', res); expect(varValue).not.toBeUndefined(); expect(varValue).toBe('test_value_1'); done(); @@ -232,7 +232,7 @@ describe('WidgetVisibilityService', () => { it('should return undefined if the variable does not exist', (done) => { service.getTaskProcessVariable('9999').subscribe( (res: TaskProcessVariableModel[]) => { - let varValue = service.getVariableValue(formTest, 'TEST_MYSTERY_VAR', res); + const varValue = service.getVariableValue(formTest, 'TEST_MYSTERY_VAR', res); expect(varValue).toBeUndefined(); done(); } @@ -248,7 +248,7 @@ describe('WidgetVisibilityService', () => { service.getTaskProcessVariable('9999').subscribe( (res: TaskProcessVariableModel[]) => { visibilityObjTest.rightRestResponseId = 'TEST_VAR_2'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).not.toBeNull(); expect(rightValue).toBe('test_value_2'); @@ -266,7 +266,7 @@ describe('WidgetVisibilityService', () => { service.getTaskProcessVariable('9999').subscribe( (res: TaskProcessVariableModel[]) => { visibilityObjTest.leftRestResponseId = 'TEST_VAR_2'; - let rightValue = service.getLeftValue(formTest, visibilityObjTest); + const rightValue = service.getLeftValue(formTest, visibilityObjTest); expect(rightValue).not.toBeNull(); expect(rightValue).toBe('test_value_2'); @@ -286,7 +286,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'LEFT_FORM_FIELD_ID'; visibilityObjTest.operator = '!='; visibilityObjTest.rightRestResponseId = 'TEST_VAR_2'; - let isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); + const isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); expect(isVisible).toBeTruthy(); done(); @@ -310,7 +310,7 @@ describe('WidgetVisibilityService', () => { chainedVisibilityObj.operator = '!empty'; visibilityObjTest.nextCondition = chainedVisibilityObj; - let isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); + const isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); expect(isVisible).toBeTruthy(); done(); @@ -337,13 +337,13 @@ describe('WidgetVisibilityService', () => { describe('should return the value of the field', () => { let visibilityObjTest: WidgetVisibilityModel; - let fakeFormWithField = new FormModel(fakeFormJson); - let jsonFieldFake = { + const fakeFormWithField = new FormModel(fakeFormJson); + const jsonFieldFake = { id: 'FAKE_FORM_FIELD_ID', value: 'FAKE_FORM_FIELD_VALUE', visibilityCondition: undefined }; - let fakeForm = new FormModel({ + const fakeForm = new FormModel({ variables: [ { name: 'FORM_VARIABLE_TEST', @@ -363,28 +363,28 @@ describe('WidgetVisibilityService', () => { }); it('should be able to retrieve a field value searching in the form', () => { - let formValue = service.searchValueInForm(stubFormWithFields, 'FIELD_WITH_CONDITION'); + const formValue = service.searchValueInForm(stubFormWithFields, 'FIELD_WITH_CONDITION'); expect(formValue).not.toBeNull(); expect(formValue).toBe('field_with_condition_value'); }); it('should return empty string if the field value is not in the form', () => { - let formValue = service.searchValueInForm(stubFormWithFields, 'FIELD_MYSTERY'); + const formValue = service.searchValueInForm(stubFormWithFields, 'FIELD_MYSTERY'); expect(formValue).not.toBeUndefined(); expect(formValue).toBe(''); }); it('should search in the form if element value is not in form values', () => { - let value = service.getFormValue(fakeFormWithField, 'FIELD_WITH_CONDITION'); + const value = service.getFormValue(fakeFormWithField, 'FIELD_WITH_CONDITION'); expect(value).not.toBeNull(); expect(value).toBe('field_with_condition_value'); }); it('should return empty string if the element is not present anywhere', () => { - let formValue = service.getFormValue(fakeFormWithField, 'FIELD_MYSTERY'); + const formValue = service.getFormValue(fakeFormWithField, 'FIELD_MYSTERY'); expect(formValue).not.toBeUndefined(); expect(formValue).toBe(''); @@ -392,35 +392,35 @@ describe('WidgetVisibilityService', () => { it('should retrieve the value for the right field when it is a value', () => { visibilityObjTest.rightValue = '100'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).toBe('100'); }); it('should return formatted date when right value is a date', () => { visibilityObjTest.rightValue = '9999-12-31'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).toBe('9999-12-31T00:00:00.000Z'); }); it('should return the value when right value is not a date', () => { visibilityObjTest.rightValue = '9999-99-99'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).toBe('9999-99-99'); }); it('should retrieve the value for the right field when it is a form variable', () => { visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let rightValue = service.getRightValue(fakeFormWithField, visibilityObjTest); + const rightValue = service.getRightValue(fakeFormWithField, visibilityObjTest); expect(rightValue).not.toBeNull(); expect(rightValue).toBe('RIGHT_FORM_FIELD_VALUE'); }); it('should take the value from form values if it is present', () => { - let formValue = service.getFormValue(formTest, 'test_1'); + const formValue = service.getFormValue(formTest, 'test_1'); expect(formValue).not.toBeNull(); expect(formValue).toBe('value_1'); @@ -428,7 +428,7 @@ describe('WidgetVisibilityService', () => { it('should retrieve right value from form values if it is present', () => { visibilityObjTest.rightFormFieldId = 'test_2'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).not.toBeNull(); expect(formTest.values).toEqual(formValues); @@ -437,7 +437,7 @@ describe('WidgetVisibilityService', () => { it('should retrieve the value for the left field when it is a form value', () => { visibilityObjTest.leftFormFieldId = 'FIELD_WITH_CONDITION'; - let leftValue = service.getLeftValue(fakeFormWithField, visibilityObjTest); + const leftValue = service.getLeftValue(fakeFormWithField, visibilityObjTest); expect(leftValue).not.toBeNull(); expect(leftValue).toBe('field_with_condition_value'); @@ -445,14 +445,14 @@ describe('WidgetVisibilityService', () => { it('should retrieve left value from form values if it is present', () => { visibilityObjTest.leftFormFieldId = 'test_2'; - let leftValue = service.getLeftValue(formTest, visibilityObjTest); + const leftValue = service.getLeftValue(formTest, visibilityObjTest); expect(leftValue).not.toBeNull(); expect(leftValue).toBe('value_2'); }); it('should return an empty string for a value that is not on variable or form', () => { - let leftValue = service.getLeftValue(fakeFormWithField, visibilityObjTest); + const leftValue = service.getLeftValue(fakeFormWithField, visibilityObjTest); expect(leftValue).toBe(''); }); @@ -461,7 +461,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'test_1'; visibilityObjTest.operator = '=='; visibilityObjTest.rightFormFieldId = 'test_3'; - let isVisible = service.isFieldVisible(formTest, visibilityObjTest); + const isVisible = service.isFieldVisible(formTest, visibilityObjTest); expect(isVisible).toBeTruthy(); }); @@ -470,14 +470,14 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'test_1'; visibilityObjTest.operator = '=='; visibilityObjTest.rightValue = 'value_1'; - let isVisible = service.isFieldVisible(formTest, visibilityObjTest); + const isVisible = service.isFieldVisible(formTest, visibilityObjTest); expect(isVisible).toBeTruthy(); }); it('should return empty string for a value that is not on variable or form', () => { visibilityObjTest.rightFormFieldId = 'NO_FIELD_FORM'; - let rightValue = service.getRightValue(fakeFormWithField, visibilityObjTest); + const rightValue = service.getRightValue(fakeFormWithField, visibilityObjTest); expect(rightValue).not.toBeUndefined(); expect(rightValue).toBe(''); @@ -487,7 +487,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'LEFT_FORM_FIELD_ID'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); + const isVisible = service.isFieldVisible(fakeFormWithField, visibilityObjTest); expect(isVisible).toBeTruthy(); }); @@ -496,7 +496,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'test_1'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'test_3'; - let fakeFormField: FormFieldModel = new FormFieldModel(formTest, jsonFieldFake); + const fakeFormField: FormFieldModel = new FormFieldModel(formTest, jsonFieldFake); service.refreshEntityVisibility(fakeFormField); expect(fakeFormField.isVisible).toBeFalsy(); @@ -506,14 +506,14 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = ''; visibilityObjTest.leftRestResponseId = ''; visibilityObjTest.operator = '!='; - let isVisible = service.evaluateVisibility(formTest, visibilityObjTest); + const isVisible = service.evaluateVisibility(formTest, visibilityObjTest); expect(isVisible).toBeTruthy(); }); it('should return always true when field does not have a visibility condition', () => { jsonFieldFake.visibilityCondition = null; - let fakeFormField: FormFieldModel = new FormFieldModel(fakeFormWithField, jsonFieldFake); + const fakeFormField: FormFieldModel = new FormFieldModel(fakeFormWithField, jsonFieldFake); fakeFormField.isVisible = false; service.refreshEntityVisibility(fakeFormField); @@ -521,28 +521,28 @@ describe('WidgetVisibilityService', () => { }); it('should be able to retrieve the value of a form variable', () => { - let varValue = service.getVariableValue(fakeForm, 'FORM_VARIABLE_TEST', null); + const varValue = service.getVariableValue(fakeForm, 'FORM_VARIABLE_TEST', null); expect(varValue).not.toBeUndefined(); expect(varValue).toBe('form_value_test'); }); it('should return undefined for not existing form variable', () => { - let varValue = service.getVariableValue(fakeForm, 'MYSTERY_FORM_VARIABLE', null); + const varValue = service.getVariableValue(fakeForm, 'MYSTERY_FORM_VARIABLE', null); expect(varValue).toBeUndefined(); }); it('should retrieve the value for the left field when it is a form variable', () => { visibilityObjTest.leftRestResponseId = 'FORM_VARIABLE_TEST'; - let leftValue = service.getLeftValue(fakeForm, visibilityObjTest); + const leftValue = service.getLeftValue(fakeForm, visibilityObjTest); expect(leftValue).not.toBeNull(); expect(leftValue).toBe('form_value_test'); }); it('should determine visibility for dropdown on label condition', () => { - let dropdownValue = service.getFieldValue(formTest.values, 'dropdown_LABEL'); + const dropdownValue = service.getFieldValue(formTest.values, 'dropdown_LABEL'); expect(dropdownValue).not.toBeNull(); expect(dropdownValue).toBeDefined(); @@ -550,7 +550,7 @@ describe('WidgetVisibilityService', () => { }); it('should be able to get the value for a dropdown filtered with Label', () => { - let dropdownValue = service.getFieldValue(formTest.values, 'dropdown_LABEL'); + const dropdownValue = service.getFieldValue(formTest.values, 'dropdown_LABEL'); expect(dropdownValue).not.toBeNull(); expect(dropdownValue).toBeDefined(); @@ -558,7 +558,7 @@ describe('WidgetVisibilityService', () => { }); it('should be able to get the value for a standard field', () => { - let dropdownValue = service.getFieldValue(formTest.values, 'test_2'); + const dropdownValue = service.getFieldValue(formTest.values, 'test_2'); expect(dropdownValue).not.toBeNull(); expect(dropdownValue).toBeDefined(); @@ -566,7 +566,7 @@ describe('WidgetVisibilityService', () => { }); it('should get the dropdown label value from a form', () => { - let dropdownValue = service.getFormValue(formTest, 'dropdown_LABEL'); + const dropdownValue = service.getFormValue(formTest, 'dropdown_LABEL'); expect(dropdownValue).not.toBeNull(); expect(dropdownValue).toBeDefined(); @@ -574,7 +574,7 @@ describe('WidgetVisibilityService', () => { }); it('should get the dropdown id value from a form', () => { - let dropdownValue = service.getFormValue(formTest, 'dropdown'); + const dropdownValue = service.getFormValue(formTest, 'dropdown'); expect(dropdownValue).not.toBeNull(); expect(dropdownValue).toBeDefined(); @@ -583,7 +583,7 @@ describe('WidgetVisibilityService', () => { it('should retrieve the value for the right field when it is a dropdown id', () => { visibilityObjTest.rightFormFieldId = 'dropdown'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).toBeDefined(); expect(rightValue).toBe('dropdown_id'); @@ -591,7 +591,7 @@ describe('WidgetVisibilityService', () => { it('should retrieve the value for the right field when it is a dropdown label', () => { visibilityObjTest.rightFormFieldId = 'dropdown_LABEL'; - let rightValue = service.getRightValue(formTest, visibilityObjTest); + const rightValue = service.getRightValue(formTest, visibilityObjTest); expect(rightValue).toBeDefined(); expect(rightValue).toBe('dropdown_label'); @@ -601,7 +601,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'test_5'; visibilityObjTest.operator = '=='; visibilityObjTest.rightFormFieldId = 'dropdown_LABEL'; - let fakeFormField: FormFieldModel = new FormFieldModel(formTest, jsonFieldFake); + const fakeFormField: FormFieldModel = new FormFieldModel(formTest, jsonFieldFake); service.refreshEntityVisibility(fakeFormField); expect(fakeFormField.isVisible).toBeTruthy(); @@ -611,14 +611,14 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'test_4'; visibilityObjTest.operator = '=='; visibilityObjTest.rightFormFieldId = 'dropdown'; - let fakeFormField: FormFieldModel = new FormFieldModel(formTest, jsonFieldFake); + const fakeFormField: FormFieldModel = new FormFieldModel(formTest, jsonFieldFake); service.refreshEntityVisibility(fakeFormField); expect(fakeFormField.isVisible).toBeTruthy(); }); it('should be able to get value from form values', () => { - let res = service.getFormValue(formTest, 'test_1'); + const res = service.getFormValue(formTest, 'test_1'); expect(res).not.toBeNull(); expect(res).toBeDefined(); @@ -630,9 +630,9 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let container = <ContainerModel> fakeFormWithField.fields[0]; - let column0 = container.field.columns[0]; - let column1 = container.field.columns[1]; + const container = <ContainerModel> fakeFormWithField.fields[0]; + const column0 = container.field.columns[0]; + const column1 = container.field.columns[1]; column0.fields[0].visibilityCondition = visibilityObjTest; service.refreshVisibility(fakeFormWithField); @@ -647,7 +647,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let tab = new TabModel(fakeFormWithField, { id: 'fake-tab-id', title: 'fake-tab-title', isVisible: true }); + const tab = new TabModel(fakeFormWithField, { id: 'fake-tab-id', title: 'fake-tab-title', isVisible: true }); tab.visibilityCondition = visibilityObjTest; fakeFormWithField.tabs.push(tab); service.refreshVisibility(fakeFormWithField); @@ -659,7 +659,7 @@ describe('WidgetVisibilityService', () => { service.getTaskProcessVariable('9999').subscribe( (res: TaskProcessVariableModel[]) => { expect(res).toBeDefined(); - let varValue = service.getVariableValue(formTest, 'FIELD_FORM_EMPTY', res); + const varValue = service.getVariableValue(formTest, 'FIELD_FORM_EMPTY', res); expect(varValue).not.toBeUndefined(); expect(varValue).toBe('PROCESS_RIGHT_FORM_FIELD_VALUE'); @@ -667,7 +667,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.operator = '=='; visibilityObjTest.rightValue = 'RIGHT_FORM_FIELD_VALUE'; - let myForm = new FormModel({ + const myForm = new FormModel({ id: '9999', name: 'FORM_PROCESS_VARIABLE_VISIBILITY', processDefinitionId: 'PROCESS_TEST:9:9999', @@ -733,7 +733,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.operator = '=='; visibilityObjTest.rightValue = 'PROCESS_RIGHT_FORM_FIELD_VALUE'; - let myForm = new FormModel({ + const myForm = new FormModel({ id: '9999', name: 'FORM_PROCESS_VARIABLE_VISIBILITY', processDefinitionId: 'PROCESS_TEST:9:9999', @@ -799,7 +799,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.operator = '=='; visibilityObjTest.rightValue = 'RIGHT_FORM_FIELD_VALUE'; - let myForm = new FormModel({ + const myForm = new FormModel({ id: '9999', name: 'FORM_PROCESS_VARIABLE_VISIBILITY', processDefinitionId: 'PROCESS_TEST:9:9999', @@ -859,7 +859,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let tab = new TabModel(fakeFormWithField, { id: 'fake-tab-id', title: 'fake-tab-title', isVisible: true }); + const tab = new TabModel(fakeFormWithField, { id: 'fake-tab-id', title: 'fake-tab-title', isVisible: true }); tab.visibilityCondition = visibilityObjTest; service.refreshEntityVisibility(tab); @@ -870,7 +870,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '=='; visibilityObjTest.rightFormFieldId = 'LEFT_FORM_FIELD_ID'; - let contModel = new ContainerModel(new FormFieldModel(fakeFormWithField, { + const contModel = new ContainerModel(new FormFieldModel(fakeFormWithField, { id: 'fake-container-id', type: FormFieldTypes.GROUP, name: 'fake-container-name', @@ -887,7 +887,7 @@ describe('WidgetVisibilityService', () => { visibilityObjTest.leftFormFieldId = 'FIELD_TEST'; visibilityObjTest.operator = '!='; visibilityObjTest.rightFormFieldId = 'RIGHT_FORM_FIELD_ID'; - let contModel = new ContainerModel(new FormFieldModel(fakeFormWithField, { + const contModel = new ContainerModel(new FormFieldModel(fakeFormWithField, { id: 'fake-container-id', type: FormFieldTypes.GROUP, name: 'fake-container-name', diff --git a/lib/core/form/services/widget-visibility.service.ts b/lib/core/form/services/widget-visibility.service.ts index df34689927..3abacaaf14 100644 --- a/lib/core/form/services/widget-visibility.service.ts +++ b/lib/core/form/services/widget-visibility.service.ts @@ -47,12 +47,12 @@ export class WidgetVisibilityService { } refreshEntityVisibility(element: FormFieldModel | TabModel) { - let visible = this.evaluateVisibility(element.form, element.visibilityCondition); + const visible = this.evaluateVisibility(element.form, element.visibilityCondition); element.isVisible = visible; } evaluateVisibility(form: FormModel, visibilityObj: WidgetVisibilityModel): boolean { - let isLeftFieldPresent = visibilityObj && ( visibilityObj.leftFormFieldId || visibilityObj.leftRestResponseId ); + const isLeftFieldPresent = visibilityObj && ( visibilityObj.leftFormFieldId || visibilityObj.leftRestResponseId ); if (!isLeftFieldPresent || isLeftFieldPresent === 'null') { return true; } else { @@ -61,9 +61,9 @@ export class WidgetVisibilityService { } isFieldVisible(form: FormModel, visibilityObj: WidgetVisibilityModel): boolean { - let leftValue = this.getLeftValue(form, visibilityObj); - let rightValue = this.getRightValue(form, visibilityObj); - let actualResult = this.evaluateCondition(leftValue, rightValue, visibilityObj.operator); + const leftValue = this.getLeftValue(form, visibilityObj); + const rightValue = this.getRightValue(form, visibilityObj); + const actualResult = this.evaluateCondition(leftValue, rightValue, visibilityObj.operator); if (visibilityObj.nextCondition) { return this.evaluateLogicalOperation( visibilityObj.nextConditionOperator, @@ -150,7 +150,7 @@ export class WidgetVisibilityService { if (field.value && field.value.name) { value = field.value.name; } else if (field.options) { - let option = field.options.find((opt) => opt.id === field.value); + const option = field.options.find((opt) => opt.id === field.value); if (option) { value = this.getValueFromOption(fieldId, option); } @@ -169,7 +169,7 @@ export class WidgetVisibilityService { } private isSearchedField(field: FormFieldModel, fieldToFind: string): boolean { - let formattedFieldName = this.removeLabel(field, fieldToFind); + const formattedFieldName = this.removeLabel(field, fieldToFind); return field.id ? field.id.toUpperCase() === formattedFieldName.toUpperCase() : false; } @@ -188,14 +188,14 @@ export class WidgetVisibilityService { private getFormVariableValue(form: FormModel, name: string) { if (form.json.variables) { - let formVariable = form.json.variables.find((formVar) => formVar.name === name); + const formVariable = form.json.variables.find((formVar) => formVar.name === name); return formVariable ? formVariable.value : formVariable; } } private getProcessVariableValue(name: string, processVarList: TaskProcessVariableModel[]) { if (this.processVarList) { - let processVariable = this.processVarList.find((variable) => variable.id === name); + const processVariable = this.processVarList.find((variable) => variable.id === name); return processVariable ? processVariable.value : processVariable; } } @@ -249,7 +249,7 @@ export class WidgetVisibilityService { return from(this.apiService.getInstance().activiti.taskFormsApi.getTaskFormVariables(taskId)) .pipe( map((res) => { - let jsonRes = this.toJson(res); + const jsonRes = this.toJson(res); this.processVarList = <TaskProcessVariableModel[]> jsonRes; return jsonRes; }), diff --git a/lib/core/info-drawer/info-drawer.component.spec.ts b/lib/core/info-drawer/info-drawer.component.spec.ts index 26a5cf08e9..0bdf4d1faf 100644 --- a/lib/core/info-drawer/info-drawer.component.spec.ts +++ b/lib/core/info-drawer/info-drawer.component.spec.ts @@ -47,13 +47,13 @@ describe('InfoDrawerComponent', () => { }); it('should define InfoDrawerTabLayout', () => { - let infoDrawerTabLayout = element.querySelector('adf-info-drawer-layout'); + const infoDrawerTabLayout = element.querySelector('adf-info-drawer-layout'); expect(infoDrawerTabLayout).toBeDefined(); }); it('should emit when tab is changed', () => { - let tabEmitSpy = spyOn(component.currentTab, 'emit'); - let event = {index: 1, tab: {textLabel: 'DETAILS'}}; + const tabEmitSpy = spyOn(component.currentTab, 'emit'); + const event = {index: 1, tab: {textLabel: 'DETAILS'}}; component.onTabChange(<MatTabChangeEvent> event); expect(tabEmitSpy).toHaveBeenCalledWith(1); }); @@ -61,7 +61,7 @@ describe('InfoDrawerComponent', () => { it('should render the title', () => { component.title = 'FakeTitle'; fixture.detectChanges(); - let title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); + const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('FakeTitle'); }); @@ -106,14 +106,14 @@ describe('Custom InfoDrawer', () => { it('should render the title', () => { fixture.detectChanges(); - let title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); + const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]')); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('Fake Title Custom'); }); it('should select the tab 1 (index 0) as default', () => { fixture.detectChanges(); - let tab: any = fixture.debugElement.queryAll(By.css('.mat-tab-label-active')); + const tab: any = fixture.debugElement.queryAll(By.css('.mat-tab-label-active')); expect(tab.length).toBe(1); expect(tab[0].nativeElement.innerText).toContain('Tab1'); }); @@ -121,7 +121,7 @@ describe('Custom InfoDrawer', () => { it('should select the tab 2 (index 1)', () => { component.tabIndex = 1; fixture.detectChanges(); - let tab: any = fixture.debugElement.queryAll(By.css('.mat-tab-label-active')); + const tab: any = fixture.debugElement.queryAll(By.css('.mat-tab-label-active')); expect(tab.length).toBe(1); expect(tab[0].nativeElement.innerText).toContain('Tab2'); }); @@ -129,7 +129,7 @@ describe('Custom InfoDrawer', () => { it('should render a tab with icon', () => { component.tabIndex = 2; fixture.detectChanges(); - let tab: any = fixture.debugElement.queryAll(By.css('.mat-tab-label-active')); + const tab: any = fixture.debugElement.queryAll(By.css('.mat-tab-label-active')); expect(tab[0].nativeElement.innerText).not.toBe('Tab3'); expect(tab[0].nativeElement.innerText).toContain('tab-icon'); }); diff --git a/lib/core/login/components/login.component.spec.ts b/lib/core/login/components/login.component.spec.ts index 458e7625a6..160d8dc0a1 100644 --- a/lib/core/login/components/login.component.spec.ts +++ b/lib/core/login/components/login.component.spec.ts @@ -49,8 +49,8 @@ describe('LoginComponent', () => { }; const getLoginErrorMessage = () => { - let errorMessage = undefined; - let errorElement = element.querySelector('#login-error .adf-login-error-message'); + const errorMessage = undefined; + const errorElement = element.querySelector('#login-error .adf-login-error-message'); if (errorElement) { return errorElement.innerText; diff --git a/lib/core/login/components/login.component.ts b/lib/core/login/components/login.component.ts index 9b88b602a0..315ea91888 100644 --- a/lib/core/login/components/login.component.ts +++ b/lib/core/login/components/login.component.ts @@ -150,7 +150,7 @@ export class LoginComponent implements OnInit { ngOnInit() { if (this.authService.isOauth()) { - let oauth: OauthConfigModel = this.appConfig.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null); + const oauth: OauthConfigModel = this.appConfig.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null); if (oauth && oauth.implicitFlow) { this.implicitFlow = true; } @@ -220,15 +220,15 @@ export class LoginComponent implements OnInit { */ onValueChanged(data: any) { this.disableError(); - for (let field in this.formError) { + for (const field in this.formError) { if (field) { this.formError[field] = ''; - let hasError = + const hasError = (this.form.controls[field].errors && data[field] !== '') || (this.form.controls[field].dirty && !this.form.controls[field].valid); if (hasError) { - for (let key in this.form.controls[field].errors) { + for (const key in this.form.controls[field].errors) { if (key) { const message = this._message[field][key]; if (message && message.value) { diff --git a/lib/core/mock/event.mock.ts b/lib/core/mock/event.mock.ts index 97411d1247..28bff694c3 100644 --- a/lib/core/mock/event.mock.ts +++ b/lib/core/mock/event.mock.ts @@ -18,14 +18,14 @@ export class EventMock { static keyDown(key: any) { - let event: any = document.createEvent('Event'); + const event: any = document.createEvent('Event'); event.keyCode = key; event.initEvent('keydown'); document.dispatchEvent(event); } static keyUp(key: any) { - let event: any = document.createEvent('Event'); + const event: any = document.createEvent('Event'); event.keyCode = key; event.initEvent('keyup'); document.dispatchEvent(event); diff --git a/lib/core/pagination/infinite-pagination.component.spec.ts b/lib/core/pagination/infinite-pagination.component.spec.ts index b51b187692..cc8434618b 100644 --- a/lib/core/pagination/infinite-pagination.component.spec.ts +++ b/lib/core/pagination/infinite-pagination.component.spec.ts @@ -36,7 +36,7 @@ class TestPaginatedComponent implements PaginatedComponent { get pagination(): BehaviorSubject<PaginationModel> { if (!this._pagination) { - let defaultPagination = <PaginationModel> { + const defaultPagination = <PaginationModel> { maxItems: 10, skipCount: 0, totalItems: 0, @@ -90,7 +90,7 @@ describe('InfinitePaginationComponent', () => { component.target = null; changeDetectorRef.detectChanges(); - let loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); + const loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); expect(loadingSpinner).not.toBeNull(); }); @@ -100,7 +100,7 @@ describe('InfinitePaginationComponent', () => { component.isLoading = false; changeDetectorRef.detectChanges(); - let loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); + const loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); expect(loadingSpinner).toBeNull(); }); @@ -110,7 +110,7 @@ describe('InfinitePaginationComponent', () => { component.isLoading = false; changeDetectorRef.detectChanges(); - let loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); + const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); expect(loadMoreButton).not.toBeNull(); }); @@ -124,7 +124,7 @@ describe('InfinitePaginationComponent', () => { component.onLoadMore(); fixture.whenStable().then(() => { - let loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); + const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); expect(loadMoreButton).toBeNull(); done(); }); @@ -138,7 +138,7 @@ describe('InfinitePaginationComponent', () => { changeDetectorRef.detectChanges(); fixture.whenStable().then(() => { - let loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); + const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); expect(loadMoreButton).not.toBeNull(); done(); }); @@ -149,9 +149,9 @@ describe('InfinitePaginationComponent', () => { component.target.updatePagination(pagination); changeDetectorRef.detectChanges(); - let loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); + const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); expect(loadMoreButton).toBeNull(); - let loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); + const loadingSpinner = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-spinner"]')); expect(loadingSpinner).toBeNull(); }); @@ -169,7 +169,7 @@ describe('InfinitePaginationComponent', () => { done(); }); - let loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); + const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); loadMoreButton.triggerEventHandler('click', {}); }); @@ -187,7 +187,7 @@ describe('InfinitePaginationComponent', () => { done(); }); - let loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); + const loadMoreButton = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]')); loadMoreButton.triggerEventHandler('click', {}); }); }); @@ -245,7 +245,7 @@ describe('InfinitePaginationComponent', () => { fixture.destroy(); const emitNewPaginationEvent = () => { - let newPagination = { maxItems: 1, skipCount: 0, totalItems: 2, hasMoreItems: true }; + const newPagination = { maxItems: 1, skipCount: 0, totalItems: 2, hasMoreItems: true }; component.target.pagination.next(newPagination); }; diff --git a/lib/core/pipes/format-space.pipe.spec.ts b/lib/core/pipes/format-space.pipe.spec.ts index 6972753f84..2f736a89f5 100644 --- a/lib/core/pipes/format-space.pipe.spec.ts +++ b/lib/core/pipes/format-space.pipe.spec.ts @@ -26,40 +26,40 @@ describe('FormatSpacePipe', () => { }); it('should replace the white space with an underscore by default', () => { - let result = pipe.transform('FAKE TEST'); + const result = pipe.transform('FAKE TEST'); expect(result).toBe('fake_test'); }); it('should replace all the white spaces with an underscore by default', () => { - let result = pipe.transform('FAKE TEST CHECK '); + const result = pipe.transform('FAKE TEST CHECK '); expect(result).toBe('fake_test_check'); }); it('should trim the space at the end of the string and replace the ones in the middle', () => { - let result = pipe.transform(' FAKE TEST CHECK '); + const result = pipe.transform(' FAKE TEST CHECK '); expect(result).toBe('fake_test_check'); }); it('should return a lower case string by default', () => { const testString = 'FAKE_TEST_LOWERCASE'; - let result = pipe.transform(testString); + const result = pipe.transform(testString); expect(result).toBe(testString.toLocaleLowerCase()); }); it('should replace the empty space with the character given', () => { const testString = 'FAKE TEST LOWERCASE'; - let result = pipe.transform(testString, '+'); + const result = pipe.transform(testString, '+'); expect(result).toBe('fake+test+lowercase'); }); it('should leave the string uppercase if explicitly set', () => { const testString = 'FAKE TEST LOWERCASE'; - let result = pipe.transform(testString, '-', false); + const result = pipe.transform(testString, '-', false); expect(result).toBe('FAKE-TEST-LOWERCASE'); }); it('should return an empty string when input is null', () => { - let result = pipe.transform(null); + const result = pipe.transform(null); expect(result).toBe(''); }); }); diff --git a/lib/core/pipes/node-name-tooltip.pipe.spec.ts b/lib/core/pipes/node-name-tooltip.pipe.spec.ts index 82f047f17e..32a5aa2f46 100644 --- a/lib/core/pipes/node-name-tooltip.pipe.spec.ts +++ b/lib/core/pipes/node-name-tooltip.pipe.spec.ts @@ -48,7 +48,7 @@ describe('NodeNameTooltipPipe', () => { } } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(`${nodeTitle}\n${nodeDescription}`); }); @@ -58,7 +58,7 @@ describe('NodeNameTooltipPipe', () => { name: nodeName } }; - let tooltip = pipe.transform(<NodeEntry> node); + const tooltip = pipe.transform(<NodeEntry> node); expect(tooltip).toBe(nodeName); }); @@ -69,7 +69,7 @@ describe('NodeNameTooltipPipe', () => { properties: {} } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(nodeName); }); @@ -83,7 +83,7 @@ describe('NodeNameTooltipPipe', () => { } } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(`${nodeName}\n${nodeDescription}`); }); @@ -97,7 +97,7 @@ describe('NodeNameTooltipPipe', () => { } } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(`${nodeName}\n${nodeTitle}`); }); @@ -111,7 +111,7 @@ describe('NodeNameTooltipPipe', () => { } } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(nodeName); }); @@ -125,7 +125,7 @@ describe('NodeNameTooltipPipe', () => { } } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(nodeName); }); @@ -139,7 +139,7 @@ describe('NodeNameTooltipPipe', () => { } } }; - let tooltip = pipe.transform(node); + const tooltip = pipe.transform(node); expect(tooltip).toBe(nodeName); }); }); diff --git a/lib/core/pipes/time-ago.pipe.spec.ts b/lib/core/pipes/time-ago.pipe.spec.ts index 936e68956a..0900f6a204 100644 --- a/lib/core/pipes/time-ago.pipe.spec.ts +++ b/lib/core/pipes/time-ago.pipe.spec.ts @@ -27,12 +27,12 @@ describe('TimeAgoPipe', () => { })); it('should return time difference for a given date', () => { - let date = new Date(); + const date = new Date(); expect(pipe.transform(date)).toBe('a few seconds ago'); }); it('should return exact date if given date is more than seven days ', () => { - let date = new Date('1990-11-03T15:25:42.749'); + const date = new Date('1990-11-03T15:25:42.749'); expect(pipe.transform(date)).toBe('03/11/1990 15:25'); }); @@ -44,7 +44,7 @@ describe('TimeAgoPipe', () => { describe('When a locale is given', () => { it('should return a localised message', async(() => { - let date = new Date(); + const date = new Date(); const transformedDate = pipe.transform(date, 'de'); /* cspell:disable-next-line */ expect(transformedDate).toBe('vor ein paar Sekunden'); diff --git a/lib/core/pipes/user-initial.pipe.spec.ts b/lib/core/pipes/user-initial.pipe.spec.ts index 0f2029ac1a..bccd134b05 100644 --- a/lib/core/pipes/user-initial.pipe.spec.ts +++ b/lib/core/pipes/user-initial.pipe.spec.ts @@ -63,33 +63,33 @@ describe('UserInitialPipe', () => { it('should return a div with the user initials', () => { fakeUser.firstName = 'FAKE-NAME'; fakeUser.lastName = 'FAKE-SURNAME'; - let result = pipe.transform(fakeUser); + const result = pipe.transform(fakeUser); expect(result).toBe('<div id="user-initials-image" class="">FF</div>'); }); it('should apply the style class passed in input', () => { fakeUser.firstName = 'FAKE-NAME'; fakeUser.lastName = 'FAKE-SURNAME'; - let result = pipe.transform(fakeUser, 'fake-class-to-check'); + const result = pipe.transform(fakeUser, 'fake-class-to-check'); expect(result).toBe('<div id="user-initials-image" class="fake-class-to-check">FF</div>'); }); it('should return a single letter into div when lastName is undefined', () => { fakeUser.firstName = 'FAKE-NAME'; fakeUser.lastName = undefined; - let result = pipe.transform(fakeUser); + const result = pipe.transform(fakeUser); expect(result).toBe('<div id="user-initials-image" class="">F</div>'); }); it('should return a single letter into div when firstname is null', () => { fakeUser.firstName = undefined; fakeUser.lastName = 'FAKE-SURNAME'; - let result = pipe.transform(fakeUser); + const result = pipe.transform(fakeUser); expect(result).toBe('<div id="user-initials-image" class="">F</div>'); }); it('should return an empty string when user is null', () => { - let result = pipe.transform(null); + const result = pipe.transform(null); expect(result).toBe(''); }); }); diff --git a/lib/core/pipes/user-initial.pipe.ts b/lib/core/pipes/user-initial.pipe.ts index 0ed9bc3eaf..3fb8c4fc45 100644 --- a/lib/core/pipes/user-initial.pipe.ts +++ b/lib/core/pipes/user-initial.pipe.ts @@ -31,7 +31,7 @@ export class InitialUsernamePipe implements PipeTransform { transform(user: UserProcessModel | EcmUserModel, className: string = '', delimiter: string = ''): SafeHtml { let safeHtml: SafeHtml = ''; if (user) { - let initialResult = this.getInitialUserName(user.firstName, user.lastName, delimiter); + const initialResult = this.getInitialUserName(user.firstName, user.lastName, delimiter); safeHtml = this.sanitized.bypassSecurityTrustHtml(`<div id="user-initials-image" class="${className}">${initialResult}</div>`); } return safeHtml; diff --git a/lib/core/services/alfresco-api.service.ts b/lib/core/services/alfresco-api.service.ts index 46d048c0be..5e0421685f 100644 --- a/lib/core/services/alfresco-api.service.ts +++ b/lib/core/services/alfresco-api.service.ts @@ -111,7 +111,7 @@ export class AlfrescoApiService { } protected initAlfrescoApi() { - let oauth: OauthConfigModel = Object.assign({}, this.appConfig.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null)); + const oauth: OauthConfigModel = Object.assign({}, this.appConfig.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null)); if (oauth) { oauth.redirectUri = window.location.origin + (oauth.redirectUri || '/'); oauth.redirectUriLogout = window.location.origin + (oauth.redirectUriLogout || '/'); diff --git a/lib/core/services/auth-guard-sso-role.service.ts b/lib/core/services/auth-guard-sso-role.service.ts index e1ec3c22cc..b9d0ec78be 100644 --- a/lib/core/services/auth-guard-sso-role.service.ts +++ b/lib/core/services/auth-guard-sso-role.service.ts @@ -29,7 +29,7 @@ export class AuthGuardSsoRoleService implements CanActivate { let hasRole = false; if (route.data) { - let rolesToCheck = route.data['roles']; + const rolesToCheck = route.data['roles']; hasRole = this.hasRoles(rolesToCheck); } diff --git a/lib/core/services/authentication.service.spec.ts b/lib/core/services/authentication.service.spec.ts index 1c3169b323..863c5adb80 100644 --- a/lib/core/services/authentication.service.spec.ts +++ b/lib/core/services/authentication.service.spec.ts @@ -85,7 +85,7 @@ describe('AuthenticationService', () => { }); it('[ECM] should return an ECM ticket after the login done', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { expect(authService.isLoggedIn()).toBe(true); expect(authService.getTicketEcm()).toEqual('fake-post-ticket'); expect(authService.isEcmLoggedIn()).toBe(true); @@ -101,7 +101,7 @@ describe('AuthenticationService', () => { }); it('[ECM] should login in the ECM if no provider are defined calling the login', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { disposableLogin.unsubscribe(); done(); }); @@ -114,8 +114,8 @@ describe('AuthenticationService', () => { }); it('[ECM] should return a ticket undefined after logout', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { - let disposableLogout = authService.logout().subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { + const disposableLogout = authService.logout().subscribe(() => { expect(authService.isLoggedIn()).toBe(false); expect(authService.getTicketEcm()).toBe(null); expect(authService.isEcmLoggedIn()).toBe(false); @@ -206,7 +206,7 @@ describe('AuthenticationService', () => { }); it('[BPM] should return an BPM ticket after the login done', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe((response) => { + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe((response) => { expect(authService.isLoggedIn()).toBe(true); // cspell: disable-next expect(authService.getTicketBpm()).toEqual('Basic ZmFrZS11c2VybmFtZTpmYWtlLXBhc3N3b3Jk'); @@ -222,8 +222,8 @@ describe('AuthenticationService', () => { }); it('[BPM] should return a ticket undefined after logout', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { - let disposableLogout = authService.logout().subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { + const disposableLogout = authService.logout().subscribe(() => { expect(authService.isLoggedIn()).toBe(false); expect(authService.getTicketBpm()).toBe(null); expect(authService.isBpmLoggedIn()).toBe(false); @@ -309,7 +309,7 @@ describe('AuthenticationService', () => { }); it('[ECM] should save the remember me cookie as a session cookie after successful login', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password', false).subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password', false).subscribe(() => { expect(cookie['ALFRESCO_REMEMBER_ME']).not.toBeUndefined(); expect(cookie['ALFRESCO_REMEMBER_ME'].expiration).toBeNull(); disposableLogin.unsubscribe(); @@ -324,7 +324,7 @@ describe('AuthenticationService', () => { }); it('[ECM] should save the remember me cookie as a persistent cookie after successful login', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password', true).subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password', true).subscribe(() => { expect(cookie['ALFRESCO_REMEMBER_ME']).not.toBeUndefined(); expect(cookie['ALFRESCO_REMEMBER_ME'].expiration).not.toBeNull(); disposableLogin.unsubscribe(); @@ -340,7 +340,7 @@ describe('AuthenticationService', () => { }); it('[ECM] should not save the remember me cookie after failed login', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe( + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe( (res) => { }, (err: any) => { @@ -374,7 +374,7 @@ describe('AuthenticationService', () => { }); it('[ALL] should return both ECM and BPM tickets after the login done', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(() => { expect(authService.isLoggedIn()).toBe(true); expect(authService.getTicketEcm()).toEqual('fake-post-ticket'); // cspell: disable-next @@ -397,7 +397,7 @@ describe('AuthenticationService', () => { }); it('[ALL] should return login fail if only ECM call fail', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe( + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe( (res) => { }, (err: any) => { @@ -420,7 +420,7 @@ describe('AuthenticationService', () => { }); it('[ALL] should return login fail if only BPM call fail', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe( + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe( (res) => { }, (err: any) => { @@ -444,7 +444,7 @@ describe('AuthenticationService', () => { }); it('[ALL] should return ticket undefined when the credentials are wrong', (done) => { - let disposableLogin = authService.login('fake-username', 'fake-password').subscribe( + const disposableLogin = authService.login('fake-username', 'fake-password').subscribe( (res) => { }, (err: any) => { diff --git a/lib/core/services/authentication.service.ts b/lib/core/services/authentication.service.ts index ce2d96caa3..03ae5a885e 100644 --- a/lib/core/services/authentication.service.ts +++ b/lib/core/services/authentication.service.ts @@ -185,7 +185,7 @@ export class AuthenticationService { * @returns The ticket or `null` if none was found */ getTicketEcmBase64(): string | null { - let ticket = this.alfrescoApi.getInstance().getTicketEcm(); + const ticket = this.alfrescoApi.getInstance().getTicketEcm(); if (ticket) { return 'Basic ' + btoa(ticket); } @@ -247,7 +247,7 @@ export class AuthenticationService { * @returns The redirect URL */ getRedirect(): string { - let provider = <string> this.appConfig.get(AppConfigValues.PROVIDERS); + const provider = <string> this.appConfig.get(AppConfigValues.PROVIDERS); return this.hasValidRedirection(provider) ? this.redirectUrl.url : null; } diff --git a/lib/core/services/comment-process.service.spec.ts b/lib/core/services/comment-process.service.spec.ts index 25bb21d8ca..0fe68bc925 100644 --- a/lib/core/services/comment-process.service.spec.ts +++ b/lib/core/services/comment-process.service.spec.ts @@ -69,7 +69,7 @@ describe('Comment ProcessService Service', () => { it('should return the correct comment data', async(() => { service.getProcessInstanceComments(processId).subscribe((comments) => { - let comment: any = comments[0]; + const comment: any = comments[0]; expect(comment.id).toBe(fakeProcessComment.id); expect(comment.created).toBe(fakeProcessComment.created); expect(comment.message).toBe(fakeProcessComment.message); diff --git a/lib/core/services/comment-process.service.ts b/lib/core/services/comment-process.service.ts index 4ea7a8bf3f..7ee6287f6e 100644 --- a/lib/core/services/comment-process.service.ts +++ b/lib/core/services/comment-process.service.ts @@ -62,9 +62,9 @@ export class CommentProcessService { return from(this.apiService.getInstance().activiti.taskApi.getTaskComments(taskId)) .pipe( map((response: any) => { - let comments: CommentModel[] = []; + const comments: CommentModel[] = []; response.data.forEach((comment: CommentModel) => { - let user = new UserProcessModel(comment.createdBy); + const user = new UserProcessModel(comment.createdBy); comments.push(new CommentModel({ id: comment.id, message: comment.message, @@ -87,9 +87,9 @@ export class CommentProcessService { return from(this.apiService.getInstance().activiti.commentsApi.getProcessInstanceComments(processInstanceId)) .pipe( map((response: any) => { - let comments: CommentModel[] = []; + const comments: CommentModel[] = []; response.data.forEach((comment: CommentModel) => { - let user = new UserProcessModel(comment.createdBy); + const user = new UserProcessModel(comment.createdBy); comments.push(new CommentModel({ id: comment.id, message: comment.message, diff --git a/lib/core/services/content.service.spec.ts b/lib/core/services/content.service.spec.ts index a029426b08..526443331c 100644 --- a/lib/core/services/content.service.spec.ts +++ b/lib/core/services/content.service.spec.ts @@ -66,7 +66,7 @@ describe('ContentService', () => { jasmine.Ajax.install(); - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config = { ecmHost: 'http://localhost:9876/ecm', provider: 'ECM' @@ -109,33 +109,33 @@ describe('ContentService', () => { describe('AllowableOperations', () => { it('should hasAllowableOperations be false if allowableOperation is not present in the node', () => { - let permissionNode = new Node({}); + const permissionNode = new Node({}); expect(contentService.hasAllowableOperations(permissionNode, 'create')).toBeFalsy(); }); it('should hasAllowableOperations be true if allowableOperation is present and you have the permission for the request operation', () => { - let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'create', 'updatePermissions'] }); + const permissionNode = new Node({ allowableOperations: ['delete', 'update', 'create', 'updatePermissions'] }); expect(contentService.hasAllowableOperations(permissionNode, 'create')).toBeTruthy(); }); it('should hasAllowableOperations be false if allowableOperation is present but you don\'t have the permission for the request operation', () => { - let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] }); + const permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] }); expect(contentService.hasAllowableOperations(permissionNode, 'create')).toBeFalsy(); }); it('should hasAllowableOperations works in the opposite way with negate value', () => { - let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] }); + const permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] }); expect(contentService.hasAllowableOperations(permissionNode, '!create')).toBeTruthy(); }); it('should hasAllowableOperations return false if no permission parameter are passed', () => { - let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] }); + const permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] }); expect(contentService.hasAllowableOperations(permissionNode, null)).toBeFalsy(); }); it('should havePermission return true if permission parameter is copy', () => { - let permissionNode = null; + const permissionNode = null; expect(contentService.hasAllowableOperations(permissionNode, 'copy')).toBeTruthy(); }); }); @@ -143,38 +143,38 @@ describe('ContentService', () => { describe('Permissions', () => { it('should havePermission be false if allowableOperation is not present in the node', () => { - let permissionNode = new Node({}); + const permissionNode = new Node({}); expect(contentService.hasPermissions(permissionNode, 'manager')).toBeFalsy(); }); it('should havePermission be true if permissions is present and you have the permission for the request operation', () => { - let permissionNode = new Node({ permissions: { locallySet: [{ name: 'manager' }, { name: 'collaborator' }, { name: 'consumer' }] } }); + const permissionNode = new Node({ permissions: { locallySet: [{ name: 'manager' }, { name: 'collaborator' }, { name: 'consumer' }] } }); expect(contentService.hasPermissions(permissionNode, 'manager')).toBeTruthy(); }); it('should havePermission be false if permissions is present but you don\'t have the permission for the request operation', () => { - let permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } }); + const permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } }); expect(contentService.hasPermissions(permissionNode, 'manager')).toBeFalsy(); }); it('should havePermission works in the opposite way with negate value', () => { - let permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } }); + const permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } }); expect(contentService.hasPermissions(permissionNode, '!manager')).toBeTruthy(); }); it('should havePermission return false if no permission parameter are passed', () => { - let permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } }); + const permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } }); expect(contentService.hasPermissions(permissionNode, null)).toBeFalsy(); }); it('should havePermission return true if the permissions is empty and the permission to check is Consumer', () => { - let permissionNode = new Node({ permissions: [] }); + const permissionNode = new Node({ permissions: [] }); expect(contentService.hasPermissions(permissionNode, 'Consumer')).toBeTruthy(); }); it('should havePermission return false if the permissions is empty and the permission to check is not Consumer', () => { - let permissionNode = new Node({ permissions: [] }); + const permissionNode = new Node({ permissions: [] }); expect(contentService.hasPermissions(permissionNode, '!Consumer')).toBeFalsy(); }); }); @@ -183,13 +183,13 @@ describe('ContentService', () => { it('Should use native msSaveOrOpenBlob if the browser is IE', (done) => { - let navigatorAny: any = window.navigator; + const navigatorAny: any = window.navigator; navigatorAny.__defineGetter__('msSaveOrOpenBlob', () => { done(); }); - let blob = new Blob([''], { type: 'text/html' }); + const blob = new Blob([''], { type: 'text/html' }); contentService.downloadBlob(blob, 'test_ie'); }); }); diff --git a/lib/core/services/content.service.ts b/lib/core/services/content.service.ts index 342199b00a..38bec4f3c9 100644 --- a/lib/core/services/content.service.ts +++ b/lib/core/services/content.service.ts @@ -43,7 +43,7 @@ export class ContentService { private logService: LogService, private sanitizer: DomSanitizer) { this.saveData = (function () { - let a = document.createElement('a'); + const a = document.createElement('a'); document.body.appendChild(a); a.style.display = 'none'; @@ -55,7 +55,7 @@ export class ContentService { } if (format === 'object' || format === 'json') { - let json = JSON.stringify(fileData); + const json = JSON.stringify(fileData); blob = new Blob([json], { type: 'octet/stream' }); } @@ -64,7 +64,7 @@ export class ContentService { if (typeof window.navigator !== 'undefined' && window.navigator.msSaveOrOpenBlob) { navigator.msSaveOrOpenBlob(blob, fileName); } else { - let url = window.URL.createObjectURL(blob); + const url = window.URL.createObjectURL(blob); a.href = url; a.download = fileName; a.click(); @@ -110,7 +110,7 @@ export class ContentService { * @returns URL string */ createTrustedUrl(blob: Blob): string { - let url = window.URL.createObjectURL(blob); + const url = window.URL.createObjectURL(blob); return <string> this.sanitizer.bypassSecurityTrustUrl(url); } diff --git a/lib/core/services/discovery-api.service.spec.ts b/lib/core/services/discovery-api.service.spec.ts index cca8e4e34c..d97ae0d6bc 100644 --- a/lib/core/services/discovery-api.service.spec.ts +++ b/lib/core/services/discovery-api.service.spec.ts @@ -24,7 +24,7 @@ import { CoreTestingModule } from '../testing/core.testing.module'; declare let jasmine: any; -let fakeEcmDiscoveryResponse: any = { +const fakeEcmDiscoveryResponse: any = { 'entry': { 'repository': { 'edition': 'FAKE', @@ -79,7 +79,7 @@ let fakeEcmDiscoveryResponse: any = { } }; -let fakeBPMDiscoveryResponse: any = { +const fakeBPMDiscoveryResponse: any = { 'revisionVersion': '2', 'edition': 'SUPER FAKE EDITION', 'type': 'bpmSuite', @@ -96,7 +96,7 @@ describe('Discovery Api Service', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config = { ecmHost: 'http://localhost:9876/ecm' }; diff --git a/lib/core/services/dynamic-component-mapper.service.ts b/lib/core/services/dynamic-component-mapper.service.ts index 7391fdfedf..27914ddc2d 100644 --- a/lib/core/services/dynamic-component-mapper.service.ts +++ b/lib/core/services/dynamic-component-mapper.service.ts @@ -59,7 +59,7 @@ export abstract class DynamicComponentMapper { throw new Error(`resolver is null or not defined`); } - let existing = this.types[type]; + const existing = this.types[type]; if (existing && !override) { throw new Error(`already mapped, use override option if you intend replacing existing mapping.`); } @@ -75,7 +75,7 @@ export abstract class DynamicComponentMapper { */ resolveComponentType(model: DynamicComponentModel, defaultValue: Type<{}> = this.defaultValue): Type<{}> { if (model) { - let resolver = this.getComponentTypeResolver(model.type, defaultValue); + const resolver = this.getComponentTypeResolver(model.type, defaultValue); return resolver(model); } return defaultValue; diff --git a/lib/core/services/external-alfresco-api.service.ts b/lib/core/services/external-alfresco-api.service.ts index 108b4801fa..c6fee9cd2a 100644 --- a/lib/core/services/external-alfresco-api.service.ts +++ b/lib/core/services/external-alfresco-api.service.ts @@ -44,7 +44,7 @@ export class ExternalAlfrescoApiService { init(ecmHost: string, contextRoot: string) { - let domainPrefix = this.createPrefixFromHost(ecmHost); + const domainPrefix = this.createPrefixFromHost(ecmHost); const config = { provider: 'ECM', @@ -65,7 +65,7 @@ export class ExternalAlfrescoApiService { } private createPrefixFromHost(url: string): string { - let match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i); + const match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i); let result = null; if (match != null && match.length > 2 && typeof match[2] === 'string' && match[2].length > 0) { result = match[2]; diff --git a/lib/core/services/jwt-helper.service.ts b/lib/core/services/jwt-helper.service.ts index 6bb3304571..6fe6bece91 100644 --- a/lib/core/services/jwt-helper.service.ts +++ b/lib/core/services/jwt-helper.service.ts @@ -30,13 +30,13 @@ export class JwtHelperService { * @returns Decoded token data object */ decodeToken(token): Object { - let parts = token.split('.'); + const parts = token.split('.'); if (parts.length !== 3) { throw new Error('JWT must have 3 parts'); } - let decoded = this.urlBase64Decode(parts[1]); + const decoded = this.urlBase64Decode(parts[1]); if (!decoded) { throw new Error('Cannot decode the token'); } diff --git a/lib/core/services/log.service.ts b/lib/core/services/log.service.ts index 4fab3c00c8..79238611bd 100644 --- a/lib/core/services/log.service.ts +++ b/lib/core/services/log.service.ts @@ -28,7 +28,7 @@ import { Subject } from 'rxjs'; export class LogService { get currentLogLevel() { - let configLevel: string = this.appConfig.get<string>(AppConfigValues.LOG_LEVEL); + const configLevel: string = this.appConfig.get<string>(AppConfigValues.LOG_LEVEL); if (configLevel) { return this.getLogLevel(configLevel); @@ -168,7 +168,7 @@ export class LogService { * @returns Numeric log level */ getLogLevel(level: string): LogLevelsEnum { - let referencedLevel = logLevels.find((currentLevel: any) => { + const referencedLevel = logLevels.find((currentLevel: any) => { return currentLevel.name.toLocaleLowerCase() === level.toLocaleLowerCase(); }); diff --git a/lib/core/services/login-dialog.service.spec.ts b/lib/core/services/login-dialog.service.spec.ts index 88ed949a52..e111488baf 100644 --- a/lib/core/services/login-dialog.service.spec.ts +++ b/lib/core/services/login-dialog.service.spec.ts @@ -27,7 +27,6 @@ describe('LoginDialogService', () => { let service: LoginDialogService; let materialDialog: MatDialog; let spyOnDialogOpen: jasmine.Spy; - let afterOpenObservable: Subject<any>; setupTestBed({ imports: [CoreModule.forRoot()] @@ -37,7 +36,7 @@ describe('LoginDialogService', () => { service = TestBed.get(LoginDialogService); materialDialog = TestBed.get(MatDialog); spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({ - afterOpen: () => afterOpenObservable, + afterOpen: () => of({}), afterClosed: () => of({}), componentInstance: { error: new Subject<any>() diff --git a/lib/core/services/notification.service.spec.ts b/lib/core/services/notification.service.spec.ts index ef568a8482..7d2eb3f3b3 100644 --- a/lib/core/services/notification.service.spec.ts +++ b/lib/core/services/notification.service.spec.ts @@ -36,32 +36,32 @@ class ProvidesNotificationServiceComponent { } sendMessageWithoutConfig() { - let promise = this.notificationService.openSnackMessage('Test notification', 1000); + const promise = this.notificationService.openSnackMessage('Test notification', 1000); return promise; } sendMessage() { - let promise = this.notificationService.openSnackMessage('Test notification', 1000); + const promise = this.notificationService.openSnackMessage('Test notification', 1000); return promise; } sendCustomMessage() { - let promise = this.notificationService.openSnackMessage('Test notification', new MatSnackBarConfig()); + const promise = this.notificationService.openSnackMessage('Test notification', new MatSnackBarConfig()); return promise; } sendMessageActionWithoutConfig() { - let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 1000); + const promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 1000); return promise; } sendMessageAction() { - let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 1000); + const promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 1000); return promise; } sendCustomMessageAction() { - let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', new MatSnackBarConfig()); + const promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', new MatSnackBarConfig()); return promise; } @@ -99,7 +99,7 @@ describe('NotificationService', () => { it('should translate messages', (done) => { spyOn(translationService, 'instant').and.callThrough(); - let promise = fixture.componentInstance.sendMessage(); + const promise = fixture.componentInstance.sendMessage(); promise.afterDismissed().subscribe(() => { expect(translationService.instant).toHaveBeenCalled(); done(); @@ -109,7 +109,7 @@ describe('NotificationService', () => { }); it('should open a message notification bar', (done) => { - let promise = fixture.componentInstance.sendMessage(); + const promise = fixture.componentInstance.sendMessage(); promise.afterDismissed().subscribe(() => { done(); }); @@ -120,7 +120,7 @@ describe('NotificationService', () => { }); it('should open a message notification bar without custom configuration', (done) => { - let promise = fixture.componentInstance.sendMessageWithoutConfig(); + const promise = fixture.componentInstance.sendMessageWithoutConfig(); promise.afterDismissed().subscribe(() => { done(); }); @@ -131,7 +131,7 @@ describe('NotificationService', () => { }); it('should open a message notification bar with custom configuration', async((done) => { - let promise = fixture.componentInstance.sendCustomMessage(); + const promise = fixture.componentInstance.sendCustomMessage(); promise.afterDismissed().subscribe(() => { done(); }); @@ -142,7 +142,7 @@ describe('NotificationService', () => { })); it('should open a message notification bar with action', (done) => { - let promise = fixture.componentInstance.sendMessageAction(); + const promise = fixture.componentInstance.sendMessageAction(); promise.afterDismissed().subscribe(() => { done(); }); @@ -153,7 +153,7 @@ describe('NotificationService', () => { }); it('should open a message notification bar with action and custom configuration', async((done) => { - let promise = fixture.componentInstance.sendCustomMessageAction(); + const promise = fixture.componentInstance.sendCustomMessageAction(); promise.afterDismissed().subscribe(() => { done(); }); @@ -164,7 +164,7 @@ describe('NotificationService', () => { })); it('should open a message notification bar with action and no custom configuration', (done) => { - let promise = fixture.componentInstance.sendMessageActionWithoutConfig(); + const promise = fixture.componentInstance.sendMessageActionWithoutConfig(); promise.afterDismissed().subscribe(() => { done(); }); diff --git a/lib/core/services/people-process.service.spec.ts b/lib/core/services/people-process.service.spec.ts index 3c87c78259..a4df9151d2 100644 --- a/lib/core/services/people-process.service.spec.ts +++ b/lib/core/services/people-process.service.spec.ts @@ -96,7 +96,7 @@ describe('PeopleProcessService', () => { }); it('should return user image url', () => { - let url = service.getUserImage(firstInvolvedUser); + const url = service.getUserImage(firstInvolvedUser); expect(url).toContain('/users/' + firstInvolvedUser.id + '/picture'); }); diff --git a/lib/core/services/people-process.service.ts b/lib/core/services/people-process.service.ts index 5bcec3fc3f..e4c4856899 100644 --- a/lib/core/services/people-process.service.ts +++ b/lib/core/services/people-process.service.ts @@ -38,7 +38,7 @@ export class PeopleProcessService { * @returns Array of user information objects */ getWorkflowUsers(taskId?: string, searchWord?: string): Observable<UserProcessModel[]> { - let option = { excludeTaskId: taskId, filter: searchWord }; + const option = { excludeTaskId: taskId, filter: searchWord }; return from(this.getWorkflowUserApi(option)) .pipe( map((response: any) => <UserProcessModel[]> response.data || []), @@ -62,7 +62,7 @@ export class PeopleProcessService { * @returns Empty response when the update completes */ involveUserWithTask(taskId: string, idToInvolve: string): Observable<UserProcessModel[]> { - let node = {userId: idToInvolve}; + const node = {userId: idToInvolve}; return from(this.involveUserToTaskApi(taskId, node)) .pipe( catchError((err) => this.handleError(err)) @@ -76,7 +76,7 @@ export class PeopleProcessService { * @returns Empty response when the update completes */ removeInvolvedUser(taskId: string, idToRemove: string): Observable<UserProcessModel[]> { - let node = {userId: idToRemove}; + const node = {userId: idToRemove}; return from(this.removeInvolvedUserFromTaskApi(taskId, node)) .pipe( catchError((err) => this.handleError(err)) diff --git a/lib/core/services/renditions.service.ts b/lib/core/services/renditions.service.ts index e30a1a696b..3c67919054 100644 --- a/lib/core/services/renditions.service.ts +++ b/lib/core/services/renditions.service.ts @@ -37,9 +37,9 @@ export class RenditionsService { getAvailableRenditionForNode(nodeId: string): Observable<RenditionEntry> { return from(this.apiService.renditionsApi.getRenditions(nodeId)).pipe( map((availableRenditions: RenditionPaging) => { - let renditionsAvailable: RenditionEntry[] = availableRenditions.list.entries.filter( + const renditionsAvailable: RenditionEntry[] = availableRenditions.list.entries.filter( (rendition) => (rendition.entry.id === 'pdf' || rendition.entry.id === 'imgpreview')); - let existingRendition = renditionsAvailable.find((rend) => rend.entry.status === 'CREATED'); + const existingRendition = renditionsAvailable.find((rend) => rend.entry.status === 'CREATED'); return existingRendition ? existingRendition : renditionsAvailable[0]; })); } diff --git a/lib/core/services/search-configuration.service.ts b/lib/core/services/search-configuration.service.ts index 31f708a32a..114743d31c 100644 --- a/lib/core/services/search-configuration.service.ts +++ b/lib/core/services/search-configuration.service.ts @@ -35,7 +35,7 @@ export class SearchConfigurationService implements SearchConfigurationInterface * @returns Query body defined by the parameters */ public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody { - let defaultQueryBody: QueryBody = { + const defaultQueryBody: QueryBody = { query: { query: searchTerm ? `'${searchTerm}*' OR name:'${searchTerm}*'` : searchTerm }, diff --git a/lib/core/services/search.service.spec.ts b/lib/core/services/search.service.spec.ts index 8f9a129995..17351e67e2 100644 --- a/lib/core/services/search.service.spec.ts +++ b/lib/core/services/search.service.spec.ts @@ -50,7 +50,7 @@ describe('SearchService', () => { }); it('should call search API with no additional options', (done) => { - let searchTerm = 'searchTerm63688'; + const searchTerm = 'searchTerm63688'; spyOn(searchMockApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch)); service.getNodeQueryResults(searchTerm).subscribe( () => { @@ -61,7 +61,7 @@ describe('SearchService', () => { }); it('should call search API with additional options', (done) => { - let searchTerm = 'searchTerm63688', options = { + const searchTerm = 'searchTerm63688', options = { include: [ 'path' ], rootNodeId: '-root-', nodeType: 'cm:content' diff --git a/lib/core/services/sites.service.spec.ts b/lib/core/services/sites.service.spec.ts index 4d8657719d..61c4ce2cf6 100644 --- a/lib/core/services/sites.service.spec.ts +++ b/lib/core/services/sites.service.spec.ts @@ -32,7 +32,7 @@ describe('Sites service', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config = { ecmHost: 'http://localhost:9876/ecm', files: { diff --git a/lib/core/services/sites.service.ts b/lib/core/services/sites.service.ts index 72a6a5d7b1..cf380ec9f4 100644 --- a/lib/core/services/sites.service.ts +++ b/lib/core/services/sites.service.ts @@ -67,7 +67,7 @@ export class SitesService { * @returns Null response notifying when the operation is complete */ deleteSite(siteId: string, permanentFlag: boolean = true): Observable<any> { - let options: any = {}; + const options: any = {}; options.permanent = permanentFlag; return from(this.apiService.getInstance().core.sitesApi.deleteSite(siteId, options)) .pipe( diff --git a/lib/core/services/storage.service.ts b/lib/core/services/storage.service.ts index fb5b40b637..35ace886f8 100644 --- a/lib/core/services/storage.service.ts +++ b/lib/core/services/storage.service.ts @@ -91,7 +91,7 @@ export class StorageService { private storageAvailable(type: string): boolean { try { - let storage = window[type]; + const storage = window[type]; const key = '__storage_test__'; storage.setItem(key, key); storage.removeItem(key, key); diff --git a/lib/core/services/thumbnail.service.ts b/lib/core/services/thumbnail.service.ts index 7a80e60c47..e211e1e163 100644 --- a/lib/core/services/thumbnail.service.ts +++ b/lib/core/services/thumbnail.service.ts @@ -170,7 +170,7 @@ export class ThumbnailService { * @returns URL string */ public getDocumentThumbnailUrl(node: any): string { - let thumbnail = this.contentService.getDocumentThumbnailUrl(node); + const thumbnail = this.contentService.getDocumentThumbnailUrl(node); return thumbnail || this.DEFAULT_ICON; } @@ -180,7 +180,7 @@ export class ThumbnailService { * @returns URL string */ public getMimeTypeIcon(mimeType: string): string { - let icon = this.mimeTypeIcons[mimeType]; + const icon = this.mimeTypeIcons[mimeType]; return (icon || this.DEFAULT_ICON); } diff --git a/lib/core/services/translate-loader.service.ts b/lib/core/services/translate-loader.service.ts index 3f68292069..4883ac89c1 100644 --- a/lib/core/services/translate-loader.service.ts +++ b/lib/core/services/translate-loader.service.ts @@ -43,7 +43,7 @@ export class TranslateLoaderService implements TranslateLoader { } registerProvider(name: string, path: string) { - let registered = this.providers.find((provider) => provider.name === name); + const registered = this.providers.find((provider) => provider.name === name); if (registered) { registered.path = path; } else { @@ -148,7 +148,7 @@ export class TranslateLoaderService implements TranslateLoader { if (batch.length > 0) { forkJoin(batch).subscribe( () => { - let fullTranslation = this.getFullTranslationJSON(lang); + const fullTranslation = this.getFullTranslationJSON(lang); if (fullTranslation) { observer.next(fullTranslation); } @@ -162,7 +162,7 @@ export class TranslateLoaderService implements TranslateLoader { observer.error('Failed to load some resources'); }); } else { - let fullTranslation = this.getFullTranslationJSON(lang); + const fullTranslation = this.getFullTranslationJSON(lang); if (fullTranslation) { observer.next(fullTranslation); observer.complete(); diff --git a/lib/core/services/translate-loader.spec.ts b/lib/core/services/translate-loader.spec.ts index 0320372215..f8208ea17c 100644 --- a/lib/core/services/translate-loader.spec.ts +++ b/lib/core/services/translate-loader.spec.ts @@ -21,7 +21,7 @@ import { TranslationService } from './translation.service'; import { setupTestBed } from '../testing/setupTestBed'; import { CoreModule } from '../core.module'; -let componentJson1 = ' {"TEST": "This is a test", "TEST2": "This is another test"} ' ; +const componentJson1 = ' {"TEST": "This is a test", "TEST2": "This is another test"} ' ; declare let jasmine: any; diff --git a/lib/core/services/translation.service.ts b/lib/core/services/translation.service.ts index 4c1d990b0a..44b33217db 100644 --- a/lib/core/services/translation.service.ts +++ b/lib/core/services/translation.service.ts @@ -46,7 +46,7 @@ export class TranslationService { this.customLoader.setDefaultLang(this.defaultLang); if (providers && providers.length > 0) { - for (let provider of providers) { + for (const provider of providers) { this.addTranslationFolder(provider.name, provider.source); } } diff --git a/lib/core/services/upload.service.spec.ts b/lib/core/services/upload.service.spec.ts index f6effee761..5e4ecaadf5 100644 --- a/lib/core/services/upload.service.spec.ts +++ b/lib/core/services/upload.service.spec.ts @@ -38,7 +38,7 @@ describe('UploadService', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config = { ecmHost: 'http://localhost:9876/ecm', files: { @@ -66,13 +66,13 @@ describe('UploadService', () => { }); it('should add an element in the queue and returns it', () => { - let filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }); + const filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }); service.addToQueue(filesFake); expect(service.getQueue().length).toEqual(1); }); it('should add two elements in the queue and returns them', () => { - let filesFake = [ + const filesFake = [ new FileModel(<File> { name: 'fake-name', size: 10 }), new FileModel(<File> { name: 'fake-name2', size: 20 }) ]; @@ -97,21 +97,21 @@ describe('UploadService', () => { }); it('should make XHR done request after the file is added in the queue', (done) => { - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); - let emitterDisposable = emitter.subscribe((e) => { + const emitterDisposable = emitter.subscribe((e) => { expect(e.value).toBe('File uploaded'); emitterDisposable.unsubscribe(); done(); }); - let fileFake = new FileModel( + const fileFake = new FileModel( <File> { name: 'fake-name', size: 10 }, <FileUploadOptions> { parentId: '-root-', path: 'fake-dir' } ); service.addToQueue(fileFake); service.uploadFilesInTheQueue(emitter); - let request = jasmine.Ajax.requests.mostRecent(); + const request = jasmine.Ajax.requests.mostRecent(); expect(request.url).toBe('http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/-root-/children?autoRename=true&include=allowableOperations'); expect(request.method).toBe('POST'); @@ -123,14 +123,14 @@ describe('UploadService', () => { }); it('should make XHR error request after an error occur', (done) => { - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); - let emitterDisposable = emitter.subscribe((e) => { + const emitterDisposable = emitter.subscribe((e) => { expect(e.value).toBe('Error file uploaded'); emitterDisposable.unsubscribe(); done(); }); - let fileFake = new FileModel( + const fileFake = new FileModel( <File> { name: 'fake-name', size: 10 }, <FileUploadOptions> { parentId: '-root-' } ); @@ -147,26 +147,26 @@ describe('UploadService', () => { }); it('should make XHR abort request after the xhr abort is called', (done) => { - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); - let emitterDisposable = emitter.subscribe((e) => { + const emitterDisposable = emitter.subscribe((e) => { expect(e.value).toEqual('File aborted'); emitterDisposable.unsubscribe(); done(); }); - let fileFake = new FileModel(<File> { name: 'fake-name', size: 10 }); + const fileFake = new FileModel(<File> { name: 'fake-name', size: 10 }); service.addToQueue(fileFake); service.uploadFilesInTheQueue(emitter); - let file = service.getQueue(); + const file = service.getQueue(); service.cancelUpload(...file); }); it('If newVersion is set, name should be a param', () => { - let uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough(); + const uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough(); - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); const filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }, { newVersion: true @@ -188,21 +188,21 @@ describe('UploadService', () => { }); it('should use custom root folder ID given to the service', (done) => { - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); - let emitterDisposable = emitter.subscribe((e) => { + const emitterDisposable = emitter.subscribe((e) => { expect(e.value).toBe('File uploaded'); emitterDisposable.unsubscribe(); done(); }); - let filesFake = new FileModel( + const filesFake = new FileModel( <File> { name: 'fake-name', size: 10 }, <FileUploadOptions> { parentId: '123', path: 'fake-dir' } ); service.addToQueue(filesFake); service.uploadFilesInTheQueue(emitter); - let request = jasmine.Ajax.requests.mostRecent(); + const request = jasmine.Ajax.requests.mostRecent(); expect(request.url).toBe('http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/123/children?autoRename=true&include=allowableOperations'); expect(request.method).toBe('POST'); @@ -214,10 +214,10 @@ describe('UploadService', () => { }); it('should append to the request the extra upload options', () => { - let uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough(); - let emitter = new EventEmitter(); + const uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough(); + const emitter = new EventEmitter(); - let filesFake = new FileModel( + const filesFake = new FileModel( <File> { name: 'fake-name', size: 10 }, <FileUploadOptions> { parentId: '123', path: 'fake-dir', @@ -246,7 +246,7 @@ describe('UploadService', () => { }); it('should start downloading the next one if a file of the list is aborted', (done) => { - let emitter = new EventEmitter(); + const emitter = new EventEmitter(); service.fileUploadAborted.subscribe((e) => { expect(e).not.toBeNull(); @@ -257,13 +257,13 @@ describe('UploadService', () => { done(); }); - let fileFake1 = new FileModel(<File> { name: 'fake-name1', size: 10 }); - let fileFake2 = new FileModel(<File> { name: 'fake-name2', size: 10 }); - let fileList = [fileFake1, fileFake2]; + const fileFake1 = new FileModel(<File> { name: 'fake-name1', size: 10 }); + const fileFake2 = new FileModel(<File> { name: 'fake-name2', size: 10 }); + const fileList = [fileFake1, fileFake2]; service.addToQueue(...fileList); service.uploadFilesInTheQueue(emitter); - let file = service.getQueue(); + const file = service.getQueue(); service.cancelUpload(...file); }); diff --git a/lib/core/services/upload.service.ts b/lib/core/services/upload.service.ts index 575ce31ebc..dbe4333c44 100644 --- a/lib/core/services/upload.service.ts +++ b/lib/core/services/upload.service.ts @@ -94,7 +94,7 @@ export class UploadService { this.matchingOptions = this.appConfigService.get('files.match-options'); isAllowed = this.excludedFileList.filter((pattern) => { - let minimatch = new Minimatch(pattern, this.matchingOptions); + const minimatch = new Minimatch(pattern, this.matchingOptions); return minimatch.match(file.name); }).length === 0; } @@ -107,7 +107,7 @@ export class UploadService { */ uploadFilesInTheQueue(emitter?: EventEmitter<any>): void { if (!this.activeTask) { - let file = this.queue.find((currentFile) => currentFile.status === FileUploadStatus.Pending); + const file = this.queue.find((currentFile) => currentFile.status === FileUploadStatus.Pending); if (file) { this.onUploadStarting(file); @@ -115,7 +115,7 @@ export class UploadService { this.activeTask = promise; this.cache[file.id] = promise; - let next = () => { + const next = () => { this.activeTask = null; setTimeout(() => this.uploadFilesInTheQueue(emitter), 100); }; @@ -162,7 +162,7 @@ export class UploadService { * @returns Promise that is resolved if the upload is successful or error otherwise */ getUploadPromise(file: FileModel): any { - let opts: any = { + const opts: any = { renditions: 'doclib', include: ['allowableOperations'] }; @@ -199,7 +199,7 @@ export class UploadService { private beginUpload(file: FileModel, emitter: EventEmitter<any>): any { - let promise = this.getUploadPromise(file); + const promise = this.getUploadPromise(file); promise.on('progress', (progress: FileUploadProgress) => { this.onUploadProgress(file, progress); diff --git a/lib/core/services/user-preferences.service.ts b/lib/core/services/user-preferences.service.ts index 3602e8ae43..a3f178aa39 100644 --- a/lib/core/services/user-preferences.service.ts +++ b/lib/core/services/user-preferences.service.ts @@ -167,7 +167,7 @@ export class UserPreferencesService { * @returns Array of page size values */ get supportedPageSizes(): number[] { - let supportedPageSizes = this.get(UserPreferenceValues.SupportedPageSizes); + const supportedPageSizes = this.get(UserPreferenceValues.SupportedPageSizes); if (supportedPageSizes) { return JSON.parse(supportedPageSizes); @@ -186,7 +186,7 @@ export class UserPreferencesService { } get paginationSize(): number { - let paginationSize = this.get(UserPreferenceValues.PaginationSize); + const paginationSize = this.get(UserPreferenceValues.PaginationSize); if (paginationSize) { return Number(paginationSize); diff --git a/lib/core/settings/host-settings.component.ts b/lib/core/settings/host-settings.component.ts index ad10c69618..9b9d357b1b 100644 --- a/lib/core/settings/host-settings.component.ts +++ b/lib/core/settings/host-settings.component.ts @@ -69,7 +69,7 @@ export class HostSettingsComponent implements OnInit { this.showSelectProviders = false; } - let providerSelected = this.appConfig.get<string>(AppConfigValues.PROVIDERS); + const providerSelected = this.appConfig.get<string>(AppConfigValues.PROVIDERS); const authType = this.appConfig.get<string>(AppConfigValues.AUTHTYPE, 'BASIC'); @@ -136,7 +136,7 @@ export class HostSettingsComponent implements OnInit { } private createOAuthFormGroup(): AbstractControl { - let oauth = <OauthConfigModel> this.appConfig.get(AppConfigValues.OAUTHCONFIG, {}); + const oauth = <OauthConfigModel> this.appConfig.get(AppConfigValues.OAUTHCONFIG, {}); return this.formBuilder.group({ host: [oauth.host, [Validators.required, Validators.pattern(this.HOST_REGEX)]], diff --git a/lib/core/userinfo/components/user-info.component.spec.ts b/lib/core/userinfo/components/user-info.component.spec.ts index efbba1a055..cb57d9e206 100644 --- a/lib/core/userinfo/components/user-info.component.spec.ts +++ b/lib/core/userinfo/components/user-info.component.spec.ts @@ -74,13 +74,13 @@ describe('User info component', () => { let bpmUserService: BpmUserService; let identityUserService: IdentityUserService; - let identityUserMock = { firstName: 'fake-identity-first-name', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' }; - let identityUserWithOutFirstNameMock = { firstName: null, lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' }; - let identityUserWithOutLastNameMock = { firstName: 'fake-identity-first-name', lastName: null, email: 'fakeIdentity@email.com' }; + const identityUserMock = { firstName: 'fake-identity-first-name', lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' }; + const identityUserWithOutFirstNameMock = { firstName: null, lastName: 'fake-identity-last-name', email: 'fakeIdentity@email.com' }; + const identityUserWithOutLastNameMock = { firstName: 'fake-identity-first-name', lastName: null, email: 'fakeIdentity@email.com' }; function openUserInfo() { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); } @@ -146,11 +146,11 @@ describe('User info component', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); expect(element.querySelector('#userinfo_container')).toBeDefined(); - let ecmUsername = fixture.debugElement.query(By.css('#ecm-username')); + const ecmUsername = fixture.debugElement.query(By.css('#ecm-username')); expect(ecmUsername).toBeDefined(); expect(ecmUsername).not.toBeNull(); expect(ecmUsername.nativeElement.textContent).not.toContain('fake-ecm-first-name'); @@ -210,10 +210,10 @@ describe('User info component', () => { it('should get the ecm current user image from the service', async(() => { fixture.whenStable().then(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); - let loggedImage = fixture.debugElement.query(By.css('#logged-user-img')); + const loggedImage = fixture.debugElement.query(By.css('#logged-user-img')); expect(element.querySelector('#userinfo_container')).not.toBeNull(); expect(loggedImage).not.toBeNull(); @@ -225,10 +225,10 @@ describe('User info component', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); - let loggedImage = fixture.debugElement.query(By.css('#logged-user-img')); + const loggedImage = fixture.debugElement.query(By.css('#logged-user-img')); component.ecmUser$.subscribe((response: EcmUserModel) => { expect(response).toBeDefined(); expect(response.avatarId).toBe('fake-avatar-id'); @@ -243,12 +243,12 @@ describe('User info component', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); - let ecmImage = fixture.debugElement.query(By.css('#ecm-user-detail-image')); - let ecmFullName = fixture.debugElement.query(By.css('#ecm-full-name')); - let ecmJobTitle = fixture.debugElement.query(By.css('#ecm-job-title-label')); + const ecmImage = fixture.debugElement.query(By.css('#ecm-user-detail-image')); + const ecmFullName = fixture.debugElement.query(By.css('#ecm-full-name')); + const ecmJobTitle = fixture.debugElement.query(By.css('#ecm-job-title-label')); expect(element.querySelector('#userinfo_container')).not.toBeNull(); expect(fixture.debugElement.query(By.css('#ecm-username'))).not.toBeNull(); @@ -272,28 +272,28 @@ describe('User info component', () => { })); it('should show N/A when the job title is null', async(() => { - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#user-initials-image'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#user-initials-image'); imageButton.click(); fixture.detectChanges(); expect(element.querySelector('#userinfo_container')).not.toBeNull(); - let ecmJobTitle = fixture.debugElement.query(By.css('#ecm-job-title')); + const ecmJobTitle = fixture.debugElement.query(By.css('#ecm-job-title')); expect(ecmJobTitle).not.toBeNull(); expect(ecmJobTitle).not.toBeNull(); expect(ecmJobTitle.nativeElement.textContent).toContain('N/A'); })); it('should not show the tabs', () => { - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#user-initials-image'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#user-initials-image'); imageButton.click(); fixture.detectChanges(); - let tabHeader = fixture.debugElement.query(By.css('#tab-group-env')); + const tabHeader = fixture.debugElement.query(By.css('#tab-group-env')); expect(tabHeader.classes['adf-hide-tab']).toBeTruthy(); }); it('should display the current user Initials if the user dose not have avatarId', async(() => { fixture.whenStable().then(() => { fixture.detectChanges(); - let pipe = new InitialUsernamePipe(new FakeSanitizer()); + const pipe = new InitialUsernamePipe(new FakeSanitizer()); component.ecmUser$.subscribe((response: EcmUserModel) => { expect(response).toBeDefined(); expect(response.avatarId).toBeNull(); @@ -339,10 +339,10 @@ describe('User info component', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); - let bpmUserName = fixture.debugElement.query(By.css('#bpm-username')); + const bpmUserName = fixture.debugElement.query(By.css('#bpm-username')); expect(element.querySelector('#userinfo_container')).not.toBeNull(); expect(bpmUserName).toBeDefined(); expect(bpmUserName).not.toBeNull(); @@ -364,7 +364,7 @@ describe('User info component', () => { it('should show last name if first name is null', async(() => { fixture.detectChanges(); - let wrongBpmUser: BpmUserModel = new BpmUserModel({ + const wrongBpmUser: BpmUserModel = new BpmUserModel({ firstName: null, lastName: 'fake-last-name' }); @@ -382,7 +382,7 @@ describe('User info component', () => { })); it('should not show first name if it is null string', async(() => { - let wrongFirstNameBpmUser: BpmUserModel = new BpmUserModel({ + const wrongFirstNameBpmUser: BpmUserModel = new BpmUserModel({ firstName: 'null', lastName: 'fake-last-name' }); @@ -399,7 +399,7 @@ describe('User info component', () => { })); it('should not show last name if it is null string', async(() => { - let wrongLastNameBpmUser: BpmUserModel = new BpmUserModel({ + const wrongLastNameBpmUser: BpmUserModel = new BpmUserModel({ firstName: 'fake-first-name', lastName: 'null' }); @@ -417,7 +417,7 @@ describe('User info component', () => { it('should not show the tabs', async(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#logged-user-img'); imageButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -470,12 +470,12 @@ describe('User info component', () => { it('should get the bpm user informations from the service', async(() => { openUserInfo(); - let bpmTab = fixture.debugElement.queryAll(By.css('#tab-group-env .mat-tab-labels .mat-tab-label'))[1]; + const bpmTab = fixture.debugElement.queryAll(By.css('#tab-group-env .mat-tab-labels .mat-tab-label'))[1]; bpmTab.triggerEventHandler('click', null); fixture.detectChanges(); fixture.whenStable().then(() => { - let bpmUsername = fixture.debugElement.query(By.css('#bpm-username')); - let bpmImage = fixture.debugElement.query(By.css('#bpm-user-detail-image')); + const bpmUsername = fixture.debugElement.query(By.css('#bpm-username')); + const bpmImage = fixture.debugElement.query(By.css('#bpm-user-detail-image')); expect(element.querySelector('#userinfo_container')).not.toBeNull(); expect(bpmUsername).not.toBeNull(); expect(bpmImage).not.toBeNull(); @@ -487,8 +487,8 @@ describe('User info component', () => { it('should get the ecm user informations from the service', async(() => { openUserInfo(); - let ecmUsername = fixture.debugElement.query(By.css('#ecm-username')); - let ecmImage = fixture.debugElement.query(By.css('#ecm-user-detail-image')); + const ecmUsername = fixture.debugElement.query(By.css('#ecm-username')); + const ecmImage = fixture.debugElement.query(By.css('#ecm-user-detail-image')); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -521,8 +521,8 @@ describe('User info component', () => { it('should show the tabs for the env', () => { openUserInfo(); - let tabGroup = fixture.debugElement.query(By.css('#tab-group-env')); - let tabs = fixture.debugElement.queryAll(By.css('#tab-group-env .mat-tab-labels .mat-tab-label')); + const tabGroup = fixture.debugElement.query(By.css('#tab-group-env')); + const tabs = fixture.debugElement.queryAll(By.css('#tab-group-env .mat-tab-labels .mat-tab-label')); expect(tabGroup).not.toBeNull(); expect(tabGroup.classes['adf-hide-tab']).toBeFalsy(); @@ -531,8 +531,8 @@ describe('User info component', () => { it('should not close the menu when a tab is clicked', () => { openUserInfo(); - let tabGroup = fixture.debugElement.query(By.css('#tab-group-env')); - let tabs = fixture.debugElement.queryAll(By.css('#tab-group-env .mat-tab-labels .mat-tab-label')); + const tabGroup = fixture.debugElement.query(By.css('#tab-group-env')); + const tabs = fixture.debugElement.queryAll(By.css('#tab-group-env .mat-tab-labels .mat-tab-label')); expect(tabGroup).not.toBeNull(); tabs[1].triggerEventHandler('click', null); @@ -568,10 +568,10 @@ describe('User info component', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#identity-user-image'); + const imageButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#identity-user-image'); imageButton.click(); fixture.detectChanges(); - let bpmUserName = element.querySelector('#identity-username'); + const bpmUserName = element.querySelector('#identity-username'); fixture.detectChanges(); expect(element.querySelector('#userinfo_container')).not.toBeNull(); expect(bpmUserName).toBeDefined(); @@ -582,7 +582,7 @@ describe('User info component', () => { it('should show last name if first name is null', async(() => { fixture.detectChanges(); - let fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutFirstNameMock); + const fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutFirstNameMock); getCurrentUserInfoStub.and.returnValue(fakeIdentityUser); fixture.detectChanges(); @@ -597,7 +597,7 @@ describe('User info component', () => { })); it('should not show first name if it is null string', async(() => { - let fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutFirstNameMock); + const fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutFirstNameMock); getCurrentUserInfoStub.and.returnValue(of(fakeIdentityUser)); fixture.detectChanges(); @@ -612,7 +612,7 @@ describe('User info component', () => { })); it('should not show last name if it is null string', async(() => { - let fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutLastNameMock); + const fakeIdentityUser: IdentityUserModel = new IdentityUserModel(identityUserWithOutLastNameMock); getCurrentUserInfoStub.and.returnValue(of(fakeIdentityUser)); fixture.detectChanges(); diff --git a/lib/core/userinfo/services/bpm-user.service.spec.ts b/lib/core/userinfo/services/bpm-user.service.spec.ts index 76629b6ebd..9a3c6c8cef 100644 --- a/lib/core/userinfo/services/bpm-user.service.spec.ts +++ b/lib/core/userinfo/services/bpm-user.service.spec.ts @@ -74,7 +74,7 @@ describe('Bpm user service', () => { }); it('should retrieve avatar url for current user', () => { - let path = service.getCurrentUserProfileImage(); + const path = service.getCurrentUserProfileImage(); expect(path).toBeDefined(); expect(path).toContain('/app/rest/admin/profile-picture'); }); diff --git a/lib/core/userinfo/services/ecm-user.service.spec.ts b/lib/core/userinfo/services/ecm-user.service.spec.ts index 76a7d85e0d..41160ecdc1 100644 --- a/lib/core/userinfo/services/ecm-user.service.spec.ts +++ b/lib/core/userinfo/services/ecm-user.service.spec.ts @@ -89,14 +89,14 @@ describe('EcmUserService', () => { it('should retrieve avatar url for current user', () => { spyOn(contentService, 'getContentUrl').and.returnValue('fake/url/image/for/ecm/user'); - let urlRs = service.getUserProfileImage('fake-avatar-id'); + const urlRs = service.getUserProfileImage('fake-avatar-id'); expect(urlRs).toEqual('fake/url/image/for/ecm/user'); }); it('should not call content service without avatar id', () => { spyOn(contentService, 'getContentUrl').and.callThrough(); - let urlRs = service.getUserProfileImage(undefined); + const urlRs = service.getUserProfileImage(undefined); expect(urlRs).toBeUndefined(); expect(contentService.getContentUrl).not.toHaveBeenCalled(); @@ -104,7 +104,7 @@ describe('EcmUserService', () => { it('should build the body for the content service', () => { spyOn(contentService, 'getContentUrl').and.callThrough(); - let urlRs = service.getUserProfileImage('fake-avatar-id'); + const urlRs = service.getUserProfileImage('fake-avatar-id'); expect(urlRs).toBeDefined(); expect(contentService.getContentUrl).toHaveBeenCalledWith({entry: {id: 'fake-avatar-id'}}); diff --git a/lib/core/userinfo/services/ecm-user.service.ts b/lib/core/userinfo/services/ecm-user.service.ts index bde9af5531..f51f1b0c3f 100644 --- a/lib/core/userinfo/services/ecm-user.service.ts +++ b/lib/core/userinfo/services/ecm-user.service.ts @@ -64,7 +64,7 @@ export class EcmUserService { */ getUserProfileImage(avatarId: string) { if (avatarId) { - let nodeObj = {entry: {id: avatarId}}; + const nodeObj = {entry: {id: avatarId}}; return this.contentService.getContentUrl(nodeObj); } } diff --git a/lib/core/userinfo/services/identity-user.service.spec.ts b/lib/core/userinfo/services/identity-user.service.spec.ts index 4c21a44230..545ac498b2 100644 --- a/lib/core/userinfo/services/identity-user.service.spec.ts +++ b/lib/core/userinfo/services/identity-user.service.spec.ts @@ -54,7 +54,7 @@ describe('IdentityUserService', () => { }); beforeEach(() => { - let store = {}; + const store = {}; spyOn(localStorage, 'getItem').and.callFake( (key: string): String => { return store[key] || null; diff --git a/lib/core/utils/file-utils.ts b/lib/core/utils/file-utils.ts index 45447ae518..420c8849f3 100644 --- a/lib/core/utils/file-utils.ts +++ b/lib/core/utils/file-utils.ts @@ -24,10 +24,10 @@ export interface FileInfo { export class FileUtils { static flatten(folder: any): Promise<FileInfo[]> { - let reader = folder.createReader(); - let files: FileInfo[] = []; + const reader = folder.createReader(); + const files: FileInfo[] = []; return new Promise((resolve) => { - let iterations = []; + const iterations = []; (function traverse() { reader.readEntries((entries) => { if (!entries.length) { @@ -60,7 +60,7 @@ export class FileUtils { } static toFileArray(fileList: FileList): File[] { - let result = []; + const result = []; if (fileList && fileList.length > 0) { for (let i = 0; i < fileList.length; i++) { diff --git a/lib/core/utils/momentDateAdapter.ts b/lib/core/utils/momentDateAdapter.ts index a51f818d83..a640ec593e 100644 --- a/lib/core/utils/momentDateAdapter.ts +++ b/lib/core/utils/momentDateAdapter.ts @@ -89,7 +89,7 @@ export class MomentDateAdapter extends DateAdapter<Moment> { } clone(date: Moment): Moment { - let locale = this.locale || 'en'; + const locale = this.locale || 'en'; return date.clone().locale(locale); } @@ -98,12 +98,12 @@ export class MomentDateAdapter extends DateAdapter<Moment> { } today(): Moment { - let locale = this.locale || 'en'; + const locale = this.locale || 'en'; return moment().locale(locale); } parse(value: any, parseFormat: any): Moment { - let locale = this.locale || 'en'; + const locale = this.locale || 'en'; if (value && typeof value === 'string') { let m = moment(value, parseFormat, locale, true); @@ -207,8 +207,8 @@ export class MomentDateAdapter extends DateAdapter<Moment> { } fromIso8601(iso8601String: string): Moment | null { - let locale = this.locale || 'en'; - let d = moment(iso8601String, moment.ISO_8601).locale(locale); + const locale = this.locale || 'en'; + const d = moment(iso8601String, moment.ISO_8601).locale(locale); return this.isValid(d) ? d : null; } diff --git a/lib/core/utils/object-utils.spec.ts b/lib/core/utils/object-utils.spec.ts index 77710600b8..ddd27d6d6b 100644 --- a/lib/core/utils/object-utils.spec.ts +++ b/lib/core/utils/object-utils.spec.ts @@ -20,19 +20,19 @@ import { ObjectUtils } from './object-utils'; describe('ObjectUtils', () => { it('should get top level property value', () => { - let obj = { + const obj = { id: 1 }; expect(ObjectUtils.getValue(obj, 'id')).toBe(1); }); it('should not get top level property value', () => { - let obj = {}; + const obj = {}; expect(ObjectUtils.getValue(obj, 'missing')).toBeUndefined(); }); it('should get nested property value', () => { - let obj = { + const obj = { name: { firstName: 'John', lastName: 'Doe' @@ -43,7 +43,7 @@ describe('ObjectUtils', () => { }); it('should not get nested property value', () => { - let obj = {}; + const obj = {}; expect(ObjectUtils.getValue(obj, 'some.missing.property')).toBeUndefined(); }); diff --git a/lib/core/utils/object-utils.ts b/lib/core/utils/object-utils.ts index 1e01ec4a55..81af91ed27 100644 --- a/lib/core/utils/object-utils.ts +++ b/lib/core/utils/object-utils.ts @@ -28,12 +28,12 @@ export class ObjectUtils { return undefined; } - let keys = key.split('.'); + const keys = key.split('.'); key = ''; do { key += keys.shift(); - let value = target[key]; + const value = target[key]; if (value !== undefined && (typeof value === 'object' || !keys.length)) { target = value; key = ''; @@ -48,7 +48,7 @@ export class ObjectUtils { } static merge(...objects): any { - let result = {}; + const result = {}; objects.forEach((source) => { Object.keys(source).forEach((prop) => { diff --git a/lib/core/viewer/components/imgViewer.component.spec.ts b/lib/core/viewer/components/imgViewer.component.spec.ts index fc0afe317a..d5cf5bac2d 100644 --- a/lib/core/viewer/components/imgViewer.component.spec.ts +++ b/lib/core/viewer/components/imgViewer.component.spec.ts @@ -31,7 +31,7 @@ describe('Test Img viewer component ', () => { let element: HTMLElement; function createFakeBlob() { - let data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); + const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); return new Blob([data], {type: 'image/png'}); } @@ -221,7 +221,7 @@ describe('Test Img viewer component ', () => { }); it('If no url or blob are passed should thrown an error', () => { - let change = new SimpleChange(null, null, true); + const change = new SimpleChange(null, null, true); expect(() => { component.ngOnChanges({ 'blobFile': change }); }).toThrow(new Error('Attribute urlFile or blobFile is required')); @@ -241,10 +241,10 @@ describe('Test Img viewer component ', () => { }); it('If blob is passed should not thrown an error', () => { - let blob = createFakeBlob(); + const blob = createFakeBlob(); spyOn(service, 'createTrustedUrl').and.returnValue('fake-blob-url'); - let change = new SimpleChange(null, blob, true); + const change = new SimpleChange(null, blob, true); expect(() => { component.ngOnChanges({ 'blobFile': change }); }).not.toThrow(new Error('Attribute urlFile or blobFile is required')); diff --git a/lib/core/viewer/components/imgViewer.component.ts b/lib/core/viewer/components/imgViewer.component.ts index f389a8a761..e6c176cd76 100644 --- a/lib/core/viewer/components/imgViewer.component.ts +++ b/lib/core/viewer/components/imgViewer.component.ts @@ -132,7 +132,7 @@ export class ImgViewerComponent implements OnInit, OnChanges, OnDestroy { } ngOnChanges(changes: SimpleChanges) { - let blobFile = changes['blobFile']; + const blobFile = changes['blobFile']; if (blobFile && blobFile.currentValue) { this.urlFile = this.contentService.createTrustedUrl(this.blobFile); return; diff --git a/lib/core/viewer/components/mediaPlayer.component.spec.ts b/lib/core/viewer/components/mediaPlayer.component.spec.ts index 251e2a13c2..3998491d07 100644 --- a/lib/core/viewer/components/mediaPlayer.component.spec.ts +++ b/lib/core/viewer/components/mediaPlayer.component.spec.ts @@ -29,7 +29,7 @@ xdescribe('Test Media player component ', () => { let fixture: ComponentFixture<MediaPlayerComponent>; function createFakeBlob() { - let data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); + const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); return new Blob([data], {type: 'image/png'}); } @@ -73,10 +73,10 @@ xdescribe('Test Media player component ', () => { }); it('should not thrown an error If blob is passed', () => { - let blob = createFakeBlob(); + const blob = createFakeBlob(); spyOn(service, 'createTrustedUrl').and.returnValue('fake-blob-url'); - let change = new SimpleChange(null, blob, true); + const change = new SimpleChange(null, blob, true); expect(() => { component.ngOnChanges({ 'blobFile': change }); }).not.toThrow(new Error('Attribute urlFile or blobFile is required')); diff --git a/lib/core/viewer/components/mediaPlayer.component.ts b/lib/core/viewer/components/mediaPlayer.component.ts index e65461ddbb..64e4bbc58e 100644 --- a/lib/core/viewer/components/mediaPlayer.component.ts +++ b/lib/core/viewer/components/mediaPlayer.component.ts @@ -42,7 +42,7 @@ export class MediaPlayerComponent implements OnChanges { constructor(private contentService: ContentService ) {} ngOnChanges(changes: SimpleChanges) { - let blobFile = changes['blobFile']; + const blobFile = changes['blobFile']; if (blobFile && blobFile.currentValue) { this.urlFile = this.contentService.createTrustedUrl(this.blobFile); return; diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index 58ef24d538..4bea4af833 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -98,7 +98,7 @@ class BlobTestComponent { } createFakeBlob(): Blob { - let pdfData = atob( + const pdfData = atob( 'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' + 'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' + 'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' + @@ -350,7 +350,7 @@ describe('Test PdfViewer component', () => { }, 5000); it('should nextPage move to the next page', (done) => { - let nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); + const nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); nextPageButton.click(); fixtureUrlTestComponent.detectChanges(); @@ -391,8 +391,8 @@ describe('Test PdfViewer component', () => { }, 5000); it('should previous page move to the previous page', (done) => { - let previousPageButton: any = elementUrlTestComponent.querySelector('#viewer-previous-page-button'); - let nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); + const previousPageButton: any = elementUrlTestComponent.querySelector('#viewer-previous-page-button'); + const nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); nextPageButton.click(); nextPageButton.click(); @@ -428,27 +428,27 @@ describe('Test PdfViewer component', () => { describe('Zoom', () => { it('should zoom in increment the scale value', () => { - let zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); + const zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); - let zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; + const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; zoomInButton.click(); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - let currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; + const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; expect(zoomBefore < currentZoom).toBe(true); }, 5000); it('should zoom out decrement the scale value', () => { - let zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); + const zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); - let zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; + const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; zoomOutButton.click(); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - let currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; + const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; expect(zoomBefore > currentZoom).toBe(true); }, 5000); it('should it-in button toggle page-fit and auto scale mode', () => { - let itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); + const itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); itPage.click(); diff --git a/lib/core/viewer/components/pdfViewer.component.ts b/lib/core/viewer/components/pdfViewer.component.ts index 42fb582202..20896055ab 100644 --- a/lib/core/viewer/components/pdfViewer.component.ts +++ b/lib/core/viewer/components/pdfViewer.component.ts @@ -155,7 +155,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { }; this.loadingTask.onProgress = (progressData) => { - let level = progressData.loaded / progressData.total; + const level = progressData.loaded / progressData.total; this.loadingPercent = Math.round(level * 100); }; @@ -237,8 +237,8 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { if (this.pdfViewer) { - let viewerContainer = document.getElementById(`${this.randomPdfId}-viewer-main-container`); - let documentContainer = document.getElementById(`${this.randomPdfId}-viewer-pdf-viewer`); + const viewerContainer = document.getElementById(`${this.randomPdfId}-viewer-main-container`); + const documentContainer = document.getElementById(`${this.randomPdfId}-viewer-pdf-viewer`); let widthContainer; let heightContainer; @@ -251,11 +251,11 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { heightContainer = documentContainer.clientHeight; } - let currentPage = this.pdfViewer._pages[this.pdfViewer._currentPageNumber - 1]; + const currentPage = this.pdfViewer._pages[this.pdfViewer._currentPageNumber - 1]; - let padding = 20; - let pageWidthScale = (widthContainer - padding) / currentPage.width * currentPage.scale; - let pageHeightScale = (heightContainer - padding) / currentPage.width * currentPage.scale; + const padding = 20; + const pageWidthScale = (widthContainer - padding) / currentPage.width * currentPage.scale; + const pageHeightScale = (heightContainer - padding) / currentPage.width * currentPage.scale; let scale; @@ -409,7 +409,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { * @param page to load */ inputPage(page: string) { - let pageInput = parseInt(page, 10); + const pageInput = parseInt(page, 10); if (!isNaN(pageInput) && pageInput > 0 && pageInput <= this.totalPages) { this.page = pageInput; @@ -466,7 +466,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { */ @HostListener('document:keydown', ['$event']) handleKeyboardEvent(event: KeyboardEvent) { - let key = event.keyCode; + const key = event.keyCode; if (key === 39) { // right arrow this.nextPage(); } else if (key === 37) {// left arrow @@ -476,7 +476,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { private generateUuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); + const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } diff --git a/lib/core/viewer/components/txtViewer.component.spec.ts b/lib/core/viewer/components/txtViewer.component.spec.ts index f30ea9a275..d502c02e26 100644 --- a/lib/core/viewer/components/txtViewer.component.spec.ts +++ b/lib/core/viewer/components/txtViewer.component.spec.ts @@ -44,8 +44,8 @@ describe('Text View component', () => { it('Should text container be present with urlFile', (done) => { fixture.detectChanges(); - let urlFile = './fake-test-file.txt'; - let change = new SimpleChange(null, urlFile, true); + const urlFile = './fake-test-file.txt'; + const change = new SimpleChange(null, urlFile, true); component.ngOnChanges({ 'urlFile': change }).then(() => { fixture.detectChanges(); @@ -57,9 +57,9 @@ describe('Text View component', () => { }); it('Should text container be present with Blob file', (done) => { - let blobFile = new Blob(['text example'], {type: 'text/txt'}); + const blobFile = new Blob(['text example'], {type: 'text/txt'}); - let change = new SimpleChange(null, blobFile, true); + const change = new SimpleChange(null, blobFile, true); component.ngOnChanges({ 'blobFile': change }).then(() => { fixture.detectChanges(); diff --git a/lib/core/viewer/components/txtViewer.component.ts b/lib/core/viewer/components/txtViewer.component.ts index 23f4331442..86e3be70e6 100644 --- a/lib/core/viewer/components/txtViewer.component.ts +++ b/lib/core/viewer/components/txtViewer.component.ts @@ -42,12 +42,12 @@ export class TxtViewerComponent implements OnChanges { ngOnChanges(changes: SimpleChanges): Promise<any> { - let blobFile = changes['blobFile']; + const blobFile = changes['blobFile']; if (blobFile && blobFile.currentValue) { return this.readBlob(blobFile.currentValue); } - let urlFile = changes['urlFile']; + const urlFile = changes['urlFile']; if (urlFile && urlFile.currentValue) { return this.getUrlContent(urlFile.currentValue); } @@ -58,7 +58,7 @@ export class TxtViewerComponent implements OnChanges { } private getUrlContent(url: string): Promise<any> { - let withCredentialsMode = this.appConfigService.get<boolean>('auth.withCredentials', false); + const withCredentialsMode = this.appConfigService.get<boolean>('auth.withCredentials', false); return new Promise((resolve, reject) => { this.http.get(url, { responseType: 'text', withCredentials: withCredentialsMode }).subscribe((res) => { @@ -72,7 +72,7 @@ export class TxtViewerComponent implements OnChanges { private readBlob(blob: Blob): Promise<any> { return new Promise((resolve, reject) => { - let reader = new FileReader(); + const reader = new FileReader(); reader.onload = () => { this.content = reader.result; diff --git a/lib/core/viewer/components/viewer.component.spec.ts b/lib/core/viewer/components/viewer.component.spec.ts index a1d4cd31e4..a9865e1b30 100644 --- a/lib/core/viewer/components/viewer.component.spec.ts +++ b/lib/core/viewer/components/viewer.component.spec.ts @@ -395,8 +395,8 @@ describe('ViewerComponent', () => { describe('Viewer Example Component Rendering', () => { it('should use custom toolbar', (done) => { - let customFixture = TestBed.createComponent(ViewerWithCustomToolbarComponent); - let customElement: HTMLElement = customFixture.nativeElement; + const customFixture = TestBed.createComponent(ViewerWithCustomToolbarComponent); + const customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); fixture.whenStable().then(() => { @@ -406,8 +406,8 @@ describe('ViewerComponent', () => { }); it('should use custom toolbar actions', (done) => { - let customFixture = TestBed.createComponent(ViewerWithCustomToolbarActionsComponent); - let customElement: HTMLElement = customFixture.nativeElement; + const customFixture = TestBed.createComponent(ViewerWithCustomToolbarActionsComponent); + const customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); fixture.whenStable().then(() => { @@ -417,8 +417,8 @@ describe('ViewerComponent', () => { }); it('should use custom info drawer', (done) => { - let customFixture = TestBed.createComponent(ViewerWithCustomSidebarComponent); - let customElement: HTMLElement = customFixture.nativeElement; + const customFixture = TestBed.createComponent(ViewerWithCustomSidebarComponent); + const customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); @@ -429,8 +429,8 @@ describe('ViewerComponent', () => { }); it('should use custom open with menu', (done) => { - let customFixture = TestBed.createComponent(ViewerWithCustomOpenWithComponent); - let customElement: HTMLElement = customFixture.nativeElement; + const customFixture = TestBed.createComponent(ViewerWithCustomOpenWithComponent); + const customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); @@ -441,8 +441,8 @@ describe('ViewerComponent', () => { }); it('should use custom more actions menu', (done) => { - let customFixture = TestBed.createComponent(ViewerWithCustomMoreActionsComponent); - let customElement: HTMLElement = customFixture.nativeElement; + const customFixture = TestBed.createComponent(ViewerWithCustomMoreActionsComponent); + const customElement: HTMLElement = customFixture.nativeElement; customFixture.detectChanges(); @@ -472,7 +472,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let sidebar = element.querySelector('#adf-right-sidebar'); + const sidebar = element.querySelector('#adf-right-sidebar'); expect(sidebar).toBeNull(); done(); }); @@ -484,7 +484,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let sidebar = element.querySelector('#adf-right-sidebar'); + const sidebar = element.querySelector('#adf-right-sidebar'); expect(getComputedStyle(sidebar).order).toEqual('4'); done(); }); @@ -496,7 +496,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let sidebar = element.querySelector('#adf-left-sidebar'); + const sidebar = element.querySelector('#adf-left-sidebar'); expect(sidebar).toBeNull(); done(); }); @@ -509,7 +509,7 @@ describe('ViewerComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let sidebar = element.querySelector('#adf-left-sidebar'); + const sidebar = element.querySelector('#adf-left-sidebar'); expect(getComputedStyle(sidebar).order).toEqual('1'); done(); }); @@ -658,7 +658,7 @@ describe('ViewerComponent', () => { }); it('should Click on close button hide the viewer', (done) => { - let closebutton: any = element.querySelector('.adf-viewer-close-button'); + const closebutton: any = element.querySelector('.adf-viewer-close-button'); closebutton.click(); fixture.detectChanges(); diff --git a/lib/core/viewer/components/viewer.component.ts b/lib/core/viewer/components/viewer.component.ts index 9afd1ec919..30787a25a4 100644 --- a/lib/core/viewer/components/viewer.component.ts +++ b/lib/core/viewer/components/viewer.component.ts @@ -332,7 +332,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { } private setUpUrlFile() { - let filenameFromUrl = this.getFilenameFromUrl(this.urlFile); + const filenameFromUrl = this.getFilenameFromUrl(this.urlFile); this.fileTitle = this.getDisplayName(filenameFromUrl); this.extension = this.getFileExtension(filenameFromUrl); this.urlFileContent = this.urlFile; @@ -434,7 +434,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { mimeType = mimeType.toLowerCase(); const editorTypes = Object.keys(this.mimeTypes); - for (let type of editorTypes) { + for (const type of editorTypes) { if (this.mimeTypes[type].indexOf(mimeType) >= 0) { return type; } @@ -509,9 +509,9 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { * @param url - url file */ getFilenameFromUrl(url: string): string { - let anchor = url.indexOf('#'); - let query = url.indexOf('?'); - let end = Math.min( + const anchor = url.indexOf('#'); + const query = url.indexOf('?'); + const end = Math.min( anchor > 0 ? anchor : url.length, query > 0 ? query : url.length); return url.substring(url.lastIndexOf('/', end) + 1, end); @@ -679,7 +679,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { private async waitRendition(nodeId: string, renditionId: string): Promise<RenditionEntry> { let currentRetry: number = 0; return new Promise<RenditionEntry>((resolve, reject) => { - let intervalId = setInterval(() => { + const intervalId = setInterval(() => { currentRetry++; if (this.maxRetries >= currentRetry) { this.apiService.renditionsApi.getRendition(nodeId, renditionId).then((rendition: RenditionEntry) => { diff --git a/lib/core/viewer/services/rendering-queue.services.ts b/lib/core/viewer/services/rendering-queue.services.ts index c0e47b965c..61482cdb21 100644 --- a/lib/core/viewer/services/rendering-queue.services.ts +++ b/lib/core/viewer/services/rendering-queue.services.ts @@ -98,14 +98,14 @@ export class RenderingQueueServices { // 1 visible pages // 2 if last scrolled down page after the visible pages // 2 if last scrolled up page before the visible pages - let visibleViews = visible.views; + const visibleViews = visible.views; - let numVisible = visibleViews.length; + const numVisible = visibleViews.length; if (numVisible === 0) { return false; } for (let i = 0; i < numVisible; ++i) { - let view = visibleViews[i].view; + const view = visibleViews[i].view; if (!this.isViewFinished(view)) { return view; } @@ -113,13 +113,13 @@ export class RenderingQueueServices { // All the visible views have rendered, try to render next/previous pages. if (scrolledDown) { - let nextPageIndex = visible.last.id; + const nextPageIndex = visible.last.id; // ID's start at 1 so no need to add 1. if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex])) { return views[nextPageIndex]; } } else { - let previousPageIndex = visible.first.id - 2; + const previousPageIndex = visible.first.id - 2; if (views[previousPageIndex] && !this.isViewFinished(views[previousPageIndex])) { return views[previousPageIndex]; } @@ -142,7 +142,7 @@ export class RenderingQueueServices { * @param view */ renderView(view: any) { - let state = view.renderingState; + const state = view.renderingState; switch (state) { case this.renderingStates.FINISHED: return false; @@ -155,7 +155,7 @@ export class RenderingQueueServices { break; case this.renderingStates.INITIAL: this.highestPriorityPage = view.renderingId; - let continueRendering = function () { + const continueRendering = function () { this.renderHighestPriority(); }.bind(this); view.draw().then(continueRendering, continueRendering); diff --git a/lib/extensions/src/lib/services/extension.service.ts b/lib/extensions/src/lib/services/extension.service.ts index 4e4d1b114c..c24b6ec20b 100644 --- a/lib/extensions/src/lib/services/extension.service.ts +++ b/lib/extensions/src/lib/services/extension.service.ts @@ -92,7 +92,7 @@ export class ExtensionService { * @returns Features array found by key */ getFeature(key: string): any[] { - let properties: string[] = Array.isArray(key) ? [key] : key.split('.'); + const properties: string[] = Array.isArray(key) ? [key] : key.split('.'); return properties.reduce((prev, curr) => prev && prev[curr], this.features) || []; } diff --git a/lib/insights/analytics-process/components/analytics-generator.component.ts b/lib/insights/analytics-process/components/analytics-generator.component.ts index 3658f25c2c..7a3bb1888e 100644 --- a/lib/insights/analytics-process/components/analytics-generator.component.ts +++ b/lib/insights/analytics-process/components/analytics-generator.component.ts @@ -104,7 +104,7 @@ export class AnalyticsGeneratorComponent implements OnChanges { * so one way around it, is to clone the data, change it and then * assign it; */ - let clone = JSON.parse(JSON.stringify(report)); + const clone = JSON.parse(JSON.stringify(report)); report.datasets = clone.datasets; } diff --git a/lib/insights/analytics-process/components/analytics-report-heat-map.component.spec.ts b/lib/insights/analytics-process/components/analytics-report-heat-map.component.spec.ts index 6f2a1a2101..1f01bdc5b0 100644 --- a/lib/insights/analytics-process/components/analytics-report-heat-map.component.spec.ts +++ b/lib/insights/analytics-process/components/analytics-report-heat-map.component.spec.ts @@ -28,13 +28,13 @@ describe('AnalyticsReportHeatMapComponent', () => { let fixture: ComponentFixture<AnalyticsReportHeatMapComponent>; let element: HTMLElement; - let totalCountPercent: any = { 'sid-fake-id': 0, 'fake-start-event': 100 }; - let totalTimePercent: any = { 'sid-fake-id': 10, 'fake-start-event': 30 }; - let avgTimePercentages: any = { 'sid-fake-id': 5, 'fake-start-event': 50 }; + const totalCountPercent: any = { 'sid-fake-id': 0, 'fake-start-event': 100 }; + const totalTimePercent: any = { 'sid-fake-id': 10, 'fake-start-event': 30 }; + const avgTimePercentages: any = { 'sid-fake-id': 5, 'fake-start-event': 50 }; - let totalCountValues: any = { 'sid-fake-id': 2, 'fake-start-event': 3 }; - let totalTimeValues: any = { 'sid-fake-id': 1, 'fake-start-event': 4 }; - let avgTimeValues: any = { 'sid-fake-id': 4, 'fake-start-event': 5 }; + const totalCountValues: any = { 'sid-fake-id': 2, 'fake-start-event': 3 }; + const totalTimeValues: any = { 'sid-fake-id': 1, 'fake-start-event': 4 }; + const avgTimeValues: any = { 'sid-fake-id': 4, 'fake-start-event': 5 }; setupTestBed({ imports: [InsightsTestingModule] @@ -70,7 +70,7 @@ describe('AnalyticsReportHeatMapComponent', () => { component.success.subscribe(() => { fixture.whenStable().then(() => { - let dropDown: any = element.querySelector('#select-metrics'); + const dropDown: any = element.querySelector('#select-metrics'); expect(dropDown).toBeDefined(); expect(dropDown.length).toEqual(3); expect(dropDown[0].innerHTML).toEqual('Number of times a step is executed'); @@ -91,21 +91,21 @@ describe('AnalyticsReportHeatMapComponent', () => { })); it('should change the currentMetric width totalCount', async(() => { - let field = { value: 'totalCount' }; + const field = { value: 'totalCount' }; component.onMetricChanges(field); expect(component.currentMetric).toEqual(totalCountValues); expect(component.currentMetricColors).toEqual(totalCountPercent); })); it('should change the currentMetric width totalTime', async(() => { - let field = { value: 'totalTime' }; + const field = { value: 'totalTime' }; component.onMetricChanges(field); expect(component.currentMetric).toEqual(totalTimeValues); expect(component.currentMetricColors).toEqual(totalTimePercent); })); it('should change the currentMetric width avgTime', async(() => { - let field = { value: 'avgTime' }; + const field = { value: 'avgTime' }; component.onMetricChanges(field); expect(component.currentMetric).toEqual(avgTimeValues); expect(component.currentMetricColors).toEqual(avgTimePercentages); diff --git a/lib/insights/analytics-process/components/analytics-report-list.component.spec.ts b/lib/insights/analytics-process/components/analytics-report-list.component.spec.ts index 88fc118d72..3244c9dd3f 100644 --- a/lib/insights/analytics-process/components/analytics-report-list.component.spec.ts +++ b/lib/insights/analytics-process/components/analytics-report-list.component.spec.ts @@ -25,7 +25,7 @@ declare let jasmine: any; describe('AnalyticsReportListComponent', () => { - let reportList = [ + const reportList = [ { 'id': 2002, 'name': 'Fake Test Process definition heat map' }, { 'id': 2003, 'name': 'Fake Test Process definition overview' }, { 'id': 2004, 'name': 'Fake Test Process instances overview' }, @@ -33,7 +33,7 @@ describe('AnalyticsReportListComponent', () => { { 'id': 2006, 'name': 'Fake Test Task service level agreement' } ]; - let reportSelected = { 'id': 2003, 'name': 'Fake Test Process definition overview' }; + const reportSelected = { 'id': 2003, 'name': 'Fake Test Process definition overview' }; let component: AnalyticsReportListComponent; let fixture: ComponentFixture<AnalyticsReportListComponent>; @@ -155,13 +155,13 @@ describe('AnalyticsReportListComponent', () => { it('Should return false if the current report is different', () => { component.selectReport(reportSelected); - let anotherReport = { 'id': 111, 'name': 'Another Fake Test Process definition overview' }; + const anotherReport = { 'id': 111, 'name': 'Another Fake Test Process definition overview' }; expect(component.isSelected(anotherReport)).toBe(false); }); it('Should reload the report list', (done) => { component.initObserver(); - let report = new ReportParametersModel({ 'id': 2002, 'name': 'Fake Test Process definition heat map' }); + const report = new ReportParametersModel({ 'id': 2002, 'name': 'Fake Test Process definition heat map' }); component.reports = [report]; expect(component.reports.length).toEqual(1); component.reload(); diff --git a/lib/insights/analytics-process/components/analytics-report-list.component.ts b/lib/insights/analytics-process/components/analytics-report-list.component.ts index aab26a7097..8b8bd91d52 100644 --- a/lib/insights/analytics-process/components/analytics-report-list.component.ts +++ b/lib/insights/analytics-process/components/analytics-report-list.component.ts @@ -153,7 +153,7 @@ export class AnalyticsReportListComponent implements OnInit { } public selectReportByReportId(reportId) { - let reportFound = this.reports.find((report) => report.id === reportId); + const reportFound = this.reports.find((report) => report.id === reportId); if (reportFound) { this.currentReport = reportFound; this.reportClick.emit(reportFound); diff --git a/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts b/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts index 8f9b1398b7..745ca13f64 100644 --- a/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts +++ b/lib/insights/analytics-process/components/analytics-report-parameters.component.spec.ts @@ -60,7 +60,7 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should initialize the Report form with a Form Group ', (done) => { - let fakeReportParam = new ReportParametersModel(analyticParamsMock.reportDefParamTask); + const fakeReportParam = new ReportParametersModel(analyticParamsMock.reportDefParamTask); component.successReportParams.subscribe(() => { fixture.detectChanges(); expect(component.reportForm.get('taskGroup')).toBeDefined(); @@ -73,7 +73,7 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a dropdown with all the status when the definition parameter type is \'status\' ', (done) => { component.successReportParams.subscribe(() => { fixture.detectChanges(); - let dropDown: any = element.querySelector('#select-status'); + const dropDown: any = element.querySelector('#select-status'); expect(element.querySelector('h4').textContent.trim()).toEqual('Fake Task overview status'); expect(dropDown).toBeDefined(); expect(dropDown.length).toEqual(4); @@ -84,8 +84,8 @@ describe('AnalyticsReportParametersComponent', () => { done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -98,14 +98,14 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a number with the default value when the definition parameter type is \'integer\' ', (done) => { component.successReportParams.subscribe(() => { fixture.detectChanges(); - let numberElement: any = element.querySelector('#slowProcessInstanceInteger'); + const numberElement: any = element.querySelector('#slowProcessInstanceInteger'); expect(numberElement.value).toEqual('10'); done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -118,10 +118,10 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a duration component when the definition parameter type is \'duration\' ', (done) => { component.successReportParams.subscribe(() => { fixture.detectChanges(); - let numberElement: any = element.querySelector('#duration'); + const numberElement: any = element.querySelector('#duration'); expect(numberElement.value).toEqual('0'); - let dropDown: any = element.querySelector('#select-duration'); + const dropDown: any = element.querySelector('#select-duration'); expect(dropDown).toBeDefined(); expect(dropDown.length).toEqual(4); expect(dropDown[0].innerHTML).toEqual('Seconds'); @@ -131,8 +131,8 @@ describe('AnalyticsReportParametersComponent', () => { done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -155,7 +155,7 @@ describe('AnalyticsReportParametersComponent', () => { expect(res.typeFiltering).toEqual(true); }); - let values: any = { + const values: any = { dateRange: { startDate: '2016-09-01', endDate: '2016-10-05' }, @@ -188,13 +188,13 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a checkbox with the value true when the definition parameter type is \'boolean\' ', (done) => { component.successReportParams.subscribe(() => { fixture.detectChanges(); - let checkElement: any = element.querySelector('#typeFiltering-input'); + const checkElement: any = element.querySelector('#typeFiltering-input'); expect(checkElement.checked).toBeTruthy(); done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -206,13 +206,13 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a date range components when the definition parameter type is \'dateRange\' ', (done) => { component.successReportParams.subscribe(() => { - let dateElement: any = element.querySelector('adf-date-range-widget'); + const dateElement: any = element.querySelector('adf-date-range-widget'); expect(dateElement).toBeDefined(); done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.toggleParameters(); component.ngOnChanges({'reportId': change}); @@ -226,7 +226,7 @@ describe('AnalyticsReportParametersComponent', () => { it('Should render a dropdown with all the RangeInterval when the definition parameter type is \'dateRangeInterval\' ', (done) => { component.successReportParams.subscribe(() => { fixture.detectChanges(); - let dropDown: any = element.querySelector('#select-dateRangeInterval'); + const dropDown: any = element.querySelector('#select-dateRangeInterval'); expect(dropDown).toBeDefined(); expect(dropDown.length).toEqual(5); expect(dropDown[0].innerHTML).toEqual('By hour'); @@ -237,8 +237,8 @@ describe('AnalyticsReportParametersComponent', () => { done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -252,7 +252,7 @@ describe('AnalyticsReportParametersComponent', () => { ' reportId change', (done) => { component.successParamOpt.subscribe(() => { fixture.detectChanges(); - let dropDown: any = element.querySelector('#select-processDefinitionId'); + const dropDown: any = element.querySelector('#select-processDefinitionId'); expect(dropDown).toBeDefined(); expect(dropDown.length).toEqual(5); expect(dropDown[0].innerHTML).toEqual('Choose One'); @@ -275,8 +275,8 @@ describe('AnalyticsReportParametersComponent', () => { responseText: analyticParamsMock.reportDefParamProcessDefOptionsNoApp }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); }); @@ -285,7 +285,7 @@ describe('AnalyticsReportParametersComponent', () => { ' appId change', (done) => { component.successParamOpt.subscribe(() => { fixture.detectChanges(); - let dropDown: any = element.querySelector('#select-processDefinitionId'); + const dropDown: any = element.querySelector('#select-processDefinitionId'); expect(dropDown).toBeDefined(); expect(dropDown.length).toEqual(3); expect(dropDown[0].innerHTML).toEqual('Choose One'); @@ -300,7 +300,7 @@ describe('AnalyticsReportParametersComponent', () => { responseText: analyticParamsMock.reportDefParamProcessDef }); - let appId = 1; + const appId = 1; jasmine.Ajax.stubRequest('http://localhost:9876/bpm/activiti-app/api/enterprise/process-definitions?appDefinitionId=' + appId).andReturn({ status: 200, @@ -310,7 +310,7 @@ describe('AnalyticsReportParametersComponent', () => { component.appId = appId; component.reportId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.ngOnChanges({'appId': change}); }); @@ -322,8 +322,8 @@ describe('AnalyticsReportParametersComponent', () => { expect(component.reportForm.controls).toEqual({}); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -372,8 +372,8 @@ describe('AnalyticsReportParametersComponent', () => { responseText: [] }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); }); @@ -384,8 +384,8 @@ describe('AnalyticsReportParametersComponent', () => { done(); }); - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); jasmine.Ajax.requests.mostRecent().respondWith({ @@ -396,13 +396,13 @@ describe('AnalyticsReportParametersComponent', () => { }); it('Should convert a string in number', () => { - let numberConvert = component.convertNumber('2'); + const numberConvert = component.convertNumber('2'); expect(numberConvert).toEqual(2); }); describe('When the form is rendered correctly', () => { - let values: any = { + const values: any = { dateRange: { startDate: '2016-09-01', endDate: '2016-10-05' }, @@ -430,8 +430,8 @@ describe('AnalyticsReportParametersComponent', () => { }; beforeEach(async(() => { - let reportId = 1; - let change = new SimpleChange(null, reportId, true); + const reportId = 1; + const change = new SimpleChange(null, reportId, true); component.ngOnChanges({'reportId': change}); fixture.detectChanges(); @@ -450,11 +450,11 @@ describe('AnalyticsReportParametersComponent', () => { it('Should be able to change the report title', (done) => { spyOn(service, 'updateReport').and.returnValue(of(analyticParamsMock.reportDefParamStatus)); - let title: HTMLElement = element.querySelector('h4'); + const title: HTMLElement = element.querySelector('h4'); title.click(); fixture.detectChanges(); - let reportName: HTMLInputElement = <HTMLInputElement> element.querySelector('#reportName'); + const reportName: HTMLInputElement = <HTMLInputElement> element.querySelector('#reportName'); expect(reportName).not.toBeNull(); reportName.focus(); @@ -465,7 +465,7 @@ describe('AnalyticsReportParametersComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let titleChanged: HTMLElement = element.querySelector('h4'); + const titleChanged: HTMLElement = element.querySelector('h4'); expect(titleChanged.textContent.trim()).toEqual('FAKE_TEST_NAME'); done(); }); @@ -481,7 +481,7 @@ describe('AnalyticsReportParametersComponent', () => { component.submit(values); fixture.detectChanges(); - let saveButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#save-button'); + const saveButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#save-button'); expect(saveButton).toBeDefined(); expect(saveButton).not.toBeNull(); saveButton.click(); @@ -490,11 +490,11 @@ describe('AnalyticsReportParametersComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let reportDialogTitle: HTMLElement = <HTMLElement> window.document.querySelector('#report-dialog-title'); - let saveTitleSubMessage: HTMLElement = <HTMLElement> window.document.querySelector('#save-title-submessage'); - let inputSaveName: HTMLInputElement = <HTMLInputElement> window.document.querySelector('#repName'); - let performActionButton: HTMLButtonElement = <HTMLButtonElement> window.document.querySelector('#action-dialog-button'); - let todayDate = component.getTodayDate(); + const reportDialogTitle: HTMLElement = <HTMLElement> window.document.querySelector('#report-dialog-title'); + const saveTitleSubMessage: HTMLElement = <HTMLElement> window.document.querySelector('#save-title-submessage'); + const inputSaveName: HTMLInputElement = <HTMLInputElement> window.document.querySelector('#repName'); + const performActionButton: HTMLButtonElement = <HTMLButtonElement> window.document.querySelector('#action-dialog-button'); + const todayDate = component.getTodayDate(); expect(reportDialogTitle).not.toBeNull('Dialog title should not be null'); expect(saveTitleSubMessage).not.toBeNull('Dialog save title submessage should not be null'); @@ -513,7 +513,7 @@ describe('AnalyticsReportParametersComponent', () => { xit('Should show a dialog to allowing report export', async(() => { component.submit(values); fixture.detectChanges(); - let exportButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#export-button'); + const exportButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#export-button'); expect(exportButton).toBeDefined(); expect(exportButton).not.toBeNull(); @@ -523,10 +523,10 @@ describe('AnalyticsReportParametersComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let reportDialogTitle: HTMLElement = <HTMLElement> window.document.querySelector('#report-dialog-title'); - let inputSaveName: HTMLInputElement = <HTMLInputElement> window.document.querySelector('#repName'); - let performActionButton: HTMLButtonElement = <HTMLButtonElement> window.document.querySelector('#action-dialog-button'); - let todayDate = component.getTodayDate(); + const reportDialogTitle: HTMLElement = <HTMLElement> window.document.querySelector('#report-dialog-title'); + const inputSaveName: HTMLInputElement = <HTMLInputElement> window.document.querySelector('#repName'); + const performActionButton: HTMLButtonElement = <HTMLButtonElement> window.document.querySelector('#action-dialog-button'); + const todayDate = component.getTodayDate(); expect(reportDialogTitle).not.toBeNull(); expect(inputSaveName.value.trim()).toEqual(analyticParamsMock.reportDefParamStatus.name + ' ( ' + todayDate + ' )'); @@ -562,7 +562,7 @@ describe('AnalyticsReportParametersComponent', () => { it('Should raise an event for report deleted', async(() => { fixture.detectChanges(); spyOn(component, 'deleteReport'); - let deleteButton = fixture.debugElement.nativeElement.querySelector('#delete-button'); + const deleteButton = fixture.debugElement.nativeElement.querySelector('#delete-button'); expect(deleteButton).toBeDefined(); expect(deleteButton).not.toBeNull(); component.deleteReportSuccess.subscribe((reportId) => { diff --git a/lib/insights/analytics-process/components/analytics-report-parameters.component.ts b/lib/insights/analytics-process/components/analytics-report-parameters.component.ts index 23f50a8a0b..e4c3673baf 100644 --- a/lib/insights/analytics-process/components/analytics-report-parameters.component.ts +++ b/lib/insights/analytics-process/components/analytics-report-parameters.component.ts @@ -111,7 +111,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On ngOnInit() { this.dropDownSub = this.onDropdownChanged.subscribe((field) => { - let paramDependOn: ReportParameterDetailsModel = this.reportParameters.definition.parameters.find((p) => p.dependsOn === field.id); + const paramDependOn: ReportParameterDetailsModel = this.reportParameters.definition.parameters.find((p) => p.dependsOn === field.id); if (paramDependOn) { this.retrieveParameterOptions(this.reportParameters.definition.parameters, this.appId, this.reportId, field.value); } @@ -131,20 +131,20 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On this.reportForm.reset(); } - let reportId = changes['reportId']; + const reportId = changes['reportId']; if (reportId && reportId.currentValue) { this.reportId = reportId.currentValue; this.getReportParams(reportId.currentValue); } - let appId = changes['appId']; + const appId = changes['appId']; if (appId && (appId.currentValue || appId.currentValue === null)) { this.getReportParams(this.reportId); } } private generateFormGroupFromParameter(parameters: ReportParameterDetailsModel[]) { - let formBuilderGroup: any = {}; + const formBuilderGroup: any = {}; parameters.forEach((param: ReportParameterDetailsModel) => { switch (param.type) { case 'dateRange': @@ -263,7 +263,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On } convertFormValuesToReportParamQuery(values: any): ReportQuery { - let reportParamQuery: ReportQuery = new ReportQuery(); + const reportParamQuery: ReportQuery = new ReportQuery(); if (values.dateRange) { reportParamQuery.dateRange.startDate = this.convertMomentDate(values.dateRange.startDate); reportParamQuery.dateRange.endDate = this.convertMomentDate(values.dateRange.endDate); @@ -353,7 +353,7 @@ export class AnalyticsReportParametersComponent implements OnInit, OnChanges, On doExport(paramQuery: ReportQuery) { this.analyticsService.exportReportToCsv(this.reportId, paramQuery).subscribe( (data: any) => { - let blob: Blob = new Blob([data], { type: 'text/csv' }); + const blob: Blob = new Blob([data], { type: 'text/csv' }); this.contentService.downloadBlob(blob, paramQuery.reportName + '.csv'); }); } diff --git a/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.ts b/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.ts index 0799bb0a7b..80e64b4633 100644 --- a/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.ts +++ b/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.ts @@ -62,7 +62,7 @@ export class DateRangeWidgetComponent implements OnInit { this.dateAdapter.setLocale(locale); }); - let momentDateAdapter = <MomentDateAdapter> this.dateAdapter; + const momentDateAdapter = <MomentDateAdapter> this.dateAdapter; momentDateAdapter.overrideDisplayFormat = this.SHOW_FORMAT; if (this.field) { @@ -75,11 +75,11 @@ export class DateRangeWidgetComponent implements OnInit { } } - let startDateControl = new FormControl(this.startDatePicker); + const startDateControl = new FormControl(this.startDatePicker); startDateControl.setValidators(Validators.required); this.dateRange.addControl('startDate', startDateControl); - let endDateControl = new FormControl(this.endDatePicker); + const endDateControl = new FormControl(this.endDatePicker); endDateControl.setValidators(Validators.required); this.dateRange.addControl('endDate', endDateControl); @@ -89,8 +89,8 @@ export class DateRangeWidgetComponent implements OnInit { onGroupValueChanged() { if (this.dateRange.valid) { - let dateStart = this.convertToMomentDateWithTime(this.dateRange.controls.startDate.value); - let endStart = this.convertToMomentDateWithTime(this.dateRange.controls.endDate.value); + const dateStart = this.convertToMomentDateWithTime(this.dateRange.controls.startDate.value); + const endStart = this.convertToMomentDateWithTime(this.dateRange.controls.endDate.value); this.dateRangeChanged.emit({startDate: dateStart, endDate: endStart}); } } @@ -100,9 +100,9 @@ export class DateRangeWidgetComponent implements OnInit { } dateCheck(formControl: AbstractControl) { - let startDate = moment(formControl.get('startDate').value); - let endDate = moment(formControl.get('endDate').value); - let isAfterCheck = startDate.isAfter(endDate); + const startDate = moment(formControl.get('startDate').value); + const endDate = moment(formControl.get('endDate').value); + const isAfterCheck = startDate.isAfter(endDate); return isAfterCheck ? {'greaterThan': true} : null; } diff --git a/lib/insights/analytics-process/components/widgets/dropdown/dropdown.widget.ts b/lib/insights/analytics-process/components/widgets/dropdown/dropdown.widget.ts index de6d79b155..4ccc18b77c 100644 --- a/lib/insights/analytics-process/components/widgets/dropdown/dropdown.widget.ts +++ b/lib/insights/analytics-process/components/widgets/dropdown/dropdown.widget.ts @@ -65,7 +65,7 @@ export class DropdownWidgetAnalyticsComponent extends WidgetComponent implements } buildValidatorList() { - let validatorList = []; + const validatorList = []; validatorList.push(Validators.required); if (this.showDefaultOption) { validatorList.push(this.validateDropDown); diff --git a/lib/insights/analytics-process/components/widgets/duration/duration.widget.ts b/lib/insights/analytics-process/components/widgets/duration/duration.widget.ts index 131d9d4798..38349200c5 100644 --- a/lib/insights/analytics-process/components/widgets/duration/duration.widget.ts +++ b/lib/insights/analytics-process/components/widgets/duration/duration.widget.ts @@ -53,7 +53,7 @@ export class DurationWidgetComponent extends NumberWidgetAnalyticsComponent impl } ngOnInit() { - let timeType = new FormControl(); + const timeType = new FormControl(); this.formGroup.addControl('timeType', timeType); if (this.required) { @@ -63,7 +63,7 @@ export class DurationWidgetComponent extends NumberWidgetAnalyticsComponent impl this.field.value = 0; } - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; paramOptions.push(new ParameterValueModel({id: '1', name: 'Seconds'})); paramOptions.push(new ParameterValueModel({id: '60', name: 'Minutes'})); paramOptions.push(new ParameterValueModel({id: '3600', name: 'Hours'})); diff --git a/lib/insights/analytics-process/components/widgets/widget.component.ts b/lib/insights/analytics-process/components/widgets/widget.component.ts index f0a8581f9d..7ce468acc3 100644 --- a/lib/insights/analytics-process/components/widgets/widget.component.ts +++ b/lib/insights/analytics-process/components/widgets/widget.component.ts @@ -26,7 +26,7 @@ export class WidgetComponent implements OnChanges { fieldChanged: EventEmitter<any> = new EventEmitter<any>(); ngOnChanges(changes: SimpleChanges) { - let field = changes['field']; + const field = changes['field']; if (field && field.currentValue) { this.fieldChanged.emit(field.currentValue.value); return; diff --git a/lib/insights/analytics-process/services/analytics.service.ts b/lib/insights/analytics-process/services/analytics.service.ts index f57e603f80..c2e7fe747e 100644 --- a/lib/insights/analytics-process/services/analytics.service.ts +++ b/lib/insights/analytics-process/services/analytics.service.ts @@ -44,9 +44,9 @@ export class AnalyticsService { return from(this.apiService.getInstance().activiti.reportApi.getReportList()) .pipe( map((res: any) => { - let reports: ReportParametersModel[] = []; + const reports: ReportParametersModel[] = []; res.forEach((report: ReportParametersModel) => { - let reportModel = new ReportParametersModel(report); + const reportModel = new ReportParametersModel(report); if (this.isReportValid(appId, report)) { reports.push(reportModel); } @@ -111,7 +111,7 @@ export class AnalyticsService { } getProcessStatusValues(): Observable<any> { - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; paramOptions.push(new ParameterValueModel({ id: 'All', name: 'All' })); paramOptions.push(new ParameterValueModel({ id: 'Active', name: 'Active' })); @@ -124,7 +124,7 @@ export class AnalyticsService { } getDateIntervalValues(): Observable<any> { - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; paramOptions.push(new ParameterValueModel({ id: 'byHour', name: 'By hour' })); paramOptions.push(new ParameterValueModel({ id: 'byDay', name: 'By day' })); @@ -139,7 +139,7 @@ export class AnalyticsService { } getMetricValues(): Observable<any> { - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; paramOptions.push(new ParameterValueModel({ id: 'totalCount', name: 'Number of times a step is executed' })); paramOptions.push(new ParameterValueModel({ id: 'totalTime', name: 'Total time spent in a process step' })); @@ -155,7 +155,7 @@ export class AnalyticsService { return from(this.apiService.getInstance().activiti.reportApi.getProcessDefinitions()) .pipe( map((res: any) => { - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; res.forEach((opt) => { paramOptions.push(new ParameterValueModel(opt)); }); @@ -166,11 +166,11 @@ export class AnalyticsService { } getProcessDefinitionsValues(appId: number): Observable<any> { - let options = { 'appDefinitionId': appId }; + const options = { 'appDefinitionId': appId }; return from(this.apiService.getInstance().activiti.processDefinitionsApi.getProcessDefinitions(options)) .pipe( map((res: any) => { - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; res.data.forEach((opt) => { paramOptions.push(new ParameterValueModel(opt)); }); @@ -184,7 +184,7 @@ export class AnalyticsService { return from(this.apiService.getInstance().activiti.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId)) .pipe( map((res: any) => { - let paramOptions: ParameterValueModel[] = []; + const paramOptions: ParameterValueModel[] = []; res.forEach((opt) => { paramOptions.push(new ParameterValueModel({ id: opt, name: opt })); }); @@ -198,7 +198,7 @@ export class AnalyticsService { return from(this.apiService.getInstance().activiti.reportApi.getReportsByParams(reportId, paramsQuery)) .pipe( map((res: any) => { - let elements: Chart[] = []; + const elements: Chart[] = []; res.elements.forEach((chartData) => { if (chartData.type === 'pieChart') { elements.push(new PieChart(chartData)); diff --git a/lib/insights/diagram/components/diagram.component.activities.spec.ts b/lib/insights/diagram/components/diagram.component.activities.spec.ts index 34f3dda23a..bfd9e4b761 100644 --- a/lib/insights/diagram/components/diagram.component.activities.spec.ts +++ b/lib/insights/diagram/components/diagram.component.activities.spec.ts @@ -55,7 +55,7 @@ describe('Diagrams activities', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -70,23 +70,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake User task'); - let iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); + const iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.userTask] }; + const resp = { elements: [diagramsActivitiesMock.userTask] }; ajaxReply(resp); })); @@ -95,23 +95,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Manual task'); - let iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); + const iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.manualTask] }; + const resp = { elements: [diagramsActivitiesMock.manualTask] }; ajaxReply(resp); })); @@ -120,23 +120,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Service task'); - let iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); + const iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.serviceTask] }; + const resp = { elements: [diagramsActivitiesMock.serviceTask] }; ajaxReply(resp); })); @@ -145,23 +145,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Camel task'); - let iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); + const iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.camelTask] }; + const resp = { elements: [diagramsActivitiesMock.camelTask] }; ajaxReply(resp); })); @@ -170,19 +170,19 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Mule task'); - let iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); + const iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); expect(iconTask).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.muleTask] }; + const resp = { elements: [diagramsActivitiesMock.muleTask] }; ajaxReply(resp); })); @@ -191,24 +191,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Alfresco Publish task'); - let iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + + const iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + ' raphael-icon-alfresco-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.alfrescoPublishTask] }; + const resp = { elements: [diagramsActivitiesMock.alfrescoPublishTask] }; ajaxReply(resp); })); @@ -217,24 +217,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Google Drive Publish task'); - let iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + + const iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + ' diagram-icon-google-drive-publish-task > raphael-icon-google-drive-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.googleDrivePublishTask] }; + const resp = { elements: [diagramsActivitiesMock.googleDrivePublishTask] }; ajaxReply(resp); })); @@ -243,24 +243,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Rest Call task'); - let iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + + const iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + ' raphael-icon-rest-call'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.restCallTask] }; + const resp = { elements: [diagramsActivitiesMock.restCallTask] }; ajaxReply(resp); })); @@ -269,24 +269,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Box Publish task'); - let iconTask: any = element.querySelector('diagram-box-publish-task >' + + const iconTask: any = element.querySelector('diagram-box-publish-task >' + ' diagram-icon-box-publish-task > raphael-icon-box-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.boxPublishTask] }; + const resp = { elements: [diagramsActivitiesMock.boxPublishTask] }; ajaxReply(resp); })); @@ -295,23 +295,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Receive task'); - let iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); + const iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.receiveTask] }; + const resp = { elements: [diagramsActivitiesMock.receiveTask] }; ajaxReply(resp); })); @@ -320,23 +320,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Script task'); - let iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); + const iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.scriptTask] }; + const resp = { elements: [diagramsActivitiesMock.scriptTask] }; ajaxReply(resp); })); @@ -345,23 +345,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake BusinessRule task'); - let iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); + const iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.businessRuleTask] }; + const resp = { elements: [diagramsActivitiesMock.businessRuleTask] }; ajaxReply(resp); })); @@ -374,23 +374,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake User task'); - let iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); + const iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.userTask] }; + const resp = { elements: [diagramsActivitiesMock.userTask] }; ajaxReply(resp); })); @@ -399,23 +399,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake User task'); - let iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); + const iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.userTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.userTaskActive] }; ajaxReply(resp); })); @@ -424,23 +424,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-user-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-user-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake User task'); - let iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); + const iconTask: any = element.querySelector('diagram-user-task > diagram-icon-user-task > raphael-icon-user'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.userTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.userTaskCompleted] }; ajaxReply(resp); })); @@ -449,23 +449,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Manual task'); - let iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); + const iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.manualTask] }; + const resp = { elements: [diagramsActivitiesMock.manualTask] }; ajaxReply(resp); })); @@ -474,23 +474,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Manual task'); - let iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); + const iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.manualTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.manualTaskActive] }; ajaxReply(resp); })); @@ -499,23 +499,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-manual-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-manual-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Manual task'); - let iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); + const iconTask: any = element.querySelector('diagram-manual-task > diagram-icon-manual-task > raphael-icon-manual'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.manualTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.manualTaskCompleted] }; ajaxReply(resp); })); @@ -524,23 +524,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Service task'); - let iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); + const iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.serviceTask] }; + const resp = { elements: [diagramsActivitiesMock.serviceTask] }; ajaxReply(resp); })); @@ -549,23 +549,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Service task'); - let iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); + const iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.serviceTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.serviceTaskActive] }; ajaxReply(resp); })); @@ -574,23 +574,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-service-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-service-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Service task'); - let iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); + const iconTask: any = element.querySelector('diagram-service-task > diagram-icon-service-task > raphael-icon-service'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.serviceTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.serviceTaskCompleted] }; ajaxReply(resp); })); @@ -599,23 +599,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Camel task'); - let iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); + const iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.camelTask] }; + const resp = { elements: [diagramsActivitiesMock.camelTask] }; ajaxReply(resp); })); @@ -624,23 +624,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Camel task'); - let iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); + const iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.camelTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.camelTaskActive] }; ajaxReply(resp); })); @@ -649,23 +649,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-camel-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-camel-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Camel task'); - let iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); + const iconTask: any = element.querySelector('diagram-camel-task > diagram-icon-camel-task > raphael-icon-camel'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.camelTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.camelTaskCompleted] }; ajaxReply(resp); })); @@ -674,19 +674,19 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Mule task'); - let iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); + const iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); expect(iconTask).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.muleTask] }; + const resp = { elements: [diagramsActivitiesMock.muleTask] }; ajaxReply(resp); })); @@ -695,19 +695,19 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Mule task'); - let iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); + const iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); expect(iconTask).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.muleTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.muleTaskActive] }; ajaxReply(resp); })); @@ -716,19 +716,19 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-mule-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-mule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Mule task'); - let iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); + const iconTask: any = element.querySelector('diagram-mule-task > diagram-icon-mule-task > raphael-icon-mule'); expect(iconTask).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.muleTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.muleTaskCompleted] }; ajaxReply(resp); })); @@ -737,24 +737,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Alfresco Publish task'); - let iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + + const iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + ' raphael-icon-alfresco-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.alfrescoPublishTask] }; + const resp = { elements: [diagramsActivitiesMock.alfrescoPublishTask] }; ajaxReply(resp); })); @@ -763,24 +763,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Alfresco Publish task'); - let iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + + const iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + ' raphael-icon-alfresco-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.alfrescoPublishTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.alfrescoPublishTaskActive] }; ajaxReply(resp); })); @@ -789,24 +789,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('adf-diagram-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Alfresco Publish task'); - let iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + + const iconTask: any = element.querySelector('adf-diagram-publish-task > diagram-icon-alfresco-publish-task >' + ' raphael-icon-alfresco-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.alfrescoPublishTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.alfrescoPublishTaskCompleted] }; ajaxReply(resp); })); @@ -815,24 +815,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Google Drive Publish task'); - let iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + + const iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + ' diagram-icon-google-drive-publish-task > raphael-icon-google-drive-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.googleDrivePublishTask] }; + const resp = { elements: [diagramsActivitiesMock.googleDrivePublishTask] }; ajaxReply(resp); })); @@ -841,24 +841,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Google Drive Publish task'); - let iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + + const iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + ' diagram-icon-google-drive-publish-task > raphael-icon-google-drive-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.googleDrivePublishTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.googleDrivePublishTaskActive] }; ajaxReply(resp); })); @@ -867,24 +867,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-google-drive-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Google Drive Publish task'); - let iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + + const iconTask: any = element.querySelector('diagram-google-drive-publish-task >' + ' diagram-icon-google-drive-publish-task > raphael-icon-google-drive-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.googleDrivePublishTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.googleDrivePublishTaskCompleted] }; ajaxReply(resp); })); @@ -893,24 +893,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Rest Call task'); - let iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + + const iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + ' raphael-icon-rest-call'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.restCallTask] }; + const resp = { elements: [diagramsActivitiesMock.restCallTask] }; ajaxReply(resp); })); @@ -919,24 +919,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Rest Call task'); - let iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + + const iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + ' raphael-icon-rest-call'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.restCallTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.restCallTaskActive] }; ajaxReply(resp); })); @@ -945,24 +945,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-rest-call-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Rest Call task'); - let iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + + const iconTask: any = element.querySelector('diagram-rest-call-task > diagram-icon-rest-call-task >' + ' raphael-icon-rest-call'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.restCallTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.restCallTaskCompleted] }; ajaxReply(resp); })); @@ -971,24 +971,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Box Publish task'); - let iconTask: any = element.querySelector('diagram-box-publish-task >' + + const iconTask: any = element.querySelector('diagram-box-publish-task >' + ' diagram-icon-box-publish-task > raphael-icon-box-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.boxPublishTask] }; + const resp = { elements: [diagramsActivitiesMock.boxPublishTask] }; ajaxReply(resp); })); @@ -997,24 +997,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Box Publish task'); - let iconTask: any = element.querySelector('diagram-box-publish-task >' + + const iconTask: any = element.querySelector('diagram-box-publish-task >' + ' diagram-icon-box-publish-task > raphael-icon-box-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.boxPublishTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.boxPublishTaskActive] }; ajaxReply(resp); })); @@ -1023,24 +1023,24 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-box-publish-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Box Publish task'); - let iconTask: any = element.querySelector('diagram-box-publish-task >' + + const iconTask: any = element.querySelector('diagram-box-publish-task >' + ' diagram-icon-box-publish-task > raphael-icon-box-publish'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.boxPublishTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.boxPublishTaskCompleted] }; ajaxReply(resp); })); @@ -1049,23 +1049,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Receive task'); - let iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); + const iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.receiveTask] }; + const resp = { elements: [diagramsActivitiesMock.receiveTask] }; ajaxReply(resp); })); @@ -1074,23 +1074,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Receive task'); - let iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); + const iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.receiveTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.receiveTaskActive] }; ajaxReply(resp); })); @@ -1099,23 +1099,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-receive-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-receive-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Receive task'); - let iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); + const iconTask: any = element.querySelector('diagram-receive-task > diagram-icon-receive-task > raphael-icon-receive'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.receiveTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.receiveTaskCompleted] }; ajaxReply(resp); })); @@ -1124,23 +1124,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Script task'); - let iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); + const iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.scriptTask] }; + const resp = { elements: [diagramsActivitiesMock.scriptTask] }; ajaxReply(resp); })); @@ -1149,23 +1149,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Script task'); - let iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); + const iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.scriptTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.scriptTaskActive] }; ajaxReply(resp); })); @@ -1174,23 +1174,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-script-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-script-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake Script task'); - let iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); + const iconTask: any = element.querySelector('diagram-script-task > diagram-icon-script-task > raphael-icon-script'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.scriptTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.scriptTaskCompleted] }; ajaxReply(resp); })); @@ -1199,23 +1199,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect'); + const task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake BusinessRule task'); - let iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); + const iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.businessRuleTask] }; + const resp = { elements: [diagramsActivitiesMock.businessRuleTask] }; ajaxReply(resp); })); @@ -1224,23 +1224,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); + const task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect[ng-reflect-stroke="#017501"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake BusinessRule task'); - let iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); + const iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.businessRuleTaskActive] }; + const resp = { elements: [diagramsActivitiesMock.businessRuleTaskActive] }; ajaxReply(resp); })); @@ -1249,23 +1249,23 @@ describe('Diagrams activities', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const task: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(task).not.toBeNull(); - let taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); + const taskText: any = element.querySelector('diagram-business-rule-task > diagram-task > raphael-multiline-text'); expect(taskText).not.toBeNull(); expect(taskText.attributes[1].value).toEqual('Fake BusinessRule task'); - let iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); + const iconTask: any = element.querySelector('diagram-business-rule-task > diagram-icon-business-rule-task > raphael-icon-business-rule'); expect(iconTask).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].name); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsActivitiesMock.businessRuleTaskCompleted] }; + const resp = { elements: [diagramsActivitiesMock.businessRuleTaskCompleted] }; ajaxReply(resp); })); diff --git a/lib/insights/diagram/components/diagram.component.boundary.spec.ts b/lib/insights/diagram/components/diagram.component.boundary.spec.ts index e7d667bf48..91225ba821 100644 --- a/lib/insights/diagram/components/diagram.component.boundary.spec.ts +++ b/lib/insights/diagram/components/diagram.component.boundary.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams boundary', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,27 +69,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryTimeEvent] }; + const resp = { elements: [boundaryEventMock.boundaryTimeEvent] }; ajaxReply(resp); })); @@ -99,30 +99,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryTimeEventActive] }; + const resp = { elements: [boundaryEventMock.boundaryTimeEventActive] }; ajaxReply(resp); })); @@ -132,30 +132,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryTimeEventCompleted] }; + const resp = { elements: [boundaryEventMock.boundaryTimeEventCompleted] }; ajaxReply(resp); })); @@ -164,27 +164,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryErrorEvent] }; + const resp = { elements: [boundaryEventMock.boundaryErrorEvent] }; ajaxReply(resp); })); @@ -194,30 +194,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryErrorEventActive] }; + const resp = { elements: [boundaryEventMock.boundaryErrorEventActive] }; ajaxReply(resp); })); @@ -227,30 +227,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryErrorEventCompleted] }; + const resp = { elements: [boundaryEventMock.boundaryErrorEventCompleted] }; ajaxReply(resp); })); @@ -259,27 +259,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundarySignalEvent] }; + const resp = { elements: [boundaryEventMock.boundarySignalEvent] }; ajaxReply(resp); })); @@ -289,30 +289,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundarySignalEventActive] }; + const resp = { elements: [boundaryEventMock.boundarySignalEventActive] }; ajaxReply(resp); })); @@ -322,30 +322,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundarySignalEventCompleted] }; + const resp = { elements: [boundaryEventMock.boundarySignalEventCompleted] }; ajaxReply(resp); })); @@ -354,27 +354,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; ajaxReply(resp); })); @@ -384,30 +384,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEventActive] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEventActive] }; ajaxReply(resp); })); @@ -417,30 +417,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEventCompleted] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEventCompleted] }; ajaxReply(resp); })); @@ -449,27 +449,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; ajaxReply(resp); })); @@ -479,30 +479,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEventActive] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEventActive] }; ajaxReply(resp); })); @@ -512,30 +512,30 @@ describe('Diagrams boundary', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-boundary-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEventCompleted] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEventCompleted] }; ajaxReply(resp); })); }); @@ -547,27 +547,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryTimeEvent] }; + const resp = { elements: [boundaryEventMock.boundaryTimeEvent] }; ajaxReply(resp); })); @@ -576,27 +576,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryErrorEvent] }; + const resp = { elements: [boundaryEventMock.boundaryErrorEvent] }; ajaxReply(resp); })); @@ -605,27 +605,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundarySignalEvent] }; + const resp = { elements: [boundaryEventMock.boundarySignalEvent] }; ajaxReply(resp); })); @@ -634,27 +634,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; ajaxReply(resp); })); @@ -663,27 +663,27 @@ describe('Diagrams boundary', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-boundary-event'); + const shape: any = element.querySelector('diagram-boundary-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-boundary-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; + const resp = { elements: [boundaryEventMock.boundaryMessageEvent] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.catching.events.spec.ts b/lib/insights/diagram/components/diagram.component.catching.events.spec.ts index fef4245471..02c892ee05 100644 --- a/lib/insights/diagram/components/diagram.component.catching.events.spec.ts +++ b/lib/insights/diagram/components/diagram.component.catching.events.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams Catching', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,27 +69,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEvent] }; ajaxReply(resp); })); @@ -98,27 +98,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEvent] }; ajaxReply(resp); })); @@ -127,27 +127,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEvent] }; ajaxReply(resp); })); @@ -156,27 +156,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEvent] }; ajaxReply(resp); })); }); @@ -188,27 +188,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEvent] }; ajaxReply(resp); })); @@ -218,30 +218,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEventActive] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEventActive] }; ajaxReply(resp); })); @@ -251,30 +251,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEventCompleted] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingTimeEventCompleted] }; ajaxReply(resp); })); @@ -283,27 +283,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEvent] }; ajaxReply(resp); })); @@ -313,30 +313,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEventActive] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEventActive] }; ajaxReply(resp); })); @@ -346,30 +346,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEventCompleted] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingErrorEventCompleted] }; ajaxReply(resp); })); @@ -378,27 +378,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEvent] }; ajaxReply(resp); })); @@ -408,30 +408,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEventActive] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEventActive] }; ajaxReply(resp); })); @@ -441,30 +441,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEventCompleted] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingSignalEventCompleted] }; ajaxReply(resp); })); @@ -473,27 +473,27 @@ describe('Diagrams Catching', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEvent] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEvent] }; ajaxReply(resp); })); @@ -503,30 +503,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEventActive] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEventActive] }; ajaxReply(resp); })); @@ -536,30 +536,30 @@ describe('Diagrams Catching', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-intermediate-catching-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-intermediate-catching-event'); + const shape: any = element.querySelector('diagram-intermediate-catching-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-intermediate-catching-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEventCompleted] }; + const resp = { elements: [intermediateCatchingMock.intermediateCatchingMessageEventCompleted] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.events.spec.ts b/lib/insights/diagram/components/diagram.component.events.spec.ts index 08204c2f94..77207dd107 100644 --- a/lib/insights/diagram/components/diagram.component.events.spec.ts +++ b/lib/insights/diagram/components/diagram.component.events.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams events', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,15 +69,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startEvent] }; + const resp = { elements: [diagramsEventsMock.startEvent] }; ajaxReply(resp); })); @@ -86,20 +86,20 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startTimeEvent] }; + const resp = { elements: [diagramsEventsMock.startTimeEvent] }; ajaxReply(resp); })); @@ -108,19 +108,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event'); + const event: any = element.querySelector('diagram-start-event'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startSignalEvent] }; + const resp = { elements: [diagramsEventsMock.startSignalEvent] }; ajaxReply(resp); })); @@ -129,19 +129,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startMessageEvent] }; + const resp = { elements: [diagramsEventsMock.startMessageEvent] }; ajaxReply(resp); })); @@ -150,19 +150,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startErrorEvent] }; + const resp = { elements: [diagramsEventsMock.startErrorEvent] }; ajaxReply(resp); })); @@ -171,15 +171,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endEvent] }; + const resp = { elements: [diagramsEventsMock.endEvent] }; ajaxReply(resp); })); @@ -188,19 +188,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endErrorEvent] }; + const resp = { elements: [diagramsEventsMock.endErrorEvent] }; ajaxReply(resp); })); }); @@ -212,15 +212,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startEvent] }; + const resp = { elements: [diagramsEventsMock.startEvent] }; ajaxReply(resp); })); @@ -229,15 +229,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startEventActive] }; + const resp = { elements: [diagramsEventsMock.startEventActive] }; ajaxReply(resp); })); @@ -246,15 +246,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startEventCompleted] }; + const resp = { elements: [diagramsEventsMock.startEventCompleted] }; ajaxReply(resp); })); @@ -263,19 +263,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startTimeEvent] }; + const resp = { elements: [diagramsEventsMock.startTimeEvent] }; ajaxReply(resp); })); @@ -285,19 +285,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startTimeEventActive] }; + const resp = { elements: [diagramsEventsMock.startTimeEventActive] }; ajaxReply(resp); })); @@ -307,19 +307,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-timer > raphael-icon-timer'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startTimeEventCompleted] }; + const resp = { elements: [diagramsEventsMock.startTimeEventCompleted] }; ajaxReply(resp); })); @@ -329,19 +329,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startSignalEvent] }; + const resp = { elements: [diagramsEventsMock.startSignalEvent] }; ajaxReply(resp); })); @@ -350,19 +350,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startSignalEventActive] }; + const resp = { elements: [diagramsEventsMock.startSignalEventActive] }; ajaxReply(resp); })); @@ -371,19 +371,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-signal > raphael-icon-signal'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startSignalEventCompleted] }; + const resp = { elements: [diagramsEventsMock.startSignalEventCompleted] }; ajaxReply(resp); })); @@ -392,19 +392,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startMessageEvent] }; + const resp = { elements: [diagramsEventsMock.startMessageEvent] }; ajaxReply(resp); })); @@ -413,19 +413,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startMessageEventActive] }; + const resp = { elements: [diagramsEventsMock.startMessageEventActive] }; ajaxReply(resp); })); @@ -434,19 +434,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-message > raphael-icon-message'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startMessageEventCompleted] }; + const resp = { elements: [diagramsEventsMock.startMessageEventCompleted] }; ajaxReply(resp); })); @@ -455,19 +455,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startErrorEvent] }; + const resp = { elements: [diagramsEventsMock.startErrorEvent] }; ajaxReply(resp); })); @@ -476,19 +476,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startErrorEventActive] }; + const resp = { elements: [diagramsEventsMock.startErrorEventActive] }; ajaxReply(resp); })); @@ -497,19 +497,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-start-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-start-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.startErrorEventCompleted] }; + const resp = { elements: [diagramsEventsMock.startErrorEventCompleted] }; ajaxReply(resp); })); @@ -518,15 +518,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endEvent] }; + const resp = { elements: [diagramsEventsMock.endEvent] }; ajaxReply(resp); })); @@ -535,15 +535,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endEventActive] }; + const resp = { elements: [diagramsEventsMock.endEventActive] }; ajaxReply(resp); })); @@ -552,15 +552,15 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endEventCompleted] }; + const resp = { elements: [diagramsEventsMock.endEventCompleted] }; ajaxReply(resp); })); @@ -569,19 +569,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endErrorEvent] }; + const resp = { elements: [diagramsEventsMock.endErrorEvent] }; ajaxReply(resp); })); @@ -590,19 +590,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#017501"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endErrorEventActive] }; + const resp = { elements: [diagramsEventsMock.endErrorEventActive] }; ajaxReply(resp); })); @@ -611,19 +611,19 @@ describe('Diagrams events', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).toBeDefined(); - let event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); + const event: any = element.querySelector('diagram-end-event > diagram-event > raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(event).not.toBeNull(); - let iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + + const iconEvent: any = element.querySelector('diagram-end-event > diagram-event >' + ' diagram-container-icon-event > div > div > diagram-icon-error > raphael-icon-error'); expect(iconEvent).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsEventsMock.endErrorEventCompleted] }; + const resp = { elements: [diagramsEventsMock.endErrorEventCompleted] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.flows.spec.ts b/lib/insights/diagram/components/diagram.component.flows.spec.ts index c037cf4892..1a470c9d27 100644 --- a/lib/insights/diagram/components/diagram.component.flows.spec.ts +++ b/lib/insights/diagram/components/diagram.component.flows.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams flows', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,16 +69,16 @@ describe('Diagrams flows', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('adf-diagram-sequence-flow > raphael-flow-arrow'); + const shape: any = element.querySelector('adf-diagram-sequence-flow > raphael-flow-arrow'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.flows[0].id); expect(tooltip.textContent).toContain(res.flows[0].type); }); }); component.ngOnChanges(); - let resp = { flows: [flowsMock.flow] }; + const resp = { flows: [flowsMock.flow] }; ajaxReply(resp); })); }); @@ -90,16 +90,16 @@ describe('Diagrams flows', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('adf-diagram-sequence-flow > raphael-flow-arrow'); + const shape: any = element.querySelector('adf-diagram-sequence-flow > raphael-flow-arrow'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.flows[0].id); expect(tooltip.textContent).toContain(res.flows[0].type); }); }); component.ngOnChanges(); - let resp = { flows: [flowsMock.flow] }; + const resp = { flows: [flowsMock.flow] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.gateways.spec.ts b/lib/insights/diagram/components/diagram.component.gateways.spec.ts index 9f9be0fa22..d72c798542 100644 --- a/lib/insights/diagram/components/diagram.component.gateways.spec.ts +++ b/lib/insights/diagram/components/diagram.component.gateways.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams gateways', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,19 +69,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); + const shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.exclusiveGateway] }; + const resp = { elements: [diagramsGatewaysMock.exclusiveGateway] }; ajaxReply(resp); })); @@ -90,19 +90,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); + const shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.inclusiveGateway] }; + const resp = { elements: [diagramsGatewaysMock.inclusiveGateway] }; ajaxReply(resp); })); @@ -111,19 +111,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); + const shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.parallelGateway] }; + const resp = { elements: [diagramsGatewaysMock.parallelGateway] }; ajaxReply(resp); })); @@ -132,29 +132,29 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-event-gateway'); + const shape1: any = element.querySelector('diagram-event-gateway'); expect(shape1).not.toBeNull(); expect(shape1.children.length).toBe(4); - let outerCircle = shape1.children[1]; + const outerCircle = shape1.children[1]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape1.children[2]; + const innerCircle = shape1.children[2]; expect(innerCircle.localName).toEqual('raphael-circle'); - let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); + const shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); expect(shape2).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.eventGateway] }; + const resp = { elements: [diagramsGatewaysMock.eventGateway] }; ajaxReply(resp); })); }); @@ -166,19 +166,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); + const shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.exclusiveGateway] }; + const resp = { elements: [diagramsGatewaysMock.exclusiveGateway] }; ajaxReply(resp); })); @@ -187,19 +187,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); + const shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); + const shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.exclusiveGatewayActive] }; + const resp = { elements: [diagramsGatewaysMock.exclusiveGatewayActive] }; ajaxReply(resp); })); @@ -208,19 +208,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); + const shape: any = element.querySelector('diagram-exclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); + const shape1: any = element.querySelector('diagram-exclusive-gateway > raphael-cross'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.exclusiveGatewayCompleted] }; + const resp = { elements: [diagramsGatewaysMock.exclusiveGatewayCompleted] }; ajaxReply(resp); })); @@ -229,19 +229,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); + const shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.inclusiveGateway] }; + const resp = { elements: [diagramsGatewaysMock.inclusiveGateway] }; ajaxReply(resp); })); @@ -250,19 +250,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); + const shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); + const shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.inclusiveGatewayActive] }; + const resp = { elements: [diagramsGatewaysMock.inclusiveGatewayActive] }; ajaxReply(resp); })); @@ -271,19 +271,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); + const shape: any = element.querySelector('diagram-inclusive-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); + const shape1: any = element.querySelector('diagram-inclusive-gateway > raphael-circle'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.inclusiveGatewayCompleted] }; + const resp = { elements: [diagramsGatewaysMock.inclusiveGatewayCompleted] }; ajaxReply(resp); })); @@ -292,19 +292,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); + const shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.parallelGateway] }; + const resp = { elements: [diagramsGatewaysMock.parallelGateway] }; ajaxReply(resp); })); @@ -313,19 +313,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); + const shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); + const shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.parallelGatewayActive] }; + const resp = { elements: [diagramsGatewaysMock.parallelGatewayActive] }; ajaxReply(resp); })); @@ -334,19 +334,19 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); + const shape: any = element.querySelector('diagram-parallel-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); + const shape1: any = element.querySelector('diagram-parallel-gateway > raphael-plus'); expect(shape1).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.parallelGatewayCompleted] }; + const resp = { elements: [diagramsGatewaysMock.parallelGatewayCompleted] }; ajaxReply(resp); })); @@ -355,29 +355,29 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus'); + const shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-event-gateway'); + const shape1: any = element.querySelector('diagram-event-gateway'); expect(shape1).not.toBeNull(); expect(shape1.children.length).toBe(4); - let outerCircle = shape1.children[1]; + const outerCircle = shape1.children[1]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape1.children[2]; + const innerCircle = shape1.children[2]; expect(innerCircle.localName).toEqual('raphael-circle'); - let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); + const shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); expect(shape2).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.eventGateway] }; + const resp = { elements: [diagramsGatewaysMock.eventGateway] }; ajaxReply(resp); })); @@ -386,29 +386,29 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); + const shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#017501"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-event-gateway'); + const shape1: any = element.querySelector('diagram-event-gateway'); expect(shape1).not.toBeNull(); expect(shape1.children.length).toBe(4); - let outerCircle = shape1.children[1]; + const outerCircle = shape1.children[1]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape1.children[2]; + const innerCircle = shape1.children[2]; expect(innerCircle.localName).toEqual('raphael-circle'); - let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); + const shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); expect(shape2).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.eventGatewayActive] }; + const resp = { elements: [diagramsGatewaysMock.eventGatewayActive] }; ajaxReply(resp); })); @@ -417,29 +417,29 @@ describe('Diagrams gateways', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); + const shape: any = element.querySelector('diagram-event-gateway > diagram-gateway > raphael-rhombus[ng-reflect-stroke="#2632aa"]'); expect(shape).not.toBeNull(); - let shape1: any = element.querySelector('diagram-event-gateway'); + const shape1: any = element.querySelector('diagram-event-gateway'); expect(shape1).not.toBeNull(); expect(shape1.children.length).toBe(4); - let outerCircle = shape1.children[1]; + const outerCircle = shape1.children[1]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape1.children[2]; + const innerCircle = shape1.children[2]; expect(innerCircle.localName).toEqual('raphael-circle'); - let shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); + const shape2: any = element.querySelector('diagram-event-gateway > raphael-pentagon'); expect(shape2).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [diagramsGatewaysMock.eventGatewayCompleted] }; + const resp = { elements: [diagramsGatewaysMock.eventGatewayCompleted] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.structural.spec.ts b/lib/insights/diagram/components/diagram.component.structural.spec.ts index 3c4b360b32..7fe85a6a15 100644 --- a/lib/insights/diagram/components/diagram.component.structural.spec.ts +++ b/lib/insights/diagram/components/diagram.component.structural.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams structural', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,16 +69,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-subprocess > raphael-rect'); + const shape: any = element.querySelector('diagram-subprocess > raphael-rect'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.subProcess] }; + const resp = { elements: [structuralMock.subProcess] }; ajaxReply(resp); })); @@ -87,16 +87,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect'); + const shape: any = element.querySelector('diagram-event-subprocess > raphael-rect'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.eventSubProcess] }; + const resp = { elements: [structuralMock.eventSubProcess] }; ajaxReply(resp); })); }); @@ -108,16 +108,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-subprocess > raphael-rect'); + const shape: any = element.querySelector('diagram-subprocess > raphael-rect'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.subProcess] }; + const resp = { elements: [structuralMock.subProcess] }; ajaxReply(resp); })); @@ -126,16 +126,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-subprocess > raphael-rect[ng-reflect-stroke="#017501"]'); + const shape: any = element.querySelector('diagram-subprocess > raphael-rect[ng-reflect-stroke="#017501"]'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.subProcessActive] }; + const resp = { elements: [structuralMock.subProcessActive] }; ajaxReply(resp); })); @@ -144,16 +144,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-subprocess > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const shape: any = element.querySelector('diagram-subprocess > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.subProcessCompleted] }; + const resp = { elements: [structuralMock.subProcessCompleted] }; ajaxReply(resp); })); @@ -162,16 +162,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect'); + const shape: any = element.querySelector('diagram-event-subprocess > raphael-rect'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.eventSubProcess] }; + const resp = { elements: [structuralMock.eventSubProcess] }; ajaxReply(resp); })); @@ -180,16 +180,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect[ng-reflect-stroke="#017501"]'); + const shape: any = element.querySelector('diagram-event-subprocess > raphael-rect[ng-reflect-stroke="#017501"]'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.eventSubProcessActive] }; + const resp = { elements: [structuralMock.eventSubProcessActive] }; ajaxReply(resp); })); @@ -198,16 +198,16 @@ describe('Diagrams structural', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-event-subprocess > raphael-rect[ng-reflect-stroke="#2632aa"]'); + const shape: any = element.querySelector('diagram-event-subprocess > raphael-rect[ng-reflect-stroke="#2632aa"]'); expect(shape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [structuralMock.eventSubProcessCompleted] }; + const resp = { elements: [structuralMock.eventSubProcessCompleted] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.swim.spec.ts b/lib/insights/diagram/components/diagram.component.swim.spec.ts index f9a8d2b6b9..d339f0cc72 100644 --- a/lib/insights/diagram/components/diagram.component.swim.spec.ts +++ b/lib/insights/diagram/components/diagram.component.swim.spec.ts @@ -54,7 +54,7 @@ describe('Diagrams swim', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -69,16 +69,16 @@ describe('Diagrams swim', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-pool > raphael-rect'); + const shape: any = element.querySelector('diagram-pool > raphael-rect'); expect(shape).not.toBeNull(); - let shapeText: any = element.querySelector('diagram-pool > raphael-text'); + const shapeText: any = element.querySelector('diagram-pool > raphael-text'); expect(shapeText).not.toBeNull(); expect(shapeText.attributes[2].value).toEqual('Activiti'); }); }); component.ngOnChanges(); - let resp = { pools: [swimLanesMock.pool] }; + const resp = { pools: [swimLanesMock.pool] }; ajaxReply(resp); })); @@ -87,19 +87,19 @@ describe('Diagrams swim', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shapeLane: any = element.querySelector('diagram-lanes > div > div > diagram-lane'); + const shapeLane: any = element.querySelector('diagram-lanes > div > div > diagram-lane'); expect(shapeLane).not.toBeNull(); - let shapeRect: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-rect'); + const shapeRect: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-rect'); expect(shapeRect).not.toBeNull(); - let shapeText: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-text'); + const shapeText: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-text'); expect(shapeText).not.toBeNull(); expect(shapeText.attributes[2].value).toEqual('Backend'); }); }); component.ngOnChanges(); - let resp = { pools: [swimLanesMock.poolLanes] }; + const resp = { pools: [swimLanesMock.poolLanes] }; ajaxReply(resp); })); }); @@ -111,16 +111,16 @@ describe('Diagrams swim', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-pool > raphael-rect'); + const shape: any = element.querySelector('diagram-pool > raphael-rect'); expect(shape).not.toBeNull(); - let shapeText: any = element.querySelector('diagram-pool > raphael-text'); + const shapeText: any = element.querySelector('diagram-pool > raphael-text'); expect(shapeText).not.toBeNull(); expect(shapeText.attributes[2].value).toEqual('Activiti'); }); }); component.ngOnChanges(); - let resp = { pools: [swimLanesMock.pool] }; + const resp = { pools: [swimLanesMock.pool] }; ajaxReply(resp); })); @@ -129,19 +129,19 @@ describe('Diagrams swim', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shapeLane: any = element.querySelector('diagram-lanes > div > div > diagram-lane'); + const shapeLane: any = element.querySelector('diagram-lanes > div > div > diagram-lane'); expect(shapeLane).not.toBeNull(); - let shapeRect: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-rect'); + const shapeRect: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-rect'); expect(shapeRect).not.toBeNull(); - let shapeText: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-text'); + const shapeText: any = element.querySelector('diagram-lanes > div > div > diagram-lane > raphael-text'); expect(shapeText).not.toBeNull(); expect(shapeText.attributes[2].value).toEqual('Backend'); }); }); component.ngOnChanges(); - let resp = { pools: [swimLanesMock.poolLanes] }; + const resp = { pools: [swimLanesMock.poolLanes] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.throw.spec.ts b/lib/insights/diagram/components/diagram.component.throw.spec.ts index a56c59cd41..9fb3d54ae8 100644 --- a/lib/insights/diagram/components/diagram.component.throw.spec.ts +++ b/lib/insights/diagram/components/diagram.component.throw.spec.ts @@ -53,7 +53,7 @@ describe('Diagrams throw', () => { jasmine.Ajax.uninstall(); }); - let ajaxReply = (resp: any) => { + const ajaxReply = (resp: any) => { jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, contentType: 'json', @@ -68,23 +68,23 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwTimeEvent] }; + const resp = { elements: [throwEventMock.throwTimeEvent] }; ajaxReply(resp); })); @@ -94,26 +94,26 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwTimeEventActive] }; + const resp = { elements: [throwEventMock.throwTimeEventActive] }; ajaxReply(resp); })); @@ -123,26 +123,26 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwTimeEventCompleted] }; + const resp = { elements: [throwEventMock.throwTimeEventCompleted] }; ajaxReply(resp); })); @@ -151,27 +151,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwErrorEvent] }; + const resp = { elements: [throwEventMock.throwErrorEvent] }; ajaxReply(resp); })); @@ -181,30 +181,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwErrorEventActive] }; + const resp = { elements: [throwEventMock.throwErrorEventActive] }; ajaxReply(resp); })); @@ -214,30 +214,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwErrorEventCompleted] }; + const resp = { elements: [throwEventMock.throwErrorEventCompleted] }; ajaxReply(resp); })); @@ -246,27 +246,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwSignalEvent] }; + const resp = { elements: [throwEventMock.throwSignalEvent] }; ajaxReply(resp); })); @@ -276,30 +276,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwSignalEventActive] }; + const resp = { elements: [throwEventMock.throwSignalEventActive] }; ajaxReply(resp); })); @@ -309,30 +309,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwSignalEventCompleted] }; + const resp = { elements: [throwEventMock.throwSignalEventCompleted] }; ajaxReply(resp); })); @@ -341,27 +341,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEvent] }; + const resp = { elements: [throwEventMock.throwMessageEvent] }; ajaxReply(resp); })); @@ -371,30 +371,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEventActive] }; + const resp = { elements: [throwEventMock.throwMessageEventActive] }; ajaxReply(resp); })); @@ -404,30 +404,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEventCompleted] }; + const resp = { elements: [throwEventMock.throwMessageEventCompleted] }; ajaxReply(resp); })); @@ -436,27 +436,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEvent] }; + const resp = { elements: [throwEventMock.throwMessageEvent] }; ajaxReply(resp); })); @@ -466,30 +466,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#017501"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEventActive] }; + const resp = { elements: [throwEventMock.throwMessageEventActive] }; ajaxReply(resp); })); @@ -499,30 +499,30 @@ describe('Diagrams throw', () => { fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); + const coloredShape: any = element.querySelector('diagram-throw-event>raphael-circle[ng-reflect-stroke="#2632aa"]'); expect(coloredShape).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEventCompleted] }; + const resp = { elements: [throwEventMock.throwMessageEventCompleted] }; ajaxReply(resp); })); }); @@ -534,23 +534,23 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-timer'); expect(iconShape).not.toBeNull(); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwTimeEvent] }; + const resp = { elements: [throwEventMock.throwTimeEvent] }; ajaxReply(resp); })); @@ -559,27 +559,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-error'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwErrorEvent] }; + const resp = { elements: [throwEventMock.throwErrorEvent] }; ajaxReply(resp); })); @@ -588,27 +588,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-signal'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwSignalEvent] }; + const resp = { elements: [throwEventMock.throwSignalEvent] }; ajaxReply(resp); })); @@ -617,27 +617,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEvent] }; + const resp = { elements: [throwEventMock.throwMessageEvent] }; ajaxReply(resp); })); @@ -646,27 +646,27 @@ describe('Diagrams throw', () => { fixture.detectChanges(); fixture.whenStable().then(() => { expect(res).not.toBeNull(); - let shape: any = element.querySelector('diagram-throw-event'); + const shape: any = element.querySelector('diagram-throw-event'); expect(shape).not.toBeNull(); expect(shape.children.length).toBe(4); - let outerCircle = shape.children[0]; + const outerCircle = shape.children[0]; expect(outerCircle.localName).toEqual('raphael-circle'); - let innerCircle = shape.children[1]; + const innerCircle = shape.children[1]; expect(innerCircle.localName).toEqual('raphael-circle'); - let iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + + const iconShape: any = element.querySelector('diagram-throw-event > diagram-container-icon-event >' + ' div > div > diagram-icon-message'); expect(iconShape).not.toBeNull(); - let tooltip: any = element.querySelector('diagram-tooltip > div'); + const tooltip: any = element.querySelector('diagram-tooltip > div'); expect(tooltip.textContent).toContain(res.elements[0].id); expect(tooltip.textContent).toContain(res.elements[0].type); }); }); component.ngOnChanges(); - let resp = { elements: [throwEventMock.throwMessageEvent] }; + const resp = { elements: [throwEventMock.throwMessageEvent] }; ajaxReply(resp); })); }); diff --git a/lib/insights/diagram/components/diagram.component.ts b/lib/insights/diagram/components/diagram.component.ts index d16781f112..95522c939f 100644 --- a/lib/insights/diagram/components/diagram.component.ts +++ b/lib/insights/diagram/components/diagram.component.ts @@ -106,9 +106,9 @@ export class DiagramComponent implements OnChanges { } setMetricValueToDiagramElement(diagram: DiagramModel, metrics: any, metricType: string) { - for (let key in metrics) { + for (const key in metrics) { if (metrics.hasOwnProperty(key)) { - let foundElement: DiagramElementModel = diagram.elements.find( + const foundElement: DiagramElementModel = diagram.elements.find( (element: DiagramElementModel) => element.id === key); if (foundElement) { foundElement.value = metrics[key]; diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-alfresco-publish.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-alfresco-publish.component.ts index 7e8f925c1a..a8f2166ee4 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-alfresco-publish.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-alfresco-publish.component.ts @@ -61,8 +61,8 @@ export class RaphaelIconAlfrescoPublishDirective extends RaphaelBase implements public draw(position: Point) { - let startX = position.x + 2; - let startY = position.y + 2; + const startX = position.x + 2; + const startY = position.y + 2; let path1 = this.paper.path(`M4.11870968,2.12890323 L6.12954839,0.117935484 L3.10993548,0.118064516 L3.10270968,0.118064516 C1.42941935,0.118064516 0.0729032258,1.47458065 0.0729032258,3.14774194 C0.0729032258,4.82116129 1.42929032,6.17754839 @@ -76,8 +76,8 @@ export class RaphaelIconAlfrescoPublishDirective extends RaphaelBase implements 'stroke-width': this.strokeWidth }); - let startX1 = startX + 1.419355; - let startY1 = startY + 8.387097; + const startX1 = startX + 1.419355; + const startY1 = startY + 8.387097; path1.transform('T' + startX1 + ',' + startY1); path1 = this.paper.path(`M10.4411613,10.5153548 L8.43032258,8.50451613 L8.43032258,11.5313548 C8.43032258,13.2047742 9.78683871, @@ -101,7 +101,7 @@ export class RaphaelIconAlfrescoPublishDirective extends RaphaelBase implements 'stroke-width': this.strokeWidth }); - let startX2 = startX + 5.548387; + const startX2 = startX + 5.548387; path1.transform('T' + startX2 + ',' + startY); path1 = this.paper.path(`M4.58090323,1.0156129 C3.39767742,-0.167483871 1.47935484,-0.167483871 0.296129032,1.01574194 diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-box-publish.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-box-publish.component.ts index d6ad2d59d2..067bcdd14d 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-box-publish.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-box-publish.component.ts @@ -61,7 +61,7 @@ export class RaphaelIconBoxPublishDirective extends RaphaelBase implements OnIni public draw(position: Point) { - let image = this.paper.image(); + const image = this.paper.image(); image.attr({'x': position.x}); image.attr({'y': position.y}); diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-business-rule.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-business-rule.component.ts index 3b45d4765f..615969c2d0 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-business-rule.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-business-rule.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconBusinessRuleDirective extends RaphaelBase implements OnI } public draw(position: Point) { - let path1 = this.paper.path(`m 1,2 0,14 16,0 0,-14 z m 1.45458,5.6000386 2.90906,0 0,2.7999224 -2.90906,0 z m 4.36364,0 8.72718,0 + const path1 = this.paper.path(`m 1,2 0,14 16,0 0,-14 z m 1.45458,5.6000386 2.90906,0 0,2.7999224 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.7999224 -8.72718,0 z m -4.36364,4.1998844 2.90906,0 0,2.800116 -2.90906,0 z m 4.36364,0 8.72718,0 0,2.800116 -8.72718,0 z`).attr({ 'stroke': this.stroke, diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-camel.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-camel.component.ts index 56d6e0caa3..793bb80cca 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-camel.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-camel.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconCamelDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`m 8.1878027,15.383782 c -0.824818,-0.3427 0.375093,-1.1925 0.404055,-1.7743 0.230509,-0.8159 + const path1 = this.paper.path(`m 8.1878027,15.383782 c -0.824818,-0.3427 0.375093,-1.1925 0.404055,-1.7743 0.230509,-0.8159 -0.217173,-1.5329 -0.550642,-2.2283 -0.106244,-0.5273 -0.03299,-1.8886005 -0.747194,-1.7818005 -0.712355,0.3776 -0.9225,1.2309005 -1.253911,1.9055005 -0.175574,1.0874 -0.630353,2.114 -0.775834,3.2123 -0.244009,0.4224 -1.741203,0.3888 -1.554386,-0.1397 0.651324,-0.3302 1.13227,-0.9222 1.180246,-1.6705 0.0082,-0.7042 -0.133578,-1.3681 0.302178,-2.0083 0.08617,-0.3202 diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-error.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-error.component.ts index 784a169b39..8f15b21dbd 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-error.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-error.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconErrorDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`M 22.820839,11.171502 L 19.36734,24.58992 L 13.54138,14.281819 L 9.3386512,20.071607 + const path1 = this.paper.path(`M 22.820839,11.171502 L 19.36734,24.58992 L 13.54138,14.281819 L 9.3386512,20.071607 L 13.048949,6.8323057 L 18.996148,16.132659 L 22.820839,11.171502 z`).attr({ 'opacity': 1, 'stroke': this.stroke, diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-google-drive-publish.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-google-drive-publish.component.ts index 31c6c64be5..33293b28e4 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-google-drive-publish.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-google-drive-publish.component.ts @@ -61,7 +61,7 @@ export class RaphaelIconGoogleDrivePublishDirective extends RaphaelBase implemen public draw(position: Point) { - let image = this.paper.image(); + const image = this.paper.image(); image.attr({'x': position.x}); image.attr({'y': position.y}); diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-manual.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-manual.component.ts index 7fa2c3770e..e16627afdd 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-manual.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-manual.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconManualDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`m 17,9.3290326 c -0.0069,0.5512461 -0.455166,1.0455894 -0.940778,1.0376604 l -5.792746,0 c + const path1 = this.paper.path(`m 17,9.3290326 c -0.0069,0.5512461 -0.455166,1.0455894 -0.940778,1.0376604 l -5.792746,0 c 0.0053,0.119381 0.0026,0.237107 0.0061,0.355965 l 5.154918,0 c 0.482032,-0.0096 0.925529,0.49051 0.919525,1.037574 -0.0078,0.537128 -0.446283,1.017531 -0.919521,1.007683 l -5.245273,0 c -0.01507,0.104484 -0.03389,0.204081 -0.05316,0.301591 l 2.630175,0 c 0.454137,-0.0096 0.872112,0.461754 0.866386,0.977186 C 13.619526,14.554106 13.206293,15.009498 12.75924,15 L 3.7753054,15 diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-message.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-message.component.ts index 082d005108..0f74a9325d 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-message.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-message.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconMessageDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 + const path1 = this.paper.path(`M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z`).attr({ 'opacity': this.fillOpacity, 'stroke': this.stroke, diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-mule.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-mule.component.ts index a5835340e8..1a9f166605 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-mule.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-mule.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconMuleDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`M 8,0 C 3.581722,0 0,3.5817 0,8 c 0,4.4183 3.581722,8 8,8 4.418278,0 8,-3.5817 8,-8 L 16,7.6562 + const path1 = this.paper.path(`M 8,0 C 3.581722,0 0,3.5817 0,8 c 0,4.4183 3.581722,8 8,8 4.418278,0 8,-3.5817 8,-8 L 16,7.6562 C 15.813571,3.3775 12.282847,0 8,0 z M 5.1875,2.7812 8,7.3437 10.8125,2.7812 c 1.323522,0.4299 2.329453,1.5645 2.8125,2.8438 1.136151,2.8609 -0.380702,6.4569 -3.25,7.5937 -0.217837,-0.6102 -0.438416,-1.2022 -0.65625,-1.8125 0.701032,-0.2274 1.313373,-0.6949 1.71875,-1.3125 0.73624,-1.2317 0.939877,-2.6305 -0.03125,-4.3125 l -2.75,4.0625 -0.65625,0 -0.65625,0 -2.75,-4 diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-receive.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-receive.component.ts index 09dde5d19b..4dab2e1151 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-receive.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-receive.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconReceiveDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`m 0.5,2.5 0,13 17,0 0,-13 z M 2,4 6.5,8.5 2,13 z M 4,4 14,4 9,9 z m 12,0 0,9 -4.5,-4.5 z + const path1 = this.paper.path(`m 0.5,2.5 0,13 17,0 0,-13 z M 2,4 6.5,8.5 2,13 z M 4,4 14,4 9,9 z m 12,0 0,9 -4.5,-4.5 z M 7.5,9.5 9,11 10.5,9.5 15,14 3,14 z`).attr({ 'stroke': this.stroke, 'fill': this.fillColors diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-rest-call.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-rest-call.component.ts index 61c8d6b45f..ee36b6129f 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-rest-call.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-rest-call.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconRestCallDirective extends RaphaelBase implements OnInit } public draw(position: Point) { - let path1 = this.paper.path(`m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 + const path1 = this.paper.path(`m 16.704699,5.9229055 q 0.358098,0 0.608767,0.2506681 0.250669,0.250668 0.250669,0.6087677 0,0.3580997 -0.250669,0.6087677 -0.250669,0.2506679 -0.608767,0.2506679 -0.358098,0 -0.608767,-0.2506679 -0.250669,-0.250668 -0.250669,-0.6087677 0,-0.3580997 0.250669,-0.6087677 0.250669,-0.2506681 0.608767,-0.2506681 z m 2.578308,-2.0053502 q -2.229162,0 -3.854034,0.6759125 -1.624871,0.6759067 -3.227361,2.2694472 -0.716197,0.725146 -1.575633,1.7457293 L diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-script.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-script.component.ts index c32cd9926d..66af5f8f02 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-script.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-script.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconScriptDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`m 5,2 0,0.094 c 0.23706,0.064 0.53189,0.1645 0.8125,0.375 0.5582,0.4186 1.05109,1.228 1.15625,2.5312 + const path1 = this.paper.path(`m 5,2 0,0.094 c 0.23706,0.064 0.53189,0.1645 0.8125,0.375 0.5582,0.4186 1.05109,1.228 1.15625,2.5312 l 8.03125,0 1,0 1,0 c 0,-3 -2,-3 -2,-3 l -10,0 z M 4,3 4,13 2,13 c 0,3 2,3 2,3 l 9,0 c 0,0 2,0 2,-3 L 15,6 6,6 6,5.5 C 6,4.1111 5.5595,3.529 5.1875,3.25 4.8155,2.971 4.5,3 4.5,3 L 4,3 z`).attr({ 'stroke': this.stroke, diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-send.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-send.component.ts index 864e1ebe38..2ab0dea316 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-send.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-send.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconSendDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 + const path1 = this.paper.path(`M 1 3 L 9 11 L 17 3 L 1 3 z M 1 5 L 1 13 L 5 9 L 1 5 z M 17 5 L 13 9 L 17 13 L 17 5 z M 6 10 L 1 15 L 17 15 L 12 10 L 9 13 L 6 10 z`).attr({ 'stroke': this.stroke, 'fill': this.fillColors diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-service.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-service.component.ts index b40765ac42..1e1097ed03 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-service.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-service.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconServiceDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path('M 8,1 7.5,2.875 c 0,0 -0.02438,0.250763 -0.40625,0.4375 C 7.05724,3.330353 7.04387,3.358818 7,3.375' + + const path1 = this.paper.path('M 8,1 7.5,2.875 c 0,0 -0.02438,0.250763 -0.40625,0.4375 C 7.05724,3.330353 7.04387,3.358818 7,3.375' + ' 6.6676654,3.4929791 6.3336971,3.6092802 6.03125,3.78125 6.02349,3.78566 6.007733,3.77681 6,3.78125 5.8811373,3.761018' + ' 5.8125,3.71875 5.8125,3.71875 l -1.6875,-1 -1.40625,1.4375 0.96875,1.65625 c 0,0 0.065705,0.068637 0.09375,0.1875' + ' 0.002,0.00849 -0.00169,0.022138 0,0.03125 C 3.6092802,6.3336971 3.4929791,6.6676654 3.375,7 3.3629836,7.0338489' + diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-signal.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-signal.component.ts index e0e00ed9d6..0867ccaaf4 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-signal.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-signal.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconSignalDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z`).attr({ + const path1 = this.paper.path(`M 8.7124971,21.247342 L 23.333334,21.247342 L 16.022915,8.5759512 L 8.7124971,21.247342 z`).attr({ 'opacity': this.fillOpacity, 'stroke': this.stroke, 'strokeWidth': this.strokeWidth, diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-timer.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-timer.component.ts index 1833041dfa..f9294721f4 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-timer.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-timer.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconTimerDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 + const path1 = this.paper.path(`M 10 0 C 4.4771525 0 0 4.4771525 0 10 C 0 15.522847 4.4771525 20 10 20 C 15.522847 20 20 15.522847 20 10 C 20 4.4771525 15.522847 1.1842379e-15 10 0 z M 9.09375 1.03125 C 9.2292164 1.0174926 9.362825 1.0389311 9.5 1.03125 L 9.5 3.5 L 10.5 3.5 L 10.5 1.03125 C 15.063526 1.2867831 18.713217 4.9364738 18.96875 9.5 L 16.5 9.5 L 16.5 10.5 L 18.96875 10.5 C 18.713217 15.063526 15.063526 18.713217 10.5 18.96875 L 10.5 16.5 L 9.5 16.5 L 9.5 18.96875 C 4.9364738 18.713217 1.2867831 15.063526 1.03125 diff --git a/lib/insights/diagram/components/raphael/icons/raphael-icon-user.component.ts b/lib/insights/diagram/components/raphael/icons/raphael-icon-user.component.ts index a5de18e85a..99e62c26ca 100644 --- a/lib/insights/diagram/components/raphael/icons/raphael-icon-user.component.ts +++ b/lib/insights/diagram/components/raphael/icons/raphael-icon-user.component.ts @@ -60,7 +60,7 @@ export class RaphaelIconUserDirective extends RaphaelBase implements OnInit { } public draw(position: Point) { - let path1 = this.paper.path(`m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 + const path1 = this.paper.path(`m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 l 0,-3.0222 C 12.555557,0.8221 9.0000001,1.0001 9.0000001,1.0001 c 0,0 -3.5555556,-0.178 -3.9111111,3.5555 l 0,3.0222 c 0,0 0,2.3111 1.2444443,2.3111 l 0,1.7778 L 1,15.2222 1,17 17,17`).attr({ 'opacity': 1, diff --git a/lib/insights/diagram/components/raphael/raphael-circle.component.ts b/lib/insights/diagram/components/raphael/raphael-circle.component.ts index b2e745eb7e..9b0949f539 100644 --- a/lib/insights/diagram/components/raphael/raphael-circle.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-circle.component.ts @@ -59,13 +59,13 @@ export class RaphaelCircleDirective extends RaphaelBase implements OnInit { ngOnInit() { - let opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; - let drawElement = this.draw(this.center, this.radius, opts); + const opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; + const drawElement = this.draw(this.center, this.radius, opts); drawElement.node.id = this.elementId; } public draw(center: Point, radius: number, opts: any) { - let circle = this.paper.circle(center.x, center.y, radius).attr(opts); + const circle = this.paper.circle(center.x, center.y, radius).attr(opts); return circle; } } diff --git a/lib/insights/diagram/components/raphael/raphael-cross.component.ts b/lib/insights/diagram/components/raphael/raphael-cross.component.ts index 8a7f17a1c9..83b70c2b84 100644 --- a/lib/insights/diagram/components/raphael/raphael-cross.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-cross.component.ts @@ -56,13 +56,13 @@ export class RaphaelCrossDirective extends RaphaelBase implements OnInit { ngOnInit() { - let opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; + const opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; this.draw(this.center, this.width, this.height, opts); } public draw(center: Point, width: number, height: number, opts?: any) { - let quarterWidth = width / 4; - let quarterHeight = height / 4; + const quarterWidth = width / 4; + const quarterHeight = height / 4; return this.paper.path( 'M' + (center.x + quarterWidth + 3) + ' ' + (center.y + quarterHeight + 3) + diff --git a/lib/insights/diagram/components/raphael/raphael-flow-arrow.component.ts b/lib/insights/diagram/components/raphael/raphael-flow-arrow.component.ts index 0d51aebdfa..2f45942a61 100644 --- a/lib/insights/diagram/components/raphael/raphael-flow-arrow.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-flow-arrow.component.ts @@ -50,30 +50,30 @@ export class RaphaelFlowArrowDirective extends RaphaelBase implements OnInit { } public draw(flow: any) { - let line = this.drawLine(flow); + const line = this.drawLine(flow); this.drawArrow(line); } public drawLine(flow: any) { - let polyline = new Polyline(flow.id, flow.waypoints, this.SEQUENCE_FLOW_STROKE, this.paper); + const polyline = new Polyline(flow.id, flow.waypoints, this.SEQUENCE_FLOW_STROKE, this.paper); polyline.element = this.paper.path(polyline.path); polyline.element.attr({'stroke-width': this.SEQUENCE_FLOW_STROKE}); polyline.element.attr({'stroke': '#585858'}); polyline.element.node.id = this.flow.id; - let lastLineIndex = polyline.getLinesCount() - 1; - let line = polyline.getLine(lastLineIndex); + const lastLineIndex = polyline.getLinesCount() - 1; + const line = polyline.getLine(lastLineIndex); return line; } public drawArrow(line: any) { - let doubleArrowWidth = 2 * this.ARROW_WIDTH; - let width = this.ARROW_WIDTH / 2 + .5; - let arrowHead: any = this.paper.path('M0 0L-' + width + '-' + doubleArrowWidth + 'L' + width + ' -' + doubleArrowWidth + 'z'); + const doubleArrowWidth = 2 * this.ARROW_WIDTH; + const width = this.ARROW_WIDTH / 2 + .5; + const arrowHead: any = this.paper.path('M0 0L-' + width + '-' + doubleArrowWidth + 'L' + width + ' -' + doubleArrowWidth + 'z'); arrowHead.transform('t' + line.x2 + ',' + line.y2); - let angle = Raphael.deg(line.angle - Math.PI / 2); + const angle = Raphael.deg(line.angle - Math.PI / 2); arrowHead.transform('...r' + angle + ' 0 0'); arrowHead.attr('fill', '#585858'); diff --git a/lib/insights/diagram/components/raphael/raphael-multiline-text.component.ts b/lib/insights/diagram/components/raphael/raphael-multiline-text.component.ts index a460e5b4e2..bc7adf08f5 100644 --- a/lib/insights/diagram/components/raphael/raphael-multiline-text.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-multiline-text.component.ts @@ -58,14 +58,14 @@ export class RaphaelMultilineTextDirective extends RaphaelBase implements OnInit } draw(position: Point, text: string) { - let textPaper = this.paper.text(position.x + this.TEXT_PADDING, position.y + this.TEXT_PADDING, text).attr({ + const textPaper = this.paper.text(position.x + this.TEXT_PADDING, position.y + this.TEXT_PADDING, text).attr({ 'text-anchor': 'middle', 'font-family': 'Arial', 'font-size': '11', 'fill': '#373e48' }); - let formattedText = this.formatText(textPaper, text, this.elementWidth); + const formattedText = this.formatText(textPaper, text, this.elementWidth); textPaper.attr({ 'text': formattedText }); @@ -74,17 +74,18 @@ export class RaphaelMultilineTextDirective extends RaphaelBase implements OnInit } private formatText(textPaper, text, elementWidth) { - let pText = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const pText = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; textPaper.attr({ 'text': pText }); - let letterWidth = textPaper.getBBox().width / text.length; - let removedLineBreaks = text.split('\n'); - let actualRowLength = 0, formattedText = []; + const letterWidth = textPaper.getBBox().width / text.length; + const removedLineBreaks = text.split('\n'); + let actualRowLength = 0; + const formattedText = []; removedLineBreaks.forEach((sentence) => { - let words = sentence.split(' '); + const words = sentence.split(' '); words.forEach((word) => { - let length = word.length; + const length = word.length; if (actualRowLength + (length * letterWidth) > elementWidth) { formattedText.push('\n'); actualRowLength = 0; diff --git a/lib/insights/diagram/components/raphael/raphael-pentagon.component.ts b/lib/insights/diagram/components/raphael/raphael-pentagon.component.ts index a05fb0ba64..4a2ce95f16 100644 --- a/lib/insights/diagram/components/raphael/raphael-pentagon.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-pentagon.component.ts @@ -53,7 +53,7 @@ export class RaphaelPentagonDirective extends RaphaelBase implements OnInit { ngOnInit() { - let opts = { + const opts = { 'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, diff --git a/lib/insights/diagram/components/raphael/raphael-plus.component.ts b/lib/insights/diagram/components/raphael/raphael-plus.component.ts index b1f4ff93fd..8569f3a49c 100644 --- a/lib/insights/diagram/components/raphael/raphael-plus.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-plus.component.ts @@ -49,12 +49,12 @@ export class RaphaelPlusDirective extends RaphaelBase implements OnInit { } ngOnInit() { - let opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; + const opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; this.draw(this.center, opts); } public draw(center: Point, opts?: any) { - let path = this.paper.path('M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75').attr(opts); + const path = this.paper.path('M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75').attr(opts); return path.transform('T' + (center.x + 4) + ',' + (center.y + 4)); } } diff --git a/lib/insights/diagram/components/raphael/raphael-rect.component.ts b/lib/insights/diagram/components/raphael/raphael-rect.component.ts index c32ebc81a6..f49676bfb0 100644 --- a/lib/insights/diagram/components/raphael/raphael-rect.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-rect.component.ts @@ -65,13 +65,13 @@ export class RaphaelRectDirective extends RaphaelBase implements OnInit { ngOnInit() { - let opts = { + const opts = { 'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity }; - let elementDraw = this.draw(this.leftCorner, this.width, this.height, this.radius, opts); + const elementDraw = this.draw(this.leftCorner, this.width, this.height, this.radius, opts); elementDraw.node.id = this.elementId; } diff --git a/lib/insights/diagram/components/raphael/raphael-rhombus.component.ts b/lib/insights/diagram/components/raphael/raphael-rhombus.component.ts index c2a790362a..51582e9208 100644 --- a/lib/insights/diagram/components/raphael/raphael-rhombus.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-rhombus.component.ts @@ -59,8 +59,8 @@ export class RaphaelRhombusDirective extends RaphaelBase implements OnInit { ngOnInit() { - let opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; - let elementDraw = this.draw(this.center, this.width, this.height, opts); + const opts = {'stroke-width': this.strokeWidth, 'fill': this.fillColors, 'stroke': this.stroke, 'fill-opacity': this.fillOpacity}; + const elementDraw = this.draw(this.center, this.width, this.height, opts); elementDraw.node.id = this.elementId; } diff --git a/lib/insights/diagram/components/raphael/raphael-text.component.ts b/lib/insights/diagram/components/raphael/raphael-text.component.ts index 01de6e6bc1..ef707480cb 100644 --- a/lib/insights/diagram/components/raphael/raphael-text.component.ts +++ b/lib/insights/diagram/components/raphael/raphael-text.component.ts @@ -54,7 +54,7 @@ export class RaphaelTextDirective extends RaphaelBase implements OnInit { } public draw(position: Point, text: string) { - let textPaper = this.paper.text(position.x, position.y, text).attr({ + const textPaper = this.paper.text(position.x, position.y, text).attr({ 'text-anchor' : 'middle', 'font-family' : 'Arial', 'font-size' : '11', diff --git a/lib/insights/diagram/components/raphael/raphael.service.ts b/lib/insights/diagram/components/raphael/raphael.service.ts index a37a8aae13..6c0fb9ab03 100644 --- a/lib/insights/diagram/components/raphael/raphael.service.ts +++ b/lib/insights/diagram/components/raphael/raphael.service.ts @@ -47,7 +47,7 @@ export class RaphaelService implements OnDestroy { if (typeof Raphael === 'undefined') { throw new Error('insights configuration issue: Embedding Chart.js lib is mandatory'); } - let paper = new Raphael(ctx, this.width, this.height); + const paper = new Raphael(ctx, this.width, this.height); return paper; } diff --git a/lib/insights/diagram/components/tooltip/diagram-tooltip.component.spec.ts b/lib/insights/diagram/components/tooltip/diagram-tooltip.component.spec.ts index 0f45628d80..7a18134ff4 100644 --- a/lib/insights/diagram/components/tooltip/diagram-tooltip.component.spec.ts +++ b/lib/insights/diagram/components/tooltip/diagram-tooltip.component.spec.ts @@ -59,7 +59,7 @@ describe('DiagramTooltipComponent', () => { }); it('should render with type and name if name is defined', () => { - let tooltipHeader = fixture.debugElement.query(By.css('.adf-diagram-tooltip-header')); + const tooltipHeader = fixture.debugElement.query(By.css('.adf-diagram-tooltip-header')); expect(tooltipHeader.nativeElement.innerText).toBe('awesome-diagram-element diagram-element-name'); }); @@ -68,13 +68,13 @@ describe('DiagramTooltipComponent', () => { data.name = ''; fixture.detectChanges(); - let tooltipHeader = fixture.debugElement.query(By.css('.adf-diagram-tooltip-header')); + const tooltipHeader = fixture.debugElement.query(By.css('.adf-diagram-tooltip-header')); expect(tooltipHeader.nativeElement.innerText).toBe('awesome-diagram-element diagram-element-id'); }); it('should render the name if name is defined in the tooltip body', () => { - let nameProperty = fixture.debugElement.query(By.css('.adf-diagram-name-property')); + const nameProperty = fixture.debugElement.query(By.css('.adf-diagram-name-property')); expect(nameProperty).not.toBeNull(); expect(nameProperty.nativeElement.innerText).toBe('Name:diagram-element-name'); @@ -84,7 +84,7 @@ describe('DiagramTooltipComponent', () => { data.name = ''; fixture.detectChanges(); - let nameProperty = fixture.debugElement.query(By.css('.adf-diagram-name-property')); + const nameProperty = fixture.debugElement.query(By.css('.adf-diagram-name-property')); expect(nameProperty).toBeNull(); }); @@ -96,7 +96,7 @@ describe('DiagramTooltipComponent', () => { ]; fixture.detectChanges(); - let propertyNames = fixture.debugElement.queryAll(By.css('.adf-diagram-general-property > .adf-diagram-propertyName')), + const propertyNames = fixture.debugElement.queryAll(By.css('.adf-diagram-general-property > .adf-diagram-propertyName')), propertyValues = fixture.debugElement.queryAll(By.css('.adf-diagram-general-property > .adf-diagram-propertyValue')); expect(propertyNames.length).toBe(2); @@ -113,7 +113,7 @@ describe('DiagramTooltipComponent', () => { fixture.detectChanges(); - let propertyValue = fixture.debugElement.queryAll(By.css('.adf-diagram-heat-value > .adf-diagram-value')), + const propertyValue = fixture.debugElement.queryAll(By.css('.adf-diagram-heat-value > .adf-diagram-value')), propertyValueType = fixture.debugElement.queryAll(By.css('.adf-diagram-heat-value > .adf-diagram-valuetype')); expect(propertyValue.length).toBe(1); @@ -150,7 +150,7 @@ describe('DiagramTooltipComponent', () => { tooltipTarget.nativeElement.dispatchEvent(new MouseEvent('mouseenter')); - let tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); + const tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); expect(tooltip).not.toBeNull(); }); @@ -159,7 +159,7 @@ describe('DiagramTooltipComponent', () => { tooltipTarget.nativeElement.dispatchEvent(new MouseEvent('touchend')); - let tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); + const tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); expect(tooltip).not.toBeNull(); }); @@ -169,7 +169,7 @@ describe('DiagramTooltipComponent', () => { tooltipTarget.nativeElement.dispatchEvent(new MouseEvent('mouseenter')); tooltipTarget.nativeElement.dispatchEvent(new MouseEvent('mouseleave')); - let tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); + const tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); expect(tooltip).toBeNull(); }); @@ -179,7 +179,7 @@ describe('DiagramTooltipComponent', () => { tooltipTarget.nativeElement.dispatchEvent(new MouseEvent('mouseenter')); window.dispatchEvent(new CustomEvent('scroll')); - let tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); + const tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); expect(tooltip).toBeNull(); }); @@ -189,7 +189,7 @@ describe('DiagramTooltipComponent', () => { tooltipTarget.nativeElement.dispatchEvent(new MouseEvent('touchend')); window.dispatchEvent(new CustomEvent('touchstart')); - let tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); + const tooltip = fixture.debugElement.query(By.css('.adf-diagram-tooltip.adf-is-active')); expect(tooltip).toBeNull(); }); }); diff --git a/lib/insights/diagram/components/tooltip/diagram-tooltip.component.ts b/lib/insights/diagram/components/tooltip/diagram-tooltip.component.ts index c616ce05f1..a8d0ac3d7d 100644 --- a/lib/insights/diagram/components/tooltip/diagram-tooltip.component.ts +++ b/lib/insights/diagram/components/tooltip/diagram-tooltip.component.ts @@ -106,9 +106,9 @@ export class DiagramTooltipComponent implements AfterViewInit, OnDestroy { props = { top: (event.pageY - 150), left: event.pageX, width: event.layerX, height: 50 }; } - let top = props.top + (props.height / 2); - let marginLeft = -1 * (this.tooltipElement.offsetWidth / 2); - let marginTop = -1 * (this.tooltipElement.offsetHeight / 2); + const top = props.top + (props.height / 2); + const marginLeft = -1 * (this.tooltipElement.offsetWidth / 2); + const marginTop = -1 * (this.tooltipElement.offsetHeight / 2); let left = props.left + (props.width / 2); if (this.position === POSITION.LEFT || this.position === POSITION.RIGHT) { diff --git a/lib/insights/diagram/models/chart/barChart.model.ts b/lib/insights/diagram/models/chart/barChart.model.ts index 7e39d43d30..f239a82821 100644 --- a/lib/insights/diagram/models/chart/barChart.model.ts +++ b/lib/insights/diagram/models/chart/barChart.model.ts @@ -53,7 +53,7 @@ export class BarChart extends Chart { this.options.scales.yAxes[0].ticks.callback = this.yAxisTickFormatFunction(this.yAxisType); if (obj.values) { obj.values.forEach((params: any) => { - let dataValue = []; + const dataValue = []; params.values.forEach((info: any) => { info.forEach((value: any, index: any) => { if (index % 2 === 0) { @@ -91,7 +91,7 @@ export class BarChart extends Chart { return function (value) { if (yAxisType !== null && yAxisType !== undefined) { if ('count' === yAxisType) { - let label = '' + value; + const label = '' + value; if (label.indexOf('.') !== -1) { return ''; } diff --git a/lib/insights/diagram/models/report/reportDefinition.model.ts b/lib/insights/diagram/models/report/reportDefinition.model.ts index c9c5e3321e..982f788eab 100644 --- a/lib/insights/diagram/models/report/reportDefinition.model.ts +++ b/lib/insights/diagram/models/report/reportDefinition.model.ts @@ -22,7 +22,7 @@ export class ReportDefinitionModel { constructor(obj?: any) { obj.parameters.forEach((params: any) => { - let reportParamsModel = new ReportParameterDetailsModel(params); + const reportParamsModel = new ReportParameterDetailsModel(params); this.parameters.push(reportParamsModel); }); } diff --git a/lib/insights/diagram/services/diagram-color.service.ts b/lib/insights/diagram/services/diagram-color.service.ts index 329301ec6e..ea25f4171c 100644 --- a/lib/insights/diagram/services/diagram-color.service.ts +++ b/lib/insights/diagram/services/diagram-color.service.ts @@ -46,7 +46,7 @@ export class DiagramColorService { getFillColour(key: string) { if (this.totalColors && this.totalColors.hasOwnProperty(key)) { - let colorPercentage = this.totalColors[key]; + const colorPercentage = this.totalColors[key]; return this.convertColorToHsb(colorPercentage); } else { return DiagramColorService.ACTIVITY_FILL_COLOR; @@ -72,7 +72,7 @@ export class DiagramColorService { } convertColorToHsb(colorPercentage: number): string { - let hue = (120.0 - (colorPercentage * 1.2)) / 360.0; + const hue = (120.0 - (colorPercentage * 1.2)) / 360.0; return 'hsb(' + hue + ', 1, 1)'; } } diff --git a/lib/insights/diagram/services/diagrams.service.spec.ts b/lib/insights/diagram/services/diagrams.service.spec.ts index abac5cda72..6520b89695 100644 --- a/lib/insights/diagram/services/diagrams.service.spec.ts +++ b/lib/insights/diagram/services/diagrams.service.spec.ts @@ -31,7 +31,7 @@ describe('DiagramsService', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.ecmHost = 'http://localhost:9876/ecm'; service = TestBed.get(DiagramsService); diff --git a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts index d6a2cf18a0..eccbf58420 100644 --- a/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/group/components/group-cloud.component.spec.ts @@ -73,7 +73,7 @@ describe('GroupCloudComponent', () => { it('should show the groups if the typed result match', async(() => { fixture.detectChanges(); component.searchGroups$ = of(<GroupModel[]> mockGroups); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.dispatchEvent(new Event('input')); inputHTMLElement.dispatchEvent(new Event('keyup')); @@ -88,7 +88,7 @@ describe('GroupCloudComponent', () => { it('should hide result list if input is empty', async(() => { fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = ''; inputHTMLElement.dispatchEvent(new Event('keyup')); @@ -102,7 +102,7 @@ describe('GroupCloudComponent', () => { it('should emit selectedGroup if option is valid', async(() => { fixture.detectChanges(); - let selectEmitSpy = spyOn(component.selectGroup, 'emit'); + const selectEmitSpy = spyOn(component.selectGroup, 'emit'); component.onSelect(new GroupModel({ name: 'group name'})); fixture.whenStable().then(() => { expect(selectEmitSpy).toHaveBeenCalled(); @@ -186,7 +186,7 @@ describe('GroupCloudComponent', () => { })); it('should emit removeGroup when a selected group is removed if mode=multiple', async(() => { - let removeGroupSpy = spyOn(component.removeGroup, 'emit'); + const removeGroupSpy = spyOn(component.removeGroup, 'emit'); component.mode = 'multiple'; component.preSelectGroups = <any> [{id: mockGroups[1].id}, {id: mockGroups[2].id}]; @@ -205,7 +205,7 @@ describe('GroupCloudComponent', () => { it('should list groups who have access to the app when appName is specified', async(() => { component.appName = 'sample-app'; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -222,7 +222,7 @@ describe('GroupCloudComponent', () => { component.appName = 'sample-app'; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('[data-automation-id="adf-cloud-group-search-input"]'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('[data-automation-id="adf-cloud-group-search-input"]'); inputHTMLElement.focus(); inputHTMLElement.value = 'Mock'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -238,7 +238,7 @@ describe('GroupCloudComponent', () => { checkGroupHasGivenRoleSpy.and.returnValue(of(true)); component.roles = ['mock-role-1', 'mock-role-2']; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -255,7 +255,7 @@ describe('GroupCloudComponent', () => { checkGroupHasGivenRoleSpy.and.returnValue(of(false)); component.roles = []; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -272,7 +272,7 @@ describe('GroupCloudComponent', () => { findGroupsByNameSpy.and.returnValue(of(mockGroups)); checkGroupHasAccessSpy.and.returnValue(of(true)); fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'Mock'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -285,7 +285,7 @@ describe('GroupCloudComponent', () => { it('should not validate access to the app when appName is not specified', async(() => { fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); diff --git a/lib/process-services-cloud/src/lib/group/pipe/group-initial.pipe.spec.ts b/lib/process-services-cloud/src/lib/group/pipe/group-initial.pipe.spec.ts index 601a2a2552..b33b1de4a4 100644 --- a/lib/process-services-cloud/src/lib/group/pipe/group-initial.pipe.spec.ts +++ b/lib/process-services-cloud/src/lib/group/pipe/group-initial.pipe.spec.ts @@ -30,12 +30,12 @@ describe('InitialGroupNamePipe', () => { it('should return with the group initial', () => { fakeGroup.name = 'FAKE-GROUP-NAME'; - let result = pipe.transform(fakeGroup); + const result = pipe.transform(fakeGroup); expect(result).toBe('F'); }); it('should return an empty string when group is null', () => { - let result = pipe.transform(null); + const result = pipe.transform(null); expect(result).toBe(''); }); }); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts index 1d6a247a3f..3bfb964261 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts @@ -258,7 +258,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges { onDateChanged(newDateValue: any, dateProperty: ProcessFilterProperties) { if (newDateValue) { - let momentDate = moment(newDateValue, this.DATE_FORMAT, true); + const momentDate = moment(newDateValue, this.DATE_FORMAT, true); if (momentDate.isValid()) { this.getPropertyController(dateProperty).setValue(momentDate.toDate()); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filter-dialog-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filter-dialog-cloud.component.spec.ts index 89e03e933d..e3a52898fb 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filter-dialog-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filter-dialog-cloud.component.spec.ts @@ -63,7 +63,7 @@ describe('ProcessFilterDialogCloudComponent', () => { it('should display title', () => { fixture.detectChanges(); - let titleElement = fixture.debugElement.nativeElement.querySelector( + const titleElement = fixture.debugElement.nativeElement.querySelector( '#adf-process-filter-dialog-title' ); expect(titleElement.textContent).toEqual(' ADF_CLOUD_EDIT_PROCESS_FILTER.DIALOG.TITLE '); @@ -71,7 +71,7 @@ describe('ProcessFilterDialogCloudComponent', () => { it('should enable save button if form is valid', async(() => { fixture.detectChanges(); - let saveButton = fixture.debugElement.nativeElement.querySelector( + const saveButton = fixture.debugElement.nativeElement.querySelector( '#adf-save-button-id' ); const inputElement = fixture.debugElement.nativeElement.querySelector( @@ -94,7 +94,7 @@ describe('ProcessFilterDialogCloudComponent', () => { inputElement.value = ''; inputElement.dispatchEvent(new Event('input')); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector( + const saveButton = fixture.debugElement.nativeElement.querySelector( '#adf-save-button-id' ); fixture.detectChanges(); @@ -111,7 +111,7 @@ describe('ProcessFilterDialogCloudComponent', () => { inputElement.value = 'My custom Name'; inputElement.dispatchEvent(new Event('input')); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector( + const saveButton = fixture.debugElement.nativeElement.querySelector( '#adf-save-button-id' ); fixture.detectChanges(); @@ -124,7 +124,7 @@ describe('ProcessFilterDialogCloudComponent', () => { it('should able close dialog on click of cancel button', () => { component.data = { data: { name: '' } }; - let cancelButton = fixture.debugElement.nativeElement.querySelector( + const cancelButton = fixture.debugElement.nativeElement.querySelector( '#adf-cancel-button-id' ); fixture.detectChanges(); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.spec.ts index 596be8c1a9..249f2dff48 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.spec.ts @@ -31,7 +31,7 @@ describe('ProcessFiltersCloudComponent', () => { let processFilterService: ProcessFilterCloudService; - let fakeGlobalFilter = [ + const fakeGlobalFilter = [ new ProcessFilterCloudModel({ name: 'FakeAllProcesses', icon: 'adjust', @@ -54,21 +54,21 @@ describe('ProcessFiltersCloudComponent', () => { }) ]; - let fakeGlobalFilterObservable = + const fakeGlobalFilterObservable = new Observable(function(observer) { observer.next(fakeGlobalFilter); observer.complete(); }); - let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + const fakeGlobalFilterPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalFilter); }); - let mockErrorFilterList = { + const mockErrorFilterList = { error: 'wrong request' }; - let mockErrorFilterPromise = Promise.reject(mockErrorFilterList); + const mockErrorFilterPromise = Promise.reject(mockErrorFilterList); let component: ProcessFiltersCloudComponent; let fixture: ComponentFixture<ProcessFiltersCloudComponent>; @@ -87,14 +87,14 @@ describe('ProcessFiltersCloudComponent', () => { it('should attach specific icon for each filter if hasIcon is true', async(() => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(fakeGlobalFilterObservable); - let change = new SimpleChange(undefined, 'my-app-1', true); + const change = new SimpleChange(undefined, 'my-app-1', true); component.ngOnChanges({'appName': change}); fixture.detectChanges(); component.showIcons = true; fixture.whenStable().then(() => { fixture.detectChanges(); expect(component.filters.length).toBe(3); - let filters = fixture.nativeElement.querySelectorAll('.adf-filters__entry-icon'); + const filters = fixture.nativeElement.querySelectorAll('.adf-filters__entry-icon'); expect(filters.length).toBe(3); expect(filters[0].innerText).toContain('adjust'); expect(filters[1].innerText).toContain('inbox'); @@ -106,13 +106,13 @@ describe('ProcessFiltersCloudComponent', () => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); component.showIcons = false; - let change = new SimpleChange(undefined, 'my-app-1', true); + const change = new SimpleChange(undefined, 'my-app-1', true); component.ngOnChanges({'appName': change}); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); + const filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); expect(filters.length).toBe(0); done(); }); @@ -120,13 +120,13 @@ describe('ProcessFiltersCloudComponent', () => { it('should display the filters', async(() => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(fakeGlobalFilterObservable); - let change = new SimpleChange(undefined, 'my-app-1', true); + const change = new SimpleChange(undefined, 'my-app-1', true); component.ngOnChanges({'appName': change}); fixture.detectChanges(); component.showIcons = true; fixture.whenStable().then(() => { fixture.detectChanges(); - let filters = fixture.debugElement.queryAll(By.css('mat-list-item[class*="adf-filters__entry"]')); + const filters = fixture.debugElement.queryAll(By.css('mat-list-item[class*="adf-filters__entry"]')); expect(component.filters.length).toBe(3); expect(filters.length).toBe(3); expect(filters[0].nativeElement.innerText).toContain('FakeAllProcesses'); @@ -139,7 +139,7 @@ describe('ProcessFiltersCloudComponent', () => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(mockErrorFilterPromise)); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({'appName': change}); component.error.subscribe((err) => { @@ -151,7 +151,7 @@ describe('ProcessFiltersCloudComponent', () => { it('should emit success with the filters when filters are loaded', (done) => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); component.success.subscribe((res) => { @@ -168,7 +168,7 @@ describe('ProcessFiltersCloudComponent', () => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(fakeGlobalFilterObservable); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.ngOnChanges({ 'appName': change }); @@ -186,7 +186,7 @@ describe('ProcessFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ name: 'FakeRunningProcesses' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.filterClick.subscribe((res) => { expect(res).toBeDefined(); @@ -205,7 +205,7 @@ describe('ProcessFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ key: 'completed-processes' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); @@ -226,7 +226,7 @@ describe('ProcessFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ name: 'UnexistableFilter' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); @@ -247,7 +247,7 @@ describe('ProcessFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ index: 2 }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.filterClick.subscribe((res) => { @@ -267,7 +267,7 @@ describe('ProcessFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ id: '12' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.filterClick.subscribe((res) => { @@ -286,7 +286,7 @@ describe('ProcessFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ id: '10' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); fixture.detectChanges(); @@ -297,7 +297,7 @@ describe('ProcessFiltersCloudComponent', () => { done(); }); - let filterButton = fixture.debugElement.nativeElement.querySelector('span[data-automation-id="FakeRunningProcesses_filter"]'); + const filterButton = fixture.debugElement.nativeElement.querySelector('span[data-automation-id="FakeRunningProcesses_filter"]'); filterButton.click(); }); @@ -305,7 +305,7 @@ describe('ProcessFiltersCloudComponent', () => { spyOn(component, 'getFilters').and.stub(); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); expect(component.getFilters).toHaveBeenCalledWith(appName); @@ -315,7 +315,7 @@ describe('ProcessFiltersCloudComponent', () => { spyOn(component, 'getFilters').and.stub(); const appName = null; - let change = new SimpleChange(undefined, appName, true); + const change = new SimpleChange(undefined, appName, true); component.ngOnChanges({ 'appName': change }); expect(component.getFilters).not.toHaveBeenCalledWith(appName); @@ -337,14 +337,14 @@ describe('ProcessFiltersCloudComponent', () => { spyOn(component, 'getFilters').and.stub(); const appName = 'fake-app-name'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); expect(component.getFilters).toHaveBeenCalledWith(appName); }); it('should return the current filter after one is selected', () => { - let filter = fakeGlobalFilter[1]; + const filter = fakeGlobalFilter[1]; component.filters = fakeGlobalFilter; expect(component.currentFilter).toBeUndefined(); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.ts index 6d4894fa1e..c74d578214 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.ts @@ -103,8 +103,8 @@ export class ProcessFilterCloudService { const user: IdentityUserModel = this.identityUserService.getCurrentUserInfo(); const key = `process-filters-${filter.appName}-${user.username}`; if (key) { - let filters = JSON.parse(this.storage.getItem(key) || '[]'); - let itemIndex = filters.findIndex((flt: ProcessFilterCloudModel) => flt.id === filter.id); + const filters = JSON.parse(this.storage.getItem(key) || '[]'); + const itemIndex = filters.findIndex((flt: ProcessFilterCloudModel) => flt.id === filter.id); filters[itemIndex] = filter; this.storage.setItem(key, JSON.stringify(filters)); this.addFiltersToStream(filters); diff --git a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts index 3e5551ee2e..92c58f4c18 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts @@ -45,7 +45,7 @@ export class ProcessHeaderCloudService { getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> { if (appName && processInstanceId) { - let queryUrl = `${this.contextRoot}/${appName}-query/v1/process-instances/${processInstanceId}`; + const queryUrl = `${this.contextRoot}/${appName}-query/v1/process-instances/${processInstanceId}`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', null, null, null, diff --git a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts index d3ee8c3b38..095538c05f 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts @@ -124,7 +124,7 @@ describe('ProcessListCloudComponent', () => { it('should return the results if an application name is given', (done) => { spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList)); - let appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); component.success.subscribe((res) => { expect(res).toBeDefined(); expect(component.rows).toBeDefined(); @@ -164,12 +164,12 @@ describe('ProcessListCloudComponent', () => { }); it('should emit row click event', (done) => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ entry: { id: '999' } }); - let rowEvent = new DataRowEvent(row, null); + const rowEvent = new DataRowEvent(row, null); component.rowClick.subscribe((taskId) => { expect(taskId).toEqual('999'); expect(component.getCurrentId()).toEqual('999'); diff --git a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts index 7ac2a3c7c6..84139f196e 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts @@ -178,7 +178,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan } private isPropertyChanged(changes: SimpleChanges): boolean { - for (let property in changes) { + for (const property in changes) { if (changes.hasOwnProperty(property)) { if (changes[property] && (changes[property].currentValue !== changes[property].previousValue)) { @@ -224,7 +224,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan } private createRequestNode(): ProcessQueryCloudRequestModel { - let requestNode = { + const requestNode = { appName: this.appName, maxItems: this.size, skipCount: this.skipCount, diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts index f36d921db0..44ea2629ee 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts @@ -69,7 +69,7 @@ describe('Activiti ProcessList Cloud Service', () => { })); it('should return the processes', (done) => { - let processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName' }; + const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName' }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returFakeProcessListResults); service.getProcessByRequest(processRequest).subscribe((res) => { expect(res).toBeDefined(); @@ -83,7 +83,7 @@ describe('Activiti ProcessList Cloud Service', () => { }); it('should append to the call all the parameters', (done) => { - let processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; + const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters); service.getProcessByRequest(processRequest).subscribe((res) => { expect(res).toBeDefined(); @@ -96,7 +96,7 @@ describe('Activiti ProcessList Cloud Service', () => { }); it('should concat the app name to the request url', (done) => { - let processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; + const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallUrl); service.getProcessByRequest(processRequest).subscribe((requestUrl) => { expect(requestUrl).toBeDefined(); @@ -107,7 +107,7 @@ describe('Activiti ProcessList Cloud Service', () => { }); it('should concat the sorting to append as parameters', (done) => { - let processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { + const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service', sorting: [{ orderBy: 'NAME', direction: 'DESC' }, { orderBy: 'TITLE', direction: 'ASC' }] }; @@ -121,7 +121,7 @@ describe('Activiti ProcessList Cloud Service', () => { }); it('should return an error when app name is not specified', (done) => { - let processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: null }; + const processRequest: ProcessQueryCloudRequestModel = <ProcessQueryCloudRequestModel> { appName: null }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallUrl); service.getProcessByRequest(processRequest).subscribe( () => { }, diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts index 18df369fb3..ff4ccdda26 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts @@ -37,9 +37,9 @@ export class ProcessListCloudService { */ getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> { if (requestNode.appName) { - let queryUrl = this.buildQueryUrl(requestNode); - let queryParams = this.buildQueryParams(requestNode); - let sortingParams = this.buildSortingParam(requestNode.sorting); + const queryUrl = this.buildQueryUrl(requestNode); + const queryParams = this.buildQueryParams(requestNode); + const sortingParams = this.buildSortingParam(requestNode.sorting); if (sortingParams) { queryParams['sort'] = sortingParams; } @@ -63,8 +63,8 @@ export class ProcessListCloudService { } private buildQueryParams(requestNode: ProcessQueryCloudRequestModel) { - let queryParam = {}; - for (let property in requestNode) { + const queryParam = {}; + for (const property in requestNode) { if (requestNode.hasOwnProperty(property) && !this.isExcludedField(property) && this.isPropertyValueValid(requestNode, property)) { @@ -81,7 +81,7 @@ export class ProcessListCloudService { private buildSortingParam(sortings: ProcessListCloudSortingModel[]): string { let finalSorting: string = ''; if (sortings) { - for (let sort of sortings) { + for (const sort of sortings) { if (!finalSorting) { finalSorting = `${sort.orderBy},${sort.direction}`; } else { diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts index f3bea343a8..af61c75319 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.spec.ts @@ -80,7 +80,7 @@ describe('StartProcessCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn.disabled).toBe(false); }); })); @@ -91,7 +91,7 @@ describe('StartProcessCloudComponent', () => { component.processForm.controls['processDefinition'].setValue(fakeProcessInstance.name); fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn.disabled).toBe(true); }); })); @@ -100,7 +100,7 @@ describe('StartProcessCloudComponent', () => { component.processPayloadCloud.processDefinitionKey = null; fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn.disabled).toBe(true); }); })); @@ -113,7 +113,7 @@ describe('StartProcessCloudComponent', () => { component.name = 'My new process'; component.appName = 'myApp'; fixture.detectChanges(); - let change = new SimpleChange(null, 'MyApp', true); + const change = new SimpleChange(null, 'MyApp', true); component.ngOnChanges({ 'appName': change }); fixture.detectChanges(); }); @@ -126,7 +126,7 @@ describe('StartProcessCloudComponent', () => { it('should display the correct number of processes in the select list', () => { fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('mat-select'); + const selectElement = fixture.nativeElement.querySelector('mat-select'); expect(selectElement.children.length).toBe(1); }); }); @@ -135,8 +135,8 @@ describe('StartProcessCloudComponent', () => { component.processDefinitionList = fakeProcessDefinitions; fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('mat-select > .mat-select-trigger'); - let optionElement = fixture.nativeElement.querySelectorAll('mat-option'); + const selectElement = fixture.nativeElement.querySelector('mat-select > .mat-select-trigger'); + const optionElement = fixture.nativeElement.querySelectorAll('mat-option'); selectElement.click(); expect(selectElement).not.toBeNull(); expect(selectElement).toBeDefined(); @@ -147,19 +147,19 @@ describe('StartProcessCloudComponent', () => { it('should indicate an error to the user if process defs cannot be loaded', async(() => { getDefinitionsSpy = getDefinitionsSpy.and.returnValue(throwError({})); - let change = new SimpleChange('myApp', 'myApp1', true); + const change = new SimpleChange('myApp', 'myApp1', true); component.ngOnChanges({ appName: change }); fixture.detectChanges(); fixture.whenStable().then(() => { - let errorEl = fixture.nativeElement.querySelector('#error-message'); + const errorEl = fixture.nativeElement.querySelector('#error-message'); expect(errorEl.innerText.trim()).toBe('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.LOAD_PROCESS_DEFS'); }); })); it('should show no process available message when no process definition is loaded', async(() => { getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([])); - let change = new SimpleChange('myApp', 'myApp1', true); + const change = new SimpleChange('myApp', 'myApp1', true); component.ngOnChanges({ appName: change }); fixture.detectChanges(); @@ -182,7 +182,7 @@ describe('StartProcessCloudComponent', () => { it('should select automatically the processDefinition if the app contain only one', async(() => { getDefinitionsSpy = getDefinitionsSpy.and.returnValue(of([fakeProcessDefinitions[0]])); - let change = new SimpleChange('myApp', 'myApp1', true); + const change = new SimpleChange('myApp', 'myApp1', true); component.ngOnChanges({ appName: change }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -210,7 +210,7 @@ describe('StartProcessCloudComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); + const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); expect(selectElement).toBeNull(); }); })); @@ -224,7 +224,7 @@ describe('StartProcessCloudComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); + const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); expect(selectElement).not.toBeNull(); }); })); @@ -237,7 +237,7 @@ describe('StartProcessCloudComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); + const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); expect(selectElement).not.toBeNull(); }); })); @@ -246,7 +246,7 @@ describe('StartProcessCloudComponent', () => { describe('input changes', () => { - let change = new SimpleChange('myApp', 'myApp1', true); + const change = new SimpleChange('myApp', 'myApp1', true); beforeEach(async(() => { component.appName = 'myApp'; @@ -294,7 +294,7 @@ describe('StartProcessCloudComponent', () => { component.processForm.controls['processInstanceName'].setValue(''); component.processForm.controls['processDefinition'].setValue(''); fixture.whenStable().then(() => { - let startProcessButton = fixture.debugElement.query(By.css('[data-automation-id="btn-start"]')); + const startProcessButton = fixture.debugElement.query(By.css('[data-automation-id="btn-start"]')); expect(startProcessButton.nativeElement.disabled).toBeTruthy(); }); })); @@ -308,7 +308,7 @@ describe('StartProcessCloudComponent', () => { })); it('should call service to start process with the variables setted', async(() => { - let inputProcessVariable: Map<string, object>[] = []; + const inputProcessVariable: Map<string, object>[] = []; inputProcessVariable['name'] = {value: 'Josh'}; component.variables = inputProcessVariable; @@ -321,7 +321,7 @@ describe('StartProcessCloudComponent', () => { })); it('should output start event when process started successfully', async(() => { - let emitSpy = spyOn(component.success, 'emit'); + const emitSpy = spyOn(component.success, 'emit'); component.processPayloadCloud = fakeProcessPayload; component.startProcess(); fixture.whenStable().then(() => { @@ -330,8 +330,8 @@ describe('StartProcessCloudComponent', () => { })); it('should throw error event when process cannot be started', async(() => { - let errorSpy = spyOn(component.error, 'emit'); - let error = { message: 'My error' }; + const errorSpy = spyOn(component.error, 'emit'); + const error = { message: 'My error' }; startProcessSpy = startProcessSpy.and.returnValue(throwError(error)); component.processPayloadCloud = fakeProcessPayload; component.startProcess(); @@ -342,19 +342,19 @@ describe('StartProcessCloudComponent', () => { it('should indicate an error to the user if process cannot be started', async(() => { getDefinitionsSpy.and.returnValue(of(fakeProcessDefinitions)); - let change = new SimpleChange('myApp', 'myApp1', true); + const change = new SimpleChange('myApp', 'myApp1', true); component.ngOnChanges({ appName: change }); startProcessSpy = startProcessSpy.and.returnValue(throwError({})); component.startProcess(); fixture.detectChanges(); fixture.whenStable().then(() => { - let errorEl = fixture.nativeElement.querySelector('#error-message'); + const errorEl = fixture.nativeElement.querySelector('#error-message'); expect(errorEl.innerText.trim()).toBe('ADF_CLOUD_PROCESS_LIST.ADF_CLOUD_START_PROCESS.ERROR.START'); }); })); it('should emit start event when start select a process and add a name', (done) => { - let disposableStart = component.success.subscribe(() => { + const disposableStart = component.success.subscribe(() => { disposableStart.unsubscribe(); done(); }); @@ -369,7 +369,7 @@ describe('StartProcessCloudComponent', () => { component.processForm.controls['processInstanceName'].setValue('My Process 1'); component.processForm.controls['processDefinition'].setValue('NewProcess 1'); - let disposableStart = component.success.subscribe(() => { + const disposableStart = component.success.subscribe(() => { disposableStart.unsubscribe(); done(); }); @@ -381,7 +381,7 @@ describe('StartProcessCloudComponent', () => { component.maxNameLength = 2; component.ngOnInit(); fixture.detectChanges(); - let processInstanceName = component.processForm.controls['processInstanceName']; + const processInstanceName = component.processForm.controls['processInstanceName']; processInstanceName.setValue('task'); fixture.detectChanges(); expect(processInstanceName.valid).toBeFalsy(); @@ -392,7 +392,7 @@ describe('StartProcessCloudComponent', () => { it('should emit error when process name field is empty', () => { fixture.detectChanges(); - let processInstanceName = component.processForm.controls['processInstanceName']; + const processInstanceName = component.processForm.controls['processInstanceName']; processInstanceName.setValue(''); fixture.detectChanges(); expect(processInstanceName.valid).toBeFalsy(); diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts index c00726ecce..9814ad4f66 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts @@ -140,7 +140,7 @@ export class StartProcessCloudComponent implements OnChanges, OnInit { } private selectDefaultProcessDefinition() { - let selectedProcess = this.getProcessDefinitionByName(this.processDefinitionName); + const selectedProcess = this.getProcessDefinitionByName(this.processDefinitionName); if (selectedProcess) { this.processForm.controls['processDefinition'].setValue(selectedProcess.name); this.processPayloadCloud.processDefinitionKey = selectedProcess.key; diff --git a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts index f58ed199f4..9a664b5307 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts @@ -47,7 +47,7 @@ export class StartProcessCloudService { getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> { if (appName) { - let queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-definitions`; + const queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-definitions`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', @@ -75,7 +75,7 @@ export class StartProcessCloudService { */ startProcess(appName: string, requestPayload: ProcessPayloadCloud): Observable<ProcessInstanceCloud> { - let queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-instances`; + const queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-instances`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index c353cb0d3f..42af23d8ce 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -103,7 +103,7 @@ export class TaskCloudService { claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; + const queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', null, null, null, @@ -131,7 +131,7 @@ export class TaskCloudService { unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/release`; + const queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/release`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', null, null, null, @@ -159,7 +159,7 @@ export class TaskCloudService { getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - let queryUrl = `${this.contextRoot}/${appName}-query/v1/tasks/${taskId}`; + const queryUrl = `${this.contextRoot}/${appName}-query/v1/tasks/${taskId}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', null, null, null, @@ -190,7 +190,7 @@ export class TaskCloudService { updatePayload.payloadType = 'UpdateTaskPayload'; - let queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}`; + const queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'PUT', null, null, null, diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 836678ba92..5b188b5c87 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -56,7 +56,7 @@ describe('PeopleCloudComponent', () => { it('should show the users if the typed result match', async(() => { component.searchUsers$ = of(<IdentityUserModel[]> mockUsers); fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.dispatchEvent(new Event('input')); inputHTMLElement.dispatchEvent(new Event('keyup')); @@ -71,7 +71,7 @@ describe('PeopleCloudComponent', () => { it('should hide result list if input is empty', async(() => { fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = ''; inputHTMLElement.dispatchEvent(new Event('keyup')); @@ -85,7 +85,7 @@ describe('PeopleCloudComponent', () => { it('should emit selectedUser if option is valid', async(() => { fixture.detectChanges(); - let selectEmitSpy = spyOn(component.selectUser, 'emit'); + const selectEmitSpy = spyOn(component.selectUser, 'emit'); component.onSelect(new IdentityUserModel({ username: 'username' })); fixture.whenStable().then(() => { expect(selectEmitSpy).toHaveBeenCalled(); @@ -174,7 +174,7 @@ describe('PeopleCloudComponent', () => { it('should emit removeUser when a selected user is removed if mode=multiple', async(() => { spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers)); - let removeUserSpy = spyOn(component.removeUser, 'emit'); + const removeUserSpy = spyOn(component.removeUser, 'emit'); component.mode = 'multiple'; component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; @@ -193,7 +193,7 @@ describe('PeopleCloudComponent', () => { it('should list users who have access to the app when appName is specified', async(() => { component.appName = 'sample-app'; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -210,7 +210,7 @@ describe('PeopleCloudComponent', () => { component.appName = 'sample-app'; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -226,7 +226,7 @@ describe('PeopleCloudComponent', () => { component.appName = 'sample-app'; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -239,7 +239,7 @@ describe('PeopleCloudComponent', () => { it('should not validate access to the app when appName is not specified', async(() => { fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -254,7 +254,7 @@ describe('PeopleCloudComponent', () => { const checkUserHasRoleSpy = spyOn(identityService, 'checkUserHasRole').and.returnValue(of(true)); component.roles = ['mock-role-1']; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -270,7 +270,7 @@ describe('PeopleCloudComponent', () => { component.appName = ''; component.roles = ['mock-role-10']; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -286,7 +286,7 @@ describe('PeopleCloudComponent', () => { component.appName = ''; component.roles = []; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.value = 'M'; inputHTMLElement.dispatchEvent(new Event('input')); @@ -320,7 +320,7 @@ describe('PeopleCloudComponent', () => { it('should not validate preselect values if preselectValidation flag is set to false', () => { component.mode = 'multiple'; component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - let change = new SimpleChange(null, 'validate', false); + const change = new SimpleChange(null, 'validate', false); component.ngOnChanges({'validate': change}); fixture.whenStable().then(() => { fixture.detectChanges(); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts index 5fc1b99349..8319a5e89c 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts @@ -314,7 +314,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges { } public async loadMultiplePreselectUsers() { - let users = await this.validatePreselectUsers(); + const users = await this.validatePreselectUsers(); this.checkPreselectValidationErrors(); this.preSelectUsers = [...users]; this.selectedUsersSubject.next(users); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts index e033b20fb0..2c929d9c73 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts @@ -68,10 +68,10 @@ describe('StartTaskCloudComponent', () => { describe('create task', () => { it('should create new task when start button is clicked', async(() => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -81,11 +81,11 @@ describe('StartTaskCloudComponent', () => { })); it('should send on success event when the task is started', async(() => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); component.assigneeName = 'fake-assignee'; fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -94,10 +94,10 @@ describe('StartTaskCloudComponent', () => { })); it('should send on success event when only name is given', async(() => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -106,10 +106,10 @@ describe('StartTaskCloudComponent', () => { })); it('should not emit success event when data not present', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue(''); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(createNewTaskSpy).not.toHaveBeenCalled(); expect(successSpy).not.toHaveBeenCalled(); @@ -133,7 +133,7 @@ describe('StartTaskCloudComponent', () => { it('should assign task to the logged in user when assignee is not selected', async(() => { component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -160,14 +160,14 @@ describe('StartTaskCloudComponent', () => { it('should disable start button if name is empty', () => { component.taskForm.controls['name'].setValue(''); fixture.detectChanges(); - let createTaskButton = fixture.nativeElement.querySelector('#button-start'); + const createTaskButton = fixture.nativeElement.querySelector('#button-start'); expect(createTaskButton.disabled).toBeTruthy(); }); it('should cancel start task on cancel button click', () => { fixture.detectChanges(); - let emitSpy = spyOn(component.cancel, 'emit'); - let cancelTaskButton = fixture.nativeElement.querySelector('#button-cancel'); + const emitSpy = spyOn(component.cancel, 'emit'); + const cancelTaskButton = fixture.nativeElement.querySelector('#button-cancel'); cancelTaskButton.click(); expect(emitSpy).not.toBeNull(); expect(emitSpy).toHaveBeenCalled(); @@ -176,15 +176,15 @@ describe('StartTaskCloudComponent', () => { it('should enable start button if name is filled out', () => { component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = fixture.nativeElement.querySelector('#button-start'); + const createTaskButton = fixture.nativeElement.querySelector('#button-start'); expect(createTaskButton.disabled).toBeFalsy(); }); it('should emit error when there is an error while creating task', () => { component.taskForm.controls['name'].setValue('fakeName'); - let errorSpy = spyOn(component.error, 'emit'); + const errorSpy = spyOn(component.error, 'emit'); createNewTaskSpy.and.returnValue(throwError({})); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); fixture.detectChanges(); createTaskButton.click(); expect(errorSpy).toHaveBeenCalled(); @@ -194,7 +194,7 @@ describe('StartTaskCloudComponent', () => { component.maxNameLength = 2; component.ngOnInit(); fixture.detectChanges(); - let name = component.taskForm.controls['name']; + const name = component.taskForm.controls['name']; name.setValue('task'); fixture.detectChanges(); expect(name.valid).toBeFalsy(); @@ -205,7 +205,7 @@ describe('StartTaskCloudComponent', () => { it('should emit error when task name field is empty', () => { fixture.detectChanges(); - let name = component.taskForm.controls['name']; + const name = component.taskForm.controls['name']; name.setValue(''); fixture.detectChanges(); expect(name.valid).toBeFalsy(); @@ -215,7 +215,7 @@ describe('StartTaskCloudComponent', () => { }); it('should emit error when description have only white spaces', () => { fixture.detectChanges(); - let description = component.taskForm.controls['description']; + const description = component.taskForm.controls['description']; description.setValue(' '); fixture.detectChanges(); expect(description.valid).toBeFalsy(); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts index 53087ac2b3..dc16962fa0 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts @@ -177,7 +177,7 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { this.dateError = false; if (newDateValue) { - let momentDate = moment(newDateValue, this.DATE_FORMAT, true); + const momentDate = moment(newDateValue, this.DATE_FORMAT, true); if (!momentDate.isValid()) { this.dateError = true; } diff --git a/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts index 7468ea239b..c265ab998d 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts @@ -41,7 +41,7 @@ export class StartTaskCloudService { * @returns Details of the newly created task */ createNewTask(taskDetails: TaskDetailsCloudModel): Observable<TaskDetailsCloudModel> { - let queryUrl = this.buildCreateTaskUrl(taskDetails.appName); + const queryUrl = this.buildCreateTaskUrl(taskDetails.appName); const bodyParam = JSON.stringify(this.buildRequestBody(taskDetails)); const pathParams = {}, queryParams = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts index c7c1afe197..bb5c1fb0c1 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts @@ -67,7 +67,7 @@ describe('EditTaskFilterCloudComponent', () => { }); it('should fetch task filter by taskId', async(() => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -81,7 +81,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should display filter name as title', () => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-task-filter-title-id'); @@ -95,7 +95,7 @@ describe('EditTaskFilterCloudComponent', () => { describe('EditTaskFilter form', () => { beforeEach(() => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({'id': taskFilterIDchange}); fixture.detectChanges(); }); @@ -126,22 +126,22 @@ describe('EditTaskFilterCloudComponent', () => { it('should disable save button if the task filter is not changed', async(() => { component.toggleFilterActions = true; - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); expect(saveButton.disabled).toBe(true); }); })); it('should disable saveAs button if the task filter is not changed', async(() => { component.toggleFilterActions = true; - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); expect(saveButton.disabled).toBe(true); }); })); @@ -149,11 +149,11 @@ describe('EditTaskFilterCloudComponent', () => { it('should enable delete button by default', async(() => { component.toggleFilterActions = true; fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); + const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); expect(deleteButton.disabled).toBe(false); }); })); @@ -161,13 +161,13 @@ describe('EditTaskFilterCloudComponent', () => { it('should display current task filter details', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-status"]'); - let assigneeElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-assignee"]'); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); - let orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-status"]'); + const assigneeElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-assignee"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); + const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]'); expect(stateElement).toBeDefined(); expect(assigneeElement).toBeDefined(); expect(sortElement).toBeDefined(); @@ -180,10 +180,10 @@ describe('EditTaskFilterCloudComponent', () => { it('should display status drop down', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-status"] .mat-select-trigger'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-status"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -194,10 +194,10 @@ describe('EditTaskFilterCloudComponent', () => { it('should display sort drop down', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -208,10 +208,10 @@ describe('EditTaskFilterCloudComponent', () => { it('should display order drop down', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]'); + const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-order"]'); orderElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -221,7 +221,7 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should able to build a editTaskFilter form with default properties if input is empty', async(() => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); component.filterProperties = []; fixture.detectChanges(); @@ -245,7 +245,7 @@ describe('EditTaskFilterCloudComponent', () => { it('should able to fetch running applications when appName property defined in the input', async(() => { component.filterProperties = ['appName', 'processInstanceId', 'priority']; fixture.detectChanges(); - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); const appController = component.editTaskFilterForm.get('appName'); fixture.detectChanges(); @@ -260,13 +260,13 @@ describe('EditTaskFilterCloudComponent', () => { describe('sort properties', () => { it('should display default sort properties', async(() => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -282,13 +282,13 @@ describe('EditTaskFilterCloudComponent', () => { component.sortProperties = ['id', 'name', 'processInstanceId']; getTaskFilterSpy.and.returnValue({ sort: 'my-custom-sort', processInstanceId: 'process-instance-id', priority: '12' }); fixture.detectChanges(); - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -303,15 +303,15 @@ describe('EditTaskFilterCloudComponent', () => { })); it('should display default sort properties if input is empty', async(() => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); component.sortProperties = []; fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"]'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -328,10 +328,10 @@ describe('EditTaskFilterCloudComponent', () => { it('should display default filter actions', async(() => { component.toggleFilterActions = true; - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -352,12 +352,12 @@ describe('EditTaskFilterCloudComponent', () => { it('should display filter actions when input actions are specified', async(() => { component.actions = ['save']; fixture.detectChanges(); - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); component.toggleFilterActions = true; fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -372,10 +372,10 @@ describe('EditTaskFilterCloudComponent', () => { it('should display default filter actions if input is empty', async(() => { component.toggleFilterActions = true; component.actions = []; - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -397,7 +397,7 @@ describe('EditTaskFilterCloudComponent', () => { describe('edit filter actions', () => { beforeEach(() => { - let taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); component.ngOnChanges({ 'id': taskFilterIDchange}); fixture.detectChanges(); @@ -406,12 +406,12 @@ describe('EditTaskFilterCloudComponent', () => { it('should emit save event and save the filter on click save button', async(() => { component.toggleFilterActions = true; const saveFilterSpy = spyOn(service, 'updateFilter').and.returnValue(fakeFilter); - let saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); + const saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); const sortOptions = fixture.debugElement.queryAll(By.css('.mat-option-text')); @@ -429,15 +429,15 @@ describe('EditTaskFilterCloudComponent', () => { it('should emit delete event and delete the filter on click of delete button', async(() => { component.toggleFilterActions = true; const deleteFilterSpy = spyOn(service, 'deleteFilter').and.callThrough(); - let deleteSpy: jasmine.Spy = spyOn(component.action, 'emit'); + const deleteSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); - let deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); + const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); deleteButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -449,12 +449,12 @@ describe('EditTaskFilterCloudComponent', () => { it('should emit saveAs event and add filter on click saveAs button', async(() => { component.toggleFilterActions = true; const saveAsFilterSpy = spyOn(service, 'addFilter').and.callThrough(); - let saveAsSpy: jasmine.Spy = spyOn(component.action, 'emit'); + const saveAsSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-task-property-sort"] .mat-select-trigger'); sortElement.click(); fixture.detectChanges(); const saveAsButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts index 1b4b07b9ed..7d20988087 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts @@ -259,7 +259,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges { onDateChanged(newDateValue: any, dateProperty: TaskFilterProperties) { if (newDateValue) { - let momentDate = moment(newDateValue, this.FORMAT_DATE, true); + const momentDate = moment(newDateValue, this.FORMAT_DATE, true); if (momentDate.isValid()) { this.getPropertyController(dateProperty).setValue(momentDate.toDate()); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filter-dialog-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filter-dialog-cloud.component.spec.ts index 369f1f8094..490a26de3b 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filter-dialog-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filter-dialog-cloud.component.spec.ts @@ -62,13 +62,13 @@ describe('TaskFilterDialogCloudComponent', () => { it('should display title', () => { fixture.detectChanges(); - let titleElement = fixture.debugElement.nativeElement.querySelector('#adf-task-filter-dialog-title'); + const titleElement = fixture.debugElement.nativeElement.querySelector('#adf-task-filter-dialog-title'); expect(titleElement.textContent).toEqual(' ADF_CLOUD_EDIT_TASK_FILTER.DIALOG.TITLE '); }); it('should enable save button if form is valid', async(() => { fixture.detectChanges(); - let saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id'); + const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id'); const inputElement = fixture.debugElement.nativeElement.querySelector('#adf-filter-name-id'); inputElement.value = 'My custom Name'; inputElement.dispatchEvent(new Event('input')); @@ -85,7 +85,7 @@ describe('TaskFilterDialogCloudComponent', () => { inputElement.value = ''; inputElement.dispatchEvent(new Event('input')); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id'); + const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id'); fixture.detectChanges(); expect(saveButton).toBeDefined(); expect(saveButton.disabled).toBe(true); @@ -98,7 +98,7 @@ describe('TaskFilterDialogCloudComponent', () => { inputElement.value = 'My custom Name'; inputElement.dispatchEvent(new Event('input')); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id'); + const saveButton = fixture.debugElement.nativeElement.querySelector('#adf-save-button-id'); fixture.detectChanges(); saveButton.click(); expect(saveButton).toBeDefined(); @@ -109,7 +109,7 @@ describe('TaskFilterDialogCloudComponent', () => { it('should able close dialog on click of cancel button', () => { component.data = { data: { name: '' } }; - let cancelButton = fixture.debugElement.nativeElement.querySelector('#adf-cancel-button-id'); + const cancelButton = fixture.debugElement.nativeElement.querySelector('#adf-cancel-button-id'); fixture.detectChanges(); cancelButton.click(); expect(cancelButton).toBeDefined(); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts index c16e51c654..fdd952cae4 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.spec.ts @@ -31,21 +31,21 @@ describe('TaskFiltersCloudComponent', () => { let taskFilterService: TaskFilterCloudService; - let fakeGlobalFilterObservable = + const fakeGlobalFilterObservable = new Observable(function(observer) { observer.next(fakeGlobalFilter); observer.complete(); }); - let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + const fakeGlobalFilterPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalFilter); }); - let mockErrorFilterList = { + const mockErrorFilterList = { error: 'wrong request' }; - let mockErrorFilterPromise = Promise.reject(mockErrorFilterList); + const mockErrorFilterPromise = Promise.reject(mockErrorFilterList); let component: TaskFiltersCloudComponent; let fixture: ComponentFixture<TaskFiltersCloudComponent>; @@ -64,14 +64,14 @@ describe('TaskFiltersCloudComponent', () => { it('should attach specific icon for each filter if hasIcon is true', async(() => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable); - let change = new SimpleChange(undefined, 'my-app-1', true); + const change = new SimpleChange(undefined, 'my-app-1', true); component.ngOnChanges({'appName': change}); fixture.detectChanges(); component.showIcons = true; fixture.whenStable().then(() => { fixture.detectChanges(); expect(component.filters.length).toBe(3); - let filters = fixture.nativeElement.querySelectorAll('.adf-filters__entry-icon'); + const filters = fixture.nativeElement.querySelectorAll('.adf-filters__entry-icon'); expect(filters.length).toBe(3); expect(filters[0].innerText).toContain('adjust'); expect(filters[1].innerText).toContain('done'); @@ -83,13 +83,13 @@ describe('TaskFiltersCloudComponent', () => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); component.showIcons = false; - let change = new SimpleChange(undefined, 'my-app-1', true); + const change = new SimpleChange(undefined, 'my-app-1', true); component.ngOnChanges({'appName': change}); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); + const filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); expect(filters.length).toBe(0); done(); }); @@ -97,13 +97,13 @@ describe('TaskFiltersCloudComponent', () => { it('should display the filters', async(() => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable); - let change = new SimpleChange(undefined, 'my-app-1', true); + const change = new SimpleChange(undefined, 'my-app-1', true); component.ngOnChanges({'appName': change}); fixture.detectChanges(); component.showIcons = true; fixture.whenStable().then(() => { fixture.detectChanges(); - let filters = fixture.debugElement.queryAll(By.css('mat-list-item[class*="adf-filters__entry"]')); + const filters = fixture.debugElement.queryAll(By.css('mat-list-item[class*="adf-filters__entry"]')); expect(component.filters.length).toBe(3); expect(filters.length).toBe(3); expect(filters[0].nativeElement.innerText).toContain('FakeInvolvedTasks'); @@ -116,7 +116,7 @@ describe('TaskFiltersCloudComponent', () => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(mockErrorFilterPromise)); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({'appName': change}); component.error.subscribe((err) => { @@ -128,7 +128,7 @@ describe('TaskFiltersCloudComponent', () => { it('should return the filter task list', (done) => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); component.success.subscribe((res) => { @@ -142,7 +142,7 @@ describe('TaskFiltersCloudComponent', () => { it('should return the filter task list, filtered By Name', (done) => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); component.success.subscribe((res) => { @@ -159,7 +159,7 @@ describe('TaskFiltersCloudComponent', () => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.ngOnChanges({ 'appName': change }); @@ -177,7 +177,7 @@ describe('TaskFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ name: 'FakeMyTasks1' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.ngOnChanges({ 'appName': change }); @@ -196,7 +196,7 @@ describe('TaskFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ name: 'UnexistableFilter' }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.ngOnChanges({ 'appName': change }); @@ -215,7 +215,7 @@ describe('TaskFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ index: 2 }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.ngOnChanges({ 'appName': change }); @@ -233,7 +233,7 @@ describe('TaskFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ id: 12 }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); fixture.detectChanges(); component.ngOnChanges({ 'appName': change }); @@ -252,12 +252,12 @@ describe('TaskFiltersCloudComponent', () => { component.filterParam = new FilterParamsModel({ id: 12 }); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); fixture.detectChanges(); spyOn(component, 'selectFilterAndEmit').and.stub(); - let filterButton = fixture.debugElement.nativeElement.querySelector('span[data-automation-id="fake-my-tast1-filter"]'); + const filterButton = fixture.debugElement.nativeElement.querySelector('span[data-automation-id="fake-my-tast1-filter"]'); filterButton.click(); expect(component.selectFilterAndEmit).toHaveBeenCalledWith({id: fakeGlobalFilter[1].id}); })); @@ -266,7 +266,7 @@ describe('TaskFiltersCloudComponent', () => { spyOn(component, 'getFilters').and.stub(); const appName = 'my-app-1'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); expect(component.getFilters).toHaveBeenCalledWith(appName); @@ -313,14 +313,14 @@ describe('TaskFiltersCloudComponent', () => { spyOn(component, 'getFilters').and.stub(); const appName = 'fake-app-name'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); expect(component.getFilters).toHaveBeenCalledWith(appName); }); it('should return the current filter after one is selected', () => { - let filter = new FilterParamsModel({ name: 'FakeInvolvedTasks' }); + const filter = new FilterParamsModel({ name: 'FakeInvolvedTasks' }); component.filters = fakeGlobalFilter; expect(component.currentFilter).toBeUndefined(); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts index 45abc78fc7..90ed79d974 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts @@ -36,10 +36,10 @@ export class TaskFilterCloudService { * @returns Observable of default filters just created */ private createDefaultFilters(appName: string) { - let myTasksFilter = this.getMyTasksFilterInstance(appName); + const myTasksFilter = this.getMyTasksFilterInstance(appName); this.addFilter(myTasksFilter); - let completedTasksFilter = this.getCompletedTasksFilterInstance(appName); + const completedTasksFilter = this.getCompletedTasksFilterInstance(appName); this.addFilter(completedTasksFilter); } @@ -50,7 +50,7 @@ export class TaskFilterCloudService { */ getTaskListFilters(appName?: string): Observable<TaskFilterCloudModel[]> { const username = this.getUsername(); - let key = `task-filters-${appName}-${username}`; + const key = `task-filters-${appName}-${username}`; const filters = JSON.parse(this.storage.getItem(key) || '[]'); if (filters.length === 0) { @@ -69,7 +69,7 @@ export class TaskFilterCloudService { */ getTaskFilterById(appName: string, id: string): TaskFilterCloudModel { const username = this.getUsername(); - let key = `task-filters-${appName}-${username}`; + const key = `task-filters-${appName}-${username}`; let filters = []; filters = JSON.parse(this.storage.getItem(key)) || []; return filters.filter((filterTmp: TaskFilterCloudModel) => id === filterTmp.id)[0]; @@ -83,7 +83,7 @@ export class TaskFilterCloudService { addFilter(filter: TaskFilterCloudModel) { const username = this.getUsername(); const key = `task-filters-${filter.appName}-${username}`; - let filters = JSON.parse(this.storage.getItem(key) || '[]'); + const filters = JSON.parse(this.storage.getItem(key) || '[]'); filters.push(filter); @@ -104,8 +104,8 @@ export class TaskFilterCloudService { const username = this.getUsername(); const key = `task-filters-${filter.appName}-${username}`; if (key) { - let filters = JSON.parse(this.storage.getItem(key) || '[]'); - let itemIndex = filters.findIndex((flt: TaskFilterCloudModel) => flt.id === filter.id); + const filters = JSON.parse(this.storage.getItem(key) || '[]'); + const itemIndex = filters.findIndex((flt: TaskFilterCloudModel) => flt.id === filter.id); filters[itemIndex] = filter; this.storage.setItem(key, JSON.stringify(filters)); this.addFiltersToStream(filters); diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts index 108a178734..b2db6f5b46 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts @@ -62,7 +62,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams'); }); })); @@ -73,7 +73,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.ASSIGNEE_DEFAULT'); }); @@ -84,7 +84,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]')); + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]')); expect(formNameEl.nativeElement.innerText).toBe('5'); }); })); @@ -94,7 +94,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toBe('Dec 18 2018'); }); })); @@ -105,7 +105,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toBe('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'); }); })); @@ -116,7 +116,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_HEADER.PROPERTIES.PARENT_NAME_DEFAULT'); }); })); @@ -127,7 +127,7 @@ describe('TaskHeaderCloudComponent', () => { spyOn(appConfigService, 'get').and.returnValue(['assignee', 'status']); component.ngOnInit(); fixture.detectChanges(); - let propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); fixture.whenStable().then(() => { expect(propertyList).toBeDefined(); @@ -145,7 +145,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); expect(propertyList).toBeDefined(); expect(propertyList).not.toBeNull(); expect(propertyList.length).toBe(component.properties.length); diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts index c173209509..b9b7b42e30 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts @@ -127,7 +127,7 @@ describe('TaskListCloudComponent', () => { it('should return the results if an application name is given', (done) => { spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask)); - let appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); component.success.subscribe((res) => { expect(res).toBeDefined(); expect(component.rows).toBeDefined(); @@ -174,12 +174,12 @@ describe('TaskListCloudComponent', () => { }); it('should emit row click event', (done) => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ entry: { id: '999' } }); - let rowEvent = new DataRowEvent(row, null); + const rowEvent = new DataRowEvent(row, null); component.rowClick.subscribe((taskId) => { expect(taskId).toEqual('999'); expect(component.getCurrentId()).toEqual('999'); diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts index 0132656712..57125e2520 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts @@ -180,7 +180,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges } private isPropertyChanged(changes: SimpleChanges): boolean { - for (let property in changes) { + for (const property in changes) { if (changes.hasOwnProperty(property)) { if (changes[property] && (changes[property].currentValue !== changes[property].previousValue)) { @@ -250,7 +250,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges private createRequestNode() { - let requestNode = { + const requestNode = { appName: this.appName, assignee: this.assignee, id: this.id, diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts index fc967a7d98..8c17a606c5 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts @@ -71,7 +71,7 @@ describe('Activiti TaskList Cloud Service', () => { })); it('should return the tasks', (done) => { - let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName' }; + const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName' }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskListResults); service.getTaskByRequest(taskRequest).subscribe((res) => { expect(res).toBeDefined(); @@ -84,7 +84,7 @@ describe('Activiti TaskList Cloud Service', () => { }); it('should append to the call all the parameters', (done) => { - let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; + const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters); service.getTaskByRequest(taskRequest).subscribe((res) => { expect(res).toBeDefined(); @@ -97,7 +97,7 @@ describe('Activiti TaskList Cloud Service', () => { }); it('should concat the app name to the request url', (done) => { - let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; + const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallUrl); service.getTaskByRequest(taskRequest).subscribe((requestUrl) => { expect(requestUrl).toBeDefined(); @@ -108,7 +108,7 @@ describe('Activiti TaskList Cloud Service', () => { }); it('should concat the sorting to append as parameters', (done) => { - let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service', + const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service', sorting: [{ orderBy: 'NAME', direction: 'DESC'}, { orderBy: 'TITLE', direction: 'ASC'}] }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters); service.getTaskByRequest(taskRequest).subscribe((res) => { @@ -120,7 +120,7 @@ describe('Activiti TaskList Cloud Service', () => { }); it('should return an error when app name is not specified', (done) => { - let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: null }; + const taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: null }; spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallUrl); service.getTaskByRequest(taskRequest).subscribe( () => { }, diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts index fcc9012df4..3c7d3d966c 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts @@ -39,9 +39,9 @@ export class TaskListCloudService { */ getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> { if (requestNode.appName) { - let queryUrl = this.buildQueryUrl(requestNode); - let queryParams = this.buildQueryParams(requestNode); - let sortingParams = this.buildSortingParam(requestNode.sorting); + const queryUrl = this.buildQueryUrl(requestNode); + const queryParams = this.buildQueryParams(requestNode); + const sortingParams = this.buildSortingParam(requestNode.sorting); if (sortingParams) { queryParams['sort'] = sortingParams; } @@ -62,8 +62,8 @@ export class TaskListCloudService { } private buildQueryParams(requestNode: TaskQueryCloudRequestModel) { - let queryParam = {}; - for (let property in requestNode) { + const queryParam = {}; + for (const property in requestNode) { if (requestNode.hasOwnProperty(property) && !this.isExcludedField(property) && this.isPropertyValueValid(requestNode, property)) { @@ -84,7 +84,7 @@ export class TaskListCloudService { private buildSortingParam(sortings: TaskListCloudSortingModel[]): string { let finalSorting: string = ''; if (sortings) { - for (let sort of sortings) { + for (const sort of sortings) { if (!finalSorting) { finalSorting = `${sort.orderBy},${sort.direction}`; } else { diff --git a/lib/process-services/app-list/apps-list.component.spec.ts b/lib/process-services/app-list/apps-list.component.spec.ts index d000e194f6..49b73495c1 100644 --- a/lib/process-services/app-list/apps-list.component.spec.ts +++ b/lib/process-services/app-list/apps-list.component.spec.ts @@ -65,7 +65,7 @@ describe('AppsListComponent', () => { component.loading = true; fixture.detectChanges(); fixture.whenStable().then(() => { - let loadingSpinner = fixture.nativeElement.querySelector('mat-spinner'); + const loadingSpinner = fixture.nativeElement.querySelector('mat-spinner'); expect(loadingSpinner).toBeDefined(); }); })); @@ -124,7 +124,7 @@ describe('AppsListComponent', () => { }); it('should emit an error when an error occurs loading apps', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); getAppsSpy.and.returnValue(throwError({})); fixture.detectChanges(); expect(emitSpy).toHaveBeenCalled(); @@ -212,7 +212,7 @@ describe('AppsListComponent', () => { }); it('should initially have no app selected', () => { - let selectedEls = debugElement.queryAll(By.css('.selectedIcon')); + const selectedEls = debugElement.queryAll(By.css('.selectedIcon')); expect(selectedEls.length).toBe(0); }); @@ -225,14 +225,14 @@ describe('AppsListComponent', () => { it('should have one app shown as selected after app selected', () => { component.selectApp(deployedApps[1]); fixture.detectChanges(); - let selectedEls = debugElement.queryAll(By.css('.adf-app-listgrid-item-card-actions-icon')); + const selectedEls = debugElement.queryAll(By.css('.adf-app-listgrid-item-card-actions-icon')); expect(selectedEls.length).toBe(1); }); it('should have the correct app shown as selected after app selected', () => { component.selectApp(deployedApps[1]); fixture.detectChanges(); - let appEls = debugElement.queryAll(By.css('.adf-app-listgrid > div')); + const appEls = debugElement.queryAll(By.css('.adf-app-listgrid > div')); expect(appEls[1].query(By.css('.adf-app-listgrid-item-card-actions-icon'))).not.toBeNull(); }); @@ -272,7 +272,7 @@ describe('Custom CustomEmptyAppListTemplateComponent', () => { it('should render the custom no-apps template', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { - let title: any = fixture.debugElement.queryAll(By.css('#custom-id')); + const title: any = fixture.debugElement.queryAll(By.css('#custom-id')); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('No Apps'); }); diff --git a/lib/process-services/app-list/apps-list.component.ts b/lib/process-services/app-list/apps-list.component.ts index 663ad1b380..5b86ff045e 100644 --- a/lib/process-services/app-list/apps-list.component.ts +++ b/lib/process-services/app-list/apps-list.component.ts @@ -147,7 +147,7 @@ export class AppsListComponent implements OnInit, AfterContentInit { } private filterApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] { - let filteredApps: AppDefinitionRepresentationModel[] = []; + const filteredApps: AppDefinitionRepresentationModel[] = []; if (this.filtersAppId) { apps.filter((app: AppDefinitionRepresentationModel) => { this.filtersAppId.forEach((filter) => { diff --git a/lib/process-services/app-list/select-apps-dialog-component.spec.ts b/lib/process-services/app-list/select-apps-dialog-component.spec.ts index 989608dd20..56dd406c25 100644 --- a/lib/process-services/app-list/select-apps-dialog-component.spec.ts +++ b/lib/process-services/app-list/select-apps-dialog-component.spec.ts @@ -52,7 +52,7 @@ export class DialogSelectAppTestComponent { describe('Select app dialog', () => { let fixture: ComponentFixture<DialogSelectAppTestComponent>; let component: DialogSelectAppTestComponent; - let dialogRef = { + const dialogRef = { close: jasmine.createSpy('close') }; let overlayContainerElement: HTMLElement; diff --git a/lib/process-services/attachment/create-process-attachment.component.spec.ts b/lib/process-services/attachment/create-process-attachment.component.spec.ts index 74e5108e4d..61575e4981 100644 --- a/lib/process-services/attachment/create-process-attachment.component.spec.ts +++ b/lib/process-services/attachment/create-process-attachment.component.spec.ts @@ -29,11 +29,11 @@ describe('CreateProcessAttachmentComponent', () => { let fixture: ComponentFixture<CreateProcessAttachmentComponent>; let element: HTMLElement; - let file = new File([new Blob()], 'Test'); - let fileObj = { entry: null, file: file, relativeFolder: '/' }; - let customEvent = { detail: { files: [fileObj] } }; + const file = new File([new Blob()], 'Test'); + const fileObj = { entry: null, file: file, relativeFolder: '/' }; + const customEvent = { detail: { files: [fileObj] } }; - let fakeUploadResponse = { + const fakeUploadResponse = { id: 9999, name: 'BANANA.jpeg', created: '2017-06-12T12:52:11.109Z', @@ -73,7 +73,7 @@ describe('CreateProcessAttachmentComponent', () => { it('should update the processInstanceId when it is changed', () => { component.processInstanceId = null; - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); expect(component.processInstanceId).toBe('123'); @@ -96,7 +96,7 @@ describe('CreateProcessAttachmentComponent', () => { })); it('should allow user to upload files via button', async(() => { - let buttonUpload: HTMLElement = <HTMLElement> element.querySelector('#add_new_process_content_button'); + const buttonUpload: HTMLElement = <HTMLElement> element.querySelector('#add_new_process_content_button'); expect(buttonUpload).toBeDefined(); expect(buttonUpload).not.toBeNull(); @@ -106,7 +106,7 @@ describe('CreateProcessAttachmentComponent', () => { expect(res.id).toBe(9999); }); - let dropEvent = new CustomEvent('upload-files', customEvent); + const dropEvent = new CustomEvent('upload-files', customEvent); buttonUpload.dispatchEvent(dropEvent); fixture.detectChanges(); diff --git a/lib/process-services/attachment/create-process-attachment.component.ts b/lib/process-services/attachment/create-process-attachment.component.ts index f0c9f3bb96..a5227a7386 100644 --- a/lib/process-services/attachment/create-process-attachment.component.ts +++ b/lib/process-services/attachment/create-process-attachment.component.ts @@ -51,11 +51,11 @@ export class CreateProcessAttachmentComponent implements OnChanges { } onFileUpload(event: any) { - let filesList: File[] = event.detail.files.map((obj) => obj.file); + const filesList: File[] = event.detail.files.map((obj) => obj.file); - for (let fileInfoObj of filesList) { - let file: File = fileInfoObj; - let opts = { + for (const fileInfoObj of filesList) { + const file: File = fileInfoObj; + const opts = { isRelatedContent: true }; this.activitiContentService.createProcessRelatedContent(this.processInstanceId, file, opts).subscribe( diff --git a/lib/process-services/attachment/create-task-attachment.component.spec.ts b/lib/process-services/attachment/create-task-attachment.component.spec.ts index 17f9e513e0..d73d3a7890 100644 --- a/lib/process-services/attachment/create-task-attachment.component.spec.ts +++ b/lib/process-services/attachment/create-task-attachment.component.spec.ts @@ -47,15 +47,15 @@ describe('AttachmentComponent', () => { }); it('should not call createTaskRelatedContent service when taskId changed', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); expect(createTaskRelatedContentSpy).not.toHaveBeenCalled(); }); it('should not call createTaskRelatedContent service when there is no file uploaded', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); - let customEvent: any = { + const customEvent: any = { detail: { files: [] } @@ -65,10 +65,10 @@ describe('AttachmentComponent', () => { }); it('should call createTaskRelatedContent service when there is a file uploaded', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'taskId': change}); - let file = new File([new Blob()], 'Test'); - let customEvent = { + const file = new File([new Blob()], 'Test'); + const customEvent = { detail: { files: [ file diff --git a/lib/process-services/attachment/create-task-attachment.component.ts b/lib/process-services/attachment/create-task-attachment.component.ts index 2bcbec6200..62b0704fc1 100644 --- a/lib/process-services/attachment/create-task-attachment.component.ts +++ b/lib/process-services/attachment/create-task-attachment.component.ts @@ -51,11 +51,11 @@ export class AttachmentComponent implements OnChanges { } onFileUpload(event: any) { - let filesList: File[] = event.detail.files.map((obj) => obj.file); + const filesList: File[] = event.detail.files.map((obj) => obj.file); - for (let fileInfoObj of filesList) { - let file: File = fileInfoObj; - let opts = { + for (const fileInfoObj of filesList) { + const file: File = fileInfoObj; + const opts = { isRelatedContent: true }; this.activitiContentService.createTaskRelatedContent(this.taskId, file, opts).subscribe( diff --git a/lib/process-services/attachment/process-attachment-list.component.spec.ts b/lib/process-services/attachment/process-attachment-list.component.spec.ts index 4e572552d2..4077c6b623 100644 --- a/lib/process-services/attachment/process-attachment-list.component.spec.ts +++ b/lib/process-services/attachment/process-attachment-list.component.spec.ts @@ -90,7 +90,7 @@ describe('ProcessAttachmentListComponent', () => { getProcessRelatedContentSpy = spyOn(service, 'getProcessRelatedContent').and.returnValue(of(mockAttachment)); spyOn(service, 'deleteRelatedContent').and.returnValue(of({successCode: true})); - let blobObj = new Blob(); + const blobObj = new Blob(); spyOn(service, 'getFileRawContent').and.returnValue(of(blobObj)); }); @@ -104,21 +104,21 @@ describe('ProcessAttachmentListComponent', () => { }); it('should load attachments when processInstanceId specified', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); expect(getProcessRelatedContentSpy).toHaveBeenCalled(); }); it('should emit an error when an error occurs loading attachments', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); getProcessRelatedContentSpy.and.returnValue(throwError({})); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); expect(emitSpy).toHaveBeenCalled(); }); it('should emit a success event when the attachments are loaded', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.success.subscribe((attachments) => { expect(attachments[0].name).toEqual(mockAttachment.data[0].name); expect(attachments[0].id).toEqual(mockAttachment.data[0].id); @@ -133,7 +133,7 @@ describe('ProcessAttachmentListComponent', () => { }); it('should display attachments when the process has attachments', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.detectChanges(); @@ -143,15 +143,15 @@ describe('ProcessAttachmentListComponent', () => { })); it('should display all actions if attachments are not read only', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.detectChanges(); - let actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); + const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); actionButton.click(); fixture.whenStable().then(() => { fixture.detectChanges(); - let actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; + const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull(); @@ -160,16 +160,16 @@ describe('ProcessAttachmentListComponent', () => { })); it('should not display remove action if attachments are read only', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); component.disabled = true; fixture.detectChanges(); - let actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); + const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); actionButton.click(); fixture.whenStable().then(() => { fixture.detectChanges(); - let actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; + const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).toBeNull(); @@ -184,7 +184,7 @@ describe('ProcessAttachmentListComponent', () => { 'start': 0, 'data': [] })); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'processInstanceId': change}); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -199,7 +199,7 @@ describe('ProcessAttachmentListComponent', () => { 'start': 0, 'data': [] })); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'processInstanceId': change}); component.disabled = true; @@ -217,7 +217,7 @@ describe('ProcessAttachmentListComponent', () => { 'start': 0, 'data': [] })); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'processInstanceId': change}); component.disabled = true; @@ -230,7 +230,7 @@ describe('ProcessAttachmentListComponent', () => { it('should not show the empty list component when the attachments list is not empty for completed process', async(() => { getProcessRelatedContentSpy.and.returnValue(of(mockAttachment)); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({'processInstanceId': change}); component.disabled = true; @@ -251,8 +251,8 @@ describe('ProcessAttachmentListComponent', () => { describe('change detection', () => { - let change = new SimpleChange('123', '456', true); - let nullChange = new SimpleChange('123', null, true); + const change = new SimpleChange('123', '456', true); + const nullChange = new SimpleChange('123', null, true); beforeEach(async(() => { component.processInstanceId = '123'; @@ -325,7 +325,7 @@ describe('Custom CustomEmptyTemplateComponent', () => { it('should render the custom template', async(() => { fixture.whenStable().then(() => { fixture.detectChanges(); - let title: any = fixture.debugElement.queryAll(By.css('[adf-empty-list-header]')); + const title: any = fixture.debugElement.queryAll(By.css('[adf-empty-list-header]')); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('Custom header'); }); diff --git a/lib/process-services/attachment/process-attachment-list.component.ts b/lib/process-services/attachment/process-attachment-list.component.ts index 3f23d324be..233823db40 100644 --- a/lib/process-services/attachment/process-attachment-list.component.ts +++ b/lib/process-services/attachment/process-attachment-list.component.ts @@ -152,17 +152,17 @@ export class ProcessAttachmentListComponent implements OnChanges, AfterContentIn } onShowRowActionsMenu(event: any) { - let viewAction = { + const viewAction = { title: 'ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT', name: 'view' }; - let removeAction = { + const removeAction = { title: 'ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT', name: 'remove' }; - let downloadAction = { + const downloadAction = { title: 'ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT', name: 'download' }; @@ -178,8 +178,8 @@ export class ProcessAttachmentListComponent implements OnChanges, AfterContentIn } onExecuteRowAction(event: any) { - let args = event.value; - let action = args.action; + const args = event.value; + const action = args.action; if (action.name === 'view') { this.emitDocumentContent(args.row.obj); } else if (action.name === 'remove') { @@ -190,7 +190,7 @@ export class ProcessAttachmentListComponent implements OnChanges, AfterContentIn } openContent(event: any): void { - let content = event.value.obj; + const content = event.value.obj; this.emitDocumentContent(content); } diff --git a/lib/process-services/attachment/task-attachment-list.component.spec.ts b/lib/process-services/attachment/task-attachment-list.component.spec.ts index ef58ca6a4e..61b74af8f5 100644 --- a/lib/process-services/attachment/task-attachment-list.component.spec.ts +++ b/lib/process-services/attachment/task-attachment-list.component.spec.ts @@ -86,7 +86,7 @@ describe('TaskAttachmentList', () => { deleteContentSpy = spyOn(service, 'deleteRelatedContent').and.returnValue(of({ successCode: true })); - let blobObj = new Blob(); + const blobObj = new Blob(); getFileRawContentSpy = spyOn(service, 'getFileRawContent').and.returnValue(of(blobObj)); }); @@ -102,21 +102,21 @@ describe('TaskAttachmentList', () => { }); it('should load attachments when taskId specified', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); expect(getTaskRelatedContentSpy).toHaveBeenCalled(); }); it('should emit an error when an error occurs loading attachments', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); getTaskRelatedContentSpy.and.returnValue(throwError({})); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); expect(emitSpy).toHaveBeenCalled(); }); it('should emit a success event when the attachments are loaded', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); disposableSuccess = component.success.subscribe((attachments) => { expect(attachments[0].name).toEqual(mockAttachment.data[0].name); expect(attachments[0].id).toEqual(mockAttachment.data[0].id); @@ -131,7 +131,7 @@ describe('TaskAttachmentList', () => { }); it('should display attachments when the task has attachments', (done) => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); @@ -160,7 +160,7 @@ describe('TaskAttachmentList', () => { 'start': 0, 'data': [] })); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); component.hasCustomTemplate = false; @@ -172,15 +172,15 @@ describe('TaskAttachmentList', () => { })); it('should display all actions if attachments are not read only', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); - let actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); + const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); actionButton.click(); fixture.whenStable().then(() => { fixture.detectChanges(); - let actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; + const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull(); @@ -189,16 +189,16 @@ describe('TaskAttachmentList', () => { })); it('should not display remove action if attachments are read only', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); component.disabled = true; fixture.detectChanges(); - let actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); + const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]'); actionButton.click(); fixture.whenStable().then(() => { fixture.detectChanges(); - let actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; + const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length; expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull(); expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).toBeNull(); @@ -213,7 +213,7 @@ describe('TaskAttachmentList', () => { 'start': 0, 'data': [] })); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -229,7 +229,7 @@ describe('TaskAttachmentList', () => { 'start': 0, 'data': [] })); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); component.disabled = true; @@ -241,7 +241,7 @@ describe('TaskAttachmentList', () => { it('should not show the empty list component when the attachments list is not empty for completed task', (done) => { getTaskRelatedContentSpy.and.returnValue(of(mockAttachment)); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'taskId': change }); component.disabled = true; @@ -346,7 +346,7 @@ describe('Custom CustomEmptyTemplateComponent', () => { it('should render the custom template', async(() => { fixture.whenStable().then(() => { fixture.detectChanges(); - let title: any = fixture.debugElement.queryAll(By.css('[adf-empty-list-header]')); + const title: any = fixture.debugElement.queryAll(By.css('[adf-empty-list-header]')); expect(title.length).toBe(1); expect(title[0].nativeElement.innerText).toBe('Custom header'); }); diff --git a/lib/process-services/attachment/task-attachment-list.component.ts b/lib/process-services/attachment/task-attachment-list.component.ts index 3252017fde..97017c0284 100644 --- a/lib/process-services/attachment/task-attachment-list.component.ts +++ b/lib/process-services/attachment/task-attachment-list.component.ts @@ -122,7 +122,7 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit const opts = 'true'; this.activitiContentService.getTaskRelatedContent(taskId, opts).subscribe( (res: any) => { - let attachList = []; + const attachList = []; res.data.forEach((content) => { attachList.push({ id: content.id, @@ -162,17 +162,17 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit } onShowRowActionsMenu(event: any) { - let viewAction = { + const viewAction = { title: 'ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT', name: 'view' }; - let removeAction = { + const removeAction = { title: 'ADF_TASK_LIST.MENU_ACTIONS.REMOVE_CONTENT', name: 'remove' }; - let downloadAction = { + const downloadAction = { title: 'ADF_TASK_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT', name: 'download' }; @@ -188,8 +188,8 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit } onExecuteRowAction(event: any) { - let args = event.value; - let action = args.action; + const args = event.value; + const action = args.action; if (action.name === 'view') { this.emitDocumentContent(args.row.obj); } else if (action.name === 'remove') { @@ -200,7 +200,7 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit } openContent(event: any): void { - let content = event.value.obj; + const content = event.value.obj; this.emitDocumentContent(content); } diff --git a/lib/process-services/content-widget/attach-file-widget-dialog.component.spec.ts b/lib/process-services/content-widget/attach-file-widget-dialog.component.spec.ts index 49078302a1..2d6505d473 100644 --- a/lib/process-services/content-widget/attach-file-widget-dialog.component.spec.ts +++ b/lib/process-services/content-widget/attach-file-widget-dialog.component.spec.ts @@ -32,7 +32,7 @@ describe('AttachFileWidgetDialogComponent', () => { let widget: AttachFileWidgetDialogComponent; let fixture: ComponentFixture<AttachFileWidgetDialogComponent>; - let data: AttachFileWidgetDialogComponentData = { + const data: AttachFileWidgetDialogComponentData = { title: 'Move along citizen...', actionName: 'move', selected: new EventEmitter<any>(), @@ -94,8 +94,8 @@ describe('AttachFileWidgetDialogComponent', () => { spyOn(authService, 'login').and.returnValue(of({ type: 'type', ticket: 'ticket'})); isLogged = true; let loginButton: HTMLButtonElement = element.querySelector('button[data-automation-id="attach-file-dialog-actions-login"]'); - let usernameInput: HTMLInputElement = element.querySelector('#username'); - let passwordInput: HTMLInputElement = element.querySelector('#password'); + const usernameInput: HTMLInputElement = element.querySelector('#username'); + const passwordInput: HTMLInputElement = element.querySelector('#password'); usernameInput.value = 'fakse-user'; passwordInput.value = 'fakse-user'; usernameInput.dispatchEvent(new Event('input')); @@ -105,7 +105,7 @@ describe('AttachFileWidgetDialogComponent', () => { fixture.whenStable().then(() => { expect(element.querySelector('#attach-file-content-node')).not.toBeNull(); loginButton = element.querySelector('button[data-automation-id="attach-file-dialog-actions-login"]'); - let chooseButton = element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]'); + const chooseButton = element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]'); expect(loginButton).toBeNull(); expect(chooseButton).not.toBeNull(); done(); @@ -137,11 +137,11 @@ describe('AttachFileWidgetDialogComponent', () => { expect(nodeList[0].isFile).toBeTruthy(); done(); }); - let fakeNode: Node = new Node({ id: 'fake', isFile: true}); + const fakeNode: Node = new Node({ id: 'fake', isFile: true}); contentNodePanel.componentInstance.select.emit([fakeNode]); fixture.detectChanges(); fixture.whenStable().then(() => { - let chooseButton: HTMLButtonElement = element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]'); + const chooseButton: HTMLButtonElement = element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]'); chooseButton.click(); }); }); diff --git a/lib/process-services/content-widget/attach-file-widget-dialog.service.spec.ts b/lib/process-services/content-widget/attach-file-widget-dialog.service.spec.ts index d62c040095..1ab346e198 100644 --- a/lib/process-services/content-widget/attach-file-widget-dialog.service.spec.ts +++ b/lib/process-services/content-widget/attach-file-widget-dialog.service.spec.ts @@ -27,7 +27,6 @@ describe('AttachFileWidgetDialogService', () => { let service: AttachFileWidgetDialogService; let materialDialog: MatDialog; let spyOnDialogOpen: jasmine.Spy; - let afterOpenObservable: Subject<any>; setupTestBed({ imports: [ @@ -40,7 +39,7 @@ describe('AttachFileWidgetDialogService', () => { service = TestBed.get(AttachFileWidgetDialogService); materialDialog = TestBed.get(MatDialog); spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({ - afterOpen: () => afterOpenObservable, + afterOpen: () => of({}), afterClosed: () => of({}), componentInstance: { error: new Subject<any>() diff --git a/lib/process-services/content-widget/attach-file-widget-dialog.service.ts b/lib/process-services/content-widget/attach-file-widget-dialog.service.ts index d6f7c33d8d..bbd00536e7 100644 --- a/lib/process-services/content-widget/attach-file-widget-dialog.service.ts +++ b/lib/process-services/content-widget/attach-file-widget-dialog.service.ts @@ -41,7 +41,7 @@ export class AttachFileWidgetDialogService { * @returns Information about the chosen file(s) */ openLogin(ecmHost: string, actionName?: string, context?: string): Observable<Node[]> { - let titleString: string = `Please log in for ${ecmHost}`; + const titleString: string = `Please log in for ${ecmHost}`; const selected = new Subject<Node[]>(); selected.subscribe({ complete: this.close.bind(this) diff --git a/lib/process-services/content-widget/attach-file-widget.component.ts b/lib/process-services/content-widget/attach-file-widget.component.ts index 683604d6c0..1864a0f199 100644 --- a/lib/process-services/content-widget/attach-file-widget.component.ts +++ b/lib/process-services/content-widget/attach-file-widget.component.ts @@ -130,7 +130,7 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements } openSelectDialogFromFileSource() { - let params = this.field.params; + const params = this.field.params; if (this.isDefinedSourceFolder()) { this.contentDialog.openFileBrowseDialogByFolderId(params.fileSource.selectedFolder.pathId).subscribe( (selections: Node[]) => { @@ -183,10 +183,10 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements openSelectDialog(repository) { const accountIdentifier = 'alfresco-' + repository.id + '-' + repository.name; - let currentECMHost = this.getDomainHost(this.appConfigService.get(AppConfigValues.ECMHOST)); - let chosenRepositoryHost = this.getDomainHost(repository.repositoryUrl); + const currentECMHost = this.getDomainHost(this.appConfigService.get(AppConfigValues.ECMHOST)); + const chosenRepositoryHost = this.getDomainHost(repository.repositoryUrl); if (chosenRepositoryHost !== currentECMHost) { - let formattedRepositoryHost = repository.repositoryUrl.replace('/alfresco', ''); + const formattedRepositoryHost = repository.repositoryUrl.replace('/alfresco', ''); this.attachDialogService.openLogin(formattedRepositoryHost).subscribe( (selections: any[]) => { selections.forEach((node) => node.isExternal = true); @@ -229,7 +229,7 @@ export class AttachFileWidgetComponent extends UploadWidgetComponent implements } private getDomainHost(urlToCheck) { - let result = urlToCheck.match('^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/?\n]+)'); + const result = urlToCheck.match('^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/?\n]+)'); return result[1]; } diff --git a/lib/process-services/content-widget/attach-file-widget.components.spec.ts b/lib/process-services/content-widget/attach-file-widget.components.spec.ts index 686b6b62b3..9dafcf1a68 100644 --- a/lib/process-services/content-widget/attach-file-widget.components.spec.ts +++ b/lib/process-services/content-widget/attach-file-widget.components.spec.ts @@ -155,7 +155,7 @@ describe('AttachFileWidgetComponent', () => { spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer)); fixture.detectChanges(); fixture.whenRenderingDone().then(() => { - let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); + const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); expect(attachButton).not.toBeNull(); attachButton.click(); fixture.detectChanges(); @@ -182,7 +182,7 @@ describe('AttachFileWidgetComponent', () => { widget.field.params = <FormFieldMetadata> allSourceParams; fixture.detectChanges(); fixture.whenStable().then(() => { - let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); + const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); expect(attachButton).not.toBeNull(); attachButton.click(); fixture.detectChanges(); @@ -206,7 +206,7 @@ describe('AttachFileWidgetComponent', () => { spyOn(contentNodeDialogService, 'openFileBrowseDialogByFolderId').and.returnValue(of([fakeMinimalNode])); fixture.detectChanges(); fixture.whenStable().then(() => { - let attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); + const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach'); expect(attachButton).not.toBeNull(); attachButton.click(); fixture.detectChanges(); @@ -228,7 +228,7 @@ describe('AttachFileWidgetComponent', () => { spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(of(fakePngAnswer)); fixture.detectChanges(); fixture.whenStable().then(() => { - let inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); + const inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); inputDebugElement.triggerEventHandler('change', { target: { files: [fakePngAnswer] } }); fixture.detectChanges(); @@ -263,7 +263,7 @@ describe('AttachFileWidgetComponent', () => { spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(of(fakePngAnswer)); fixture.detectChanges(); fixture.whenStable().then(() => { - let inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); + const inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach')); inputDebugElement.triggerEventHandler('change', {target: {files: [fakePngAnswer]}}); fixture.detectChanges(); expect(element.querySelector('#file-1155-icon')).not.toBeNull(); @@ -271,7 +271,7 @@ describe('AttachFileWidgetComponent', () => { })); it('should show the action menu', async(() => { - let menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); + const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); expect(menuButton).not.toBeNull(); menuButton.click(); fixture.detectChanges(); @@ -283,7 +283,7 @@ describe('AttachFileWidgetComponent', () => { })); it('should remove file when remove is clicked', async(() => { - let menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); + const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); expect(menuButton).not.toBeNull(); menuButton.click(); fixture.detectChanges(); @@ -297,7 +297,7 @@ describe('AttachFileWidgetComponent', () => { it('should download file when download is clicked', async(() => { spyOn(contentService, 'downloadBlob').and.stub(); - let menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); + const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); expect(menuButton).not.toBeNull(); menuButton.click(); fixture.detectChanges(); @@ -314,7 +314,7 @@ describe('AttachFileWidgetComponent', () => { expect(file).not.toBeNull(); expect(file.id).toBe(1155); }); - let menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); + const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu'); expect(menuButton).not.toBeNull(); menuButton.click(); fixture.detectChanges(); diff --git a/lib/process-services/content-widget/attach-folder-widget.component.ts b/lib/process-services/content-widget/attach-folder-widget.component.ts index cab7da468e..0d38d5ff74 100644 --- a/lib/process-services/content-widget/attach-folder-widget.component.ts +++ b/lib/process-services/content-widget/attach-folder-widget.component.ts @@ -71,7 +71,7 @@ export class AttachFolderWidgetComponent extends WidgetComponent implements OnIn } openSelectDialogFromFileSource() { - let params = this.field.params; + const params = this.field.params; if (this.isDefinedSourceFolder()) { this.contentDialog.openFolderBrowseDialogByFolderId(params.folderSource.selectedFolder.pathId).subscribe( (selections: Node[]) => { diff --git a/lib/process-services/mock/process/process.model.mock.ts b/lib/process-services/mock/process/process.model.mock.ts index f318fca076..a338919174 100644 --- a/lib/process-services/mock/process/process.model.mock.ts +++ b/lib/process-services/mock/process/process.model.mock.ts @@ -32,7 +32,7 @@ export class ProcessList { export class SingleProcessList extends ProcessList { constructor(name?: string) { - let instance = new ProcessInstance({ + const instance = new ProcessInstance({ id: '123', name: name }); diff --git a/lib/process-services/people/components/people-list/people-list.component.spec.ts b/lib/process-services/people/components/people-list/people-list.component.spec.ts index f4dbfa0f98..ade64e0a43 100644 --- a/lib/process-services/people/components/people-list/people-list.component.spec.ts +++ b/lib/process-services/people/components/people-list/people-list.component.spec.ts @@ -45,8 +45,8 @@ describe('PeopleListComponent', () => { })); it('should emit row click event', (done) => { - let row = new ObjectDataRow(fakeUser); - let rowEvent = new DataRowEvent(row, null); + const row = new ObjectDataRow(fakeUser); + const rowEvent = new DataRowEvent(row, null); peopleListComponent.clickRow.subscribe((selectedUser) => { expect(selectedUser.id).toEqual(1); @@ -60,12 +60,12 @@ describe('PeopleListComponent', () => { }); it('should emit row action event', (done) => { - let row = new ObjectDataRow(fakeUser); - let removeObj = { + const row = new ObjectDataRow(fakeUser); + const removeObj = { name: 'remove', title: 'Remove' }; - let rowActionEvent = new DataRowActionEvent(row, removeObj); + const rowActionEvent = new DataRowActionEvent(row, removeObj); peopleListComponent.clickAction.subscribe((selectedAction: UserEventModel) => { expect(selectedAction.type).toEqual('remove'); diff --git a/lib/process-services/people/components/people-list/people-list.component.ts b/lib/process-services/people/components/people-list/people-list.component.ts index 964932fa9a..1d080fb23a 100644 --- a/lib/process-services/people/components/people-list/people-list.component.ts +++ b/lib/process-services/people/components/people-list/people-list.component.ts @@ -69,7 +69,7 @@ export class PeopleListComponent implements AfterViewInit, AfterContentInit { onShowRowActionsMenu(event: any) { - let removeAction = { + const removeAction = { title: 'Remove', name: 'remove' }; @@ -80,8 +80,8 @@ export class PeopleListComponent implements AfterViewInit, AfterContentInit { } onExecuteRowAction(event: any) { - let args = event.value; - let action = args.action; + const args = event.value; + const action = args.action; this.clickAction.emit(new UserEventModel({type: action.name, value: args.row.obj})); } } diff --git a/lib/process-services/people/components/people-search-field/people-search-field.component.spec.ts b/lib/process-services/people/components/people-search-field/people-search-field.component.spec.ts index 4f52a77efb..045c42a086 100644 --- a/lib/process-services/people/components/people-search-field/people-search-field.component.spec.ts +++ b/lib/process-services/people/components/people-search-field/people-search-field.component.spec.ts @@ -40,7 +40,7 @@ describe('PeopleSearchFieldComponent', () => { }); it('should have the proper placeholder by default', () => { - let searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement; + const searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement; expect(searchField.placeholder).toBe('ADF_TASK_LIST.PEOPLE.SEARCH_USER'); }); @@ -49,7 +49,7 @@ describe('PeopleSearchFieldComponent', () => { fixture.detectChanges(); - let searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement; + const searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement; expect(searchField.placeholder).toBe('Arcadia Bay'); }); diff --git a/lib/process-services/people/components/people-search/people-search.component.spec.ts b/lib/process-services/people/components/people-search/people-search.component.spec.ts index e0f4e18a98..3e447115c2 100644 --- a/lib/process-services/people/components/people-search/people-search.component.spec.ts +++ b/lib/process-services/people/components/people-search/people-search.component.spec.ts @@ -40,7 +40,7 @@ describe('PeopleSearchComponent', () => { let peopleSearchComponent: PeopleSearchComponent; let fixture: ComponentFixture<PeopleSearchComponent>; let element: HTMLElement; - let userArray = [fakeUser, fakeSecondUser]; + const userArray = [fakeUser, fakeSecondUser]; let searchInput: any; setupTestBed({ @@ -80,7 +80,7 @@ describe('PeopleSearchComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); - let gatewayElement: any = element.querySelector('#search-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#search-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(2); done(); @@ -99,7 +99,7 @@ describe('PeopleSearchComponent', () => { fixture.whenStable() .then(() => { peopleSearchComponent.onRowClick(fakeUser); - let addUserButton = <HTMLElement> element.querySelector('#add-people'); + const addUserButton = <HTMLElement> element.querySelector('#add-people'); addUserButton.click(); }); }); @@ -115,14 +115,14 @@ describe('PeopleSearchComponent', () => { fixture.detectChanges(); peopleSearchComponent.onRowClick(fakeUser); - let addUserButton = <HTMLElement> element.querySelector('#add-people'); + const addUserButton = <HTMLElement> element.querySelector('#add-people'); addUserButton.click(); fixture.detectChanges(); fixture.whenStable() .then(() => { fixture.detectChanges(); - let gatewayElement: any = element.querySelector('#search-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#search-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(1); done(); diff --git a/lib/process-services/people/components/people/people.component.spec.ts b/lib/process-services/people/components/people/people.component.spec.ts index d5804d2bab..d447728913 100644 --- a/lib/process-services/people/components/people/people.component.spec.ts +++ b/lib/process-services/people/components/people/people.component.spec.ts @@ -42,7 +42,7 @@ describe('PeopleComponent', () => { let activitiPeopleComponent: PeopleComponent; let fixture: ComponentFixture<PeopleComponent>; let element: HTMLElement; - let userArray = [fakeUser, fakeSecondUser]; + const userArray = [fakeUser, fakeSecondUser]; let logService: LogService; setupTestBed({ @@ -99,7 +99,7 @@ describe('PeopleComponent', () => { it('should show people involved', async(() => { fixture.whenStable() .then(() => { - let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(2); }); @@ -113,7 +113,7 @@ describe('PeopleComponent', () => { fixture.whenStable() .then(() => { fixture.detectChanges(); - let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(1); }); @@ -127,7 +127,7 @@ describe('PeopleComponent', () => { fixture.whenStable() .then(() => { fixture.detectChanges(); - let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(3); }); @@ -206,7 +206,7 @@ describe('PeopleComponent', () => { fixture.whenStable() .then(() => { fixture.detectChanges(); - let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(2); }); @@ -220,7 +220,7 @@ describe('PeopleComponent', () => { fixture.whenStable() .then(() => { fixture.detectChanges(); - let gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(2); }); diff --git a/lib/process-services/process-comments/process-comments.component.spec.ts b/lib/process-services/process-comments/process-comments.component.spec.ts index ae0364a3a9..92950fc0e6 100644 --- a/lib/process-services/process-comments/process-comments.component.spec.ts +++ b/lib/process-services/process-comments/process-comments.component.spec.ts @@ -49,17 +49,17 @@ describe('ProcessCommentsComponent', () => { }); it('should load comments when processInstanceId specified', () => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.detectChanges(); expect(getCommentsSpy).toHaveBeenCalled(); }); it('should emit an error when an error occurs loading comments', () => { - let emitSpy = spyOn(component.error, 'emit'); + const emitSpy = spyOn(component.error, 'emit'); getCommentsSpy.and.returnValue(throwError({})); - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.detectChanges(); @@ -72,7 +72,7 @@ describe('ProcessCommentsComponent', () => { }); it('should display comments when the process has comments', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.whenStable().then(() => { @@ -83,18 +83,18 @@ describe('ProcessCommentsComponent', () => { })); it('should display comments count when the process has comments', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.whenStable().then(() => { fixture.detectChanges(); - let element = fixture.nativeElement.querySelector('#comment-header'); + const element = fixture.nativeElement.querySelector('#comment-header'); expect(element.innerText).toBe('ADF_PROCESS_LIST.DETAILS.COMMENTS.HEADER'); }); })); it('should not display comments when the process has no comments', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); getCommentsSpy.and.returnValue(of([])); @@ -105,7 +105,7 @@ describe('ProcessCommentsComponent', () => { })); it('should not display comments input by default', async(() => { - let change = new SimpleChange(null, '123', true); + const change = new SimpleChange(null, '123', true); component.ngOnChanges({ 'processInstanceId': change }); fixture.whenStable().then(() => { diff --git a/lib/process-services/process-comments/process-comments.component.ts b/lib/process-services/process-comments/process-comments.component.ts index bf0ca7d72e..a797ecc24c 100644 --- a/lib/process-services/process-comments/process-comments.component.ts +++ b/lib/process-services/process-comments/process-comments.component.ts @@ -57,7 +57,7 @@ export class ProcessCommentsComponent implements OnChanges { } ngOnChanges(changes: SimpleChanges) { - let processInstanceId = changes['processInstanceId']; + const processInstanceId = changes['processInstanceId']; if (processInstanceId) { if (processInstanceId.currentValue) { this.getProcessInstanceComments(processInstanceId.currentValue); @@ -73,8 +73,8 @@ export class ProcessCommentsComponent implements OnChanges { this.commentProcessService.getProcessInstanceComments(processInstanceId).subscribe( (res: CommentModel[]) => { res = res.sort((comment1: CommentModel, comment2: CommentModel) => { - let date1 = new Date(comment1.created); - let date2 = new Date(comment2.created); + const date1 = new Date(comment1.created); + const date2 = new Date(comment2.created); return date1 > date2 ? -1 : date1 < date2 ? 1 : 0; }); res.forEach((comment) => { diff --git a/lib/process-services/process-list/components/process-audit.directive.spec.ts b/lib/process-services/process-list/components/process-audit.directive.spec.ts index 3fb3a82b8f..216bfb96ee 100644 --- a/lib/process-services/process-list/components/process-audit.directive.spec.ts +++ b/lib/process-services/process-list/components/process-audit.directive.spec.ts @@ -56,7 +56,7 @@ describe('ProcessAuditDirective', () => { let service: ProcessService; function createFakePdfBlob(): Blob { - let pdfData = atob( + const pdfData = atob( 'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' + 'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' + 'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' + @@ -99,13 +99,13 @@ describe('ProcessAuditDirective', () => { it('should fetch the pdf Blob when the format is pdf', fakeAsync(() => { component.fileName = 'FakeAuditName'; component.format = 'pdf'; - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(service, 'fetchProcessAuditPdfById').and.returnValue(of(blob)); spyOn(component, 'onAuditClick').and.callThrough(); fixture.detectChanges(); - let button = fixture.nativeElement.querySelector('#auditButton'); + const button = fixture.nativeElement.querySelector('#auditButton'); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -141,7 +141,7 @@ describe('ProcessAuditDirective', () => { fixture.detectChanges(); - let button = fixture.nativeElement.querySelector('#auditButton'); + const button = fixture.nativeElement.querySelector('#auditButton'); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -155,13 +155,13 @@ describe('ProcessAuditDirective', () => { it('should fetch the pdf Blob as default when the format is UNKNOW', fakeAsync(() => { component.fileName = 'FakeAuditName'; component.format = 'fakeFormat'; - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(service, 'fetchProcessAuditPdfById').and.returnValue(of(blob)); spyOn(component, 'onAuditClick').and.callThrough(); fixture.detectChanges(); - let button = fixture.nativeElement.querySelector('#auditButton'); + const button = fixture.nativeElement.querySelector('#auditButton'); fixture.whenStable().then(() => { fixture.detectChanges(); diff --git a/lib/process-services/process-list/components/process-filters.component.spec.ts b/lib/process-services/process-list/components/process-filters.component.spec.ts index 081327a1c9..d7f18bb46d 100644 --- a/lib/process-services/process-list/components/process-filters.component.spec.ts +++ b/lib/process-services/process-list/components/process-filters.component.spec.ts @@ -85,7 +85,7 @@ describe('ProcessFiltersComponent', () => { it('should return the filter task list', (done) => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); filterList.success.subscribe((res) => { @@ -104,7 +104,7 @@ describe('ProcessFiltersComponent', () => { it('should select the Running process filter', (done) => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); expect(filterList.currentFilter).toBeUndefined(); @@ -121,7 +121,7 @@ describe('ProcessFiltersComponent', () => { it('should emit an event when a filter is selected', (done) => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); expect(filterList.currentFilter).toBeUndefined(); @@ -139,11 +139,11 @@ describe('ProcessFiltersComponent', () => { spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(Promise.resolve({ id: 1 }))); spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); - let change = new SimpleChange(null, 'test', true); + const change = new SimpleChange(null, 'test', true); filterList.ngOnChanges({ 'appName': change }); filterList.success.subscribe((res) => { - let deployApp: any = appsProcessService.getDeployedApplicationsByName; + const deployApp: any = appsProcessService.getDeployedApplicationsByName; expect(deployApp.calls.count()).toEqual(1); expect(res).toBeDefined(); done(); @@ -156,7 +156,7 @@ describe('ProcessFiltersComponent', () => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(mockErrorFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); filterList.error.subscribe((err) => { @@ -171,7 +171,7 @@ describe('ProcessFiltersComponent', () => { spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(mockErrorFilterPromise)); const appId = 'fake-app'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appName': change }); filterList.error.subscribe((err) => { @@ -183,7 +183,7 @@ describe('ProcessFiltersComponent', () => { }); it('should emit an event when a filter is selected', (done) => { - let currentFilter = new FilterProcessRepresentationModel({ + const currentFilter = new FilterProcessRepresentationModel({ id: 10, name: 'FakeInvolvedTasks', filter: { state: 'open', assignment: 'fake-involved' } @@ -203,7 +203,7 @@ describe('ProcessFiltersComponent', () => { spyOn(filterList, 'getFiltersByAppId').and.stub(); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId); @@ -213,7 +213,7 @@ describe('ProcessFiltersComponent', () => { spyOn(filterList, 'getFiltersByAppId').and.stub(); const appId = null; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId); @@ -223,14 +223,14 @@ describe('ProcessFiltersComponent', () => { spyOn(filterList, 'getFiltersByAppName').and.stub(); const appName = 'fake-app-name'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); filterList.ngOnChanges({ 'appName': change }); expect(filterList.getFiltersByAppName).toHaveBeenCalledWith(appName); }); it('should return the current filter after one is selected', () => { - let filter = new FilterProcessRepresentationModel({ + const filter = new FilterProcessRepresentationModel({ name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee' } }); @@ -245,7 +245,7 @@ describe('ProcessFiltersComponent', () => { filterList.filterParam = new FilterProcessRepresentationModel({ id: 20 }); const appId = 1; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); @@ -265,7 +265,7 @@ describe('ProcessFiltersComponent', () => { filterList.filterParam = new FilterProcessRepresentationModel({ name: 'FakeMyTasks' }); const appId = 1; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); @@ -285,7 +285,7 @@ describe('ProcessFiltersComponent', () => { filterList.filterParam = new FilterProcessRepresentationModel({}); const appId = 1; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); filterList.ngOnChanges({ 'appId': change }); @@ -302,13 +302,13 @@ describe('ProcessFiltersComponent', () => { it('should attach specific icon for each filter if hasIcon is true', (done) => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); filterList.showIcon = true; - let change = new SimpleChange(undefined, 1, true); + const change = new SimpleChange(undefined, 1, true); filterList.ngOnChanges({ 'appId': change }); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); expect(filterList.filters.length).toBe(3); - let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); + const filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); expect(filters.length).toBe(3); expect(filters[0].nativeElement.innerText).toContain('dashboard'); expect(filters[1].nativeElement.innerText).toContain('shuffle'); @@ -320,12 +320,12 @@ describe('ProcessFiltersComponent', () => { it('should not attach icons for each filter if hasIcon is false', (done) => { spyOn(processFilterService, 'getProcessFilters').and.returnValue(from(fakeGlobalFilterPromise)); filterList.showIcon = false; - let change = new SimpleChange(undefined, 1, true); + const change = new SimpleChange(undefined, 1, true); filterList.ngOnChanges({ 'appId': change }); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); + const filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); expect(filters.length).toBe(0); done(); }); diff --git a/lib/process-services/process-list/components/process-instance-details.component.spec.ts b/lib/process-services/process-list/components/process-instance-details.component.spec.ts index e205072a17..ae23a9baae 100644 --- a/lib/process-services/process-list/components/process-instance-details.component.spec.ts +++ b/lib/process-services/process-list/components/process-instance-details.component.spec.ts @@ -72,7 +72,7 @@ describe('ProcessInstanceDetailsComponent', () => { component.ngOnChanges({ 'processInstanceId': new SimpleChange(null, '123', true) }); fixture.whenStable().then(() => { fixture.detectChanges(); - let headerEl: DebugElement = fixture.debugElement.query(By.css('.mat-card-title ')); + const headerEl: DebugElement = fixture.debugElement.query(By.css('.mat-card-title ')); expect(headerEl).not.toBeNull(); expect(headerEl.nativeElement.innerText).toBe('Process 123'); }); @@ -84,7 +84,7 @@ describe('ProcessInstanceDetailsComponent', () => { component.ngOnChanges({ 'processInstanceId': new SimpleChange(null, '123', true) }); fixture.whenStable().then(() => { fixture.detectChanges(); - let headerEl: DebugElement = fixture.debugElement.query(By.css('.mat-card-title ')); + const headerEl: DebugElement = fixture.debugElement.query(By.css('.mat-card-title ')); expect(headerEl).not.toBeNull(); expect(headerEl.nativeElement.innerText).toBe('My Process - Nov 10, 2016, 3:37:30 AM'); }); @@ -92,8 +92,8 @@ describe('ProcessInstanceDetailsComponent', () => { describe('change detection', () => { - let change = new SimpleChange('123', '456', true); - let nullChange = new SimpleChange('123', null, true); + const change = new SimpleChange('123', '456', true); + const nullChange = new SimpleChange('123', null, true); beforeEach(async(() => { component.processInstanceId = '123'; @@ -130,7 +130,7 @@ describe('ProcessInstanceDetailsComponent', () => { ended: null }); fixture.detectChanges(); - let buttonEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] button')); + const buttonEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] button')); expect(buttonEl).not.toBeNull(); }); @@ -143,7 +143,7 @@ describe('ProcessInstanceDetailsComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let diagramButton = fixture.debugElement.query(By.css('#show-diagram-button')); + const diagramButton = fixture.debugElement.query(By.css('#show-diagram-button')); expect(diagramButton).not.toBeNull(); expect(diagramButton.nativeElement.disabled).toBe(false); }); @@ -157,7 +157,7 @@ describe('ProcessInstanceDetailsComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let diagramButton = fixture.debugElement.query(By.css('#show-diagram-button')); + const diagramButton = fixture.debugElement.query(By.css('#show-diagram-button')); expect(diagramButton).not.toBeNull(); expect(diagramButton.nativeElement.disabled).toBe(true); }); diff --git a/lib/process-services/process-list/components/process-instance-details.component.ts b/lib/process-services/process-list/components/process-instance-details.component.ts index bb55d144f6..1d2ca0271a 100644 --- a/lib/process-services/process-list/components/process-instance-details.component.ts +++ b/lib/process-services/process-list/components/process-instance-details.component.ts @@ -78,7 +78,7 @@ export class ProcessInstanceDetailsComponent implements OnChanges { } ngOnChanges(changes: SimpleChanges) { - let processInstanceId = changes['processInstanceId']; + const processInstanceId = changes['processInstanceId']; if (processInstanceId && !processInstanceId.currentValue) { this.reset(); return; @@ -134,7 +134,7 @@ export class ProcessInstanceDetailsComponent implements OnChanges { } getFormatDate(value, format: string) { - let datePipe = new DatePipe('en-US'); + const datePipe = new DatePipe('en-US'); try { return datePipe.transform(value, format); } catch (err) { diff --git a/lib/process-services/process-list/components/process-instance-header.component.spec.ts b/lib/process-services/process-list/components/process-instance-header.component.spec.ts index 021f773389..c3bdbe83c5 100644 --- a/lib/process-services/process-list/components/process-instance-header.component.spec.ts +++ b/lib/process-services/process-list/components/process-instance-header.component.spec.ts @@ -54,7 +54,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.ended = null; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-status"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-status"]'); expect(valueEl.innerText).toBe('Running'); }); @@ -62,7 +62,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.ended = new Date('2016-11-03'); component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-status"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-status"]'); expect(valueEl.innerText).toBe('Completed'); }); @@ -70,7 +70,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.ended = new Date('2016-11-03'); component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-dateitem-ended"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-dateitem-ended"]'); expect(valueEl.innerText).toBe('Nov 03 2016'); }); @@ -78,7 +78,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.ended = null; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-dateitem-ended"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-dateitem-ended"]'); expect(valueEl.innerText).toBe('ADF_PROCESS_LIST.PROPERTIES.END_DATE_DEFAULT'); }); @@ -86,7 +86,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.processDefinitionCategory = 'Accounts'; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-category"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-category"]'); expect(valueEl.innerText).toBe('Accounts'); }); @@ -94,7 +94,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.processDefinitionCategory = null; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-category"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-category"]'); expect(valueEl.innerText).toBe('ADF_PROCESS_LIST.PROPERTIES.CATEGORY_DEFAULT'); }); @@ -102,7 +102,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.started = new Date('2016-11-03'); component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-dateitem-created"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-dateitem-created"]'); expect(valueEl.innerText).toBe('Nov 03 2016'); }); @@ -110,7 +110,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.startedBy = {firstName: 'Admin', lastName: 'User'}; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-assignee"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-assignee"]'); expect(valueEl.innerText).toBe('Admin User'); }); @@ -118,7 +118,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.id = '123'; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-id"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-id"]'); expect(valueEl.innerText).toBe('123'); }); @@ -126,7 +126,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.processDefinitionDescription = 'Test process'; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-description"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-description"]'); expect(valueEl.innerText).toBe('Test process'); }); @@ -134,7 +134,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.processDefinitionDescription = null; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-description"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-description"]'); expect(valueEl.innerText).toBe('ADF_PROCESS_LIST.PROPERTIES.DESCRIPTION_DEFAULT'); }); @@ -142,7 +142,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.businessKey = 'fakeBusinessKey'; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-businessKey"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-businessKey"]'); expect(valueEl.innerText).toBe('fakeBusinessKey'); }); @@ -150,7 +150,7 @@ describe('ProcessInstanceHeaderComponent', () => { component.processInstance.businessKey = null; component.ngOnChanges({}); fixture.detectChanges(); - let valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-businessKey"]'); + const valueEl = fixture.nativeElement.querySelector('[data-automation-id="card-textitem-value-businessKey"]'); expect(valueEl.innerText).toBe('ADF_PROCESS_LIST.PROPERTIES.BUSINESS_KEY_DEFAULT'); }); diff --git a/lib/process-services/process-list/components/process-instance-tasks.component.spec.ts b/lib/process-services/process-list/components/process-instance-tasks.component.spec.ts index 9bac030ed4..127bb3f8d0 100644 --- a/lib/process-services/process-list/components/process-instance-tasks.component.spec.ts +++ b/lib/process-services/process-list/components/process-instance-tasks.component.spec.ts @@ -36,7 +36,7 @@ describe('ProcessInstanceTasksComponent', () => { let service: ProcessService; // let getProcessTasksSpy: jasmine.Spy; - let exampleProcessInstance = new ProcessInstance({ id: '123' }); + const exampleProcessInstance = new ProcessInstance({ id: '123' }); setupTestBed({ imports: [ @@ -61,7 +61,7 @@ describe('ProcessInstanceTasksComponent', () => { component.processInstanceDetails = undefined; fixture.detectChanges(); fixture.whenStable().then(() => { - let msgEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks-none"]')); + const msgEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks-none"]')); expect(msgEl).not.toBeNull(); }); })); @@ -70,7 +70,7 @@ describe('ProcessInstanceTasksComponent', () => { component.processInstanceDetails = undefined; fixture.detectChanges(); fixture.whenStable().then(() => { - let msgEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks-none"]')); + const msgEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks-none"]')); expect(msgEl).not.toBeNull(); }); })); @@ -78,37 +78,37 @@ describe('ProcessInstanceTasksComponent', () => { it('should not render active tasks list if no process instance ID provided', () => { component.processInstanceDetails = undefined; fixture.detectChanges(); - let listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]')); + const listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]')); expect(listEl).toBeNull(); }); it('should not render completed tasks list if no process instance ID provided', () => { component.processInstanceDetails = undefined; fixture.detectChanges(); - let listEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks"]')); + const listEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks"]')); expect(listEl).toBeNull(); }); it('should display active tasks', async(() => { - let change = new SimpleChange(null, exampleProcessInstance, true); + const change = new SimpleChange(null, exampleProcessInstance, true); fixture.detectChanges(); component.ngOnChanges({ 'processInstanceDetails': change }); fixture.whenStable().then(() => { fixture.detectChanges(); component.ngOnChanges({ 'processInstanceDetails': change }); - let listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]')); + const listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]')); expect(listEl).not.toBeNull(); expect(listEl.queryAll(By.css('mat-list-item')).length).toBe(1); }); })); it('should display completed tasks', async(() => { - let change = new SimpleChange(null, exampleProcessInstance, true); + const change = new SimpleChange(null, exampleProcessInstance, true); fixture.detectChanges(); component.ngOnChanges({ 'processInstanceDetails': change }); fixture.whenStable().then(() => { fixture.detectChanges(); - let listEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks"]')); + const listEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks"]')); expect(listEl).not.toBeNull(); expect(listEl.queryAll(By.css('mat-list-item')).length).toBe(1); }); diff --git a/lib/process-services/process-list/components/process-instance-tasks.component.ts b/lib/process-services/process-list/components/process-instance-tasks.component.ts index 932b56a881..59c5e08b91 100644 --- a/lib/process-services/process-list/components/process-instance-tasks.component.ts +++ b/lib/process-services/process-list/components/process-instance-tasks.component.ts @@ -87,7 +87,7 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges { } ngOnChanges(changes: SimpleChanges) { - let processInstanceDetails = changes['processInstanceDetails']; + const processInstanceDetails = changes['processInstanceDetails']; if (processInstanceDetails && processInstanceDetails.currentValue) { this.load(processInstanceDetails.currentValue.id); } @@ -148,7 +148,7 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges { } getFormatDate(value, format: string) { - let datePipe = new DatePipe('en-US'); + const datePipe = new DatePipe('en-US'); try { return datePipe.transform(value, format); } catch (err) { @@ -157,7 +157,7 @@ export class ProcessInstanceTasksComponent implements OnInit, OnChanges { } clickTask($event: any, task: TaskDetailsModel) { - let args = new TaskDetailsEvent(task); + const args = new TaskDetailsEvent(task); this.taskClick.emit(args); } diff --git a/lib/process-services/process-list/components/process-list.component.spec.ts b/lib/process-services/process-list/components/process-list.component.spec.ts index 74bf129e59..b6b6e46ff6 100644 --- a/lib/process-services/process-list/components/process-list.component.spec.ts +++ b/lib/process-services/process-list/components/process-list.component.spec.ts @@ -113,7 +113,7 @@ describe('ProcessInstanceListComponent', () => { }); it('should emit onSuccess event when process instances loaded', fakeAsync(() => { - let emitSpy = spyOn(component.success, 'emit'); + const emitSpy = spyOn(component.success, 'emit'); component.appId = 1; component.state = 'open'; fixture.detectChanges(); @@ -183,7 +183,7 @@ describe('ProcessInstanceListComponent', () => { }); it('should return an empty list when the response is wrong', fakeAsync(() => { - let mockError = 'Fake server error'; + const mockError = 'Fake server error'; getProcessInstancesSpy.and.returnValue(throwError(mockError)); component.appId = 1; component.state = 'open'; @@ -197,7 +197,7 @@ describe('ProcessInstanceListComponent', () => { component.state = 'open'; fixture.detectChanges(); tick(); - let emitSpy = spyOn(component.success, 'emit'); + const emitSpy = spyOn(component.success, 'emit'); component.reload(); tick(); expect(emitSpy).toHaveBeenCalledWith(fakeProcessInstance); @@ -223,10 +223,10 @@ describe('ProcessInstanceListComponent', () => { }); it('should emit row click event', (done) => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ id: '999' }); - let rowEvent = new DataRowEvent(row, null); + const rowEvent = new DataRowEvent(row, null); component.rowClick.subscribe((taskId) => { expect(taskId).toEqual('999'); @@ -239,7 +239,7 @@ describe('ProcessInstanceListComponent', () => { it('should emit row click event on Enter', (done) => { let prevented = false; - let keyEvent = new CustomEvent('Keyboard event', { detail: { + const keyEvent = new CustomEvent('Keyboard event', { detail: { keyboardEvent: { key: 'Enter' }, row: new ObjectDataRow({ id: '999' }) }}); @@ -258,7 +258,7 @@ describe('ProcessInstanceListComponent', () => { it('should NOT emit row click event on every other key', async(() => { let triggered = false; - let keyEvent = new CustomEvent('Keyboard event', { detail: { + const keyEvent = new CustomEvent('Keyboard event', { detail: { keyboardEvent: { key: 'Space' }, row: new ObjectDataRow({ id: 999 }) }}); @@ -290,7 +290,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the list when the appId parameter changes', (done) => { const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -306,7 +306,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the list when the state parameter changes', (done) => { const state = 'open'; - let change = new SimpleChange(null, state, true); + const change = new SimpleChange(null, state, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -322,7 +322,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the list when the sort parameter changes', (done) => { const sort = 'created-desc'; - let change = new SimpleChange(null, sort, true); + const change = new SimpleChange(null, sort, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -338,7 +338,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the process list when the processDefinitionId parameter changes', (done) => { const processDefinitionId = 'SimpleProcess:1:10'; - let change = new SimpleChange(null, processDefinitionId, true); + const change = new SimpleChange(null, processDefinitionId, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -354,7 +354,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the process list when the processDefinitionId parameter changes to null', (done) => { const processDefinitionId = null; - let change = new SimpleChange('SimpleProcess:1:10', processDefinitionId, false); + const change = new SimpleChange('SimpleProcess:1:10', processDefinitionId, false); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -370,7 +370,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the process list when the processInstanceId parameter changes', (done) => { const processInstanceId = '123'; - let change = new SimpleChange(null, processInstanceId, true); + const change = new SimpleChange(null, processInstanceId, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -386,7 +386,7 @@ describe('ProcessInstanceListComponent', () => { it('should reload the process list when the processInstanceId parameter changes to null', (done) => { const processInstanceId = null; - let change = new SimpleChange('123', processInstanceId, false); + const change = new SimpleChange('123', processInstanceId, false); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -486,7 +486,7 @@ describe('Process List: Custom EmptyTemplateComponent', () => { it('should render the custom template', (done) => { fixture.whenStable().then(() => { fixture.detectChanges(); - let title = fixture.debugElement.query(By.css('#custom-id')); + const title = fixture.debugElement.query(By.css('#custom-id')); expect(title).not.toBeNull(); expect(title.nativeElement.innerText).toBe('No Process Instance'); expect(fixture.debugElement.query(By.css('.adf-empty-content'))).toBeNull(); diff --git a/lib/process-services/process-list/components/process-list.component.ts b/lib/process-services/process-list/components/process-list.component.ts index 6aa4f6d87c..80e61efda9 100644 --- a/lib/process-services/process-list/components/process-list.component.ts +++ b/lib/process-services/process-list/components/process-list.component.ts @@ -173,13 +173,13 @@ export class ProcessInstanceListComponent extends DataTableSchema implements On private isPropertyChanged(changes: SimpleChanges): boolean { let changed: boolean = false; - let appId = changes['appId']; - let processDefinitionId = changes['processDefinitionId']; - let processInstanceId = changes['processInstanceId']; - let state = changes['state']; - let sort = changes['sort']; - let page = changes['page']; - let size = changes['size']; + const appId = changes['appId']; + const processDefinitionId = changes['processDefinitionId']; + const processInstanceId = changes['processInstanceId']; + const state = changes['state']; + const sort = changes['sort']; + const page = changes['page']; + const size = changes['size']; if (appId && appId.currentValue) { changed = true; @@ -232,7 +232,7 @@ export class ProcessInstanceListComponent extends DataTableSchema implements On selectFirst() { if (this.selectFirstRow) { if (!this.isListEmpty()) { - let dataRow = this.rows[0]; + const dataRow = this.rows[0]; dataRow.isSelected = true; this.currentInstanceId = dataRow['id']; } else { @@ -260,7 +260,7 @@ export class ProcessInstanceListComponent extends DataTableSchema implements On * @param event */ onRowClick(event: DataRowEvent) { - let item = event; + const item = event; this.currentInstanceId = item.value.getValue('id'); this.rowClick.emit(this.currentInstanceId); } @@ -302,7 +302,7 @@ export class ProcessInstanceListComponent extends DataTableSchema implements On } getFormatDate(value, format: string) { - let datePipe = new DatePipe('en-US'); + const datePipe = new DatePipe('en-US'); try { return datePipe.transform(value, format); } catch (err) { @@ -311,7 +311,7 @@ export class ProcessInstanceListComponent extends DataTableSchema implements On } private createRequestNode() { - let requestNode = { + const requestNode = { appDefinitionId: this.appId, processDefinitionId: this.processDefinitionId, processInstanceId: this.processInstanceId, diff --git a/lib/process-services/process-list/components/start-process.component.spec.ts b/lib/process-services/process-list/components/start-process.component.spec.ts index 2060b31806..505eff8efd 100644 --- a/lib/process-services/process-list/components/start-process.component.spec.ts +++ b/lib/process-services/process-list/components/start-process.component.spec.ts @@ -81,7 +81,7 @@ describe('StartFormComponent', () => { beforeEach(() => { fixture.detectChanges(); component.name = 'My new process'; - let change = new SimpleChange(null, 123, true); + const change = new SimpleChange(null, 123, true); component.ngOnChanges({ 'appId': change }); fixture.detectChanges(); }); @@ -94,7 +94,7 @@ describe('StartFormComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn.disabled).toBe(false); }); })); @@ -105,7 +105,7 @@ describe('StartFormComponent', () => { component.processDefinitionInput.setValue(testProcessDef.name); fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn.disabled).toBe(true); }); })); @@ -114,7 +114,7 @@ describe('StartFormComponent', () => { component.selectedProcessDef = null; fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn.disabled).toBe(true); }); })); @@ -125,7 +125,7 @@ describe('StartFormComponent', () => { beforeEach(() => { fixture.detectChanges(); getDefinitionsSpy.and.returnValue(of(testProcessDefWithForm)); - let change = new SimpleChange(null, 123, true); + const change = new SimpleChange(null, 123, true); component.ngOnChanges({ 'appId': change }); }); @@ -148,15 +148,15 @@ describe('StartFormComponent', () => { component.name = 'My new process'; fixture.detectChanges(); fixture.whenStable().then(() => { - let startBtn = fixture.nativeElement.querySelector('#button-start'); + const startBtn = fixture.nativeElement.querySelector('#button-start'); expect(startBtn).toBeNull(); }); })); it('should emit cancel event on cancel Button', async(() => { fixture.detectChanges(); - let cancelButton = fixture.nativeElement.querySelector('#cancel_process'); - let cancelSpy: jasmine.Spy = spyOn(component.cancel, 'emit'); + const cancelButton = fixture.nativeElement.querySelector('#cancel_process'); + const cancelSpy: jasmine.Spy = spyOn(component.cancel, 'emit'); cancelButton.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -218,7 +218,7 @@ describe('StartFormComponent', () => { it('should display the correct number of processes in the select list', () => { fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('mat-select'); + const selectElement = fixture.nativeElement.querySelector('mat-select'); expect(selectElement.children.length).toBe(1); }); }); @@ -227,8 +227,8 @@ describe('StartFormComponent', () => { component.processDefinitions = testMultipleProcessDefs; fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('mat-select > .mat-select-trigger'); - let optionElement = fixture.nativeElement.querySelectorAll('mat-option'); + const selectElement = fixture.nativeElement.querySelector('mat-select > .mat-select-trigger'); + const optionElement = fixture.nativeElement.querySelectorAll('mat-option'); selectElement.click(); expect(selectElement).not.toBeNull(); expect(selectElement).toBeDefined(); @@ -244,7 +244,7 @@ describe('StartFormComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let errorEl = fixture.nativeElement.querySelector('#error-message'); + const errorEl = fixture.nativeElement.querySelector('#error-message'); expect(errorEl).not.toBeNull('Expected error message to be present'); expect(errorEl.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.ERROR.LOAD_PROCESS_DEFS'); }); @@ -304,7 +304,7 @@ describe('StartFormComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); + const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); expect(selectElement).toBeNull(); }); })); @@ -318,7 +318,7 @@ describe('StartFormComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); + const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); expect(selectElement).not.toBeNull(); }); })); @@ -331,7 +331,7 @@ describe('StartFormComponent', () => { component.ngOnChanges({}); fixture.detectChanges(); fixture.whenStable().then(() => { - let selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); + const selectElement = fixture.nativeElement.querySelector('button#adf-select-process-dropdown'); expect(selectElement).not.toBeNull(); }); })); @@ -340,7 +340,7 @@ describe('StartFormComponent', () => { describe('input changes', () => { - let change = new SimpleChange(123, 456, true); + const change = new SimpleChange(123, 456, true); beforeEach(async(() => { component.appId = 123; @@ -403,9 +403,9 @@ describe('StartFormComponent', () => { })); it('should call service to start process with the variables setted', async(() => { - let inputProcessVariable: ProcessInstanceVariable[] = []; + const inputProcessVariable: ProcessInstanceVariable[] = []; - let variable: ProcessInstanceVariable = {}; + const variable: ProcessInstanceVariable = {}; variable.name = 'nodeId'; variable.value = 'id'; @@ -420,7 +420,7 @@ describe('StartFormComponent', () => { })); it('should output start event when process started successfully', async(() => { - let emitSpy = spyOn(component.start, 'emit'); + const emitSpy = spyOn(component.start, 'emit'); component.selectedProcessDef = testProcessDef; component.startProcess(); fixture.whenStable().then(() => { @@ -429,8 +429,8 @@ describe('StartFormComponent', () => { })); it('should throw error event when process cannot be started', async(() => { - let errorSpy = spyOn(component.error, 'error'); - let error = { message: 'My error' }; + const errorSpy = spyOn(component.error, 'error'); + const error = { message: 'My error' }; startProcessSpy = startProcessSpy.and.returnValue(throwError(error)); component.selectedProcessDef = testProcessDef; component.startProcess(); @@ -446,14 +446,14 @@ describe('StartFormComponent', () => { component.startProcess(); fixture.detectChanges(); fixture.whenStable().then(() => { - let errorEl = fixture.nativeElement.querySelector('#error-message'); + const errorEl = fixture.nativeElement.querySelector('#error-message'); expect(errorEl).not.toBeNull(); expect(errorEl.innerText.trim()).toBe('ADF_PROCESS_LIST.START_PROCESS.ERROR.START'); }); })); it('should emit start event when start select a process and add a name', (done) => { - let disposableStart = component.start.subscribe(() => { + const disposableStart = component.start.subscribe(() => { disposableStart.unsubscribe(); done(); }); @@ -467,7 +467,7 @@ describe('StartFormComponent', () => { it('should not emit start event when start the process without select a process and name', () => { component.name = null; component.selectedProcessDef = null; - let startSpy: jasmine.Spy = spyOn(component.start, 'emit'); + const startSpy: jasmine.Spy = spyOn(component.start, 'emit'); component.startProcess(); fixture.detectChanges(); expect(startSpy).not.toHaveBeenCalled(); @@ -475,7 +475,7 @@ describe('StartFormComponent', () => { it('should not emit start event when start the process without name', () => { component.name = null; - let startSpy: jasmine.Spy = spyOn(component.start, 'emit'); + const startSpy: jasmine.Spy = spyOn(component.start, 'emit'); component.startProcess(); fixture.detectChanges(); expect(startSpy).not.toHaveBeenCalled(); @@ -483,7 +483,7 @@ describe('StartFormComponent', () => { it('should not emit start event when start the process without select a process', () => { component.selectedProcessDef = null; - let startSpy: jasmine.Spy = spyOn(component.start, 'emit'); + const startSpy: jasmine.Spy = spyOn(component.start, 'emit'); component.startProcess(); fixture.detectChanges(); expect(startSpy).not.toHaveBeenCalled(); @@ -493,7 +493,7 @@ describe('StartFormComponent', () => { component.name = 'my:process1'; component.selectedProcessDef = testProcessDef; - let disposableStart = component.start.subscribe(() => { + const disposableStart = component.start.subscribe(() => { disposableStart.unsubscribe(); done(); }); diff --git a/lib/process-services/process-list/components/start-process.component.ts b/lib/process-services/process-list/components/start-process.component.ts index 89fd20f10b..a4dc0e0ac8 100644 --- a/lib/process-services/process-list/components/start-process.component.ts +++ b/lib/process-services/process-list/components/start-process.component.ts @@ -137,7 +137,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit { private _filter(value: string): ProcessDefinitionRepresentation[] { if (value !== null && value !== undefined) { const filterValue = value.toLowerCase(); - let filteredProcess = this.processDefinitions.filter((option) => option.name.toLowerCase().includes(filterValue)); + const filteredProcess = this.processDefinitions.filter((option) => option.name.toLowerCase().includes(filterValue)); if (this.processFilterSelector) { this.selectedProcessDef = this.getSelectedProcess(filterValue); @@ -170,7 +170,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit { } if (this.processDefinitionName) { - let selectedProcess = this.processDefinitions.find((currentProcessDefinition) => { + const selectedProcess = this.processDefinitions.find((currentProcessDefinition) => { return currentProcessDefinition.name === this.processDefinitionName; }); if (selectedProcess) { @@ -199,11 +199,11 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit { } moveNodeFromCStoPS() { - let accountIdentifier = this.getAlfrescoRepositoryName(); + const accountIdentifier = this.getAlfrescoRepositoryName(); - for (let key in this.values) { + for (const key in this.values) { if (this.values.hasOwnProperty(key)) { - let currentValue = this.values[key]; + const currentValue = this.values[key]; if (currentValue.isFile) { this.activitiContentService.applyAlfrescoNode(currentValue, null, accountIdentifier).subscribe((res) => { @@ -217,7 +217,7 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit { public startProcess(outcome?: string) { if (this.selectedProcessDef && this.selectedProcessDef.id && this.name) { this.resetErrorMessage(); - let formValues = this.startForm ? this.startForm.form.values : undefined; + const formValues = this.startForm ? this.startForm.form.values : undefined; this.activitiProcess.startProcess(this.selectedProcessDef.id, this.name, outcome, formValues, this.variables).subscribe( (res) => { this.name = ''; diff --git a/lib/process-services/process-list/services/process-filter.service.spec.ts b/lib/process-services/process-list/services/process-filter.service.spec.ts index 3e4d6bc088..71a9e71a68 100644 --- a/lib/process-services/process-list/services/process-filter.service.spec.ts +++ b/lib/process-services/process-list/services/process-filter.service.spec.ts @@ -163,7 +163,7 @@ describe('Process filter', () => { .callFake((processfilter: FilterProcessRepresentationModel) => Promise.resolve(processfilter)); }); - let filter = fakeProcessFilters.data[0]; + const filter = fakeProcessFilters.data[0]; it('should call the API to create the filter', () => { service.addProcessFilter(filter); diff --git a/lib/process-services/process-list/services/process-filter.service.ts b/lib/process-services/process-list/services/process-filter.service.ts index 8f70071733..152ec83179 100644 --- a/lib/process-services/process-list/services/process-filter.service.ts +++ b/lib/process-services/process-list/services/process-filter.service.ts @@ -38,9 +38,9 @@ export class ProcessFilterService { return from(this.callApiProcessFilters(appId)) .pipe( map((response: any) => { - let filters: FilterProcessRepresentationModel[] = []; + const filters: FilterProcessRepresentationModel[] = []; response.data.forEach((filter: FilterProcessRepresentationModel) => { - let filterModel = new FilterProcessRepresentationModel(filter); + const filterModel = new FilterProcessRepresentationModel(filter); filters.push(filterModel); }); return filters; @@ -87,14 +87,14 @@ export class ProcessFilterService { * @returns Default filters just created */ public createDefaultFilters(appId: number): Observable<FilterProcessRepresentationModel[]> { - let runningFilter = this.getRunningFilterInstance(appId); - let runningObservable = this.addProcessFilter(runningFilter); + const runningFilter = this.getRunningFilterInstance(appId); + const runningObservable = this.addProcessFilter(runningFilter); - let completedFilter = this.getCompletedFilterInstance(appId); - let completedObservable = this.addProcessFilter(completedFilter); + const completedFilter = this.getCompletedFilterInstance(appId); + const completedObservable = this.addProcessFilter(completedFilter); - let allFilter = this.getAllFilterInstance(appId); - let allObservable = this.addProcessFilter(allFilter); + const allFilter = this.getAllFilterInstance(appId); + const allObservable = this.addProcessFilter(allFilter); return new Observable((observer) => { forkJoin( @@ -103,7 +103,7 @@ export class ProcessFilterService { allObservable ).subscribe( (res) => { - let filters: FilterProcessRepresentationModel[] = []; + const filters: FilterProcessRepresentationModel[] = []; res.forEach((filter) => { if (filter.name === runningFilter.name) { runningFilter.id = filter.id; diff --git a/lib/process-services/process-list/services/process.service.spec.ts b/lib/process-services/process-list/services/process.service.spec.ts index bfc393e0c4..aa195a3cf2 100644 --- a/lib/process-services/process-list/services/process.service.spec.ts +++ b/lib/process-services/process-list/services/process.service.spec.ts @@ -47,7 +47,7 @@ describe('ProcessService', () => { let getProcessInstances: jasmine.Spy; - let filter: ProcessFilterParamRepresentationModel = new ProcessFilterParamRepresentationModel({ + const filter: ProcessFilterParamRepresentationModel = new ProcessFilterParamRepresentationModel({ processDefinitionId: '1', appDefinitionId: '1', page: 1, @@ -69,7 +69,7 @@ describe('ProcessService', () => { it('should return the correct instance data', async(() => { service.getProcessInstances(filter).subscribe((instances) => { - let instance = instances.data[0]; + const instance = instances.data[0]; expect(instance.id).toBe(exampleProcess.id); expect(instance.name).toBe(exampleProcess.name); expect(instance.started).toBe(exampleProcess.started); @@ -81,7 +81,7 @@ describe('ProcessService', () => { service.getProcessInstances(filter, 'fakeProcessDefinitionKey1').subscribe((instances) => { expect(instances.data.length).toBe(1); - let instance = instances.data[0]; + const instance = instances.data[0]; expect(instance.id).toBe('340124'); /* cspell:disable-next-line */ expect(instance.name).toBe('James Franklin EMEA Onboarding'); @@ -192,7 +192,7 @@ describe('ProcessService', () => { }); it('should call the API to create the process instance with form parameters', () => { - let formParams = { + const formParams = { type: 'ford', color: 'red' }; @@ -365,9 +365,9 @@ describe('ProcessService', () => { })); it('should return the correct task data', async(() => { - let fakeTasks = fakeTasksList.data; + const fakeTasks = fakeTasksList.data; service.getProcessTasks(processId).subscribe((tasks) => { - let task = tasks[0]; + const task = tasks[0]; expect(task.id).toBe(fakeTasks[0].id); expect(task.name).toBe(fakeTasks[0].name); expect(task.created).toEqual(moment(new Date('2016-11-10T00:00:00+00:00'), 'YYYY-MM-DD').format()); @@ -469,7 +469,7 @@ describe('ProcessService', () => { describe('create or update variables', () => { - let updatedVariables = [new ProcessInstanceVariable({ + const updatedVariables = [new ProcessInstanceVariable({ name: 'var1', value: 'Test1' }), new ProcessInstanceVariable({ diff --git a/lib/process-services/process-list/services/process.service.ts b/lib/process-services/process-list/services/process.service.ts index a4898c3422..4dc81f2681 100644 --- a/lib/process-services/process-list/services/process.service.ts +++ b/lib/process-services/process-list/services/process.service.ts @@ -115,7 +115,7 @@ export class ProcessService { * @returns Array of task instance details */ getProcessTasks(processInstanceId: string, state?: string): Observable<TaskDetailsModel[]> { - let taskOpts = state ? { + const taskOpts = state ? { processInstanceId: processInstanceId, state: state } : { @@ -138,7 +138,7 @@ export class ProcessService { * @returns Array of process definitions */ getProcessDefinitions(appId?: number): Observable<ProcessDefinitionRepresentation[]> { - let opts = appId ? { + const opts = appId ? { latest: true, appDefinitionId: appId } : { @@ -164,7 +164,7 @@ export class ProcessService { * @returns Details of the process instance just started */ startProcess(processDefinitionId: string, name: string, outcome?: string, startFormValues?: FormValues, variables?: ProcessInstanceVariable[]): Observable<ProcessInstance> { - let startRequest: any = { + const startRequest: any = { name: name, processDefinitionId: processDefinitionId }; diff --git a/lib/process-services/task-list/components/attach-form.component.spec.ts b/lib/process-services/task-list/components/attach-form.component.spec.ts index d3c847544f..4d29e83222 100644 --- a/lib/process-services/task-list/components/attach-form.component.spec.ts +++ b/lib/process-services/task-list/components/attach-form.component.spec.ts @@ -51,7 +51,7 @@ describe('AttachFormComponent', () => { it('should show the attach button disabled', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { - let attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button')); + const attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button')); expect(attachButton.nativeElement.disabled).toBeTruthy(); }); })); @@ -87,7 +87,7 @@ describe('AttachFormComponent', () => { spyOn(taskService, 'attachFormToATask').and.returnValue(of(true)); fixture.detectChanges(); fixture.whenStable().then(() => { - let attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button')); + const attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button')); expect(attachButton.nativeElement.disabled).toBeFalsy(); }); })); @@ -103,7 +103,7 @@ describe('AttachFormComponent', () => { fixture.detectChanges(); component.attachFormControl.setValue(2); fixture.detectChanges(); - let attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button')); + const attachButton = fixture.debugElement.query(By.css('#adf-no-form-attach-form-button')); expect(attachButton.nativeElement.disabled).toBeTruthy(); }); })); diff --git a/lib/process-services/task-list/components/checklist.component.spec.ts b/lib/process-services/task-list/components/checklist.component.spec.ts index 7573214e97..7627451797 100644 --- a/lib/process-services/task-list/components/checklist.component.spec.ts +++ b/lib/process-services/task-list/components/checklist.component.spec.ts @@ -178,7 +178,7 @@ describe('ChecklistComponent', () => { })); showChecklistDialog.click(); - let addButtonDialog = <HTMLElement> window.document.querySelector('#add-check'); + const addButtonDialog = <HTMLElement> window.document.querySelector('#add-check'); addButtonDialog.click(); fixture.whenStable().then(() => { @@ -197,7 +197,7 @@ describe('ChecklistComponent', () => { name: 'fake-check-name' })); fixture.detectChanges(); - let checklistElementRemove = <HTMLElement> element.querySelector('#remove-fake-check-id'); + const checklistElementRemove = <HTMLElement> element.querySelector('#remove-fake-check-id'); expect(checklistElementRemove).toBeDefined(); expect(checklistElementRemove).not.toBeNull(); checklistElementRemove.click(); @@ -220,7 +220,7 @@ describe('ChecklistComponent', () => { fixture.whenStable().then(() => { fixture.detectChanges(); expect(checklistComponent.checklist.length).toBe(1); - let checklistElementRemove = <HTMLElement> element.querySelector('#remove-fake-check-id'); + const checklistElementRemove = <HTMLElement> element.querySelector('#remove-fake-check-id'); expect(checklistElementRemove).toBeDefined(); expect(checklistElementRemove).not.toBeNull(); checklistElementRemove.click(); @@ -237,7 +237,7 @@ describe('ChecklistComponent', () => { name: 'fake-check-name' })); fixture.detectChanges(); - let change = new SimpleChange(null, 'new-fake-task-id', true); + const change = new SimpleChange(null, 'new-fake-task-id', true); checklistComponent.ngOnChanges({ taskId: change }); @@ -257,7 +257,7 @@ describe('ChecklistComponent', () => { })); fixture.detectChanges(); checklistComponent.taskId = null; - let change = new SimpleChange(null, 'new-fake-task-id', true); + const change = new SimpleChange(null, 'new-fake-task-id', true); checklistComponent.ngOnChanges({ taskId: change }); @@ -271,7 +271,7 @@ describe('ChecklistComponent', () => { it('should emit checklist task created event when the checklist is successfully added', (done) => { spyOn(service, 'addTask').and.returnValue(of({ id: 'fake-check-added-id', name: 'fake-check-added-name' })); - let disposableCreated = checklistComponent.checklistTaskCreated.subscribe((taskAdded: TaskDetailsModel) => { + const disposableCreated = checklistComponent.checklistTaskCreated.subscribe((taskAdded: TaskDetailsModel) => { fixture.detectChanges(); expect(taskAdded.id).toEqual('fake-check-added-id'); expect(taskAdded.name).toEqual('fake-check-added-name'); @@ -281,7 +281,7 @@ describe('ChecklistComponent', () => { done(); }); showChecklistDialog.click(); - let addButtonDialog = <HTMLElement> window.document.querySelector('#add-check'); + const addButtonDialog = <HTMLElement> window.document.querySelector('#add-check'); addButtonDialog.click(); }); }); diff --git a/lib/process-services/task-list/components/checklist.component.ts b/lib/process-services/task-list/components/checklist.component.ts index 44e35fe5ee..009134433c 100644 --- a/lib/process-services/task-list/components/checklist.component.ts +++ b/lib/process-services/task-list/components/checklist.component.ts @@ -72,7 +72,7 @@ export class ChecklistComponent implements OnChanges { } ngOnChanges(changes: SimpleChanges) { - let taskId = changes['taskId']; + const taskId = changes['taskId']; if (taskId && taskId.currentValue) { this.getTaskChecklist(taskId.currentValue); return; @@ -102,7 +102,7 @@ export class ChecklistComponent implements OnChanges { } public add() { - let newTask = new TaskDetailsModel({ + const newTask = new TaskDetailsModel({ name: this.taskName, parentTaskId: this.taskId, assignee: { id: this.assignee } diff --git a/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts b/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts index 774635f32b..61188986bf 100644 --- a/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts +++ b/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts @@ -34,7 +34,7 @@ describe('NoTaskDetailsTemplateDirective', () => { }); it('should set "no task details" template on task details component', () => { - let testTemplate: any = 'test template'; + const testTemplate: any = 'test template'; component.template = testTemplate; component.ngAfterContentInit(); expect(detailsComponent.noTaskDetailsTemplateComponent).toBe(testTemplate); diff --git a/lib/process-services/task-list/components/start-task.component.spec.ts b/lib/process-services/task-list/components/start-task.component.spec.ts index 53db72deb0..7b9dd69049 100644 --- a/lib/process-services/task-list/components/start-task.component.spec.ts +++ b/lib/process-services/task-list/components/start-task.component.spec.ts @@ -34,7 +34,7 @@ describe('StartTaskComponent', () => { let getFormListSpy: jasmine.Spy; let createNewTaskSpy: jasmine.Spy; let logSpy: jasmine.Spy; - let fakeForms$ = [ + const fakeForms$ = [ { id: 123, name: 'Display Data' @@ -45,7 +45,7 @@ describe('StartTaskComponent', () => { } ]; - let testUser = { id: 1001, firstName: 'fakeName', email: 'fake@app.activiti.com' }; + const testUser = { id: 1001, firstName: 'fakeName', email: 'fake@app.activiti.com' }; setupTestBed({ imports: [ProcessTestingModule] @@ -96,20 +96,20 @@ describe('StartTaskComponent', () => { }); it('should create new task when start is clicked', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('task'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalled(); }); it('should send on success event when the task is started', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock); component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalledWith({ id: 91, @@ -120,20 +120,20 @@ describe('StartTaskComponent', () => { }); it('should send on success event when only name is given', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.appId = 42; component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalled(); }); it('should not emit success event when data not present', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskDetailsModel = new TaskDetailsModel(null); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(createNewTaskSpy).not.toHaveBeenCalled(); expect(successSpy).not.toHaveBeenCalled(); @@ -161,13 +161,13 @@ describe('StartTaskComponent', () => { assignee: null } )); - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); component.taskForm.controls['formKey'].setValue(1204); component.appId = 42; component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalledWith({ id: 91, @@ -186,13 +186,13 @@ describe('StartTaskComponent', () => { assignee: null } )); - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); component.taskForm.controls['formKey'].setValue(null); component.appId = 42; component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalledWith({ id: 91, @@ -232,13 +232,13 @@ describe('StartTaskComponent', () => { }); it('should assign task when an assignee is selected', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); component.taskForm.controls['formKey'].setValue(1204); component.appId = 42; component.assigneeId = testUser.id; fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalledWith({ id: 91, @@ -249,14 +249,14 @@ describe('StartTaskComponent', () => { }); it('should assign task with id of selected user assigned', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock); component.taskForm.controls['name'].setValue('fakeName'); component.taskForm.controls['formKey'].setValue(1204); component.appId = 42; component.getAssigneeId(testUser.id); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalledWith({ id: 91, @@ -267,14 +267,14 @@ describe('StartTaskComponent', () => { }); it('should not assign task when no assignee is selected', () => { - let successSpy = spyOn(component.success, 'emit'); + const successSpy = spyOn(component.success, 'emit'); component.taskForm.controls['name'].setValue('fakeName'); component.taskForm.controls['formKey'].setValue(1204); component.appId = 42; component.assigneeId = null; component.taskDetailsModel = new TaskDetailsModel(taskDetailsMock); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); createTaskButton.click(); expect(successSpy).toHaveBeenCalledWith({ id: 91, @@ -286,7 +286,7 @@ describe('StartTaskComponent', () => { }); it('should not attach a form when a form id is not selected', () => { - let attachFormToATask = spyOn(service, 'attachFormToATask').and.returnValue([]); + const attachFormToATask = spyOn(service, 'attachFormToATask').and.returnValue([]); spyOn(service, 'createNewTask').and.callFake( function() { return new Observable((observer) => { @@ -296,7 +296,7 @@ describe('StartTaskComponent', () => { }); component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); fixture.detectChanges(); createTaskButton.click(); expect(attachFormToATask).not.toHaveBeenCalled(); @@ -310,7 +310,7 @@ describe('StartTaskComponent', () => { }); it('should not emit TaskDetails OnCancel', () => { - let emitSpy = spyOn(component.cancel, 'emit'); + const emitSpy = spyOn(component.cancel, 'emit'); component.onCancel(); expect(emitSpy).not.toBeNull(); expect(emitSpy).toHaveBeenCalled(); @@ -319,13 +319,13 @@ describe('StartTaskComponent', () => { it('should disable start button if name is empty', () => { component.taskForm.controls['name'].setValue(''); fixture.detectChanges(); - let createTaskButton = fixture.nativeElement.querySelector('#button-start'); + const createTaskButton = fixture.nativeElement.querySelector('#button-start'); expect(createTaskButton.disabled).toBeTruthy(); }); it('should cancel start task on cancel button click', () => { - let emitSpy = spyOn(component.cancel, 'emit'); - let cancelTaskButton = <HTMLElement> element.querySelector('#button-cancel'); + const emitSpy = spyOn(component.cancel, 'emit'); + const cancelTaskButton = <HTMLElement> element.querySelector('#button-cancel'); fixture.detectChanges(); cancelTaskButton.click(); expect(emitSpy).not.toBeNull(); @@ -335,27 +335,27 @@ describe('StartTaskComponent', () => { it('should enable start button if name is filled out', () => { component.taskForm.controls['name'].setValue('fakeName'); fixture.detectChanges(); - let createTaskButton = fixture.nativeElement.querySelector('#button-start'); + const createTaskButton = fixture.nativeElement.querySelector('#button-start'); expect(createTaskButton.disabled).toBeFalsy(); }); it('should define the select options for Forms', () => { component.forms$ = service.getFormList(); fixture.detectChanges(); - let selectElement = fixture.nativeElement.querySelector('#form_label'); + const selectElement = fixture.nativeElement.querySelector('#form_label'); expect(selectElement.innerHTML).toContain('ADF_TASK_LIST.START_TASK.FORM.LABEL.FORM'); }); it('should get formatted fullname', () => { - let testUser1 = { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' }; - let testUser2 = { 'id': 1002, 'firstName': '', 'lastName': 'Adams', 'email': 'adams@app.activiti.com' }; - let testUser3 = { 'id': 1003, 'firstName': 'Wilbur', 'lastName': '', 'email': 'wilbur@app.activiti.com' }; - let testUser4 = { 'id': 1004, 'firstName': '', 'lastName': '', 'email': 'test@app.activiti.com' }; + const testUser1 = { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' }; + const testUser2 = { 'id': 1002, 'firstName': '', 'lastName': 'Adams', 'email': 'adams@app.activiti.com' }; + const testUser3 = { 'id': 1003, 'firstName': 'Wilbur', 'lastName': '', 'email': 'wilbur@app.activiti.com' }; + const testUser4 = { 'id': 1004, 'firstName': '', 'lastName': '', 'email': 'test@app.activiti.com' }; - let testFullName1 = component.getDisplayUser(testUser1.firstName, testUser1.lastName, ' '); - let testFullName2 = component.getDisplayUser(testUser2.firstName, testUser2.lastName, ' '); - let testFullName3 = component.getDisplayUser(testUser3.firstName, testUser3.lastName, ' '); - let testFullName4 = component.getDisplayUser(testUser4.firstName, testUser4.lastName, ' '); + const testFullName1 = component.getDisplayUser(testUser1.firstName, testUser1.lastName, ' '); + const testFullName2 = component.getDisplayUser(testUser2.firstName, testUser2.lastName, ' '); + const testFullName3 = component.getDisplayUser(testUser3.firstName, testUser3.lastName, ' '); + const testFullName4 = component.getDisplayUser(testUser4.firstName, testUser4.lastName, ' '); expect(testFullName1.trim()).toBe('Wilbur Adams'); expect(testFullName2.trim()).toBe('Adams'); @@ -365,9 +365,9 @@ describe('StartTaskComponent', () => { it('should emit error when there is an error while creating task', () => { component.taskForm.controls['name'].setValue('fakeName'); - let errorSpy = spyOn(component.error, 'emit'); + const errorSpy = spyOn(component.error, 'emit'); spyOn(service, 'createNewTask').and.returnValue(throwError({})); - let createTaskButton = <HTMLElement> element.querySelector('#button-start'); + const createTaskButton = <HTMLElement> element.querySelector('#button-start'); fixture.detectChanges(); createTaskButton.click(); expect(errorSpy).toHaveBeenCalled(); @@ -377,7 +377,7 @@ describe('StartTaskComponent', () => { component.maxTaskNameLength = 2; component.ngOnInit(); fixture.detectChanges(); - let name = component.taskForm.controls['name']; + const name = component.taskForm.controls['name']; name.setValue('task'); fixture.detectChanges(); expect(name.valid).toBeFalsy(); @@ -388,7 +388,7 @@ describe('StartTaskComponent', () => { it('should emit error when task name field is empty', () => { fixture.detectChanges(); - let name = component.taskForm.controls['name']; + const name = component.taskForm.controls['name']; name.setValue(''); fixture.detectChanges(); expect(name.valid).toBeFalsy(); @@ -407,7 +407,7 @@ describe('StartTaskComponent', () => { it('should emit error when description have only white spaces', () => { fixture.detectChanges(); - let description = component.taskForm.controls['description']; + const description = component.taskForm.controls['description']; description.setValue(' '); fixture.detectChanges(); expect(description.valid).toBeFalsy(); diff --git a/lib/process-services/task-list/components/task-audit.directive.spec.ts b/lib/process-services/task-list/components/task-audit.directive.spec.ts index 02a63d3879..4fa1ef48fb 100644 --- a/lib/process-services/task-list/components/task-audit.directive.spec.ts +++ b/lib/process-services/task-list/components/task-audit.directive.spec.ts @@ -61,7 +61,7 @@ describe('TaskAuditDirective', () => { let service: TaskListService; function createFakePdfBlob(): Blob { - let pdfData = atob( + const pdfData = atob( 'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' + 'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' + 'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' + @@ -99,13 +99,13 @@ describe('TaskAuditDirective', () => { it('should fetch the pdf Blob when the format is pdf', fakeAsync(() => { component.fileName = 'FakeAuditName'; component.format = 'pdf'; - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(service, 'fetchTaskAuditPdfById').and.returnValue(of(blob)); spyOn(component, 'onAuditClick').and.callThrough(); fixture.detectChanges(); - let button = fixture.nativeElement.querySelector('#auditButton'); + const button = fixture.nativeElement.querySelector('#auditButton'); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -127,7 +127,7 @@ describe('TaskAuditDirective', () => { fixture.detectChanges(); - let button = fixture.nativeElement.querySelector('#auditButton'); + const button = fixture.nativeElement.querySelector('#auditButton'); fixture.whenStable().then(() => { fixture.detectChanges(); @@ -141,13 +141,13 @@ describe('TaskAuditDirective', () => { it('should fetch the pdf Blob as default when the format is UNKNOWN', fakeAsync(() => { component.fileName = 'FakeAuditName'; component.format = 'fakeFormat'; - let blob = createFakePdfBlob(); + const blob = createFakePdfBlob(); spyOn(service, 'fetchTaskAuditPdfById').and.returnValue(of(blob)); spyOn(component, 'onAuditClick').and.callThrough(); fixture.detectChanges(); - let button = fixture.nativeElement.querySelector('#auditButton'); + const button = fixture.nativeElement.querySelector('#auditButton'); fixture.whenStable().then(() => { fixture.detectChanges(); diff --git a/lib/process-services/task-list/components/task-details.component.spec.ts b/lib/process-services/task-list/components/task-details.component.spec.ts index cc6fde78ba..012251d19d 100644 --- a/lib/process-services/task-list/components/task-details.component.spec.ts +++ b/lib/process-services/task-list/components/task-details.component.spec.ts @@ -286,19 +286,19 @@ describe('TaskDetailsComponent', () => { }); it('should emit a save event when form saved', () => { - let emitSpy: jasmine.Spy = spyOn(component.formSaved, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.formSaved, 'emit'); component.onFormSaved(new FormModel()); expect(emitSpy).toHaveBeenCalled(); }); it('should emit a outcome execution event when form outcome executed', () => { - let emitSpy: jasmine.Spy = spyOn(component.executeOutcome, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.executeOutcome, 'emit'); component.onFormExecuteOutcome(new FormOutcomeEvent(new FormOutcomeModel(new FormModel()))); expect(emitSpy).toHaveBeenCalled(); }); it('should emit a complete event when form completed', () => { - let emitSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit'); component.onFormCompleted(new FormModel()); expect(emitSpy).toHaveBeenCalled(); }); @@ -316,7 +316,7 @@ describe('TaskDetailsComponent', () => { }); it('should emit an error event if an error occurs fetching the next task', () => { - let emitSpy: jasmine.Spy = spyOn(component.error, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.error, 'emit'); getTasksSpy.and.returnValue(throwError({})); component.onComplete(); expect(emitSpy).toHaveBeenCalled(); @@ -334,7 +334,7 @@ describe('TaskDetailsComponent', () => { }); it('should emit a complete event when complete button clicked and task completed', () => { - let emitSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.formCompleted, 'emit'); component.onComplete(); expect(emitSpy).toHaveBeenCalled(); }); @@ -345,13 +345,13 @@ describe('TaskDetailsComponent', () => { }); it('should emit a load event when form loaded', () => { - let emitSpy: jasmine.Spy = spyOn(component.formLoaded, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.formLoaded, 'emit'); component.onFormLoaded(new FormModel()); expect(emitSpy).toHaveBeenCalled(); }); it('should emit an error event when form error occurs', () => { - let emitSpy: jasmine.Spy = spyOn(component.error, 'emit'); + const emitSpy: jasmine.Spy = spyOn(component.error, 'emit'); component.onFormError({}); expect(emitSpy).toHaveBeenCalled(); }); @@ -368,8 +368,8 @@ describe('TaskDetailsComponent', () => { }); it('should emit a task created event when checklist task is created', () => { - let emitSpy: jasmine.Spy = spyOn(component.taskCreated, 'emit'); - let mockTask = new TaskDetailsModel(taskDetailsMock); + const emitSpy: jasmine.Spy = spyOn(component.taskCreated, 'emit'); + const mockTask = new TaskDetailsModel(taskDetailsMock); component.onChecklistTaskCreated(mockTask); expect(emitSpy).toHaveBeenCalled(); }); diff --git a/lib/process-services/task-list/components/task-details.component.ts b/lib/process-services/task-list/components/task-details.component.ts index 879d463885..5ea8c07922 100644 --- a/lib/process-services/task-list/components/task-details.component.ts +++ b/lib/process-services/task-list/components/task-details.component.ts @@ -212,7 +212,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges { } ngOnChanges(changes: SimpleChanges): void { - let taskId = changes.taskId; + const taskId = changes.taskId; this.showAssignee = false; if (taskId && !taskId.currentValue) { @@ -305,7 +305,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges { this.taskDetails.name = 'No name'; } - let endDate: any = res.endDate; + const endDate: any = res.endDate; if (endDate && !isNaN(endDate.getTime())) { this.internalReadOnlyForm = true; } else { @@ -369,7 +369,7 @@ export class TaskDetailsComponent implements OnInit, OnChanges { * @param processDefinitionId */ private loadNextTask(processInstanceId: string, processDefinitionId: string): void { - let requestNode = new TaskQueryRequestRepresentationModel( + const requestNode = new TaskQueryRequestRepresentationModel( { processInstanceId: processInstanceId, processDefinitionId: processDefinitionId diff --git a/lib/process-services/task-list/components/task-filters.component.spec.ts b/lib/process-services/task-list/components/task-filters.component.spec.ts index a0cb350772..5d62f14e7d 100644 --- a/lib/process-services/task-list/components/task-filters.component.spec.ts +++ b/lib/process-services/task-list/components/task-filters.component.spec.ts @@ -32,7 +32,7 @@ describe('TaskFiltersComponent', () => { let taskFilterService: TaskFilterService; let appsProcessService: AppsProcessService; - let fakeGlobalFilter = []; + const fakeGlobalFilter = []; fakeGlobalFilter.push(new FilterRepresentationModel({ name: 'FakeInvolvedTasks', icon: 'glyphicon-align-left', @@ -52,23 +52,23 @@ describe('TaskFiltersComponent', () => { filter: { state: 'open', assignment: 'fake-assignee' } })); - let fakeGlobalFilterPromise = new Promise(function (resolve, reject) { + const fakeGlobalFilterPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalFilter); }); - let fakeGlobalEmptyFilter = { + const fakeGlobalEmptyFilter = { message: 'invalid data' }; - let fakeGlobalEmptyFilterPromise = new Promise(function (resolve, reject) { + const fakeGlobalEmptyFilterPromise = new Promise(function (resolve, reject) { resolve(fakeGlobalEmptyFilter); }); - let mockErrorFilterList = { + const mockErrorFilterList = { error: 'wrong request' }; - let mockErrorFilterPromise = Promise.reject(mockErrorFilterList); + const mockErrorFilterPromise = Promise.reject(mockErrorFilterList); let component: TaskFiltersComponent; let fixture: ComponentFixture<TaskFiltersComponent>; @@ -80,7 +80,7 @@ describe('TaskFiltersComponent', () => { }); beforeEach(() => { - let appConfig: AppConfigService = TestBed.get(AppConfigService); + const appConfig: AppConfigService = TestBed.get(AppConfigService); appConfig.config.bpmHost = 'http://localhost:9876/bpm'; fixture = TestBed.createComponent(TaskFiltersComponent); @@ -95,7 +95,7 @@ describe('TaskFiltersComponent', () => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(mockErrorFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.ngOnChanges({ 'appId': change }); component.error.subscribe((err) => { @@ -108,7 +108,7 @@ describe('TaskFiltersComponent', () => { it('should return the filter task list', (done) => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.ngOnChanges({ 'appId': change }); component.success.subscribe((res) => { @@ -126,18 +126,18 @@ describe('TaskFiltersComponent', () => { it('should return the filter task list, filtered By Name', (done) => { - let fakeDeployedApplicationsPromise = new Promise(function (resolve, reject) { + const fakeDeployedApplicationsPromise = new Promise(function (resolve, reject) { resolve({}); }); spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(fakeDeployedApplicationsPromise)); spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); - let change = new SimpleChange(null, 'test', true); + const change = new SimpleChange(null, 'test', true); component.ngOnChanges({ 'appName': change }); component.success.subscribe((res) => { - let deployApp: any = appsProcessService.getDeployedApplicationsByName; + const deployApp: any = appsProcessService.getDeployedApplicationsByName; expect(deployApp.calls.count()).toEqual(1); expect(res).toBeDefined(); done(); @@ -150,7 +150,7 @@ describe('TaskFiltersComponent', () => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); fixture.detectChanges(); component.ngOnChanges({ 'appId': change }); @@ -169,7 +169,7 @@ describe('TaskFiltersComponent', () => { spyOn(component, 'createFiltersByAppId').and.stub(); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.ngOnChanges({ 'appId': change }); component.success.subscribe((res) => { @@ -184,7 +184,7 @@ describe('TaskFiltersComponent', () => { component.filterParam = new FilterParamsModel({ name: 'FakeMyTasks1' }); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); fixture.detectChanges(); component.ngOnChanges({ 'appId': change }); @@ -204,7 +204,7 @@ describe('TaskFiltersComponent', () => { component.filterParam = new FilterParamsModel({ name: 'UnexistableFilter' }); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); fixture.detectChanges(); component.ngOnChanges({ 'appId': change }); @@ -224,7 +224,7 @@ describe('TaskFiltersComponent', () => { component.filterParam = new FilterParamsModel({ index: 2 }); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); fixture.detectChanges(); component.ngOnChanges({ 'appId': change }); @@ -244,7 +244,7 @@ describe('TaskFiltersComponent', () => { component.filterParam = new FilterParamsModel({ id: 10 }); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); fixture.detectChanges(); component.ngOnChanges({ 'appId': change }); @@ -259,7 +259,7 @@ describe('TaskFiltersComponent', () => { }); it('should emit an event when a filter is selected', (done) => { - let currentFilter = fakeGlobalFilter[0]; + const currentFilter = fakeGlobalFilter[0]; component.filters = fakeGlobalFilter; component.filterClick.subscribe((filter: FilterRepresentationModel) => { expect(filter).toBeDefined(); @@ -275,7 +275,7 @@ describe('TaskFiltersComponent', () => { spyOn(component, 'getFiltersByAppId').and.stub(); const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.ngOnChanges({ 'appId': change }); expect(component.getFiltersByAppId).toHaveBeenCalledWith(appId); @@ -285,7 +285,7 @@ describe('TaskFiltersComponent', () => { spyOn(component, 'getFiltersByAppId').and.stub(); const appId = null; - let change = new SimpleChange(undefined, appId, true); + const change = new SimpleChange(undefined, appId, true); component.ngOnChanges({ 'appId': change }); expect(component.getFiltersByAppId).toHaveBeenCalledWith(appId); @@ -318,14 +318,14 @@ describe('TaskFiltersComponent', () => { spyOn(component, 'getFiltersByAppName').and.stub(); const appName = 'fake-app-name'; - let change = new SimpleChange(null, appName, true); + const change = new SimpleChange(null, appName, true); component.ngOnChanges({ 'appName': change }); expect(component.getFiltersByAppName).toHaveBeenCalledWith(appName); }); it('should return the current filter after one is selected', () => { - let filter = fakeGlobalFilter[1]; + const filter = fakeGlobalFilter[1]; component.filters = fakeGlobalFilter; expect(component.currentFilter).toBeUndefined(); @@ -336,14 +336,14 @@ describe('TaskFiltersComponent', () => { it('should load default list when app id is null', () => { spyOn(component, 'getFiltersByAppId').and.stub(); - let change = new SimpleChange(undefined, null, true); + const change = new SimpleChange(undefined, null, true); component.ngOnChanges({ 'appId': change }); expect(component.getFiltersByAppId).toHaveBeenCalled(); }); it('should not change the current filter if no filter with taskid is found', async(() => { - let filter = new FilterRepresentationModel({ + const filter = new FilterRepresentationModel({ name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee' } }); @@ -358,13 +358,13 @@ describe('TaskFiltersComponent', () => { it('should attach specific icon for each filter if showIcon is true', (done) => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); component.showIcon = true; - let change = new SimpleChange(undefined, 1, true); + const change = new SimpleChange(undefined, 1, true); component.ngOnChanges({ 'appId': change }); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); expect(component.filters.length).toBe(3); - let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); + const filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); expect(filters.length).toBe(3); expect(filters[0].nativeElement.innerText).toContain('format_align_left'); expect(filters[1].nativeElement.innerText).toContain('check_circle'); @@ -376,12 +376,12 @@ describe('TaskFiltersComponent', () => { it('should not attach icons for each filter if showIcon is false', (done) => { spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise)); component.showIcon = false; - let change = new SimpleChange(undefined, 1, true); + const change = new SimpleChange(undefined, 1, true); component.ngOnChanges({ 'appId': change }); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); + const filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon')); expect(filters.length).toBe(0); done(); }); diff --git a/lib/process-services/task-list/components/task-filters.component.ts b/lib/process-services/task-list/components/task-filters.component.ts index 3011049cdf..1e73a97cac 100644 --- a/lib/process-services/task-list/components/task-filters.component.ts +++ b/lib/process-services/task-list/components/task-filters.component.ts @@ -181,7 +181,7 @@ export class TaskFiltersComponent implements OnInit, OnChanges { * @param taskId */ public selectFilterWithTask(taskId: string) { - let filteredFilterList: FilterRepresentationModel[] = []; + const filteredFilterList: FilterRepresentationModel[] = []; this.taskListService.getFilterForTaskById(taskId, this.filters).subscribe( (filter: FilterRepresentationModel) => { filteredFilterList.push(filter); diff --git a/lib/process-services/task-list/components/task-header.component.spec.ts b/lib/process-services/task-list/components/task-header.component.spec.ts index 6a0807864c..f7c0558932 100644 --- a/lib/process-services/task-list/components/task-header.component.spec.ts +++ b/lib/process-services/task-list/components/task-header.component.spec.ts @@ -42,7 +42,7 @@ describe('TaskHeaderComponent', () => { let userBpmService: BpmUserService; let appConfigService: AppConfigService; - let fakeBpmAssignedUser = { + const fakeBpmAssignedUser = { id: 1001, apps: [], capabilities: 'fake-capability', @@ -83,7 +83,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams'); }); })); @@ -93,8 +93,8 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); - let iconE = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-create"]`)); + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); + const iconE = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-create"]`)); expect(formNameEl).not.toBeNull(); expect(iconE).not.toBeNull(); expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams'); @@ -108,7 +108,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); expect(valueEl.nativeElement.innerText).toBe('ADF_TASK_LIST.PROPERTIES.ASSIGNEE_DEFAULT'); }); @@ -120,7 +120,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]')); + const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-priority"]')); expect(formNameEl.nativeElement.innerText).toBe('27'); }); })); @@ -131,7 +131,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-dueDate"]`)); + const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-dueDate"]`)); expect(datePicker).toBeNull('Datepicker should NOT be in DOM'); }); })); @@ -142,7 +142,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-dueDate"]`)); + const datePicker = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-dueDate"]`)); expect(datePicker).not.toBeNull('Datepicker should be in DOM'); }); })); @@ -156,7 +156,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.CLAIM'); }); })); @@ -167,7 +167,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); expect(component.isTaskClaimable()).toBeTruthy(); expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.CLAIM'); }); @@ -180,8 +180,8 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); - let unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); expect(component.isTaskClaimable()).toBeFalsy(); expect(component.isTaskClaimedByCandidateMember()).toBeFalsy(); expect(unclaimButton).toBeNull(); @@ -196,7 +196,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); expect(component.isTaskClaimedByCandidateMember()).toBeTruthy(); expect(unclaimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.UNCLAIM'); }); @@ -208,7 +208,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); expect(component.isTaskClaimedByCandidateMember()).toBeFalsy(); expect(unclaimButton).toBeNull(); }); @@ -220,7 +220,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); expect(component.isTaskClaimable()).toBeTruthy(); expect(component.isTaskClaimedByCandidateMember()).toBeFalsy(); expect(claimButton.nativeElement.innerText).toBe('ADF_TASK_LIST.DETAILS.BUTTON.CLAIM'); @@ -233,8 +233,8 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); - let unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); + const claimButton = fixture.debugElement.query(By.css('[data-automation-id="header-claim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); expect(claimButton).toBeNull(); expect(unclaimButton).toBeNull(); }); @@ -247,7 +247,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); unclaimButton.triggerEventHandler('click', {}); expect(service.unclaimTask).toHaveBeenCalledWith('91'); @@ -266,7 +266,7 @@ describe('TaskHeaderComponent', () => { unclaimed = true; }); - let unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); + const unclaimButton = fixture.debugElement.query(By.css('[data-automation-id="header-unclaim-button"]')); unclaimButton.triggerEventHandler('click', {}); expect(unclaimed).toBeTruthy(); @@ -279,7 +279,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toBe('Nov 03 2016'); }); })); @@ -290,7 +290,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toBe('ADF_TASK_LIST.PROPERTIES.DUE_DATE_DEFAULT'); }); })); @@ -301,7 +301,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-textitem-clickable-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-textitem-clickable-value')); expect(valueEl.nativeElement.innerText).toBe('test form'); }); })); @@ -312,7 +312,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toEqual('ADF_TASK_LIST.PROPERTIES.PARENT_NAME_DEFAULT'); }); })); @@ -324,7 +324,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-parentName"] .adf-property-value')); expect(valueEl.nativeElement.innerText.trim()).toEqual('Parent Name'); }); })); @@ -334,7 +334,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-property-value')); + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-formName"] .adf-property-value')); expect(valueEl.nativeElement.innerText).toBe('ADF_TASK_LIST.PROPERTIES.FORM_NAME_DEFAULT'); }); })); @@ -347,7 +347,7 @@ describe('TaskHeaderComponent', () => { component.taskDetails.processDefinitionName = 'Parent Name'; component.refreshData(); fixture.detectChanges(); - let propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); fixture.whenStable().then(() => { expect(propertyList).toBeDefined(); @@ -366,7 +366,7 @@ describe('TaskHeaderComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); + const propertyList = fixture.debugElement.queryAll(By.css('.adf-property-list .adf-property')); expect(propertyList).toBeDefined(); expect(propertyList).not.toBeNull(); expect(propertyList.length).toBe(component.properties.length); diff --git a/lib/process-services/task-list/components/task-list.component.spec.ts b/lib/process-services/task-list/components/task-list.component.spec.ts index 3a42c62abd..6040c9b6f8 100644 --- a/lib/process-services/task-list/components/task-list.component.spec.ts +++ b/lib/process-services/task-list/components/task-list.component.spec.ts @@ -107,9 +107,9 @@ describe('TaskListComponent', () => { }); it('should return the filtered task list when the input parameters are passed', (done) => { - let state = new SimpleChange(null, 'open', true); - let processDefinitionKey = new SimpleChange(null, null, true); - let assignment = new SimpleChange(null, 'fake-assignee', true); + const state = new SimpleChange(null, 'open', true); + const processDefinitionKey = new SimpleChange(null, null, true); + const assignment = new SimpleChange(null, 'fake-assignee', true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -151,10 +151,10 @@ describe('TaskListComponent', () => { }); it('should return the filtered task list by processDefinitionKey', (done) => { - let state = new SimpleChange(null, 'open', true); + const state = new SimpleChange(null, 'open', true); /* cspell:disable-next-line */ - let processDefinitionKey = new SimpleChange(null, 'fakeprocess', true); - let assignment = new SimpleChange(null, 'fake-assignee', true); + const processDefinitionKey = new SimpleChange(null, 'fakeprocess', true); + const assignment = new SimpleChange(null, 'fake-assignee', true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -177,9 +177,9 @@ describe('TaskListComponent', () => { }); it('should return the filtered task list by processInstanceId', (done) => { - let state = new SimpleChange(null, 'open', true); - let processInstanceId = new SimpleChange(null, 'fakeprocessId', true); - let assignment = new SimpleChange(null, 'fake-assignee', true); + const state = new SimpleChange(null, 'open', true); + const processInstanceId = new SimpleChange(null, 'fakeprocessId', true); + const assignment = new SimpleChange(null, 'fake-assignee', true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -203,9 +203,9 @@ describe('TaskListComponent', () => { }); it('should return the filtered task list by processDefinitionId', (done) => { - let state = new SimpleChange(null, 'open', true); - let processDefinitionId = new SimpleChange(null, 'fakeprocessDefinitionId', true); - let assignment = new SimpleChange(null, 'fake-assignee', true); + const state = new SimpleChange(null, 'open', true); + const processDefinitionId = new SimpleChange(null, 'fakeprocessDefinitionId', true); + const assignment = new SimpleChange(null, 'fake-assignee', true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -229,8 +229,8 @@ describe('TaskListComponent', () => { }); it('should return the filtered task list by created date', (done) => { - let state = new SimpleChange(null, 'open', true); - let afterDate = new SimpleChange(null, '28-02-2017', true); + const state = new SimpleChange(null, 'open', true); + const afterDate = new SimpleChange(null, '28-02-2017', true); component.success.subscribe((res) => { expect(res).toBeDefined(); expect(component.rows).toBeDefined(); @@ -251,9 +251,9 @@ describe('TaskListComponent', () => { }); it('should return the filtered task list for all state', (done) => { - let state = new SimpleChange(null, 'all', true); + const state = new SimpleChange(null, 'all', true); /* cspell:disable-next-line */ - let processInstanceId = new SimpleChange(null, 'fakeprocessId', true); + const processInstanceId = new SimpleChange(null, 'fakeprocessId', true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -317,10 +317,10 @@ describe('TaskListComponent', () => { }); it('should emit row click event', (done) => { - let row = new ObjectDataRow({ + const row = new ObjectDataRow({ id: '999' }); - let rowEvent = new DataRowEvent(row, null); + const rowEvent = new DataRowEvent(row, null); component.rowClick.subscribe((taskId) => { expect(taskId).toEqual('999'); @@ -344,7 +344,7 @@ describe('TaskListComponent', () => { component.rows = [{ id: '999', name: 'Fake-name' }]; const landingTaskId = '999'; - let change = new SimpleChange(null, landingTaskId, true); + const change = new SimpleChange(null, landingTaskId, true); component.ngOnChanges({'landingTaskId': change}); expect(component.reload).not.toHaveBeenCalled(); expect(component.rows.length).toEqual(1); @@ -354,7 +354,7 @@ describe('TaskListComponent', () => { component.currentInstanceId = '999'; component.rows = [{ id: '999', name: 'Fake-name' }]; const landingTaskId = '888'; - let change = new SimpleChange(null, landingTaskId, true); + const change = new SimpleChange(null, landingTaskId, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -381,7 +381,7 @@ describe('TaskListComponent', () => { it('should reload the list when the appId parameter changes', (done) => { const appId = '1'; - let change = new SimpleChange(null, appId, true); + const change = new SimpleChange(null, appId, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -402,7 +402,7 @@ describe('TaskListComponent', () => { it('should reload the list when the processDefinitionKey parameter changes', (done) => { const processDefinitionKey = 'fakeprocess'; - let change = new SimpleChange(null, processDefinitionKey, true); + const change = new SimpleChange(null, processDefinitionKey, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -424,7 +424,7 @@ describe('TaskListComponent', () => { it('should reload the list when the state parameter changes', (done) => { const state = 'open'; - let change = new SimpleChange(null, state, true); + const change = new SimpleChange(null, state, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -446,7 +446,7 @@ describe('TaskListComponent', () => { it('should reload the list when the sort parameter changes', (done) => { const sort = 'desc'; - let change = new SimpleChange(null, sort, true); + const change = new SimpleChange(null, sort, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -468,7 +468,7 @@ describe('TaskListComponent', () => { it('should reload the process list when the name parameter changes', (done) => { const name = 'FakeTaskName'; - let change = new SimpleChange(null, name, true); + const change = new SimpleChange(null, name, true); component.success.subscribe((res) => { expect(res).toBeDefined(); @@ -490,7 +490,7 @@ describe('TaskListComponent', () => { it('should reload the list when the assignment parameter changes', (done) => { const assignment = 'assignee'; - let change = new SimpleChange(null, assignment, true); + const change = new SimpleChange(null, assignment, true); component.success.subscribe((res) => { expect(res).toBeDefined(); diff --git a/lib/process-services/task-list/components/task-list.component.ts b/lib/process-services/task-list/components/task-list.component.ts index 79258ceded..fb0b238cbd 100644 --- a/lib/process-services/task-list/components/task-list.component.ts +++ b/lib/process-services/task-list/components/task-list.component.ts @@ -220,9 +220,9 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft private isPropertyChanged(changes: SimpleChanges): boolean { let changed: boolean = true; - let landingTaskId = changes['landingTaskId']; - let page = changes['page']; - let size = changes['size']; + const landingTaskId = changes['landingTaskId']; + const page = changes['page']; + const size = changes['size']; if (landingTaskId && landingTaskId.currentValue && this.isEqualToCurrentId(landingTaskId.currentValue)) { changed = false; } else if (page && page.currentValue !== page.previousValue) { @@ -353,7 +353,7 @@ export class TaskListComponent extends DataTableSchema implements OnChanges, Aft private createRequestNode() { - let requestNode = { + const requestNode = { appDefinitionId: this.appId, dueAfter: this.dueAfter ? moment(this.dueAfter).toDate() : null, dueBefore: this.dueBefore ? moment(this.dueBefore).toDate() : null, diff --git a/lib/process-services/task-list/models/task-details.model.ts b/lib/process-services/task-list/models/task-details.model.ts index 65a9b3b945..fcbb7e8208 100644 --- a/lib/process-services/task-list/models/task-details.model.ts +++ b/lib/process-services/task-list/models/task-details.model.ts @@ -98,8 +98,8 @@ export class TaskDetailsModel implements TaskRepresentation { let fullName: string = ''; if (this.assignee) { - let firstName: string = this.assignee.firstName ? this.assignee.firstName : ''; - let lastName: string = this.assignee.lastName ? this.assignee.lastName : ''; + const firstName: string = this.assignee.firstName ? this.assignee.firstName : ''; + const lastName: string = this.assignee.lastName ? this.assignee.lastName : ''; fullName = `${firstName} ${lastName}`; } diff --git a/lib/process-services/task-list/services/process-upload.service.ts b/lib/process-services/task-list/services/process-upload.service.ts index 0b2ec4be1c..79b80d1601 100644 --- a/lib/process-services/task-list/services/process-upload.service.ts +++ b/lib/process-services/task-list/services/process-upload.service.ts @@ -29,11 +29,11 @@ export class ProcessUploadService extends UploadService { } getUploadPromise(file: any): any { - let opts = { + const opts = { isRelatedContent: true }; - let processInstanceId = file.options.parentId; - let promise = this.apiService.getInstance().activiti.contentApi.createRelatedContentOnProcessInstance(processInstanceId, file.file, opts); + const processInstanceId = file.options.parentId; + const promise = this.apiService.getInstance().activiti.contentApi.createRelatedContentOnProcessInstance(processInstanceId, file.file, opts); promise.catch((err) => this.handleError(err)); diff --git a/lib/process-services/task-list/services/task-filter.service.spec.ts b/lib/process-services/task-list/services/task-filter.service.spec.ts index 5e500dd29f..31d0a940b0 100644 --- a/lib/process-services/task-list/services/task-filter.service.spec.ts +++ b/lib/process-services/task-list/services/task-filter.service.spec.ts @@ -100,7 +100,7 @@ describe('Activiti Task filter Service', () => { it('should call the api with the appId', (done) => { spyOn(service, 'callApiTaskFilters').and.returnValue((fakeAppPromise)); - let appId = 1; + const appId = 1; service.getTaskListFilters(appId).subscribe((res) => { expect(service.callApiTaskFilters).toHaveBeenCalledWith(appId); done(); @@ -108,7 +108,7 @@ describe('Activiti Task filter Service', () => { }); it('should return the app filter by id', (done) => { - let appId = 1; + const appId = 1; service.getTaskListFilters(appId).subscribe((res) => { expect(res).toBeDefined(); expect(res.length).toEqual(1); @@ -172,7 +172,7 @@ describe('Activiti Task filter Service', () => { }); it('should add a filter', (done) => { - let filterFake = new FilterRepresentationModel({ + const filterFake = new FilterRepresentationModel({ name: 'FakeNameFilter', assignment: 'fake-assignment' }); diff --git a/lib/process-services/task-list/services/task-filter.service.ts b/lib/process-services/task-list/services/task-filter.service.ts index d74a25cc48..65e75b7c72 100644 --- a/lib/process-services/task-list/services/task-filter.service.ts +++ b/lib/process-services/task-list/services/task-filter.service.ts @@ -36,17 +36,17 @@ export class TaskFilterService { * @returns Array of default filters just created */ public createDefaultFilters(appId: number): Observable<FilterRepresentationModel[]> { - let involvedTasksFilter = this.getInvolvedTasksFilterInstance(appId); - let involvedObservable = this.addFilter(involvedTasksFilter); + const involvedTasksFilter = this.getInvolvedTasksFilterInstance(appId); + const involvedObservable = this.addFilter(involvedTasksFilter); - let myTasksFilter = this.getMyTasksFilterInstance(appId); - let myTaskObservable = this.addFilter(myTasksFilter); + const myTasksFilter = this.getMyTasksFilterInstance(appId); + const myTaskObservable = this.addFilter(myTasksFilter); - let queuedTasksFilter = this.getQueuedTasksFilterInstance(appId); - let queuedObservable = this.addFilter(queuedTasksFilter); + const queuedTasksFilter = this.getQueuedTasksFilterInstance(appId); + const queuedObservable = this.addFilter(queuedTasksFilter); - let completedTasksFilter = this.getCompletedTasksFilterInstance(appId); - let completeObservable = this.addFilter(completedTasksFilter); + const completedTasksFilter = this.getCompletedTasksFilterInstance(appId); + const completeObservable = this.addFilter(completedTasksFilter); return new Observable((observer) => { forkJoin( @@ -56,7 +56,7 @@ export class TaskFilterService { completeObservable ).subscribe( (res) => { - let filters: FilterRepresentationModel[] = []; + const filters: FilterRepresentationModel[] = []; res.forEach((filter) => { if (filter.name === involvedTasksFilter.name) { involvedTasksFilter.id = filter.id; diff --git a/lib/process-services/task-list/services/task-upload.service.ts b/lib/process-services/task-list/services/task-upload.service.ts index 639aa0c965..79ec62fbd9 100644 --- a/lib/process-services/task-list/services/task-upload.service.ts +++ b/lib/process-services/task-list/services/task-upload.service.ts @@ -29,11 +29,11 @@ export class TaskUploadService extends UploadService { } getUploadPromise(file: any): any { - let opts = { + const opts = { isRelatedContent: true }; - let taskId = file.options.parentId; - let promise = this.apiService.getInstance().activiti.contentApi.createRelatedContentOnTask(taskId, file.file, opts); + const taskId = file.options.parentId; + const promise = this.apiService.getInstance().activiti.contentApi.createRelatedContentOnTask(taskId, file.file, opts); promise.catch((err) => this.handleError(err)); diff --git a/lib/process-services/task-list/services/tasklist.service.spec.ts b/lib/process-services/task-list/services/tasklist.service.spec.ts index 58ca3cc5b1..0c7f545c40 100644 --- a/lib/process-services/task-list/services/tasklist.service.spec.ts +++ b/lib/process-services/task-list/services/tasklist.service.spec.ts @@ -255,7 +255,7 @@ describe('Activiti TaskList Service', () => { }); it('should add a task ', (done) => { - let taskFake = new TaskDetailsModel({ + const taskFake = new TaskDetailsModel({ id: 123, parentTaskId: 456, name: 'FakeNameTask', @@ -324,7 +324,7 @@ describe('Activiti TaskList Service', () => { }); it('should create a new standalone task ', (done) => { - let taskFake = new TaskDetailsModel({ + const taskFake = new TaskDetailsModel({ name: 'FakeNameTask', description: 'FakeDescription', category: '3' @@ -355,7 +355,7 @@ describe('Activiti TaskList Service', () => { }); it('should assign task to a user', (done) => { - let testTaskId = '8888'; + const testTaskId = '8888'; service.assignTask(testTaskId, fakeUser2).subscribe((res: TaskDetailsModel) => { expect(res).toBeDefined(); expect(res.id).toEqual(testTaskId); @@ -389,7 +389,7 @@ describe('Activiti TaskList Service', () => { }); it('should assign task to a userId', (done) => { - let testTaskId = '8888'; + const testTaskId = '8888'; service.assignTaskByUserId(testTaskId, fakeUser2.id.toString()).subscribe((res: TaskDetailsModel) => { expect(res).toBeDefined(); expect(res.id).toEqual(testTaskId); @@ -421,7 +421,7 @@ describe('Activiti TaskList Service', () => { }); it('should claim a task', (done) => { - let taskId = '111'; + const taskId = '111'; service.claimTask(taskId).subscribe(() => { done(); @@ -435,7 +435,7 @@ describe('Activiti TaskList Service', () => { }); it('should unclaim a task', (done) => { - let taskId = '111'; + const taskId = '111'; service.unclaimTask(taskId).subscribe(() => { done(); @@ -449,7 +449,7 @@ describe('Activiti TaskList Service', () => { }); it('should update a task', (done) => { - let taskId = '111'; + const taskId = '111'; service.updateTask(taskId, { property: 'value' }).subscribe(() => { done(); @@ -463,8 +463,8 @@ describe('Activiti TaskList Service', () => { }); it('should return the filter if it contains task id', (done) => { - let taskId = '1'; - let filterFake = new FilterRepresentationModel({ + const taskId = '1'; + const filterFake = new FilterRepresentationModel({ name: 'FakeNameFilter', assignment: 'fake-assignment', filter: { @@ -489,9 +489,9 @@ describe('Activiti TaskList Service', () => { }); it('should return the filters if it contains task id', (done) => { - let taskId = '1'; + const taskId = '1'; - let fakeFilterList: FilterRepresentationModel[] = []; + const fakeFilterList: FilterRepresentationModel[] = []; fakeFilterList.push(fakeRepresentationFilter1, fakeRepresentationFilter2); let resultFilter: FilterRepresentationModel = null; service.getFilterForTaskById(taskId, fakeFilterList).subscribe((res: FilterRepresentationModel) => { diff --git a/lib/process-services/task-list/services/tasklist.service.ts b/lib/process-services/task-list/services/tasklist.service.ts index 5d6e39e898..080822c41c 100644 --- a/lib/process-services/task-list/services/tasklist.service.ts +++ b/lib/process-services/task-list/services/tasklist.service.ts @@ -57,7 +57,7 @@ export class TaskListService { * @returns The search query */ private generateTaskRequestNodeFromFilter(filterModel: FilterRepresentationModel): TaskQueryRequestRepresentationModel { - let requestNode = { + const requestNode = { appDefinitionId: filterModel.appId, assignment: filterModel.filter.assignment, state: filterModel.filter.state, @@ -73,7 +73,7 @@ export class TaskListService { * @returns The filter if it is related or null otherwise */ isTaskRelatedToFilter(taskId: string, filterModel: FilterRepresentationModel): Observable<FilterRepresentationModel> { - let requestNodeForFilter = this.generateTaskRequestNodeFromFilter(filterModel); + const requestNodeForFilter = this.generateTaskRequestNodeFromFilter(filterModel); return from(this.callApiTasksFiltered(requestNodeForFilter)) .pipe( map((res: any) => { @@ -185,7 +185,7 @@ export class TaskListService { * @returns Array of form details */ getFormList(): Observable<Form[]> { - let opts = { + const opts = { 'filter': 'myReusableForms', // String | filter 'sort': 'modifiedDesc', // String | sort 'modelType': 2 // Integer | modelType @@ -194,7 +194,7 @@ export class TaskListService { return from(this.apiService.getInstance().activiti.modelsApi.getModels(opts)) .pipe( map((response: any) => { - let forms: Form[] = []; + const forms: Form[] = []; response.data.forEach((form) => { forms.push(new Form(form.id, form.name)); }); @@ -306,7 +306,7 @@ export class TaskListService { * @returns Details of the assigned task */ assignTask(taskId: string, requestNode: any): Observable<TaskDetailsModel> { - let assignee = { assignee: requestNode.id }; + const assignee = { assignee: requestNode.id }; return from(this.callApiAssignTask(taskId, assignee)) .pipe( map((response: TaskDetailsModel) => { diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/browser-visibility.ts index 2a3a297a19..7c2ecfcc42 100644 --- a/lib/testing/src/lib/core/browser-visibility.ts +++ b/lib/testing/src/lib/core/browser-visibility.ts @@ -16,7 +16,7 @@ */ import { browser, protractor } from 'protractor'; -let until = protractor.ExpectedConditions; +const until = protractor.ExpectedConditions; const DEFAULT_TIMEOUT = 40000; diff --git a/lib/testing/src/lib/core/pages/header.page.ts b/lib/testing/src/lib/core/pages/header.page.ts index 6914452431..97d397bbec 100644 --- a/lib/testing/src/lib/core/pages/header.page.ts +++ b/lib/testing/src/lib/core/pages/header.page.ts @@ -49,18 +49,18 @@ export class HeaderPage { } clickShowMenuButton() { - let checkBox = element.all(by.css('mat-checkbox')); + const checkBox = element.all(by.css('mat-checkbox')); BrowserVisibility.waitUntilElementIsVisible(checkBox); return checkBox.get(0).click(); } changeHeaderColor(color) { - let headerColor = element(by.css('option[value="' + color + '"]')); + const headerColor = element(by.css('option[value="' + color + '"]')); return headerColor.click(); } checkAppTitle(name) { - let title = element(by.cssContainingText('.adf-app-title', name)); + const title = element(by.cssContainingText('.adf-app-title', name)); return BrowserVisibility.waitUntilElementIsVisible(title); } @@ -72,7 +72,7 @@ export class HeaderPage { } checkIconIsDisplayed(url) { - let icon = element(by.css('img[src="' + url + '"]')); + const icon = element(by.css('img[src="' + url + '"]')); BrowserVisibility.waitUntilElementIsVisible(icon); } diff --git a/lib/testing/src/lib/core/pages/user-info.page.ts b/lib/testing/src/lib/core/pages/user-info.page.ts index 31ab1da8bd..3dfbfb3cce 100644 --- a/lib/testing/src/lib/core/pages/user-info.page.ts +++ b/lib/testing/src/lib/core/pages/user-info.page.ts @@ -55,19 +55,19 @@ export class UserInfoPage { } clickOnContentServicesTab() { - let tabsPage = new TabsPage(); + const tabsPage = new TabsPage(); tabsPage.clickTabByTitle('Content Services'); return this; } checkProcessServicesTabIsSelected() { - let tabsPage = new TabsPage; + const tabsPage = new TabsPage; tabsPage.checkTabIsSelectedByTitle('Process Services'); return this; } clickOnProcessServicesTab() { - let tabsPage = new TabsPage; + const tabsPage = new TabsPage; tabsPage.clickTabByTitle('Process Services'); return this; } diff --git a/lib/testing/src/lib/material/tabs.page.ts b/lib/testing/src/lib/material/tabs.page.ts index ad195a5dad..f92b4ab700 100644 --- a/lib/testing/src/lib/material/tabs.page.ts +++ b/lib/testing/src/lib/material/tabs.page.ts @@ -21,13 +21,13 @@ import { BrowserVisibility } from '../core/browser-visibility'; export class TabsPage { clickTabByTitle(tabTitle) { - let tab = element(by.cssContainingText("div[id*='mat-tab-label']", tabTitle)); + const tab = element(by.cssContainingText("div[id*='mat-tab-label']", tabTitle)); BrowserVisibility.waitUntilElementIsVisible(tab); tab.click(); } checkTabIsSelectedByTitle(tabTitle) { - let tab = element(by.cssContainingText("div[id*='mat-tab-label']", tabTitle)); + const tab = element(by.cssContainingText("div[id*='mat-tab-label']", tabTitle)); tab.getAttribute('aria-selected').then((result) => { expect(result).toBe('true'); }); diff --git a/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts b/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts index 62bf797a4d..b6c9d50c0e 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts @@ -27,7 +27,7 @@ export class TestingAlfrescoApiService extends AlfrescoApiService { constructor(public appConfig: AppConfigService) { super(null, null); - let oauth = Object.assign({}, this.appConfig.get<any>(AppConfigValues.OAUTHCONFIG, null)); + const oauth = Object.assign({}, this.appConfig.get<any>(AppConfigValues.OAUTHCONFIG, null)); this.config = new AlfrescoApiConfig({ provider: this.appConfig.get<string>(AppConfigValues.PROVIDERS), hostEcm: this.appConfig.get<string>(AppConfigValues.ECMHOST), diff --git a/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts b/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts index 41efdbbd92..bc5aa073fa 100644 --- a/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts +++ b/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts @@ -27,18 +27,18 @@ export class AppListCloudPage { } goToApp(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); BrowserVisibility.waitUntilElementIsVisible(app); app.click(); } checkAppIsNotDisplayed(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); return BrowserVisibility.waitUntilElementIsNotOnPage(app); } checkAppIsDisplayed(applicationName) { - let app = element(by.css('mat-card[title="' + applicationName + '"]')); + const app = element(by.css('mat-card[title="' + applicationName + '"]')); return BrowserVisibility.waitUntilElementIsVisible(app); } diff --git a/lib/testing/src/lib/process-services/pages/form-fields.page.ts b/lib/testing/src/lib/process-services/pages/form-fields.page.ts index f259e7aed9..a3f3c1e9d4 100644 --- a/lib/testing/src/lib/process-services/pages/form-fields.page.ts +++ b/lib/testing/src/lib/process-services/pages/form-fields.page.ts @@ -34,53 +34,53 @@ export class FormFieldsPage { errorMessage = by.css('.adf-error-text-container .adf-error-text'); setFieldValue(locator, field, value) { - let fieldElement: any = element(locator(field)); + const fieldElement: any = element(locator(field)); BrowserVisibility.waitUntilElementIsVisible(fieldElement); fieldElement.clear().sendKeys(value); return this; } checkWidgetIsVisible(fieldId) { - let fieldElement = element.all(by.css(`adf-form-field div[id='field-${fieldId}-container']`)).first(); + const fieldElement = element.all(by.css(`adf-form-field div[id='field-${fieldId}-container']`)).first(); BrowserVisibility.waitUntilElementIsVisible(fieldElement); } checkWidgetIsHidden(fieldId) { - let hiddenElement = element(by.css(`adf-form-field div[id='field-${fieldId}-container'][hidden]`)); + const hiddenElement = element(by.css(`adf-form-field div[id='field-${fieldId}-container'][hidden]`)); BrowserVisibility.waitUntilElementIsVisible(hiddenElement); } getWidget(fieldId) { - let widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); + const widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); BrowserVisibility.waitUntilElementIsVisible(widget); return widget; } getFieldValue(fieldId, valueLocatorParam) { - let value = this.getWidget(fieldId).element(valueLocatorParam || this.valueLocator); + const value = this.getWidget(fieldId).element(valueLocatorParam || this.valueLocator); BrowserVisibility.waitUntilElementIsVisible(value); return value.getAttribute('value'); } getFieldLabel(fieldId, labelLocatorParam) { - let label = this.getWidget(fieldId).all(labelLocatorParam || this.labelLocator).first(); + const label = this.getWidget(fieldId).all(labelLocatorParam || this.labelLocator).first(); BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } getFieldErrorMessage(fieldId) { - let error = this.getWidget(fieldId).element(this.errorMessage); + const error = this.getWidget(fieldId).element(this.errorMessage); return error.getText(); } getFieldText(fieldId, labelLocatorParam) { - let label = this.getWidget(fieldId).element(labelLocatorParam || this.labelLocator); + const label = this.getWidget(fieldId).element(labelLocatorParam || this.labelLocator); BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } getFieldPlaceHolder(fieldId, locator = 'input') { - let placeHolderLocator = element(by.css(`${locator}#${fieldId}`)).getAttribute('placeholder'); + const placeHolderLocator = element(by.css(`${locator}#${fieldId}`)).getAttribute('placeholder'); BrowserVisibility.waitUntilElementIsVisible(placeHolderLocator); return placeHolderLocator; } @@ -138,14 +138,14 @@ export class FormFieldsPage { } selectFormFromDropDown(formName) { - let formNameElement = element(by.cssContainingText('span', formName)); + const formNameElement = element(by.cssContainingText('span', formName)); BrowserVisibility.waitUntilElementIsVisible(formNameElement); formNameElement.click(); } checkWidgetIsReadOnlyMode(fieldId) { - let widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); - let widgetReadOnly = widget.element(by.css('div[class*="adf-readonly"]')); + const widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); + const widgetReadOnly = widget.element(by.css('div[class*="adf-readonly"]')); BrowserVisibility.waitUntilElementIsVisible(widgetReadOnly); return widgetReadOnly; } @@ -156,7 +156,7 @@ export class FormFieldsPage { } setValueInInputById(fieldId, value) { - let input: any = element(by.id(fieldId)); + const input: any = element(by.id(fieldId)); BrowserVisibility.waitUntilElementIsVisible(input); input.clear().sendKeys(value); return this; diff --git a/tslint.json b/tslint.json index f516762fa3..87615cb6ca 100644 --- a/tslint.json +++ b/tslint.json @@ -138,7 +138,7 @@ "no-empty-interface": true, "no-string-literal": false, "no-string-throw": true, - "prefer-const": false, + "prefer-const": true, "unified-signatures": true, "whitespace": [ true, From f9e39aaebd7e416c645f65b862bf97ed789a9463 Mon Sep 17 00:00:00 2001 From: Marouan Bentaleb <38426175+marouanbentaleb@users.noreply.github.com> Date: Mon, 25 Mar 2019 15:23:58 +0100 Subject: [PATCH 003/208] [ADF-NO-ISSUE] Removing wrong dependencies (#4458) --- .../src/lib/core/material/public-api.ts | 18 ++++++++++++++++++ .../src/lib/{ => core}/material/tabs.page.ts | 2 +- lib/testing/src/lib/core/pages/public-api.ts | 1 - .../src/lib/core/pages/user-info.page.ts | 2 +- lib/testing/src/lib/core/public-api.ts | 1 + lib/testing/src/lib/material/public-api.ts | 5 ----- .../process-services-cloud/pages/public-api.ts | 2 -- lib/testing/src/public-api.ts | 2 +- 8 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 lib/testing/src/lib/core/material/public-api.ts rename lib/testing/src/lib/{ => core}/material/tabs.page.ts (94%) delete mode 100644 lib/testing/src/lib/material/public-api.ts diff --git a/lib/testing/src/lib/core/material/public-api.ts b/lib/testing/src/lib/core/material/public-api.ts new file mode 100644 index 0000000000..5e77b5653c --- /dev/null +++ b/lib/testing/src/lib/core/material/public-api.ts @@ -0,0 +1,18 @@ +/*! + * @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. + */ + +export * from './tabs.page'; diff --git a/lib/testing/src/lib/material/tabs.page.ts b/lib/testing/src/lib/core/material/tabs.page.ts similarity index 94% rename from lib/testing/src/lib/material/tabs.page.ts rename to lib/testing/src/lib/core/material/tabs.page.ts index f92b4ab700..12ae7bb8a2 100644 --- a/lib/testing/src/lib/material/tabs.page.ts +++ b/lib/testing/src/lib/core/material/tabs.page.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { BrowserVisibility } from '../core/browser-visibility'; +import { BrowserVisibility } from '../browser-visibility'; export class TabsPage { diff --git a/lib/testing/src/lib/core/pages/public-api.ts b/lib/testing/src/lib/core/pages/public-api.ts index cc3b246893..a3a3be60b5 100644 --- a/lib/testing/src/lib/core/pages/public-api.ts +++ b/lib/testing/src/lib/core/pages/public-api.ts @@ -3,5 +3,4 @@ */ export * from './header.page'; -export * from '../../material/tabs.page'; export * from './user-info.page'; diff --git a/lib/testing/src/lib/core/pages/user-info.page.ts b/lib/testing/src/lib/core/pages/user-info.page.ts index 3dfbfb3cce..582b0d1307 100644 --- a/lib/testing/src/lib/core/pages/user-info.page.ts +++ b/lib/testing/src/lib/core/pages/user-info.page.ts @@ -17,7 +17,7 @@ import { element, by, browser, protractor } from 'protractor'; import { BrowserVisibility } from '../browser-visibility'; -import { TabsPage } from '../../material/tabs.page'; +import { TabsPage } from '../material/tabs.page'; export class UserInfoPage { diff --git a/lib/testing/src/lib/core/public-api.ts b/lib/testing/src/lib/core/public-api.ts index 58347a10f2..f9bf45abd6 100644 --- a/lib/testing/src/lib/core/public-api.ts +++ b/lib/testing/src/lib/core/public-api.ts @@ -4,3 +4,4 @@ export * from './browser-visibility'; export * from './pages/public-api'; +export * from './material/public-api'; diff --git a/lib/testing/src/lib/material/public-api.ts b/lib/testing/src/lib/material/public-api.ts deleted file mode 100644 index 457dd6c15a..0000000000 --- a/lib/testing/src/lib/material/public-api.ts +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Public API Surface of testing - */ - -export * from './tabs.page'; diff --git a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts index 2b844fe887..6ae4c6bed1 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts @@ -3,7 +3,5 @@ */ export * from './login-sso.page'; -export * from '../../core/pages/user-info.page'; -export * from '../app/app-list-cloud.page'; export * from './start-tasks-cloud-component.page'; export * from './task-header-cloud-component.page'; diff --git a/lib/testing/src/public-api.ts b/lib/testing/src/public-api.ts index a238510043..dceecee5ac 100644 --- a/lib/testing/src/public-api.ts +++ b/lib/testing/src/public-api.ts @@ -3,7 +3,7 @@ */ export * from './lib/core/public-api'; -export * from './lib/material/public-api'; +export * from './lib/core/material/public-api'; export * from './lib/content-services/public-api'; export * from './lib/process-services/public-api'; export * from './lib/process-services-cloud/public-api'; From e415bd8cd5b96aaf0bdd93a8ca553973a1eb86ac Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Mon, 25 Mar 2019 16:40:42 +0200 Subject: [PATCH 004/208] [ADF-4241]Added tests for process header cloud component (#4463) * Added tests for process header cloud component * Move the process-header-cloud-component page to testing folder * Changed the test rail ids * Fix lint issues. --- e2e/actions/APS-cloud/process-instances.ts | 5 +- e2e/actions/APS-cloud/query.ts | 10 ++ .../processListCloudComponent.ts | 8 + .../process-header-cloud.e2e.ts | 139 ++++++++++++++++++ ...-cloud.e2e.ts => task-header-cloud.e2e.ts} | 0 e2e/util/constants.js | 7 + .../process-header-cloud-component.page.ts | 72 +++++++++ .../pages/public-api.ts | 1 + 8 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 e2e/process-services-cloud/process-header-cloud.e2e.ts rename e2e/process-services-cloud/{task-details-cloud.e2e.ts => task-header-cloud.e2e.ts} (100%) create mode 100644 lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts diff --git a/e2e/actions/APS-cloud/process-instances.ts b/e2e/actions/APS-cloud/process-instances.ts index a369d95594..5a6f640744 100644 --- a/e2e/actions/APS-cloud/process-instances.ts +++ b/e2e/actions/APS-cloud/process-instances.ts @@ -28,13 +28,14 @@ export class ProcessInstances { await this.api.login(username, password); } - async createProcessInstance(processDefKey, appName) { + async createProcessInstance(processDefKey, appName, options?) { const path = '/' + appName + '-rb/v1/process-instances'; const method = 'POST'; const queryParams = {}, postBody = { 'processDefinitionKey': processDefKey, - 'payloadType': 'StartProcessPayload' + 'payloadType': 'StartProcessPayload', + ...options }; const data = await this.api.performBpmOperation(path, method, queryParams, postBody); diff --git a/e2e/actions/APS-cloud/query.ts b/e2e/actions/APS-cloud/query.ts index 901cfe21f0..be0ec036b1 100644 --- a/e2e/actions/APS-cloud/query.ts +++ b/e2e/actions/APS-cloud/query.ts @@ -38,4 +38,14 @@ export class Query { return data; } + async getProcessInstanceSubProcesses(processInstanceId, appName) { + const path = '/' + appName + '-query/v1/process-instances/' + processInstanceId + '/subprocesses'; + const method = 'GET'; + + const queryParams = {}; + + const data = await this.api.performBpmOperation(path, method, queryParams, {}); + return data; + } + } diff --git a/e2e/pages/adf/process-cloud/processListCloudComponent.ts b/e2e/pages/adf/process-cloud/processListCloudComponent.ts index ab4e24ea0b..603ceb1819 100644 --- a/e2e/pages/adf/process-cloud/processListCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/processListCloudComponent.ts @@ -30,6 +30,14 @@ export class ProcessListCloudComponent { return this.dataTable; } + selectRow(processName) { + return this.dataTable.selectRow('Name', processName); + } + + selectRowById(processId) { + return this.dataTable.selectRow('Id', processId); + } + checkContentIsDisplayedByName(processName) { return this.dataTable.checkContentIsDisplayed('Name', processName); } diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts new file mode 100644 index 0000000000..67049f2c16 --- /dev/null +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -0,0 +1,139 @@ +/*! + * @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 TestConfig = require('../test.config'); +import CONSTANTS = require('../util/constants'); +import { Util } from '../util/util'; +import moment = require('moment'); + +import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; +import { ProcessInstances } from '../actions/APS-cloud/process-instances'; +import { Query } from '../actions/APS-cloud/query'; + +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; +import { LoginSSOPage } from '@alfresco/adf-testing'; +import { SettingsPage } from '../pages/adf/settingsPage'; +import { AppListCloudPage } from '@alfresco/adf-testing'; +import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; +import { ProcessHeaderCloudPage } from '@alfresco/adf-testing'; +import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; +import { browser } from 'protractor'; + +describe('Process Header cloud component', () => { + + describe('Process Header cloud component', () => { + + const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; + const simpleApp = 'simple-app', subProcessApp = 'projectsubprocess'; + let formatDate = 'DD-MM-YYYY'; + + let processHeaderCloudPage = new ProcessHeaderCloudPage(); + + const settingsPage = new SettingsPage(); + const loginSSOPage = new LoginSSOPage(); + const navigationBarPage = new NavigationBarPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); + let processCloudDemoPage = new ProcessCloudDemoPage(); + + const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); + const processInstancesService: ProcessInstances = new ProcessInstances(); + const queryService: Query = new Query(); + + let silentLogin; + let runningProcess, runningCreatedDate, parentCompleteProcess, childCompleteProcess, completedCreatedDate; + + beforeAll(async (done) => { + silentLogin = false; + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + loginSSOPage.clickOnSSOButton(); + browser.ignoreSynchronization = true; + loginSSOPage.loginSSOIdentityService(user, password); + + await processDefinitionService.init(user, password); + let processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + let childProcessDefinition = await processDefinitionService.getProcessDefinitions(subProcessApp); + + await processInstancesService.init(user, password); + runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, + simpleApp, {name: Util.generateRandomString(), businessKey: 'test'}); + runningCreatedDate = moment(runningProcess.entry.startDate).format(formatDate); + parentCompleteProcess = await processInstancesService.createProcessInstance(childProcessDefinition.list.entries[0].entry.key, + subProcessApp, {name: 'cris'}); + + let parentProcessInstance = await queryService.getProcessInstanceSubProcesses(parentCompleteProcess.entry.id, + subProcessApp); + childCompleteProcess = parentProcessInstance.list.entries[0]; + completedCreatedDate = moment(childCompleteProcess.entry.startDate).format(formatDate); + + done(); + }); + + beforeEach(async (done) => { + await navigationBarPage.navigateToProcessServicesCloudPage(); + appListCloudComponent.checkApsContainer(); + done(); + }); + + it('[C305010] Should display process details for running process', async () => { + await appListCloudComponent.goToApp(simpleApp); + tasksCloudDemoPage.taskListCloudComponent().checkTaskListIsLoaded(); + processCloudDemoPage.clickOnProcessFilters(); + + processCloudDemoPage.runningProcessesFilter().checkProcessFilterIsDisplayed(); + processCloudDemoPage.runningProcessesFilter().clickProcessFilter(); + expect(processCloudDemoPage.getActiveFilterName()).toBe('Running Processes'); + processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedByName(runningProcess.entry.name); + + processCloudDemoPage.processListCloudComponent().checkProcessListIsLoaded(); + processCloudDemoPage.processListCloudComponent().selectRow(runningProcess.entry.name); + expect(processHeaderCloudPage.getId()).toEqual(runningProcess.entry.id); + expect(processHeaderCloudPage.getName()).toEqual(runningProcess.entry.name); + expect(processHeaderCloudPage.getStatus()).toEqual(runningProcess.entry.status); + expect(processHeaderCloudPage.getInitiator()).toEqual(runningProcess.entry.initiator); + expect(processHeaderCloudPage.getStartDate()).toEqual(runningCreatedDate); + expect(processHeaderCloudPage.getParentId()).toEqual(CONSTANTS.PROCESS_DETAILS.NO_PARENT); + expect(processHeaderCloudPage.getBusinessKey()).toEqual(runningProcess.entry.businessKey); + expect(processHeaderCloudPage.getLastModified()).toEqual(runningCreatedDate); + }); + + it('[C305008] Should display process details for completed process', async () => { + await appListCloudComponent.goToApp(subProcessApp); + tasksCloudDemoPage.taskListCloudComponent().checkTaskListIsLoaded(); + processCloudDemoPage.clickOnProcessFilters(); + + processCloudDemoPage.completedProcessesFilter().checkProcessFilterIsDisplayed(); + processCloudDemoPage.completedProcessesFilter().clickProcessFilter(); + expect(processCloudDemoPage.getActiveFilterName()).toBe('Completed Processes'); + processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedByName(childCompleteProcess.entry.name); + + processCloudDemoPage.processListCloudComponent().checkProcessListIsLoaded(); + processCloudDemoPage.processListCloudComponent().selectRowById(childCompleteProcess.entry.id); + + expect(processHeaderCloudPage.getId()).toEqual(childCompleteProcess.entry.id); + expect(processHeaderCloudPage.getName()).toEqual(childCompleteProcess.entry.name); + expect(processHeaderCloudPage.getStatus()).toEqual(childCompleteProcess.entry.status); + expect(processHeaderCloudPage.getInitiator()).toEqual(childCompleteProcess.entry.initiator); + expect(processHeaderCloudPage.getStartDate()).toEqual(completedCreatedDate); + expect(processHeaderCloudPage.getParentId()).toEqual(childCompleteProcess.entry.parentId); + expect(processHeaderCloudPage.getBusinessKey()).toEqual(CONSTANTS.PROCESS_DETAILS.NO_BUSINESS_KEY); + expect(processHeaderCloudPage.getLastModified()).toEqual(completedCreatedDate); + }); + + }); + +}); diff --git a/e2e/process-services-cloud/task-details-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts similarity index 100% rename from e2e/process-services-cloud/task-details-cloud.e2e.ts rename to e2e/process-services-cloud/task-header-cloud.e2e.ts diff --git a/e2e/util/constants.js b/e2e/util/constants.js index 70a14017b3..e937d2d668 100644 --- a/e2e/util/constants.js +++ b/e2e/util/constants.js @@ -127,6 +127,13 @@ exports.PROCESS_DESCRIPTION = "No description"; exports.PROCESS_DATE_FORMAT = "mmm dd yyyy"; +exports.PROCESS_DETAILS = { + NO_PARENT: "None", + NO_DATE: "No date", + NO_BUSINESS_KEY: 'None', + NO_DESCRIPTION: 'No description' +}; + exports.PROCESS_STATUS = { RUNNING: 'Running', COMPLETED: 'Completed' diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts new file mode 100644 index 0000000000..83579432b9 --- /dev/null +++ b/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts @@ -0,0 +1,72 @@ +/*! + * @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 { element, by } from 'protractor'; +import { BrowserVisibility } from '../../core/browser-visibility'; + +export class ProcessHeaderCloudPage { + + idField = element.all(by.css('span[data-automation-id*="id"] span')).first(); + nameField = element.all(by.css('span[data-automation-id*="name"] span')).first(); + statusField = element(by.css('span[data-automation-id*="status"] span')); + initiatorField = element(by.css('span[data-automation-id*="initiator"] span')); + startDateField = element(by.css('span[data-automation-id*="startDate"] span')); + lastModifiedField = element(by.css('span[data-automation-id*="lastModified"] span')); + parentIdField = element(by.css('span[data-automation-id*="parentId"] span')); + businessKeyField = element.all(by.css('span[data-automation-id*="businessKey"] span')).first(); + + getId() { + BrowserVisibility.waitUntilElementIsVisible(this.idField); + return this.idField.getText(); + } + + getName() { + BrowserVisibility.waitUntilElementIsVisible(this.nameField); + return this.nameField.getText(); + } + + getStatus() { + BrowserVisibility.waitUntilElementIsVisible(this.statusField); + return this.statusField.getText(); + } + + getInitiator() { + BrowserVisibility.waitUntilElementIsVisible(this.initiatorField); + return this.initiatorField.getText(); + } + + getStartDate() { + BrowserVisibility.waitUntilElementIsVisible(this.startDateField); + return this.startDateField.getText(); + } + + getLastModified() { + BrowserVisibility.waitUntilElementIsVisible(this.lastModifiedField); + return this.lastModifiedField.getText(); + } + + getParentId() { + BrowserVisibility.waitUntilElementIsVisible(this.parentIdField); + return this.parentIdField.getText(); + } + + getBusinessKey() { + BrowserVisibility.waitUntilElementIsVisible(this.businessKeyField); + return this.businessKeyField.getText(); + } + +} diff --git a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts index 6ae4c6bed1..151e1597ab 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts @@ -5,3 +5,4 @@ export * from './login-sso.page'; export * from './start-tasks-cloud-component.page'; export * from './task-header-cloud-component.page'; +export * from './process-header-cloud-component.page'; From c3bbbe6dab905ef18fb1323a9c8e1f0d50af5dae Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Mon, 25 Mar 2019 18:23:04 +0200 Subject: [PATCH 005/208] [ADF-4096] ProcessCloud/TaskList - undefined filename attribute (#4333) * [ADF-4127] ProcessServicesCloud - add claim/unclaim directive (#4464) * [ADF-4127] ProessServicesCloud - claim task directive * [ADF-4127] - fix doc * [ADF-4127] - revert docs changes * [ADF-4127] - revert doc changes * [ADF-4127] - fix doc and reset sourceLinker.js * [ADF-4127] - refractor task-cloud.service. add validation for claim/unclaim and fix unit tests * [ADF-4127] - fix docs files * [ADF-4127[ - add aditional complete task validation * [ADF-4127] - PR changes * [ADF-4127] - complete docs file * [ADF-4127] - more PR changes * [ADF-4127] - change Unclaim task name and wait for task to be claimed and unclaimed before emit the success event * [ADF-4127] - fix unit tests * [ADF-4095] ProcessCloud - change api response format * Revert "[ADF-4095] ProcessCloud - change api response format" This reverts commit 8ddd3477ad3de047911f0538941c65d2bf7e60e2. * [ADF-4096] DatatableComponent - revert changes and remove filename attribute * [ADF-4096] - change filename attribute and fix unit tests * [ADF-4096] - fix core e2e test --- .../claim-task.directive.md | 26 +++++++++++++++++++ .../unclaim-tas.directie.md | 26 +++++++++++++++++++ e2e/pages/adf/contentServicesPage.ts | 18 ++++++------- .../process-services/attachmentListPage.ts | 20 +++++++------- e2e/pages/adf/viewerPage.ts | 2 +- .../datatable/datatable.component.html | 2 +- .../datatable/datatable.component.ts | 15 ++++++++--- .../src/lib/i18n/en.json | 2 +- lib/process-services/i18n/en.json | 2 +- 9 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 docs/process-services-cloud/claim-task.directive.md create mode 100644 docs/process-services-cloud/unclaim-tas.directie.md diff --git a/docs/process-services-cloud/claim-task.directive.md b/docs/process-services-cloud/claim-task.directive.md new file mode 100644 index 0000000000..97ccdd8e80 --- /dev/null +++ b/docs/process-services-cloud/claim-task.directive.md @@ -0,0 +1,26 @@ +--- +Title: Claim Task Directive +Added: v3.1.0 +Status: Experimental +Last reviewed: 2019-03-05 +--- + +# [Claim task directive](../../lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts "Defined in claim-task.directive.ts") + +Claim a task + +## Basic Usage + +```html +<button adf-claim-task [appName]="appName" [taskId]="taskId" (success)="onTaskClaimed()">Complete</button> +``` +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| taskId | `string` | empty |(Required) The id of the task. | +| appName | `string` | empty | (Required) The name of the application. | +| success | `EventEmitter<any>` | empty | Emitted when the task is completed. | +| error | `EventEmitter<any>` | empty | Emitted when the task cannot be completed. | \ No newline at end of file diff --git a/docs/process-services-cloud/unclaim-tas.directie.md b/docs/process-services-cloud/unclaim-tas.directie.md new file mode 100644 index 0000000000..1bdebdf9b0 --- /dev/null +++ b/docs/process-services-cloud/unclaim-tas.directie.md @@ -0,0 +1,26 @@ +--- +Title: Unclaim Task Directive +Added: v3.1.0 +Status: Experimental +Last reviewed: 2019-03-05 +--- + +# [Unclaim task directive](../../lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts "Defined in unclaim-task.directive.ts") + +Unclaim a task + +## Basic Usage + +```html +<button adf-unclaim-task [appName]="appName" [taskId]="taskId" (success)="onTaskUnclaimed()">Complete</button> +``` +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| taskId | `string` | empty |(Required) The id of the task. | +| appName | `string` | empty | (Required) The name of the application. | +| success | `EventEmitter<any>` | empty | Emitted when the task is completed. | +| error | `EventEmitter<any>` | empty | Emitted when the task cannot be completed. | \ No newline at end of file diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index ccf4e9291c..8c5f4cdcf0 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -544,7 +544,7 @@ export class ContentServicesPage { } checkLockIsDisplayedForElement(name) { - const lockButton = element(by.css(`div.adf-datatable-cell[filename="${name}"] button`)); + const lockButton = element(by.css(`div.adf-datatable-cell[data-automation-id="${name}"] button`)); Util.waitUntilElementIsVisible(lockButton); } @@ -553,7 +553,7 @@ export class ContentServicesPage { } async getStyleValueForRowText(rowName, styleName) { - const row = element(by.css(`div.adf-datatable-cell[filename="${rowName}"] span.adf-datatable-cell-value[title="${rowName}"]`)); + const row = element(by.css(`div.adf-datatable-cell[data-automation-id="${rowName}"] span.adf-datatable-cell-value[title="${rowName}"]`)); Util.waitUntilElementIsVisible(row); return row.getCssValue(styleName); } @@ -577,7 +577,7 @@ export class ContentServicesPage { } checkIconForRowIsDisplayed(fileName) { - const iconRow = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${fileName}"] img`)); + const iconRow = element(by.css(`.adf-document-list-container div.adf-datatable-cell[data-automation-id="${fileName}"] img`)); Util.waitUntilElementIsVisible(iconRow); return iconRow; } @@ -607,17 +607,17 @@ export class ContentServicesPage { } getDocumentCardIconForElement(elementName) { - const elementIcon = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"] img`)); + const elementIcon = element(by.css(`.adf-document-list-container div.adf-datatable-cell[data-automation-id="${elementName}"] img`)); return elementIcon.getAttribute('src'); } checkDocumentCardPropertyIsShowed(elementName, propertyName) { - const elementProperty = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"][title="${propertyName}"]`)); + const elementProperty = element(by.css(`.adf-document-list-container div.adf-datatable-cell[data-automation-id="${elementName}"][title="${propertyName}"]`)); Util.waitUntilElementIsVisible(elementProperty); } getAttributeValueForElement(elementName, propertyName) { - const elementSize = element(by.css(`.adf-document-list-container div.adf-datatable-cell[filename="${elementName}"][title="${propertyName}"] span`)); + const elementSize = element(by.css(`.adf-document-list-container div.adf-datatable-cell[data-automation-id="${elementName}"][title="${propertyName}"] span`)); return elementSize.getText(); } @@ -627,9 +627,9 @@ export class ContentServicesPage { } navigateToCardFolder(folderName) { - const folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[filename="${folderName}"]`)); + let folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[data-automation-id="${folderName}"]`)); folderCard.click(); - const folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[filename="${folderName}"].adf-datatable-cell--image`)); + let folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[data-automation-id="${folderName}"].adf-datatable-cell--image`)); Util.waitUntilElementIsVisible(folderSelected); browser.actions().sendKeys(protractor.Key.ENTER).perform(); } @@ -659,7 +659,7 @@ export class ContentServicesPage { } clickContentNodeSelectorResult(name) { - const resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[filename="${name}"`)).first(); + const resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[data-automation-id="${name}"`)).first(); Util.waitUntilElementIsVisible(resultElement); resultElement.click(); } diff --git a/e2e/pages/adf/process-services/attachmentListPage.ts b/e2e/pages/adf/process-services/attachmentListPage.ts index fdc5004df2..6d27b548ff 100644 --- a/e2e/pages/adf/process-services/attachmentListPage.ts +++ b/e2e/pages/adf/process-services/attachmentListPage.ts @@ -43,7 +43,7 @@ export class AttachmentListPage { } checkFileIsAttached(name) { - const fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); + const fileAttached = element.all(by.css('div[data-automation-id="' + name + '"]')).first(); Util.waitUntilElementIsVisible(fileAttached); } @@ -52,8 +52,8 @@ export class AttachmentListPage { } viewFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[filename="' + name + '"]')).first()); - element.all(by.css('div[filename="' + name + '"]')).first().click(); + Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + element.all(by.css('div[data-automation-id="' + name + '"]')).first().click(); Util.waitUntilElementIsVisible(this.buttonMenu); this.buttonMenu.click(); Util.waitUntilElementIsVisible(this.viewButton); @@ -64,8 +64,8 @@ export class AttachmentListPage { } removeFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[filename="' + name + '"]')).first()); - element.all(by.css('div[filename="' + name + '"]')).first().click(); + Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + element.all(by.css('div[data-automation-id="' + name + '"]')).first().click(); Util.waitUntilElementIsVisible(this.buttonMenu); this.buttonMenu.click(); Util.waitUntilElementIsVisible(this.removeButton); @@ -76,8 +76,8 @@ export class AttachmentListPage { } downloadFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[filename="' + name + '"]')).first()); - element.all(by.css('div[filename="' + name + '"]')).first().click(); + Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + element.all(by.css('div[data-automation-id="' + name + '"]')).first().click(); Util.waitUntilElementIsVisible(this.buttonMenu); this.buttonMenu.click(); Util.waitUntilElementIsVisible(this.downloadButton); @@ -87,8 +87,8 @@ export class AttachmentListPage { } doubleClickFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[filename="' + name + '"]')).first()); - const fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); + Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + const fileAttached = element.all(by.css('div[data-automation-id="' + name + '"]')).first(); Util.waitUntilElementIsVisible(fileAttached); Util.waitUntilElementIsClickable(fileAttached); fileAttached.click(); @@ -96,7 +96,7 @@ export class AttachmentListPage { } checkFileIsRemoved(name) { - const fileAttached = element.all(by.css('div[filename="' + name + '"]')).first(); + const fileAttached = element.all(by.css('div[data-automation-id="' + name + '"]')).first(); Util.waitUntilElementIsNotVisible(fileAttached); return this; } diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index 51361a5bad..64ccb71bc5 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -103,7 +103,7 @@ export class ViewerPage { } viewFile(fileName) { - const fileView = element.all(by.css(`#document-list-container div[filename="${fileName}"]`)).first(); + const fileView = element.all(by.css(`#document-list-container div[data-automation-id="${fileName}"]`)).first(); Util.waitUntilElementIsVisible(fileView); fileView.click(); browser.actions().sendKeys(protractor.Key.ENTER).perform(); diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 8b0a49affd..27cfd67003 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -90,7 +90,7 @@ role="gridcell" class=" adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}}" [attr.title]="col.title | translate" - [attr.filename]="getFilename(row)" + [attr.data-automation-id]="getAutomationValue(row, col)" tabindex="0" (click)="onRowClick(row, $event)" (keydown.enter)="onEnterKeyPressed(row, $event)" diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 5f4568eea6..524984017b 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -599,10 +599,6 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, return `${row.cssClass} ${this.rowStyleClass}`; } - getFilename(row: DataRow): string { - return row.getValue('name'); - } - getSortingKey(): string { if (this.data.getSorting()) { return this.data.getSorting().key; @@ -694,4 +690,15 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, this.fakeRows = []; } } + + getNameColumnValue() { + return this.data.getColumns().find( (el: any) => { + return el.key.includes('name'); + }); + } + + getAutomationValue(row: DataRow, col: DataColumn) { + const name = this.getNameColumnValue(); + return name ? row.getValue(name.key) : ''; + } } diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 671168543d..8080e779ee 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -174,7 +174,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Claim", - "UNCLAIM": "Requeue" + "UNCLAIM": "Release" }, "PROPERTIES": { "TASK_NAME": "Task", diff --git a/lib/process-services/i18n/en.json b/lib/process-services/i18n/en.json index 6d2c1283ac..199cd86c4d 100644 --- a/lib/process-services/i18n/en.json +++ b/lib/process-services/i18n/en.json @@ -73,7 +73,7 @@ "BUTTON": { "COMPLETE": "Complete", "CLAIM": "Claim", - "UNCLAIM": "Requeue", + "UNCLAIM": "Release", "DRAG-ATTACHMENT": "Drop files to upload", "UPLOAD-ATTACHMENT": "Upload Attachment" }, From 391094e4674b6eaf1ed97c958412b1811ed1c4f2 Mon Sep 17 00:00:00 2001 From: Maurizio Vitale <maurizio.vitale@alfresco.com> Date: Mon, 25 Mar 2019 17:07:22 +0000 Subject: [PATCH 006/208] [ADF-4295] AuthGuardSsoRoleService - Provide a way to check the resorces_access of the jwt token (#4488) * Provide a way to check the resorces_access of a jwt token * Add unit test in case the client role is missing or contains a different one * Improve the documentation related to the AuthGuardSSO --- demo-shell/src/app/app.routes.ts | 2 + .../services/auth-guard-sso-role.service.md | 24 ++++- .../auth-guard-sso-role.service.spec.ts | 94 +++++++++++++++++++ .../services/auth-guard-sso-role.service.ts | 51 ++++++++-- 4 files changed, 160 insertions(+), 11 deletions(-) diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 1c5a7b2dc5..02ad2ba0b6 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -167,6 +167,8 @@ export const appRoutes: Routes = [ }, { path: ':appName', + canActivate: [AuthGuardSsoRoleService], + data: { clientRoles: ['appName'], roles: ['ACTIVITI_USER'], redirectUrl: '/error/403'}, children: [ { path: '', diff --git a/docs/core/services/auth-guard-sso-role.service.md b/docs/core/services/auth-guard-sso-role.service.md index f40051e974..3d8917caed 100644 --- a/docs/core/services/auth-guard-sso-role.service.md +++ b/docs/core/services/auth-guard-sso-role.service.md @@ -13,9 +13,10 @@ Checks the user roles of a user. The [Auth Guard SSO role service](../../core/services/auth-guard-sso-role.service.md) implements an Angular [route guard](https://angular.io/guide/router#milestone-5-route-guards) -to check the user has the right role permission. This is typically used with the -`canActivate` guard check in the route definition. The roles that user needs to have in order to access the route has to be specified in the roles array as in the example below: +to check the user has the right realms/client roles permission. This is typically used with the +`canActivate` guard check in the route definition. The Auth Guard SSO is resposible to check if the JWT contains Realm roles (realm_access) or Client roles (resource_access) based on the route configuration. +*Realms role Example* ```ts const appRoutes: Routes = [ ... @@ -29,7 +30,24 @@ const appRoutes: Routes = [ ] ``` -If the user now clicks on a link or button that follows this route, they will be not able to access this content if they do not have the roles. +If the user now clicks on a link or button that follows this route, they will be not able to access this content if they do not have the Realms roles. + + +Client role Example +```ts +const appRoutes: Routes = [ + ... + { + path: ':examplepath', + component: ExampleComponent, + canActivate: [ AuthGuardSsoRoleService ], + data: { clientRoles: ['examplepath'], roles: ['ACTIVITI_USER']}, + }, + ... +] +``` + +If the user now clicks on a link or button that follows this route, they will be not able to access this content if they do not have the Client roles. ## Redirect over forbidden diff --git a/lib/core/services/auth-guard-sso-role.service.spec.ts b/lib/core/services/auth-guard-sso-role.service.spec.ts index bc32c4e6e8..a687428898 100644 --- a/lib/core/services/auth-guard-sso-role.service.spec.ts +++ b/lib/core/services/auth-guard-sso-role.service.spec.ts @@ -116,4 +116,98 @@ describe('Auth Guard SSO role service', () => { expect(routerService.navigate).not.toHaveBeenCalled(); })); + it('Should canActivate be false hasRealm is true and hasClientRol is false', () => { + const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); + spyOn(this, 'hasRealmRoles').and.returnValue(true); + spyOn(this, 'hasRealmRolesForClientRole').and.returnValue(false); + + route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; + + expect(authGuard.canActivate(route, null)).toBeFalsy(); + }); + + it('Should canActivate be false hasRealm is false and hasClientRol is true', () => { + const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); + spyOn(this, 'hasRealmRoles').and.returnValue(false); + spyOn(this, 'hasRealmRolesForClientRole').and.returnValue(true); + + route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; + + expect(authGuard.canActivate(route, null)).toBeFalsy(); + }); + + it('Should canActivate be true if both Real Role and Client Role are present int the JWT token', () => { + const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); + spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + + spyOn(jwtHelperService, 'decodeToken').and.returnValue({ + 'realm_access': { roles: ['role1'] }, + 'resource_access': { fakeapp: { roles: ['role2'] }} + }); + + route.params = {appName: 'fakeapp'}; + route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; + + expect(authGuard.canActivate(route, null)).toBeTruthy(); + }); + + it('Should canActivate be false if the Client Role is not present int the JWT token with the correct role', () => { + const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); + spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + + spyOn(jwtHelperService, 'decodeToken').and.returnValue({ + 'realm_access': { roles: ['role1'] }, + 'resource_access': { fakeapp: { roles: ['role3'] }} + }); + + route.params = {appName: 'fakeapp'}; + route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; + + expect(authGuard.canActivate(route, null)).toBeFalsy(); + }); + + describe('ClientRole ', () => { + + it('Should be true if the resource_access contains the single role', () => { + spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + + spyOn(jwtHelperService, 'decodeToken').and.returnValue( + {'resource_access': { fakeapp: { roles: ['role1'] } } + }); + + const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1'] ); + expect(result).toBeTruthy(); + }); + + it('Should be true if the resource_access contains at least one of the roles', () => { + spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + + spyOn(jwtHelperService, 'decodeToken').and.returnValue( + {'resource_access': { fakeapp: { roles: ['role1'] } } + }); + + const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2'] ); + expect(result).toBeTruthy(); + }); + + it('Should be false if the resource_access does not contain the role', () => { + spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(jwtHelperService, 'decodeToken').and.returnValue( + {'resource_access': { fakeapp: { roles: ['role3'] } } + }); + const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2']); + expect(result).toBeFalsy(); + }); + + it('Should be false if the resource_access does not contain the client role related to the app', () => { + spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(jwtHelperService, 'decodeToken').and.returnValue( + {'resource_access': { anotherfakeapp: { roles: ['role1'] } } + }); + const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2']); + expect(result).toBeFalsy(); + }); + + }); + }); diff --git a/lib/core/services/auth-guard-sso-role.service.ts b/lib/core/services/auth-guard-sso-role.service.ts index b9d0ec78be..d3a496314b 100644 --- a/lib/core/services/auth-guard-sso-role.service.ts +++ b/lib/core/services/auth-guard-sso-role.service.ts @@ -27,12 +27,24 @@ export class AuthGuardSsoRoleService implements CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { let hasRole = false; + let hasRealmRole = false; + let hasClientRole = true; if (route.data) { - const rolesToCheck = route.data['roles']; - hasRole = this.hasRoles(rolesToCheck); + if (route.data['roles']) { + const rolesToCheck = route.data['roles']; + hasRealmRole = this.hasRealmRoles(rolesToCheck); + } + + if (route.data['clientRoles']) { + const clientRoleName = route.params[route.data['clientRoles']]; + const rolesToCheck = route.data['roles']; + hasClientRole = this.hasRealmRolesForClientRole(clientRoleName, rolesToCheck); + } } + hasRole = hasRealmRole && hasClientRole; + if (!hasRole && route.data && route.data['redirectUrl']) { this.router.navigate(['/' + route.data['redirectUrl']]); } @@ -43,33 +55,56 @@ export class AuthGuardSsoRoleService implements CanActivate { constructor(private storageService: StorageService, private jwtHelperService: JwtHelperService, private router: Router) { } - getRoles(): string[] { + getRealmRoles(): string[] { const access = this.getValueFromToken<any>('realm_access'); const roles = access ? access['roles'] : []; return roles; } + getClientRoles(client: string): string[] { + const clientRole = this.getValueFromToken<any>('resource_access')[client]; + const roles = clientRole ? clientRole['roles'] : []; + return roles; + } + getAccessToken(): string { return this.storageService.getItem('access_token'); } - hasRole(role: string): boolean { + hasRealmRole(role: string): boolean { let hasRole = false; if (this.getAccessToken()) { - const roles = this.getRoles(); - hasRole = roles.some((currentRole) => { + const realmRoles = this.getRealmRoles(); + hasRole = realmRoles.some((currentRole) => { return currentRole === role; }); } return hasRole; } - hasRoles(rolesToCheck: string []): boolean { + hasRealmRoles(rolesToCheck: string []): boolean { return rolesToCheck.some((currentRole) => { - return this.hasRole(currentRole); + return this.hasRealmRole(currentRole); }); } + hasRealmRolesForClientRole(clientRole: string, rolesToCheck: string []): boolean { + return rolesToCheck.some((currentRole) => { + return this.hasClientRole(clientRole, currentRole); + }); + } + + hasClientRole(clientRole, role: string): boolean { + let hasRole = false; + if (this.getAccessToken()) { + const clientRoles = this.getClientRoles(clientRole); + hasRole = clientRoles.some((currentRole) => { + return currentRole === role; + }); + } + return hasRole; + } + getValueFromToken<T>(key: string): T { let value; const accessToken = this.getAccessToken(); From 046d3f2e333d2e2fe49a381621d7b8a1293bdbb2 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 26 Mar 2019 12:47:30 +0000 Subject: [PATCH 007/208] fix new lint --- e2e/pages/adf/contentServicesPage.ts | 4 +- .../process-header-cloud.e2e.ts | 12 ++-- e2e/search/search-component.e2e.ts | 7 +- ...dit-process-filter-cloud.component.spec.ts | 70 +++++++++---------- 4 files changed, 45 insertions(+), 48 deletions(-) diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index 8c5f4cdcf0..3bc7aa25ba 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -627,9 +627,9 @@ export class ContentServicesPage { } navigateToCardFolder(folderName) { - let folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[data-automation-id="${folderName}"]`)); + const folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[data-automation-id="${folderName}"]`)); folderCard.click(); - let folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[data-automation-id="${folderName}"].adf-datatable-cell--image`)); + const folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[data-automation-id="${folderName}"].adf-datatable-cell--image`)); Util.waitUntilElementIsVisible(folderSelected); browser.actions().sendKeys(protractor.Key.ENTER).perform(); } diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index 67049f2c16..b8372187a2 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -39,16 +39,16 @@ describe('Process Header cloud component', () => { const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const simpleApp = 'simple-app', subProcessApp = 'projectsubprocess'; - let formatDate = 'DD-MM-YYYY'; + const formatDate = 'DD-MM-YYYY'; - let processHeaderCloudPage = new ProcessHeaderCloudPage(); + const processHeaderCloudPage = new ProcessHeaderCloudPage(); const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - let processCloudDemoPage = new ProcessCloudDemoPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); const processInstancesService: ProcessInstances = new ProcessInstances(); @@ -65,8 +65,8 @@ describe('Process Header cloud component', () => { loginSSOPage.loginSSOIdentityService(user, password); await processDefinitionService.init(user, password); - let processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - let childProcessDefinition = await processDefinitionService.getProcessDefinitions(subProcessApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const childProcessDefinition = await processDefinitionService.getProcessDefinitions(subProcessApp); await processInstancesService.init(user, password); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, @@ -75,7 +75,7 @@ describe('Process Header cloud component', () => { parentCompleteProcess = await processInstancesService.createProcessInstance(childProcessDefinition.list.entries[0].entry.key, subProcessApp, {name: 'cris'}); - let parentProcessInstance = await queryService.getProcessInstanceSubProcesses(parentCompleteProcess.entry.id, + const parentProcessInstance = await queryService.getProcessInstanceSubProcesses(parentCompleteProcess.entry.id, subProcessApp); childCompleteProcess = parentProcessInstance.list.entries[0]; completedCreatedDate = moment(childCompleteProcess.entry.startDate).format(formatDate); diff --git a/e2e/search/search-component.e2e.ts b/e2e/search/search-component.e2e.ts index ff3063fd7f..8909337c36 100644 --- a/e2e/search/search-component.e2e.ts +++ b/e2e/search/search-component.e2e.ts @@ -49,9 +49,6 @@ describe('Search component - Search Bar', () => { const loginPage = new LoginPage(); const contentServicesPage = new ContentServicesPage(); - const searchDialog = new SearchDialog(); - const searchResultPage = new SearchResultsPage(); - const filePreviewPage = new FilePreviewPage(); const searchDialog = new SearchDialog(); const searchResultPage = new SearchResultsPage(); @@ -80,7 +77,7 @@ describe('Search component - Search Bar', () => { 'name': thirdFolderName, 'shortName': thirdFolderName.substring(0, 8) }); - let term = 'Zoizo'; + const term = 'Zoizo'; let fileHighlightUploaded; @@ -309,7 +306,7 @@ describe('Search component - Search Bar', () => { const navigationBar = new NavigationBarPage(); const configEditor = new ConfigEditorPage(); - let searchConfiguration = new SearchConfiguration().getConfiguration(); + const searchConfiguration = new SearchConfiguration().getConfiguration(); beforeAll(async () => { diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts index baea35e1f9..1364d94812 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts @@ -40,7 +40,7 @@ describe('EditProcessFilterCloudComponent', () => { let getRunningApplicationsSpy: jasmine.Spy; let getProcessFilterByIdSpy: jasmine.Spy; - let fakeFilter = new ProcessFilterCloudModel({ + const fakeFilter = new ProcessFilterCloudModel({ name: 'FakeRunningProcess', icon: 'adjust', id: 'mock-process-filter-id', @@ -85,7 +85,7 @@ describe('EditProcessFilterCloudComponent', () => { }); it('should fetch process instance filter by id', async(() => { - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -100,7 +100,7 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should display filter name as title', () => { - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); const title = fixture.debugElement.nativeElement.querySelector('#adf-edit-process-filter-title-id'); @@ -117,7 +117,7 @@ describe('EditProcessFilterCloudComponent', () => { describe('EditProcessFilter form', () => { beforeEach(() => { - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); }); @@ -145,33 +145,33 @@ describe('EditProcessFilterCloudComponent', () => { it('should disable save button if the process filter is not changed', async(() => { component.toggleFilterActions = true; - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); expect(saveButton.disabled).toEqual(true); }); })); it('should disable saveAs button if the process filter is not changed', async(() => { component.toggleFilterActions = true; - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); expect(saveButton.disabled).toEqual(true); }); })); it('should enable delete button by default', async(() => { component.toggleFilterActions = true; - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - let deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); + const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); expect(deleteButton.disabled).toEqual(false); }); })); @@ -179,12 +179,12 @@ describe('EditProcessFilterCloudComponent', () => { it('should display current process filter details', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"]'); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); - let orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-order"]'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); + const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-order"]'); expect(stateElement).toBeDefined(); expect(sortElement).toBeDefined(); expect(orderElement).toBeDefined(); @@ -196,9 +196,9 @@ describe('EditProcessFilterCloudComponent', () => { it('should enable save button if the process filter is changed', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - let stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger'); + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger'); stateElement.click(); fixture.detectChanges(); const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); @@ -212,7 +212,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should display state drop down', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger'); stateElement.click(); @@ -225,7 +225,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should display sort drop down', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"] .mat-select-trigger'); sortElement.click(); @@ -238,7 +238,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should display order drop down', async(() => { fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); const orderElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-order"] .mat-select-trigger'); orderElement.click(); @@ -254,7 +254,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); component.filterProperties = ['appName', 'processName']; fixture.detectChanges(); - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -269,7 +269,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); component.filterProperties = []; fixture.detectChanges(); - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -293,7 +293,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); component.filterProperties = ['appName', 'processName']; fixture.detectChanges(); - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); const appController = component.editProcessFilterForm.get('appName'); @@ -306,13 +306,13 @@ describe('EditProcessFilterCloudComponent', () => { })); it('should display default sort properties', async(() => { - let processFilterIdchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIdchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIdchange }); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -336,13 +336,13 @@ describe('EditProcessFilterCloudComponent', () => { }); component.sortProperties = ['id', 'processName', 'processDefinitionId']; fixture.detectChanges(); - let processFilterIdchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIdchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIdchange }); fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); - let sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); + const sortElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-sort"]'); sortElement.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -359,7 +359,7 @@ describe('EditProcessFilterCloudComponent', () => { describe('edit filter actions', () => { beforeEach(() => { - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); }); @@ -367,7 +367,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should emit save event and save the filter on click save button', async(() => { component.toggleFilterActions = true; const saveFilterSpy = spyOn(service, 'updateFilter').and.returnValue(fakeFilter); - let saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); + const saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); @@ -390,7 +390,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should emit delete event and delete the filter on click of delete button', async(() => { component.toggleFilterActions = true; const deleteFilterSpy = spyOn(service, 'deleteFilter').and.callThrough(); - let deleteSpy: jasmine.Spy = spyOn(component.action, 'emit'); + const deleteSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); @@ -411,7 +411,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should emit saveAs event and add filter on click saveAs button', async(() => { component.toggleFilterActions = true; const saveAsFilterSpy = spyOn(service, 'addFilter').and.callThrough(); - let saveAsSpy: jasmine.Spy = spyOn(component.action, 'emit'); + const saveAsSpy: jasmine.Spy = spyOn(component.action, 'emit'); fixture.detectChanges(); const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); @@ -436,7 +436,7 @@ describe('EditProcessFilterCloudComponent', () => { it('should display default filter actions', async(() => { fixture.detectChanges(); component.toggleFilterActions = true; - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -459,7 +459,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); component.actions = ['save']; fixture.detectChanges(); - let processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); + const processFilterIDchange = new SimpleChange(null, 'mock-process-filter-id', true); component.ngOnChanges({ 'id': processFilterIDchange }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -475,7 +475,7 @@ describe('EditProcessFilterCloudComponent', () => { component.actions = []; component.id = 'mock-process-filter-id'; fixture.detectChanges(); - let expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); fixture.detectChanges(); fixture.whenStable().then(() => { From c9dbcdfc8c887df06d144534ebc95ad8b472ff85 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 26 Mar 2019 12:56:03 +0000 Subject: [PATCH 008/208] [ADF-4242] Make Date format uniform across components (#4496) --- .../task/task-header/components/task-header-cloud.component.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index 3aa0fa3c1b..af9c24e2bf 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -121,6 +121,7 @@ export class TaskHeaderCloudComponent implements OnInit { label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE', value: this.taskDetails.dueDate, key: 'dueDate', + format: 'DD-MM-YYYY', default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'), editable: this.isReadOnlyMode() } @@ -137,6 +138,7 @@ export class TaskHeaderCloudComponent implements OnInit { { label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.CREATED', value: this.taskDetails.createdDate, + format: 'DD-MM-YYYY', key: 'created' } ), @@ -159,6 +161,7 @@ export class TaskHeaderCloudComponent implements OnInit { { label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.END_DATE', value: '', + format: 'DD-MM-YYYY', key: 'endDate' } ), From fbb6ab6cb858a06a257bfb40801b3269eacae3f2 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 26 Mar 2019 14:54:49 +0000 Subject: [PATCH 009/208] update version --- demo-shell/package.json | 2 +- lib/content-services/package.json | 4 ++-- lib/core/package.json | 2 +- lib/extensions/package.json | 2 +- lib/insights/package.json | 6 +++--- lib/process-services-cloud/package.json | 4 ++-- lib/process-services/package.json | 6 +++--- lib/testing/package.json | 2 +- package.json | 16 ++++++++-------- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/demo-shell/package.json b/demo-shell/package.json index 5f45d1d4ac..3dcc1e9a1d 100644 --- a/demo-shell/package.json +++ b/demo-shell/package.json @@ -1,7 +1,7 @@ { "name": "Alfresco-ADF-Angular-Demo", "description": "Demo shell for Alfresco Angular components", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "repository": { "type": "git", diff --git a/lib/content-services/package.json b/lib/content-services/package.json index 5885fef812..33539613c8 100644 --- a/lib/content-services/package.json +++ b/lib/content-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-content-services", "description": "Alfresco ADF content services", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-content-services.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.1.0-beta5", + "@alfresco/adf-core": "3.2.0-beta1", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/core/package.json b/lib/core/package.json index f4ba426e90..c91201a10b 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-core", "description": "Alfresco ADF core", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-core.js", "repository": { diff --git a/lib/extensions/package.json b/lib/extensions/package.json index 5941a2e6c2..1f045cf9d0 100644 --- a/lib/extensions/package.json +++ b/lib/extensions/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-extensions", "description": "Provides extensibility support for ADF applications.", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-extensions.js", "repository": { diff --git a/lib/insights/package.json b/lib/insights/package.json index c0119744d6..eb32cd060e 100644 --- a/lib/insights/package.json +++ b/lib/insights/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-insights", "description": "Alfresco ADF insights", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-insights.js", "repository": { @@ -27,8 +27,8 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.1.0-beta5", - "@alfresco/adf-content-services": "3.1.0-beta5", + "@alfresco/adf-core": "3.2.0-beta1", + "@alfresco/adf-content-services": "3.2.0-beta1", "@ngx-translate/core": ">=11.0.0", "chart.js": ">=2.5.0", "core-js": ">=2.5.4", diff --git a/lib/process-services-cloud/package.json b/lib/process-services-cloud/package.json index a5271b4cad..1344bf7db8 100644 --- a/lib/process-services-cloud/package.json +++ b/lib/process-services-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services-cloud", "description": "Alfresco ADF process services cloud", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services-cloud.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.1.0-beta5", + "@alfresco/adf-core": "3.2.0-beta1", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/process-services/package.json b/lib/process-services/package.json index 0f55324c2c..d74d2cac0d 100644 --- a/lib/process-services/package.json +++ b/lib/process-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services", "description": "Alfresco ADF process services", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services.js", "repository": { @@ -27,8 +27,8 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.1.0-beta5", - "@alfresco/adf-content-services": "3.1.0-beta5", + "@alfresco/adf-core": "3.2.0-beta1", + "@alfresco/adf-content-services": "3.2.0-beta1", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", "hammerjs": ">=2.0.8", diff --git a/lib/testing/package.json b/lib/testing/package.json index 6b4e3b73c7..d4bba9d1af 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,6 +1,6 @@ { "name": "@alfresco/adf-testing", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0", diff --git a/package.json b/package.json index d1713d21ab..37f2f8c4a3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alfresco-components", "description": "Alfresco Angular components", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "author": "Alfresco Software, Ltd.", "main": "./index.js", "scripts": { @@ -55,13 +55,13 @@ "process services-cloud" ], "dependencies": { - "@alfresco/adf-content-services": "3.1.0-beta5", - "@alfresco/adf-core": "3.1.0-beta5", - "@alfresco/adf-extensions": "3.1.0-beta5", - "@alfresco/adf-insights": "3.1.0-beta5", - "@alfresco/adf-process-services": "3.1.0-beta5", - "@alfresco/adf-process-services-cloud": "3.1.0-beta5", - "@alfresco/adf-testing": "3.1.0-beta5", + "@alfresco/adf-content-services": "3.2.0-beta1", + "@alfresco/adf-core": "3.2.0-beta1", + "@alfresco/adf-extensions": "3.2.0-beta1", + "@alfresco/adf-insights": "3.2.0-beta1", + "@alfresco/adf-process-services": "3.2.0-beta1", + "@alfresco/adf-process-services-cloud": "3.2.0-beta1", + "@alfresco/adf-testing": "3.2.0-beta1", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "@angular/animations": "7.0.3", "@angular/cdk": "7.0.3", From 89f612bbb043b59ea880c84cfc340e59e1d04501 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 26 Mar 2019 17:05:03 +0000 Subject: [PATCH 010/208] update codelyzer last version wit accessibility check --- .../components/document-list.component.html | 3 +- .../components/search-control.component.html | 2 +- .../components/search-control.component.ts | 11 +- lib/core/about/about.component.html | 14 +- lib/core/comments/comment-list.component.html | 5 +- .../widgets/people/people.widget.html | 2 +- .../login/components/login.component.html | 12 +- .../settings/host-settings.component.html | 6 +- .../components/pdfViewer-thumb.component.html | 2 +- .../viewer/components/viewer.component.html | 2 +- .../widgets/date-range/date-range.widget.html | 4 +- .../attach-file-widget.component.html | 4 +- .../people-search-field.component.html | 4 +- .../components/people/people.component.html | 2 +- lib/tslint.json | 7 +- package-lock.json | 181 ++++++++++-------- package.json | 2 +- tslint.json | 13 +- 18 files changed, 150 insertions(+), 126 deletions(-) diff --git a/lib/content-services/document-list/components/document-list.component.html b/lib/content-services/document-list/components/document-list.component.html index a2526e8c01..f006522f5d 100644 --- a/lib/content-services/document-list/components/document-list.component.html +++ b/lib/content-services/document-list/components/document-list.component.html @@ -31,9 +31,8 @@ <div class="adf-empty-folder-this-space-is-empty">{{'ADF-DOCUMENT-LIST.EMPTY.HEADER' | translate}}</div> <div fxHide.lt-md="true" class="adf-empty-folder-drag-drop">{{ 'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.TITLE' | translate }}</div> <div fxHide.lt-md="true" class="adf-empty-folder-any-files-here-to-add">{{ 'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.SUBTITLE' | translate }}</div> - <img class="adf-empty-folder-image" [src]="emptyFolderImageUrl"> + <img [alt]="'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.TITLE' | translate" class="adf-empty-folder-image" [src]="emptyFolderImageUrl"> </div> - <!-- <div adf-empty-list-header class="adf-empty-list-header"> {{'ADF-DOCUMENT-LIST.EMPTY.HEADER' | translate}} </div> --> </adf-empty-list> <ng-content select="adf-custom-empty-content-template, empty-folder-content"></ng-content> </ng-template> diff --git a/lib/content-services/search/components/search-control.component.html b/lib/content-services/search/components/search-control.component.html index 6ff83bab2f..317075412f 100644 --- a/lib/content-services/search/components/search-control.component.html +++ b/lib/content-services/search/components/search-control.component.html @@ -50,7 +50,7 @@ (touchend)="elementClicked(item)"> <!-- This is a comment --> <mat-icon mat-list-icon> - <img [src]="getMimeTypeIcon(item)"/> + <img [alt]="getMimeType(item)" [src]="getMimeTypeIcon(item)"/> </mat-icon> <h4 mat-line id="result_name_{{idx}}" *ngIf="highlight; else elseBlock" diff --git a/lib/content-services/search/components/search-control.component.ts b/lib/content-services/search/components/search-control.component.ts index e0602c00bb..eefd255197 100644 --- a/lib/content-services/search/components/search-control.component.ts +++ b/lib/content-services/search/components/search-control.component.ts @@ -174,14 +174,21 @@ export class SearchControlComponent implements OnInit, OnDestroy { getMimeTypeIcon(node: NodeEntry): string { let mimeType; + mimeType = this.getMimeType(node); + + return this.thumbnailService.getMimeTypeIcon(mimeType); + } + + private getMimeType(node: NodeEntry) { + let mimeType; + if (node.entry.content && node.entry.content.mimeType) { mimeType = node.entry.content.mimeType; } if (node.entry.isFolder) { mimeType = 'folder'; } - - return this.thumbnailService.getMimeTypeIcon(mimeType); + return mimeType; } isSearchBarActive() { diff --git a/lib/core/about/about.component.html b/lib/core/about/about.component.html index a120358b73..00b92447c9 100644 --- a/lib/core/about/about.component.html +++ b/lib/core/about/about.component.html @@ -63,24 +63,24 @@ <h3>{{ 'ABOUT.VERSIONS.TITLE' | translate }}</h3> <div *ngIf="bpmVersion"> <h3>{{ 'ABOUT.VERSIONS.PROCESS_SERVICE' | translate }}</h3> - <label> {{ 'ABOUT.VERSIONS.LABELS.EDITION' | translate }} </label> {{ bpmVersion.edition }} + <div> {{ 'ABOUT.VERSIONS.divS.EDITION' | translate }} </div> {{ bpmVersion.edition }} <p></p> - <label> {{ 'ABOUT.VERSIONS.LABELS.VERSION' | translate }} </label> {{ bpmVersion.majorVersion }}.{{ + <div> {{ 'ABOUT.VERSIONS.divS.VERSION' | translate }} </div> {{ bpmVersion.majorVersion }}.{{ bpmVersion.minorVersion }}.{{ bpmVersion.revisionVersion }} </div> <div *ngIf="ecmVersion"> <h3>{{ 'ABOUT.VERSIONS.CONTENT_SERVICE' | translate }}</h3> - <label>{{ 'ABOUT.VERSIONS.LABELS.EDITION' | translate }}</label> {{ ecmVersion.edition }} + <div>{{ 'ABOUT.VERSIONS.divS.EDITION' | translate }}</div> {{ ecmVersion.edition }} <p></p> - <label> {{ 'ABOUT.VERSIONS.LABELS.VERSION' | translate }} </label> {{ ecmVersion.version.display }} + <div> {{ 'ABOUT.VERSIONS.divS.VERSION' | translate }} </div> {{ ecmVersion.version.display }} <p></p> - <h4>{{ 'ABOUT.VERSIONS.LABELS.LICENSE' | translate }}</h4> + <h4>{{ 'ABOUT.VERSIONS.divS.LICENSE' | translate }}</h4> <adf-datatable [data]="license"></adf-datatable> - <h4> {{ 'ABOUT.VERSIONS.LABELS.STATUS' | translate }}</h4> + <h4> {{ 'ABOUT.VERSIONS.divS.STATUS' | translate }}</h4> <adf-datatable [data]="status"></adf-datatable> - <h4>{{ 'ABOUT.VERSIONS.LABELS.MODULES' | translate }}</h4> + <h4>{{ 'ABOUT.VERSIONS.divS.MODULES' | translate }}</h4> <adf-datatable [data]="modules"></adf-datatable> </div> diff --git a/lib/core/comments/comment-list.component.html b/lib/core/comments/comment-list.component.html index 777f880841..5128af5947 100644 --- a/lib/core/comments/comment-list.component.html +++ b/lib/core/comments/comment-list.component.html @@ -11,10 +11,9 @@ {{getUserShortName(comment.createdBy)}} </div> <div> - <img *ngIf="isPictureDefined(comment.createdBy)" + <img [alt]="comment.createdBy" *ngIf="isPictureDefined(comment.createdBy)" class="adf-people-img" - [src]="getUserImage(comment.createdBy)" - /> + [src]="getUserImage(comment.createdBy)" /> </div> </div> <div class="adf-comment-contents"> diff --git a/lib/core/form/components/widgets/people/people.widget.html b/lib/core/form/components/widgets/people/people.widget.html index 6a7f67c1a6..355fb77b60 100644 --- a/lib/core/form/components/widgets/people/people.widget.html +++ b/lib/core/form/components/widgets/people/people.widget.html @@ -22,7 +22,7 @@ <div [outerHTML]="user | usernameInitials:'adf-people-widget-pic'"></div> <div *ngIf="user.pictureId" class="adf-people-widget-image-row"> <img id="adf-people-widget-pic-{{i}}" class="adf-people-widget-image" - [src]="peopleProcessService.getUserImage(user)"/> + [alt]="getDisplayName(user)" [src]="peopleProcessService.getUserImage(user)"/> </div> <span class="adf-people-label-name">{{getDisplayName(user)}}</span> </div> diff --git a/lib/core/login/components/login.component.html b/lib/core/login/components/login.component.html index 4e9ee9bb99..1434e7ffc8 100644 --- a/lib/core/login/components/login.component.html +++ b/lib/core/login/components/login.component.html @@ -44,7 +44,7 @@ id="username" data-automation-id="username" (blur)="trimUsername($event)" - tabindex="1"> + tabindex="-1"> </mat-form-field> <span class="adf-login-validation" for="username" *ngIf="formError['username']"> @@ -60,13 +60,13 @@ [formControl]="form.controls['password']" id="password" data-automation-id="password" - tabindex="2"> + tabindex="-2"> <mat-icon *ngIf="isPasswordShow" matSuffix class="adf-login-password-icon" - data-automation-id="hide_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="3"> + data-automation-id="hide_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="-3"> visibility </mat-icon> <mat-icon *ngIf="!isPasswordShow" matSuffix class="adf-login-password-icon" - data-automation-id="show_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="3"> + data-automation-id="show_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="-3"> visibility_off </mat-icon> </mat-form-field> @@ -80,7 +80,7 @@ <ng-content></ng-content> <br> - <button type="submit" id="login-button" tabindex="4" + <button type="submit" id="login-button" tabindex="-4" class="adf-login-button" mat-raised-button color="primary" [class.adf-isChecking]="actualLoginStep === LoginSteps.Checking" @@ -115,7 +115,7 @@ </div> <div *ngIf="implicitFlow"> - <button type="button" (click)="implicitLogin()" id="login-button-sso" tabindex="1" + <button type="button" (click)="implicitLogin()" id="login-button-sso" tabindex="-1" class="adf-login-button" mat-raised-button color="primary" data-automation-id="login-button-sso"> diff --git a/lib/core/settings/host-settings.component.html b/lib/core/settings/host-settings.component.html index bb2f4114c1..06e08ee8f9 100644 --- a/lib/core/settings/host-settings.component.html +++ b/lib/core/settings/host-settings.component.html @@ -27,7 +27,7 @@ <mat-card-content> <mat-form-field class="adf-full-width" floatLabel="{{'CORE.HOST_SETTINGS.CS-HOST' | translate }}"> <mat-label>{{'CORE.HOST_SETTINGS.CS-HOST' | translate }}</mat-label> - <input matInput [formControl]="ecmHost" data-automation-id="ecmHost" type="text" tabindex="2" + <input matInput [formControl]="ecmHost" data-automation-id="ecmHost" type="text" id="ecmHost" placeholder="http(s)://host|ip:port(/path)"> <mat-error *ngIf="ecmHost.hasError('pattern')"> {{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }} @@ -44,7 +44,7 @@ <mat-card-content> <mat-form-field class="adf-full-width" floatLabel="{{'CORE.HOST_SETTINGS.BP-HOST' | translate }}"> <mat-label>{{'CORE.HOST_SETTINGS.BP-HOST' | translate }}</mat-label> - <input matInput [formControl]="bpmHost" data-automation-id="bpmHost" type="text" tabindex="2" + <input matInput [formControl]="bpmHost" data-automation-id="bpmHost" type="text" id="bpmHost" placeholder="http(s)://host|ip:port(/path)"> <mat-error *ngIf="bpmHost.hasError('pattern')"> {{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }} @@ -134,7 +134,7 @@ <button mat-button (click)="onCancel()" color="primary"> {{'CORE.HOST_SETTINGS.BACK' | translate }} </button> - <button type="submit" id="host-button" tabindex="4" class="adf-login-button" mat-raised-button + <button type="submit" id="host-button" class="adf-login-button" mat-raised-button color="primary" data-automation-id="host-button" [disabled]="!form.valid"> {{'CORE.HOST_SETTINGS.APPLY' | translate }} diff --git a/lib/core/viewer/components/pdfViewer-thumb.component.html b/lib/core/viewer/components/pdfViewer-thumb.component.html index 564a5b2008..b355eabce3 100644 --- a/lib/core/viewer/components/pdfViewer-thumb.component.html +++ b/lib/core/viewer/components/pdfViewer-thumb.component.html @@ -1,4 +1,4 @@ <ng-container *ngIf="image$ | async as image"> - <img [src]="image" + <img [src]="image" [alt]="'ADF_VIEWER.SIDEBAR.THUMBNAILS.PAGE' | translate: { pageNum: page.id }" title="{{ 'ADF_VIEWER.SIDEBAR.THUMBNAILS.PAGE' | translate: { pageNum: page.id } }}"> </ng-container> diff --git a/lib/core/viewer/components/viewer.component.html b/lib/core/viewer/components/viewer.component.html index 9a0513af79..009caaf978 100644 --- a/lib/core/viewer/components/viewer.component.html +++ b/lib/core/viewer/components/viewer.component.html @@ -40,7 +40,7 @@ (click)="onNavigateBeforeClick()"> <mat-icon>navigate_before</mat-icon> </button> - <img class="adf-viewer__mimeicon" [src]="mimeType | adfMimeTypeIcon" data-automation-id="adf-file-thumbnail"> + <img class="adf-viewer__mimeicon" [alt]="mimeType | adfMimeTypeIcon" [src]="mimeType | adfMimeTypeIcon" data-automation-id="adf-file-thumbnail"> <span class="adf-viewer__display-name" id="adf-viewer-display-name">{{ fileTitle }}</span> <button *ngIf="allowNavigate && canNavigateNext" diff --git a/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.html b/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.html index d9d4b5123f..7571ae251b 100644 --- a/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.html +++ b/lib/insights/analytics-process/components/widgets/date-range/date-range.widget.html @@ -1,5 +1,5 @@ -<label>{{field.nameKey | translate}}</label><br> -<div [formGroup]="dateRange"> +<label for="adf-dateRange" >{{field.nameKey | translate}}</label><br> +<div id="adf-dateRange" [formGroup]="dateRange"> <small *ngIf="isStartDateGreaterThanEndDate()" class="adf-date-range-analytics-text-danger"> {{'DATE-WIDGET.MESSAGES.START-LESS-THAN-END-DATE' | translate}} </small> diff --git a/lib/process-services/content-widget/attach-file-widget.component.html b/lib/process-services/content-widget/attach-file-widget.component.html index 2a42f1e16a..38f9607e00 100644 --- a/lib/process-services/content-widget/attach-file-widget.component.html +++ b/lib/process-services/content-widget/attach-file-widget.component.html @@ -40,7 +40,7 @@ (click)="openSelectDialogFromFileSource()"> {{field.params?.fileSource?.name}} <mat-icon> - <img class="adf-attach-widget__image-logo" src="../assets/images/alfresco-flower.svg"> + <img alt="alfresco" class="adf-attach-widget__image-logo" src="../assets/images/alfresco-flower.svg"> </mat-icon> </button> <div *ngIf="!isDefinedSourceFolder()"> @@ -49,7 +49,7 @@ (click)="openSelectDialog(repo)"> {{repo.name}} <mat-icon> - <img class="adf-attach-widget__image-logo" src="../assets/images/alfresco-flower.svg"> + <img alt="alfresco" class="adf-attach-widget__image-logo" src="../assets/images/alfresco-flower.svg"> </mat-icon> </button> </div> diff --git a/lib/process-services/people/components/people-search-field/people-search-field.component.html b/lib/process-services/people/components/people-search-field/people-search-field.component.html index 211e67b70d..19378a98eb 100644 --- a/lib/process-services/people/components/people-search-field/people-search-field.component.html +++ b/lib/process-services/people/components/people-search-field/people-search-field.component.html @@ -17,7 +17,7 @@ <div *ngIf="!entry.row.obj.pictureId" class="adf-people-pic"> {{getInitialUserName(entry.row.obj.firstName, entry.row.obj.lastName)}}</div> <div> - <img *ngIf="entry.row.obj.pictureId" class="adf-people-img" + <img [alt]="getDisplayUser(entry.row.obj.firstName, entry.row.obj.lastName, ' ')" *ngIf="entry.row.obj.pictureId" class="adf-people-img" [src]="peopleProcessService.getUserImage(entry.row.obj)"/> </div> </ng-template> @@ -30,4 +30,4 @@ </data-columns> </adf-people-list> </div> -</ng-container> \ No newline at end of file +</ng-container> diff --git a/lib/process-services/people/components/people/people.component.html b/lib/process-services/people/components/people/people.component.html index a25bf78859..5ce9ff6d49 100644 --- a/lib/process-services/people/components/people/people.component.html +++ b/lib/process-services/people/components/people/people.component.html @@ -33,7 +33,7 @@ <div *ngIf="!entry.row.obj.pictureId" class="adf-people-search-people-pic"> {{getInitialUserName(entry.row.obj.firstName, entry.row.obj.lastName)}}</div> <div> - <img *ngIf="entry.row.obj.pictureId" class="adf-people-img" + <img [alt]="getDisplayUser(entry.row.obj.firstName, entry.row.obj.lastName, ' ')" *ngIf="entry.row.obj.pictureId" class="adf-people-img" [src]="peopleProcessService.getUserImage(entry.row.obj)"/> </div> </ng-template> diff --git a/lib/tslint.json b/lib/tslint.json index 1bd18ddc42..ae261ecbde 100644 --- a/lib/tslint.json +++ b/lib/tslint.json @@ -2,5 +2,10 @@ "extends": "../tslint.json", "rules": { "adf-license-banner": [true, "lib/+(core|content-services|process-services|process-services-cloud|insights|extensions)/**/*.ts", "./license-community.txt"] - } + }, + "template-accessibility-alt-text": true, + "template-accessibility-label-for": true, + "template-accessibility-tabindex-no-positive": true, + "template-accessibility-table-scope": true, + "template-accessibility-valid-aria": true } diff --git a/package-lock.json b/package-lock.json index 8f2858e17e..0ad5d80389 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,61 +1,61 @@ { "name": "alfresco-components", - "version": "3.1.0-beta5", + "version": "3.2.0-beta1", "lockfileVersion": 1, "requires": true, "dependencies": { "@alfresco/adf-content-services": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.1.0-beta5.tgz", - "integrity": "sha512-XgfeNPbbSAORj/D8FUOTHHDM0AxSv8dfSyEk14Hfkz+XGjSKJI53rNBjzfNXBf/IFIBfBgaPS9tXeWcIBqJ7EA==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta1.tgz", + "integrity": "sha512-IDMvGc9gFMkBuIuvP9pM7WhpWGXTbKGl/Wy/v8ZQUQJKqI+/frDBJLCer1oct22Mw2H+pq9NzAAmHqGOiqh3cw==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-core": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.1.0-beta5.tgz", - "integrity": "sha512-gmkxDUUt4WcT7XJ5a7MUvPVmOeweHXCPcIHX6WErSA/o+bI43FRu6wV7pBLaJ35UAR3MopCxHjW0zD2MTT1ENA==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta1.tgz", + "integrity": "sha512-tWdC2ht65MTcPBn2ILqRTy9T8MbXv5hzJIxzEOqoOSLf1pbuyGBN2dI6vWPzmtbZeLTMJg6B5DMeyHykxJHYkQ==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-extensions": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.1.0-beta5.tgz", - "integrity": "sha512-AvUNFxN1knwh8T3C92NmrnDvFb8xKU0El+PqO3XkMSS+Dh7NgE7bH1yQTmrUcFeF7dDR/KMrO+EVmdGPxvkYAA==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta1.tgz", + "integrity": "sha512-hkgQ97t/jZYTv1COhjt3RVONF8HmXM9Uo7/fvDDbGoac+hc2nJbQCWKdIwysZwkglHHbBRZSj/DVwppbKuNroQ==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-insights": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.1.0-beta5.tgz", - "integrity": "sha512-zrf7eCtFU6QLqg1MK6tvBC+LrEQWAry5FflpCkwvmxCa7ulPyY0wJRExQI9QygdAA3vYRUOOlA4l8PTpjmhnKw==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta1.tgz", + "integrity": "sha512-9bXFrCCzYbD1/mB7KIwrFKqLBx5UCEZ0+V3+MIpbJRprOU5iTlvzim1uNFbvJX8TNoHi2trEADo+0uSo7F+Zog==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.1.0-beta5.tgz", - "integrity": "sha512-koK55IE6sxcqMuSZs2jhaOqJFo0l8t/MO74C+v5MkA0ORxYtoswq2V3tRFLdAQinPWORAyzdtWNseDcyWKoDAA==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta1.tgz", + "integrity": "sha512-ljFWeaUn12x5MYBIBk1fEMqtFZJWZk32ivpuxpVMjiKrL55ryxrzSnc6SNddJMpcm1l6wXdO+ljygSUr3yhcDA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services-cloud": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.1.0-beta5.tgz", - "integrity": "sha512-ZuKQK4WL/Ere+ofvYQOb/QevIoHJVXL2LA4Gyo1K3f3zIaZXgaoWKqeDv/fQvqacQybUoc1Mo9iOytjC4DCJgA==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta1.tgz", + "integrity": "sha512-yV1V4UzEgaqvbiqFo/m8/bMeiTzWHV9PodaqV9T7j1tDkrf+QFpvWIf/eXpXRtTOqdFZbt2ojcZLEd7drOgM4g==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-testing": { - "version": "3.1.0-beta5", - "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.1.0-beta5.tgz", - "integrity": "sha512-Ylzak+r3b5yjsffDtlzxFBkwR84Se4n0mKCObYIzLsTxLNuEXagx44qlDG0S2w7lfjZgDKNQ4sQaenNxqZZ2Hg==", + "version": "3.2.0-beta1", + "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta1.tgz", + "integrity": "sha512-EL9hmTsCqSNXe4EK0lIw1XUy1utL0ooNltsafr4nsAUI5sFNUbWC/UZynmBv9fLvTGIe4Fd3ubDZgnBNBUNtSw==", "requires": { "tslib": "^1.9.0" } @@ -2081,6 +2081,16 @@ "sprintf-js": "~1.0.2" } }, + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -2251,6 +2261,12 @@ "dev": true, "optional": true }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -2337,6 +2353,15 @@ "is-buffer": "^1.1.5" } }, + "axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -2824,7 +2849,6 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, - "optional": true, "requires": { "hoek": "2.x.x" } @@ -3488,8 +3512,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", - "dev": true, - "optional": true + "dev": true }, "buffer-xor": { "version": "1.0.3", @@ -4035,25 +4058,39 @@ "dev": true }, "codelyzer": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz", - "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==", + "version": "5.0.0-beta.2", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.0.0-beta.2.tgz", + "integrity": "sha512-cH5vxszkzhAg92pvuKXFuoDgKIqX3a5hIPv545pfuPc2GKDXuiWACPteny29k3/FGaw9eub1iUlyLVkPpETtsg==", "dev": true, "requires": { "app-root-path": "^2.1.0", - "css-selector-tokenizer": "^0.7.0", + "aria-query": "^3.0.0", + "axobject-query": "^2.0.2", + "css-selector-tokenizer": "^0.7.1", "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", "semver-dsl": "^1.0.1", "source-map": "^0.5.7", - "sprintf-js": "^1.1.1" + "sprintf-js": "^1.1.2" }, "dependencies": { "app-root-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", - "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", + "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==", "dev": true }, + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4939,6 +4976,12 @@ "es5-ext": "~0.10.2" } }, + "damerau-levenshtein": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -6716,8 +6759,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6738,14 +6780,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6760,20 +6800,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6890,8 +6927,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6903,7 +6939,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6918,7 +6953,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6926,14 +6960,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -6952,7 +6984,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7033,8 +7064,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7046,7 +7076,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7132,8 +7161,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7169,7 +7197,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7189,7 +7216,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7233,14 +7259,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -8007,8 +8031,7 @@ "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true, - "optional": true + "dev": true }, "homedir-polyfill": { "version": "1.0.3", @@ -8171,7 +8194,6 @@ "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, - "optional": true, "requires": { "httpreq": ">=0.4.22", "underscore": "~1.7.0" @@ -8181,8 +8203,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true, - "optional": true + "dev": true }, "https-browserify": { "version": "1.0.0", @@ -9077,8 +9098,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true, - "optional": true + "dev": true }, "is-redirect": { "version": "1.0.0", @@ -10011,15 +10031,13 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true, - "optional": true + "dev": true }, "libmime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, - "optional": true, "requires": { "iconv-lite": "0.4.15", "libbase64": "0.1.0", @@ -10030,8 +10048,7 @@ "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true, - "optional": true + "dev": true } } }, @@ -10039,8 +10056,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true, - "optional": true + "dev": true }, "license-checker": { "version": "25.0.1", @@ -12102,15 +12118,13 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true, - "optional": true + "dev": true }, "nodemailer-shared": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", "dev": true, - "optional": true, "requires": { "nodemailer-fetch": "1.6.0" } @@ -12143,8 +12157,7 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true, - "optional": true + "dev": true }, "nopt": { "version": "3.0.6", @@ -15735,7 +15748,6 @@ "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", "dev": true, - "optional": true, "requires": { "httpntlm": "1.6.1", "nodemailer-shared": "1.1.0" @@ -17793,8 +17805,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true, - "optional": true + "dev": true }, "unherit": { "version": "1.1.1", diff --git a/package.json b/package.json index 37f2f8c4a3..5c28fa5dca 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "ajv-cli": "^3.0.0", "bundlesize": "^0.15.3", "chalk": "^2.3.2", - "codelyzer": "^4.5.0", + "codelyzer": "5.0.0-beta.2", "commander": "^2.15.1", "concurrently": "^3.5.1", "cspell": "^3.1.3", diff --git a/tslint.json b/tslint.json index 87615cb6ca..b1affcc921 100644 --- a/tslint.json +++ b/tslint.json @@ -159,7 +159,10 @@ ], "directive-selector": [ true, - ["element", "attribute"], + [ + "element", + "attribute" + ], "adf", "kebab-case" ], @@ -172,11 +175,11 @@ "arrow-parens": true, "no-input-prefix": true, "ordered-imports": false, - "template-conditional-complexity": [true, 2], - "banana-in-box": true, + "template-conditional-complexity": [ + true, + 2 + ], "contextual-life-cycle": true, - "use-input-property-decorator": true, - "use-output-property-decorator": true, "use-host-property-decorator": false, "use-life-cycle-interface": true, "use-pipe-transform-interface": true, From 4376d357ac20646c888821e4db2f7d6b07bb4593 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Wed, 27 Mar 2019 09:36:58 +0000 Subject: [PATCH 011/208] [ADF-3962] sso download directive automated (#4452) * sso download directive automated * temp changes * temp changes * moving of services under lib testing and ADF-3962 automated * removed the browser sleep * cspell and linting fixes. * codacy improvements * export public-api update * remove circular dep * remove circular dep * fixes * fix user info test * fix datatable * random commit * move other string * fix lint * fix lint * fix prolem type * fix failing test * fix tag test * fix problems after rebase * fix lint * remove space * remove visibility method duplicated --- cspell.json | 3 +- .../comments/comment-component.e2e.ts | 4 +- .../create-library-directive.e2e.ts | 34 +- .../document-list-actions.e2e.ts | 8 +- .../document-list-component.e2e.ts | 18 +- e2e/content-services/lock-file.e2e.ts | 4 +- .../permissions/permissions-component.e2e.ts | 62 +--- .../permissions/site-permissions.e2e.ts | 8 +- .../share-file/unshare-file.e2e.ts | 8 +- .../sso-download-directive-component.e2e.ts | 166 ++++++++++ e2e/content-services/tag-component.e2e.ts | 22 +- .../upload/uploader-component.e2e.ts | 4 +- .../upload/user-permission.e2e.ts | 6 +- .../version/version-actions.e2e.ts | 5 +- .../version/version-permissions.e2e.ts | 4 +- .../version/version-properties.e2e.ts | 18 +- .../version/version-smoke-tests.e2e.ts | 28 +- e2e/core/card-view/card-view-component.e2e.ts | 28 +- .../card-view/metadata-permissions.e2e.ts | 4 +- e2e/core/error-component.e2e.ts | 2 +- e2e/core/login/login-component.e2e.ts | 2 +- e2e/core/login/redirection.e2e.ts | 4 +- e2e/core/user-info-component-cloud.e2e.ts | 17 +- e2e/core/user-info-component.e2e.ts | 14 +- e2e/core/viewer/viewer-component.e2e.ts | 4 +- e2e/models/ACS/acsUserModel.ts | 13 +- e2e/models/ACS/createdByModel.ts | 6 +- e2e/models/ACS/fileModel.ts | 6 +- e2e/models/ACS/folderModel.ts | 6 +- e2e/models/APS/standaloneTask.ts | 4 +- e2e/models/APS/tenant.ts | 4 +- e2e/models/APS/user.ts | 10 +- e2e/pages/adf/cardViewComponentPage.ts | 62 ++-- e2e/pages/adf/commentsPage.ts | 18 +- e2e/pages/adf/configEditorPage.ts | 42 +-- .../adf/content-services/documentListPage.ts | 18 +- .../search/components/dateRangeFilterPage.ts | 30 +- .../components/numberRangeFilterPage.ts | 42 +-- .../search/components/search-checkList.ts | 60 ++-- .../search/components/search-radio.ts | 18 +- .../search/components/search-slider.page.ts | 10 +- .../components/search-sortingPicker.page.ts | 24 +- .../search/components/search-text.ts | 6 +- .../search/search-categories.ts | 8 +- .../adf/content-services/treeViewPage.ts | 24 +- e2e/pages/adf/contentServicesPage.ts | 145 +++++---- e2e/pages/adf/core/headerPage.ts | 42 +-- e2e/pages/adf/core/infinitePaginationPage.ts | 10 +- e2e/pages/adf/dataTableComponentPage.ts | 78 ++--- e2e/pages/adf/demo-shell/aboutPage.ts | 4 +- e2e/pages/adf/demo-shell/customSourcesPage.ts | 6 +- e2e/pages/adf/demo-shell/dataTablePage.ts | 46 +-- e2e/pages/adf/demo-shell/logoutPage.ts | 4 +- .../peopleGroupCloudComponentPage.ts | 20 +- .../process-services/processCloudDemoPage.ts | 13 +- .../process-services/processListDemoPage.ts | 30 +- .../process-services/taskFiltersDemoPage.ts | 4 +- .../process-services/taskListDemoPage.ts | 64 ++-- .../process-services/tasksCloudDemoPage.ts | 29 +- e2e/pages/adf/dialog/createFolderDialog.ts | 12 +- e2e/pages/adf/dialog/createLibraryDialog.ts | 18 +- .../adf/dialog/editProcessFilterDialog.ts | 20 +- e2e/pages/adf/dialog/editTaskFilterDialog.ts | 20 +- e2e/pages/adf/dialog/searchDialog.ts | 26 +- e2e/pages/adf/dialog/shareDialog.ts | 48 +-- e2e/pages/adf/dialog/uploadDialog.ts | 42 +-- e2e/pages/adf/dialog/uploadToggles.ts | 16 +- e2e/pages/adf/errorPage.ts | 14 +- e2e/pages/adf/filePreviewPage.ts | 66 ++-- e2e/pages/adf/lockFilePage.ts | 16 +- e2e/pages/adf/loginPage.ts | 66 ++-- e2e/pages/adf/material/datePickerPage.ts | 8 +- e2e/pages/adf/material/formControllersPage.ts | 10 +- e2e/pages/adf/metadataViewPage.ts | 84 ++--- e2e/pages/adf/navigationBarPage.ts | 78 ++--- e2e/pages/adf/notificationPage.ts | 32 +- e2e/pages/adf/paginationPage.ts | 60 ++-- e2e/pages/adf/permissionsPage.ts | 50 +-- .../editProcessFilterCloudComponent.ts | 66 ++-- .../editTaskFilterCloudComponent.ts | 54 ++-- .../adf/process-cloud/groupCloudComponent.ts | 14 +- .../adf/process-cloud/peopleCloudComponent.ts | 18 +- .../processFiltersCloudComponent.ts | 18 +- .../processListCloudComponent.ts | 6 +- .../taskFiltersCloudComponent.ts | 16 +- .../process-cloud/taskListCloudComponent.ts | 10 +- .../adf/process-services/analyticsPage.ts | 18 +- .../process-services/appNavigationBarPage.ts | 8 +- .../adf/process-services/attachFormPage.ts | 22 +- .../process-services/attachmentListPage.ts | 36 +-- .../dialog/appSettingsToggles.ts | 10 - .../dialog/createChecklistDialog.ts | 20 +- .../dialog/startTaskDialog.ts | 36 +-- e2e/pages/adf/process-services/filtersPage.ts | 6 +- e2e/pages/adf/process-services/formFields.ts | 50 +-- e2e/pages/adf/process-services/formPage.ts | 14 +- .../process-services/processDetailsPage.ts | 80 ++--- .../process-services/processFiltersPage.ts | 46 +-- .../adf/process-services/processListPage.ts | 6 +- .../process-services/processServicesPage.ts | 22 +- .../adf/process-services/startProcessPage.ts | 46 +-- .../adf/process-services/taskDetailsPage.ts | 158 +++++----- .../adf/process-services/taskFiltersPage.ts | 16 +- .../adf/process-services/tasksListPage.ts | 6 +- e2e/pages/adf/process-services/tasksPage.ts | 38 +-- .../process-services/widgets/amountWidget.ts | 10 +- .../widgets/attachFileWidget.ts | 10 +- .../widgets/checkboxWidget.ts | 7 +- .../widgets/dateTimeWidget.ts | 22 +- .../process-services/widgets/dateWidget.ts | 12 +- .../widgets/dropdownWidget.ts | 6 +- .../widgets/dynamicTableWidget.ts | 40 +-- .../widgets/hyperlinkWidget.ts | 4 +- .../process-services/widgets/numberWidget.ts | 8 +- .../process-services/widgets/peopleWidget.ts | 16 +- .../widgets/radioButtonsWidget.ts | 10 +- .../editTaskFilterCloudComponent.ts | 36 +-- e2e/pages/adf/searchFiltersPage.ts | 10 +- e2e/pages/adf/searchResultsPage.ts | 10 +- e2e/pages/adf/settingsPage.ts | 74 ++--- e2e/pages/adf/tagPage.ts | 61 ++-- e2e/pages/adf/trashcanPage.ts | 6 +- e2e/pages/adf/versionManagerPage.ts | 58 ++-- e2e/pages/adf/viewerPage.ts | 181 ++++++----- .../edit-task-filters-component.e2e.ts | 14 +- .../people-group-cloud-component.e2e.ts | 29 +- .../process-custom-filters.e2e.ts | 37 ++- .../process-filters-cloud.e2e.ts | 25 +- .../process-header-cloud.e2e.ts | 30 +- .../processList-cloud-component.e2e.ts | 21 +- .../processListCloud.config.ts | 3 - .../start-process-cloud.e2e.ts | 8 +- .../start-task-custom-app-cloud.e2e.ts | 10 +- .../task-filters-cloud.e2e.ts | 21 +- .../task-header-cloud.e2e.ts | 18 +- .../task-list-properties.e2e.ts | 32 +- .../task-list-selection.e2e.ts | 15 +- .../tasks-custom-filters.e2e.ts | 31 +- .../start-process-component.e2e.ts | 5 +- .../start-task-task-app.e2e.ts | 6 +- e2e/process-services/task-details-form.e2e.ts | 8 +- e2e/restAPI/httpRequest/HTTPRequestPublic.js | 2 +- e2e/search/components/search-checkList.e2e.ts | 4 +- e2e/search/components/search-radio.e2e.ts | 4 +- e2e/search/search-component.e2e.ts | 13 +- e2e/search/search-filters.e2e.ts | 12 +- e2e/search/search-multiselect.e2e.ts | 14 +- e2e/search/search-page-component.e2e.ts | 12 +- e2e/test.config.js | 1 + e2e/util/material.ts | 6 +- e2e/util/util.ts | 290 +----------------- .../actions/example.action.ts | 2 +- .../content-services/actions/public-api.ts | 17 +- .../content-services/pages/example.page.ts | 2 +- .../lib/content-services/pages/public-api.ts | 17 +- .../src/lib/content-services/public-api.ts | 17 +- .../src/lib/core/actions/api.service.ts | 52 ++-- .../identity/group-identity.service.ts | 14 +- .../core/actions/identity/identity.service.ts | 52 +++- .../lib/core/actions/identity/public-api.ts | 22 ++ .../core/actions/identity/query.service.ts | 13 +- .../core/actions/identity/roles.service.ts | 12 +- .../core/actions/identity/tasks.service.ts | 13 +- .../src/lib/core/actions/public-api.ts | 20 +- .../src/lib/core/browser-visibility.ts | 32 +- lib/testing/src/lib/core/models/public-api.ts | 18 ++ lib/testing/src/lib/core/models/user.model.ts | 36 +++ lib/testing/src/lib/core/pages/header.page.ts | 2 +- lib/testing/src/lib/core/pages/public-api.ts | 17 +- lib/testing/src/lib/core/public-api.ts | 20 +- lib/testing/src/lib/core/string.util.ts | 106 +++++++ lib/testing/src/lib/material/public-api.ts | 18 ++ .../actions/process-definitions.service.ts | 13 +- .../actions/process-instances.service.ts | 27 +- .../actions/public-api.ts | 19 +- .../process-services-cloud/app/public-api.ts | 19 +- .../pages/login-sso.page.ts | 1 + .../pages/public-api.ts | 17 +- .../lib/process-services-cloud/public-api.ts | 17 +- .../pages/form-fields.page.ts | 2 +- .../lib/process-services/pages/public-api.ts | 17 +- .../src/lib/process-services/public-api.ts | 17 +- lib/testing/src/lib/testing.module.ts | 17 + lib/testing/src/lib/testing.service.spec.ts | 17 + lib/testing/src/lib/testing.service.ts | 17 + lib/testing/src/public-api.ts | 18 +- lib/testing/src/test.ts | 17 +- lib/tslint.json | 2 +- package-lock.json | 59 ++++ package.json | 1 + tslint.json | 3 +- 191 files changed, 2664 insertions(+), 2299 deletions(-) create mode 100644 e2e/content-services/sso/sso-download-directive-component.e2e.ts rename e2e/actions/APS-cloud/apiservice.ts => lib/testing/src/lib/core/actions/api.service.ts (66%) rename e2e/actions/APS-cloud/groupIdentity.ts => lib/testing/src/lib/core/actions/identity/group-identity.service.ts (86%) rename e2e/actions/APS-cloud/identity.ts => lib/testing/src/lib/core/actions/identity/identity.service.ts (62%) create mode 100644 lib/testing/src/lib/core/actions/identity/public-api.ts rename e2e/actions/APS-cloud/query.ts => lib/testing/src/lib/core/actions/identity/query.service.ts (86%) rename e2e/actions/APS-cloud/roles.ts => lib/testing/src/lib/core/actions/identity/roles.service.ts (81%) rename e2e/actions/APS-cloud/tasks.ts => lib/testing/src/lib/core/actions/identity/tasks.service.ts (93%) create mode 100644 lib/testing/src/lib/core/models/public-api.ts create mode 100644 lib/testing/src/lib/core/models/user.model.ts create mode 100644 lib/testing/src/lib/core/string.util.ts create mode 100644 lib/testing/src/lib/material/public-api.ts rename e2e/actions/APS-cloud/process-definitions.ts => lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts (79%) rename e2e/actions/APS-cloud/process-instances.ts => lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts (71%) diff --git a/cspell.json b/cspell.json index 3812092713..dcde13fef3 100644 --- a/cspell.json +++ b/cspell.json @@ -124,7 +124,8 @@ "hardend", "filedata", "uncheck", - "subfolders" + "subfolders", + "ECMBPM" ], "dictionaries": [ "html", diff --git a/e2e/content-services/comments/comment-component.e2e.ts b/e2e/content-services/comments/comment-component.e2e.ts index 6c68e9e274..3e4983be0a 100644 --- a/e2e/content-services/comments/comment-component.e2e.ts +++ b/e2e/content-services/comments/comment-component.e2e.ts @@ -27,7 +27,7 @@ import { FileModel } from '../../models/ACS/fileModel'; import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); import CONSTANTS = require('../../util/constants'); -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; @@ -183,7 +183,7 @@ describe('Comment Component', () => { await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(8), + title: StringUtil.generateRandomString(8), visibility: 'PUBLIC' }); diff --git a/e2e/content-services/directives/create-library-directive.e2e.ts b/e2e/content-services/directives/create-library-directive.e2e.ts index c97abf56e3..e93d2835c9 100644 --- a/e2e/content-services/directives/create-library-directive.e2e.ts +++ b/e2e/content-services/directives/create-library-directive.e2e.ts @@ -24,7 +24,7 @@ import { AcsUserModel } from '../../models/ACS/acsUserModel'; import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { browser, Key } from 'protractor'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; describe('Create library directive', function () { @@ -56,14 +56,14 @@ describe('Create library directive', function () { loginPage.loginToContentServicesUsingUserModel(acsUser); createSite = await this.alfrescoJsApi.core.sitesApi.createSite({ - 'title': Util.generateRandomString(20).toLowerCase(), + 'title': StringUtil.generateRandomString(20).toLowerCase(), 'visibility': 'PUBLIC' }); done(); }); - beforeEach( (done) => { + beforeEach((done) => { contentServicesPage.goToDocumentList(); contentServicesPage.openCreateLibraryDialog(); done(); @@ -98,8 +98,8 @@ describe('Create library directive', function () { }); it('[C290160] Should create a public library', () => { - const libraryName = Util.generateRandomString(); - const libraryDescription = Util.generateRandomString(); + const libraryName = StringUtil.generateRandomString(); + const libraryDescription = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(libraryName); createLibraryDialog.typeLibraryDescription(libraryDescription); createLibraryDialog.selectPublic(); @@ -119,8 +119,8 @@ describe('Create library directive', function () { }); it('[C290173] Should create a private library', () => { - const libraryName = Util.generateRandomString(); - const libraryDescription = Util.generateRandomString(); + const libraryName = StringUtil.generateRandomString(); + const libraryDescription = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(libraryName); createLibraryDialog.typeLibraryDescription(libraryDescription); createLibraryDialog.selectPrivate(); @@ -140,9 +140,9 @@ describe('Create library directive', function () { }); it('[C290174, C290175] Should create a moderated library with a given Library ID', () => { - const libraryName = Util.generateRandomString(); - const libraryId = Util.generateRandomString(); - const libraryDescription = Util.generateRandomString(); + const libraryName = StringUtil.generateRandomString(); + const libraryId = StringUtil.generateRandomString(); + const libraryDescription = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(libraryName); createLibraryDialog.typeLibraryId(libraryId); createLibraryDialog.typeLibraryDescription(libraryDescription); @@ -163,7 +163,7 @@ describe('Create library directive', function () { }); it('[C290163] Should disable Create button when a mandatory field is not filled in', () => { - const inputValue = Util.generateRandomString(); + const inputValue = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(inputValue); createLibraryDialog.clearLibraryId(); @@ -214,7 +214,7 @@ describe('Create library directive', function () { it('[C291793] Should display error for Name field filled in with spaces only', () => { const name = ' '; - const libraryId = Util.generateRandomString(); + const libraryId = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); @@ -225,7 +225,7 @@ describe('Create library directive', function () { it('[C290177] Should not accept a duplicate Library Id', () => { const name = 'My Library'; - const libraryId = Util.generateRandomString(); + const libraryId = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); @@ -242,7 +242,7 @@ describe('Create library directive', function () { it('[C290178] Should accept the same library name but different Library Ids', () => { const name = createSite.entry.title; - const libraryId = Util.generateRandomString(); + const libraryId = StringUtil.generateRandomString(); createLibraryDialog.typeLibraryName(name.toUpperCase()); createLibraryDialog.typeLibraryId(libraryId); @@ -257,9 +257,9 @@ describe('Create library directive', function () { }); it('[C290179] Should not accept more than the expected characters for input fields', () => { - const name = Util.generateRandomString(257); - const libraryId = Util.generateRandomString(73); - const libraryDescription = Util.generateRandomString(513); + const name = StringUtil.generateRandomString(257); + const libraryId = StringUtil.generateRandomString(73); + const libraryDescription = StringUtil.generateRandomString(513); createLibraryDialog.typeLibraryName(name); createLibraryDialog.typeLibraryId(libraryId); diff --git a/e2e/content-services/document-list/document-list-actions.e2e.ts b/e2e/content-services/document-list/document-list-actions.e2e.ts index c1f3e98284..f14b564c43 100644 --- a/e2e/content-services/document-list/document-list-actions.e2e.ts +++ b/e2e/content-services/document-list/document-list-actions.e2e.ts @@ -24,7 +24,7 @@ import resources = require('../../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { FileModel } from '../../models/ACS/fileModel'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; describe('Document List Component - Actions', () => { @@ -59,7 +59,7 @@ describe('Document List Component - Actions', () => { beforeEach(async (done) => { acsUser = new AcsUserModel(); - folderName = `TATSUMAKY_${Util.generateRandomString(5)}_SENPOUKYAKU`; + folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); @@ -147,8 +147,8 @@ describe('Document List Component - Actions', () => { beforeEach(async (done) => { acsUser = new AcsUserModel(); - folderName = `TATSUMAKY_${Util.generateRandomString(5)}_SENPOUKYAKU`; - secondFolderName = `TATSUMAKY_${Util.generateRandomString(5)}_SENPOUKYAKU`; + folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; + secondFolderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); diff --git a/e2e/content-services/document-list/document-list-component.e2e.ts b/e2e/content-services/document-list/document-list-component.e2e.ts index 15ceebb10b..f648f41114 100644 --- a/e2e/content-services/document-list/document-list-component.e2e.ts +++ b/e2e/content-services/document-list/document-list-component.e2e.ts @@ -23,7 +23,7 @@ import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { ViewerPage } from '../../pages/adf/viewerPage'; import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { ErrorPage } from '../../pages/adf/errorPage'; @@ -74,8 +74,8 @@ describe('Document List Component', () => { beforeAll(async (done) => { acsUser = new AcsUserModel(); - const siteName = `PRIVATE_TEST_SITE_${Util.generateRandomString(5)}`; - const folderName = `MEESEEKS_${Util.generateRandomString(5)}`; + const siteName = `PRIVATE_TEST_SITE_${StringUtil.generateRandomString(5)}`; + const folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}`; const privateSiteBody = { visibility: 'PRIVATE', title: siteName }; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -149,7 +149,7 @@ describe('Document List Component', () => { acsUser = new AcsUserModel(); /* cspell:disable-next-line */ - folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}_LOOK_AT_ME`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -331,7 +331,7 @@ describe('Document List Component', () => { }); acsUser = new AcsUserModel(); /* cspell:disable-next-line */ - const folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}_LOOK_AT_ME`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); @@ -362,8 +362,8 @@ describe('Document List Component', () => { it('[C279970] Should display Islocked field for folders', async (done) => { acsUser = new AcsUserModel(); - const folderNameA = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; - const folderNameB = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderNameA = `MEESEEKS_${StringUtil.generateRandomString(5)}_LOOK_AT_ME`; + const folderNameB = `MEESEEKS_${StringUtil.generateRandomString(5)}_LOOK_AT_ME`; await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); await this.alfrescoJsApi.login(acsUser.id, acsUser.password); @@ -455,7 +455,7 @@ describe('Document List Component', () => { 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - const folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}_LOOK_AT_ME`; let filePdfNode, fileTestNode, fileDocxNode, folderNode; beforeAll(async (done) => { @@ -562,7 +562,7 @@ describe('Document List Component', () => { 'name': resources.Files.ADF_DOCUMENTS.DOCX.file_name, 'location': resources.Files.ADF_DOCUMENTS.DOCX.file_location }); - const folderName = `MEESEEKS_${Util.generateRandomString(5)}_LOOK_AT_ME`; + const folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}_LOOK_AT_ME`; let filePdfNode, fileTestNode, fileDocxNode, folderNode, filePDFSubNode; beforeAll(async (done) => { diff --git a/e2e/content-services/lock-file.e2e.ts b/e2e/content-services/lock-file.e2e.ts index 4e317f8768..1739c05a48 100644 --- a/e2e/content-services/lock-file.e2e.ts +++ b/e2e/content-services/lock-file.e2e.ts @@ -25,7 +25,7 @@ import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FileModel } from '../models/ACS/fileModel'; import CONSTANTS = require('../util/constants'); -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import resources = require('../util/resources'); @@ -70,7 +70,7 @@ describe('Lock File', () => { await this.alfrescoJsApi.login(adminUser.id, adminUser.password); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(), + title: StringUtil.generateRandomString(), visibility: 'PRIVATE' }); diff --git a/e2e/content-services/permissions/permissions-component.e2e.ts b/e2e/content-services/permissions/permissions-component.e2e.ts index 3a4d6cb312..1d76745ef0 100644 --- a/e2e/content-services/permissions/permissions-component.e2e.ts +++ b/e2e/content-services/permissions/permissions-component.e2e.ts @@ -16,117 +16,71 @@ */ import { PermissionsPage } from '../../pages/adf/permissionsPage'; - import { LoginPage } from '../../pages/adf/loginPage'; - import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; - import { AcsUserModel } from '../../models/ACS/acsUserModel'; - import TestConfig = require('../../test.config'); - import resources = require('../../util/resources'); - import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; - import { FileModel } from '../../models/ACS/fileModel'; - import { UploadActions } from '../../actions/ACS/upload.actions'; - -import { Util } from '../../util/util'; - +import { StringUtil } from '@alfresco/adf-testing'; import { browser, protractor } from 'protractor'; - import { FolderModel } from '../../models/ACS/folderModel'; - import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; - import { ViewerPage } from '../../pages/adf/viewerPage'; - import { NotificationPage } from '../../pages/adf/notificationPage'; - import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; - import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; describe('Permissions Component', function () { const loginPage = new LoginPage(); - const contentServicesPage = new ContentServicesPage(); - const permissionsPage = new PermissionsPage(); - const uploadActions = new UploadActions(); const contentList = contentServicesPage.getDocumentList(); const searchDialog = new SearchDialog(); - const viewerPage = new ViewerPage(); - const metadataViewPage = new MetadataViewPage(); - const notificationPage = new NotificationPage(); - const uploadDialog = new UploadDialog(); - let fileOwnerUser, filePermissionUser, file; - const fileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, - 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location - }); const testFileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, - 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location - }); const pngFileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, - 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location - }); const groupBody = { - - id: Util.generateRandomString(), - - displayName: Util.generateRandomString() - + id: StringUtil.generateRandomString(), + displayName: StringUtil.generateRandomString() }; const alfrescoJsApi = new AlfrescoApi({ - provider: 'ECM', - hostEcm: TestConfig.adf.url - }); - const roleConsumerFolderModel = new FolderModel({'name': 'roleConsumer' + Util.generateRandomString()}); - - const roleCoordinatorFolderModel = new FolderModel({'name': 'roleCoordinator' + Util.generateRandomString()}); - - const roleCollaboratorFolderModel = new FolderModel({'name': 'roleCollaborator' + Util.generateRandomString()}); - - const roleContributorFolderModel = new FolderModel({'name': 'roleContributor' + Util.generateRandomString()}); - - const roleEditorFolderModel = new FolderModel({'name': 'roleEditor' + Util.generateRandomString()}); + const roleConsumerFolderModel = new FolderModel({ 'name': 'roleConsumer' + StringUtil.generateRandomString() }); + const roleCoordinatorFolderModel = new FolderModel({ 'name': 'roleCoordinator' + StringUtil.generateRandomString() }); + const roleCollaboratorFolderModel = new FolderModel({ 'name': 'roleCollaborator' + StringUtil.generateRandomString() }); + const roleContributorFolderModel = new FolderModel({ 'name': 'roleContributor' + StringUtil.generateRandomString() }); + const roleEditorFolderModel = new FolderModel({ 'name': 'roleEditor' + StringUtil.generateRandomString() }); let roleConsumerFolder, roleCoordinatorFolder, roleContributorFolder, roleCollaboratorFolder, roleEditorFolder; - let folders; - fileOwnerUser = new AcsUserModel(); filePermissionUser = new AcsUserModel(); diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index 28018959a2..105c674833 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -33,7 +33,7 @@ import { FileModel } from '../../models/ACS/fileModel'; import { UploadActions } from '../../actions/ACS/upload.actions'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { browser, protractor } from 'protractor'; @@ -143,11 +143,11 @@ describe('Permissions Component', function () { await alfrescoJsApi.login(folderOwnerUser.id, folderOwnerUser.password); - const publicSiteName = `PUBLIC_TEST_SITE_${Util.generateRandomString(5)}`; + const publicSiteName = `PUBLIC_TEST_SITE_${StringUtil.generateRandomString(5)}`; - const privateSiteName = `PRIVATE_TEST_SITE_${Util.generateRandomString(5)}`; + const privateSiteName = `PRIVATE_TEST_SITE_${StringUtil.generateRandomString(5)}`; - folderName = `MEESEEKS_${Util.generateRandomString(5)}`; + folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}`; const publicSiteBody = {visibility: 'PUBLIC', title: publicSiteName}; diff --git a/e2e/content-services/share-file/unshare-file.e2e.ts b/e2e/content-services/share-file/unshare-file.e2e.ts index d9b8d96b7f..b4ca80e061 100644 --- a/e2e/content-services/share-file/unshare-file.e2e.ts +++ b/e2e/content-services/share-file/unshare-file.e2e.ts @@ -16,7 +16,7 @@ */ import CONSTANTS = require('../../util/constants'); -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { LoginPage } from '../../pages/adf/loginPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; @@ -38,7 +38,7 @@ describe('Unshare file', () => { const navBar = new NavigationBarPage(); const errorPage = new ErrorPage(); const shareDialog = new ShareDialog(); - const siteName = `PRIVATE-TEST-SITE-${Util.generateRandomString(5)}`; + const siteName = `PRIVATE-TEST-SITE-${StringUtil.generateRandomString(5)}`; const acsUser = new AcsUserModel(); const uploadActions = new UploadActions(); @@ -63,10 +63,10 @@ describe('Unshare file', () => { }; nodeBody = { - name: Util.generateRandomString(5), + name: StringUtil.generateRandomString(5), nodeType: 'cm:content', properties: { - 'cm:title': Util.generateRandomString(5) + 'cm:title': StringUtil.generateRandomString(5) } }; diff --git a/e2e/content-services/sso/sso-download-directive-component.e2e.ts b/e2e/content-services/sso/sso-download-directive-component.e2e.ts new file mode 100644 index 0000000000..6bc59d5037 --- /dev/null +++ b/e2e/content-services/sso/sso-download-directive-component.e2e.ts @@ -0,0 +1,166 @@ +/*! + * @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 { SettingsPage } from '../../pages/adf/settingsPage'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import TestConfig = require('../../test.config'); +import { browser } from 'protractor'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { ApiService, LoginSSOPage } from '@alfresco/adf-testing'; +import { UploadActions } from '../../actions/ACS/upload.actions'; +import { FileModel } from '../../models/ACS/fileModel'; +import { ViewerPage } from '../../pages/adf/viewerPage'; +import resources = require('../../util/resources'); +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import * as path from 'path'; +import { Util } from '../../util/util'; +import { IdentityService } from '@alfresco/adf-testing'; +import { StringUtil, UserModel } from '@alfresco/adf-testing'; + +describe('SSO in ADF using ACS and AIS, Download Directive, Viewer, DocumentList, implicitFlow true', () => { + + const settingsPage = new SettingsPage(); + const navigationBarPage = new NavigationBarPage(); + const contentServicesPage = new ContentServicesPage(); + const contentListPage = contentServicesPage.getDocumentList(); + const loginSsoPage = new LoginSSOPage(); + const viewerPage = new ViewerPage(); + let silentLogin; + let implicitFlow; + const uploadActions = new UploadActions(); + const firstPdfFileModel = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PDF_B.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PDF_B.file_location + }); + + const pngFileModel = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + let pdfUploadedFile, pngUploadedFile, folder; + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + const downloadedPngFile = path.join(__dirname, 'downloads', pngFileModel.name); + const downloadedMultipleFiles = path.join(__dirname, 'downloads', 'archive.zip'); + const folderName = StringUtil.generateRandomString(5); + const acsUser = new UserModel(); + let identityService: IdentityService; + + describe('SSO in ADF using ACS and AIS, implicit flow set', () => { + + beforeAll(async (done) => { + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + const apiService = new ApiService('alfresco', TestConfig.adf.url, TestConfig.adf.hostSso, 'ECM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + identityService = new IdentityService(apiService); + + await identityService.createIdentityUserAndSyncECMBPM(acsUser); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + folder = await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); + + pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, folder.entry.id); + + pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, folder.entry.id); + + silentLogin = false; + implicitFlow = true; + settingsPage.setProviderEcmSso(TestConfig.adf.url, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin, implicitFlow, 'alfresco'); + loginSsoPage.clickOnSSOButton(); + loginSsoPage.loginSSOIdentityService(acsUser.id, acsUser.password); + + navigationBarPage.clickContentServicesButton(); + contentServicesPage.checkAcsContainer(); + contentListPage.doubleClickRow(folderName); + contentListPage.waitForTableBody(); + done(); + }); + + afterAll(async (done) => { + try { + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, folder.entry.id); + await identityService.deleteIdentityUser(acsUser.id); + } catch (error) { + } + await this.alfrescoJsApi.logout(); + browser.executeScript('window.sessionStorage.clear();'); + browser.executeScript('window.localStorage.clear();'); + done(); + }); + + afterEach(async (done) => { + browser.refresh(); + contentListPage.waitForTableBody(); + done(); + }); + + it('[C291936] Should be able to download a file', async (done) => { + contentListPage.selectRow(pngFileModel.name); + contentServicesPage.clickDownloadButton(); + expect(Util.fileExists(downloadedPngFile, 30)).toBe(true); + done(); + }); + + it('[C291938] Should be able to open a document', async (done) => { + contentServicesPage.doubleClickRow(firstPdfFileModel.name); + viewerPage.checkFileIsLoaded(); + viewerPage.checkFileNameIsDisplayed(firstPdfFileModel.name); + viewerPage.clickCloseButton(); + contentListPage.waitForTableBody(); + done(); + }); + + it('[C291942] Should be able to open an image', async (done) => { + viewerPage.viewFile(pngFileModel.name); + viewerPage.checkImgViewerIsDisplayed(); + viewerPage.checkFileNameIsDisplayed(pngFileModel.name); + viewerPage.clickCloseButton(); + contentListPage.waitForTableBody(); + done(); + }); + + it('[C291941] Should be able to download multiple files', async (done) => { + contentServicesPage.clickMultiSelectToggle(); + contentServicesPage.checkAcsContainer(); + contentListPage.dataTablePage().checkAllRows(); + contentListPage.dataTablePage().checkRowIsChecked('Display name', pngFileModel.name); + contentListPage.dataTablePage().checkRowIsChecked('Display name', firstPdfFileModel.name); + contentServicesPage.clickDownloadButton(); + expect(Util.fileExists(downloadedMultipleFiles, 30)).toBe(true); + done(); + }); + + it('[C291940] Should be able to view thumbnails when enabled', async (done) => { + contentServicesPage.enableThumbnails(); + contentServicesPage.checkAcsContainer(); + contentListPage.waitForTableBody(); + const filePdfIconUrl = await contentServicesPage.getRowIconImageUrl(firstPdfFileModel.name); + expect(filePdfIconUrl).toContain(`/versions/1/nodes/${pdfUploadedFile.entry.id}/renditions`); + const filePngIconUrl = await contentServicesPage.getRowIconImageUrl(pngFileModel.name); + expect(filePngIconUrl).toContain(`/versions/1/nodes/${pngUploadedFile.entry.id}/renditions`); + done(); + }); + }); +}); diff --git a/e2e/content-services/tag-component.e2e.ts b/e2e/content-services/tag-component.e2e.ts index 20f79b4611..42fb4cdadd 100644 --- a/e2e/content-services/tag-component.e2e.ts +++ b/e2e/content-services/tag-component.e2e.ts @@ -28,7 +28,7 @@ import resources = require('../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Tag component', () => { @@ -40,14 +40,14 @@ describe('Tag component', () => { const acsUser = new AcsUserModel(); const uploadActions = new UploadActions(); const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name }); - const deleteFile = new FileModel({ 'name': Util.generateRandomString() }); - const sameTag = Util.generateRandomStringToLowerCase(); + const deleteFile = new FileModel({ 'name': StringUtil.generateRandomString() }); + const sameTag = StringUtil.generateRandomString().toLowerCase(); const tagList = [ - Util.generateRandomStringToLowerCase(), - Util.generateRandomStringToLowerCase(), - Util.generateRandomStringToLowerCase(), - Util.generateRandomStringToLowerCase()]; + StringUtil.generateRandomString().toLowerCase(), + StringUtil.generateRandomString().toLowerCase(), + StringUtil.generateRandomString().toLowerCase(), + StringUtil.generateRandomString().toLowerCase()]; const tags = [ { tag: 'test-tag-01' }, { tag: 'test-tag-02' }, { tag: 'test-tag-03' }, { tag: 'test-tag-04' }, { tag: 'test-tag-05' }, @@ -57,9 +57,9 @@ describe('Tag component', () => { { tag: 'test-tag-21' }, { tag: 'test-tag-22' }, { tag: 'test-tag-23' }, { tag: 'test-tag-24' }, { tag: 'test-tag-25' }, { tag: 'test-tag-26' }, { tag: 'test-tag-27' }, { tag: 'test-tag-28' }, { tag: 'test-tag-29' }, { tag: 'test-tag-30' }]; - const uppercaseTag = Util.generateRandomStringToUpperCase(); - const digitsTag = Util.generateRandomStringDigits(); - const nonLatinTag = Util.generateRandomStringNonLatin(); + const uppercaseTag = StringUtil.generateRandomString().toUpperCase(); + const digitsTag = StringUtil.generateRandomStringDigits(); + const nonLatinTag = StringUtil.generateRandomStringNonLatin(); let pdfUploadedFile, nodeId; beforeAll(async (done) => { @@ -160,7 +160,7 @@ describe('Tag component', () => { }); it('[C260375] Should be possible to delete a tag', () => { - const deleteTag = Util.generateRandomStringToUpperCase(); + const deleteTag = StringUtil.generateRandomString().toUpperCase(); tagPage.insertNodeId(deleteFile.id); diff --git a/e2e/content-services/upload/uploader-component.e2e.ts b/e2e/content-services/upload/uploader-component.e2e.ts index e23fb66c18..75c144f0b2 100644 --- a/e2e/content-services/upload/uploader-component.e2e.ts +++ b/e2e/content-services/upload/uploader-component.e2e.ts @@ -28,7 +28,7 @@ import { FolderModel } from '../../models/ACS/folderModel'; import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; @@ -365,7 +365,7 @@ describe('Upload component', () => { }); it('[C291921] Should display tooltip for uploading files on a not found location', async () => { - const folderName = Util.generateRandomString(8); + const folderName = StringUtil.generateRandomString(8); const folderUploadedModel = await browser.controlFlow().execute(async () => { return await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); diff --git a/e2e/content-services/upload/user-permission.e2e.ts b/e2e/content-services/upload/user-permission.e2e.ts index 675cf5a1a9..66bdb41a59 100644 --- a/e2e/content-services/upload/user-permission.e2e.ts +++ b/e2e/content-services/upload/user-permission.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { LoginPage } from '../../pages/adf/loginPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; @@ -88,12 +88,12 @@ describe('Upload - User permission', () => { loginPage.loginToContentServicesUsingUserModel(acsUser); this.consumerSite = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(), + title: StringUtil.generateRandomString(), visibility: 'PUBLIC' }); this.managerSite = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(), + title: StringUtil.generateRandomString(), visibility: 'PUBLIC' }); diff --git a/e2e/content-services/version/version-actions.e2e.ts b/e2e/content-services/version/version-actions.e2e.ts index 77ea27701f..7326f326a1 100644 --- a/e2e/content-services/version/version-actions.e2e.ts +++ b/e2e/content-services/version/version-actions.e2e.ts @@ -32,6 +32,7 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; import { Util } from '../../util/util'; import path = require('path'); import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; describe('Version component actions', () => { @@ -86,14 +87,14 @@ describe('Version component actions', () => { versionManagePage.clickActionButton('1.0'); expect(element(by.css(`[id="adf-version-list-action-delete-1.0"]`)).isEnabled()).toBe(false); versionManagePage.closeActionButton(); - Util.waitUntilElementIsNotOnPage(element(by.css(`[id="adf-version-list-action-delete-1.0"]`))); + BrowserVisibility.waitUntilElementIsNotOnPage(element(by.css(`[id="adf-version-list-action-delete-1.0"]`))); }); it('[C280004] Should not be possible restore the version if there is only one version', () => { versionManagePage.clickActionButton('1.0'); expect(element(by.css(`[id="adf-version-list-action-restore-1.0"]`)).isEnabled()).toBe(false); versionManagePage.closeActionButton(); - Util.waitUntilElementIsNotOnPage(element(by.css(`[id="adf-version-list-action-restore-1.0"]`))); + BrowserVisibility.waitUntilElementIsNotOnPage(element(by.css(`[id="adf-version-list-action-restore-1.0"]`))); }); it('[C280005] Should be showed all the default action when you have more then one version', () => { diff --git a/e2e/content-services/version/version-permissions.e2e.ts b/e2e/content-services/version/version-permissions.e2e.ts index 02ffce4376..f132b3edf7 100644 --- a/e2e/content-services/version/version-permissions.e2e.ts +++ b/e2e/content-services/version/version-permissions.e2e.ts @@ -34,7 +34,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { NodeActions } from '../../actions/ACS/node.actions'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import CONSTANTS = require('../../util/constants'); describe('Version component permissions', () => { @@ -89,7 +89,7 @@ describe('Version component permissions', () => { await this.alfrescoJsApi.core.peopleApi.addPerson(fileCreatorUser); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(), + title: StringUtil.generateRandomString(), visibility: 'PUBLIC' }); diff --git a/e2e/content-services/version/version-properties.e2e.ts b/e2e/content-services/version/version-properties.e2e.ts index db897c9a20..7a8d6ab4f8 100644 --- a/e2e/content-services/version/version-properties.e2e.ts +++ b/e2e/content-services/version/version-properties.e2e.ts @@ -29,8 +29,8 @@ import resources = require('../../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; -import { Util } from '../../util/util'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; describe('Version Properties', () => { @@ -86,7 +86,7 @@ describe('Version Properties', () => { versionManagePage.clickActionButton('1.0'); - Util.waitUntilElementIsNotVisible(element(by.css(`[id="adf-version-list-action-download-1.0"]`))); + BrowserVisibility.waitUntilElementIsNotVisible(element(by.css(`[id="adf-version-list-action-download-1.0"]`))); versionManagePage.closeActionButton(); }); @@ -96,7 +96,7 @@ describe('Version Properties', () => { versionManagePage.clickActionButton('1.0'); - Util.waitUntilElementIsVisible(element(by.css(`[id="adf-version-list-action-download-1.0"]`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`[id="adf-version-list-action-download-1.0"]`))); versionManagePage.closeActionButton(); }); @@ -113,28 +113,28 @@ describe('Version Properties', () => { versionManagePage.disableComments(); - Util.waitUntilElementIsNotVisible(element(by.css(`[id="adf-version-list-item-comment-1.1"]`))); + BrowserVisibility.waitUntilElementIsNotVisible(element(by.css(`[id="adf-version-list-item-comment-1.1"]`))); }); it('[C277277] Should show/hide actions menu when readOnly is true/false', () => { versionManagePage.disableReadOnly(); - Util.waitUntilElementIsVisible(element(by.css(`[id="adf-version-list-action-menu-button-1.0"]`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`[id="adf-version-list-action-menu-button-1.0"]`))); versionManagePage.enableReadOnly(); - Util.waitUntilElementIsNotVisible(element(by.css(`[id="adf-version-list-action-menu-button-1.0"]`))); + BrowserVisibility.waitUntilElementIsNotVisible(element(by.css(`[id="adf-version-list-action-menu-button-1.0"]`))); }); it('[C279994] Should show/hide upload new version button when readOnly is true/false', () => { versionManagePage.disableReadOnly(); - Util.waitUntilElementIsVisible(versionManagePage.showNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.showNewVersionButton); versionManagePage.enableReadOnly(); - Util.waitUntilElementIsNotVisible(versionManagePage.showNewVersionButton); - Util.waitUntilElementIsNotVisible(versionManagePage.uploadNewVersionButton); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.showNewVersionButton); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.uploadNewVersionButton); }); }); diff --git a/e2e/content-services/version/version-smoke-tests.e2e.ts b/e2e/content-services/version/version-smoke-tests.e2e.ts index 188c4d2d85..dd541953dd 100644 --- a/e2e/content-services/version/version-smoke-tests.e2e.ts +++ b/e2e/content-services/version/version-smoke-tests.e2e.ts @@ -29,8 +29,8 @@ import resources = require('../../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; -import { Util } from '../../util/util'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; describe('Version component', () => { @@ -109,25 +109,25 @@ describe('Version component', () => { browser.driver.sleep(300); - Util.waitUntilElementIsVisible(versionManagePage.cancelButton); - Util.waitUntilElementIsVisible(versionManagePage.majorRadio); - Util.waitUntilElementIsVisible(versionManagePage.minorRadio); - Util.waitUntilElementIsVisible(versionManagePage.cancelButton); - Util.waitUntilElementIsVisible(versionManagePage.commentText); - Util.waitUntilElementIsVisible(versionManagePage.uploadNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.majorRadio); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.minorRadio); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.commentText); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.uploadNewVersionButton); versionManagePage.cancelButton.click(); browser.driver.sleep(300); - Util.waitUntilElementIsNotVisible(versionManagePage.cancelButton); - Util.waitUntilElementIsNotVisible(versionManagePage.majorRadio); - Util.waitUntilElementIsNotVisible(versionManagePage.minorRadio); - Util.waitUntilElementIsNotVisible(versionManagePage.cancelButton); - Util.waitUntilElementIsNotVisible(versionManagePage.commentText); - Util.waitUntilElementIsNotVisible(versionManagePage.uploadNewVersionButton); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.cancelButton); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.majorRadio); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.minorRadio); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.cancelButton); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.commentText); + BrowserVisibility.waitUntilElementIsNotVisible(versionManagePage.uploadNewVersionButton); - Util.waitUntilElementIsVisible(versionManagePage.showNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(versionManagePage.showNewVersionButton); }); it('[C260244] Should show the version history when select a file with multiple version', () => { diff --git a/e2e/core/card-view/card-view-component.e2e.ts b/e2e/core/card-view/card-view-component.e2e.ts index 8524558eff..62452ef936 100644 --- a/e2e/core/card-view/card-view-component.e2e.ts +++ b/e2e/core/card-view/card-view-component.e2e.ts @@ -23,7 +23,7 @@ import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; import TestConfig = require('../../test.config'); import { CardViewComponentPage } from '../../pages/adf/cardViewComponentPage'; -import { Util } from '../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; describe('CardView Component', () => { const loginPage = new LoginPage(); @@ -47,7 +47,7 @@ describe('CardView Component', () => { it('[C279938] Should the label be present', () => { const label = element(by.css('div[data-automation-id="card-key-value-pairs-label-key-value-pairs"]')); - Util.waitUntilElementIsPresent(label); + BrowserVisibility.waitUntilElementIsPresent(label); }); it('[C279898] Should be possible edit key-value pair properties', () => { @@ -69,7 +69,7 @@ describe('CardView Component', () => { it('[C279939] Should the label be present', () => { const label = element(by.css('div[data-automation-id="card-select-label-select"]')); - Util.waitUntilElementIsPresent(label); + BrowserVisibility.waitUntilElementIsPresent(label); }); it('[C279899] Should be possible edit selectBox item', () => { @@ -86,7 +86,7 @@ describe('CardView Component', () => { it('[C279937] Should the label be present', () => { const label = element(by.css('div[data-automation-id="card-textitem-label-name"]')); - Util.waitUntilElementIsPresent(label); + BrowserVisibility.waitUntilElementIsPresent(label); }); it('[C279943] Should be present a default value', () => { @@ -117,7 +117,7 @@ describe('CardView Component', () => { it('[C279940] Should the label be present', () => { const label = element(by.css('div[data-automation-id="card-textitem-label-int"]')); - Util.waitUntilElementIsPresent(label); + BrowserVisibility.waitUntilElementIsPresent(label); }); it('[C279945] Should be present a default value', () => { @@ -191,7 +191,7 @@ describe('CardView Component', () => { it('[C279941] Should the label be present', () => { const label = element(by.css('div[data-automation-id="card-textitem-label-float"]')); - Util.waitUntilElementIsPresent(label); + BrowserVisibility.waitUntilElementIsPresent(label); }); it('[C279952] Should be present a default value', () => { @@ -241,7 +241,7 @@ describe('CardView Component', () => { it('[C279942] Should the label be present', () => { const label = element(by.css('div[data-automation-id="card-boolean-label-boolean"]')); - Util.waitUntilElementIsPresent(label); + BrowserVisibility.waitUntilElementIsPresent(label); }); it('[C279957] Should be possible edit the checkbox value when click on it', () => { @@ -260,11 +260,11 @@ describe('CardView Component', () => { it('[C279961] Should the label be present', () => { const labelDate = element(by.css('div[data-automation-id="card-dateitem-label-date"]')); - Util.waitUntilElementIsPresent(labelDate); + BrowserVisibility.waitUntilElementIsPresent(labelDate); const labelDatetime = element(by.css('div[data-automation-id="card-dateitem-label-datetime"]')); - Util.waitUntilElementIsPresent(labelDatetime); + BrowserVisibility.waitUntilElementIsPresent(labelDatetime); }); it('[C279962] Should be present a default value', () => { @@ -283,10 +283,10 @@ describe('CardView Component', () => { const editIconKey = element(by.css('mat-icon[data-automation-id="card-key-value-pairs-button-key-value-pairs"]')); const editIconData = element(by.css('mat-datetimepicker-toggle')); - Util.waitUntilElementIsNotVisible(editIconText); - Util.waitUntilElementIsNotVisible(editIconInt); - Util.waitUntilElementIsNotVisible(editIconFloat); - Util.waitUntilElementIsNotVisible(editIconKey); - Util.waitUntilElementIsNotVisible(editIconData); + BrowserVisibility.waitUntilElementIsNotVisible(editIconText); + BrowserVisibility.waitUntilElementIsNotVisible(editIconInt); + BrowserVisibility.waitUntilElementIsNotVisible(editIconFloat); + BrowserVisibility.waitUntilElementIsNotVisible(editIconKey); + BrowserVisibility.waitUntilElementIsNotVisible(editIconData); }); }); diff --git a/e2e/core/card-view/metadata-permissions.e2e.ts b/e2e/core/card-view/metadata-permissions.e2e.ts index b688e7899d..eeb338b902 100644 --- a/e2e/core/card-view/metadata-permissions.e2e.ts +++ b/e2e/core/card-view/metadata-permissions.e2e.ts @@ -29,7 +29,7 @@ import resources = require('../../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import CONSTANTS = require('../../util/constants'); describe('permissions', () => { @@ -78,7 +78,7 @@ describe('permissions', () => { await this.alfrescoJsApi.core.peopleApi.addPerson(contributorUser); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(), + title: StringUtil.generateRandomString(), visibility: 'PUBLIC' }); diff --git a/e2e/core/error-component.e2e.ts b/e2e/core/error-component.e2e.ts index d17f7d4f54..e774dc6594 100644 --- a/e2e/core/error-component.e2e.ts +++ b/e2e/core/error-component.e2e.ts @@ -20,7 +20,7 @@ import { AcsUserModel } from '../models/ACS/acsUserModel'; import TestConfig = require('../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { ErrorPage } from '../pages/adf/errorPage'; -import { browser } from '../../node_modules/protractor'; +import { browser } from 'protractor'; describe('Error Component', () => { diff --git a/e2e/core/login/login-component.e2e.ts b/e2e/core/login/login-component.e2e.ts index 21dc1db9a4..4843c3d63e 100644 --- a/e2e/core/login/login-component.e2e.ts +++ b/e2e/core/login/login-component.e2e.ts @@ -259,7 +259,7 @@ describe('Login component', () => { settingsPage.setProviderEcmBpm(); loginPage.enableLogoSwitch(); loginPage.enterLogo('https://rawgit.com/Alfresco/alfresco-ng2-components/master/assets/angular2.png'); - loginPage.checkLoginImgURL('https://rawgit.com/Alfresco/alfresco-ng2-components/master/assets/angular2.png'); + loginPage.checkLoginImgURL(); }); it('[C291854] Should be possible login in valid credentials', () => { diff --git a/e2e/core/login/redirection.e2e.ts b/e2e/core/login/redirection.e2e.ts index f5d51f0250..2c366e3cc9 100644 --- a/e2e/core/login/redirection.e2e.ts +++ b/e2e/core/login/redirection.e2e.ts @@ -29,7 +29,7 @@ import { SettingsPage } from '../../pages/adf/settingsPage'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { LogoutPage } from '../../pages/adf/demo-shell/logoutPage'; @@ -64,7 +64,7 @@ describe('Login component - Redirect', () => { await this.alfrescoJsApi.login(user.id, user.password); - uploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, 'protecteFolder' + Util.generateRandomString(), '-my-'); + uploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, 'protecteFolder' + StringUtil.generateRandomString(), '-my-'); done(); }); diff --git a/e2e/core/user-info-component-cloud.e2e.ts b/e2e/core/user-info-component-cloud.e2e.ts index 9b1350f308..88990d88d2 100644 --- a/e2e/core/user-info-component-cloud.e2e.ts +++ b/e2e/core/user-info-component-cloud.e2e.ts @@ -18,10 +18,9 @@ import { LoginSSOPage } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import TestConfig = require('../test.config'); -import { browser } from 'protractor'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { UserInfoPage } from '@alfresco/adf-testing'; -import { Identity } from '../actions/APS-cloud/identity'; +import { IdentityService, ApiService } from '@alfresco/adf-testing'; describe('User Info - SSO', () => { @@ -29,21 +28,25 @@ describe('User Info - SSO', () => { const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); const userInfoPage = new UserInfoPage(); - const identityService: Identity = new Identity(); let silentLogin, identityUser; + let identityService: IdentityService; beforeAll(async () => { - await identityService.init(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword, 'alfresco'); + const apiService = new ApiService('alfresco', TestConfig.adf.url, TestConfig.adf.hostSso, 'ECM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + identityService = new IdentityService(apiService); identityUser = await identityService.createIdentityUser(); + silentLogin = false; settingsPage.setProviderEcmSso(TestConfig.adf.url, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin, true, 'alfresco'); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; - loginSSOPage.loginSSOIdentityService(identityUser.username, identityUser.password); + + loginSSOPage.loginSSOIdentityService(identityUser.email, identityUser.password); }); afterAll(async () => { - await identityService.deleteIdentityUser(identityUser.id); + await identityService.deleteIdentityUser(identityUser.idIdentityService); }); it('[C290066] Should display UserInfo when login using SSO', () => { diff --git a/e2e/core/user-info-component.e2e.ts b/e2e/core/user-info-component.e2e.ts index 0dd4243b27..0d6758bba1 100644 --- a/e2e/core/user-info-component.e2e.ts +++ b/e2e/core/user-info-component.e2e.ts @@ -81,7 +81,7 @@ describe('User Info component', () => { expect(userInfoPage.getContentHeaderTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); expect(userInfoPage.getContentTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); expect(userInfoPage.getContentEmail()).toEqual(contentUserModel.email); - expect(userInfoPage.getContentJobTitle()).toEqual(contentUserModel.jobTitle); + expect(userInfoPage.getContentJobTitle()).toEqual('N/A'); userInfoPage.checkInitialImage(); userInfoPage.APSProfileImageNotDisplayed(); @@ -91,7 +91,7 @@ describe('User Info component', () => { expect(userInfoPage.getContentHeaderTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); expect(userInfoPage.getContentTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); expect(userInfoPage.getContentEmail()).toEqual(contentUserModel.email); - expect(userInfoPage.getContentJobTitle()).toEqual(contentUserModel.jobTitle); + expect(userInfoPage.getContentJobTitle()).toEqual('N/A'); userInfoPage.checkInitialImage(); userInfoPage.APSProfileImageNotDisplayed(); @@ -99,9 +99,9 @@ describe('User Info component', () => { userInfoPage.clickOnProcessServicesTab(); userInfoPage.checkProcessServicesTabIsSelected(); - expect(userInfoPage.getProcessHeaderTitle()).toEqual(processUserModel.firstName + ' ' + processUserModel.lastName); - expect(userInfoPage.getProcessTitle()).toEqual(processUserModel.firstName + ' ' + processUserModel.lastName); - expect(userInfoPage.getProcessEmail()).toEqual(processUserModel.email); + expect(userInfoPage.getProcessHeaderTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); + expect(userInfoPage.getProcessTitle()).toEqual(contentUserModel.firstName + ' ' + processUserModel.lastName); + expect(userInfoPage.getProcessEmail()).toEqual(contentUserModel.email); userInfoPage.checkInitialImage(); userInfoPage.APSProfileImageNotDisplayed(); @@ -120,7 +120,7 @@ describe('User Info component', () => { expect(userInfoPage.getContentHeaderTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); expect(userInfoPage.getContentTitle()).toEqual(contentUserModel.firstName + ' ' + contentUserModel.lastName); expect(userInfoPage.getContentEmail()).toEqual(contentUserModel.email); - expect(userInfoPage.getContentJobTitle()).toEqual(contentUserModel.jobTitle); + expect(userInfoPage.getContentJobTitle()).toEqual('N/A'); userInfoPage.checkInitialImage(); userInfoPage.APSProfileImageNotDisplayed(); @@ -150,7 +150,7 @@ describe('User Info component', () => { it('[C260117] Should display UserInfo with profile image uploaded in ACS', async(done) => { browser.controlFlow().execute(async() => { await PeopleAPI.updateAvatarViaAPI(contentUserModel, acsAvatarFileModel, '-me-'); - await PeopleAPI.getAvatarViaAPI(4, contentUserModel, '-me-', function (result) {}); + await PeopleAPI.getAvatarViaAPI(4, contentUserModel, '-me-', function () {}); }); loginPage.goToLoginPage(); diff --git a/e2e/core/viewer/viewer-component.e2e.ts b/e2e/core/viewer/viewer-component.e2e.ts index be020f6a3c..9d313f9b68 100644 --- a/e2e/core/viewer/viewer-component.e2e.ts +++ b/e2e/core/viewer/viewer-component.e2e.ts @@ -26,7 +26,7 @@ import { AboutPage } from '../../pages/adf/demo-shell/aboutPage'; import CONSTANTS = require('../../util/constants'); import resources = require('../../util/resources'); -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { FileModel } from '../../models/ACS/fileModel'; import { FolderModel } from '../../models/ACS/folderModel'; @@ -106,7 +106,7 @@ xdescribe('Viewer', () => { await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(8), + title: StringUtil.generateRandomString(8), visibility: 'PUBLIC' }); diff --git a/e2e/models/ACS/acsUserModel.ts b/e2e/models/ACS/acsUserModel.ts index fbae7eecdb..ea2d41622a 100644 --- a/e2e/models/ACS/acsUserModel.ts +++ b/e2e/models/ACS/acsUserModel.ts @@ -15,16 +15,15 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; export class AcsUserModel { - firstName = Util.generateRandomString(); - lastName = Util.generateRandomString(); - password = Util.generateRandomString(); - email = Util.generateRandomString(); - id = Util.generateRandomString(); - jobTitle = 'N/A'; + firstName = StringUtil.generateRandomString(); + lastName = StringUtil.generateRandomString(); + password = StringUtil.generateRandomString(); + email = StringUtil.generateRandomString(); + id = StringUtil.generateRandomString(); constructor(details?: any) { Object.assign(this, details); diff --git a/e2e/models/ACS/createdByModel.ts b/e2e/models/ACS/createdByModel.ts index ed1bf0f008..773d2fe6b6 100644 --- a/e2e/models/ACS/createdByModel.ts +++ b/e2e/models/ACS/createdByModel.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; export class CreatedByModel { - displayName = Util.generateRandomString(); - id = Util.generateRandomString(); + displayName = StringUtil.generateRandomString(); + id = StringUtil.generateRandomString(); constructor(details?: any) { Object.assign(this, details); diff --git a/e2e/models/ACS/fileModel.ts b/e2e/models/ACS/fileModel.ts index 6dbe3f1914..074d166810 100644 --- a/e2e/models/ACS/fileModel.ts +++ b/e2e/models/ACS/fileModel.ts @@ -19,12 +19,12 @@ import resources = require('../../util/resources'); import ContentModel = require('./contentModel'); import ContentPropertiesModel = require('./contentProperties'); import { CreatedByModel } from './createdByModel'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; export class FileModel { - id = Util.generateRandomString(); - name = Util.generateRandomString(); + id = StringUtil.generateRandomString(); + name = StringUtil.generateRandomString(); shortName = this.name; location = resources.Files.ADF_DOCUMENTS.PDF.file_location; tooltip = this.name; diff --git a/e2e/models/ACS/folderModel.ts b/e2e/models/ACS/folderModel.ts index a3dccc61c2..0c4f59e7e4 100644 --- a/e2e/models/ACS/folderModel.ts +++ b/e2e/models/ACS/folderModel.ts @@ -15,12 +15,12 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; export class FolderModel { - id = Util.generateRandomString(); - name = Util.generateRandomString(); + id = StringUtil.generateRandomString(); + name = StringUtil.generateRandomString(); shortName = this.name; tooltip = this.name; location = ''; diff --git a/e2e/models/APS/standaloneTask.ts b/e2e/models/APS/standaloneTask.ts index 4b129712d3..29c819a844 100644 --- a/e2e/models/APS/standaloneTask.ts +++ b/e2e/models/APS/standaloneTask.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; /** * Create Json Object for standalone task @@ -25,7 +25,7 @@ import { Util } from '../../util/util'; */ export class StandaloneTask { - name = Util.generateRandomString(); + name = StringUtil.generateRandomString(); constructor(details?: any) { Object.assign(this, details); diff --git a/e2e/models/APS/tenant.ts b/e2e/models/APS/tenant.ts index d27d1ad2f5..dbf7c416ef 100644 --- a/e2e/models/APS/tenant.ts +++ b/e2e/models/APS/tenant.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; /** * Create tenant JSON Object @@ -29,7 +29,7 @@ export class Tenant { configuration = 'DefaultConfig'; domain = 'DefaultDomain'; maxUsers = 10; - name = Util.generateRandomString(); + name = StringUtil.generateRandomString(); constructor(details?: any) { Object.assign(this, details); diff --git a/e2e/models/APS/user.ts b/e2e/models/APS/user.ts index 4e1b1c2acf..00dde1aebc 100644 --- a/e2e/models/APS/user.ts +++ b/e2e/models/APS/user.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; /** * Create tenant JSON Object @@ -25,10 +25,10 @@ import { Util } from '../../util/util'; */ export class User { - email = Util.generateRandomEmail(); - firstName = Util.generateRandomString(); - lastName = Util.generateRandomString(); - password = Util.generatePasswordString(); + email = StringUtil.generateRandomEmail('@activiti.test.com'); + firstName = StringUtil.generateRandomString(); + lastName = StringUtil.generateRandomString(); + password = StringUtil.generatePasswordString(); type = 'enterprise'; tenantId = '1'; company = null; diff --git a/e2e/pages/adf/cardViewComponentPage.ts b/e2e/pages/adf/cardViewComponentPage.ts index 4e64f48d32..fe9a9119fd 100644 --- a/e2e/pages/adf/cardViewComponentPage.ts +++ b/e2e/pages/adf/cardViewComponentPage.ts @@ -16,7 +16,7 @@ */ import { by, element } from 'protractor'; -import { Util } from '../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class CardViewComponentPage { @@ -38,45 +38,45 @@ export class CardViewComponentPage { editableSwitch = element(by.id('adf-toggle-editable')); clickOnAddButton() { - Util.waitUntilElementIsVisible(this.addButton); + BrowserVisibility.waitUntilElementIsVisible(this.addButton); this.addButton.click(); return this; } clickOnResetButton() { - Util.waitUntilElementIsVisible(this.resetButton); + BrowserVisibility.waitUntilElementIsVisible(this.resetButton); this.resetButton.click(); return this; } clickOnTextField() { const toggleText = element(by.css(`div[data-automation-id='card-textitem-edit-toggle-name']`)); - Util.waitUntilElementIsVisible(toggleText); + BrowserVisibility.waitUntilElementIsVisible(toggleText); toggleText.click(); - Util.waitUntilElementIsVisible(this.textField); + BrowserVisibility.waitUntilElementIsVisible(this.textField); return this; } clickOnTextClearIcon() { const clearIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-reset-name"]`)); - Util.waitUntilElementIsVisible(clearIcon); + BrowserVisibility.waitUntilElementIsVisible(clearIcon); return clearIcon.click(); } clickOnTextSaveIcon() { const saveIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-update-name"]`)); - Util.waitUntilElementIsVisible(saveIcon); + BrowserVisibility.waitUntilElementIsVisible(saveIcon); return saveIcon.click(); } getTextFieldText() { const textField = element(by.css(`span[data-automation-id="card-textitem-value-name"]`)); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); return textField.getText(); } enterTextField(text) { - Util.waitUntilElementIsVisible(this.textField); + BrowserVisibility.waitUntilElementIsVisible(this.textField); this.textField.sendKeys(''); this.textField.clear(); this.textField.sendKeys(text); @@ -85,26 +85,26 @@ export class CardViewComponentPage { clickOnIntField() { const toggleText = element(by.css('div[data-automation-id="card-textitem-edit-toggle-int"]')); - Util.waitUntilElementIsVisible(toggleText); + BrowserVisibility.waitUntilElementIsVisible(toggleText); toggleText.click(); - Util.waitUntilElementIsVisible(this.intField); + BrowserVisibility.waitUntilElementIsVisible(this.intField); return this; } clickOnIntClearIcon() { const clearIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-int"]')); - Util.waitUntilElementIsVisible(clearIcon); + BrowserVisibility.waitUntilElementIsVisible(clearIcon); return clearIcon.click(); } clickOnIntSaveIcon() { const saveIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-int"]')); - Util.waitUntilElementIsVisible(saveIcon); + BrowserVisibility.waitUntilElementIsVisible(saveIcon); return saveIcon.click(); } enterIntField(text) { - Util.waitUntilElementIsVisible(this.intField); + BrowserVisibility.waitUntilElementIsVisible(this.intField); this.intField.sendKeys(''); this.intField.clear(); this.intField.sendKeys(text); @@ -113,38 +113,38 @@ export class CardViewComponentPage { getIntFieldText() { const textField = element(by.css('span[data-automation-id="card-textitem-value-int"]')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); return textField.getText(); } getErrorInt() { const errorElement = element(by.css('mat-error[data-automation-id="card-textitem-error-int"]')); - Util.waitUntilElementIsVisible(errorElement); + BrowserVisibility.waitUntilElementIsVisible(errorElement); return errorElement.getText(); } clickOnFloatField() { const toggleText = element(by.css('div[data-automation-id="card-textitem-edit-toggle-float"]')); - Util.waitUntilElementIsVisible(toggleText); + BrowserVisibility.waitUntilElementIsVisible(toggleText); toggleText.click(); - Util.waitUntilElementIsVisible(this.floatField); + BrowserVisibility.waitUntilElementIsVisible(this.floatField); return this; } clickOnFloatClearIcon() { const clearIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-reset-float"]`)); - Util.waitUntilElementIsVisible(clearIcon); + BrowserVisibility.waitUntilElementIsVisible(clearIcon); return clearIcon.click(); } clickOnFloatSaveIcon() { const saveIcon = element(by.css(`mat-icon[data-automation-id="card-textitem-update-float"]`)); - Util.waitUntilElementIsVisible(saveIcon); + BrowserVisibility.waitUntilElementIsVisible(saveIcon); return saveIcon.click(); } enterFloatField(text) { - Util.waitUntilElementIsVisible(this.floatField); + BrowserVisibility.waitUntilElementIsVisible(this.floatField); this.floatField.sendKeys(''); this.floatField.clear(); this.floatField.sendKeys(text); @@ -153,30 +153,30 @@ export class CardViewComponentPage { getFloatFieldText() { const textField = element(by.css('span[data-automation-id="card-textitem-value-float"]')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); return textField.getText(); } getErrorFloat() { const errorElement = element(by.css('mat-error[data-automation-id="card-textitem-error-float"]')); - Util.waitUntilElementIsVisible(errorElement); + BrowserVisibility.waitUntilElementIsVisible(errorElement); return errorElement.getText(); } setName(name) { - Util.waitUntilElementIsVisible(this.nameInputField); + BrowserVisibility.waitUntilElementIsVisible(this.nameInputField); this.nameInputField.sendKeys(name); return this; } setValue(value) { - Util.waitUntilElementIsVisible(this.valueInputField); + BrowserVisibility.waitUntilElementIsVisible(this.valueInputField); this.valueInputField.sendKeys(value); return this; } waitForOutput() { - Util.waitUntilElementIsVisible(this.consoleLog); + BrowserVisibility.waitUntilElementIsVisible(this.consoleLog); return this; } @@ -185,13 +185,13 @@ export class CardViewComponentPage { } deletePairsValues() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); this.deleteButton.click(); return this; } checkNameAndValueVisibility(index) { - Util.waitUntilElementIsNotOnPage(this.getKeyValueRow(index)); + BrowserVisibility.waitUntilElementIsNotOnPage(this.getKeyValueRow(index)); return this; } @@ -206,7 +206,7 @@ export class CardViewComponentPage { clickSelectBox() { this.select.click(); - Util.waitUntilElementIsVisible(this.listContent); + BrowserVisibility.waitUntilElementIsVisible(this.listContent); } checkboxClick() { @@ -215,7 +215,7 @@ export class CardViewComponentPage { selectValueFromComboBox(index) { const value = this.getMatSelectValue(index).click(); - Util.waitUntilElementIsVisible(value); + BrowserVisibility.waitUntilElementIsVisible(value); return this; } @@ -224,7 +224,7 @@ export class CardViewComponentPage { } disableEdit() { - Util.waitUntilElementIsVisible(this.editableSwitch); + BrowserVisibility.waitUntilElementIsVisible(this.editableSwitch); this.editableSwitch.getAttribute('class').then((check) => { if (check.indexOf('mat-checked') > -1) { diff --git a/e2e/pages/adf/commentsPage.ts b/e2e/pages/adf/commentsPage.ts index 9fce3b0640..0c6b7c02cc 100644 --- a/e2e/pages/adf/commentsPage.ts +++ b/e2e/pages/adf/commentsPage.ts @@ -17,8 +17,8 @@ import { element, by } from 'protractor'; -import { Util } from '../../util/util'; import { TabsPage } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class CommentsPage { @@ -32,36 +32,36 @@ export class CommentsPage { addCommentButton = element(by.css("[data-automation-id='comments-input-add']")); getTotalNumberOfComments() { - Util.waitUntilElementIsVisible(this.numberOfComments); + BrowserVisibility.waitUntilElementIsVisible(this.numberOfComments); return this.numberOfComments.getText(); } checkUserIconIsDisplayed(position) { - Util.waitUntilElementIsVisible(this.commentUserIcon); + BrowserVisibility.waitUntilElementIsVisible(this.commentUserIcon); return this.commentUserIcon.get(position); } getUserName(position) { - Util.waitUntilElementIsVisible(this.commentUserName); + BrowserVisibility.waitUntilElementIsVisible(this.commentUserName); return this.commentUserName.get(position).getText(); } getMessage(position) { - Util.waitUntilElementIsVisible(this.commentMessage); + BrowserVisibility.waitUntilElementIsVisible(this.commentMessage); return this.commentMessage.get(position).getText(); } getTime(position) { - Util.waitUntilElementIsVisible(this.commentTime); + BrowserVisibility.waitUntilElementIsVisible(this.commentTime); return this.commentTime.get(position).getText(); } checkCommentInputIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.commentInput); + BrowserVisibility.waitUntilElementIsNotVisible(this.commentInput); } addComment(comment) { - Util.waitUntilElementIsVisible(this.commentInput); + BrowserVisibility.waitUntilElementIsVisible(this.commentInput); this.commentInput.sendKeys(comment); return this.addCommentButton.click(); } @@ -71,6 +71,6 @@ export class CommentsPage { } checkCommentInputIsDisplayed() { - Util.waitUntilElementIsVisible(this.commentInput); + BrowserVisibility.waitUntilElementIsVisible(this.commentInput); } } diff --git a/e2e/pages/adf/configEditorPage.ts b/e2e/pages/adf/configEditorPage.ts index aebf4585ae..306319baea 100644 --- a/e2e/pages/adf/configEditorPage.ts +++ b/e2e/pages/adf/configEditorPage.ts @@ -16,20 +16,20 @@ */ import { element, by, browser } from 'protractor'; -import { Util } from '../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ConfigEditorPage { enterConfiguration(text) { const textField = element(by.css('#adf-code-configuration-editor div.overflow-guard > textarea')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); textField.sendKeys(text); return this; } enterBigConfigurationText(text) { const textField = element(by.css('#adf-code-configuration-editor div.overflow-guard > textarea')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); browser.executeScript('this.monaco.editor.getModels()[0].setValue(`' + text + '`)'); return this; @@ -37,64 +37,64 @@ export class ConfigEditorPage { clickSaveButton() { const saveButton = element(by.id('adf-configuration-save')); - Util.waitUntilElementIsVisible(saveButton); - Util.waitUntilElementIsClickable(saveButton); + BrowserVisibility.waitUntilElementIsVisible(saveButton); + BrowserVisibility.waitUntilElementIsClickable(saveButton); return saveButton.click(); } clickClearButton() { const clearButton = element(by.id('adf-configuration-clear')); - Util.waitUntilElementIsVisible(clearButton); - Util.waitUntilElementIsClickable(clearButton); + BrowserVisibility.waitUntilElementIsVisible(clearButton); + BrowserVisibility.waitUntilElementIsClickable(clearButton); return clearButton.click(); } clickFileConfiguration() { const button = element(by.id('adf-file-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } clickSearchConfiguration() { const button = element(by.id('adf-search-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } clickProcessListCloudConfiguration() { const button = element(by.id('adf-process-list-cloud-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } clickEditProcessCloudConfiguration() { const button = element(by.id('adf-edit-process-filter-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } clickEditTaskConfiguration() { const button = element(by.id('adf-edit-task-filter-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } clickTaskListCloudConfiguration() { const button = element(by.id('adf-task-list-cloud-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } clickInfinitePaginationConfiguration() { const button = element(by.id('adf-infinite-pagination-conf')); - Util.waitUntilElementIsVisible(button); - Util.waitUntilElementIsClickable(button); + BrowserVisibility.waitUntilElementIsVisible(button); + BrowserVisibility.waitUntilElementIsClickable(button); return button.click(); } } diff --git a/e2e/pages/adf/content-services/documentListPage.ts b/e2e/pages/adf/content-services/documentListPage.ts index 13afd6e0b3..034930ec6d 100644 --- a/e2e/pages/adf/content-services/documentListPage.ts +++ b/e2e/pages/adf/content-services/documentListPage.ts @@ -17,7 +17,7 @@ import { by, element, ElementFinder, browser } from 'protractor'; import { DataTableComponentPage } from '../dataTableComponentPage'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DocumentListPage { @@ -34,21 +34,21 @@ export class DocumentListPage { } checkLockedIcon(content) { - const row = this.dataTable.getRowParentElement('Display name', content); + const row = this.dataTable.getRow('Display name', content); const lockIcon = row.element(by.cssContainingText('div[title="Lock"] mat-icon', 'lock')); - Util.waitUntilElementIsVisible(lockIcon); + BrowserVisibility.waitUntilElementIsVisible(lockIcon); return this; } checkUnlockedIcon(content) { - const row = this.dataTable.getRowParentElement('Display name', content); + const row = this.dataTable.getRow('Display name', content); const lockIcon = row.element(by.cssContainingText('div[title="Lock"] mat-icon', 'lock_open')); - Util.waitUntilElementIsVisible(lockIcon); + BrowserVisibility.waitUntilElementIsVisible(lockIcon); return this; } waitForTableBody() { - return Util.waitUntilElementIsVisible(this.tableBody); + return BrowserVisibility.waitUntilElementIsVisible(this.tableBody); } getTooltip(nodeName) { @@ -64,15 +64,15 @@ export class DocumentListPage { } clickOnActionMenu(content) { - const row = this.dataTable.getRowParentElement('Display name', content); + const row = this.dataTable.getRow('Display name', content); row.element(this.optionButton).click(); - Util.waitUntilElementIsVisible(this.actionMenu); + BrowserVisibility.waitUntilElementIsVisible(this.actionMenu); browser.sleep(500); return this; } checkActionMenuIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.actionMenu); + BrowserVisibility.waitUntilElementIsNotVisible(this.actionMenu); return this; } diff --git a/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts b/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts index 1af248d5cc..2be8311358 100644 --- a/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts +++ b/e2e/pages/adf/content-services/search/components/dateRangeFilterPage.ts @@ -15,9 +15,9 @@ * limitations under the License. */ -import { Util } from '../../../../../util/util'; import { by, browser, protractor } from 'protractor'; import { DatePickerPage } from '../../../material/datePickerPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DateRangeFilterPage { @@ -54,25 +54,25 @@ export class DateRangeFilterPage { } openFromDatePicker() { - Util.waitUntilElementIsClickable(this.filter.element(this.fromDateToggle)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.fromDateToggle)); this.filter.element(this.fromDateToggle).click(); return new DatePickerPage().checkDatePickerIsDisplayed(); } openToDatePicker() { - Util.waitUntilElementIsClickable(this.filter.element(this.toDateToggle)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.toDateToggle)); this.filter.element(this.toDateToggle).click(); return new DatePickerPage().checkDatePickerIsDisplayed(); } clickFromField() { - Util.waitUntilElementIsClickable(this.filter.element(this.fromField)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.fromField)); this.filter.element(this.fromField).click(); return this; } checkFromErrorMessageIsDisplayed(msg) { - Util.waitUntilElementIsVisible(this.filter.element(this.fromErrorMessage)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromErrorMessage)); browser.controlFlow().execute(async () => { await expect(this.filter.element(this.fromErrorMessage).getText()).toEqual(msg); }); @@ -80,17 +80,17 @@ export class DateRangeFilterPage { } checkFromErrorMessageIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter.element(this.fromErrorMessage)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.fromErrorMessage)); return this; } checkFromFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromField)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromField)); return this; } checkFromDateToggleIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromDateToggle)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromDateToggle)); return this; } @@ -107,13 +107,13 @@ export class DateRangeFilterPage { } clickToField() { - Util.waitUntilElementIsClickable(this.filter.element(this.toField)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.toField)); this.filter.element(this.toField).click(); return this; } checkToErrorMessageIsDisplayed(msg) { - Util.waitUntilElementIsVisible(this.filter.element(this.toErrorMessage)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toErrorMessage)); browser.controlFlow().execute(async () => { await expect(this.filter.element(this.toErrorMessage).getText()).toEqual(msg); }); @@ -121,23 +121,23 @@ export class DateRangeFilterPage { } checkToFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.toField)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toField)); return this; } checkToDateToggleIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.toDateToggle)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toDateToggle)); return this; } clickApplyButton() { - Util.waitUntilElementIsClickable(this.filter.element(this.applyButton)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.applyButton)); this.filter.element(this.applyButton).click(); return this; } checkApplyButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.applyButton)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.applyButton)); return this; } @@ -156,7 +156,7 @@ export class DateRangeFilterPage { } checkClearButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.clearButton)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.clearButton)); return this; } } diff --git a/e2e/pages/adf/content-services/search/components/numberRangeFilterPage.ts b/e2e/pages/adf/content-services/search/components/numberRangeFilterPage.ts index 8b94a215c2..287eec5af2 100644 --- a/e2e/pages/adf/content-services/search/components/numberRangeFilterPage.ts +++ b/e2e/pages/adf/content-services/search/components/numberRangeFilterPage.ts @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Util } from '../../../../../util/util'; import { by, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class NumberRangeFilterPage { @@ -33,7 +33,7 @@ export class NumberRangeFilterPage { this.filter = filter; } clearFromField() { - Util.waitUntilElementIsClickable(this.filter.element(this.fromInput)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.fromInput)); this.filter.element(this.fromInput).getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { this.filter.element(this.fromInput).sendKeys(protractor.Key.BACK_SPACE); @@ -52,27 +52,27 @@ export class NumberRangeFilterPage { return this; } getFromErrorRequired() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromErrorRequired)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromErrorRequired)); return this.filter.element(this.fromErrorRequired).getText(); } checkFromErrorRequiredIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromErrorRequired)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromErrorRequired)); return this; } getFromErrorInvalid() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromErrorInvalid)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromErrorInvalid)); return this.filter.element(this.fromErrorInvalid).getText(); } checkFromErrorInvalidIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromErrorInvalid)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromErrorInvalid)); return this; } checkFromFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.fromInput)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.fromInput)); return this; } clearToField() { - Util.waitUntilElementIsClickable(this.filter.element(this.toInput)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.toInput)); this.filter.element(this.toInput).getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { this.filter.element(this.toInput).sendKeys(protractor.Key.BACK_SPACE); @@ -91,51 +91,51 @@ export class NumberRangeFilterPage { return this; } getToErrorRequired() { - Util.waitUntilElementIsVisible(this.filter.element(this.toErrorRequired)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toErrorRequired)); return this.filter.element(this.toErrorRequired).getText(); } checkToErrorRequiredIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.toErrorRequired)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toErrorRequired)); return this; } getToErrorInvalid() { - Util.waitUntilElementIsVisible(this.filter.element(this.toErrorInvalid)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toErrorInvalid)); return this.filter.element(this.toErrorInvalid).getText(); } checkToErrorInvalidIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.toErrorInvalid)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toErrorInvalid)); return this; } checkToFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.toInput)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.toInput)); return this; } clickApplyButton() { - Util.waitUntilElementIsClickable(this.filter.element(this.applyButton)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.applyButton)); this.filter.element(this.applyButton).click(); return this; } checkApplyButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.applyButton)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.applyButton)); return this; } checkApplyButtonIsEnabled() { return this.filter.element(this.applyButton).isEnabled(); } clickClearButton() { - Util.waitUntilElementIsClickable(this.filter.element(this.clearButton)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.clearButton)); this.filter.element(this.clearButton).click(); return this; } checkClearButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.clearButton)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.clearButton)); return this; } checkNoErrorMessageIsDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter.element(this.fromErrorInvalid)); - Util.waitUntilElementIsNotVisible(this.filter.element(this.fromErrorRequired)); - Util.waitUntilElementIsNotVisible(this.filter.element(this.toErrorInvalid)); - Util.waitUntilElementIsNotVisible(this.filter.element(this.toErrorRequired)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.fromErrorInvalid)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.fromErrorRequired)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.toErrorInvalid)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.toErrorRequired)); return this; } } diff --git a/e2e/pages/adf/content-services/search/components/search-checkList.ts b/e2e/pages/adf/content-services/search/components/search-checkList.ts index e980b88239..57c51e5660 100644 --- a/e2e/pages/adf/content-services/search/components/search-checkList.ts +++ b/e2e/pages/adf/content-services/search/components/search-checkList.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../../../util/util'; import { element, by, ElementFinder } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchCheckListPage { @@ -31,26 +31,26 @@ export class SearchCheckListPage { } clickCheckListOption(option) { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const result = this.filter.all(by.css(`mat-checkbox[data-automation-id*='-${option}'] .mat-checkbox-inner-container`)).first(); - Util.waitUntilElementIsVisible(result); - Util.waitUntilElementIsClickable(result); + BrowserVisibility.waitUntilElementIsVisible(result); + BrowserVisibility.waitUntilElementIsClickable(result); result.click(); } checkChipIsDisplayed(option) { - Util.waitUntilElementIsVisible(element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon'))); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon'))); return this; } checkChipIsNotDisplayed(option) { - Util.waitUntilElementIsNotOnPage(element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon'))); + BrowserVisibility.waitUntilElementIsNotOnPage(element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon'))); return this; } removeFilterOption(option) { const cancelChipButton = element(by.cssContainingText('mat-chip', option)).element(by.css('mat-icon')); - Util.waitUntilElementIsClickable(cancelChipButton); + BrowserVisibility.waitUntilElementIsClickable(cancelChipButton); cancelChipButton.click(); return this; } @@ -63,14 +63,14 @@ export class SearchCheckListPage { } checkSearchFilterInputIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.all(this.inputBy).first()); + BrowserVisibility.waitUntilElementIsVisible(this.filter.all(this.inputBy).first()); return this; } searchInFilter(option) { - Util.waitUntilElementIsClickable(this.filter); + BrowserVisibility.waitUntilElementIsClickable(this.filter); const inputElement = this.filter.all(this.inputBy).first(); - Util.waitUntilElementIsClickable(inputElement); + BrowserVisibility.waitUntilElementIsClickable(inputElement); inputElement.clear(); this.filter.all(this.inputBy).first().sendKeys(option); @@ -78,22 +78,22 @@ export class SearchCheckListPage { } checkShowLessButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter.element(this.showLessBy)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.showLessBy)); return this; } checkShowLessButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.showLessBy)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.showLessBy)); return this; } checkShowMoreButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.showMoreBy)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.showMoreBy)); return this; } checkShowMoreButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter.element(this.showMoreBy)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.showMoreBy)); return this; } @@ -104,7 +104,7 @@ export class SearchCheckListPage { this.clickShowMoreButtonUntilIsNotDisplayed(); } - }, (err) => { + }, () => { }); return this; } @@ -116,14 +116,14 @@ export class SearchCheckListPage { this.clickShowLessButtonUntilIsNotDisplayed(); } - }, (err) => { + }, () => { }); return this; } getBucketNumberOfFilterType(option) { const fileTypeFilter = this.filter.all(by.css('mat-checkbox[data-automation-id*=".' + option + '"] span')).first(); - Util.waitUntilElementIsVisible(fileTypeFilter); + BrowserVisibility.waitUntilElementIsVisible(fileTypeFilter); const bucketNumber = fileTypeFilter.getText().then((valueOfBucket) => { const numberOfBucket = valueOfBucket.split('(')[1]; const totalNumberOfBucket = numberOfBucket.split(')')[0]; @@ -134,49 +134,49 @@ export class SearchCheckListPage { } checkCheckListOptionIsDisplayed(option) { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}']`)); - return Util.waitUntilElementIsVisible(result); + return BrowserVisibility.waitUntilElementIsVisible(result); } checkCheckListOptionIsNotSelected(option) { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`)); - return Util.waitUntilElementIsNotVisible(result); + return BrowserVisibility.waitUntilElementIsNotVisible(result); } checkCheckListOptionIsSelected(option) { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const result = this.filter.element(by.css(`mat-checkbox[data-automation-id*='-${option}'][class*='checked']`)); - return Util.waitUntilElementIsVisible(result); + return BrowserVisibility.waitUntilElementIsVisible(result); } checkClearAllButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const result = this.filter.element(this.clearAllButton); - return Util.waitUntilElementIsVisible(result); + return BrowserVisibility.waitUntilElementIsVisible(result); } clickClearAllButton() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const result = this.filter.element(this.clearAllButton); - Util.waitUntilElementIsVisible(result); + BrowserVisibility.waitUntilElementIsVisible(result); return result.click(); } getCheckListOptionsNumberOnPage() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const checkListOptions = this.filter.all(by.css('div[class="checklist"] mat-checkbox')); return checkListOptions.count(); } clickShowMoreButton() { - Util.waitUntilElementIsVisible(this.filter.element(this.showMoreBy)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.showMoreBy)); return this.filter.element(this.showMoreBy).click(); } clickShowLessButton() { - Util.waitUntilElementIsVisible(this.filter.element(this.showLessBy)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.showLessBy)); return this.filter.element(this.showLessBy).click(); } diff --git a/e2e/pages/adf/content-services/search/components/search-radio.ts b/e2e/pages/adf/content-services/search/components/search-radio.ts index 251980bfd3..b72300ba3a 100644 --- a/e2e/pages/adf/content-services/search/components/search-radio.ts +++ b/e2e/pages/adf/content-services/search/components/search-radio.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../../../util/util'; import { element, by, browser } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchRadioPage { @@ -30,12 +30,12 @@ export class SearchRadioPage { checkFilterRadioButtonIsDisplayed(filterName) { const filterType = element(by.css('mat-radio-button[data-automation-id="search-radio-' + filterName + '"]')); - return Util.waitUntilElementIsVisible(filterType); + return BrowserVisibility.waitUntilElementIsVisible(filterType); } checkFilterRadioButtonIsChecked(filterName) { const selectedFilterType = element(by.css('mat-radio-button[data-automation-id="search-radio-' + filterName + '"][class*="checked"]')); - return Util.waitUntilElementIsVisible(selectedFilterType); + return BrowserVisibility.waitUntilElementIsVisible(selectedFilterType); } clickFilterRadioButton(filterName) { @@ -48,28 +48,28 @@ export class SearchRadioPage { } checkShowMoreButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.showMoreButton); + return BrowserVisibility.waitUntilElementIsVisible(this.showMoreButton); } checkShowLessButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.showLessButton); + return BrowserVisibility.waitUntilElementIsVisible(this.showLessButton); } checkShowMoreButtonIsNotDisplayed() { - return Util.waitUntilElementIsNotVisible(this.showMoreButton); + return BrowserVisibility.waitUntilElementIsNotVisible(this.showMoreButton); } checkShowLessButtonIsNotDisplayed() { - return Util.waitUntilElementIsNotVisible(this.showLessButton); + return BrowserVisibility.waitUntilElementIsNotVisible(this.showLessButton); } clickShowMoreButton() { - Util.waitUntilElementIsVisible(this.showMoreButton); + BrowserVisibility.waitUntilElementIsVisible(this.showMoreButton); return this.showMoreButton.click(); } clickShowLessButton() { - Util.waitUntilElementIsVisible(this.showLessButton); + BrowserVisibility.waitUntilElementIsVisible(this.showLessButton); return this.showLessButton.click(); } diff --git a/e2e/pages/adf/content-services/search/components/search-slider.page.ts b/e2e/pages/adf/content-services/search/components/search-slider.page.ts index b1c920bc45..dfc835f612 100644 --- a/e2e/pages/adf/content-services/search/components/search-slider.page.ts +++ b/e2e/pages/adf/content-services/search/components/search-slider.page.ts @@ -16,7 +16,7 @@ */ import { browser, by } from 'protractor'; -import { Util } from '../../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchSliderPage { @@ -51,17 +51,17 @@ export class SearchSliderPage { } checkSliderIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.slider)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.slider)); return this; } checkSliderWithThumbLabelIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter.element(this.sliderWithThumbLabel)); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter.element(this.sliderWithThumbLabel)); return this; } clickClearButton() { - Util.waitUntilElementIsClickable(this.filter.element(this.clearButton)); + BrowserVisibility.waitUntilElementIsClickable(this.filter.element(this.clearButton)); this.filter.element(this.clearButton).click(); return this; } @@ -71,7 +71,7 @@ export class SearchSliderPage { } checkClearButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter.element(this.clearButton)); + BrowserVisibility.waitUntilElementIsVisible(this.filter.element(this.clearButton)); return this; } } diff --git a/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts b/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts index 3f18daea60..f00c5ebd37 100644 --- a/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts +++ b/e2e/pages/adf/content-services/search/components/search-sortingPicker.page.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { Util } from '../../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchSortingPickerPage { @@ -25,18 +25,18 @@ export class SearchSortingPickerPage { optionsDropdown = element(by.css('div[class*="mat-select-panel"]')); sortBy(sortOrder, sortType) { - Util.waitUntilElementIsClickable(this.sortingSelector); + BrowserVisibility.waitUntilElementIsClickable(this.sortingSelector); this.sortingSelector.click(); const selectedSortingOption = element(by.cssContainingText('span[class="mat-option-text"]', sortType)); - Util.waitUntilElementIsClickable(selectedSortingOption); + BrowserVisibility.waitUntilElementIsClickable(selectedSortingOption); selectedSortingOption.click(); this.sortByOrder(sortOrder); } sortByOrder(sortOrder) { - Util.waitUntilElementIsVisible(this.orderArrow); + BrowserVisibility.waitUntilElementIsVisible(this.orderArrow); this.orderArrow.getText().then((result) => { if (sortOrder === true) { if (result !== 'arrow_upward') { @@ -52,42 +52,42 @@ export class SearchSortingPickerPage { clickSortingOption(option) { const selectedSortingOption = element(by.cssContainingText('span[class="mat-option-text"]', option)); - Util.waitUntilElementIsClickable(selectedSortingOption); + BrowserVisibility.waitUntilElementIsClickable(selectedSortingOption); selectedSortingOption.click(); return this; } clickSortingSelector() { - Util.waitUntilElementIsClickable(this.sortingSelector); + BrowserVisibility.waitUntilElementIsClickable(this.sortingSelector); this.sortingSelector.click(); return this; } checkOptionIsDisplayed(option) { const optionSelector = this.optionsDropdown.element(by.cssContainingText('span[class="mat-option-text"]', option)); - Util.waitUntilElementIsVisible(optionSelector); + BrowserVisibility.waitUntilElementIsVisible(optionSelector); return this; } checkOptionIsNotDisplayed(option) { const optionSelector = this.optionsDropdown.element(by.cssContainingText('span[class="mat-option-text"]', option)); - Util.waitUntilElementIsNotVisible(optionSelector); + BrowserVisibility.waitUntilElementIsNotVisible(optionSelector); return this; } checkOptionsDropdownIsDisplayed() { - Util.waitUntilElementIsVisible(this.optionsDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.optionsDropdown); return this; } checkSortingSelectorIsDisplayed() { - Util.waitUntilElementIsVisible(this.sortingSelector); + BrowserVisibility.waitUntilElementIsVisible(this.sortingSelector); return this; } checkOrderArrowIsDownward() { const deferred = protractor.promise.defer(); - Util.waitUntilElementIsVisible(this.orderArrow); + BrowserVisibility.waitUntilElementIsVisible(this.orderArrow); this.orderArrow.getText().then((result) => { deferred.fulfill(result !== 'arrow_upward'); }); @@ -95,7 +95,7 @@ export class SearchSortingPickerPage { } checkOrderArrowIsDisplayed() { - Util.waitUntilElementIsVisible(this.orderArrow); + BrowserVisibility.waitUntilElementIsVisible(this.orderArrow); return this; } diff --git a/e2e/pages/adf/content-services/search/components/search-text.ts b/e2e/pages/adf/content-services/search/components/search-text.ts index 4250dc137a..7d209a0bb7 100644 --- a/e2e/pages/adf/content-services/search/components/search-text.ts +++ b/e2e/pages/adf/content-services/search/components/search-text.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../../../util/util'; import { protractor, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchTextPage { @@ -28,12 +28,12 @@ export class SearchTextPage { } getNamePlaceholder() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); return this.filter.element(this.inputBy).getAttribute('placeholder'); } searchByName(name) { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); this.filter.element(this.inputBy).clear(); this.filter.element(this.inputBy).sendKeys(name).sendKeys(protractor.Key.ENTER); } diff --git a/e2e/pages/adf/content-services/search/search-categories.ts b/e2e/pages/adf/content-services/search/search-categories.ts index ce726733ec..26115be40c 100644 --- a/e2e/pages/adf/content-services/search/search-categories.ts +++ b/e2e/pages/adf/content-services/search/search-categories.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { Util } from '../../../../util/util'; import { by, ElementFinder } from 'protractor'; import { SearchTextPage } from './components/search-text'; import { SearchCheckListPage } from './components/search-checkList'; @@ -23,6 +22,7 @@ import { SearchRadioPage } from './components/search-radio'; import { DateRangeFilterPage } from './components/dateRangeFilterPage'; import { NumberRangeFilterPage } from './components/numberRangeFilterPage'; import { SearchSliderPage } from './components/search-slider.page'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchCategoriesPage { @@ -51,19 +51,19 @@ export class SearchCategoriesPage { } checkFilterIsDisplayed(filter: ElementFinder) { - Util.waitUntilElementIsVisible(filter); + BrowserVisibility.waitUntilElementIsVisible(filter); return this; } clickFilter(filter: ElementFinder) { - Util.waitUntilElementIsVisible(filter); + BrowserVisibility.waitUntilElementIsVisible(filter); filter.element(by.css('mat-expansion-panel-header')).click(); return this; } clickFilterHeader(filter: ElementFinder) { const fileSizeFilterHeader = filter.element(by.css('mat-expansion-panel-header')); - Util.waitUntilElementIsClickable(fileSizeFilterHeader); + BrowserVisibility.waitUntilElementIsClickable(fileSizeFilterHeader); fileSizeFilterHeader.click(); return this; } diff --git a/e2e/pages/adf/content-services/treeViewPage.ts b/e2e/pages/adf/content-services/treeViewPage.ts index 42cb1d3ad4..a974aa78c4 100644 --- a/e2e/pages/adf/content-services/treeViewPage.ts +++ b/e2e/pages/adf/content-services/treeViewPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { element, by, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TreeViewPage { @@ -26,42 +26,42 @@ export class TreeViewPage { nodesOnPage = element.all(by.css('mat-tree-node')); checkTreeViewTitleIsDisplayed() { - return Util.waitUntilElementIsVisible(this.treeViewTitle); + return BrowserVisibility.waitUntilElementIsVisible(this.treeViewTitle); } getNodeId() { - Util.waitUntilElementIsVisible(this.nodeIdInput); + BrowserVisibility.waitUntilElementIsVisible(this.nodeIdInput); return this.nodeIdInput.getAttribute('value'); } clickNode(nodeName) { const node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"] button')); - Util.waitUntilElementIsClickable(node); + BrowserVisibility.waitUntilElementIsClickable(node); return node.click(); } checkNodeIsDisplayedAsClosed(nodeName) { const node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"][aria-expanded="false"]')); - return Util.waitUntilElementIsVisible(node); + return BrowserVisibility.waitUntilElementIsVisible(node); } checkNodeIsDisplayedAsOpen(nodeName) { const node = element(by.css('mat-tree-node[id="' + nodeName + '-tree-child-node"][aria-expanded="true"]')); - return Util.waitUntilElementIsVisible(node); + return BrowserVisibility.waitUntilElementIsVisible(node); } checkClickedNodeName(nodeName) { const clickedNode = element(by.cssContainingText('span', ' CLICKED NODE: ' + nodeName + '')); - return Util.waitUntilElementIsVisible(clickedNode); + return BrowserVisibility.waitUntilElementIsVisible(clickedNode); } checkNodeIsNotDisplayed(nodeName) { const node = element(by.id('' + nodeName + '-tree-child-node')); - return Util.waitUntilElementIsNotVisible(node); + return BrowserVisibility.waitUntilElementIsNotVisible(node); } clearNodeIdInput() { - Util.waitUntilElementIsVisible(this.nodeIdInput); + BrowserVisibility.waitUntilElementIsVisible(this.nodeIdInput); this.nodeIdInput.getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { this.nodeIdInput.sendKeys(protractor.Key.BACK_SPACE); @@ -70,11 +70,11 @@ export class TreeViewPage { } checkNoNodeIdMessageIsDisplayed() { - return Util.waitUntilElementIsVisible(this.noNodeMessage); + return BrowserVisibility.waitUntilElementIsVisible(this.noNodeMessage); } addNodeId(nodeId) { - Util.waitUntilElementIsVisible(this.nodeIdInput); + BrowserVisibility.waitUntilElementIsVisible(this.nodeIdInput); this.nodeIdInput.click(); this.nodeIdInput.clear(); this.nodeIdInput.sendKeys(nodeId + ' '); @@ -83,7 +83,7 @@ export class TreeViewPage { checkErrorMessageIsDisplayed() { const clickedNode = element(by.cssContainingText('span', 'An Error Occurred ')); - return Util.waitUntilElementIsVisible(clickedNode); + return BrowserVisibility.waitUntilElementIsVisible(clickedNode); } getTotalNodes() { diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index 3bc7aa25ba..14617c7607 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -16,22 +16,20 @@ */ import TestConfig = require('../../test.config'); -import { Util } from '../../util/util'; import { DocumentListPage } from './content-services/documentListPage'; import { CreateFolderDialog } from './dialog/createFolderDialog'; import { CreateLibraryDialog } from './dialog/createLibraryDialog'; -import { NodeActions } from '../../actions/ACS/node.actions'; import { DropActions } from '../../actions/drop.actions'; import { by, element, protractor, $$, browser } from 'protractor'; import path = require('path'); import { DateUtil } from '../../util/dateUtil'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ContentServicesPage { contentList = new DocumentListPage(element.all(by.css('adf-upload-drag-area adf-document-list')).first()); createFolderDialog = new CreateFolderDialog(); - nodeActions = new NodeActions(); createLibraryDialog = new CreateLibraryDialog(); dragAndDropAction = new DropActions(); uploadBorder = element(by.id('document-list-container')); @@ -75,6 +73,8 @@ export class ContentServicesPage { lockContentElement = element(by.css('button[data-automation-id="DOCUMENT_LIST.ACTIONS.LOCK"]')); downloadContent = element(by.css('button[data-automation-id*="DOWNLOAD"]')); siteListDropdown = element(by.css(`mat-select[data-automation-id='site-my-files-option']`)); + downloadButton = element(by.css('button[title="Download"]')); + multiSelectToggle = element(by.cssContainingText('span.mat-slide-toggle-content', ' Multiselect (with checkboxes) ')); pressContextMenuActionNamed(actionName) { const actionButton = this.checkContextActionIsVisible(actionName); @@ -83,8 +83,8 @@ export class ContentServicesPage { checkContextActionIsVisible(actionName) { const actionButton = element(by.css(`button[data-automation-id="context-${actionName}"`)); - Util.waitUntilElementIsVisible(actionButton); - Util.waitUntilElementIsClickable(actionButton); + BrowserVisibility.waitUntilElementIsVisible(actionButton); + BrowserVisibility.waitUntilElementIsClickable(actionButton); return actionButton; } @@ -104,7 +104,7 @@ export class ContentServicesPage { this.contentList.clickOnActionMenu(content); this.waitForContentOptions(); const disabledDelete = element(by.css(`button[data-automation-id*='DELETE'][disabled='true']`)); - Util.waitUntilElementIsVisible(disabledDelete); + BrowserVisibility.waitUntilElementIsVisible(disabledDelete); } deleteContent(content) { @@ -136,29 +136,29 @@ export class ContentServicesPage { } waitForContentOptions() { - Util.waitUntilElementIsVisible(this.copyContentElement); - Util.waitUntilElementIsVisible(this.moveContentElement); - Util.waitUntilElementIsVisible(this.deleteContentElement); - Util.waitUntilElementIsVisible(this.downloadContent); + BrowserVisibility.waitUntilElementIsVisible(this.copyContentElement); + BrowserVisibility.waitUntilElementIsVisible(this.moveContentElement); + BrowserVisibility.waitUntilElementIsVisible(this.deleteContentElement); + BrowserVisibility.waitUntilElementIsVisible(this.downloadContent); } clickFileHyperlink(fileName) { const hyperlink = this.contentList.dataTablePage().getFileHyperlink(fileName); - Util.waitUntilElementIsClickable(hyperlink); + BrowserVisibility.waitUntilElementIsClickable(hyperlink); hyperlink.click(); return this; } checkFileHyperlinkIsEnabled(fileName) { const hyperlink = this.contentList.dataTablePage().getFileHyperlink(fileName); - Util.waitUntilElementIsVisible(hyperlink); + BrowserVisibility.waitUntilElementIsVisible(hyperlink); return this; } clickHyperlinkNavigationToggle() { const hyperlinkToggle = element(by.cssContainingText('.mat-slide-toggle-content', 'Hyperlink navigation')); - Util.waitUntilElementIsVisible(hyperlinkToggle); + BrowserVisibility.waitUntilElementIsVisible(hyperlinkToggle); hyperlinkToggle.click(); return this; } @@ -244,7 +244,7 @@ export class ContentServicesPage { } checkRecentFileToBeShowed() { - Util.waitUntilElementIsVisible(this.recentFiles); + BrowserVisibility.waitUntilElementIsVisible(this.recentFiles); } expandRecentFiles() { @@ -262,20 +262,20 @@ export class ContentServicesPage { } checkRecentFileToBeClosed() { - Util.waitUntilElementIsVisible(this.recentFilesClosed); + BrowserVisibility.waitUntilElementIsVisible(this.recentFilesClosed); } checkRecentFileToBeOpened() { - Util.waitUntilElementIsVisible(this.recentFilesExpanded); + BrowserVisibility.waitUntilElementIsVisible(this.recentFilesExpanded); } async getRecentFileIcon() { - await Util.waitUntilElementIsVisible(this.recentFileIcon); + await BrowserVisibility.waitUntilElementIsVisible(this.recentFileIcon); return this.recentFileIcon.getText(); } checkAcsContainer() { - Util.waitUntilElementIsVisible(this.uploadBorder); + BrowserVisibility.waitUntilElementIsVisible(this.uploadBorder); return this; } @@ -290,8 +290,8 @@ export class ContentServicesPage { } clickOnContentServices() { - Util.waitUntilElementIsVisible(this.contentServices); - Util.waitUntilElementIsClickable(this.contentServices); + BrowserVisibility.waitUntilElementIsVisible(this.contentServices); + BrowserVisibility.waitUntilElementIsClickable(this.contentServices); this.contentServices.click(); } @@ -301,7 +301,7 @@ export class ContentServicesPage { currentFolderName() { const deferred = protractor.promise.defer(); - Util.waitUntilElementIsVisible(this.currentFolder); + BrowserVisibility.waitUntilElementIsVisible(this.currentFolder); this.currentFolder.getText().then(function (result) { deferred.fulfill(result); }); @@ -373,13 +373,13 @@ export class ContentServicesPage { } clickOnCreateNewFolder() { - Util.waitUntilElementIsVisible(this.createFolderButton); + BrowserVisibility.waitUntilElementIsVisible(this.createFolderButton); this.createFolderButton.click(); return this; } openCreateLibraryDialog() { - Util.waitUntilElementIsVisible(this.createLibraryButton); + BrowserVisibility.waitUntilElementIsVisible(this.createLibraryButton); this.createLibraryButton.click(); this.createLibraryDialog.waitForDialogToOpen(); return this.createLibraryDialog; @@ -411,54 +411,54 @@ export class ContentServicesPage { } getActiveBreadcrumb() { - Util.waitUntilElementIsVisible(this.activeBreadcrumb); + BrowserVisibility.waitUntilElementIsVisible(this.activeBreadcrumb); return this.activeBreadcrumb.getAttribute('title'); } uploadFile(fileLocation) { this.checkUploadButton(); - Util.waitUntilElementIsVisible(this.uploadFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadFileButton); this.uploadFileButton.sendKeys(path.resolve(path.join(TestConfig.main.rootPath, fileLocation))); this.checkUploadButton(); return this; } uploadMultipleFile(files) { - Util.waitUntilElementIsVisible(this.uploadMultipleFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadMultipleFileButton); let allFiles = path.resolve(path.join(TestConfig.main.rootPath, files[0])); for (let i = 1; i < files.length; i++) { allFiles = allFiles + '\n' + path.resolve(path.join(TestConfig.main.rootPath, files[i])); } this.uploadMultipleFileButton.sendKeys(allFiles); - Util.waitUntilElementIsVisible(this.uploadMultipleFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadMultipleFileButton); return this; } uploadFolder(folder) { - Util.waitUntilElementIsVisible(this.uploadFolderButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadFolderButton); this.uploadFolderButton.sendKeys(path.resolve(path.join(TestConfig.main.rootPath, folder))); - Util.waitUntilElementIsVisible(this.uploadFolderButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadFolderButton); return this; } getSingleFileButtonTooltip() { - Util.waitUntilElementIsVisible(this.uploadFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadFileButton); return this.uploadFileButton.getAttribute('title'); } getMultipleFileButtonTooltip() { - Util.waitUntilElementIsVisible(this.uploadMultipleFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadMultipleFileButton); return this.uploadMultipleFileButton.getAttribute('title'); } getFolderButtonTooltip() { - Util.waitUntilElementIsVisible(this.uploadFolderButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadFolderButton); return this.uploadFolderButton.getAttribute('title'); } checkUploadButton() { - Util.waitUntilElementIsVisible(this.uploadFileButton); - Util.waitUntilElementIsClickable(this.uploadFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadFileButton); + BrowserVisibility.waitUntilElementIsClickable(this.uploadFileButton); return this; } @@ -467,7 +467,7 @@ export class ContentServicesPage { } getErrorMessage() { - Util.waitUntilElementIsVisible(this.errorSnackBar); + BrowserVisibility.waitUntilElementIsVisible(this.errorSnackBar); const deferred = protractor.promise.defer(); this.errorSnackBar.getText().then(function (text) { deferred.fulfill(text); @@ -477,60 +477,60 @@ export class ContentServicesPage { enableInfiniteScrolling() { const infiniteScrollButton = element(by.cssContainingText('.mat-slide-toggle-content', 'Enable Infinite Scrolling')); - Util.waitUntilElementIsVisible(infiniteScrollButton); + BrowserVisibility.waitUntilElementIsVisible(infiniteScrollButton); infiniteScrollButton.click(); return this; } enableCustomPermissionMessage() { const customPermissionMessage = element(by.cssContainingText('.mat-slide-toggle-content', 'Enable custom permission message')); - Util.waitUntilElementIsVisible(customPermissionMessage); + BrowserVisibility.waitUntilElementIsVisible(customPermissionMessage); customPermissionMessage.click(); return this; } enableMediumTimeFormat() { const mediumTimeFormat = element(by.css('#enableMediumTimeFormat')); - Util.waitUntilElementIsVisible(mediumTimeFormat); + BrowserVisibility.waitUntilElementIsVisible(mediumTimeFormat); mediumTimeFormat.click(); return this; } enableThumbnails() { const thumbnailSlide = element(by.id('adf-thumbnails-upload-switch')); - Util.waitUntilElementIsVisible(thumbnailSlide); + BrowserVisibility.waitUntilElementIsVisible(thumbnailSlide); thumbnailSlide.click(); return this; } checkPaginationIsNotDisplayed() { - Util.waitUntilElementIsVisible(this.emptyPagination); + BrowserVisibility.waitUntilElementIsVisible(this.emptyPagination); } getDocumentListRowNumber() { const documentList = element(by.css('adf-upload-drag-area adf-document-list')); - Util.waitUntilElementIsVisible(documentList); + BrowserVisibility.waitUntilElementIsVisible(documentList); return $$('adf-upload-drag-area adf-document-list .adf-datatable-row').count(); } checkColumnNameHeader() { - Util.waitUntilElementIsVisible(this.nameHeader); + BrowserVisibility.waitUntilElementIsVisible(this.nameHeader); } checkColumnSizeHeader() { - Util.waitUntilElementIsVisible(this.sizeHeader); + BrowserVisibility.waitUntilElementIsVisible(this.sizeHeader); } checkColumnCreatedByHeader() { - Util.waitUntilElementIsVisible(this.createdByHeader); + BrowserVisibility.waitUntilElementIsVisible(this.createdByHeader); } checkColumnCreatedHeader() { - Util.waitUntilElementIsVisible(this.createdHeader); + BrowserVisibility.waitUntilElementIsVisible(this.createdHeader); } checkDragAndDropDIsDisplayed() { - Util.waitUntilElementIsVisible(this.dragAndDrop); + BrowserVisibility.waitUntilElementIsVisible(this.dragAndDrop); } dragAndDropFile(file) { @@ -545,7 +545,7 @@ export class ContentServicesPage { checkLockIsDisplayedForElement(name) { const lockButton = element(by.css(`div.adf-datatable-cell[data-automation-id="${name}"] button`)); - Util.waitUntilElementIsVisible(lockButton); + BrowserVisibility.waitUntilElementIsVisible(lockButton); } getColumnValueForRow(file, columnName) { @@ -554,31 +554,31 @@ export class ContentServicesPage { async getStyleValueForRowText(rowName, styleName) { const row = element(by.css(`div.adf-datatable-cell[data-automation-id="${rowName}"] span.adf-datatable-cell-value[title="${rowName}"]`)); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return row.getCssValue(styleName); } checkSpinnerIsShowed() { - Util.waitUntilElementIsPresent(this.documentListSpinner); + BrowserVisibility.waitUntilElementIsPresent(this.documentListSpinner); } checkEmptyFolderTextToBe(text) { - Util.waitUntilElementIsVisible(this.emptyFolder); + BrowserVisibility.waitUntilElementIsVisible(this.emptyFolder); expect(this.emptyFolder.getText()).toContain(text); } checkEmptyFolderImageUrlToContain(url) { - Util.waitUntilElementIsVisible(this.emptyFolderImage); + BrowserVisibility.waitUntilElementIsVisible(this.emptyFolderImage); expect(this.emptyFolderImage.getAttribute('src')).toContain(url); } checkEmptyRecentFileIsDisplayed() { - Util.waitUntilElementIsVisible(this.emptyRecent); + BrowserVisibility.waitUntilElementIsVisible(this.emptyRecent); } checkIconForRowIsDisplayed(fileName) { const iconRow = element(by.css(`.adf-document-list-container div.adf-datatable-cell[data-automation-id="${fileName}"] img`)); - Util.waitUntilElementIsVisible(iconRow); + BrowserVisibility.waitUntilElementIsVisible(iconRow); return iconRow; } @@ -588,7 +588,7 @@ export class ContentServicesPage { } checkGridViewButtonIsVisible() { - Util.waitUntilElementIsVisible(this.gridViewButton); + BrowserVisibility.waitUntilElementIsVisible(this.gridViewButton); } clickGridViewButton() { @@ -597,7 +597,7 @@ export class ContentServicesPage { } checkCardViewContainerIsDisplayed() { - Util.waitUntilElementIsVisible(this.cardViewContainer); + BrowserVisibility.waitUntilElementIsVisible(this.cardViewContainer); } getCardElementShowedInPage() { @@ -613,7 +613,7 @@ export class ContentServicesPage { checkDocumentCardPropertyIsShowed(elementName, propertyName) { const elementProperty = element(by.css(`.adf-document-list-container div.adf-datatable-cell[data-automation-id="${elementName}"][title="${propertyName}"]`)); - Util.waitUntilElementIsVisible(elementProperty); + BrowserVisibility.waitUntilElementIsVisible(elementProperty); } getAttributeValueForElement(elementName, propertyName) { @@ -623,20 +623,20 @@ export class ContentServicesPage { checkMenuIsShowedForElementIndex(elementIndex) { const elementMenu = element(by.css(`button[data-automation-id="action_menu_${elementIndex}"]`)); - Util.waitUntilElementIsVisible(elementMenu); + BrowserVisibility.waitUntilElementIsVisible(elementMenu); } navigateToCardFolder(folderName) { const folderCard = element(by.css(`.adf-document-list-container div.adf-image-table-cell.adf-datatable-cell[data-automation-id="${folderName}"]`)); folderCard.click(); const folderSelected = element(by.css(`.adf-datatable-row.adf-is-selected div[data-automation-id="${folderName}"].adf-datatable-cell--image`)); - Util.waitUntilElementIsVisible(folderSelected); + BrowserVisibility.waitUntilElementIsVisible(folderSelected); browser.actions().sendKeys(protractor.Key.ENTER).perform(); } getGridViewSortingDropdown() { const sortingDropdown = element(by.css('mat-select[data-automation-id="grid-view-sorting"]')); - Util.waitUntilElementIsVisible(sortingDropdown); + BrowserVisibility.waitUntilElementIsVisible(sortingDropdown); return sortingDropdown; } @@ -644,37 +644,48 @@ export class ContentServicesPage { const dropdownSorting = this.getGridViewSortingDropdown(); dropdownSorting.click(); const optionToClick = element(by.css(`mat-option[data-automation-id="grid-view-sorting-${sortingChosen}"]`)); - Util.waitUntilElementIsPresent(optionToClick); + BrowserVisibility.waitUntilElementIsPresent(optionToClick); optionToClick.click(); } checkRowIsDisplayed(rowName) { - const row = this.contentList.dataTablePage().getRow('Display name', rowName); - Util.waitUntilElementIsVisible(row); + const row = this.contentList.dataTablePage().getRowElement('Display name', rowName); + BrowserVisibility.waitUntilElementIsVisible(row); } typeIntoNodeSelectorSearchField(text) { - Util.waitUntilElementIsVisible(this.searchInputElement); + BrowserVisibility.waitUntilElementIsVisible(this.searchInputElement); this.searchInputElement.sendKeys(text); } clickContentNodeSelectorResult(name) { const resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[data-automation-id="${name}"`)).first(); - Util.waitUntilElementIsVisible(resultElement); + BrowserVisibility.waitUntilElementIsVisible(resultElement); resultElement.click(); } clickCopyButton() { - Util.waitUntilElementIsClickable(this.copyButton); + BrowserVisibility.waitUntilElementIsClickable(this.copyButton); this.copyButton.click(); } clickShareButton() { - Util.waitUntilElementIsClickable(this.shareNodeButton); + BrowserVisibility.waitUntilElementIsClickable(this.shareNodeButton); this.shareNodeButton.click(); } checkSelectedSiteIsDisplayed(siteName) { - Util.waitUntilElementIsVisible(this.siteListDropdown.element(by.cssContainingText('.mat-select-value-text span', siteName))); + BrowserVisibility.waitUntilElementIsVisible(this.siteListDropdown.element(by.cssContainingText('.mat-select-value-text span', siteName))); } + + clickDownloadButton() { + BrowserVisibility.waitUntilElementIsClickable(this.downloadButton); + this.downloadButton.click(); + } + + clickMultiSelectToggle() { + BrowserVisibility.waitUntilElementIsClickable(this.multiSelectToggle); + this.multiSelectToggle.click(); + } + } diff --git a/e2e/pages/adf/core/headerPage.ts b/e2e/pages/adf/core/headerPage.ts index a94613a0c8..02677e5a2f 100644 --- a/e2e/pages/adf/core/headerPage.ts +++ b/e2e/pages/adf/core/headerPage.ts @@ -17,7 +17,7 @@ import { element, by, protractor } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class HeaderPage { @@ -34,24 +34,24 @@ export class HeaderPage { sideBarPositionLeft = element(by.css('mat-sidenav.mat-drawer.mat-sidenav')); checkShowMenuCheckBoxIsDisplayed() { - return Util.waitUntilElementIsVisible(this.checkBox); + return BrowserVisibility.waitUntilElementIsVisible(this.checkBox); } checkChooseHeaderColourIsDisplayed() { - return Util.waitUntilElementIsVisible(this.headerColor); + return BrowserVisibility.waitUntilElementIsVisible(this.headerColor); } checkChangeTitleIsDisplayed() { - return Util.waitUntilElementIsVisible(this.titleInput); + return BrowserVisibility.waitUntilElementIsVisible(this.titleInput); } checkChangeUrlPathIsDisplayed() { - return Util.waitUntilElementIsVisible(this.iconInput); + return BrowserVisibility.waitUntilElementIsVisible(this.iconInput); } clickShowMenuButton() { const checkBox = element.all(by.css('mat-checkbox')); - Util.waitUntilElementIsVisible(checkBox); + BrowserVisibility.waitUntilElementIsVisible(checkBox); return checkBox.get(0).click(); } @@ -62,11 +62,11 @@ export class HeaderPage { checkAppTitle(name) { const title = element(by.cssContainingText('.adf-app-title', name)); - return Util.waitUntilElementIsVisible(title); + return BrowserVisibility.waitUntilElementIsVisible(title); } addTitle(title) { - Util.waitUntilElementIsVisible(this.titleInput); + BrowserVisibility.waitUntilElementIsVisible(this.titleInput); this.titleInput.click(); this.titleInput.sendKeys(title); this.titleInput.sendKeys(protractor.Key.ENTER); @@ -74,66 +74,66 @@ export class HeaderPage { checkIconIsDisplayed(url) { const icon = element(by.css('img[src="' + url + '"]')); - Util.waitUntilElementIsVisible(icon); + BrowserVisibility.waitUntilElementIsVisible(icon); } addIcon(url) { - Util.waitUntilElementIsVisible(this.iconInput); + BrowserVisibility.waitUntilElementIsVisible(this.iconInput); this.iconInput.click(); this.iconInput.sendKeys(url); this.iconInput.sendKeys(protractor.Key.ENTER); } checkHexColorInputIsDisplayed() { - return Util.waitUntilElementIsVisible(this.hexColorInput); + return BrowserVisibility.waitUntilElementIsVisible(this.hexColorInput); } checkLogoHyperlinkInputIsDisplayed() { - return Util.waitUntilElementIsVisible(this.logoHyperlinkInput); + return BrowserVisibility.waitUntilElementIsVisible(this.logoHyperlinkInput); } checkLogoTooltipInputIsDisplayed() { - return Util.waitUntilElementIsVisible(this.logoTooltipInput); + return BrowserVisibility.waitUntilElementIsVisible(this.logoTooltipInput); } addHexCodeColor(hexCode) { - Util.waitUntilElementIsVisible(this.hexColorInput); + BrowserVisibility.waitUntilElementIsVisible(this.hexColorInput); this.hexColorInput.click(); this.hexColorInput.sendKeys(hexCode); return this.hexColorInput.sendKeys(protractor.Key.ENTER); } addLogoHyperlink(hyperlink) { - Util.waitUntilElementIsVisible(this.logoHyperlinkInput); - Util.waitUntilElementIsClickable(this.logoHyperlinkInput); + BrowserVisibility.waitUntilElementIsVisible(this.logoHyperlinkInput); + BrowserVisibility.waitUntilElementIsClickable(this.logoHyperlinkInput); this.logoHyperlinkInput.click(); this.logoHyperlinkInput.sendKeys(hyperlink); return this.logoHyperlinkInput.sendKeys(protractor.Key.ENTER); } addLogoTooltip(tooltip) { - Util.waitUntilElementIsVisible(this.logoTooltipInput); + BrowserVisibility.waitUntilElementIsVisible(this.logoTooltipInput); this.logoTooltipInput.click(); this.logoTooltipInput.sendKeys(tooltip); return this.logoTooltipInput.sendKeys(protractor.Key.ENTER); } sideBarPositionStart() { - Util.waitUntilElementIsVisible(this.positionStart); + BrowserVisibility.waitUntilElementIsVisible(this.positionStart); return this.positionStart.click(); } sideBarPositionEnd() { - Util.waitUntilElementIsVisible(this.positionEnd); + BrowserVisibility.waitUntilElementIsVisible(this.positionEnd); return this.positionEnd.click(); } checkSidebarPositionStart() { - return Util.waitUntilElementIsVisible(this.sideBarPositionLeft); + return BrowserVisibility.waitUntilElementIsVisible(this.sideBarPositionLeft); } checkSidebarPositionEnd() { - return Util.waitUntilElementIsVisible(this.sideBarPositionRight); + return BrowserVisibility.waitUntilElementIsVisible(this.sideBarPositionRight); } } diff --git a/e2e/pages/adf/core/infinitePaginationPage.ts b/e2e/pages/adf/core/infinitePaginationPage.ts index cb03fce84e..e82868c92c 100644 --- a/e2e/pages/adf/core/infinitePaginationPage.ts +++ b/e2e/pages/adf/core/infinitePaginationPage.ts @@ -18,7 +18,7 @@ import { element, by } from 'protractor'; import { ElementFinder } from 'protractor/built/element'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class InfinitePaginationPage { @@ -31,18 +31,18 @@ export class InfinitePaginationPage { } clickLoadMoreButton() { - Util.waitUntilElementIsVisible(this.loadMoreButton); - Util.waitUntilElementIsClickable(this.loadMoreButton); + BrowserVisibility.waitUntilElementIsVisible(this.loadMoreButton); + BrowserVisibility.waitUntilElementIsClickable(this.loadMoreButton); this.loadMoreButton.click(); return this; } checkLoadMoreButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.loadMoreButton); + return BrowserVisibility.waitUntilElementIsVisible(this.loadMoreButton); } checkLoadMoreButtonIsNotDisplayed() { - return Util.waitUntilElementIsNotOnPage(this.loadMoreButton); + return BrowserVisibility.waitUntilElementIsNotOnPage(this.loadMoreButton); } } diff --git a/e2e/pages/adf/dataTableComponentPage.ts b/e2e/pages/adf/dataTableComponentPage.ts index 286c761142..f072c9b179 100644 --- a/e2e/pages/adf/dataTableComponentPage.ts +++ b/e2e/pages/adf/dataTableComponentPage.ts @@ -16,8 +16,8 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { Util } from '../../util/util'; import { ElementFinder, ElementArrayFinder } from 'protractor/built/element'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DataTableComponentPage { @@ -45,40 +45,41 @@ export class DataTableComponentPage { } checkAllRowsButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.selectAll); + BrowserVisibility.waitUntilElementIsVisible(this.selectAll); return this; } checkAllRows() { - Util.waitUntilElementIsClickable(this.selectAll).then(() => { + BrowserVisibility.waitUntilElementIsVisible(this.selectAll); + BrowserVisibility.waitUntilElementIsClickable(this.selectAll).then(() => { this.selectAll.click(); - Util.waitUntilElementIsVisible(this.selectAll.element(by.css('input[aria-checked="true"]'))); + BrowserVisibility.waitUntilElementIsVisible(this.selectAll.element(by.css('input[aria-checked="true"]'))); }); return this; } clickCheckbox(columnName, columnValue) { const checkbox = this.getRowCheckbox(columnName, columnValue); - Util.waitUntilElementIsClickable(checkbox); + BrowserVisibility.waitUntilElementIsClickable(checkbox); checkbox.click(); } checkRowIsNotChecked(columnName, columnValue) { - Util.waitUntilElementIsNotOnPage(this.getRowCheckbox(columnName, columnValue).element(by.css('input[aria-checked="true"]'))); + BrowserVisibility.waitUntilElementIsNotOnPage(this.getRowCheckbox(columnName, columnValue).element(by.css('input[aria-checked="true"]'))); } checkRowIsChecked(columnName, columnValue) { const rowCheckbox = this.getRowCheckbox(columnName, columnValue); - Util.waitUntilElementIsVisible(rowCheckbox.element(by.css('input[aria-checked="true"]'))); + BrowserVisibility.waitUntilElementIsVisible(rowCheckbox.element(by.css('input[aria-checked="true"]'))); } getRowCheckbox(columnName, columnValue) { - return this.getRowParentElement(columnName, columnValue) + return this.getRow(columnName, columnValue) .element(by.css('mat-checkbox')); } checkNoRowIsSelected() { - Util.waitUntilElementIsNotOnPage(this.selectedRowNumber); + BrowserVisibility.waitUntilElementIsNotOnPage(this.selectedRowNumber); } getNumberOfSelectedRows() { @@ -92,28 +93,29 @@ export class DataTableComponentPage { selectRow(columnName, columnValue) { const row = this.getRow(columnName, columnValue); - Util.waitUntilElementIsClickable(row); + BrowserVisibility.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsClickable(row); row.click(); return this; } checkRowIsSelected(columnName, columnValue) { - const selectedRow = this.getRow(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); - Util.waitUntilElementIsVisible(selectedRow); + const selectedRow = this.getRowElement(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + BrowserVisibility.waitUntilElementIsVisible(selectedRow); return this; } checkRowIsNotSelected(columnName, columnValue) { - const selectedRow = this.getRow(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); - Util.waitUntilElementIsNotOnPage(selectedRow); + const selectedRow = this.getRowElement(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + BrowserVisibility.waitUntilElementIsNotOnPage(selectedRow); return this; } getColumnValueForRow(identifyingColumn, identifyingValue, columnName) { - const row = this.getRow(identifyingColumn, identifyingValue).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]`)); - Util.waitUntilElementIsVisible(row); + const row = this.getRow(identifyingColumn, identifyingValue); + BrowserVisibility.waitUntilElementIsVisible(row); const rowColumn = row.element(by.css(`div[title="${columnName}"] span`)); - Util.waitUntilElementIsVisible(rowColumn); + BrowserVisibility.waitUntilElementIsVisible(rowColumn); return rowColumn.getText(); } @@ -127,7 +129,7 @@ export class DataTableComponentPage { checkListIsSorted(sortOrder, locator) { const deferred = protractor.promise.defer(); const column = element.all(by.css(`div[title='${locator}'] span`)); - Util.waitUntilElementIsVisible(column.first()); + BrowserVisibility.waitUntilElementIsVisible(column.first()); const initialList = []; column.each(function (currentElement) { currentElement.getText().then(function (text) { @@ -147,11 +149,11 @@ export class DataTableComponentPage { rightClickOnRow(columnName, columnValue) { const row = this.getRow(columnName, columnValue); browser.actions().click(row, protractor.Button.RIGHT).perform(); - Util.waitUntilElementIsVisible(element(by.id('adf-context-menu-content'))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id('adf-context-menu-content'))); } getTooltip(columnName, columnValue) { - return this.getRow(columnName, columnValue).getAttribute('title'); + return this.getRowElement(columnName, columnValue).getAttribute('title'); } getFileHyperlink(filename) { @@ -164,21 +166,21 @@ export class DataTableComponentPage { async getAllRowsColumnValues(column) { const columnLocator = by.css("adf-datatable div[class*='adf-datatable-body'] div[class*='adf-datatable-row'] div[title='" + column + "'] span"); - Util.waitUntilElementIsVisible(element.all(columnLocator).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(columnLocator).first()); const initialList: any = await element.all(columnLocator).getText(); return initialList.filter((el) => el); } async getRowsWithSameColumnValues(columnName, columnValue) { const columnLocator = by.css(`div[title='${columnName}'] div[data-automation-id="text_${columnValue}"] span`); - Util.waitUntilElementIsVisible(this.rootElement.all(columnLocator).first()); + BrowserVisibility.waitUntilElementIsVisible(this.rootElement.all(columnLocator).first()); return this.rootElement.all(columnLocator).getText(); } doubleClickRow(columnName, columnValue) { const row = this.getRow(columnName, columnValue); - Util.waitUntilElementIsVisible(row); - Util.waitUntilElementIsClickable(row); + BrowserVisibility.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsClickable(row); row.click(); this.checkRowIsSelected(columnName, columnValue); browser.actions().sendKeys(protractor.Key.ENTER).perform(); @@ -186,7 +188,7 @@ export class DataTableComponentPage { } waitForTableBody() { - Util.waitUntilElementIsVisible(this.tableBody); + BrowserVisibility.waitUntilElementIsVisible(this.tableBody); } getFirstElementDetail(detail) { @@ -200,7 +202,7 @@ export class DataTableComponentPage { sortByColumn(sortOrder, column) { const locator = by.css(`div[data-automation-id="auto_id_${column}"]`); - Util.waitUntilElementIsVisible(element(locator)); + BrowserVisibility.waitUntilElementIsVisible(element(locator)); return element(locator).getAttribute('class').then(function (result) { if (sortOrder === true) { if (!result.includes('sorted-asc')) { @@ -223,49 +225,49 @@ export class DataTableComponentPage { checkContentIsDisplayed(columnName, columnValue) { const row = this.getRow(columnName, columnValue); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return this; } checkContentIsNotDisplayed(columnName, columnValue) { - const row = this.getRow(columnName, columnValue); - Util.waitUntilElementIsNotOnPage(row); + const row = this.getRowElement(columnName, columnValue); + BrowserVisibility.waitUntilElementIsNotOnPage(row); return this; } contentInPosition(position) { - Util.waitUntilElementIsVisible(this.contents); + BrowserVisibility.waitUntilElementIsVisible(this.contents); return this.contents.get(position - 1).getText(); } - getRowParentElement(columnName, columnValue) { + getRow(columnName, columnValue) { const row = this.rootElement.all(by.css(`div[title="${columnName}"] div[data-automation-id="text_${columnValue}"]`)).first() .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]`)); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return row; } - getRow(columnName, columnValue) { + getRowElement(columnName, columnValue) { return this.rootElement.all(by.css(`div[title="${columnName}"] div[data-automation-id="text_${columnValue}"] span`)).first(); } checkSpinnerIsDisplayed() { - Util.waitUntilElementIsPresent(this.spinner); + BrowserVisibility.waitUntilElementIsPresent(this.spinner); return this; } checkSpinnerIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.spinner); + BrowserVisibility.waitUntilElementIsNotOnPage(this.spinner); return this; } tableIsLoaded() { - Util.waitUntilElementIsVisible(this.rootElement); + BrowserVisibility.waitUntilElementIsVisible(this.rootElement); return this; } checkColumnIsDisplayed(column) { - Util.waitUntilElementIsVisible(element(by.css(`div[data-automation-id="auto_id_entry.${column}"]`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`div[data-automation-id="auto_id_entry.${column}"]`))); return this; } @@ -278,6 +280,6 @@ export class DataTableComponentPage { } getCellByRowAndColumn(rowColumn, rowContent, columnName) { - return this.getRowParentElement(rowColumn, rowContent).element(by.css(`div[title='${columnName}']`)); + return this.getRow(rowColumn, rowContent).element(by.css(`div[title='${columnName}']`)); } } diff --git a/e2e/pages/adf/demo-shell/aboutPage.ts b/e2e/pages/adf/demo-shell/aboutPage.ts index 3b506fed58..8e025dc9e7 100644 --- a/e2e/pages/adf/demo-shell/aboutPage.ts +++ b/e2e/pages/adf/demo-shell/aboutPage.ts @@ -16,13 +16,13 @@ */ import { by, element } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class AboutPage { monacoPlugin = element(by.cssContainingText('mat-row > mat-cell', 'monaco plugin')); checkMonacoPluginIsDisplayed() { - return Util.waitUntilElementIsVisible(this.monacoPlugin); + return BrowserVisibility.waitUntilElementIsVisible(this.monacoPlugin); } } diff --git a/e2e/pages/adf/demo-shell/customSourcesPage.ts b/e2e/pages/adf/demo-shell/customSourcesPage.ts index af5cfac0f2..fbaf9e7393 100644 --- a/e2e/pages/adf/demo-shell/customSourcesPage.ts +++ b/e2e/pages/adf/demo-shell/customSourcesPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; import { DataTableComponentPage } from '../dataTableComponentPage'; import { NavigationBarPage } from '../navigationBarPage'; @@ -49,7 +49,7 @@ export class CustomSources { } waitForToolbarToBeVisible() { - Util.waitUntilElementIsVisible(this.toolbar); + BrowserVisibility.waitUntilElementIsVisible(this.toolbar); return this; } @@ -72,7 +72,7 @@ export class CustomSources { getStatusCell(rowName) { const cell = this.dataTable.getCellByRowAndColumn('Name', rowName, column.status); - Util.waitUntilElementIsVisible(cell); + BrowserVisibility.waitUntilElementIsVisible(cell); return cell.getText(); } diff --git a/e2e/pages/adf/demo-shell/dataTablePage.ts b/e2e/pages/adf/demo-shell/dataTablePage.ts index 4495491fc8..a6ff81141d 100644 --- a/e2e/pages/adf/demo-shell/dataTablePage.ts +++ b/e2e/pages/adf/demo-shell/dataTablePage.ts @@ -17,7 +17,7 @@ import { browser, by, element, protractor } from 'protractor'; import { DataTableComponentPage } from '../dataTableComponentPage'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DataTablePage { @@ -41,54 +41,54 @@ export class DataTablePage { } addRow() { - Util.waitUntilElementIsVisible(this.addRowElement); + BrowserVisibility.waitUntilElementIsVisible(this.addRowElement); this.addRowElement.click(); } replaceRows(id) { - const rowID = this.dataTable.getRow('Id', id); - Util.waitUntilElementIsVisible(rowID); + const rowID = this.dataTable.getRowElement('Id', id); + BrowserVisibility.waitUntilElementIsVisible(rowID); this.replaceRowsElement.click(); - Util.waitUntilElementIsNotVisible(rowID); + BrowserVisibility.waitUntilElementIsNotVisible(rowID); } replaceColumns() { - Util.waitUntilElementIsVisible(this.replaceColumnsElement); + BrowserVisibility.waitUntilElementIsVisible(this.replaceColumnsElement); this.replaceColumnsElement.click(); - Util.waitUntilElementIsNotOnPage(this.createdOnColumn); + BrowserVisibility.waitUntilElementIsNotOnPage(this.createdOnColumn); } clickMultiSelect() { - Util.waitUntilElementIsVisible(this.multiSelect); + BrowserVisibility.waitUntilElementIsVisible(this.multiSelect); this.multiSelect.click(); } clickReset() { - Util.waitUntilElementIsVisible(this.reset); + BrowserVisibility.waitUntilElementIsVisible(this.reset); this.reset.click(); } checkRowIsNotSelected(rowNumber) { - const isRowSelected = this.dataTable.getRow('Id', rowNumber) + const isRowSelected = this.dataTable.getRowElement('Id', rowNumber) .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row custom-row-style ng-star-inserted is-selected')]`)); - Util.waitUntilElementIsNotOnPage(isRowSelected); + BrowserVisibility.waitUntilElementIsNotOnPage(isRowSelected); } checkNoRowIsSelected() { - Util.waitUntilElementIsNotOnPage(this.selectedRowNumber); + BrowserVisibility.waitUntilElementIsNotOnPage(this.selectedRowNumber); } checkAllRows() { - Util.waitUntilElementIsVisible(this.selectAll); + BrowserVisibility.waitUntilElementIsVisible(this.selectAll); this.selectAll.click(); } checkRowIsChecked(rowNumber) { - Util.waitUntilElementIsVisible(this.getRowCheckbox(rowNumber)); + BrowserVisibility.waitUntilElementIsVisible(this.getRowCheckbox(rowNumber)); } checkRowIsNotChecked(rowNumber) { - Util.waitUntilElementIsNotOnPage(this.getRowCheckbox(rowNumber)); + BrowserVisibility.waitUntilElementIsNotOnPage(this.getRowCheckbox(rowNumber)); } getNumberOfSelectedRows() { @@ -96,32 +96,32 @@ export class DataTablePage { } clickCheckbox(rowNumber) { - const checkbox = this.dataTable.getRow('Id', rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); - Util.waitUntilElementIsVisible(checkbox); + const checkbox = this.dataTable.getRowElement('Id', rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); + BrowserVisibility.waitUntilElementIsVisible(checkbox); checkbox.click(); } selectRow(rowNumber) { - const locator = this.dataTable.getRow('Id', rowNumber); - Util.waitUntilElementIsVisible(locator); - Util.waitUntilElementIsClickable(locator); + const locator = this.dataTable.getRowElement('Id', rowNumber); + BrowserVisibility.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsClickable(locator); locator.click(); return this; } selectRowWithKeyboard(rowNumber) { - const row = this.dataTable.getRow('Id', rowNumber); + const row = this.dataTable.getRowElement('Id', rowNumber); browser.actions().sendKeys(protractor.Key.COMMAND).click(row).perform(); } selectSelectionMode(selectionMode) { const selectMode = element(by.cssContainingText(`span[class='mat-option-text']`, selectionMode)); this.selectionButton.click(); - Util.waitUntilElementIsVisible(this.selectionDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.selectionDropDown); selectMode.click(); } getRowCheckbox(rowNumber) { - return this.dataTable.getRow('Id', rowNumber).element(by.xpath(`ancestor::div/div/mat-checkbox[contains(@class, 'mat-checkbox-checked')]`)); + return this.dataTable.getRowElement('Id', rowNumber).element(by.xpath(`ancestor::div/div/mat-checkbox[contains(@class, 'mat-checkbox-checked')]`)); } } diff --git a/e2e/pages/adf/demo-shell/logoutPage.ts b/e2e/pages/adf/demo-shell/logoutPage.ts index 385109c538..8849568fad 100644 --- a/e2e/pages/adf/demo-shell/logoutPage.ts +++ b/e2e/pages/adf/demo-shell/logoutPage.ts @@ -16,13 +16,13 @@ */ import { by, element } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class LogoutPage { logoutSection = element(by.css('div[data-automation-id="adf-logout-section"]')); checkLogoutSectionIsDisplayed() { - return Util.waitUntilElementIsVisible(this.logoutSection); + return BrowserVisibility.waitUntilElementIsVisible(this.logoutSection); } } diff --git a/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts b/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts index 200c52196d..a7ff4a75df 100644 --- a/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts @@ -16,7 +16,7 @@ */ import { by, element, protractor } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class PeopleGroupCloudComponentPage { @@ -34,39 +34,39 @@ export class PeopleGroupCloudComponentPage { groupCloudComponentTitle = element(by.cssContainingText('mat-card-title', 'Groups Cloud Component')); checkPeopleCloudComponentTitleIsDisplayed() { - Util.waitUntilElementIsVisible(this.peopleCloudComponentTitle); + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudComponentTitle); return this; } checkGroupsCloudComponentTitleIsDisplayed() { - Util.waitUntilElementIsVisible(this.groupCloudComponentTitle); + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudComponentTitle); return this; } clickPeopleCloudMultipleSelection() { - Util.waitUntilElementIsVisible(this.peopleCloudMultipleSelection); + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudMultipleSelection); this.peopleCloudMultipleSelection.click(); } clickPeopleCloudFilterRole() { - Util.waitUntilElementIsVisible(this.peopleCloudFilterRole); + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudFilterRole); this.peopleCloudFilterRole.click(); } clickGroupCloudFilterRole() { - Util.waitUntilElementIsVisible(this.groupCloudFilterRole); + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudFilterRole); this.groupCloudFilterRole.click(); } enterPeopleRoles(roles) { - Util.waitUntilElementIsVisible(this.peopleRoleInput); + BrowserVisibility.waitUntilElementIsVisible(this.peopleRoleInput); this.peopleRoleInput.clear(); this.peopleRoleInput.sendKeys(roles); return this; } clearField(locator) { - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); locator.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { locator.sendKeys(protractor.Key.BACK_SPACE); @@ -75,12 +75,12 @@ export class PeopleGroupCloudComponentPage { } clickGroupCloudMultipleSelection() { - Util.waitUntilElementIsVisible(this.groupCloudMultipleSelection); + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudMultipleSelection); this.groupCloudMultipleSelection.click(); } enterGroupRoles(roles) { - Util.waitUntilElementIsVisible(this.groupRoleInput); + BrowserVisibility.waitUntilElementIsVisible(this.groupRoleInput); this.groupRoleInput.clear(); this.groupRoleInput.sendKeys(roles); return this; diff --git a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts index 12b9ff150d..a84fb3444d 100644 --- a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts @@ -15,12 +15,11 @@ * limitations under the License. */ -import { Util } from '../../../../util/util'; - import { ProcessFiltersCloudComponent } from '../../process-cloud/processFiltersCloudComponent'; import { ProcessListCloudComponent } from '../../process-cloud/processListCloudComponent'; import { EditProcessFilterCloudComponent } from '../../process-cloud/editProcessFilterCloudComponent'; import { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ProcessCloudDemoPage { @@ -69,12 +68,12 @@ export class ProcessCloudDemoPage { } getActiveFilterName() { - Util.waitUntilElementIsVisible(this.activeFilter); + BrowserVisibility.waitUntilElementIsVisible(this.activeFilter); return this.activeFilter.getText(); } clickOnProcessFilters() { - Util.waitUntilElementIsVisible(this.processFilters); + BrowserVisibility.waitUntilElementIsVisible(this.processFilters); return this.processFilters.click(); } @@ -87,17 +86,17 @@ export class ProcessCloudDemoPage { } createButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.createButton); + BrowserVisibility.waitUntilElementIsVisible(this.createButton); return this; } newProcessButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.newProcessButton); + BrowserVisibility.waitUntilElementIsVisible(this.newProcessButton); return this; } clickOnCreateButton() { - Util.waitUntilElementIsClickable(this.createButton); + BrowserVisibility.waitUntilElementIsClickable(this.createButton); this.createButton.click(); return this; } diff --git a/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts index bfa5395f37..99b7e97d31 100644 --- a/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { DataTableComponentPage } from '../../dataTableComponentPage'; import { element, by, protractor } from 'protractor'; @@ -36,25 +36,25 @@ export class ProcessListDemoPage { } selectSorting(sort) { - Util.waitUntilElementIsVisible(this.stateSelector); + BrowserVisibility.waitUntilElementIsVisible(this.stateSelector); this.sortSelector.click(); const sortLocator = element(by.cssContainingText('mat-option span', sort)); - Util.waitUntilElementIsVisible(sortLocator); + BrowserVisibility.waitUntilElementIsVisible(sortLocator); sortLocator.click(); return this; } selectStateFilter(state) { - Util.waitUntilElementIsVisible(this.stateSelector); + BrowserVisibility.waitUntilElementIsVisible(this.stateSelector); this.stateSelector.click(); const stateLocator = element(by.cssContainingText('mat-option span', state)); - Util.waitUntilElementIsVisible(stateLocator); + BrowserVisibility.waitUntilElementIsVisible(stateLocator); stateLocator.click(); return this; } addAppId(appId) { - Util.waitUntilElementIsVisible(this.appIdInput); + BrowserVisibility.waitUntilElementIsVisible(this.appIdInput); this.appIdInput.click(); this.appIdInput.sendKeys(protractor.Key.ENTER); this.appIdInput.clear(); @@ -62,17 +62,17 @@ export class ProcessListDemoPage { } clickResetButton() { - Util.waitUntilElementIsVisible(this.resetButton); + BrowserVisibility.waitUntilElementIsVisible(this.resetButton); return this.resetButton.click(); } checkErrorMessageIsDisplayed(error) { const errorMessage = element(by.cssContainingText('mat-error', error)); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); } checkNoProcessFoundIsDisplayed() { - return Util.waitUntilElementIsVisible(this.emptyProcessContent); + return BrowserVisibility.waitUntilElementIsVisible(this.emptyProcessContent); } checkProcessIsNotDisplayed(processName) { @@ -84,34 +84,34 @@ export class ProcessListDemoPage { } checkAppIdFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.appIdInput); + BrowserVisibility.waitUntilElementIsVisible(this.appIdInput); return this; } checkProcessInstanceIdFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.processInstanceInput); + BrowserVisibility.waitUntilElementIsVisible(this.processInstanceInput); return this; } checkStateFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.stateSelector); + BrowserVisibility.waitUntilElementIsVisible(this.stateSelector); return this; } checkSortFieldIsDisplayed() { - Util.waitUntilElementIsVisible(this.sortSelector); + BrowserVisibility.waitUntilElementIsVisible(this.sortSelector); return this; } addProcessDefinitionId(procDefinitionId) { - Util.waitUntilElementIsVisible(this.processDefinitionInput); + BrowserVisibility.waitUntilElementIsVisible(this.processDefinitionInput); this.processDefinitionInput.click(); this.processDefinitionInput.clear(); return this.processDefinitionInput.sendKeys(procDefinitionId); } addProcessInstanceId(procInstanceId) { - Util.waitUntilElementIsVisible(this.processInstanceInput); + BrowserVisibility.waitUntilElementIsVisible(this.processInstanceInput); this.processInstanceInput.click(); this.processInstanceInput.clear(); return this.processInstanceInput.sendKeys(procInstanceId); diff --git a/e2e/pages/adf/demo-shell/process-services/taskFiltersDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/taskFiltersDemoPage.ts index 0458c398e5..1959b60b1e 100644 --- a/e2e/pages/adf/demo-shell/process-services/taskFiltersDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/taskFiltersDemoPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; import { TaskFiltersPage } from '../../process-services/taskFiltersPage'; @@ -53,7 +53,7 @@ export class TaskFiltersDemoPage { } checkActiveFilterActive () { - Util.waitUntilElementIsVisible(this.activeFilter); + BrowserVisibility.waitUntilElementIsVisible(this.activeFilter); return this.activeFilter.getText(); } diff --git a/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts index 4be5673fa7..095b122b82 100644 --- a/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { Util } from '../../../../util/util'; import { TasksListPage } from '../../process-services/tasksListPage'; import { PaginationPage } from '../../paginationPage'; import { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TaskListDemoPage { @@ -49,130 +49,130 @@ export class TaskListDemoPage { } typeAppId(input) { - Util.waitUntilElementIsVisible(this.appId); + BrowserVisibility.waitUntilElementIsVisible(this.appId); this.clearText(this.appId); this.appId.sendKeys(input); return this; } clickAppId() { - Util.waitUntilElementIsVisible(this.appId); + BrowserVisibility.waitUntilElementIsVisible(this.appId); this.appId.click(); return this; } getAppId() { - Util.waitUntilElementIsVisible(this.appId); + BrowserVisibility.waitUntilElementIsVisible(this.appId); return this.appId.getAttribute('value'); } typeTaskId(input) { - Util.waitUntilElementIsVisible(this.taskId); + BrowserVisibility.waitUntilElementIsVisible(this.taskId); this.clearText(this.taskId); this.taskId.sendKeys(input); return this; } getTaskId() { - Util.waitUntilElementIsVisible(this.taskId); + BrowserVisibility.waitUntilElementIsVisible(this.taskId); return this.taskId.getAttribute('value'); } typeTaskName(input) { - Util.waitUntilElementIsVisible(this.taskName); + BrowserVisibility.waitUntilElementIsVisible(this.taskName); this.clearText(this.taskName); this.taskName.sendKeys(input); return this; } getTaskName() { - Util.waitUntilElementIsVisible(this.taskName); + BrowserVisibility.waitUntilElementIsVisible(this.taskName); return this.taskName.getAttribute('value'); } typeItemsPerPage(input) { - Util.waitUntilElementIsVisible(this.itemsPerPage); + BrowserVisibility.waitUntilElementIsVisible(this.itemsPerPage); this.clearText(this.itemsPerPage); this.itemsPerPage.sendKeys(input); return this; } getItemsPerPage() { - Util.waitUntilElementIsVisible(this.itemsPerPage); + BrowserVisibility.waitUntilElementIsVisible(this.itemsPerPage); return this.itemsPerPage.getAttribute('value'); } typeProcessDefinitionId(input) { - Util.waitUntilElementIsVisible(this.processDefinitionId); + BrowserVisibility.waitUntilElementIsVisible(this.processDefinitionId); this.clearText(this.processDefinitionId); this.processDefinitionId.sendKeys(input); return this; } getProcessDefinitionId() { - Util.waitUntilElementIsVisible(this.processInstanceId); + BrowserVisibility.waitUntilElementIsVisible(this.processInstanceId); return this.processInstanceId.getAttribute('value'); } typeProcessInstanceId(input) { - Util.waitUntilElementIsVisible(this.processInstanceId); + BrowserVisibility.waitUntilElementIsVisible(this.processInstanceId); this.clearText(this.processInstanceId); this.processInstanceId.sendKeys(input); return this; } getProcessInstanceId() { - Util.waitUntilElementIsVisible(this.processInstanceId); + BrowserVisibility.waitUntilElementIsVisible(this.processInstanceId); return this.processInstanceId.getAttribute('value'); } getItemsPerPageFieldErrorMessage() { - Util.waitUntilElementIsVisible(this.itemsPerPageForm); + BrowserVisibility.waitUntilElementIsVisible(this.itemsPerPageForm); const errorMessage = this.itemsPerPageForm.element(by.css('mat-error')); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } typePage(input) { - Util.waitUntilElementIsVisible(this.page); + BrowserVisibility.waitUntilElementIsVisible(this.page); this.clearText(this.page); this.page.sendKeys(input); return this; } getPage() { - Util.waitUntilElementIsVisible(this.page); + BrowserVisibility.waitUntilElementIsVisible(this.page); return this.page.getAttribute('value'); } getPageFieldErrorMessage() { - Util.waitUntilElementIsVisible(this.pageForm); + BrowserVisibility.waitUntilElementIsVisible(this.pageForm); const errorMessage = this.pageForm.element(by.css('mat-error')); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } typeDueAfter(input) { - Util.waitUntilElementIsVisible(this.dueAfter); + BrowserVisibility.waitUntilElementIsVisible(this.dueAfter); this.clearText(this.dueAfter); this.dueAfter.sendKeys(input); return this; } typeDueBefore(input) { - Util.waitUntilElementIsVisible(this.dueBefore); + BrowserVisibility.waitUntilElementIsVisible(this.dueBefore); this.clearText(this.dueBefore); this.dueBefore.sendKeys(input); return this; } clearText(input) { - Util.waitUntilElementIsVisible(input); + BrowserVisibility.waitUntilElementIsVisible(input); return input.clear(); } clickResetButton() { - Util.waitUntilElementIsVisible(this.resetButton); + BrowserVisibility.waitUntilElementIsVisible(this.resetButton); this.resetButton.click(); } @@ -180,32 +180,32 @@ export class TaskListDemoPage { this.clickOnSortDropDownArrow(); const sortElement = element.all(by.cssContainingText('mat-option span', sort)).first(); - Util.waitUntilElementIsClickable(sortElement); - Util.waitUntilElementIsVisible(sortElement); + BrowserVisibility.waitUntilElementIsClickable(sortElement); + BrowserVisibility.waitUntilElementIsVisible(sortElement); sortElement.click(); return this; } clickOnSortDropDownArrow() { - Util.waitUntilElementIsVisible(this.sortDropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(this.sortDropDownArrow); this.sortDropDownArrow.click(); - Util.waitUntilElementIsVisible(this.sortSelector); + BrowserVisibility.waitUntilElementIsVisible(this.sortSelector); } selectState(state) { this.clickOnStateDropDownArrow(); const stateElement = element.all(by.cssContainingText('mat-option span', state)).first(); - Util.waitUntilElementIsClickable(stateElement); - Util.waitUntilElementIsVisible(stateElement); + BrowserVisibility.waitUntilElementIsClickable(stateElement); + BrowserVisibility.waitUntilElementIsVisible(stateElement); stateElement.click(); return this; } clickOnStateDropDownArrow() { - Util.waitUntilElementIsVisible(this.stateDropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(this.stateDropDownArrow); this.stateDropDownArrow.click(); - Util.waitUntilElementIsVisible(this.stateSelector); + BrowserVisibility.waitUntilElementIsVisible(this.stateSelector); } getAllProcessDefinitionIds() { diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index 5bcf7cff62..51b591a609 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -15,14 +15,13 @@ * limitations under the License. */ -import { Util } from '../../../../util/util'; - import { TaskFiltersCloudComponent } from '../../process-cloud/taskFiltersCloudComponent'; import { TaskListCloudComponent } from '../../process-cloud/taskListCloudComponent'; import { EditTaskFilterCloudComponent } from '../../process-cloud/editTaskFilterCloudComponent'; import { FormControllersPage } from '../../material/formControllersPage'; import { element, by, browser } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TasksCloudDemoPage { @@ -81,7 +80,7 @@ export class TasksCloudDemoPage { } getActiveFilterName() { - Util.waitUntilElementIsVisible(this.activeFilter); + BrowserVisibility.waitUntilElementIsVisible(this.activeFilter); return this.activeFilter.getText(); } @@ -94,7 +93,7 @@ export class TasksCloudDemoPage { } clickOnTaskFilters() { - Util.waitUntilElementIsVisible(this.taskFilters); + BrowserVisibility.waitUntilElementIsVisible(this.taskFilters); return this.taskFilters.click(); } @@ -107,17 +106,17 @@ export class TasksCloudDemoPage { } createButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.createButton); + BrowserVisibility.waitUntilElementIsVisible(this.createButton); return this; } newTaskButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.newTaskButton); + BrowserVisibility.waitUntilElementIsVisible(this.newTaskButton); return this; } clickOnCreateButton() { - Util.waitUntilElementIsClickable(this.createButton); + BrowserVisibility.waitUntilElementIsClickable(this.createButton); this.createButton.click(); return this; } @@ -129,9 +128,9 @@ export class TasksCloudDemoPage { clickSettingsButton() { this.settingsButton.click(); browser.driver.sleep(400); - Util.waitUntilElementIsVisible(this.multiSelectionToggle); - Util.waitUntilElementIsVisible(this.modeDropDownArrow); - Util.waitUntilElementIsClickable(this.modeDropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(this.multiSelectionToggle); + BrowserVisibility.waitUntilElementIsVisible(this.modeDropDownArrow); + BrowserVisibility.waitUntilElementIsClickable(this.modeDropDownArrow); return this; } @@ -145,16 +144,16 @@ export class TasksCloudDemoPage { this.clickOnSelectionModeDropDownArrow(); const modeElement = element.all(by.cssContainingText('mat-option span', mode)).first(); - Util.waitUntilElementIsClickable(modeElement); - Util.waitUntilElementIsVisible(modeElement); + BrowserVisibility.waitUntilElementIsClickable(modeElement); + BrowserVisibility.waitUntilElementIsVisible(modeElement); modeElement.click(); return this; } clickOnSelectionModeDropDownArrow() { - Util.waitUntilElementIsVisible(this.modeDropDownArrow); - Util.waitUntilElementIsClickable(this.modeDropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(this.modeDropDownArrow); + BrowserVisibility.waitUntilElementIsClickable(this.modeDropDownArrow); this.modeDropDownArrow.click(); - Util.waitUntilElementIsVisible(this.modeSelector); + BrowserVisibility.waitUntilElementIsVisible(this.modeSelector); } } diff --git a/e2e/pages/adf/dialog/createFolderDialog.ts b/e2e/pages/adf/dialog/createFolderDialog.ts index f3e8650cae..77f44e7db8 100644 --- a/e2e/pages/adf/dialog/createFolderDialog.ts +++ b/e2e/pages/adf/dialog/createFolderDialog.ts @@ -16,7 +16,7 @@ */ import { browser, by, element } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class CreateFolderDialog { folderNameField = element(by.id('adf-folder-name-input')); @@ -25,13 +25,13 @@ export class CreateFolderDialog { cancelButton = element(by.id('adf-folder-cancel-button')); clickOnCreateButton() { - Util.waitUntilElementIsVisible(this.createButton); + BrowserVisibility.waitUntilElementIsVisible(this.createButton); this.createButton.click(); return this; } checkCreateBtnIsDisabled() { - Util.waitUntilElementIsVisible(this.createButton); + BrowserVisibility.waitUntilElementIsVisible(this.createButton); expect(this.createButton.getAttribute('disabled')).toEqual('true'); return this; } @@ -42,13 +42,13 @@ export class CreateFolderDialog { } clickOnCancelButton() { - Util.waitUntilElementIsVisible(this.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); this.cancelButton.click(); return this; } addFolderName(folderName) { - Util.waitUntilElementIsVisible(this.folderNameField); + BrowserVisibility.waitUntilElementIsVisible(this.folderNameField); this.folderNameField.clear(); this.folderNameField.sendKeys(folderName); browser.driver.sleep(500); @@ -56,7 +56,7 @@ export class CreateFolderDialog { } addFolderDescription(folderDescription) { - Util.waitUntilElementIsVisible(this.folderDescriptionField); + BrowserVisibility.waitUntilElementIsVisible(this.folderDescriptionField); this.folderDescriptionField.clear(); this.folderDescriptionField.sendKeys(folderDescription); return this; diff --git a/e2e/pages/adf/dialog/createLibraryDialog.ts b/e2e/pages/adf/dialog/createLibraryDialog.ts index 6d567f5bb2..3d55746b8f 100644 --- a/e2e/pages/adf/dialog/createLibraryDialog.ts +++ b/e2e/pages/adf/dialog/createLibraryDialog.ts @@ -16,7 +16,7 @@ */ import { by, element, browser, protractor } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class CreateLibraryDialog { libraryDialog = element(by.css('[role="dialog"]')); @@ -35,17 +35,17 @@ export class CreateLibraryDialog { getSelectedRadio() { const radio = element(by.css('.mat-radio-button[class*="checked"]')); - Util.waitUntilElementIsVisible(radio); + BrowserVisibility.waitUntilElementIsVisible(radio); return radio.getText(); } waitForDialogToOpen() { - Util.waitUntilElementIsPresent(this.libraryDialog); + BrowserVisibility.waitUntilElementIsPresent(this.libraryDialog); return this; } waitForDialogToClose() { - Util.waitUntilElementIsNotOnPage(this.libraryDialog); + BrowserVisibility.waitUntilElementIsNotOnPage(this.libraryDialog); return this; } @@ -66,21 +66,21 @@ export class CreateLibraryDialog { } getErrorMessage() { - Util.waitUntilElementIsVisible(this.errorMessage); + BrowserVisibility.waitUntilElementIsVisible(this.errorMessage); return this.errorMessage.getText(); } getErrorMessages(position) { - Util.waitUntilElementIsVisible(this.errorMessages); + BrowserVisibility.waitUntilElementIsVisible(this.errorMessages); return this.errorMessages.get(position).getText(); } waitForLibraryNameHint() { - Util.waitUntilElementIsVisible(this.libraryNameHint); + BrowserVisibility.waitUntilElementIsVisible(this.libraryNameHint); return this; } getLibraryNameHint() { - Util.waitUntilElementIsVisible(this.libraryNameHint); + BrowserVisibility.waitUntilElementIsVisible(this.libraryNameHint); return this.libraryNameHint.getText(); } @@ -117,7 +117,7 @@ export class CreateLibraryDialog { } clickCreate() { - Util.waitUntilElementIsClickable(this.createButton); + BrowserVisibility.waitUntilElementIsClickable(this.createButton); this.createButton.click(); } diff --git a/e2e/pages/adf/dialog/editProcessFilterDialog.ts b/e2e/pages/adf/dialog/editProcessFilterDialog.ts index 077f2f0513..34eae03507 100644 --- a/e2e/pages/adf/dialog/editProcessFilterDialog.ts +++ b/e2e/pages/adf/dialog/editProcessFilterDialog.ts @@ -16,7 +16,7 @@ */ import { by, element, protractor } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class EditProcessFilterDialog { @@ -28,32 +28,32 @@ export class EditProcessFilterDialog { clickOnSaveButton() { const saveButton = this.componentElement.element(this.saveButtonLocator); - Util.waitUntilElementIsVisible(saveButton); + BrowserVisibility.waitUntilElementIsVisible(saveButton); saveButton.click(); - Util.waitUntilElementIsNotVisible(this.componentElement); + BrowserVisibility.waitUntilElementIsNotVisible(this.componentElement); return this; } checkSaveButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.componentElement.element(this.saveButtonLocator)); + BrowserVisibility.waitUntilElementIsVisible(this.componentElement.element(this.saveButtonLocator)); return this.componentElement.element(this.saveButtonLocator).isEnabled(); } clickOnCancelButton() { const cancelButton = this.componentElement.element(this.cancelButtonLocator); - Util.waitUntilElementIsVisible(cancelButton); + BrowserVisibility.waitUntilElementIsVisible(cancelButton); cancelButton.click(); - Util.waitUntilElementIsNotVisible(this.componentElement); + BrowserVisibility.waitUntilElementIsNotVisible(this.componentElement); return this; } checkCancelButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.componentElement.element(this.cancelButtonLocator)); + BrowserVisibility.waitUntilElementIsVisible(this.componentElement.element(this.cancelButtonLocator)); return this.componentElement.element(this.cancelButtonLocator).isEnabled(); } getFilterName() { - Util.waitUntilElementIsVisible(this.filterNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.filterNameInput); return this.filterNameInput.getAttribute('value'); } @@ -64,7 +64,7 @@ export class EditProcessFilterDialog { } clearFilterName() { - Util.waitUntilElementIsVisible(this.filterNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.filterNameInput); this.filterNameInput.click(); this.filterNameInput.getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { @@ -75,7 +75,7 @@ export class EditProcessFilterDialog { } getTitle() { - Util.waitUntilElementIsVisible(this.title); + BrowserVisibility.waitUntilElementIsVisible(this.title); return this.title.getText(); } diff --git a/e2e/pages/adf/dialog/editTaskFilterDialog.ts b/e2e/pages/adf/dialog/editTaskFilterDialog.ts index 0599e79cd0..e4b91fb3c9 100644 --- a/e2e/pages/adf/dialog/editTaskFilterDialog.ts +++ b/e2e/pages/adf/dialog/editTaskFilterDialog.ts @@ -16,7 +16,7 @@ */ import { by, element, protractor } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class EditTaskFilterDialog { @@ -28,32 +28,32 @@ export class EditTaskFilterDialog { clickOnSaveButton() { const saveButton = this.componentElement.element(this.saveButtonLocator); - Util.waitUntilElementIsVisible(saveButton); + BrowserVisibility.waitUntilElementIsVisible(saveButton); saveButton.click(); - Util.waitUntilElementIsNotVisible(this.componentElement); + BrowserVisibility.waitUntilElementIsNotVisible(this.componentElement); return this; } checkSaveButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.componentElement.element(this.saveButtonLocator)); + BrowserVisibility.waitUntilElementIsVisible(this.componentElement.element(this.saveButtonLocator)); return this.componentElement.element(this.saveButtonLocator).isEnabled(); } clickOnCancelButton() { const cancelButton = this.componentElement.element(this.cancelButtonLocator); - Util.waitUntilElementIsVisible(cancelButton); + BrowserVisibility.waitUntilElementIsVisible(cancelButton); cancelButton.click(); - Util.waitUntilElementIsNotVisible(this.componentElement); + BrowserVisibility.waitUntilElementIsNotVisible(this.componentElement); return this; } checkCancelButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.componentElement.element(this.cancelButtonLocator)); + BrowserVisibility.waitUntilElementIsVisible(this.componentElement.element(this.cancelButtonLocator)); return this.componentElement.element(this.cancelButtonLocator).isEnabled(); } getFilterName() { - Util.waitUntilElementIsVisible(this.filterNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.filterNameInput); return this.filterNameInput.getAttribute('value'); } @@ -64,7 +64,7 @@ export class EditTaskFilterDialog { } clearFilterName() { - Util.waitUntilElementIsVisible(this.filterNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.filterNameInput); this.filterNameInput.click(); this.filterNameInput.getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { @@ -75,7 +75,7 @@ export class EditTaskFilterDialog { } getTitle() { - Util.waitUntilElementIsVisible(this.title); + BrowserVisibility.waitUntilElementIsVisible(this.title); return this.title.getText(); } diff --git a/e2e/pages/adf/dialog/searchDialog.ts b/e2e/pages/adf/dialog/searchDialog.ts index 857ab4a0f9..0cd7d597d1 100644 --- a/e2e/pages/adf/dialog/searchDialog.ts +++ b/e2e/pages/adf/dialog/searchDialog.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { browser, by, element, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchDialog { @@ -35,47 +35,47 @@ export class SearchDialog { } clickOnSearchIcon() { - Util.waitUntilElementIsVisible(this.searchIcon); + BrowserVisibility.waitUntilElementIsVisible(this.searchIcon); this.searchIcon.click(); return this; } checkSearchIconIsVisible() { - Util.waitUntilElementIsVisible(this.searchIcon); + BrowserVisibility.waitUntilElementIsVisible(this.searchIcon); return this; } checkSearchBarIsVisible() { - Util.waitUntilElementIsVisible(this.searchBar); + BrowserVisibility.waitUntilElementIsVisible(this.searchBar); return this; } checkSearchBarIsNotVisible() { - Util.waitUntilElementIsVisible(this.searchBar); - Util.waitUntilElementIsNotVisible(this.searchBarExpanded); + BrowserVisibility.waitUntilElementIsVisible(this.searchBar); + BrowserVisibility.waitUntilElementIsNotVisible(this.searchBarExpanded); return this; } checkNoResultMessageIsDisplayed() { browser.driver.sleep(500); - Util.waitUntilElementIsVisible(this.noResultMessage); + BrowserVisibility.waitUntilElementIsVisible(this.noResultMessage); return this; } checkNoResultMessageIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.noResultMessage); + BrowserVisibility.waitUntilElementIsNotOnPage(this.noResultMessage); return this; } enterText(text) { - Util.waitUntilElementIsVisible(this.searchBar); + BrowserVisibility.waitUntilElementIsVisible(this.searchBar); browser.executeScript(`document.querySelector("adf-search-control input").click();`); this.searchBar.sendKeys(text); return this; } enterTextAndPressEnter(text) { - Util.waitUntilElementIsVisible(this.searchBar); + BrowserVisibility.waitUntilElementIsVisible(this.searchBar); browser.executeScript(`document.querySelector("adf-search-control input").click();`); this.searchBar.sendKeys(text); this.searchBar.sendKeys(protractor.Key.ENTER); @@ -83,8 +83,8 @@ export class SearchDialog { } resultTableContainsRow(name) { - Util.waitUntilElementIsVisible(this.searchDialog); - Util.waitUntilElementIsVisible(this.getRowByRowName(name)); + BrowserVisibility.waitUntilElementIsVisible(this.searchDialog); + BrowserVisibility.waitUntilElementIsVisible(this.getRowByRowName(name)); return this; } @@ -111,7 +111,7 @@ export class SearchDialog { } clearText() { - Util.waitUntilElementIsVisible(this.searchBar); + BrowserVisibility.waitUntilElementIsVisible(this.searchBar); return this.searchBar.clear(); } } diff --git a/e2e/pages/adf/dialog/shareDialog.ts b/e2e/pages/adf/dialog/shareDialog.ts index 21a0165bc0..3ff98bdcf9 100644 --- a/e2e/pages/adf/dialog/shareDialog.ts +++ b/e2e/pages/adf/dialog/shareDialog.ts @@ -16,8 +16,8 @@ */ import { element, by } from 'protractor'; -import { Util } from '../../../util/util'; import { FormControllersPage } from '../material/formControllersPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ShareDialog { @@ -43,7 +43,7 @@ export class ShareDialog { confirmationRemoveButton = element(by.id('adf-confirm-accept')); checkDialogIsDisplayed() { - return Util.waitUntilElementIsVisible(this.dialogTitle); + return BrowserVisibility.waitUntilElementIsVisible(this.dialogTitle); } clickUnShareFile() { @@ -51,92 +51,92 @@ export class ShareDialog { } clickConfirmationDialogCancelButton() { - Util.waitUntilElementIsVisible(this.confirmationCancelButton); + BrowserVisibility.waitUntilElementIsVisible(this.confirmationCancelButton); this.confirmationCancelButton.click(); } clickConfirmationDialogRemoveButton() { - Util.waitUntilElementIsVisible(this.confirmationRemoveButton); + BrowserVisibility.waitUntilElementIsVisible(this.confirmationRemoveButton); this.confirmationRemoveButton.click(); } checkShareLinkIsDisplayed() { - return Util.waitUntilElementIsVisible(this.shareLink); + return BrowserVisibility.waitUntilElementIsVisible(this.shareLink); } getShareLink() { - Util.waitUntilElementIsVisible(this.shareLink); + BrowserVisibility.waitUntilElementIsVisible(this.shareLink); return this.shareLink.getAttribute('value'); } clickCloseButton() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); return this.closeButton.click(); } clickShareLinkButton() { - Util.waitUntilElementIsVisible(this.copySharedLinkButton); + BrowserVisibility.waitUntilElementIsVisible(this.copySharedLinkButton); return this.copySharedLinkButton.click(); } shareToggleButtonIsChecked() { - Util.waitUntilElementIsPresent(this.shareToggleChecked); + BrowserVisibility.waitUntilElementIsPresent(this.shareToggleChecked); } shareToggleButtonIsDisabled() { - Util.waitUntilElementIsPresent(this.shareToggleDisabled); + BrowserVisibility.waitUntilElementIsPresent(this.shareToggleDisabled); } shareToggleButtonIsUnchecked() { - Util.waitUntilElementIsVisible(this.shareToggleUnchecked); + BrowserVisibility.waitUntilElementIsVisible(this.shareToggleUnchecked); } checkNotificationWithMessage(message) { - Util.waitUntilElementIsVisible( + BrowserVisibility.waitUntilElementIsVisible( element(by.cssContainingText('simple-snack-bar', message)) ); } waitForNotificationToClose() { - Util.waitUntilElementIsStale(element(by.css('simple-snack-bar'))); + BrowserVisibility.waitUntilElementIsStale(element(by.css('simple-snack-bar'))); } dialogIsClosed() { - Util.waitUntilElementIsStale(this.shareDialog); + BrowserVisibility.waitUntilElementIsStale(this.shareDialog); } clickDateTimePickerButton() { - Util.waitUntilElementIsVisible(this.timeDatePickerButton); + BrowserVisibility.waitUntilElementIsVisible(this.timeDatePickerButton); this.timeDatePickerButton.click(); } calendarTodayDayIsDisabled() { const today: any = this.dayPicker.element(by.css('.mat-datetimepicker-calendar-body-today')).getText(); - Util.waitUntilElementIsPresent(element(by.cssContainingText('.mat-datetimepicker-calendar-body-disabled', today))); + BrowserVisibility.waitUntilElementIsPresent(element(by.cssContainingText('.mat-datetimepicker-calendar-body-disabled', today))); } setDefaultDay() { const selector = '.mat-datetimepicker-calendar-body-cell:not(.mat-datetimepicker-calendar-body-disabled)'; - Util.waitUntilElementIsVisible(this.dayPicker); + BrowserVisibility.waitUntilElementIsVisible(this.dayPicker); const tomorrow = new Date(new Date().getTime() + 48 * 60 * 60 * 1000).getDate().toString(); this.dayPicker.element(by.cssContainingText(selector, tomorrow)).click(); } setDefaultHour() { const selector = '.mat-datetimepicker-clock-cell:not(.mat-datetimepicker-clock-cell-disabled)'; - Util.waitUntilElementIsVisible(this.clockPicker); - Util.waitUntilElementIsVisible(this.hoursPicker); + BrowserVisibility.waitUntilElementIsVisible(this.clockPicker); + BrowserVisibility.waitUntilElementIsVisible(this.hoursPicker); this.hoursPicker.all(by.css(selector)).first().click(); } setDefaultMinutes() { const selector = '.mat-datetimepicker-clock-cell:not(.mat-datetimepicker-clock-cell-disabled)'; - Util.waitUntilElementIsVisible(this.minutePicker); + BrowserVisibility.waitUntilElementIsVisible(this.minutePicker); this.minutePicker.all(by.css(selector)).first().click(); } dateTimePickerDialogIsClosed() { - Util.waitUntilElementIsStale(element(by.css('mat-datetimepicker-content'))); + BrowserVisibility.waitUntilElementIsStale(element(by.css('mat-datetimepicker-content'))); } getExpirationDate() { @@ -144,14 +144,14 @@ export class ShareDialog { } expirationDateInputHasValue(value) { - Util.waitUntilElementHasValue(this.expirationDateInput, value); + BrowserVisibility.waitUntilElementHasValue(this.expirationDateInput, value); } confirmationDialogIsDisplayed() { - return Util.waitUntilElementIsVisible(this.confirmationDialog); + return BrowserVisibility.waitUntilElementIsVisible(this.confirmationDialog); } confirmationDialogIsNotDisplayed() { - return Util.waitUntilElementIsNotVisible(this.confirmationDialog); + return BrowserVisibility.waitUntilElementIsNotVisible(this.confirmationDialog); } } diff --git a/e2e/pages/adf/dialog/uploadDialog.ts b/e2e/pages/adf/dialog/uploadDialog.ts index fdbfde438e..22ff81d9b3 100644 --- a/e2e/pages/adf/dialog/uploadDialog.ts +++ b/e2e/pages/adf/dialog/uploadDialog.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { element, by, protractor, browser } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class UploadDialog { @@ -45,28 +45,28 @@ export class UploadDialog { } checkCloseButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); return this; } dialogIsDisplayed() { - Util.waitUntilElementIsVisible(this.dialog); + BrowserVisibility.waitUntilElementIsVisible(this.dialog); return this; } dialogIsMinimized() { - Util.waitUntilElementIsVisible(this.minimizedDialog); + BrowserVisibility.waitUntilElementIsVisible(this.minimizedDialog); return this; } dialogIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.dialog); + BrowserVisibility.waitUntilElementIsNotOnPage(this.dialog); return this; } getRowsName(content) { const row = element.all(by.css(`div[class*='uploading-row'] span[title="${content}"]`)).first(); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return row; } @@ -75,12 +75,12 @@ export class UploadDialog { } fileIsUploaded(content) { - Util.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.uploadedStatusIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.uploadedStatusIcon)); return this; } fileIsError(content) { - Util.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.errorStatusIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.errorStatusIcon)); return this; } @@ -92,29 +92,29 @@ export class UploadDialog { } fileIsNotDisplayedInDialog(content) { - Util.waitUntilElementIsNotVisible(element(by.css(`div[class*='uploading-row'] span[title="${content}"]`))); + BrowserVisibility.waitUntilElementIsNotVisible(element(by.css(`div[class*='uploading-row'] span[title="${content}"]`))); return this; } cancelUploads() { - Util.waitUntilElementIsVisible(this.cancelUploadsElement); + BrowserVisibility.waitUntilElementIsVisible(this.cancelUploadsElement); this.cancelUploadsElement.click(); return this; } fileIsCancelled(content) { - Util.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.cancelledStatusIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.cancelledStatusIcon)); return this; } removeUploadedFile(content) { - Util.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.uploadedStatusIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.getRowByRowName(content).element(this.uploadedStatusIcon)); this.getRowByRowName(content).element(this.uploadedStatusIcon).click(); return this; } getTitleText() { - Util.waitUntilElementIsVisible(this.title); + BrowserVisibility.waitUntilElementIsVisible(this.title); const deferred = protractor.promise.defer(); this.title.getText().then((text) => { deferred.fulfill(text); @@ -123,7 +123,7 @@ export class UploadDialog { } getConfirmationDialogTitleText() { - Util.waitUntilElementIsVisible(this.canUploadConfirmationTitle); + BrowserVisibility.waitUntilElementIsVisible(this.canUploadConfirmationTitle); const deferred = protractor.promise.defer(); this.canUploadConfirmationTitle.getText().then((text) => { deferred.fulfill(text); @@ -132,7 +132,7 @@ export class UploadDialog { } getConfirmationDialogDescriptionText() { - Util.waitUntilElementIsVisible(this.canUploadConfirmationDescription); + BrowserVisibility.waitUntilElementIsVisible(this.canUploadConfirmationDescription); const deferred = protractor.promise.defer(); this.canUploadConfirmationDescription.getText().then((text) => { deferred.fulfill(text); @@ -141,13 +141,13 @@ export class UploadDialog { } clickOnConfirmationDialogYesButton() { - Util.waitUntilElementIsVisible(this.confirmationDialogYesButton); + BrowserVisibility.waitUntilElementIsVisible(this.confirmationDialogYesButton); this.confirmationDialogYesButton.click(); return this; } clickOnConfirmationDialogNoButton() { - Util.waitUntilElementIsVisible(this.confirmationDialogNoButton); + BrowserVisibility.waitUntilElementIsVisible(this.confirmationDialogNoButton); this.confirmationDialogNoButton.click(); return this; } @@ -173,24 +173,24 @@ export class UploadDialog { } minimizeUploadDialog() { - Util.waitUntilElementIsVisible(this.minimizeButton); + BrowserVisibility.waitUntilElementIsVisible(this.minimizeButton); this.minimizeButton.click(); return this; } maximizeUploadDialog() { - Util.waitUntilElementIsVisible(this.maximizeButton); + BrowserVisibility.waitUntilElementIsVisible(this.maximizeButton); this.maximizeButton.click(); return this; } displayTooltip() { - Util.waitUntilElementIsVisible(element(this.errorStatusIcon)); + BrowserVisibility.waitUntilElementIsVisible(element(this.errorStatusIcon)); browser.actions().mouseMove(element(this.errorStatusIcon)).perform(); } getTooltip() { - Util.waitUntilElementIsVisible(this.errorTooltip); + BrowserVisibility.waitUntilElementIsVisible(this.errorTooltip); return this.errorTooltip.getText(); } diff --git a/e2e/pages/adf/dialog/uploadToggles.ts b/e2e/pages/adf/dialog/uploadToggles.ts index 2b6742f3be..c9f2ced0d4 100644 --- a/e2e/pages/adf/dialog/uploadToggles.ts +++ b/e2e/pages/adf/dialog/uploadToggles.ts @@ -17,8 +17,8 @@ import { FormControllersPage } from '../material/formControllersPage'; -import { Util } from '../../../util/util'; import { by, element, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class UploadToggles { @@ -49,25 +49,25 @@ export class UploadToggles { checkFolderUploadToggleIsEnabled() { const enabledToggle = element(by.css('mat-slide-toggle[id="adf-folder-upload-switch"][class*="mat-checked"]')); - Util.waitUntilElementIsVisible(enabledToggle); + BrowserVisibility.waitUntilElementIsVisible(enabledToggle); return this; } checkMultipleFileUploadToggleIsEnabled() { const enabledToggle = element(by.css('mat-slide-toggle[id="adf-multiple-upload-switch"][class*="mat-checked"]')); - Util.waitUntilElementIsVisible(enabledToggle); + BrowserVisibility.waitUntilElementIsVisible(enabledToggle); return this; } checkMaxSizeToggleIsEnabled() { const enabledToggle = element(by.css('mat-slide-toggle[id="adf-max-size-filter-upload-switch"][class*="mat-checked"]')); - Util.waitUntilElementIsVisible(enabledToggle); + BrowserVisibility.waitUntilElementIsVisible(enabledToggle); return this; } checkVersioningToggleIsEnabled() { const enabledToggle = element(by.css('mat-slide-toggle[id="adf-version-upload-switch"][class*="mat-checked"]')); - Util.waitUntilElementIsVisible(enabledToggle); + BrowserVisibility.waitUntilElementIsVisible(enabledToggle); return this; } @@ -111,7 +111,7 @@ export class UploadToggles { } addExtension(extension) { - Util.waitUntilElementIsVisible(this.extensionAcceptedField); + BrowserVisibility.waitUntilElementIsVisible(this.extensionAcceptedField); this.extensionAcceptedField.sendKeys(',' + extension); } @@ -121,9 +121,9 @@ export class UploadToggles { } clearText() { - Util.waitUntilElementIsVisible(this.maxSizeField); + BrowserVisibility.waitUntilElementIsVisible(this.maxSizeField); const deferred = protractor.promise.defer(); - this.maxSizeField.clear().then((value) => { + this.maxSizeField.clear().then(() => { this.maxSizeField.sendKeys(protractor.Key.ESCAPE); }); return deferred.promise; diff --git a/e2e/pages/adf/errorPage.ts b/e2e/pages/adf/errorPage.ts index 587f57890e..32ae2005ea 100644 --- a/e2e/pages/adf/errorPage.ts +++ b/e2e/pages/adf/errorPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; export class ErrorPage { @@ -27,31 +27,31 @@ export class ErrorPage { secondButton = element(by.id('adf-secondary-button')); clickBackButton() { - Util.waitUntilElementIsVisible(this.backButton); + BrowserVisibility.waitUntilElementIsVisible(this.backButton); this.backButton.click(); } clickSecondButton() { - Util.waitUntilElementIsVisible(this.secondButton); + BrowserVisibility.waitUntilElementIsVisible(this.secondButton); this.secondButton.click(); } checkErrorCode() { - Util.waitUntilElementIsVisible(this.errorPageCode); + BrowserVisibility.waitUntilElementIsVisible(this.errorPageCode); } getErrorCode() { - Util.waitUntilElementIsVisible(this.errorPageCode); + BrowserVisibility.waitUntilElementIsVisible(this.errorPageCode); return this.errorPageCode.getText(); } getErrorTitle() { - Util.waitUntilElementIsVisible(this.errorPageTitle); + BrowserVisibility.waitUntilElementIsVisible(this.errorPageTitle); return this.errorPageTitle.getText(); } getErrorDescription() { - Util.waitUntilElementIsVisible(this.errorPageDescription); + BrowserVisibility.waitUntilElementIsVisible(this.errorPageDescription); return this.errorPageDescription.getText(); } } diff --git a/e2e/pages/adf/filePreviewPage.ts b/e2e/pages/adf/filePreviewPage.ts index 0edef8d95a..5a08e6009e 100644 --- a/e2e/pages/adf/filePreviewPage.ts +++ b/e2e/pages/adf/filePreviewPage.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { Util } from '../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class FilePreviewPage { @@ -25,19 +25,19 @@ export class FilePreviewPage { closeButton = element(by.css('button[data-automation-id="adf-toolbar-back"]')); waitForElements() { - Util.waitUntilElementIsVisible(element(by.css(`i[id='viewer-close-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`i[id='viewer-close-button']`))); } viewFile(fileName) { - Util.waitUntilElementIsVisible(element(by.cssContainingText(`div[data-automation-id="${fileName}"]`, fileName))); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`div[data-automation-id="${fileName}"]`, fileName))); browser.actions().doubleClick(element(by.cssContainingText(`div[data-automation-id="${fileName}"]`, fileName))).perform(); this.waitForElements(); } getPDFTitleFromSearch() { const deferred = protractor.promise.defer(); - Util.waitUntilElementIsVisible(this.pdfTitleFromSearch); - Util.waitUntilElementIsVisible(this.textLayer); + BrowserVisibility.waitUntilElementIsVisible(this.pdfTitleFromSearch); + BrowserVisibility.waitUntilElementIsVisible(this.textLayer); this.pdfTitleFromSearch.getText().then((result) => { deferred.fulfill(result); }); @@ -45,36 +45,36 @@ export class FilePreviewPage { } checkCloseButton() { - Util.waitUntilElementIsVisible(element(by.css(`i[id='viewer-close-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`i[id='viewer-close-button']`))); } checkOriginalSizeButton() { - Util.waitUntilElementIsVisible(element(by.cssContainingText(`div[id='viewer-scale-page-button'] > i `, `zoom_out_map`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`div[id='viewer-scale-page-button'] > i `, `zoom_out_map`))); } checkZoomInButton() { - Util.waitUntilElementIsVisible(element(by.css(`div[id='viewer-zoom-in-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`div[id='viewer-zoom-in-button']`))); } checkZoomOutButton() { - Util.waitUntilElementIsVisible(element(by.css(`div[id='viewer-zoom-out-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`div[id='viewer-zoom-out-button']`))); } checkPreviousPageButton() { - Util.waitUntilElementIsVisible(element(by.css(`div[id='viewer-previous-page-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`div[id='viewer-previous-page-button']`))); } checkNextPageButton() { - Util.waitUntilElementIsVisible(element(by.css(`div[id='viewer-next-page-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`div[id='viewer-next-page-button']`))); } checkDownloadButton() { - Util.waitUntilElementIsVisible(element(by.css(`button[id='viewer-download-button']`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`button[id='viewer-download-button']`))); } checkCurrentPageNumber(pageNumber) { - Util.waitUntilElementIsVisible(element(by.css(`input[id='viewer-pagenumber-input'][ng-reflect-value="${pageNumber}"]`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`input[id='viewer-pagenumber-input'][ng-reflect-value="${pageNumber}"]`))); } checkText(pageNumber, text) { @@ -83,35 +83,35 @@ export class FilePreviewPage { const textLayerLoaded = element(by.css(`div[id="pageContainer${pageNumber}"] div[class='textLayer'] > div`)); const specificText = element(by.cssContainingText(`div[id="pageContainer${pageNumber}"] div[class='textLayer'] > div`, text)); - Util.waitUntilElementIsVisible(allPages); - Util.waitUntilElementIsVisible(pageLoaded); - Util.waitUntilElementIsVisible(textLayerLoaded); - Util.waitUntilElementIsVisible(specificText); + BrowserVisibility.waitUntilElementIsVisible(allPages); + BrowserVisibility.waitUntilElementIsVisible(pageLoaded); + BrowserVisibility.waitUntilElementIsVisible(textLayerLoaded); + BrowserVisibility.waitUntilElementIsVisible(specificText); } goToNextPage() { const nextPageIcon = element(by.css(`div[id='viewer-next-page-button']`)); - Util.waitUntilElementIsVisible(nextPageIcon); + BrowserVisibility.waitUntilElementIsVisible(nextPageIcon); nextPageIcon.click(); } goToPreviousPage() { const previousPageIcon = element(by.css(`div[id='viewer-previous-page-button']`)); - Util.waitUntilElementIsVisible(previousPageIcon); + BrowserVisibility.waitUntilElementIsVisible(previousPageIcon); previousPageIcon.click(); } goToPage(page) { const pageInput = element(by.css(`input[id='viewer-pagenumber-input']`)); - Util.waitUntilElementIsVisible(pageInput); + BrowserVisibility.waitUntilElementIsVisible(pageInput); pageInput.clear(); pageInput.sendKeys(page); pageInput.sendKeys(protractor.Key.ENTER); } closePreviewWithButton() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); this.closeButton.click(); } @@ -119,35 +119,35 @@ export class FilePreviewPage { const filePreview = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); - Util.waitUntilElementIsVisible(element(by.cssContainingText(`div[data-automation-id="text_${fileName}"]`, fileName))); - Util.waitUntilElementIsNotOnPage(filePreview); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText(`div[data-automation-id="text_${fileName}"]`, fileName))); + BrowserVisibility.waitUntilElementIsNotOnPage(filePreview); } clickDownload(fileName) { const downloadButton = element(by.css(`button[id='viewer-download-button']`)); - Util.waitUntilElementIsVisible(downloadButton); + BrowserVisibility.waitUntilElementIsVisible(downloadButton); downloadButton.click(); } clickZoomIn() { const zoomInButton = element(by.css(`div[id='viewer-zoom-in-button']`)); - Util.waitUntilElementIsVisible(zoomInButton); + BrowserVisibility.waitUntilElementIsVisible(zoomInButton); zoomInButton.click(); } clickZoomOut() { const zoomOutButton = element(by.css(`div[id='viewer-zoom-out-button']`)); - Util.waitUntilElementIsVisible(zoomOutButton); + BrowserVisibility.waitUntilElementIsVisible(zoomOutButton); zoomOutButton.click(); } clickActualSize() { const actualSizeButton = element(by.css(`div[id='viewer-scale-page-button']`)); - Util.waitUntilElementIsVisible(actualSizeButton); + BrowserVisibility.waitUntilElementIsVisible(actualSizeButton); actualSizeButton.click(); } @@ -167,8 +167,8 @@ export class FilePreviewPage { const canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); const textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); - Util.waitUntilElementIsVisible(canvasLayer); - Util.waitUntilElementIsVisible(textLayer); + BrowserVisibility.waitUntilElementIsVisible(canvasLayer); + BrowserVisibility.waitUntilElementIsVisible(textLayer); let actualWidth, zoomedInWidth, @@ -210,8 +210,8 @@ export class FilePreviewPage { const canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); const textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); - Util.waitUntilElementIsVisible(canvasLayer); - Util.waitUntilElementIsVisible(textLayer); + BrowserVisibility.waitUntilElementIsVisible(canvasLayer); + BrowserVisibility.waitUntilElementIsVisible(textLayer); let actualWidth, actualHeight, @@ -262,8 +262,8 @@ export class FilePreviewPage { const canvasLayer = element.all(by.css(`div[class='canvasWrapper'] > canvas`)).first(); const textLayer = element(by.css(`div[id*='pageContainer'] div[class='textLayer'] > div`)); - Util.waitUntilElementIsVisible(canvasLayer); - Util.waitUntilElementIsVisible(textLayer); + BrowserVisibility.waitUntilElementIsVisible(canvasLayer); + BrowserVisibility.waitUntilElementIsVisible(textLayer); let actualWidth; let zoomedOutWidth; diff --git a/e2e/pages/adf/lockFilePage.ts b/e2e/pages/adf/lockFilePage.ts index 98c79450e9..97ebbb2e25 100644 --- a/e2e/pages/adf/lockFilePage.ts +++ b/e2e/pages/adf/lockFilePage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class LockFilePage { @@ -27,34 +27,34 @@ export class LockFilePage { allowOwnerCheckbox = element(by.cssContainingText('mat-checkbox[class*="adf-lock-file-name"] span', ' Allow the owner to modify this file ')); checkLockFileCheckboxIsDisplayed() { - return Util.waitUntilElementIsVisible(this.lockFileCheckboxText); + return BrowserVisibility.waitUntilElementIsVisible(this.lockFileCheckboxText); } checkCancelButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.cancelButton); + return BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); } checkSaveButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.saveButton); + return BrowserVisibility.waitUntilElementIsVisible(this.saveButton); } clickCancelButton() { - Util.waitUntilElementIsClickable(this.cancelButton); + BrowserVisibility.waitUntilElementIsClickable(this.cancelButton); return this.cancelButton.click(); } clickLockFileCheckbox() { - Util.waitUntilElementIsClickable(this.lockFileCheckbox); + BrowserVisibility.waitUntilElementIsClickable(this.lockFileCheckbox); return this.lockFileCheckbox.click(); } clickSaveButton() { - Util.waitUntilElementIsClickable(this.saveButton); + BrowserVisibility.waitUntilElementIsClickable(this.saveButton); return this.saveButton.click(); } clickAllowOwnerCheckbox() { - Util.waitUntilElementIsClickable(this.allowOwnerCheckbox); + BrowserVisibility.waitUntilElementIsClickable(this.allowOwnerCheckbox); return this.allowOwnerCheckbox.click(); } } diff --git a/e2e/pages/adf/loginPage.ts b/e2e/pages/adf/loginPage.ts index 86ed418f8d..704d0d2d31 100644 --- a/e2e/pages/adf/loginPage.ts +++ b/e2e/pages/adf/loginPage.ts @@ -17,10 +17,10 @@ import { FormControllersPage } from './material/formControllersPage'; -import { Util } from '../../util/util'; import { SettingsPage } from './settingsPage'; import { browser, by, element, protractor } from 'protractor'; import TestConfig = require('../../test.config'); +import { BrowserVisibility } from '@alfresco/adf-testing'; export class LoginPage { @@ -53,26 +53,26 @@ export class LoginPage { settingsIcon = element(by.cssContainingText('a[data-automation-id="settings"] mat-icon', 'settings')); waitForElements() { - Util.waitUntilElementIsVisible(this.txtUsername); - Util.waitUntilElementIsVisible(this.txtPassword); + BrowserVisibility.waitUntilElementIsVisible(this.txtUsername); + BrowserVisibility.waitUntilElementIsVisible(this.txtPassword); return this; } enterUsername(username) { - Util.waitUntilElementIsVisible(this.txtUsername); + BrowserVisibility.waitUntilElementIsVisible(this.txtUsername); this.txtUsername.sendKeys(''); this.txtUsername.clear(); return this.txtUsername.sendKeys(username); } enterPassword(password) { - Util.waitUntilElementIsVisible(this.txtPassword); + BrowserVisibility.waitUntilElementIsVisible(this.txtPassword); this.txtPassword.clear(); return this.txtPassword.sendKeys(password); } clearUsername() { - Util.waitUntilElementIsVisible(this.txtUsername); + BrowserVisibility.waitUntilElementIsVisible(this.txtUsername); this.txtUsername.click(); this.txtUsername.getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { @@ -83,7 +83,7 @@ export class LoginPage { } clearPassword() { - Util.waitUntilElementIsVisible(this.txtPassword); + BrowserVisibility.waitUntilElementIsVisible(this.txtPassword); this.txtPassword.getAttribute('value').then((value) => { for (let i = value.length; i >= 0; i--) { this.txtPassword.sendKeys(protractor.Key.BACK_SPACE); @@ -92,53 +92,53 @@ export class LoginPage { } getUsernameTooltip() { - Util.waitUntilElementIsVisible(this.usernameTooltip); + BrowserVisibility.waitUntilElementIsVisible(this.usernameTooltip); return this.usernameTooltip.getText(); } getPasswordTooltip() { - Util.waitUntilElementIsVisible(this.passwordTooltip); + BrowserVisibility.waitUntilElementIsVisible(this.passwordTooltip); return this.passwordTooltip.getText(); } getLoginError() { - Util.waitUntilElementIsVisible(this.loginTooltip); + BrowserVisibility.waitUntilElementIsVisible(this.loginTooltip); return this.loginTooltip.getText(); } - checkLoginImgURL(url) { - Util.waitUntilElementIsVisible(this.logoImg); + checkLoginImgURL() { + BrowserVisibility.waitUntilElementIsVisible(this.logoImg); return this.logoImg.getAttribute('src'); } checkUsernameInactive() { - Util.waitUntilElementIsVisible(this.usernameInactive); + BrowserVisibility.waitUntilElementIsVisible(this.usernameInactive); } checkPasswordInactive() { - Util.waitUntilElementIsVisible(this.passwordInactive); + BrowserVisibility.waitUntilElementIsVisible(this.passwordInactive); } checkUsernameHighlighted() { this.adfLogo.click(); - Util.waitUntilElementIsVisible(this.usernameHighlighted); + BrowserVisibility.waitUntilElementIsVisible(this.usernameHighlighted); } checkPasswordHighlighted() { this.adfLogo.click(); - Util.waitUntilElementIsVisible(this.passwordHighlighted); + BrowserVisibility.waitUntilElementIsVisible(this.passwordHighlighted); } checkUsernameTooltipIsNotVisible() { - Util.waitUntilElementIsNotVisible(this.usernameTooltip); + BrowserVisibility.waitUntilElementIsNotVisible(this.usernameTooltip); } checkPasswordTooltipIsNotVisible() { - Util.waitUntilElementIsNotVisible(this.passwordTooltip); + BrowserVisibility.waitUntilElementIsNotVisible(this.passwordTooltip); } getSignInButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.signInButton); + BrowserVisibility.waitUntilElementIsVisible(this.signInButton); return this.signInButton.isEnabled(); } @@ -168,22 +168,22 @@ export class LoginPage { } clickSignInButton() { - Util.waitUntilElementIsVisible(this.signInButton); + BrowserVisibility.waitUntilElementIsVisible(this.signInButton); this.signInButton.click(); } clickSettingsIcon() { - Util.waitUntilElementIsVisible(this.settingsIcon); + BrowserVisibility.waitUntilElementIsVisible(this.settingsIcon); this.settingsIcon.click(); } showPassword() { - Util.waitUntilElementIsVisible(this.showPasswordElement); + BrowserVisibility.waitUntilElementIsVisible(this.showPasswordElement); this.showPasswordElement.click(); } hidePassword() { - Util.waitUntilElementIsVisible(this.hidePasswordElement); + BrowserVisibility.waitUntilElementIsVisible(this.hidePasswordElement); this.hidePasswordElement.click(); } @@ -192,31 +192,31 @@ export class LoginPage { } checkPasswordIsHidden() { - Util.waitUntilElementIsVisible(this.txtPassword); + BrowserVisibility.waitUntilElementIsVisible(this.txtPassword); } checkRememberIsDisplayed() { - Util.waitUntilElementIsVisible(this.rememberMe); + BrowserVisibility.waitUntilElementIsVisible(this.rememberMe); } checkRememberIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.rememberMe); + BrowserVisibility.waitUntilElementIsNotVisible(this.rememberMe); } checkNeedHelpIsDisplayed() { - Util.waitUntilElementIsVisible(this.needHelp); + BrowserVisibility.waitUntilElementIsVisible(this.needHelp); } checkNeedHelpIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.needHelp); + BrowserVisibility.waitUntilElementIsNotVisible(this.needHelp); } checkRegisterDisplayed() { - Util.waitUntilElementIsVisible(this.register); + BrowserVisibility.waitUntilElementIsVisible(this.register); } checkRegisterIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.register); + BrowserVisibility.waitUntilElementIsNotVisible(this.register); } enableFooter() { @@ -240,14 +240,14 @@ export class LoginPage { } enterSuccessRoute(route) { - Util.waitUntilElementIsVisible(this.successRouteTxt); + BrowserVisibility.waitUntilElementIsVisible(this.successRouteTxt); this.successRouteTxt.sendKeys(''); this.successRouteTxt.clear(); return this.successRouteTxt.sendKeys(route); } enterLogo(logo) { - Util.waitUntilElementIsVisible(this.logoTxt); + BrowserVisibility.waitUntilElementIsVisible(this.logoTxt); this.logoTxt.sendKeys(''); this.logoTxt.clear(); return this.logoTxt.sendKeys(logo); @@ -258,6 +258,6 @@ export class LoginPage { this.enterUsername(username); this.enterPassword(password); this.clickSignInButton(); - return Util.waitUntilElementIsVisible(this.header); + return BrowserVisibility.waitUntilElementIsVisible(this.header); } } diff --git a/e2e/pages/adf/material/datePickerPage.ts b/e2e/pages/adf/material/datePickerPage.ts index 6e0fa1c077..304c62f4e7 100644 --- a/e2e/pages/adf/material/datePickerPage.ts +++ b/e2e/pages/adf/material/datePickerPage.ts @@ -15,9 +15,9 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { element, by, browser, protractor } from 'protractor'; import { DateUtil } from '../../../util/dateUtil'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DatePickerPage { @@ -56,7 +56,7 @@ export class DatePickerPage { selectTodayDate() { this.checkDatePickerIsDisplayed(); const todayDate = element(by.css('.mat-calendar-body-today')); - Util.waitUntilElementIsClickable(todayDate); + BrowserVisibility.waitUntilElementIsClickable(todayDate); todayDate.click(); return this; } @@ -69,12 +69,12 @@ export class DatePickerPage { } checkDatePickerIsDisplayed() { - Util.waitUntilElementIsVisible(this.datePicker); + BrowserVisibility.waitUntilElementIsVisible(this.datePicker); return this; } checkDatePickerIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.datePicker); + BrowserVisibility.waitUntilElementIsNotVisible(this.datePicker); return this; } } diff --git a/e2e/pages/adf/material/formControllersPage.ts b/e2e/pages/adf/material/formControllersPage.ts index 1f74759f51..50b2ad0cce 100644 --- a/e2e/pages/adf/material/formControllersPage.ts +++ b/e2e/pages/adf/material/formControllersPage.ts @@ -15,26 +15,26 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class FormControllersPage { enableToggle(toggle) { - Util.waitUntilElementIsVisible(toggle); + BrowserVisibility.waitUntilElementIsVisible(toggle); toggle.getAttribute('class').then((check) => { if (check.indexOf('mat-checked') < 0) { - Util.waitUntilElementIsClickable(toggle.all(by.css('div')).first()); + BrowserVisibility.waitUntilElementIsClickable(toggle.all(by.css('div')).first()); toggle.all(by.css('div')).first().click(); } }); } disableToggle(toggle) { - Util.waitUntilElementIsVisible(toggle); + BrowserVisibility.waitUntilElementIsVisible(toggle); toggle.getAttribute('class').then((check) => { if (check.indexOf('mat-checked') >= 0) { - Util.waitUntilElementIsClickable(toggle.all(by.css('div')).first()); + BrowserVisibility.waitUntilElementIsClickable(toggle.all(by.css('div')).first()); toggle.all(by.css('div')).first().click(); } }); diff --git a/e2e/pages/adf/metadataViewPage.ts b/e2e/pages/adf/metadataViewPage.ts index d46de60f02..4a247f7364 100644 --- a/e2e/pages/adf/metadataViewPage.ts +++ b/e2e/pages/adf/metadataViewPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { browser, by, element, promise } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class MetadataViewPage { @@ -46,85 +46,85 @@ export class MetadataViewPage { closeButton = element(by.cssContainingText('button.mat-button span', 'Close')); getTitle(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.title); + BrowserVisibility.waitUntilElementIsVisible(this.title); return this.title.getText(); } getExpandedAspectName(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.expandedAspect); + BrowserVisibility.waitUntilElementIsVisible(this.expandedAspect); return this.expandedAspect.element(this.aspectTitle).getText(); } getName(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.name); + BrowserVisibility.waitUntilElementIsVisible(this.name); return this.name.getText(); } getCreator(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.creator); + BrowserVisibility.waitUntilElementIsVisible(this.creator); return this.creator.getText(); } getCreatedDate(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.createdDate); + BrowserVisibility.waitUntilElementIsVisible(this.createdDate); return this.createdDate.getText(); } getModifier(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.modifier); + BrowserVisibility.waitUntilElementIsVisible(this.modifier); return this.modifier.getText(); } getModifiedDate(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.modifiedDate); + BrowserVisibility.waitUntilElementIsVisible(this.modifiedDate); return this.modifiedDate.getText(); } getMimetypeName(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.mimetypeName); + BrowserVisibility.waitUntilElementIsVisible(this.mimetypeName); return this.mimetypeName.getText(); } getSize(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.size); + BrowserVisibility.waitUntilElementIsVisible(this.size); return this.size.getText(); } getDescription(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.description); + BrowserVisibility.waitUntilElementIsVisible(this.description); return this.description.getText(); } getAuthor(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.author); + BrowserVisibility.waitUntilElementIsVisible(this.author); return this.author.getText(); } getTitleProperty(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.titleProperty); + BrowserVisibility.waitUntilElementIsVisible(this.titleProperty); return this.titleProperty.getText(); } editIconIsDisplayed(): promise.Promise<boolean> { - return Util.waitUntilElementIsVisible(this.editIcon); + return BrowserVisibility.waitUntilElementIsVisible(this.editIcon); } editIconIsNotDisplayed(): promise.Promise<any> { - return Util.waitUntilElementIsNotVisible(this.editIcon); + return BrowserVisibility.waitUntilElementIsNotVisible(this.editIcon); } editIconClick(): promise.Promise<void> { - Util.waitUntilElementIsVisible(this.editIcon); + BrowserVisibility.waitUntilElementIsVisible(this.editIcon); return this.editIcon.click(); } informationButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.informationButton); - Util.waitUntilElementIsClickable(this.informationButton); + BrowserVisibility.waitUntilElementIsVisible(this.informationButton); + BrowserVisibility.waitUntilElementIsClickable(this.informationButton); } informationButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.informationButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.informationButton); } clickOnInformationButton(): MetadataViewPage { @@ -135,24 +135,24 @@ export class MetadataViewPage { } getInformationButtonText(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.informationSpan); + BrowserVisibility.waitUntilElementIsVisible(this.informationSpan); return this.informationSpan.getText(); } getInformationIconText(): promise.Promise<string> { - Util.waitUntilElementIsVisible(this.informationIcon); + BrowserVisibility.waitUntilElementIsVisible(this.informationIcon); return this.informationIcon.getText(); } clickOnPropertiesTab(): MetadataViewPage { const propertiesTab = element(by.cssContainingText(`.adf-info-drawer-layout-content div.mat-tab-labels div .mat-tab-label-content`, `Properties`)); - Util.waitUntilElementIsVisible(propertiesTab); + BrowserVisibility.waitUntilElementIsVisible(propertiesTab); propertiesTab.click(); return this; } clickRightChevron(): MetadataViewPage { - Util.waitUntilElementIsVisible(this.rightChevron); + BrowserVisibility.waitUntilElementIsVisible(this.rightChevron); this.rightChevron.click(); return this; } @@ -167,29 +167,29 @@ export class MetadataViewPage { editPropertyIconIsDisplayed(propertyName: string) { const editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(editPropertyIcon); + BrowserVisibility.waitUntilElementIsVisible(editPropertyIcon); } updatePropertyIconIsDisplayed(propertyName: string) { const updatePropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(updatePropertyIcon); + BrowserVisibility.waitUntilElementIsVisible(updatePropertyIcon); } clickUpdatePropertyIcon(propertyName: string): promise.Promise<void> { const updatePropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-update-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(updatePropertyIcon); + BrowserVisibility.waitUntilElementIsVisible(updatePropertyIcon); return updatePropertyIcon.click(); } clickClearPropertyIcon(propertyName: string): promise.Promise<void> { const clearPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(clearPropertyIcon); + BrowserVisibility.waitUntilElementIsVisible(clearPropertyIcon); return clearPropertyIcon.click(); } enterPropertyText(propertyName: string, text: string | number): MetadataViewPage { const textField = element(by.css('input[data-automation-id="card-textitem-editinput-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); textField.sendKeys(''); textField.clear(); textField.sendKeys(text); @@ -198,7 +198,7 @@ export class MetadataViewPage { enterPresetText(text: string): MetadataViewPage { const presetField = element(by.css('input[data-automation-id="adf-text-custom-preset"]')); - Util.waitUntilElementIsVisible(presetField); + BrowserVisibility.waitUntilElementIsVisible(presetField); presetField.sendKeys(''); presetField.clear(); presetField.sendKeys(text); @@ -209,7 +209,7 @@ export class MetadataViewPage { enterDescriptionText(text: string): MetadataViewPage { const textField = element(by.css('textarea[data-automation-id="card-textitem-edittextarea-properties.cm:description"]')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); textField.sendKeys(''); textField.clear(); textField.sendKeys(text); @@ -220,18 +220,18 @@ export class MetadataViewPage { const propertyType = type || 'textitem'; const textField = element(by.css('span[data-automation-id="card-' + propertyType + '-value-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); return textField.getText(); } clearPropertyIconIsDisplayed(propertyName: string) { const clearPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-reset-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(clearPropertyIcon); + BrowserVisibility.waitUntilElementIsVisible(clearPropertyIcon); } clickEditPropertyIcons(propertyName: string) { const editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); - Util.waitUntilElementIsClickable(editPropertyIcon); + BrowserVisibility.waitUntilElementIsClickable(editPropertyIcon); editPropertyIcon.click(); } @@ -242,50 +242,50 @@ export class MetadataViewPage { clickMetadataGroup(groupName: string) { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); - Util.waitUntilElementIsVisible(group); + BrowserVisibility.waitUntilElementIsVisible(group); group.click(); } checkMetadataGroupIsPresent(groupName: string): promise.Promise<boolean> { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); - return Util.waitUntilElementIsVisible(group); + return BrowserVisibility.waitUntilElementIsVisible(group); } checkMetadataGroupIsNotPresent(groupName: string): promise.Promise<any> { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"]')); - return Util.waitUntilElementIsNotVisible(group); + return BrowserVisibility.waitUntilElementIsNotVisible(group); } checkMetadataGroupIsExpand(groupName: string) { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); - Util.waitUntilElementIsVisible(group); + BrowserVisibility.waitUntilElementIsVisible(group); expect(group.getAttribute('class')).toContain('mat-expanded'); } checkMetadataGroupIsNotExpand(groupName: string) { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); - Util.waitUntilElementIsVisible(group); + BrowserVisibility.waitUntilElementIsVisible(group); expect(group.getAttribute('class')).not.toContain('mat-expanded'); } getMetadataGroupTitle(groupName: string): promise.Promise<string> { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header > span > mat-panel-title')); - Util.waitUntilElementIsVisible(group); + BrowserVisibility.waitUntilElementIsVisible(group); return group.getText(); } checkPropertyIsVisible(propertyName: string, type: string) { const property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); - Util.waitUntilElementIsVisible(property); + BrowserVisibility.waitUntilElementIsVisible(property); } checkPropertyIsNotVisible(propertyName: string, type: string) { const property = element(by.css('div[data-automation-id="card-' + type + '-label-' + propertyName + '"]')); - Util.waitUntilElementIsNotVisible(property); + BrowserVisibility.waitUntilElementIsNotVisible(property); } clickCloseButton() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); this.closeButton.click(); } } diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index 92d8e34f56..a49e740ef0 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -15,12 +15,12 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { browser, by, element } from 'protractor'; import { ProcessServicesPage } from './process-services/processServicesPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../../test.config'); import { PeopleGroupCloudComponentPage } from './demo-shell/process-services/peopleGroupCloudComponentPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class NavigationBarPage { @@ -54,91 +54,91 @@ export class NavigationBarPage { aboutButton = element(by.css('a[data-automation-id="About"]')); navigateToDatatable() { - Util.waitUntilElementIsVisible(this.dataTableButton); + BrowserVisibility.waitUntilElementIsVisible(this.dataTableButton); this.dataTableButton.click(); - Util.waitUntilElementIsVisible(this.dataTableNestedButton); + BrowserVisibility.waitUntilElementIsVisible(this.dataTableNestedButton); this.dataTableNestedButton.click(); } clickContentServicesButton() { - Util.waitUntilElementIsVisible(this.contentServicesButton); + BrowserVisibility.waitUntilElementIsVisible(this.contentServicesButton); this.contentServicesButton.click(); } clickTaskListButton() { - Util.waitUntilElementIsVisible(this.taskListButton); + BrowserVisibility.waitUntilElementIsVisible(this.taskListButton); this.taskListButton.click(); } clickConfigEditorButton() { - Util.waitUntilElementIsVisible(this.configEditorButton); + BrowserVisibility.waitUntilElementIsVisible(this.configEditorButton); this.configEditorButton.click(); } navigateToProcessServicesPage() { - Util.waitUntilElementIsVisible(this.processServicesButton); + BrowserVisibility.waitUntilElementIsVisible(this.processServicesButton); this.processServicesButton.click(); - Util.waitUntilElementIsVisible(this.processServicesNestedButton); + BrowserVisibility.waitUntilElementIsVisible(this.processServicesNestedButton); this.processServicesNestedButton.click(); return new ProcessServicesPage(); } navigateToProcessServicesCloudPage() { - Util.waitUntilElementIsVisible(this.processServicesCloudButton); + BrowserVisibility.waitUntilElementIsVisible(this.processServicesCloudButton); this.processServicesCloudButton.click(); - Util.waitUntilElementIsVisible(this.processServicesCloudHomeButton); + BrowserVisibility.waitUntilElementIsVisible(this.processServicesCloudHomeButton); this.processServicesCloudHomeButton.click(); return new AppListCloudPage(); } navigateToPeopleGroupCloudPage() { - Util.waitUntilElementIsVisible(this.peopleGroupCloud); + BrowserVisibility.waitUntilElementIsVisible(this.peopleGroupCloud); this.peopleGroupCloud.click(); return new PeopleGroupCloudComponentPage(); } navigateToSettingsPage() { - Util.waitUntilElementIsVisible(this.settingsButton); + BrowserVisibility.waitUntilElementIsVisible(this.settingsButton); this.settingsButton.click(); return new AppListCloudPage(); } clickLoginButton() { - Util.waitUntilElementIsVisible(this.loginButton); + BrowserVisibility.waitUntilElementIsVisible(this.loginButton); this.loginButton.click(); } clickTrashcanButton() { - Util.waitUntilElementIsVisible(this.trashcanButton); + BrowserVisibility.waitUntilElementIsVisible(this.trashcanButton); this.trashcanButton.click(); } clickOverlayViewerButton() { - Util.waitUntilElementIsVisible(this.overlayViewerButton); + BrowserVisibility.waitUntilElementIsVisible(this.overlayViewerButton); this.overlayViewerButton.click(); return this; } clickThemeButton() { - Util.waitUntilElementIsVisible(this.themeButton); + BrowserVisibility.waitUntilElementIsVisible(this.themeButton); this.themeButton.click(); - Util.waitUntilElementIsVisible(this.themeMenuContent); + BrowserVisibility.waitUntilElementIsVisible(this.themeMenuContent); } clickOnSpecificThemeButton(themeName) { const themeElement = element(by.css(`button[data-automation-id="${themeName}"]`)); - Util.waitUntilElementIsVisible(themeElement); - Util.waitUntilElementIsClickable(themeElement); + BrowserVisibility.waitUntilElementIsVisible(themeElement); + BrowserVisibility.waitUntilElementIsClickable(themeElement); themeElement.click(); } clickLogoutButton() { - Util.waitUntilElementIsVisible(this.logoutButton); + BrowserVisibility.waitUntilElementIsVisible(this.logoutButton); this.logoutButton.click(); } clickCardViewButton() { - Util.waitUntilElementIsVisible(this.cardViewButton); + BrowserVisibility.waitUntilElementIsVisible(this.cardViewButton); this.cardViewButton.click(); } @@ -148,65 +148,65 @@ export class NavigationBarPage { chooseLanguage(language) { const buttonLanguage = element(by.xpath(`//adf-language-menu//button[contains(text(), '${language}')]`)); - Util.waitUntilElementIsVisible(buttonLanguage); + BrowserVisibility.waitUntilElementIsVisible(buttonLanguage); buttonLanguage.click(); } openLanguageMenu() { - Util.waitUntilElementIsVisible(this.languageMenuButton); + BrowserVisibility.waitUntilElementIsVisible(this.languageMenuButton); this.languageMenuButton.click(); - Util.waitUntilElementIsVisible(this.appTitle); + BrowserVisibility.waitUntilElementIsVisible(this.appTitle); } clickHeaderDataButton() { - Util.waitUntilElementIsVisible(this.headerDataButton); - Util.waitUntilElementIsClickable(this.headerDataButton); + BrowserVisibility.waitUntilElementIsVisible(this.headerDataButton); + BrowserVisibility.waitUntilElementIsClickable(this.headerDataButton); return this.headerDataButton.click(); } clickAboutButton() { - Util.waitUntilElementIsClickable(this.aboutButton); + BrowserVisibility.waitUntilElementIsClickable(this.aboutButton); return this.aboutButton.click(); } checkAboutButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.aboutButton); + return BrowserVisibility.waitUntilElementIsVisible(this.aboutButton); } checkMenuButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.menuButton); + return BrowserVisibility.waitUntilElementIsVisible(this.menuButton); } checkMenuButtonIsNotDisplayed() { - return Util.waitUntilElementIsNotVisible(this.menuButton); + return BrowserVisibility.waitUntilElementIsNotVisible(this.menuButton); } checkToolbarColor(color) { const toolbarColor = element(by.css(`mat-toolbar[class*="mat-${color}"]`)); - return Util.waitUntilElementIsVisible(toolbarColor); + return BrowserVisibility.waitUntilElementIsVisible(toolbarColor); } clickAppLogo(logoTitle) { const appLogo = element(by.css('a[title="' + logoTitle + '"]')); - Util.waitUntilElementIsVisible(appLogo); + BrowserVisibility.waitUntilElementIsVisible(appLogo); appLogo.click(); } clickAppLogoText() { - Util.waitUntilElementIsVisible(this.appTitle); + BrowserVisibility.waitUntilElementIsVisible(this.appTitle); this.appTitle.click(); } clickFormButton() { - Util.waitUntilElementIsVisible(this.processServicesButton); + BrowserVisibility.waitUntilElementIsVisible(this.processServicesButton); this.processServicesButton.click(); - Util.waitUntilElementIsVisible(this.formButton); + BrowserVisibility.waitUntilElementIsVisible(this.formButton); return this.formButton.click(); } checkLogoTooltip(logoTooltipTitle) { const logoTooltip = element(by.css('a[title="' + logoTooltipTitle + '"]')); - Util.waitUntilElementIsVisible(logoTooltip); + BrowserVisibility.waitUntilElementIsVisible(logoTooltip); } openViewer(nodeId) { @@ -219,17 +219,17 @@ export class NavigationBarPage { } clickTreeViewButton() { - Util.waitUntilElementIsVisible(this.treeViewButton); + BrowserVisibility.waitUntilElementIsVisible(this.treeViewButton); this.treeViewButton.click(); } navigateToIconsPage() { - Util.waitUntilElementIsVisible(this.iconsButton); + BrowserVisibility.waitUntilElementIsVisible(this.iconsButton); this.iconsButton.click(); } navigateToCustomSources() { - Util.waitUntilElementIsVisible(this.customSourcesButton); + BrowserVisibility.waitUntilElementIsVisible(this.customSourcesButton); this.customSourcesButton.click(); } } diff --git a/e2e/pages/adf/notificationPage.ts b/e2e/pages/adf/notificationPage.ts index 68e59bdd36..c52902a363 100644 --- a/e2e/pages/adf/notificationPage.ts +++ b/e2e/pages/adf/notificationPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { element, by, protractor, browser, until } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class NotificationPage { @@ -34,44 +34,44 @@ export class NotificationPage { notificationConfig = element(by.css('p[data-automation-id="notification-custom-object"]')); checkNotifyContains(message) { - Util.waitUntilElementIsVisible(element(by.cssContainingText('simple-snack-bar', message))); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText('simple-snack-bar', message))); return this; } goToNotificationsPage() { - Util.waitUntilElementIsVisible(this.notificationsPage); + BrowserVisibility.waitUntilElementIsVisible(this.notificationsPage); this.notificationsPage.click(); } getConfigObject() { - Util.waitUntilElementIsVisible(this.notificationConfig); + BrowserVisibility.waitUntilElementIsVisible(this.notificationConfig); return this.notificationConfig.getText(); } checkNotificationSnackBarIsDisplayed() { - Util.waitUntilElementIsVisible(this.notificationSnackBar); + BrowserVisibility.waitUntilElementIsVisible(this.notificationSnackBar); return this; } checkNotificationSnackBarIsDisplayedWithMessage(message) { const notificationSnackBarMessage = element(by.cssContainingText('simple-snack-bar', message)); - Util.waitUntilElementIsVisible(notificationSnackBarMessage); + BrowserVisibility.waitUntilElementIsVisible(notificationSnackBarMessage); return this; } checkNotificationSnackBarIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.notificationSnackBar); + BrowserVisibility.waitUntilElementIsNotVisible(this.notificationSnackBar); return this; } enterMessageField(text) { - Util.waitUntilElementIsVisible(this.messageField); + BrowserVisibility.waitUntilElementIsVisible(this.messageField); this.messageField.clear(); this.messageField.sendKeys(text); } enterDurationField(time) { - Util.waitUntilElementIsVisible(this.durationField); + BrowserVisibility.waitUntilElementIsVisible(this.durationField); this.durationField.clear(); this.durationField.sendKeys(time); } @@ -79,38 +79,38 @@ export class NotificationPage { selectHorizontalPosition(selectedItem) { const selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); this.horizontalPosition.click(); - Util.waitUntilElementIsVisible(this.selectionDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.selectionDropDown); selectItem.click(); } selectVerticalPosition(selectedItem) { const selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); this.verticalPosition.click(); - Util.waitUntilElementIsVisible(this.selectionDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.selectionDropDown); selectItem.click(); } selectDirection(selectedItem) { const selectItem = element(by.cssContainingText('span[class="mat-option-text"]', selectedItem)); this.direction.click(); - Util.waitUntilElementIsVisible(this.selectionDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.selectionDropDown); selectItem.click(); } clickNotificationButton() { - // Util.waitUntilElementIsVisible(this.customNotificationButton); + // BrowserVisibility.waitUntilElementIsVisible(this.customNotificationButton); // this.customNotificationButton.click(); const button = browser.wait(until.elementLocated(by.css('button[data-automation-id="notification-custom-config-button"]'))); button.click(); } checkActionEvent() { - Util.waitUntilElementIsVisible(this.actionOutput); + BrowserVisibility.waitUntilElementIsVisible(this.actionOutput); return this; } clickActionToggle() { - Util.waitUntilElementIsVisible(this.actionToggle); + BrowserVisibility.waitUntilElementIsVisible(this.actionToggle); this.actionToggle.click(); } @@ -119,7 +119,7 @@ export class NotificationPage { } clearMessage() { - Util.waitUntilElementIsVisible(this.messageField); + BrowserVisibility.waitUntilElementIsVisible(this.messageField); this.messageField.clear(); this.messageField.sendKeys('a'); this.messageField.sendKeys(protractor.Key.BACK_SPACE); diff --git a/e2e/pages/adf/paginationPage.ts b/e2e/pages/adf/paginationPage.ts index dcadd67ce1..3ee35d6c1a 100644 --- a/e2e/pages/adf/paginationPage.ts +++ b/e2e/pages/adf/paginationPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { browser, by, element, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class PaginationPage { @@ -37,81 +37,81 @@ export class PaginationPage { totalFiles = element(by.css('span[class="adf-pagination__range"]')); selectItemsPerPage(numberOfItem: string) { - Util.waitUntilElementIsVisible(this.itemsPerPageDropdown); - Util.waitUntilElementIsClickable(this.itemsPerPageDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.itemsPerPageDropdown); + BrowserVisibility.waitUntilElementIsClickable(this.itemsPerPageDropdown); browser.actions().mouseMove(this.itemsPerPageDropdown).perform(); - Util.waitUntilElementIsVisible(this.itemsPerPageDropdown); - Util.waitUntilElementIsClickable(this.itemsPerPageDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.itemsPerPageDropdown); + BrowserVisibility.waitUntilElementIsClickable(this.itemsPerPageDropdown); this.itemsPerPageDropdown.click(); - Util.waitUntilElementIsVisible(this.pageSelectorDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.pageSelectorDropDown); const itemsPerPage = element.all(by.cssContainingText('.mat-menu-item', numberOfItem)).first(); - Util.waitUntilElementIsClickable(itemsPerPage); - Util.waitUntilElementIsVisible(itemsPerPage); + BrowserVisibility.waitUntilElementIsClickable(itemsPerPage); + BrowserVisibility.waitUntilElementIsVisible(itemsPerPage); itemsPerPage.click(); return this; } checkPageSelectorIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.pageSelectorArrow); + BrowserVisibility.waitUntilElementIsNotOnPage(this.pageSelectorArrow); } checkPageSelectorIsDisplayed() { - Util.waitUntilElementIsVisible(this.pageSelectorArrow); + BrowserVisibility.waitUntilElementIsVisible(this.pageSelectorArrow); } checkPaginationIsNotDisplayed() { - Util.waitUntilElementIsOnPage(this.paginationSectionEmpty); + BrowserVisibility.waitUntilElementIsOnPage(this.paginationSectionEmpty); return this; } getCurrentItemsPerPage() { - Util.waitUntilElementIsVisible(this.itemsPerPage); + BrowserVisibility.waitUntilElementIsVisible(this.itemsPerPage); return this.itemsPerPage.getText(); } getCurrentPage() { - Util.waitUntilElementIsVisible(this.paginationSection); - Util.waitUntilElementIsVisible(this.currentPage); + BrowserVisibility.waitUntilElementIsVisible(this.paginationSection); + BrowserVisibility.waitUntilElementIsVisible(this.currentPage); return this.currentPage.getText(); } getTotalPages() { - Util.waitUntilElementIsVisible(this.totalPages); + BrowserVisibility.waitUntilElementIsVisible(this.totalPages); return this.totalPages.getText(); } getPaginationRange() { - Util.waitUntilElementIsVisible(this.paginationRange); + BrowserVisibility.waitUntilElementIsVisible(this.paginationRange); return this.paginationRange.getText(); } clickOnNextPage() { - Util.waitUntilElementIsVisible(this.nextPageButton); - Util.waitUntilElementIsClickable(this.nextPageButton); + BrowserVisibility.waitUntilElementIsVisible(this.nextPageButton); + BrowserVisibility.waitUntilElementIsClickable(this.nextPageButton); browser.actions().mouseMove(this.nextPageButton).perform(); - Util.waitUntilElementIsVisible(this.nextPageButton); - Util.waitUntilElementIsClickable(this.nextPageButton); + BrowserVisibility.waitUntilElementIsVisible(this.nextPageButton); + BrowserVisibility.waitUntilElementIsClickable(this.nextPageButton); return this.nextPageButton.click(); } clickOnPageDropdown() { - Util.waitUntilElementIsVisible(this.pageDropDown); - Util.waitUntilElementIsClickable(this.pageDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.pageDropDown); + BrowserVisibility.waitUntilElementIsClickable(this.pageDropDown); return this.pageDropDown.click(); } clickOnPageDropdownOption(numberOfItemPerPage: string) { - Util.waitUntilElementIsVisible(element.all(this.pageDropDownOptions).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(this.pageDropDownOptions).first()); const option = element(by.cssContainingText('div[class*="mat-menu-content"] button', numberOfItemPerPage)); - Util.waitUntilElementIsVisible(option); + BrowserVisibility.waitUntilElementIsVisible(option); option.click(); return this; } getPageDropdownOptions() { const deferred = protractor.promise.defer(); - Util.waitUntilElementIsVisible(element.all(this.pageDropDownOptions).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(this.pageDropDownOptions).first()); const initialList = []; element.all(this.pageDropDownOptions).each(function (currentOption) { currentOption.getText().then(function (text) { @@ -126,23 +126,23 @@ export class PaginationPage { } checkNextPageButtonIsDisabled() { - Util.waitUntilElementIsVisible(this.nextButtonDisabled); + BrowserVisibility.waitUntilElementIsVisible(this.nextButtonDisabled); } checkPreviousPageButtonIsDisabled() { - Util.waitUntilElementIsVisible(this.previousButtonDisabled); + BrowserVisibility.waitUntilElementIsVisible(this.previousButtonDisabled); } checkNextPageButtonIsEnabled() { - Util.waitUntilElementIsNotOnPage(this.nextButtonDisabled); + BrowserVisibility.waitUntilElementIsNotOnPage(this.nextButtonDisabled); } checkPreviousPageButtonIsEnabled() { - Util.waitUntilElementIsNotOnPage(this.previousButtonDisabled); + BrowserVisibility.waitUntilElementIsNotOnPage(this.previousButtonDisabled); } getTotalNumberOfFiles() { - Util.waitUntilElementIsVisible(this.totalFiles); + BrowserVisibility.waitUntilElementIsVisible(this.totalFiles); const numberOfFiles = this.totalFiles.getText().then(function (totalNumber) { const totalNumberOfFiles = totalNumber.split('of ')[1]; return totalNumberOfFiles; diff --git a/e2e/pages/adf/permissionsPage.ts b/e2e/pages/adf/permissionsPage.ts index 3772decb98..830a60bca0 100644 --- a/e2e/pages/adf/permissionsPage.ts +++ b/e2e/pages/adf/permissionsPage.ts @@ -17,8 +17,8 @@ import { element, by } from 'protractor'; -import { Util } from '../../util/util'; import { DataTableComponentPage } from './dataTableComponentPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; const column = { role: 'Role' @@ -42,75 +42,75 @@ export class PermissionsPage { closeButton = element(by.id('add-permission-dialog-close-button')); clickCloseButton() { - Util.waitUntilElementIsClickable(this.closeButton); + BrowserVisibility.waitUntilElementIsClickable(this.closeButton); this.closeButton.click(); } checkAddPermissionButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.addPermissionButton); + BrowserVisibility.waitUntilElementIsVisible(this.addPermissionButton); } clickAddPermissionButton() { - Util.waitUntilElementIsClickable(this.addPermissionButton); + BrowserVisibility.waitUntilElementIsClickable(this.addPermissionButton); return this.addPermissionButton.click(); } checkAddPermissionDialogIsDisplayed() { - Util.waitUntilElementIsVisible(this.addPermissionDialog); + BrowserVisibility.waitUntilElementIsVisible(this.addPermissionDialog); } checkSearchUserInputIsDisplayed() { - Util.waitUntilElementIsVisible(this.searchUserInput); + BrowserVisibility.waitUntilElementIsVisible(this.searchUserInput); } searchUserOrGroup(name) { - Util.waitUntilElementIsClickable(this.searchUserInput); + BrowserVisibility.waitUntilElementIsClickable(this.searchUserInput); this.searchUserInput.clear(); return this.searchUserInput.sendKeys(name); } checkResultListIsDisplayed() { - Util.waitUntilElementIsVisible(this.searchResults); + BrowserVisibility.waitUntilElementIsVisible(this.searchResults); } clickUserOrGroup(name) { const userOrGroupName = element(by.cssContainingText('mat-list-option .mat-list-text', name)); - Util.waitUntilElementIsVisible(userOrGroupName); + BrowserVisibility.waitUntilElementIsVisible(userOrGroupName); userOrGroupName.click(); - Util.waitUntilElementIsVisible(this.addButton); + BrowserVisibility.waitUntilElementIsVisible(this.addButton); return this.addButton.click(); } checkUserOrGroupIsAdded(name) { const userOrGroupName = element(by.css('div[data-automation-id="text_' + name + '"]')); - Util.waitUntilElementIsVisible(userOrGroupName); + BrowserVisibility.waitUntilElementIsVisible(userOrGroupName); } checkUserOrGroupIsDeleted(name) { const userOrGroupName = element(by.css('div[data-automation-id="text_' + name + '"]')); - Util.waitUntilElementIsNotVisible(userOrGroupName); + BrowserVisibility.waitUntilElementIsNotVisible(userOrGroupName); } checkPermissionInheritedButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.permissionInheritedButton); + BrowserVisibility.waitUntilElementIsVisible(this.permissionInheritedButton); } clickPermissionInheritedButton() { - Util.waitUntilElementIsClickable(this.permissionInheritedButton); + BrowserVisibility.waitUntilElementIsClickable(this.permissionInheritedButton); return this.permissionInheritedButton.click(); } clickDeletePermissionButton() { - Util.waitUntilElementIsClickable(this.deletePermissionButton); + BrowserVisibility.waitUntilElementIsClickable(this.deletePermissionButton); return this.deletePermissionButton.click(); } checkNoPermissionsIsDisplayed() { - Util.waitUntilElementIsVisible(this.noPermissions); + BrowserVisibility.waitUntilElementIsVisible(this.noPermissions); } getPermissionInheritedButtonText() { - Util.waitUntilElementIsClickable(this.permissionInheritedButton); + BrowserVisibility.waitUntilElementIsClickable(this.permissionInheritedButton); return this.permissionInheritedButtonText.getText(); } @@ -120,39 +120,39 @@ export class PermissionsPage { getRoleCellValue(rowName) { const locator = new DataTableComponentPage().getCellByRowAndColumn('Authority ID', rowName, column.role); - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getText(); } clickRoleDropdown() { - Util.waitUntilElementIsVisible(this.roleDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.roleDropdown); return this.roleDropdown.click(); } getRoleDropdownOptions() { - Util.waitUntilElementIsVisible(this.roleDropdownOptions); + BrowserVisibility.waitUntilElementIsVisible(this.roleDropdownOptions); return this.roleDropdownOptions; } selectOption(name) { const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); - Util.waitUntilElementIsVisible(selectProcessDropdown); - Util.waitUntilElementIsClickable(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsVisible(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsClickable(selectProcessDropdown); selectProcessDropdown.click(); return this; } getAssignPermissionErrorText() { - Util.waitUntilElementIsVisible(this.assignPermissionError); + BrowserVisibility.waitUntilElementIsVisible(this.assignPermissionError); return this.assignPermissionError.getText(); } checkPermissionContainerIsDisplayed() { - Util.waitUntilElementIsVisible(this.permissionDisplayContainer); + BrowserVisibility.waitUntilElementIsVisible(this.permissionDisplayContainer); } checkUserOrGroupIsDisplayed(name) { const userOrGroupName = element(by.cssContainingText('mat-list-option .mat-list-text', name)); - Util.waitUntilElementIsVisible(userOrGroupName); + BrowserVisibility.waitUntilElementIsVisible(userOrGroupName); } } diff --git a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts b/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts index ed75cf0d72..741b8cfaab 100644 --- a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Util } from '../../../util/util'; import { by, element, protractor } from 'protractor'; import { EditProcessFilterDialog } from '../dialog/editProcessFilterDialog'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class EditProcessFilterCloudComponent { @@ -33,16 +33,16 @@ export class EditProcessFilterCloudComponent { } clickCustomiseFilterHeader() { - Util.waitUntilElementIsVisible(this.customiseFilter); + BrowserVisibility.waitUntilElementIsVisible(this.customiseFilter); this.customiseFilter.click(); return this; } checkCustomiseFilterHeaderIsExpanded() { const expansionPanelExtended = element.all(by.css('mat-expansion-panel-header[class*="mat-expanded"]')).first(); - Util.waitUntilElementIsVisible(expansionPanelExtended); + BrowserVisibility.waitUntilElementIsVisible(expansionPanelExtended); const content = element(by.css('div[class*="mat-expansion-panel-content "][style*="visible"]')); - Util.waitUntilElementIsVisible(content); + BrowserVisibility.waitUntilElementIsVisible(content); return this; } @@ -50,8 +50,8 @@ export class EditProcessFilterCloudComponent { this.clickOnDropDownArrow('status'); const statusElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(statusElement); - Util.waitUntilElementIsVisible(statusElement); + BrowserVisibility.waitUntilElementIsClickable(statusElement); + BrowserVisibility.waitUntilElementIsVisible(statusElement); statusElement.click(); return this; } @@ -64,15 +64,15 @@ export class EditProcessFilterCloudComponent { this.clickOnDropDownArrow('sort'); const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(sortElement); - Util.waitUntilElementIsVisible(sortElement); + BrowserVisibility.waitUntilElementIsClickable(sortElement); + BrowserVisibility.waitUntilElementIsVisible(sortElement); sortElement.click(); return this; } getSortFilterDropDownValue() { const sortLocator = element.all(by.css("mat-form-field[data-automation-id='sort'] span")).first(); - Util.waitUntilElementIsVisible(sortLocator); + BrowserVisibility.waitUntilElementIsVisible(sortLocator); return sortLocator.getText(); } @@ -80,8 +80,8 @@ export class EditProcessFilterCloudComponent { this.clickOnDropDownArrow('order'); const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(orderElement); - Util.waitUntilElementIsVisible(orderElement); + BrowserVisibility.waitUntilElementIsClickable(orderElement); + BrowserVisibility.waitUntilElementIsVisible(orderElement); orderElement.click(); return this; } @@ -92,18 +92,18 @@ export class EditProcessFilterCloudComponent { clickOnDropDownArrow(option) { const dropDownArrow = element.all(by.css("mat-form-field[data-automation-id='" + option + "'] div[class='mat-select-arrow-wrapper']")).first(); - Util.waitUntilElementIsVisible(dropDownArrow); - Util.waitUntilElementIsClickable(dropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(dropDownArrow); + BrowserVisibility.waitUntilElementIsClickable(dropDownArrow); dropDownArrow.click(); - Util.waitUntilElementIsVisible(this.selectedOption); + BrowserVisibility.waitUntilElementIsVisible(this.selectedOption); } setAppNameDropDown(option) { this.clickOnDropDownArrow('appName'); const appNameElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(appNameElement); - Util.waitUntilElementIsVisible(appNameElement); + BrowserVisibility.waitUntilElementIsClickable(appNameElement); + BrowserVisibility.waitUntilElementIsVisible(appNameElement); appNameElement.click(); return this; } @@ -134,13 +134,13 @@ export class EditProcessFilterCloudComponent { getProperty(property) { const locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first(); - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getAttribute('value'); } setProperty(property, option) { const locator = element.all(by.css('input[data-automation-id="adf-cloud-edit-process-property-' + property + '"]')).first(); - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); locator.clear(); locator.sendKeys(option); locator.sendKeys(protractor.Key.ENTER); @@ -148,55 +148,55 @@ export class EditProcessFilterCloudComponent { } checkSaveButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this; } checkSaveAsButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); return this; } checkDeleteButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); return this; } checkSaveButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this.saveButton.isEnabled(); } checkSaveAsButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); return this.saveAsButton.isEnabled(); } checkDeleteButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); return this.deleteButton.isEnabled(); } clickSaveAsButton() { - const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); - Util.waitUntilElementIsClickable(this.saveAsButton); - Util.waitUntilElementIsVisible(this.saveAsButton); - Util.waitUntilElementIsNotVisible(disabledButton); + const disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]"))); + BrowserVisibility.waitUntilElementIsClickable(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); this.saveAsButton.click(); return this.editProcessFilter; } clickDeleteButton() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); this.deleteButton.click(); return this; } clickSaveButton() { - const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); - Util.waitUntilElementIsClickable(this.saveButton); - Util.waitUntilElementIsVisible(this.saveButton); - Util.waitUntilElementIsNotVisible(disabledButton); + const disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]"))); + BrowserVisibility.waitUntilElementIsClickable(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); this.saveButton.click(); return this; } diff --git a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts b/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts index c5484f2413..51e802e91d 100644 --- a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts @@ -15,9 +15,9 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by, element, protractor } from 'protractor'; import { EditTaskFilterDialog } from '../dialog/editTaskFilterDialog'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class EditTaskFilterCloudComponent { @@ -43,7 +43,7 @@ export class EditTaskFilterCloudComponent { } clickCustomiseFilterHeader() { - Util.waitUntilElementIsVisible(this.customiseFilter); + BrowserVisibility.waitUntilElementIsVisible(this.customiseFilter); this.customiseFilter.click(); return this; } @@ -52,8 +52,8 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('status'); const statusElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsVisible(statusElement); - Util.waitUntilElementIsClickable(statusElement); + BrowserVisibility.waitUntilElementIsVisible(statusElement); + BrowserVisibility.waitUntilElementIsClickable(statusElement); statusElement.click(); return this; } @@ -66,15 +66,15 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('sort'); const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(sortElement); - Util.waitUntilElementIsVisible(sortElement); + BrowserVisibility.waitUntilElementIsClickable(sortElement); + BrowserVisibility.waitUntilElementIsVisible(sortElement); sortElement.click(); return this; } getSortFilterDropDownValue() { const elementSort = element.all(by.css("mat-select[data-automation-id='adf-cloud-edit-task-property-sort'] span")).first(); - Util.waitUntilElementIsVisible(elementSort); + BrowserVisibility.waitUntilElementIsVisible(elementSort); return elementSort.getText(); } @@ -82,8 +82,8 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('order'); const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(orderElement); - Util.waitUntilElementIsVisible(orderElement); + BrowserVisibility.waitUntilElementIsClickable(orderElement); + BrowserVisibility.waitUntilElementIsVisible(orderElement); orderElement.click(); return this; } @@ -94,9 +94,9 @@ export class EditTaskFilterCloudComponent { clickOnDropDownArrow(option) { const dropDownArrow = element.all(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")).first(); - Util.waitUntilElementIsVisible(dropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(dropDownArrow); dropDownArrow.click(); - Util.waitUntilElementIsVisible(this.selectedOption); + BrowserVisibility.waitUntilElementIsVisible(this.selectedOption); } setAssignee(option) { @@ -150,52 +150,52 @@ export class EditTaskFilterCloudComponent { } checkSaveButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this; } checkSaveAsButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); return this; } checkDeleteButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); return this; } checkSaveButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this.saveButton.isEnabled(); } checkSaveAsButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this.saveAsButton.isEnabled(); } checkDeleteButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this.deleteButton.isEnabled(); } clickSaveAsButton() { const disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]"))); - Util.waitUntilElementIsClickable(this.saveAsButton); - Util.waitUntilElementIsVisible(this.saveAsButton); - Util.waitUntilElementIsNotVisible(disabledButton); + BrowserVisibility.waitUntilElementIsClickable(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); this.saveAsButton.click(); return this.editTaskFilter; } clickDeleteButton() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); this.deleteButton.click(); return this; } clickSaveButton() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); this.saveButton.click(); return this; } @@ -206,7 +206,7 @@ export class EditTaskFilterCloudComponent { } clearField(locator) { - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); locator.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { locator.sendKeys(protractor.Key.BACK_SPACE); @@ -218,15 +218,15 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('appName'); const appNameElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(appNameElement); - Util.waitUntilElementIsVisible(appNameElement); + BrowserVisibility.waitUntilElementIsClickable(appNameElement); + BrowserVisibility.waitUntilElementIsVisible(appNameElement); appNameElement.click(); return this; } getAppNameDropDownValue() { const locator = element.all(by.css("mat-select[data-automation-id='adf-cloud-edit-task-property-appName'] span")).first(); - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getText(); } @@ -252,7 +252,7 @@ export class EditTaskFilterCloudComponent { setProperty(property, option) { const locator = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-' + property + '"]')); - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); locator.clear(); locator.sendKeys(option); locator.sendKeys(protractor.Key.ENTER); diff --git a/e2e/pages/adf/process-cloud/groupCloudComponent.ts b/e2e/pages/adf/process-cloud/groupCloudComponent.ts index da69613b33..8552a82d34 100644 --- a/e2e/pages/adf/process-cloud/groupCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/groupCloudComponent.ts @@ -16,14 +16,14 @@ */ import { by, element, protractor } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class GroupCloudComponent { groupCloudSearch = element(by.css('input[data-automation-id="adf-cloud-group-search-input"]')); searchGroups(name) { - Util.waitUntilElementIsVisible(this.groupCloudSearch); + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudSearch); this.groupCloudSearch.clear().then(() => { for (let i = 0; i < name.length; i++) { this.groupCloudSearch.sendKeys(name[i]); @@ -36,26 +36,26 @@ export class GroupCloudComponent { selectGroupFromList(name) { const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); - Util.waitUntilElementIsVisible(groupRow); + BrowserVisibility.waitUntilElementIsVisible(groupRow); groupRow.click(); - Util.waitUntilElementIsNotVisible(groupRow); + BrowserVisibility.waitUntilElementIsNotVisible(groupRow); return this; } checkGroupIsDisplayed(name) { const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); - Util.waitUntilElementIsVisible(groupRow); + BrowserVisibility.waitUntilElementIsVisible(groupRow); return this; } checkGroupIsNotDisplayed(name) { const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); - Util.waitUntilElementIsNotVisible(groupRow); + BrowserVisibility.waitUntilElementIsNotVisible(groupRow); return this; } checkSelectedGroup(group) { - Util.waitUntilElementIsVisible(element(by.cssContainingText('mat-chip[data-automation-id*="adf-cloud-group-chip-"]', group))); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText('mat-chip[data-automation-id*="adf-cloud-group-chip-"]', group))); return this; } diff --git a/e2e/pages/adf/process-cloud/peopleCloudComponent.ts b/e2e/pages/adf/process-cloud/peopleCloudComponent.ts index 939a414ea6..85f7f7c109 100644 --- a/e2e/pages/adf/process-cloud/peopleCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/peopleCloudComponent.ts @@ -16,14 +16,14 @@ */ import { by, element, protractor } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class PeopleCloudComponent { peopleCloudSearch = element(by.css('input[data-automation-id="adf-people-cloud-search-input"]')); searchAssigneeAndSelect(name) { - Util.waitUntilElementIsVisible(this.peopleCloudSearch); + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); this.peopleCloudSearch.clear(); this.peopleCloudSearch.sendKeys(name); this.selectAssigneeFromList(name); @@ -31,7 +31,7 @@ export class PeopleCloudComponent { } searchAssignee(name) { - Util.waitUntilElementIsVisible(this.peopleCloudSearch); + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); this.peopleCloudSearch.clear().then(() => { for (let i = 0; i < name.length; i++) { this.peopleCloudSearch.sendKeys(name[i]); @@ -44,31 +44,31 @@ export class PeopleCloudComponent { selectAssigneeFromList(name) { const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); - Util.waitUntilElementIsVisible(assigneeRow); + BrowserVisibility.waitUntilElementIsVisible(assigneeRow); assigneeRow.click(); - Util.waitUntilElementIsNotVisible(assigneeRow); + BrowserVisibility.waitUntilElementIsNotVisible(assigneeRow); return this; } getAssignee() { - Util.waitUntilElementIsVisible(this.peopleCloudSearch); + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); return this.peopleCloudSearch.getAttribute('value'); } checkUserIsDisplayed(name) { const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); - Util.waitUntilElementIsVisible(assigneeRow); + BrowserVisibility.waitUntilElementIsVisible(assigneeRow); return this; } checkUserIsNotDisplayed(name) { const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); - Util.waitUntilElementIsNotVisible(assigneeRow); + BrowserVisibility.waitUntilElementIsNotVisible(assigneeRow); return this; } checkSelectedPeople(person) { - Util.waitUntilElementIsVisible(element(by.cssContainingText('mat-chip-list mat-chip', person))); + BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText('mat-chip-list mat-chip', person))); return this; } diff --git a/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts b/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts index a4871f0fa4..194b98bb8b 100644 --- a/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ProcessFiltersCloudComponent { @@ -28,30 +28,30 @@ export class ProcessFiltersCloudComponent { } checkProcessFilterIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); return this; } getProcessFilterIcon() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const icon = this.filter.element(this.filterIcon); - Util.waitUntilElementIsVisible(icon); + BrowserVisibility.waitUntilElementIsVisible(icon); return icon.getText(); } checkProcessFilterHasNoIcon() { - Util.waitUntilElementIsVisible(this.filter); - Util.waitUntilElementIsNotOnPage(this.filter.element(this.filterIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsNotOnPage(this.filter.element(this.filterIcon)); } clickProcessFilter() { - Util.waitUntilElementIsVisible(this.filter); - Util.waitUntilElementIsClickable(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsClickable(this.filter); return this.filter.click(); } checkProcessFilterNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter); return this.filter; } diff --git a/e2e/pages/adf/process-cloud/processListCloudComponent.ts b/e2e/pages/adf/process-cloud/processListCloudComponent.ts index 603ceb1819..6107cb6e82 100644 --- a/e2e/pages/adf/process-cloud/processListCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/processListCloudComponent.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { DataTableComponentPage } from '../dataTableComponentPage'; import { element, by } from 'protractor'; @@ -55,12 +55,12 @@ export class ProcessListCloudComponent { } checkProcessListIsLoaded() { - Util.waitUntilElementIsVisible(this.processList); + BrowserVisibility.waitUntilElementIsVisible(this.processList); return this; } getNoProcessFoundMessage() { - Util.waitUntilElementIsVisible(this.noProcessFound); + BrowserVisibility.waitUntilElementIsVisible(this.noProcessFound); return this.noProcessFound.getText(); } diff --git a/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts b/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts index c0bc3ef967..2bca03e1bc 100644 --- a/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TaskFiltersCloudComponent { @@ -28,29 +28,29 @@ export class TaskFiltersCloudComponent { } checkTaskFilterIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); return this; } getTaskFilterIcon() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const icon = this.filter.element(this.taskIcon); - Util.waitUntilElementIsVisible(icon); + BrowserVisibility.waitUntilElementIsVisible(icon); return icon.getText(); } checkTaskFilterHasNoIcon() { - Util.waitUntilElementIsVisible(this.filter); - Util.waitUntilElementIsNotOnPage(this.filter.element(this.taskIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsNotOnPage(this.filter.element(this.taskIcon)); } clickTaskFilter() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); return this.filter.click(); } checkTaskFilterNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter); return this.filter; } diff --git a/e2e/pages/adf/process-cloud/taskListCloudComponent.ts b/e2e/pages/adf/process-cloud/taskListCloudComponent.ts index 55bdcdab20..db2b09186e 100644 --- a/e2e/pages/adf/process-cloud/taskListCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/taskListCloudComponent.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { DataTableComponentPage } from '../dataTableComponentPage'; import { element, by } from 'protractor'; @@ -67,7 +67,7 @@ export class TaskListCloudComponent { } getRow(taskName) { - return this.dataTable.getRow('Name', taskName); + return this.dataTable.getRowElement('Name', taskName); } checkContentIsDisplayedByProcessInstanceId(taskName) { @@ -87,12 +87,12 @@ export class TaskListCloudComponent { } checkTaskListIsLoaded() { - Util.waitUntilElementIsVisible(this.taskList); + BrowserVisibility.waitUntilElementIsVisible(this.taskList); return this; } getNoTasksFoundMessage() { - Util.waitUntilElementIsVisible(this.noTasksFound); + BrowserVisibility.waitUntilElementIsVisible(this.noTasksFound); return this.noTasksFound.getText(); } @@ -106,7 +106,7 @@ export class TaskListCloudComponent { getIdCellValue(rowName) { const locator = new DataTableComponentPage().getCellByRowAndColumn('Name', rowName, column.id); - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getText(); } diff --git a/e2e/pages/adf/process-services/analyticsPage.ts b/e2e/pages/adf/process-services/analyticsPage.ts index c3afdcc4b8..f6e0464134 100644 --- a/e2e/pages/adf/process-services/analyticsPage.ts +++ b/e2e/pages/adf/process-services/analyticsPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { element, by, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class AnalyticsPage { @@ -27,15 +27,15 @@ export class AnalyticsPage { getReport(title) { const reportTitle = element(by.css(`mat-icon[data-automation-id="${title}_filter"]`)); - Util.waitUntilElementIsVisible(reportTitle); + BrowserVisibility.waitUntilElementIsVisible(reportTitle); reportTitle.click(); } changeReportTitle(title) { - Util.waitUntilElementIsVisible(this.toolbarTitleContainer); - Util.waitUntilElementIsClickable(this.toolbarTitleContainer); + BrowserVisibility.waitUntilElementIsVisible(this.toolbarTitleContainer); + BrowserVisibility.waitUntilElementIsClickable(this.toolbarTitleContainer); this.toolbarTitleContainer.click(); - Util.waitUntilElementIsVisible(this.toolbarTitleInput); + BrowserVisibility.waitUntilElementIsVisible(this.toolbarTitleInput); this.toolbarTitleInput.click(); this.clearReportTitle(); this.toolbarTitleInput.sendKeys(title); @@ -43,23 +43,23 @@ export class AnalyticsPage { } clearReportTitle() { - Util.waitUntilElementIsVisible(this.toolbarTitleInput); + BrowserVisibility.waitUntilElementIsVisible(this.toolbarTitleInput); this.toolbarTitleInput.getAttribute('value').then((value) => { let i; for (i = value.length; i >= 0; i--) { this.toolbarTitleInput.sendKeys(protractor.Key.BACK_SPACE); } }); - Util.waitUntilElementIsVisible(this.toolbarTitleInput); + BrowserVisibility.waitUntilElementIsVisible(this.toolbarTitleInput); } getReportTitle() { - Util.waitUntilElementIsVisible(this.toolbarTitle); + BrowserVisibility.waitUntilElementIsVisible(this.toolbarTitle); return this.toolbarTitle.getText(); } checkNoReportMessage() { - Util.waitUntilElementIsVisible(this.reportMessage); + BrowserVisibility.waitUntilElementIsVisible(this.reportMessage); } } diff --git a/e2e/pages/adf/process-services/appNavigationBarPage.ts b/e2e/pages/adf/process-services/appNavigationBarPage.ts index 8b3b1e5927..24be431a9e 100644 --- a/e2e/pages/adf/process-services/appNavigationBarPage.ts +++ b/e2e/pages/adf/process-services/appNavigationBarPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by, browser } from 'protractor'; export class AppNavigationBarPage { @@ -28,7 +28,7 @@ export class AppNavigationBarPage { reportsButtonSelected = element.all(by.cssContainingText('div[class*="mat-tab-label"] .mat-tab-labels div[aria-selected="true"]', 'Reports')).first(); clickTasksButton() { - Util.waitUntilElementIsVisible(this.tasksButton); + BrowserVisibility.waitUntilElementIsVisible(this.tasksButton); this.tasksButton.click(); return browser.sleep(400); } @@ -48,8 +48,8 @@ export class AppNavigationBarPage { } clickReportsButton() { - Util.waitUntilElementIsVisible(this.reportsButton); + BrowserVisibility.waitUntilElementIsVisible(this.reportsButton); this.reportsButton.click(); - return Util.waitUntilElementIsVisible(this.reportsButtonSelected); + return BrowserVisibility.waitUntilElementIsVisible(this.reportsButtonSelected); } } diff --git a/e2e/pages/adf/process-services/attachFormPage.ts b/e2e/pages/adf/process-services/attachFormPage.ts index 1d298526b0..501bdfedeb 100644 --- a/e2e/pages/adf/process-services/attachFormPage.ts +++ b/e2e/pages/adf/process-services/attachFormPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class AttachFormPage { @@ -29,19 +29,19 @@ export class AttachFormPage { attachFormDropdown = element(by.css("div[class='adf-attach-form-row']")); checkNoFormMessageIsDisplayed() { - return Util.waitUntilElementIsVisible(this.noFormMessage); + return BrowserVisibility.waitUntilElementIsVisible(this.noFormMessage); } checkAttachFormButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.attachFormButton); + return BrowserVisibility.waitUntilElementIsVisible(this.attachFormButton); } checkCompleteButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.completeButton); + return BrowserVisibility.waitUntilElementIsVisible(this.completeButton); } clickAttachFormButton() { - Util.waitUntilElementIsVisible(this.attachFormButton); + BrowserVisibility.waitUntilElementIsVisible(this.attachFormButton); return this.attachFormButton.click(); } @@ -52,29 +52,29 @@ export class AttachFormPage { } checkFormDropdownIsDisplayed() { - return Util.waitUntilElementIsVisible(this.formDropdown); + return BrowserVisibility.waitUntilElementIsVisible(this.formDropdown); } checkCancelButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.cancelButton); + return BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); } clickAttachFormDropdown() { - Util.waitUntilElementIsClickable(this.attachFormDropdown); + BrowserVisibility.waitUntilElementIsClickable(this.attachFormDropdown); return this.attachFormDropdown.click(); } selectAttachFormOption(option) { - Util.waitUntilElementIsClickable(element(by.cssContainingText("mat-option[role='option']", option))); + BrowserVisibility.waitUntilElementIsClickable(element(by.cssContainingText("mat-option[role='option']", option))); return element(by.cssContainingText("mat-option[role='option']", option)).click(); } clickCancelButton() { - Util.waitUntilElementIsVisible(this.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); return this.cancelButton.click(); } checkAttachFormButtonIsDisabled() { - return Util.waitUntilElementIsVisible(element(by.css('button[id="adf-no-form-attach-form-button"][disabled]'))); + return BrowserVisibility.waitUntilElementIsVisible(element(by.css('button[id="adf-no-form-attach-form-button"][disabled]'))); } } diff --git a/e2e/pages/adf/process-services/attachmentListPage.ts b/e2e/pages/adf/process-services/attachmentListPage.ts index 6d27b548ff..3fb2606d1d 100644 --- a/e2e/pages/adf/process-services/attachmentListPage.ts +++ b/e2e/pages/adf/process-services/attachmentListPage.ts @@ -17,10 +17,10 @@ import { element, by, protractor, browser } from 'protractor'; -import { Util } from '../../../util/util'; import TestConfig = require('../../../test.config'); import path = require('path'); import remote = require('selenium-webdriver/remote'); +import { BrowserVisibility } from '@alfresco/adf-testing'; export class AttachmentListPage { @@ -32,31 +32,31 @@ export class AttachmentListPage { noContentContainer = element(by.css("div[class*='adf-no-content-container']")); checkEmptyAttachmentList() { - Util.waitUntilElementIsVisible(this.noContentContainer); + BrowserVisibility.waitUntilElementIsVisible(this.noContentContainer); } clickAttachFileButton(fileLocation) { browser.setFileDetector(new remote.FileDetector()); - Util.waitUntilElementIsVisible(this.attachFileButton); + BrowserVisibility.waitUntilElementIsVisible(this.attachFileButton); return this.attachFileButton.sendKeys(path.resolve(path.join(TestConfig.main.rootPath, fileLocation))); } checkFileIsAttached(name) { const fileAttached = element.all(by.css('div[data-automation-id="' + name + '"]')).first(); - Util.waitUntilElementIsVisible(fileAttached); + BrowserVisibility.waitUntilElementIsVisible(fileAttached); } checkAttachFileButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.attachFileButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.attachFileButton); } viewFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); element.all(by.css('div[data-automation-id="' + name + '"]')).first().click(); - Util.waitUntilElementIsVisible(this.buttonMenu); + BrowserVisibility.waitUntilElementIsVisible(this.buttonMenu); this.buttonMenu.click(); - Util.waitUntilElementIsVisible(this.viewButton); + BrowserVisibility.waitUntilElementIsVisible(this.viewButton); browser.driver.sleep(500); this.viewButton.click(); browser.driver.sleep(500); @@ -64,11 +64,11 @@ export class AttachmentListPage { } removeFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); element.all(by.css('div[data-automation-id="' + name + '"]')).first().click(); - Util.waitUntilElementIsVisible(this.buttonMenu); + BrowserVisibility.waitUntilElementIsVisible(this.buttonMenu); this.buttonMenu.click(); - Util.waitUntilElementIsVisible(this.removeButton); + BrowserVisibility.waitUntilElementIsVisible(this.removeButton); browser.driver.sleep(500); this.removeButton.click(); browser.driver.sleep(500); @@ -76,28 +76,28 @@ export class AttachmentListPage { } downloadFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); element.all(by.css('div[data-automation-id="' + name + '"]')).first().click(); - Util.waitUntilElementIsVisible(this.buttonMenu); + BrowserVisibility.waitUntilElementIsVisible(this.buttonMenu); this.buttonMenu.click(); - Util.waitUntilElementIsVisible(this.downloadButton); + BrowserVisibility.waitUntilElementIsVisible(this.downloadButton); browser.driver.sleep(500); this.downloadButton.click(); return this; } doubleClickFile(name) { - Util.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); + BrowserVisibility.waitUntilElementIsVisible(element.all(by.css('div[data-automation-id="' + name + '"]')).first()); const fileAttached = element.all(by.css('div[data-automation-id="' + name + '"]')).first(); - Util.waitUntilElementIsVisible(fileAttached); - Util.waitUntilElementIsClickable(fileAttached); + BrowserVisibility.waitUntilElementIsVisible(fileAttached); + BrowserVisibility.waitUntilElementIsClickable(fileAttached); fileAttached.click(); browser.actions().sendKeys(protractor.Key.ENTER).perform(); } checkFileIsRemoved(name) { const fileAttached = element.all(by.css('div[data-automation-id="' + name + '"]')).first(); - Util.waitUntilElementIsNotVisible(fileAttached); + BrowserVisibility.waitUntilElementIsNotVisible(fileAttached); return this; } diff --git a/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts b/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts index 51550bca84..69c59d9e1b 100644 --- a/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts +++ b/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts @@ -41,19 +41,9 @@ export class AppSettingsToggles { return this; } - disableTaskFiltersIcon() { - this.formControllersPage.disableToggle(this.showTaskFilterIconsToggle); - return this; - } - enableProcessFiltersIcon() { this.formControllersPage.enableToggle(this.showProcessFilterIconsToggle); return this; } - disableProcessFiltersIcon() { - this.formControllersPage.disableToggle(this.showProcessFilterIconsToggle); - return this; - } - } diff --git a/e2e/pages/adf/process-services/dialog/createChecklistDialog.ts b/e2e/pages/adf/process-services/dialog/createChecklistDialog.ts index 36d167de1a..18e8a7c213 100644 --- a/e2e/pages/adf/process-services/dialog/createChecklistDialog.ts +++ b/e2e/pages/adf/process-services/dialog/createChecklistDialog.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ChecklistDialog { @@ -26,41 +26,41 @@ export class ChecklistDialog { dialogTitle = element(by.id('add-checklist-title')); addName(name) { - Util.waitUntilElementIsClickable(this.nameField); + BrowserVisibility.waitUntilElementIsClickable(this.nameField); this.nameField.clear(); this.nameField.sendKeys(name); return this; } clickCreateChecklistButton() { - Util.waitUntilElementIsVisible(this.addChecklistButton); + BrowserVisibility.waitUntilElementIsVisible(this.addChecklistButton); this.addChecklistButton.click(); } clickCancelButton() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); this.closeButton.click(); } getDialogTitle() { - Util.waitUntilElementIsVisible(this.dialogTitle); + BrowserVisibility.waitUntilElementIsVisible(this.dialogTitle); return this.dialogTitle.getText(); } getNameFieldPlaceholder() { - Util.waitUntilElementIsVisible(this.nameField); + BrowserVisibility.waitUntilElementIsVisible(this.nameField); return this.nameField.getAttribute('placeholder'); } checkCancelButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.closeButton); - Util.waitUntilElementIsClickable(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsClickable(this.closeButton); return this; } checkAddChecklistButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.addChecklistButton); - Util.waitUntilElementIsClickable(this.addChecklistButton); + BrowserVisibility.waitUntilElementIsVisible(this.addChecklistButton); + BrowserVisibility.waitUntilElementIsClickable(this.addChecklistButton); return this; } diff --git a/e2e/pages/adf/process-services/dialog/startTaskDialog.ts b/e2e/pages/adf/process-services/dialog/startTaskDialog.ts index 52d6435849..2c16a2ee35 100644 --- a/e2e/pages/adf/process-services/dialog/startTaskDialog.ts +++ b/e2e/pages/adf/process-services/dialog/startTaskDialog.ts @@ -16,7 +16,7 @@ */ import { element, by, Key } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class StartTaskDialog { @@ -30,26 +30,26 @@ export class StartTaskDialog { cancelButton = element(by.css('button[id="button-cancel"]')); addName(userName) { - Util.waitUntilElementIsVisible(this.name); + BrowserVisibility.waitUntilElementIsVisible(this.name); this.name.clear(); this.name.sendKeys(userName); return this; } addDescription(userDescription) { - Util.waitUntilElementIsVisible(this.description); + BrowserVisibility.waitUntilElementIsVisible(this.description); this.description.sendKeys(userDescription); return this; } addDueDate(date) { - Util.waitUntilElementIsVisible(this.dueDate); + BrowserVisibility.waitUntilElementIsVisible(this.dueDate); this.dueDate.sendKeys(date); return this; } addAssignee(name) { - Util.waitUntilElementIsVisible(this.assignee); + BrowserVisibility.waitUntilElementIsVisible(this.assignee); this.assignee.sendKeys(name); this.selectAssigneeFromList(name); return this; @@ -57,50 +57,50 @@ export class StartTaskDialog { selectAssigneeFromList(name) { const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); - Util.waitUntilElementIsVisible(assigneeRow); + BrowserVisibility.waitUntilElementIsVisible(assigneeRow); assigneeRow.click(); - Util.waitUntilElementIsNotVisible(assigneeRow); + BrowserVisibility.waitUntilElementIsNotVisible(assigneeRow); return this; } getAssignee() { - Util.waitUntilElementIsVisible(this.assignee); + BrowserVisibility.waitUntilElementIsVisible(this.assignee); return this.assignee.getAttribute('placeholder'); } addForm(form) { - Util.waitUntilElementIsVisible(this.formDropDown); + BrowserVisibility.waitUntilElementIsVisible(this.formDropDown); this.formDropDown.click(); return this.selectForm(form); } selectForm(form) { const option = element(by.cssContainingText('span[class*="mat-option-text"]', form)); - Util.waitUntilElementIsVisible(option); - Util.waitUntilElementIsClickable(option); + BrowserVisibility.waitUntilElementIsVisible(option); + BrowserVisibility.waitUntilElementIsClickable(option); option.click(); return this; } clickStartButton() { - Util.waitUntilElementIsVisible(this.startButton); - Util.waitUntilElementIsClickable(this.startButton); + BrowserVisibility.waitUntilElementIsVisible(this.startButton); + BrowserVisibility.waitUntilElementIsClickable(this.startButton); return this.startButton.click(); } checkStartButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.startButtonEnabled); + BrowserVisibility.waitUntilElementIsVisible(this.startButtonEnabled); return this; } checkStartButtonIsDisabled() { - Util.waitUntilElementIsVisible(this.startButton.getAttribute('disabled')); + BrowserVisibility.waitUntilElementIsVisible(this.startButton.getAttribute('disabled')); return this; } clickCancelButton() { - Util.waitUntilElementIsVisible(this.cancelButton); - Util.waitUntilElementIsClickable(this.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); + BrowserVisibility.waitUntilElementIsClickable(this.cancelButton); return this.cancelButton.click(); } @@ -112,7 +112,7 @@ export class StartTaskDialog { checkValidationErrorIsDisplayed(error, elementRef = 'mat-error') { const errorElement = element(by.cssContainingText(elementRef, error)); - Util.waitUntilElementIsVisible(errorElement); + BrowserVisibility.waitUntilElementIsVisible(errorElement); return this; } } diff --git a/e2e/pages/adf/process-services/filtersPage.ts b/e2e/pages/adf/process-services/filtersPage.ts index 5e66ea05a7..fc41f71501 100644 --- a/e2e/pages/adf/process-services/filtersPage.ts +++ b/e2e/pages/adf/process-services/filtersPage.ts @@ -16,8 +16,8 @@ */ import { by, element } from 'protractor'; -import { Util } from '../../../util/util'; import { DataTableComponentPage } from '../dataTableComponentPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class FiltersPage { @@ -25,13 +25,13 @@ export class FiltersPage { dataTable = new DataTableComponentPage(); getActiveFilter() { - Util.waitUntilElementIsVisible(this.activeFilter); + BrowserVisibility.waitUntilElementIsVisible(this.activeFilter); return this.activeFilter.getText(); } goToFilter(filterName) { const filter = element(by.css(`span[data-automation-id="${filterName}_filter"]`)); - Util.waitUntilElementIsVisible(filter); + BrowserVisibility.waitUntilElementIsVisible(filter); filter.click(); return this; } diff --git a/e2e/pages/adf/process-services/formFields.ts b/e2e/pages/adf/process-services/formFields.ts index 00bef9cdf0..72086647d8 100644 --- a/e2e/pages/adf/process-services/formFields.ts +++ b/e2e/pages/adf/process-services/formFields.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by, element } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class FormFields { @@ -35,7 +35,7 @@ export class FormFields { setFieldValue(locator, field, value) { const fieldElement = element(locator(field)); - Util.waitUntilElementIsVisible(fieldElement); + BrowserVisibility.waitUntilElementIsVisible(fieldElement); fieldElement.clear(); fieldElement.sendKeys(value); return this; @@ -43,29 +43,29 @@ export class FormFields { checkWidgetIsVisible(fieldId) { const fieldElement = element.all(by.css(`adf-form-field div[id='field-${fieldId}-container']`)).first(); - Util.waitUntilElementIsVisible(fieldElement); + BrowserVisibility.waitUntilElementIsVisible(fieldElement); } checkWidgetIsHidden(fieldId) { const hiddenElement = element(by.css(`adf-form-field div[id='field-${fieldId}-container'][hidden]`)); - Util.waitUntilElementIsVisible(hiddenElement); + BrowserVisibility.waitUntilElementIsVisible(hiddenElement); } getWidget(fieldId) { const widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); - Util.waitUntilElementIsVisible(widget); + BrowserVisibility.waitUntilElementIsVisible(widget); return widget; } getFieldValue(fieldId, valueLocatorParam?: any) { const value = this.getWidget(fieldId).element(valueLocatorParam || this.valueLocator); - Util.waitUntilElementIsVisible(value); + BrowserVisibility.waitUntilElementIsVisible(value); return value.getAttribute('value'); } getFieldLabel(fieldId, labelLocatorParam?: any) { const label = this.getWidget(fieldId).all(labelLocatorParam || this.labelLocator).first(); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } @@ -76,96 +76,96 @@ export class FormFields { getFieldText(fieldId, labelLocatorParam?: any) { const label = this.getWidget(fieldId).element(labelLocatorParam || this.labelLocator); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } getFieldPlaceHolder(fieldId, locator = 'input') { const placeHolderLocator = element(by.css(`${locator}#${fieldId}`)).getAttribute('placeholder'); - Util.waitUntilElementIsVisible(placeHolderLocator); + BrowserVisibility.waitUntilElementIsVisible(placeHolderLocator); return placeHolderLocator; } checkFieldValue(locator, field, val) { - Util.waitUntilElementHasValue(element(locator(field)), val); + BrowserVisibility.waitUntilElementHasValue(element(locator(field)), val); return this; } refreshForm() { - Util.waitUntilElementIsVisible(this.refreshButton); + BrowserVisibility.waitUntilElementIsVisible(this.refreshButton); this.refreshButton.click(); return this; } saveForm() { - Util.waitUntilElementIsVisible(this.saveButton); - Util.waitUntilElementIsClickable(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsClickable(this.saveButton); this.saveButton.click(); return this; } noFormIsDisplayed() { - Util.waitUntilElementIsNotOnPage(this.formContent); + BrowserVisibility.waitUntilElementIsNotOnPage(this.formContent); return this; } checkFormIsDisplayed() { - Util.waitUntilElementIsVisible(this.formContent); + BrowserVisibility.waitUntilElementIsVisible(this.formContent); return this; } getNoFormMessage() { - Util.waitUntilElementIsVisible(this.noFormMessage); + BrowserVisibility.waitUntilElementIsVisible(this.noFormMessage); return this.noFormMessage.getText(); } getCompletedTaskNoFormMessage() { - Util.waitUntilElementIsVisible(this.completedTaskNoFormMessage); + BrowserVisibility.waitUntilElementIsVisible(this.completedTaskNoFormMessage); return this.completedTaskNoFormMessage.getText(); } clickOnAttachFormButton() { - Util.waitUntilElementIsVisible(this.attachFormButton); + BrowserVisibility.waitUntilElementIsVisible(this.attachFormButton); this.attachFormButton.click(); return this; } selectForm(formName) { - Util.waitUntilElementIsVisible(this.selectFormDropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(this.selectFormDropDownArrow); this.selectFormDropDownArrow.click(); - Util.waitUntilElementIsVisible(this.selectFormContent); + BrowserVisibility.waitUntilElementIsVisible(this.selectFormContent); this.selectFormFromDropDown(formName); return this; } selectFormFromDropDown(formName) { const formNameElement = element(by.cssContainingText('span', formName)); - Util.waitUntilElementIsVisible(formNameElement); + BrowserVisibility.waitUntilElementIsVisible(formNameElement); formNameElement.click(); } checkWidgetIsReadOnlyMode(fieldId) { const widget = element(by.css(`adf-form-field div[id='field-${fieldId}-container']`)); const widgetReadOnly = widget.element(by.css('div[class*="adf-readonly"]')); - Util.waitUntilElementIsVisible(widgetReadOnly); + BrowserVisibility.waitUntilElementIsVisible(widgetReadOnly); return widgetReadOnly; } completeForm() { - Util.waitUntilElementIsVisible(this.completeButton); + BrowserVisibility.waitUntilElementIsVisible(this.completeButton); return this.completeButton.click(); } setValueInInputById(fieldId, value) { const input = element(by.id(fieldId)); - Util.waitUntilElementIsVisible(input); + BrowserVisibility.waitUntilElementIsVisible(input); input.clear(); input.sendKeys(value); return this; } isCompleteFormButtonDisabled() { - Util.waitUntilElementIsVisible(this.completeButton); + BrowserVisibility.waitUntilElementIsVisible(this.completeButton); return this.completeButton.getAttribute('disabled'); } } diff --git a/e2e/pages/adf/process-services/formPage.ts b/e2e/pages/adf/process-services/formPage.ts index 9ccde1bc17..0684eecde4 100644 --- a/e2e/pages/adf/process-services/formPage.ts +++ b/e2e/pages/adf/process-services/formPage.ts @@ -16,28 +16,28 @@ */ import { element, by } from 'protractor'; -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class FormPage { errorLog = element(by.css('div[class*="console"]')); checkErrorMessageForWidgetIsDisplayed(errorMessage) { - return Util.waitUntilElementIsVisible(element(by.cssContainingText('.adf-error-text', errorMessage))); + return BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText('.adf-error-text', errorMessage))); } checkErrorMessageForWidgetIsNotDisplayed(errorMessage) { - return Util.waitUntilElementIsNotVisible(element(by.cssContainingText('.adf-error-text', errorMessage))); + return BrowserVisibility.waitUntilElementIsNotVisible(element(by.cssContainingText('.adf-error-text', errorMessage))); } checkErrorLogMessage(errorMessage) { - Util.waitUntilElementIsVisible(this.errorLog); - return Util.waitUntilElementIsVisible(element(by.cssContainingText('div[class*="console"] p', errorMessage))); + BrowserVisibility.waitUntilElementIsVisible(this.errorLog); + return BrowserVisibility.waitUntilElementIsVisible(element(by.cssContainingText('div[class*="console"] p', errorMessage))); } checkErrorMessageIsNotDisplayed(errorMessage) { - Util.waitUntilElementIsVisible(this.errorLog); - return Util.waitUntilElementIsNotVisible(element(by.cssContainingText('div[class*="console"] p', errorMessage))); + BrowserVisibility.waitUntilElementIsVisible(this.errorLog); + return BrowserVisibility.waitUntilElementIsNotVisible(element(by.cssContainingText('div[class*="console"] p', errorMessage))); } } diff --git a/e2e/pages/adf/process-services/processDetailsPage.ts b/e2e/pages/adf/process-services/processDetailsPage.ts index 8e7ec3a943..78d4f76ea9 100644 --- a/e2e/pages/adf/process-services/processDetailsPage.ts +++ b/e2e/pages/adf/process-services/processDetailsPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by, element, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ProcessDetailsPage { @@ -49,88 +49,88 @@ export class ProcessDetailsPage { taskTitle = element(by.css('h2[class="adf-activiti-task-details__header"]')); checkDetailsAreDisplayed() { - Util.waitUntilElementIsVisible(this.processStatusField); - Util.waitUntilElementIsVisible(this.processEndDateField); - Util.waitUntilElementIsVisible(this.processCategoryField); - Util.waitUntilElementIsVisible(this.processBusinessKeyField); - Util.waitUntilElementIsVisible(this.processCreatedByField); - Util.waitUntilElementIsVisible(this.processCreatedField); - Util.waitUntilElementIsVisible(this.processIdField); - Util.waitUntilElementIsVisible(this.processDescription); - Util.waitUntilElementIsVisible(this.showDiagramButton); - Util.waitUntilElementIsVisible(this.activeTask); - Util.waitUntilElementIsVisible(this.cancelProcessButton); - Util.waitUntilElementIsVisible(this.commentInput); - Util.waitUntilElementIsVisible(this.auditLogButton); + BrowserVisibility.waitUntilElementIsVisible(this.processStatusField); + BrowserVisibility.waitUntilElementIsVisible(this.processEndDateField); + BrowserVisibility.waitUntilElementIsVisible(this.processCategoryField); + BrowserVisibility.waitUntilElementIsVisible(this.processBusinessKeyField); + BrowserVisibility.waitUntilElementIsVisible(this.processCreatedByField); + BrowserVisibility.waitUntilElementIsVisible(this.processCreatedField); + BrowserVisibility.waitUntilElementIsVisible(this.processIdField); + BrowserVisibility.waitUntilElementIsVisible(this.processDescription); + BrowserVisibility.waitUntilElementIsVisible(this.showDiagramButton); + BrowserVisibility.waitUntilElementIsVisible(this.activeTask); + BrowserVisibility.waitUntilElementIsVisible(this.cancelProcessButton); + BrowserVisibility.waitUntilElementIsVisible(this.commentInput); + BrowserVisibility.waitUntilElementIsVisible(this.auditLogButton); return this; } checkProcessTitleIsDisplayed() { - Util.waitUntilElementIsVisible(this.processTitle); + BrowserVisibility.waitUntilElementIsVisible(this.processTitle); return this.processTitle.getText(); } checkProcessDetailsMessage() { - Util.waitUntilElementIsVisible(this.processDetailsMessage); + BrowserVisibility.waitUntilElementIsVisible(this.processDetailsMessage); return this.processDetailsMessage.getText(); } getProcessStatus() { - Util.waitUntilElementIsVisible(this.processStatusField); + BrowserVisibility.waitUntilElementIsVisible(this.processStatusField); return this.processStatusField.getText(); } getEndDate() { - Util.waitUntilElementIsVisible(this.processEndDateField); + BrowserVisibility.waitUntilElementIsVisible(this.processEndDateField); return this.processEndDateField.getText(); } getProcessCategory() { - Util.waitUntilElementIsVisible(this.processCategoryField); + BrowserVisibility.waitUntilElementIsVisible(this.processCategoryField); return this.processCategoryField.getText(); } getBusinessKey() { - Util.waitUntilElementIsVisible(this.processBusinessKeyField); + BrowserVisibility.waitUntilElementIsVisible(this.processBusinessKeyField); return this.processBusinessKeyField.getText(); } getCreatedBy() { - Util.waitUntilElementIsVisible(this.processCreatedByField); + BrowserVisibility.waitUntilElementIsVisible(this.processCreatedByField); return this.processCreatedByField.getText(); } getCreated() { - Util.waitUntilElementIsVisible(this.processCreatedField); + BrowserVisibility.waitUntilElementIsVisible(this.processCreatedField); return this.processCreatedField.getText(); } getId() { - Util.waitUntilElementIsVisible(this.processIdField); + BrowserVisibility.waitUntilElementIsVisible(this.processIdField); return this.processIdField.getText(); } getProcessDescription() { - Util.waitUntilElementIsVisible(this.processDescription); + BrowserVisibility.waitUntilElementIsVisible(this.processDescription); return this.processDescription.getText(); } clickShowDiagram() { - Util.waitUntilElementIsVisible(this.showDiagramButton); - Util.waitUntilElementIsClickable(this.showDiagramButton); + BrowserVisibility.waitUntilElementIsVisible(this.showDiagramButton); + BrowserVisibility.waitUntilElementIsClickable(this.showDiagramButton); this.showDiagramButton.click(); - Util.waitUntilElementIsVisible(this.diagramCanvas); - Util.waitUntilElementIsVisible(this.backButton); - Util.waitUntilElementIsClickable(this.backButton); + BrowserVisibility.waitUntilElementIsVisible(this.diagramCanvas); + BrowserVisibility.waitUntilElementIsVisible(this.backButton); + BrowserVisibility.waitUntilElementIsClickable(this.backButton); this.backButton.click(); } checkShowDiagramIsDisabled() { - Util.waitUntilElementIsVisible(this.showDiagramButtonDisabled); + BrowserVisibility.waitUntilElementIsVisible(this.showDiagramButtonDisabled); } addComment(comment) { - Util.waitUntilElementIsVisible(this.commentInput); + BrowserVisibility.waitUntilElementIsVisible(this.commentInput); this.commentInput.sendKeys(comment); this.commentInput.sendKeys(protractor.Key.ENTER); return this; @@ -138,37 +138,37 @@ export class ProcessDetailsPage { checkCommentIsDisplayed(comment) { const commentInserted = element(by.cssContainingText('div[id="comment-message"]', comment)); - Util.waitUntilElementIsVisible(commentInserted); + BrowserVisibility.waitUntilElementIsVisible(commentInserted); return this; } clickAuditLogButton() { - Util.waitUntilElementIsVisible(this.auditLogButton); - Util.waitUntilElementIsClickable(this.auditLogButton); + BrowserVisibility.waitUntilElementIsVisible(this.auditLogButton); + BrowserVisibility.waitUntilElementIsClickable(this.auditLogButton); this.auditLogButton.click(); } clickCancelProcessButton() { - Util.waitUntilElementIsVisible(this.cancelProcessButton); - Util.waitUntilElementIsClickable(this.cancelProcessButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelProcessButton); + BrowserVisibility.waitUntilElementIsClickable(this.cancelProcessButton); this.cancelProcessButton.click(); } clickOnActiveTask() { - Util.waitUntilElementIsVisible(this.activeTask); + BrowserVisibility.waitUntilElementIsVisible(this.activeTask); return this.activeTask.click(); } clickOnCompletedTask() { - Util.waitUntilElementIsClickable(this.completedTask); + BrowserVisibility.waitUntilElementIsClickable(this.completedTask); return this.completedTask.click(); } checkActiveTaskTitleIsDisplayed() { - Util.waitUntilElementIsVisible(this.taskTitle); + BrowserVisibility.waitUntilElementIsVisible(this.taskTitle); } checkProcessDetailsCard() { - Util.waitUntilElementIsVisible(this.propertiesList); + BrowserVisibility.waitUntilElementIsVisible(this.propertiesList); } } diff --git a/e2e/pages/adf/process-services/processFiltersPage.ts b/e2e/pages/adf/process-services/processFiltersPage.ts index d906393228..5681ef3623 100644 --- a/e2e/pages/adf/process-services/processFiltersPage.ts +++ b/e2e/pages/adf/process-services/processFiltersPage.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { element, by } from 'protractor'; import { StartProcessPage } from './startProcessPage'; import { DataTableComponentPage } from '../dataTableComponentPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ProcessFiltersPage { @@ -44,52 +44,52 @@ export class ProcessFiltersPage { } clickRunningFilterButton() { - Util.waitUntilElementIsVisible(this.runningFilter); - Util.waitUntilElementIsClickable(this.runningFilter); + BrowserVisibility.waitUntilElementIsVisible(this.runningFilter); + BrowserVisibility.waitUntilElementIsClickable(this.runningFilter); return this.runningFilter.click(); } clickCompletedFilterButton() { - Util.waitUntilElementIsVisible(this.completedFilter); - Util.waitUntilElementIsClickable(this.completedFilter); + BrowserVisibility.waitUntilElementIsVisible(this.completedFilter); + BrowserVisibility.waitUntilElementIsClickable(this.completedFilter); this.completedFilter.click(); expect(this.completedFilter.isEnabled()).toBe(true); } clickAllFilterButton() { - Util.waitUntilElementIsVisible(this.allFilter); - Util.waitUntilElementIsClickable(this.allFilter); + BrowserVisibility.waitUntilElementIsVisible(this.allFilter); + BrowserVisibility.waitUntilElementIsClickable(this.allFilter); this.allFilter.click(); expect(this.allFilter.isEnabled()).toBe(true); } clickCreateProcessButton() { - Util.waitUntilElementIsOnPage(this.accordionMenu); - Util.waitUntilElementIsVisible(this.processesPage); - Util.waitUntilElementIsPresent(this.createProcessButton); + BrowserVisibility.waitUntilElementIsOnPage(this.accordionMenu); + BrowserVisibility.waitUntilElementIsVisible(this.processesPage); + BrowserVisibility.waitUntilElementIsPresent(this.createProcessButton); this.createProcessButton.click(); } clickNewProcessDropdown() { - Util.waitUntilElementIsOnPage(this.buttonWindow); - Util.waitUntilElementIsVisible(this.newProcessButton); - Util.waitUntilElementIsClickable(this.newProcessButton); + BrowserVisibility.waitUntilElementIsOnPage(this.buttonWindow); + BrowserVisibility.waitUntilElementIsVisible(this.newProcessButton); + BrowserVisibility.waitUntilElementIsClickable(this.newProcessButton); this.newProcessButton.click(); } checkNoContentMessage() { - return Util.waitUntilElementIsVisible(this.noContentMessage); + return BrowserVisibility.waitUntilElementIsVisible(this.noContentMessage); } selectFromProcessList(title) { const processName = element.all(by.css(`div[data-automation-id="text_${title}"]`)).first(); - Util.waitUntilElementIsVisible(processName); + BrowserVisibility.waitUntilElementIsVisible(processName); processName.click(); } checkFilterIsHighlighted(filterName) { const processNameHighlighted = element(by.css(`mat-list-item.adf-active span[data-automation-id='${filterName}_filter']`)); - Util.waitUntilElementIsVisible(processNameHighlighted); + BrowserVisibility.waitUntilElementIsVisible(processNameHighlighted); } numberOfProcessRows() { @@ -97,7 +97,7 @@ export class ProcessFiltersPage { } waitForTableBody() { - Util.waitUntilElementIsVisible(this.tableBody); + BrowserVisibility.waitUntilElementIsVisible(this.tableBody); } /** @@ -115,26 +115,26 @@ export class ProcessFiltersPage { checkFilterIsDisplayed(name) { const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); - return Util.waitUntilElementIsVisible(filterName); + return BrowserVisibility.waitUntilElementIsVisible(filterName); } checkFilterHasNoIcon(name) { const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); - Util.waitUntilElementIsVisible(filterName); - return Util.waitUntilElementIsNotOnPage(filterName.element(this.processIcon)); + BrowserVisibility.waitUntilElementIsVisible(filterName); + return BrowserVisibility.waitUntilElementIsNotOnPage(filterName.element(this.processIcon)); } getFilterIcon(name) { const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); - Util.waitUntilElementIsVisible(filterName); + BrowserVisibility.waitUntilElementIsVisible(filterName); const icon = filterName.element(this.processIcon); - Util.waitUntilElementIsVisible(icon); + BrowserVisibility.waitUntilElementIsVisible(icon); return icon.getText(); } checkFilterIsNotDisplayed(name) { const filterName = element(by.css(`span[data-automation-id='${name}_filter']`)); - return Util.waitUntilElementIsNotVisible(filterName); + return BrowserVisibility.waitUntilElementIsNotVisible(filterName); } checkProcessesSortedByNameAsc() { diff --git a/e2e/pages/adf/process-services/processListPage.ts b/e2e/pages/adf/process-services/processListPage.ts index ae161b1571..e90de2dd88 100644 --- a/e2e/pages/adf/process-services/processListPage.ts +++ b/e2e/pages/adf/process-services/processListPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; export class ProcessListPage { @@ -24,12 +24,12 @@ export class ProcessListPage { processInstanceList = element(by.css('adf-process-instance-list')); checkProcessListTitleIsDisplayed() { - Util.waitUntilElementIsVisible(this.processListTitle); + BrowserVisibility.waitUntilElementIsVisible(this.processListTitle); return this.processListTitle.getText(); } checkProcessListIsDisplayed() { - Util.waitUntilElementIsVisible(this.processInstanceList); + BrowserVisibility.waitUntilElementIsVisible(this.processInstanceList); } } diff --git a/e2e/pages/adf/process-services/processServicesPage.ts b/e2e/pages/adf/process-services/processServicesPage.ts index 97ad72b21b..f1a33944bb 100644 --- a/e2e/pages/adf/process-services/processServicesPage.ts +++ b/e2e/pages/adf/process-services/processServicesPage.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { AppNavigationBarPage } from './appNavigationBarPage'; import { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ProcessServicesPage { @@ -28,52 +28,52 @@ export class ProcessServicesPage { descriptionLocator = by.css('mat-card-subtitle[class*="subtitle"]'); checkApsContainer() { - Util.waitUntilElementIsVisible(this.apsAppsContainer); + BrowserVisibility.waitUntilElementIsVisible(this.apsAppsContainer); } goToApp(applicationName) { const app = element(by.css('mat-card[title="' + applicationName + '"]')); - Util.waitUntilElementIsVisible(app); + BrowserVisibility.waitUntilElementIsVisible(app); app.click(); return new AppNavigationBarPage(); } goToTaskApp() { - Util.waitUntilElementIsVisible(this.taskApp); + BrowserVisibility.waitUntilElementIsVisible(this.taskApp); this.taskApp.click(); return new AppNavigationBarPage(); } getAppIconType(applicationName) { const app = element(by.css('mat-card[title="' + applicationName + '"]')); - Util.waitUntilElementIsVisible(app); + BrowserVisibility.waitUntilElementIsVisible(app); const iconType = app.element(this.iconTypeLocator); - Util.waitUntilElementIsVisible(iconType); + BrowserVisibility.waitUntilElementIsVisible(iconType); return iconType.getText(); } getBackgroundColor(applicationName) { const app = element(by.css('mat-card[title="' + applicationName + '"]')); - Util.waitUntilElementIsVisible(app); + BrowserVisibility.waitUntilElementIsVisible(app); return app.getCssValue('background-color'); } getDescription(applicationName) { const app = element(by.css('mat-card[title="' + applicationName + '"]')); - Util.waitUntilElementIsVisible(app); + BrowserVisibility.waitUntilElementIsVisible(app); const description = app.element(this.descriptionLocator); - Util.waitUntilElementIsVisible(description); + BrowserVisibility.waitUntilElementIsVisible(description); return description.getText(); } checkAppIsNotDisplayed(applicationName) { const app = element(by.css('mat-card[title="' + applicationName + '"]')); - return Util.waitUntilElementIsNotOnPage(app); + return BrowserVisibility.waitUntilElementIsNotOnPage(app); } checkAppIsDisplayed(applicationName) { const app = element(by.css('mat-card[title="' + applicationName + '"]')); - return Util.waitUntilElementIsVisible(app); + return BrowserVisibility.waitUntilElementIsVisible(app); } } diff --git a/e2e/pages/adf/process-services/startProcessPage.ts b/e2e/pages/adf/process-services/startProcessPage.ts index 366de7f580..689394538e 100644 --- a/e2e/pages/adf/process-services/startProcessPage.ts +++ b/e2e/pages/adf/process-services/startProcessPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by, element, Key, protractor, browser } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class StartProcessPage { @@ -31,7 +31,7 @@ export class StartProcessPage { processDefinitionOptionsPanel = element(by.css('div[class*="processDefinitionOptions"]')); checkNoProcessMessage() { - Util.waitUntilElementIsVisible(this.noProcess); + BrowserVisibility.waitUntilElementIsVisible(this.noProcess); } pressDownArrowAndEnter() { @@ -40,16 +40,16 @@ export class StartProcessPage { } checkNoProcessDefinitionOptionIsDisplayed() { - Util.waitUntilElementIsNotOnPage(this.processDefinitionOptionsPanel); + BrowserVisibility.waitUntilElementIsNotOnPage(this.processDefinitionOptionsPanel); } getDefaultName() { - Util.waitUntilElementIsVisible(this.defaultProcessName); + BrowserVisibility.waitUntilElementIsVisible(this.defaultProcessName); return this.defaultProcessName.getAttribute('value'); } deleteDefaultName(name) { - Util.waitUntilElementIsVisible(this.processNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.processNameInput); this.processNameInput.getAttribute('value').then((currentValue) => { for (let i = currentValue.length; i >= 0; i--) { if (currentValue === name) { @@ -60,13 +60,13 @@ export class StartProcessPage { } enterProcessName(name) { - Util.waitUntilElementIsVisible(this.processNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.processNameInput); this.clearProcessName(); this.processNameInput.sendKeys(name); } clearProcessName() { - Util.waitUntilElementIsVisible(this.processNameInput); + BrowserVisibility.waitUntilElementIsVisible(this.processNameInput); this.processNameInput.clear(); } @@ -76,53 +76,53 @@ export class StartProcessPage { } clickProcessDropdownArrow() { - Util.waitUntilElementIsVisible(this.selectProcessDropdownArrow); - Util.waitUntilElementIsClickable(this.selectProcessDropdownArrow); + BrowserVisibility.waitUntilElementIsVisible(this.selectProcessDropdownArrow); + BrowserVisibility.waitUntilElementIsClickable(this.selectProcessDropdownArrow); this.selectProcessDropdownArrow.click(); } checkOptionIsDisplayed(name) { const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); - Util.waitUntilElementIsVisible(selectProcessDropdown); - Util.waitUntilElementIsClickable(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsVisible(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsClickable(selectProcessDropdown); return this; } checkOptionIsNotDisplayed(name) { const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); - Util.waitUntilElementIsNotOnPage(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsNotOnPage(selectProcessDropdown); return this; } selectOption(name) { const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); - Util.waitUntilElementIsVisible(selectProcessDropdown); - Util.waitUntilElementIsClickable(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsVisible(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsClickable(selectProcessDropdown); selectProcessDropdown.click(); return this; } typeProcessDefinition(name) { - Util.waitUntilElementIsVisible(this.processDefinition); - Util.waitUntilElementIsClickable(this.processDefinition); + BrowserVisibility.waitUntilElementIsVisible(this.processDefinition); + BrowserVisibility.waitUntilElementIsClickable(this.processDefinition); this.processDefinition.clear(); this.processDefinition.sendKeys(name); return this; } getProcessDefinitionValue() { - Util.waitUntilElementIsVisible(this.processDefinition); + BrowserVisibility.waitUntilElementIsVisible(this.processDefinition); return this.processDefinition.getAttribute('value'); } clickCancelProcessButton() { - Util.waitUntilElementIsVisible(this.cancelProcessButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelProcessButton); this.cancelProcessButton.click(); } clickFormStartProcessButton() { - Util.waitUntilElementIsVisible(this.formStartProcessButton); - Util.waitUntilElementIsClickable(this.formStartProcessButton); + BrowserVisibility.waitUntilElementIsVisible(this.formStartProcessButton); + BrowserVisibility.waitUntilElementIsClickable(this.formStartProcessButton); return this.formStartProcessButton.click(); } @@ -139,7 +139,7 @@ export class StartProcessPage { } checkSelectProcessPlaceholderIsDisplayed() { - Util.waitUntilElementIsVisible(this.processDefinition); + BrowserVisibility.waitUntilElementIsVisible(this.processDefinition); const processPlaceholder = this.processDefinition.getAttribute('value').then(((result) => { return result; })); @@ -148,7 +148,7 @@ export class StartProcessPage { checkValidationErrorIsDisplayed(error, elementRef = 'mat-error') { const errorElement = element(by.cssContainingText(elementRef, error)); - Util.waitUntilElementIsVisible(errorElement); + BrowserVisibility.waitUntilElementIsVisible(errorElement); return this; } @@ -159,7 +159,7 @@ export class StartProcessPage { } clearField(locator) { - Util.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsVisible(locator); locator.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { locator.sendKeys(protractor.Key.BACK_SPACE); diff --git a/e2e/pages/adf/process-services/taskDetailsPage.ts b/e2e/pages/adf/process-services/taskDetailsPage.ts index 8e7fe2c2d4..2e1daeab72 100644 --- a/e2e/pages/adf/process-services/taskDetailsPage.ts +++ b/e2e/pages/adf/process-services/taskDetailsPage.ts @@ -16,9 +16,9 @@ */ import { AppSettingsToggles } from './dialog/appSettingsToggles'; -import { Util } from '../../../util/util'; import { element, by, protractor, browser } from 'protractor'; import { TabsPage } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TaskDetailsPage { @@ -68,152 +68,152 @@ export class TaskDetailsPage { emptyTaskDetails = element(by.css('adf-task-details > div > div')); getTaskDetailsTitle() { - Util.waitUntilElementIsVisible(this.taskDetailsTitle); + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsTitle); return this.taskDetailsTitle.getText(); } checkSelectedForm(formName) { - Util.waitUntilElementIsVisible(this.attachFormName); + BrowserVisibility.waitUntilElementIsVisible(this.attachFormName); expect(formName).toEqual(this.attachFormName.getText()); } checkAttachFormButtonIsDisabled() { - Util.waitUntilElementIsVisible(this.disabledAttachFormButton); + BrowserVisibility.waitUntilElementIsVisible(this.disabledAttachFormButton); } checkAttachFormButtonIsEnabled() { - Util.waitUntilElementIsClickable(this.attachFormButton); + BrowserVisibility.waitUntilElementIsClickable(this.attachFormButton); } checkEditFormButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.editFormButton); + BrowserVisibility.waitUntilElementIsVisible(this.editFormButton); } clickEditFormButton() { - Util.waitUntilElementIsClickable(this.editFormButton); + BrowserVisibility.waitUntilElementIsClickable(this.editFormButton); return this.editFormButton.click(); } checkAttachFormDropdownIsDisplayed() { - Util.waitUntilElementIsVisible(this.attachFormDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.attachFormDropdown); } clickAttachFormDropdown() { - Util.waitUntilElementIsClickable(this.attachFormDropdown); + BrowserVisibility.waitUntilElementIsClickable(this.attachFormDropdown); return this.attachFormDropdown.click(); } selectAttachFormOption(option) { const selectedOption = element(by.cssContainingText('mat-option[role="option"]', option)); - Util.waitUntilElementIsClickable(selectedOption); + BrowserVisibility.waitUntilElementIsClickable(selectedOption); return selectedOption.click(); } checkCancelAttachFormIsDisplayed() { - Util.waitUntilElementIsVisible(this.cancelAttachForm); + BrowserVisibility.waitUntilElementIsVisible(this.cancelAttachForm); } noFormIsDisplayed() { - Util.waitUntilElementIsNotOnPage(this.formContent); + BrowserVisibility.waitUntilElementIsNotOnPage(this.formContent); return this; } clickCancelAttachForm() { - Util.waitUntilElementIsClickable(this.cancelAttachForm); + BrowserVisibility.waitUntilElementIsClickable(this.cancelAttachForm); return this.cancelAttachForm.click(); } checkRemoveAttachFormIsDisplayed() { - Util.waitUntilElementIsVisible(this.removeAttachForm); + BrowserVisibility.waitUntilElementIsVisible(this.removeAttachForm); } clickRemoveAttachForm() { - Util.waitUntilElementIsClickable(this.removeAttachForm); + BrowserVisibility.waitUntilElementIsClickable(this.removeAttachForm); return this.removeAttachForm.click(); } checkAttachFormButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.attachFormButton); + BrowserVisibility.waitUntilElementIsVisible(this.attachFormButton); } checkAttachFormButtonIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.attachFormButton); + BrowserVisibility.waitUntilElementIsNotOnPage(this.attachFormButton); } clickAttachFormButton() { - Util.waitUntilElementIsClickable(this.attachFormButton); + BrowserVisibility.waitUntilElementIsClickable(this.attachFormButton); return this.attachFormButton.click(); } checkFormIsAttached(formName) { - Util.waitUntilElementIsVisible(this.formNameField); + BrowserVisibility.waitUntilElementIsVisible(this.formNameField); this.formNameField.getText().then((attachedFormName) => { expect(attachedFormName).toEqual(formName); }); } getFormName() { - Util.waitUntilElementIsVisible(this.formNameField); + BrowserVisibility.waitUntilElementIsVisible(this.formNameField); return this.formNameField.getText(); } getAssignee() { - Util.waitUntilElementIsVisible(this.assigneeField); + BrowserVisibility.waitUntilElementIsVisible(this.assigneeField); return this.assigneeField.getText(); } getStatus() { - Util.waitUntilElementIsVisible(this.statusField); + BrowserVisibility.waitUntilElementIsVisible(this.statusField); return this.statusField.getText(); } getCategory() { - Util.waitUntilElementIsVisible(this.categoryField); + BrowserVisibility.waitUntilElementIsVisible(this.categoryField); return this.categoryField.getText(); } getParentName() { - Util.waitUntilElementIsVisible(this.parentNameField); + BrowserVisibility.waitUntilElementIsVisible(this.parentNameField); return this.parentNameField.getText(); } getParentTaskId() { - Util.waitUntilElementIsVisible(this.parentTaskIdField); + BrowserVisibility.waitUntilElementIsVisible(this.parentTaskIdField); return this.parentTaskIdField.getText(); } getDuration() { - Util.waitUntilElementIsVisible(this.durationField); + BrowserVisibility.waitUntilElementIsVisible(this.durationField); return this.durationField.getText(); } getEndDate() { - Util.waitUntilElementIsVisible(this.endDateField); + BrowserVisibility.waitUntilElementIsVisible(this.endDateField); return this.endDateField.getText(); } getCreated() { - Util.waitUntilElementIsVisible(this.createdField); + BrowserVisibility.waitUntilElementIsVisible(this.createdField); return this.createdField.getText(); } getId() { - Util.waitUntilElementIsVisible(this.idField); + BrowserVisibility.waitUntilElementIsVisible(this.idField); return this.idField.getText(); } getDescription() { - Util.waitUntilElementIsVisible(this.descriptionField); + BrowserVisibility.waitUntilElementIsVisible(this.descriptionField); return this.descriptionField.getText(); } getDueDate() { - Util.waitUntilElementIsVisible(this.dueDateField); + BrowserVisibility.waitUntilElementIsVisible(this.dueDateField); return this.dueDateField.getText(); } getTitle() { - Util.waitUntilElementIsVisible(this.activitiesTitle); + BrowserVisibility.waitUntilElementIsVisible(this.activitiesTitle); return this.activitiesTitle.getText(); } @@ -230,34 +230,34 @@ export class TaskDetailsPage { } addComment(comment) { - Util.waitUntilElementIsVisible(this.commentField); + BrowserVisibility.waitUntilElementIsVisible(this.commentField); this.commentField.sendKeys(comment); this.addCommentButton.click(); return this; } clearComment(comment) { - Util.waitUntilElementIsVisible(this.commentField); + BrowserVisibility.waitUntilElementIsVisible(this.commentField); this.commentField.sendKeys(protractor.Key.ENTER); return this; } checkCommentIsDisplayed(comment) { const row = element(by.cssContainingText('div[id="comment-message"]', comment)); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return this; } clickInvolvePeopleButton() { - Util.waitUntilElementIsVisible(this.involvePeopleButton); - Util.waitUntilElementIsClickable(this.involvePeopleButton); + BrowserVisibility.waitUntilElementIsVisible(this.involvePeopleButton); + BrowserVisibility.waitUntilElementIsClickable(this.involvePeopleButton); browser.actions().mouseMove(this.involvePeopleButton).perform(); this.involvePeopleButton.click(); return this; } typeUser(user) { - Util.waitUntilElementIsVisible(this.addPeopleField); + BrowserVisibility.waitUntilElementIsVisible(this.addPeopleField); this.addPeopleField.sendKeys(user); return this; } @@ -269,45 +269,45 @@ export class TaskDetailsPage { checkUserIsSelected(user) { const row = element(by.cssContainingText('div[class*="search-list-container"] div[class*="people-full-name"]', user)); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return this; } clickAddInvolvedUserButton() { - Util.waitUntilElementIsVisible(this.addInvolvedUserButton); - Util.waitUntilElementIsClickable(this.addInvolvedUserButton); + BrowserVisibility.waitUntilElementIsVisible(this.addInvolvedUserButton); + BrowserVisibility.waitUntilElementIsClickable(this.addInvolvedUserButton); this.addInvolvedUserButton.click(); return this; } getRowsUser(user) { const row = element(by.cssContainingText('div[class*="people-full-name"]', user)); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return row; } removeInvolvedUser(user) { const row = this.getRowsUser(user).element(by.xpath('ancestor::div[contains(@class, "adf-datatable-row")]')); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); row.element(by.css('button[data-automation-id="action_menu_0"]')).click(); - Util.waitUntilElementIsVisible(this.removeInvolvedPeople); + BrowserVisibility.waitUntilElementIsVisible(this.removeInvolvedPeople); return this.removeInvolvedPeople.click(); } getInvolvedUserEmail(user) { const email = this.getRowsUser(user).element(this.emailInvolvedUser); - Util.waitUntilElementIsVisible(email); + BrowserVisibility.waitUntilElementIsVisible(email); return email.getText(); } getInvolvedUserEditAction(user) { const edit = this.getRowsUser(user).element(this.editActionInvolvedUser); - Util.waitUntilElementIsVisible(edit); + BrowserVisibility.waitUntilElementIsVisible(edit); return edit.getText(); } clickAuditLogButton() { - Util.waitUntilElementIsVisible(this.auditLogButton); + BrowserVisibility.waitUntilElementIsVisible(this.auditLogButton); this.auditLogButton.click(); } @@ -316,115 +316,115 @@ export class TaskDetailsPage { } taskInfoDrawerIsDisplayed() { - Util.waitUntilElementIsVisible(this.taskDetailsInfoDrawer); + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsInfoDrawer); } taskInfoDrawerIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.taskDetailsInfoDrawer); + BrowserVisibility.waitUntilElementIsNotOnPage(this.taskDetailsInfoDrawer); } checkNoPeopleIsInvolved() { - Util.waitUntilElementIsVisible(this.noPeopleInvolved); + BrowserVisibility.waitUntilElementIsVisible(this.noPeopleInvolved); return this; } clickCancelInvolvePeopleButton() { - Util.waitUntilElementIsVisible(this.cancelInvolvePeopleButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelInvolvePeopleButton); this.cancelInvolvePeopleButton.click(); return this; } getInvolvePeopleHeader() { - Util.waitUntilElementIsVisible(this.involvePeopleHeader); + BrowserVisibility.waitUntilElementIsVisible(this.involvePeopleHeader); return this.involvePeopleHeader.getText(); } getInvolvePeoplePlaceholder() { - Util.waitUntilElementIsVisible(this.addPeopleField); + BrowserVisibility.waitUntilElementIsVisible(this.addPeopleField); return this.addPeopleField.getAttribute('placeholder'); } checkCancelButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.cancelInvolvePeopleButton); - Util.waitUntilElementIsClickable(this.cancelInvolvePeopleButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelInvolvePeopleButton); + BrowserVisibility.waitUntilElementIsClickable(this.cancelInvolvePeopleButton); return this; } checkAddPeopleButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.addInvolvedUserButton); - Util.waitUntilElementIsClickable(this.addInvolvedUserButton); + BrowserVisibility.waitUntilElementIsVisible(this.addInvolvedUserButton); + BrowserVisibility.waitUntilElementIsClickable(this.addInvolvedUserButton); return this; } noUserIsDisplayedInSearchInvolvePeople(user) { - Util.waitUntilElementIsNotOnPage(element(by.cssContainingText('div[class*="people-full-name"]', user))); + BrowserVisibility.waitUntilElementIsNotOnPage(element(by.cssContainingText('div[class*="people-full-name"]', user))); return this; } getInvolvedPeopleTitle() { - Util.waitUntilElementIsVisible(this.peopleTitle); + BrowserVisibility.waitUntilElementIsVisible(this.peopleTitle); return this.peopleTitle.getText(); } getInvolvedPeopleInitialImage(user) { const pic = this.getRowsUser(user).element(this.involvedUserPic); - Util.waitUntilElementIsVisible(pic); + BrowserVisibility.waitUntilElementIsVisible(pic); return pic.getText(); } checkTaskDetails() { - Util.waitUntilElementIsVisible(this.taskDetailsSection); + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsSection); return this.taskDetailsSection.getText(); } checkTaskDetailsEmpty() { - Util.waitUntilElementIsVisible(this.taskDetailsEmptySection); + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsEmptySection); return this.taskDetailsEmptySection.getText(); } checkTaskDetailsDisplayed() { - Util.waitUntilElementIsVisible(this.taskDetailsSection); - Util.waitUntilElementIsVisible(this.formNameField); - Util.waitUntilElementIsVisible(this.assigneeField); - Util.waitUntilElementIsVisible(this.statusField); - Util.waitUntilElementIsVisible(this.categoryField); - Util.waitUntilElementIsVisible(this.parentNameField); - Util.waitUntilElementIsVisible(this.createdField); - Util.waitUntilElementIsVisible(this.idField); - Util.waitUntilElementIsVisible(this.descriptionField); - Util.waitUntilElementIsVisible(this.dueDateField); - Util.waitUntilElementIsVisible(this.activitiesTitle); + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsSection); + BrowserVisibility.waitUntilElementIsVisible(this.formNameField); + BrowserVisibility.waitUntilElementIsVisible(this.assigneeField); + BrowserVisibility.waitUntilElementIsVisible(this.statusField); + BrowserVisibility.waitUntilElementIsVisible(this.categoryField); + BrowserVisibility.waitUntilElementIsVisible(this.parentNameField); + BrowserVisibility.waitUntilElementIsVisible(this.createdField); + BrowserVisibility.waitUntilElementIsVisible(this.idField); + BrowserVisibility.waitUntilElementIsVisible(this.descriptionField); + BrowserVisibility.waitUntilElementIsVisible(this.dueDateField); + BrowserVisibility.waitUntilElementIsVisible(this.activitiesTitle); return this.taskDetailsSection.getText(); } clickCompleteTask() { - Util.waitUntilElementIsVisible(this.completeTask); + BrowserVisibility.waitUntilElementIsVisible(this.completeTask); return this.completeTask.click(); } checkCompleteFormButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.completeFormTask); + BrowserVisibility.waitUntilElementIsVisible(this.completeFormTask); return this.completeFormTask; } checkCompleteTaskButtonIsEnabled() { - Util.waitUntilElementIsClickable(this.completeTask); + BrowserVisibility.waitUntilElementIsClickable(this.completeTask); return this; } checkCompleteTaskButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.completeTask); + BrowserVisibility.waitUntilElementIsVisible(this.completeTask); return this; } clickCompleteFormTask() { - Util.waitUntilElementIsClickable(this.completeFormTask); + BrowserVisibility.waitUntilElementIsClickable(this.completeFormTask); return this.completeFormTask.click(); } getEmptyTaskDetailsMessage() { - Util.waitUntilElementIsVisible(this.emptyTaskDetails); + BrowserVisibility.waitUntilElementIsVisible(this.emptyTaskDetails); return this.emptyTaskDetails.getText(); } diff --git a/e2e/pages/adf/process-services/taskFiltersPage.ts b/e2e/pages/adf/process-services/taskFiltersPage.ts index 19e167d081..4bc0acc193 100644 --- a/e2e/pages/adf/process-services/taskFiltersPage.ts +++ b/e2e/pages/adf/process-services/taskFiltersPage.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TaskFiltersPage { @@ -28,29 +28,29 @@ export class TaskFiltersPage { } checkTaskFilterIsDisplayed() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); return this; } getTaskFilterIcon() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); const icon = this.filter.element(this.taskIcon); - Util.waitUntilElementIsVisible(icon); + BrowserVisibility.waitUntilElementIsVisible(icon); return icon.getText(); } checkTaskFilterHasNoIcon() { - Util.waitUntilElementIsVisible(this.filter); - Util.waitUntilElementIsNotOnPage(this.filter.element(this.taskIcon)); + BrowserVisibility.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsNotOnPage(this.filter.element(this.taskIcon)); } clickTaskFilter() { - Util.waitUntilElementIsVisible(this.filter); + BrowserVisibility.waitUntilElementIsVisible(this.filter); return this.filter.click(); } checkTaskFilterNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.filter); + BrowserVisibility.waitUntilElementIsNotVisible(this.filter); return this.filter; } diff --git a/e2e/pages/adf/process-services/tasksListPage.ts b/e2e/pages/adf/process-services/tasksListPage.ts index ecd5338af6..4faaa94eb8 100644 --- a/e2e/pages/adf/process-services/tasksListPage.ts +++ b/e2e/pages/adf/process-services/tasksListPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { DataTableComponentPage } from '../dataTableComponentPage'; import { by, element } from 'protractor'; @@ -54,12 +54,12 @@ export class TasksListPage { } checkTaskListIsLoaded() { - Util.waitUntilElementIsVisible(this.taskList); + BrowserVisibility.waitUntilElementIsVisible(this.taskList); return this; } getNoTasksFoundMessage() { - Util.waitUntilElementIsVisible(this.noTasksFound); + BrowserVisibility.waitUntilElementIsVisible(this.noTasksFound); return this.noTasksFound.getText(); } diff --git a/e2e/pages/adf/process-services/tasksPage.ts b/e2e/pages/adf/process-services/tasksPage.ts index c03f26b289..876cbd87be 100644 --- a/e2e/pages/adf/process-services/tasksPage.ts +++ b/e2e/pages/adf/process-services/tasksPage.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { StartTaskDialog } from './dialog/startTaskDialog'; import { FormFields } from './formFields'; import { TaskDetailsPage } from './taskDetailsPage'; @@ -24,6 +23,7 @@ import { FiltersPage } from './filtersPage'; import { ChecklistDialog } from './dialog/createChecklistDialog'; import { TasksListPage } from './tasksListPage'; import { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TasksPage { @@ -49,17 +49,17 @@ export class TasksPage { } createButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.createButton); + BrowserVisibility.waitUntilElementIsVisible(this.createButton); return this; } newTaskButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.newTaskButton); + BrowserVisibility.waitUntilElementIsVisible(this.newTaskButton); return this; } clickOnCreateButton() { - Util.waitUntilElementIsClickable(this.createButton); + BrowserVisibility.waitUntilElementIsClickable(this.createButton); this.createButton.click(); return this; } @@ -85,80 +85,80 @@ export class TasksPage { } clickOnAddChecklistButton() { - Util.waitUntilElementIsClickable(this.addChecklistButton); + BrowserVisibility.waitUntilElementIsClickable(this.addChecklistButton); this.addChecklistButton.click(); return new ChecklistDialog(); } getRowsName(name) { const row = element(this.checklistContainer).element(by.cssContainingText('span', name)); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return row; } getChecklistByName(checklist) { const row = this.getRowsName(checklist).element(this.rowByRowName); - Util.waitUntilElementIsVisible(row); + BrowserVisibility.waitUntilElementIsVisible(row); return row; } checkChecklistIsDisplayed(checklist) { - Util.waitUntilElementIsVisible(this.getChecklistByName(checklist)); + BrowserVisibility.waitUntilElementIsVisible(this.getChecklistByName(checklist)); return this; } checkChecklistIsNotDisplayed(checklist) { - Util.waitUntilElementIsNotOnPage(element(this.checklistContainer).element(by.cssContainingText('span', checklist))); + BrowserVisibility.waitUntilElementIsNotOnPage(element(this.checklistContainer).element(by.cssContainingText('span', checklist))); return this; } checkTaskTitle(taskName) { - Util.waitUntilElementIsVisible(element(by.css(this.taskTitle))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(this.taskTitle))); const title = element(by.cssContainingText(this.taskTitle, taskName)); - Util.waitUntilElementIsVisible(title); + BrowserVisibility.waitUntilElementIsVisible(title); return this; } completeTaskNoForm() { - Util.waitUntilElementIsClickable(this.completeButtonNoForm); + BrowserVisibility.waitUntilElementIsClickable(this.completeButtonNoForm); this.completeButtonNoForm.click(); } completeTaskNoFormNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.completeButtonNoForm); + BrowserVisibility.waitUntilElementIsNotOnPage(this.completeButtonNoForm); return this; } checkChecklistDialogIsDisplayed() { - Util.waitUntilElementIsVisible(this.checklistDialog); + BrowserVisibility.waitUntilElementIsVisible(this.checklistDialog); return this; } checkChecklistDialogIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.checklistDialog); + BrowserVisibility.waitUntilElementIsNotOnPage(this.checklistDialog); return this; } checkNoChecklistIsDisplayed() { - Util.waitUntilElementIsVisible(this.checklistNoMessage); + BrowserVisibility.waitUntilElementIsVisible(this.checklistNoMessage); return this; } getNumberOfChecklists() { - Util.waitUntilElementIsVisible(this.numberOfChecklists); + BrowserVisibility.waitUntilElementIsVisible(this.numberOfChecklists); return this.numberOfChecklists.getText(); } removeChecklists(checklist) { const row = this.getRowsName(checklist).element(this.rowByRowName); - Util.waitUntilElementIsVisible(row.element(by.css('mat-icon'))); + BrowserVisibility.waitUntilElementIsVisible(row.element(by.css('mat-icon'))); row.element(by.css('mat-icon')).click(); return this; } checkChecklistsRemoveButtonIsNotDisplayed(checklist) { const row = this.getRowsName(checklist).element(this.rowByRowName); - Util.waitUntilElementIsNotOnPage(row.element(by.css('mat-icon'))); + BrowserVisibility.waitUntilElementIsNotOnPage(row.element(by.css('mat-icon'))); return this; } diff --git a/e2e/pages/adf/process-services/widgets/amountWidget.ts b/e2e/pages/adf/process-services/widgets/amountWidget.ts index 10813288df..27e4e50e50 100644 --- a/e2e/pages/adf/process-services/widgets/amountWidget.ts +++ b/e2e/pages/adf/process-services/widgets/amountWidget.ts @@ -16,7 +16,7 @@ */ import { element, by, protractor } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { FormFields } from '../formFields'; export class AmountWidget { @@ -26,7 +26,7 @@ export class AmountWidget { getAmountFieldLabel(fieldId) { const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } @@ -39,7 +39,7 @@ export class AmountWidget { } removeFromAmountWidget(fieldId) { - Util.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); + BrowserVisibility.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); const amountWidgetInput = element(by.id(fieldId)); amountWidgetInput.getAttribute('value').then((result) => { @@ -51,7 +51,7 @@ export class AmountWidget { clearFieldValue(fieldId) { const numberField = element(by.id(fieldId)); - Util.waitUntilElementIsVisible(numberField); + BrowserVisibility.waitUntilElementIsVisible(numberField); return numberField.clear(); } @@ -61,7 +61,7 @@ export class AmountWidget { getErrorMessage(fieldId) { const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } diff --git a/e2e/pages/adf/process-services/widgets/attachFileWidget.ts b/e2e/pages/adf/process-services/widgets/attachFileWidget.ts index 5d54828c1a..401563bd85 100644 --- a/e2e/pages/adf/process-services/widgets/attachFileWidget.ts +++ b/e2e/pages/adf/process-services/widgets/attachFileWidget.ts @@ -18,7 +18,7 @@ import { FormFields } from '../formFields'; import TestConfig = require('../../../../test.config'); import path = require('path'); -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import remote = require('selenium-webdriver/remote'); import { element, by, browser } from 'protractor'; @@ -33,10 +33,10 @@ export class AttachFileWidget { browser.setFileDetector(new remote.FileDetector()); const widget = this.formFields.getWidget(fieldId); const uploadButton = widget.element(this.uploadLocator); - Util.waitUntilElementIsVisible(uploadButton); + BrowserVisibility.waitUntilElementIsVisible(uploadButton); uploadButton.click(); - Util.waitUntilElementIsVisible(this.localStorageButton); + BrowserVisibility.waitUntilElementIsVisible(this.localStorageButton); this.localStorageButton.sendKeys(path.resolve(path.join(TestConfig.main.rootPath, fileLocation))); return this; } @@ -44,13 +44,13 @@ export class AttachFileWidget { checkFileIsAttached(fieldId, name) { const widget = this.formFields.getWidget(fieldId); const fileAttached = widget.element(this.filesListLocator).element(by.cssContainingText('mat-list-item span ', name)); - Util.waitUntilElementIsVisible(fileAttached); + BrowserVisibility.waitUntilElementIsVisible(fileAttached); return this; } viewFile(name) { const fileView = element(this.filesListLocator).element(by.cssContainingText('mat-list-item span ', name)); - Util.waitUntilElementIsVisible(fileView); + BrowserVisibility.waitUntilElementIsVisible(fileView); fileView.click(); browser.actions().doubleClick(fileView).perform(); return this; diff --git a/e2e/pages/adf/process-services/widgets/checkboxWidget.ts b/e2e/pages/adf/process-services/widgets/checkboxWidget.ts index 7f5c8889a6..1c5bbae855 100644 --- a/e2e/pages/adf/process-services/widgets/checkboxWidget.ts +++ b/e2e/pages/adf/process-services/widgets/checkboxWidget.ts @@ -16,23 +16,22 @@ */ import { FormFields } from '../formFields'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { by, element } from 'protractor'; export class CheckboxWidget { formFields = new FormFields(); - checkboxField = element(by.css('span[class*="mat-checkbox-label"]')); checkboxLabel = element(by.css('span[class*="mat-checkbox-label"]')); getCheckboxLabel() { - Util.waitUntilElementIsVisible(this.checkboxLabel); + BrowserVisibility.waitUntilElementIsVisible(this.checkboxLabel); return this.checkboxLabel.getText(); } clickCheckboxInput(fieldId) { const checkboxInput = element.all(by.css(`mat-checkbox[id="${fieldId}"] div`)).first(); - Util.waitUntilElementIsVisible(checkboxInput); + BrowserVisibility.waitUntilElementIsVisible(checkboxInput); return checkboxInput.click(); } diff --git a/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts b/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts index f4241e6d6d..caf08fc6c5 100644 --- a/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dateTimeWidget.ts @@ -17,7 +17,7 @@ import { FormFields } from '../formFields'; import { element, by, protractor } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DateTimeWidget { @@ -28,13 +28,9 @@ export class DateTimeWidget { return this.formFields.checkWidgetIsVisible(fieldId); } - checkLabelIsVisible(fieldId) { - return this.formFields.checkWidgetIsVisible(fieldId); - } - getDateTimeLabel(fieldId) { const label = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } @@ -44,30 +40,30 @@ export class DateTimeWidget { clearDateTimeInput(fieldId) { const dateInput = element(by.id(fieldId)); - Util.waitUntilElementIsVisible(dateInput); + BrowserVisibility.waitUntilElementIsVisible(dateInput); return dateInput.clear(); } clickOutsideWidget(fieldId) { const form = this.formFields.getWidget(fieldId); - Util.waitUntilElementIsVisible(form); + BrowserVisibility.waitUntilElementIsVisible(form); return form.click(); } closeDataTimeWidget() { - Util.waitUntilElementIsVisible(this.outsideLayer); + BrowserVisibility.waitUntilElementIsVisible(this.outsideLayer); return this.outsideLayer.click(); } getErrorMessage(fieldId) { const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } selectDay(day) { const selectedDay = element(by.cssContainingText('div[class*="mat-datetimepicker-calendar-body-cell-content"]', day)); - Util.waitUntilElementIsVisible(selectedDay); + BrowserVisibility.waitUntilElementIsVisible(selectedDay); return selectedDay.click(); } @@ -77,7 +73,7 @@ export class DateTimeWidget { private selectTime(time) { const selectedTime = element(by.cssContainingText('div[class*="mat-datetimepicker-clock-cell"]', time)); - Util.waitUntilElementIsClickable(selectedTime); + BrowserVisibility.waitUntilElementIsClickable(selectedTime); return selectedTime.click(); } @@ -94,7 +90,7 @@ export class DateTimeWidget { } removeFromDatetimeWidget(fieldId) { - Util.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); + BrowserVisibility.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); const amountWidgetInput = element(by.id(fieldId)); amountWidgetInput.getAttribute('value').then((result) => { diff --git a/e2e/pages/adf/process-services/widgets/dateWidget.ts b/e2e/pages/adf/process-services/widgets/dateWidget.ts index c72c2db5d2..9d9148ec31 100644 --- a/e2e/pages/adf/process-services/widgets/dateWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dateWidget.ts @@ -17,7 +17,7 @@ import { FormFields } from '../formFields'; import { element, by, protractor } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DateWidget { @@ -33,7 +33,7 @@ export class DateWidget { getDateLabel(fieldId) { const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } @@ -44,24 +44,24 @@ export class DateWidget { clearDateInput(fieldId) { const dateInput = element(by.id(fieldId)); - Util.waitUntilElementIsVisible(dateInput); + BrowserVisibility.waitUntilElementIsVisible(dateInput); return dateInput.clear(); } clickOutsideWidget(fieldId) { const form = this.formFields.getWidget(fieldId); - Util.waitUntilElementIsVisible(form); + BrowserVisibility.waitUntilElementIsVisible(form); return form.click(); } getErrorMessage(fieldId) { const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } removeFromDatetimeWidget(fieldId) { - Util.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); + BrowserVisibility.waitUntilElementIsVisible(this.formFields.getWidget(fieldId)); const dateWidgetInput = element(by.id(fieldId)); dateWidgetInput.getAttribute('value').then((result) => { diff --git a/e2e/pages/adf/process-services/widgets/dropdownWidget.ts b/e2e/pages/adf/process-services/widgets/dropdownWidget.ts index 500572179f..7cd86f9c0b 100644 --- a/e2e/pages/adf/process-services/widgets/dropdownWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dropdownWidget.ts @@ -17,7 +17,7 @@ import { FormFields } from '../formFields'; import { by, element } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DropdownWidget { @@ -38,12 +38,12 @@ export class DropdownWidget { openDropdown() { this.checkDropdownIsDisplayed(); - Util.waitUntilElementIsClickable(this.dropdown); + BrowserVisibility.waitUntilElementIsClickable(this.dropdown); return this.dropdown.click(); } checkDropdownIsDisplayed() { - Util.waitUntilElementIsVisible(this.dropdown); + BrowserVisibility.waitUntilElementIsVisible(this.dropdown); return this.dropdown; } } diff --git a/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts b/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts index 0369bb98a7..c38b7e0ee7 100644 --- a/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts +++ b/e2e/pages/adf/process-services/widgets/dynamicTableWidget.ts @@ -16,8 +16,8 @@ */ import { FormFields } from '../formFields'; -import { Util } from '../../../../util/util'; import { by, element, browser, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class DynamicTableWidget { @@ -48,63 +48,63 @@ export class DynamicTableWidget { } clickAddButton() { - Util.waitUntilElementIsVisible(this.addButton); + BrowserVisibility.waitUntilElementIsVisible(this.addButton); return this.addButton.click(); } clickAddRow() { - Util.waitUntilElementIsVisible(this.addRow); + BrowserVisibility.waitUntilElementIsVisible(this.addRow); return this.addRow.click(); } clickTableRow(rowNumber) { const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); - Util.waitUntilElementIsVisible(tableRowByIndex); + BrowserVisibility.waitUntilElementIsVisible(tableRowByIndex); return tableRowByIndex.click(); } clickEditButton() { - Util.waitUntilElementIsVisible(this.editButton); + BrowserVisibility.waitUntilElementIsVisible(this.editButton); return this.editButton.click(); } clickCancelButton() { - Util.waitUntilElementIsVisible(this.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); return this.cancelButton.click(); } setDatatableInput(text) { - Util.waitUntilElementIsVisible(this.dataTableInput); + BrowserVisibility.waitUntilElementIsVisible(this.dataTableInput); this.dataTableInput.clear(); return this.dataTableInput.sendKeys(text); } getTableRowText(rowNumber) { const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); - Util.waitUntilElementIsVisible(tableRowByIndex); + BrowserVisibility.waitUntilElementIsVisible(tableRowByIndex); return tableRowByIndex.getText(); } checkTableRowIsVisible(rowNumber) { const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); - return Util.waitUntilElementIsVisible(tableRowByIndex); + return BrowserVisibility.waitUntilElementIsVisible(tableRowByIndex); } checkTableRowIsNotVisible(rowNumber) { const tableRowByIndex = element(by.id('dynamictable-row-' + rowNumber)); - return Util.waitUntilElementIsNotVisible(tableRowByIndex); + return BrowserVisibility.waitUntilElementIsNotVisible(tableRowByIndex); } clickColumnDateTime() { - Util.waitUntilElementIsVisible(this.columnDateTime); + BrowserVisibility.waitUntilElementIsVisible(this.columnDateTime); this.columnDateTime.click(); - Util.waitUntilElementIsVisible(this.calendarHeader); - Util.waitUntilElementIsVisible(this.calendarContent); + BrowserVisibility.waitUntilElementIsVisible(this.calendarHeader); + BrowserVisibility.waitUntilElementIsVisible(this.calendarContent); browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); } addRandomStringOnDateTime(randomText) { - Util.waitUntilElementIsVisible(this.columnDateTime); + BrowserVisibility.waitUntilElementIsVisible(this.columnDateTime); this.columnDateTime.click(); browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); this.columnDateTime.sendKeys(randomText); @@ -113,33 +113,33 @@ export class DynamicTableWidget { } addRandomStringOnDate(randomText) { - Util.waitUntilElementIsVisible(this.columnDate); + BrowserVisibility.waitUntilElementIsVisible(this.columnDate); this.columnDate.click(); return this.columnDate.sendKeys(randomText); } clickSaveButton() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this.saveButton.click(); } checkErrorMessage() { - Util.waitUntilElementIsVisible(this.errorMessage); + BrowserVisibility.waitUntilElementIsVisible(this.errorMessage); return this.errorMessage.getText(); } clickDateWidget() { - Util.waitUntilElementIsVisible(this.dateWidget); + BrowserVisibility.waitUntilElementIsVisible(this.dateWidget); return this.dateWidget.click(); } getTableRow(rowNumber) { - return Util.waitUntilElementIsVisible(this.tableRow.get(rowNumber)); + return BrowserVisibility.waitUntilElementIsVisible(this.tableRow.get(rowNumber)); } checkItemIsPresent(item) { const row = element(by.cssContainingText('table tbody tr td span', item)); - const present = Util.waitUntilElementIsVisible(row); + const present = BrowserVisibility.waitUntilElementIsVisible(row); expect(present).toBe(true); } } diff --git a/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts b/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts index 6f3ef56ddf..bde523aab2 100644 --- a/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts +++ b/e2e/pages/adf/process-services/widgets/hyperlinkWidget.ts @@ -17,7 +17,7 @@ import { FormFields } from '../formFields'; import { by, element } from 'protractor'; -import { Util } from '../../../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class HyperlinkWidget { @@ -31,7 +31,7 @@ export class HyperlinkWidget { getFieldLabel(fieldId) { const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } } diff --git a/e2e/pages/adf/process-services/widgets/numberWidget.ts b/e2e/pages/adf/process-services/widgets/numberWidget.ts index dcf46b570d..139aec5fb3 100644 --- a/e2e/pages/adf/process-services/widgets/numberWidget.ts +++ b/e2e/pages/adf/process-services/widgets/numberWidget.ts @@ -16,8 +16,8 @@ */ import { element, by } from 'protractor'; -import { Util } from '../../../../util/util'; import { FormFields } from '../formFields'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class NumberWidget { @@ -25,7 +25,7 @@ export class NumberWidget { getNumberFieldLabel(fieldId) { const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } @@ -35,7 +35,7 @@ export class NumberWidget { clearFieldValue(fieldId) { const numberField = element(by.id(fieldId)); - Util.waitUntilElementIsVisible(numberField); + BrowserVisibility.waitUntilElementIsVisible(numberField); return numberField.clear(); } @@ -45,7 +45,7 @@ export class NumberWidget { getErrorMessage(fieldId) { const errorMessage = element(by.css(`adf-form-field div[id="field-${fieldId}-container"] div[class="adf-error-text"]`)); - Util.waitUntilElementIsVisible(errorMessage); + BrowserVisibility.waitUntilElementIsVisible(errorMessage); return errorMessage.getText(); } diff --git a/e2e/pages/adf/process-services/widgets/peopleWidget.ts b/e2e/pages/adf/process-services/widgets/peopleWidget.ts index 78fa36aba4..6a6f519ca0 100644 --- a/e2e/pages/adf/process-services/widgets/peopleWidget.ts +++ b/e2e/pages/adf/process-services/widgets/peopleWidget.ts @@ -16,8 +16,8 @@ */ import { FormFields } from '../formFields'; -import { Util } from '../../../../util/util'; import { by, element } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class PeopleWidget { @@ -28,8 +28,6 @@ export class PeopleWidget { labelLocator = by.css('div[class*="display-text-widget"]'); inputLocator = by.id('involvepeople'); peopleDropDownList = by.css('div[class*="adf-people-widget-list"]'); - userProfileImage = by.css('div[class*="adf-people-widget-pic"'); - userProfileName = by.css('div[class*="adf-people-label-name"'); getFieldLabel(fieldId) { return this.formFields.getFieldLabel(fieldId, this.labelLocator); @@ -48,17 +46,17 @@ export class PeopleWidget { } checkDropDownListIsDisplayed() { - return Util.waitUntilElementIsVisible(element(this.peopleDropDownList)); + return BrowserVisibility.waitUntilElementIsVisible(element(this.peopleDropDownList)); } checkUserIsListed(userName) { const user = element(by.cssContainingText('.adf-people-label-name', userName)); - return Util.waitUntilElementIsVisible(user); + return BrowserVisibility.waitUntilElementIsVisible(user); } checkUserNotListed(userName) { const user = element(by.xpath('div[text()="' + userName + '"]')); - return Util.waitUntilElementIsNotVisible(user); + return BrowserVisibility.waitUntilElementIsNotVisible(user); } selectUserFromDropDown(userName) { @@ -68,16 +66,16 @@ export class PeopleWidget { } checkPeopleFieldIsDisplayed() { - return Util.waitUntilElementIsVisible(this.peopleField); + return BrowserVisibility.waitUntilElementIsVisible(this.peopleField); } fillPeopleField(value) { - Util.waitUntilElementIsClickable(this.peopleField); + BrowserVisibility.waitUntilElementIsClickable(this.peopleField); return this.peopleField.sendKeys(value); } selectUserFromDropdown() { - Util.waitUntilElementIsVisible(this.firstResult); + BrowserVisibility.waitUntilElementIsVisible(this.firstResult); return this.firstResult.click(); } } diff --git a/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts b/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts index 317c28777e..55ccc88831 100644 --- a/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts +++ b/e2e/pages/adf/process-services/widgets/radioButtonsWidget.ts @@ -16,8 +16,8 @@ */ import { FormFields } from '../formFields'; -import { Util } from '../../../../util/util'; import { by, element } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class RadioButtonsWidget { @@ -29,7 +29,7 @@ export class RadioButtonsWidget { const optionLocator = by.css('label[for*="radiobuttons-option_' + optionNumber + '"]'); const option = this.formFields.getWidget(fieldId).element(optionLocator); - Util.waitUntilElementIsVisible(option); + BrowserVisibility.waitUntilElementIsVisible(option); return option.getText(); } @@ -37,18 +37,18 @@ export class RadioButtonsWidget { const optionLocator = by.css(`label[for*="${fieldId}-option_${optionNumber}"]`); const option = this.formFields.getWidget(fieldId).element(optionLocator); - Util.waitUntilElementIsVisible(option); + BrowserVisibility.waitUntilElementIsVisible(option); return option.click(); } isSelectionClean(fieldId) { const option = this.formFields.getWidget(fieldId).element(this.selectedOption); - return Util.waitUntilElementIsNotVisible(option); + return BrowserVisibility.waitUntilElementIsNotVisible(option); } getRadioWidgetLabel(fieldId) { const label = element.all(by.css(`adf-form-field div[id="field-${fieldId}-container"] label`)).first(); - Util.waitUntilElementIsVisible(label); + BrowserVisibility.waitUntilElementIsVisible(label); return label.getText(); } diff --git a/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts b/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts index 2df7b06424..f202cf108b 100644 --- a/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts +++ b/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts @@ -15,9 +15,9 @@ * limitations under the License. */ -import { Util } from '../../../util/util'; import { by, element, protractor } from 'protractor'; import { EditTaskFilterDialog } from '../dialog/editTaskFilterDialog'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class EditTaskFilterCloudComponent { @@ -35,7 +35,7 @@ export class EditTaskFilterCloudComponent { } clickCustomiseFilterHeader() { - Util.waitUntilElementIsVisible(this.customiseFilter); + BrowserVisibility.waitUntilElementIsVisible(this.customiseFilter); this.customiseFilter.click(); return this; } @@ -44,8 +44,8 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('status'); const stateElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(stateElement); - Util.waitUntilElementIsVisible(stateElement); + BrowserVisibility.waitUntilElementIsClickable(stateElement); + BrowserVisibility.waitUntilElementIsVisible(stateElement); stateElement.click(); return this; } @@ -58,8 +58,8 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('sort'); const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(sortElement); - Util.waitUntilElementIsVisible(sortElement); + BrowserVisibility.waitUntilElementIsClickable(sortElement); + BrowserVisibility.waitUntilElementIsVisible(sortElement); sortElement.click(); return this; } @@ -72,8 +72,8 @@ export class EditTaskFilterCloudComponent { this.clickOnDropDownArrow('order'); const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); - Util.waitUntilElementIsClickable(orderElement); - Util.waitUntilElementIsVisible(orderElement); + BrowserVisibility.waitUntilElementIsClickable(orderElement); + BrowserVisibility.waitUntilElementIsVisible(orderElement); orderElement.click(); return this; } @@ -84,13 +84,13 @@ export class EditTaskFilterCloudComponent { clickOnDropDownArrow(option) { const dropDownArrow = element(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")); - Util.waitUntilElementIsVisible(dropDownArrow); + BrowserVisibility.waitUntilElementIsVisible(dropDownArrow); dropDownArrow.click(); - Util.waitUntilElementIsVisible(this.selectedOption); + BrowserVisibility.waitUntilElementIsVisible(this.selectedOption); } setAssignment(option) { - Util.waitUntilElementIsVisible(this.assignment); + BrowserVisibility.waitUntilElementIsVisible(this.assignment); this.assignment.clear(); this.assignment.sendKeys(option); this.assignment.sendKeys(protractor.Key.ENTER); @@ -102,17 +102,17 @@ export class EditTaskFilterCloudComponent { } checkSaveButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); return this; } checkSaveAsButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); return this; } checkDeleteButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); return this; } @@ -129,20 +129,20 @@ export class EditTaskFilterCloudComponent { } clickSaveAsButton() { - Util.waitUntilElementIsClickable(this.saveAsButton); - Util.waitUntilElementIsVisible(this.saveAsButton); + BrowserVisibility.waitUntilElementIsClickable(this.saveAsButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); this.saveAsButton.click(); return this.editTaskFilter; } clickDeleteButton() { - Util.waitUntilElementIsVisible(this.deleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); this.deleteButton.click(); return this; } clickSaveButton() { - Util.waitUntilElementIsVisible(this.saveButton); + BrowserVisibility.waitUntilElementIsVisible(this.saveButton); this.saveButton.click(); return this; } diff --git a/e2e/pages/adf/searchFiltersPage.ts b/e2e/pages/adf/searchFiltersPage.ts index 8bc5724e3c..1db76ba82e 100644 --- a/e2e/pages/adf/searchFiltersPage.ts +++ b/e2e/pages/adf/searchFiltersPage.ts @@ -15,9 +15,9 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { element, by } from 'protractor'; import { SearchCategoriesPage } from './content-services/search/search-categories'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchFiltersPage { @@ -41,7 +41,7 @@ export class SearchFiltersPage { facetIntervalsByModified = element(by.css('mat-expansion-panel[data-automation-id="expansion-panel-TheModified"]')); checkSearchFiltersIsDisplayed() { - Util.waitUntilElementIsVisible(this.searchFilters); + BrowserVisibility.waitUntilElementIsVisible(this.searchFilters); } sizeRangeFilterPage() { @@ -69,7 +69,7 @@ export class SearchFiltersPage { } checkCustomFacetFieldLabelIsDisplayed(fieldLabel) { - Util.waitUntilElementIsVisible(element(by.css(`mat-expansion-panel[data-automation-id="expansion-panel-${fieldLabel}"]`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.css(`mat-expansion-panel[data-automation-id="expansion-panel-${fieldLabel}"]`))); } sizeSliderFilterPage() { @@ -283,12 +283,12 @@ export class SearchFiltersPage { } checkFileTypeFacetLabelIsDisplayed(fileType) { - Util.waitUntilElementIsVisible(this.fileTypeFilter.element(by.cssContainingText('.adf-facet-label', fileType))); + BrowserVisibility.waitUntilElementIsVisible(this.fileTypeFilter.element(by.cssContainingText('.adf-facet-label', fileType))); return this; } checkFileTypeFacetLabelIsNotDisplayed(fileType) { - Util.waitUntilElementIsNotVisible(this.fileTypeFilter.element(by.cssContainingText('.adf-facet-label', fileType))); + BrowserVisibility.waitUntilElementIsNotVisible(this.fileTypeFilter.element(by.cssContainingText('.adf-facet-label', fileType))); return this; } diff --git a/e2e/pages/adf/searchResultsPage.ts b/e2e/pages/adf/searchResultsPage.ts index 902fb94daf..c36305d517 100644 --- a/e2e/pages/adf/searchResultsPage.ts +++ b/e2e/pages/adf/searchResultsPage.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import { DataTableComponentPage } from './dataTableComponentPage'; import { SearchSortingPickerPage } from './content-services/search/components/search-sortingPicker.page'; import { element, by } from 'protractor'; import { ContentServicesPage } from './contentServicesPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SearchResultsPage { @@ -38,9 +38,9 @@ export class SearchResultsPage { closeActionButton() { const container = element(by.css('div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing')); - Util.waitUntilElementIsVisible(container); + BrowserVisibility.waitUntilElementIsVisible(container); container.click(); - Util.waitUntilElementIsNotVisible(container); + BrowserVisibility.waitUntilElementIsNotVisible(container); return this; } @@ -59,12 +59,12 @@ export class SearchResultsPage { } checkNoResultMessageIsDisplayed() { - Util.waitUntilElementIsVisible(this.noResultsMessage); + BrowserVisibility.waitUntilElementIsVisible(this.noResultsMessage); return this; } checkNoResultMessageIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.noResultsMessage); + BrowserVisibility.waitUntilElementIsNotOnPage(this.noResultsMessage); return this; } diff --git a/e2e/pages/adf/settingsPage.ts b/e2e/pages/adf/settingsPage.ts index bbdef90c41..ee83eb2b4b 100644 --- a/e2e/pages/adf/settingsPage.ts +++ b/e2e/pages/adf/settingsPage.ts @@ -16,8 +16,8 @@ */ import TestConfig = require('../../test.config'); -import { Util } from '../../util/util'; import { browser, by, element, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class SettingsPage { @@ -58,14 +58,14 @@ export class SettingsPage { goToSettingsPage() { browser.waitForAngularEnabled(true); browser.driver.get(this.settingsURL); - Util.waitUntilElementIsVisible(this.providerDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.providerDropdown); return this; } setProvider(option, selected) { - Util.waitUntilElementIsVisible(this.providerDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.providerDropdown); this.providerDropdown.click(); - Util.waitUntilElementIsVisible(option); + BrowserVisibility.waitUntilElementIsVisible(option); option.click(); return expect(this.selectedOption.getText()).toEqual(selected); } @@ -97,8 +97,8 @@ export class SettingsPage { setProviderEcmBpm() { this.goToSettingsPage(); this.setProvider(this.ecmAndBpm.option, this.ecmAndBpm.text); - Util.waitUntilElementIsVisible(this.bpmText); - Util.waitUntilElementIsVisible(this.ecmText); + BrowserVisibility.waitUntilElementIsVisible(this.bpmText); + BrowserVisibility.waitUntilElementIsVisible(this.ecmText); this.clickApply(); return this; } @@ -106,7 +106,7 @@ export class SettingsPage { setProviderBpm() { this.goToSettingsPage(); this.setProvider(this.bpm.option, this.bpm.text); - Util.waitUntilElementIsVisible(this.bpmText); + BrowserVisibility.waitUntilElementIsVisible(this.bpmText); this.clickApply(); return this; } @@ -114,7 +114,7 @@ export class SettingsPage { setProviderEcm() { this.goToSettingsPage(); this.setProvider(this.ecm.option, this.ecm.text); - Util.waitUntilElementIsVisible(this.ecmText); + BrowserVisibility.waitUntilElementIsVisible(this.ecmText); expect(this.bpmText.isPresent()).toBe(false); this.clickApply(); return this; @@ -123,28 +123,28 @@ export class SettingsPage { setProviderOauth() { this.goToSettingsPage(); this.setProvider(this.oauth.option, this.oauth.text); - Util.waitUntilElementIsVisible(this.bpmText); - Util.waitUntilElementIsVisible(this.ecmText); + BrowserVisibility.waitUntilElementIsVisible(this.bpmText); + BrowserVisibility.waitUntilElementIsVisible(this.ecmText); expect(this.authHostText.isPresent()).toBe(true); this.clickApply(); return this; } async clickBackButton() { - Util.waitUntilElementIsVisible(this.backButton); + BrowserVisibility.waitUntilElementIsVisible(this.backButton); await this.backButton.click(); } async clickSsoRadioButton() { - Util.waitUntilElementIsVisible(this.ssoRadioButton); + BrowserVisibility.waitUntilElementIsVisible(this.ssoRadioButton); await this.ssoRadioButton.click(); } async setProviderEcmSso(contentServiceURL, authHost, identityHost, silentLogin = true, implicitFlow = true, clientId?: string) { this.goToSettingsPage(); this.setProvider(this.ecm.option, this.ecm.text); - Util.waitUntilElementIsNotOnPage(this.bpmText); - Util.waitUntilElementIsVisible(this.ecmText); + BrowserVisibility.waitUntilElementIsNotOnPage(this.bpmText); + BrowserVisibility.waitUntilElementIsVisible(this.ecmText); await this.clickSsoRadioButton(); await this.setClientId(clientId); await this.setContentServicesURL(contentServiceURL); @@ -158,8 +158,8 @@ export class SettingsPage { async setProviderBpmSso(processServiceURL, authHost, identityHost, silentLogin = true, implicitFlow = true) { this.goToSettingsPage(); this.setProvider(this.bpm.option, this.bpm.text); - Util.waitUntilElementIsVisible(this.bpmText); - Util.waitUntilElementIsNotOnPage(this.ecmText); + BrowserVisibility.waitUntilElementIsVisible(this.bpmText); + BrowserVisibility.waitUntilElementIsNotOnPage(this.ecmText); await this.clickSsoRadioButton(); await this.setClientId(); await this.setProcessServicesURL(processServiceURL); @@ -171,56 +171,56 @@ export class SettingsPage { } async setProcessServicesURL(processServiceURL) { - Util.waitUntilElementIsVisible(this.bpmText); + BrowserVisibility.waitUntilElementIsVisible(this.bpmText); this.bpmText.clear(); this.bpmText.sendKeys(processServiceURL); } async setClientId(clientId: string = TestConfig.adf_aps.clientIdSso) { - Util.waitUntilElementIsVisible(this.clientIdText); + BrowserVisibility.waitUntilElementIsVisible(this.clientIdText); this.clientIdText.clear(); this.clientIdText.sendKeys(clientId); } async setContentServicesURL(contentServiceURL) { - Util.waitUntilElementIsClickable(this.ecmText); + BrowserVisibility.waitUntilElementIsClickable(this.ecmText); this.ecmText.clear(); this.ecmText.sendKeys(contentServiceURL); } clearContentServicesURL() { - Util.waitUntilElementIsVisible(this.ecmText); + BrowserVisibility.waitUntilElementIsVisible(this.ecmText); this.ecmText.clear(); this.ecmText.sendKeys('a'); this.ecmText.sendKeys(protractor.Key.BACK_SPACE); } clearProcessServicesURL() { - Util.waitUntilElementIsVisible(this.bpmText); + BrowserVisibility.waitUntilElementIsVisible(this.bpmText); this.bpmText.clear(); this.bpmText.sendKeys('a'); this.bpmText.sendKeys(protractor.Key.BACK_SPACE); } async setAuthHost(authHostURL) { - Util.waitUntilElementIsVisible(this.authHostText); + BrowserVisibility.waitUntilElementIsVisible(this.authHostText); await this.authHostText.clear(); await this.authHostText.sendKeys(authHostURL); } async setIdentityHost(identityHost) { - Util.waitUntilElementIsVisible(this.identityHostText); + BrowserVisibility.waitUntilElementIsVisible(this.identityHostText); await this.identityHostText.clear(); await this.identityHostText.sendKeys(identityHost); } async clickApply() { - Util.waitUntilElementIsVisible(this.applyButton); + BrowserVisibility.waitUntilElementIsVisible(this.applyButton); await this.applyButton.click(); } async setSilentLogin(enableToggle) { - await Util.waitUntilElementIsVisible(this.silentLoginToggleElement); + await BrowserVisibility.waitUntilElementIsVisible(this.silentLoginToggleElement); const isChecked = (await this.silentLoginToggleElement.getAttribute('class')).includes('mat-checked'); @@ -232,7 +232,7 @@ export class SettingsPage { } async setImplicitFlow(enableToggle) { - await Util.waitUntilElementIsVisible(this.implicitFlowElement); + await BrowserVisibility.waitUntilElementIsVisible(this.implicitFlowElement); const isChecked = (await this.implicitFlowElement.getAttribute('class')).includes('mat-checked'); @@ -244,43 +244,43 @@ export class SettingsPage { } checkApplyButtonIsDisabled() { - Util.waitUntilElementIsVisible(this.applyButton.getAttribute('disabled')); + BrowserVisibility.waitUntilElementIsVisible(this.applyButton.getAttribute('disabled')); return this; } checkProviderDropdownIsDisplayed() { - Util.waitUntilElementIsVisible(this.providerDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.providerDropdown); } checkValidationMessageIsDisplayed() { - Util.waitUntilElementIsVisible(this.validationMessage); + BrowserVisibility.waitUntilElementIsVisible(this.validationMessage); } checkProviderOptions() { - Util.waitUntilElementIsVisible(this.providerDropdown); + BrowserVisibility.waitUntilElementIsVisible(this.providerDropdown); this.providerDropdown.click(); - Util.waitUntilElementIsVisible(this.ecmAndBpm.option); - Util.waitUntilElementIsVisible(this.ecm.option); - Util.waitUntilElementIsVisible(this.bpm.option); + BrowserVisibility.waitUntilElementIsVisible(this.ecmAndBpm.option); + BrowserVisibility.waitUntilElementIsVisible(this.ecm.option); + BrowserVisibility.waitUntilElementIsVisible(this.bpm.option); } getBasicAuthRadioButton() { - Util.waitUntilElementIsVisible(this.basicAuthRadioButton); + BrowserVisibility.waitUntilElementIsVisible(this.basicAuthRadioButton); return this.basicAuthRadioButton; } getSsoRadioButton() { - Util.waitUntilElementIsVisible(this.ssoRadioButton); + BrowserVisibility.waitUntilElementIsVisible(this.ssoRadioButton); return this.ssoRadioButton; } getBackButton() { - Util.waitUntilElementIsVisible(this.backButton); + BrowserVisibility.waitUntilElementIsVisible(this.backButton); return this.backButton; } getApplyButton() { - Util.waitUntilElementIsVisible(this.applyButton); + BrowserVisibility.waitUntilElementIsVisible(this.applyButton); return this.applyButton; } diff --git a/e2e/pages/adf/tagPage.ts b/e2e/pages/adf/tagPage.ts index 1bd740a4bb..11e5dc349e 100644 --- a/e2e/pages/adf/tagPage.ts +++ b/e2e/pages/adf/tagPage.ts @@ -15,9 +15,8 @@ * limitations under the License. */ -import { Util } from '../../util/util'; - import { element, by, protractor, browser } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class TagPage { @@ -36,12 +35,12 @@ export class TagPage { tagsOnPage = element.all(by.css('div[class*="adf-list-tag"]')); getNodeId() { - Util.waitUntilElementIsVisible(this.insertNodeIdElement); + BrowserVisibility.waitUntilElementIsVisible(this.insertNodeIdElement); return this.insertNodeIdElement.getAttribute('value'); } insertNodeId(nodeId) { - Util.waitUntilElementIsVisible(this.insertNodeIdElement); + BrowserVisibility.waitUntilElementIsVisible(this.insertNodeIdElement); this.insertNodeIdElement.clear(); this.insertNodeIdElement.sendKeys(nodeId); browser.driver.sleep(200); @@ -51,83 +50,83 @@ export class TagPage { } addNewTagInput(tag) { - Util.waitUntilElementIsVisible(this.newTagInput); + BrowserVisibility.waitUntilElementIsVisible(this.newTagInput); this.newTagInput.sendKeys(tag); return this; } addTag(tag) { this.addNewTagInput(tag); - Util.waitUntilElementIsVisible(this.addTagButton); - Util.waitUntilElementIsClickable(this.addTagButton); + BrowserVisibility.waitUntilElementIsVisible(this.addTagButton); + BrowserVisibility.waitUntilElementIsClickable(this.addTagButton); this.addTagButton.click(); return this; } deleteTagFromTagListByNodeId(name) { const deleteChip = element(by.id('tag_chips_delete_' + name)); - Util.waitUntilElementIsVisible(deleteChip); + BrowserVisibility.waitUntilElementIsVisible(deleteChip); deleteChip.click(); return this; } deleteTagFromTagList(name) { const deleteChip = element(by.id('tag_chips_delete_' + name)); - Util.waitUntilElementIsVisible(deleteChip); + BrowserVisibility.waitUntilElementIsVisible(deleteChip); deleteChip.click(); return this; } getNewTagInput() { - Util.waitUntilElementIsVisible(this.newTagInput); + BrowserVisibility.waitUntilElementIsVisible(this.newTagInput); return this.newTagInput.getAttribute('value'); } getNewTagPlaceholder() { - Util.waitUntilElementIsVisible(this.newTagInput); + BrowserVisibility.waitUntilElementIsVisible(this.newTagInput); return this.newTagInput.getAttribute('placeholder'); } addTagButtonIsEnabled() { - Util.waitUntilElementIsVisible(this.addTagButton); + BrowserVisibility.waitUntilElementIsVisible(this.addTagButton); return this.addTagButton.isEnabled(); } checkTagIsDisplayedInTagList(tagName) { const tag = element(by.cssContainingText('div[id*="tag_name"]', tagName)); - return Util.waitUntilElementIsVisible(tag); + return BrowserVisibility.waitUntilElementIsVisible(tag); } checkTagIsNotDisplayedInTagList(tagName) { const tag = element(by.cssContainingText('div[id*="tag_name"]', tagName)); - return Util.waitUntilElementIsNotOnPage(tag); + return BrowserVisibility.waitUntilElementIsNotOnPage(tag); } checkTagIsNotDisplayedInTagListByNodeId(tagName) { const tag = element(by.cssContainingText('span[id*="tag_name"]', tagName)); - return Util.waitUntilElementIsNotOnPage(tag); + return BrowserVisibility.waitUntilElementIsNotOnPage(tag); } checkTagIsDisplayedInTagListByNodeId(tagName) { const tag = element(by.cssContainingText('span[id*="tag_name"]', tagName)); - return Util.waitUntilElementIsVisible(tag); + return BrowserVisibility.waitUntilElementIsVisible(tag); } checkTagListIsEmpty() { - Util.waitUntilElementIsNotOnPage(this.tagListRow); + BrowserVisibility.waitUntilElementIsNotOnPage(this.tagListRow); } checkTagListByNodeIdIsEmpty() { - return Util.waitUntilElementIsNotOnPage(this.tagListByNodeIdRow); + return BrowserVisibility.waitUntilElementIsNotOnPage(this.tagListByNodeIdRow); } checkTagIsDisplayedInTagListContentServices(tagName) { const tag = element(by.cssContainingText('div[class="adf-list-tag"][id*="tag_name"]', tagName)); - return Util.waitUntilElementIsVisible(tag); + return BrowserVisibility.waitUntilElementIsVisible(tag); } getErrorMessage() { - Util.waitUntilElementIsPresent(this.errorMessage); + BrowserVisibility.waitUntilElementIsPresent(this.errorMessage); return this.errorMessage.getText(); } @@ -158,7 +157,7 @@ export class TagPage { checkListIsSorted(sortOrder, locator) { const deferred = protractor.promise.defer(); const tagList = element.all(locator); - Util.waitUntilElementIsVisible(tagList.first()); + BrowserVisibility.waitUntilElementIsVisible(tagList.first()); const initialList = []; tagList.each(function (currentElement) { currentElement.getText().then(function (text) { @@ -177,26 +176,26 @@ export class TagPage { checkDeleteTagFromTagListByNodeIdIsDisplayed(name) { const deleteChip = element(by.id('tag_chips_delete_' + name)); - return Util.waitUntilElementIsVisible(deleteChip); + return BrowserVisibility.waitUntilElementIsVisible(deleteChip); } checkDeleteTagFromTagListByNodeIdIsNotDisplayed(name) { const deleteChip = element(by.id('tag_chips_delete_' + name)); - return Util.waitUntilElementIsNotVisible(deleteChip); + return BrowserVisibility.waitUntilElementIsNotVisible(deleteChip); } clickShowDeleteButtonSwitch() { - Util.waitUntilElementIsVisible(this.showDeleteButton); - Util.waitUntilElementIsClickable(this.showDeleteButton); + BrowserVisibility.waitUntilElementIsVisible(this.showDeleteButton); + BrowserVisibility.waitUntilElementIsClickable(this.showDeleteButton); this.showDeleteButton.click(); } checkShowMoreButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.showMoreButton); + return BrowserVisibility.waitUntilElementIsVisible(this.showMoreButton); } clickShowMoreButton() { - Util.waitUntilElementIsClickable(this.showMoreButton); + BrowserVisibility.waitUntilElementIsClickable(this.showMoreButton); return this.showMoreButton.click(); } @@ -205,11 +204,11 @@ export class TagPage { } checkShowLessButtonIsDisplayed() { - return Util.waitUntilElementIsVisible(this.showLessButton); + return BrowserVisibility.waitUntilElementIsVisible(this.showLessButton); } checkShowLessButtonIsNotDisplayed() { - return Util.waitUntilElementIsNotVisible(this.showLessButton); + return BrowserVisibility.waitUntilElementIsNotVisible(this.showLessButton); } clickShowMoreButtonUntilNotDisplayed() { @@ -218,7 +217,7 @@ export class TagPage { this.showMoreButton.click(); this.clickShowMoreButtonUntilNotDisplayed(); } - }, (err) => { + }, () => { }); } @@ -229,7 +228,7 @@ export class TagPage { this.clickShowLessButtonUntilNotDisplayed(); } - }, (err) => { + }, () => { }); } } diff --git a/e2e/pages/adf/trashcanPage.ts b/e2e/pages/adf/trashcanPage.ts index 08fb371e72..2f624ceeb2 100644 --- a/e2e/pages/adf/trashcanPage.ts +++ b/e2e/pages/adf/trashcanPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Util } from '../../util/util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; @@ -30,11 +30,11 @@ export class TrashcanPage { } waitForTableBody() { - Util.waitUntilElementIsVisible(this.tableBody); + BrowserVisibility.waitUntilElementIsVisible(this.tableBody); } waitForPagination() { - Util.waitUntilElementIsVisible(this.pagination); + BrowserVisibility.waitUntilElementIsVisible(this.pagination); } } diff --git a/e2e/pages/adf/versionManagerPage.ts b/e2e/pages/adf/versionManagerPage.ts index 6bd2c87e3f..0db919f8c1 100644 --- a/e2e/pages/adf/versionManagerPage.ts +++ b/e2e/pages/adf/versionManagerPage.ts @@ -15,12 +15,12 @@ * limitations under the License. */ -import { Util } from '../../util/util'; import TestConfig = require('../../test.config'); import path = require('path'); import remote = require('selenium-webdriver/remote'); import { browser, by, element, protractor } from 'protractor'; import { FormControllersPage } from './material/formControllersPage'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class VersionManagePage { @@ -38,74 +38,74 @@ export class VersionManagePage { commentsSwitch = element(by.id('adf-version-manager-switch-comments')); checkUploadNewVersionsButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.showNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(this.showNewVersionButton); return this; } checkMajorChangeIsDisplayed() { - Util.waitUntilElementIsVisible(this.majorRadio); + BrowserVisibility.waitUntilElementIsVisible(this.majorRadio); return this; } checkMinorChangeIsDisplayed() { - Util.waitUntilElementIsVisible(this.minorRadio); + BrowserVisibility.waitUntilElementIsVisible(this.minorRadio); return this; } checkCommentTextIsDisplayed() { - Util.waitUntilElementIsVisible(this.commentText); + BrowserVisibility.waitUntilElementIsVisible(this.commentText); return this; } clickAddNewVersionsButton() { - Util.waitUntilElementIsVisible(this.showNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(this.showNewVersionButton); this.showNewVersionButton.click(); return this; } checkCancelButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.cancelButton); + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); return this; } uploadNewVersionFile(fileLocation) { browser.setFileDetector(new remote.FileDetector()); - Util.waitUntilElementIsVisible(this.uploadNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadNewVersionButton); this.uploadNewVersionButton.sendKeys(path.resolve(path.join(TestConfig.main.rootPath, fileLocation))); - Util.waitUntilElementIsVisible(this.showNewVersionButton); + BrowserVisibility.waitUntilElementIsVisible(this.showNewVersionButton); return this; } getFileVersionName(version) { const fileElement = element(by.css(`[id="adf-version-list-item-name-${version}"]`)); - Util.waitUntilElementIsVisible(fileElement); + BrowserVisibility.waitUntilElementIsVisible(fileElement); return fileElement.getText(); } checkFileVersionExist(version) { const fileVersion = element(by.id(`adf-version-list-item-version-${version}`)); - return Util.waitUntilElementIsVisible(fileVersion); + return BrowserVisibility.waitUntilElementIsVisible(fileVersion); } checkFileVersionNotExist(version) { const fileVersion = element(by.id(`adf-version-list-item-version-${version}`)); - return Util.waitUntilElementIsNotVisible(fileVersion); + return BrowserVisibility.waitUntilElementIsNotVisible(fileVersion); } getFileVersionComment(version) { const fileComment = element(by.id(`adf-version-list-item-comment-${version}`)); - Util.waitUntilElementIsVisible(fileComment); + BrowserVisibility.waitUntilElementIsVisible(fileComment); return fileComment.getText(); } getFileVersionDate(version) { const fileDate = element(by.id(`adf-version-list-item-date-${version}`)); - Util.waitUntilElementIsVisible(fileDate); + BrowserVisibility.waitUntilElementIsVisible(fileDate); return fileDate.getText(); } enterCommentText(text) { - Util.waitUntilElementIsVisible(this.commentText); + BrowserVisibility.waitUntilElementIsVisible(this.commentText); this.commentText.sendKeys(''); this.commentText.clear(); this.commentText.sendKeys(text); @@ -114,13 +114,13 @@ export class VersionManagePage { clickMajorChange() { const radioMajor = element(by.id(`adf-new-version-major`)); - Util.waitUntilElementIsVisible(radioMajor); + BrowserVisibility.waitUntilElementIsVisible(radioMajor); radioMajor.click(); } clickMinorChange() { const radioMinor = element(by.id(`adf-new-version-minor`)); - Util.waitUntilElementIsVisible(radioMinor); + BrowserVisibility.waitUntilElementIsVisible(radioMinor); radioMinor.click(); } @@ -168,35 +168,35 @@ export class VersionManagePage { } clickActionButton(version) { - Util.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-menu-button-${version}`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-menu-button-${version}`))); element(by.id(`adf-version-list-action-menu-button-${version}`)).click(); return this; } clickAcceptConfirm() { - Util.waitUntilElementIsVisible(element(by.id(`adf-confirm-accept`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-confirm-accept`))); element(by.id(`adf-confirm-accept`)).click(); return this; } clickCancelConfirm() { - Util.waitUntilElementIsVisible(element(by.id(`adf-confirm-cancel`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-confirm-cancel`))); element(by.id(`adf-confirm-cancel`)).click(); return this; } closeActionButton() { const container = element(by.css('div.cdk-overlay-backdrop.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing')); - Util.waitUntilElementIsVisible(container); + BrowserVisibility.waitUntilElementIsVisible(container); container.click(); - Util.waitUntilElementIsNotVisible(container); + BrowserVisibility.waitUntilElementIsNotVisible(container); return this; } downloadFileVersion(version) { this.clickActionButton(version); const downloadButton = element(by.id(`adf-version-list-action-download-${version}`)); - Util.waitUntilElementIsVisible(downloadButton); + BrowserVisibility.waitUntilElementIsVisible(downloadButton); browser.driver.sleep(500); downloadButton.click(); return this; @@ -205,7 +205,7 @@ export class VersionManagePage { deleteFileVersion(version) { this.clickActionButton(version); const deleteButton = element(by.id(`adf-version-list-action-delete-${version}`)); - Util.waitUntilElementIsVisible(deleteButton); + BrowserVisibility.waitUntilElementIsVisible(deleteButton); browser.driver.sleep(500); deleteButton.click(); return this; @@ -214,20 +214,20 @@ export class VersionManagePage { restoreFileVersion(version) { this.clickActionButton(version); const restoreButton = element(by.id(`adf-version-list-action-restore-${version}`)); - Util.waitUntilElementIsVisible(restoreButton); + BrowserVisibility.waitUntilElementIsVisible(restoreButton); browser.driver.sleep(500); restoreButton.click(); return this; } checkActionsArePresent(version) { - Util.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-download-${version}`))); - Util.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-delete-${version}`))); - Util.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-restore-${version}`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-download-${version}`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-delete-${version}`))); + BrowserVisibility.waitUntilElementIsVisible(element(by.id(`adf-version-list-action-restore-${version}`))); } closeVersionDialog() { browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); - Util.waitUntilElementIsNotOnPage(this.uploadNewVersionContainer); + BrowserVisibility.waitUntilElementIsNotOnPage(this.uploadNewVersionContainer); } } diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index 64ccb71bc5..a56b7f7acc 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -15,11 +15,10 @@ * limitations under the License. */ -import { Util } from '../../util/util'; - import { TabsPage } from '@alfresco/adf-testing'; import { FormControllersPage } from './material/formControllersPage'; import { element, by, browser, protractor } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export class ViewerPage { @@ -99,18 +98,18 @@ export class ViewerPage { moveRightChevron = element(by.css('.mat-tab-header-pagination-after .mat-tab-header-pagination-chevron')); checkCodeViewerIsDisplayed() { - return Util.waitUntilElementIsVisible(this.codeViewer); + return BrowserVisibility.waitUntilElementIsVisible(this.codeViewer); } viewFile(fileName) { const fileView = element.all(by.css(`#document-list-container div[data-automation-id="${fileName}"]`)).first(); - Util.waitUntilElementIsVisible(fileView); + BrowserVisibility.waitUntilElementIsVisible(fileView); fileView.click(); browser.actions().sendKeys(protractor.Key.ENTER).perform(); } clearPageNumber() { - Util.waitUntilElementIsVisible(this.pageSelectorInput); + BrowserVisibility.waitUntilElementIsVisible(this.pageSelectorInput); this.pageSelectorInput.clear(); this.pageSelectorInput.sendKeys(protractor.Key.ENTER); } @@ -125,33 +124,33 @@ export class ViewerPage { } enterPassword(password) { - Util.waitUntilElementIsVisible(this.passwordInput); + BrowserVisibility.waitUntilElementIsVisible(this.passwordInput); this.passwordInput.clear(); this.passwordInput.sendKeys(password); } checkFileIsLoaded() { - Util.waitUntilElementIsOnPage(this.pdfPageLoaded, 15000); + BrowserVisibility.waitUntilElementIsOnPage(this.pdfPageLoaded, 15000); } checkImgViewerIsDisplayed() { - Util.waitUntilElementIsOnPage(this.imgViewer); + BrowserVisibility.waitUntilElementIsOnPage(this.imgViewer); } checkPasswordErrorIsDisplayed() { - Util.waitUntilElementIsVisible(this.passwordError); + BrowserVisibility.waitUntilElementIsVisible(this.passwordError); } checkPasswordInputIsDisplayed() { - Util.waitUntilElementIsVisible(this.passwordInput); + BrowserVisibility.waitUntilElementIsVisible(this.passwordInput); } checkPasswordSubmitDisabledIsDisplayed() { - Util.waitUntilElementIsVisible(this.passwordSubmitDisabled); + BrowserVisibility.waitUntilElementIsVisible(this.passwordSubmitDisabled); } checkPasswordDialogIsDisplayed() { - Util.waitUntilElementIsVisible(this.passwordDialog); + BrowserVisibility.waitUntilElementIsVisible(this.passwordDialog); } checkAllThumbnailsDisplayed(nbPages) { @@ -169,28 +168,28 @@ export class ViewerPage { } checkThumbnailsCloseIsDisplayed() { - Util.waitUntilElementIsVisible(this.thumbnailsClose); + BrowserVisibility.waitUntilElementIsVisible(this.thumbnailsClose); } checkThumbnailsBtnIsDisplayed() { - Util.waitUntilElementIsVisible(this.thumbnailsBtn); + BrowserVisibility.waitUntilElementIsVisible(this.thumbnailsBtn); } checkThumbnailsBtnIsDisabled() { - Util.waitUntilElementIsVisible(this.thumbnailsBtn.getAttribute('disabled')); + BrowserVisibility.waitUntilElementIsVisible(this.thumbnailsBtn.getAttribute('disabled')); return this; } checkThumbnailsContentIsDisplayed() { - Util.waitUntilElementIsVisible(this.thumbnailsContent); + BrowserVisibility.waitUntilElementIsVisible(this.thumbnailsContent); } checkThumbnailsContentIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.thumbnailsContent); + BrowserVisibility.waitUntilElementIsNotVisible(this.thumbnailsContent); } checkCloseButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); } getLastButtonTitle() { @@ -202,63 +201,63 @@ export class ViewerPage { } checkDownloadButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.downloadButton); + BrowserVisibility.waitUntilElementIsVisible(this.downloadButton); } checkInfoButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.infoButton); + BrowserVisibility.waitUntilElementIsVisible(this.infoButton); } checkInfoButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.infoButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.infoButton); } checkFileThumbnailIsDisplayed() { - Util.waitUntilElementIsVisible(this.fileThumbnail); + BrowserVisibility.waitUntilElementIsVisible(this.fileThumbnail); } checkFileNameIsDisplayed(file) { - Util.waitUntilElementIsVisible(this.fileName); + BrowserVisibility.waitUntilElementIsVisible(this.fileName); expect(this.fileName.getText()).toEqual(file); } checkPreviousPageButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.previousPageButton); + BrowserVisibility.waitUntilElementIsVisible(this.previousPageButton); } checkNextPageButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.nextPageButton); + BrowserVisibility.waitUntilElementIsVisible(this.nextPageButton); } checkZoomInButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.zoomInButton); + BrowserVisibility.waitUntilElementIsVisible(this.zoomInButton); } checkZoomInButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.zoomInButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.zoomInButton); } checkZoomOutButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.zoomOutButton); + BrowserVisibility.waitUntilElementIsVisible(this.zoomOutButton); } checkScalePageButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.scalePageButton); + BrowserVisibility.waitUntilElementIsVisible(this.scalePageButton); } checkPageSelectorInputIsDisplayed(checkNumber) { - Util.waitUntilElementIsVisible(this.pageSelectorInput); + BrowserVisibility.waitUntilElementIsVisible(this.pageSelectorInput); this.pageSelectorInput.getAttribute('value').then((pageNumber) => { expect(pageNumber).toEqual(checkNumber); }); } checkImgContainerIsDisplayed() { - Util.waitUntilElementIsVisible(this.imgContainer); + BrowserVisibility.waitUntilElementIsVisible(this.imgContainer); } checkMediaPlayerContainerIsDisplayed() { - Util.waitUntilElementIsVisible(this.mediaContainer); + BrowserVisibility.waitUntilElementIsVisible(this.mediaContainer); } checkFileContent(pageNumber, text) { @@ -267,22 +266,22 @@ export class ViewerPage { const textLayerLoaded = element.all(by.css('div[data-page-number="' + pageNumber + '"] div[class="textLayer"] > div')).first(); const specificText = element.all(by.cssContainingText('div[data-page-number="' + pageNumber + '"] div[class="textLayer"] > div', text)).first(); - Util.waitUntilElementIsVisible(allPages); - Util.waitUntilElementIsVisible(pageLoaded); - Util.waitUntilElementIsVisible(textLayerLoaded); - Util.waitUntilElementIsVisible(specificText); + BrowserVisibility.waitUntilElementIsVisible(allPages); + BrowserVisibility.waitUntilElementIsVisible(pageLoaded); + BrowserVisibility.waitUntilElementIsVisible(textLayerLoaded); + BrowserVisibility.waitUntilElementIsVisible(specificText); } checkFullScreenButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.fullScreenButton); + BrowserVisibility.waitUntilElementIsVisible(this.fullScreenButton); } checkFullScreenButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.fullScreenButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.fullScreenButton); } checkPercentageIsDisplayed() { - Util.waitUntilElementIsVisible(this.percentage); + BrowserVisibility.waitUntilElementIsVisible(this.percentage); } checkZoomedIn(zoom) { @@ -294,15 +293,15 @@ export class ViewerPage { } checkRotateLeftButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.rotateLeft); + BrowserVisibility.waitUntilElementIsVisible(this.rotateLeft); } checkRotateRightButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.rotateRight); + BrowserVisibility.waitUntilElementIsVisible(this.rotateRight); } checkScaleImgButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.scaleImg); + BrowserVisibility.waitUntilElementIsVisible(this.scaleImg); } checkRotation(text) { @@ -311,23 +310,23 @@ export class ViewerPage { } checkInfoSideBarIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.infoSideBar); + BrowserVisibility.waitUntilElementIsNotVisible(this.infoSideBar); } checkInfoSideBarIsDisplayed() { - Util.waitUntilElementIsVisible(this.infoSideBar); + BrowserVisibility.waitUntilElementIsVisible(this.infoSideBar); } checkLeftSideBarButtonIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.leftSideBarButton); + BrowserVisibility.waitUntilElementIsNotOnPage(this.leftSideBarButton); } checkLeftSideBarButtonIsDisplayed() { - Util.waitUntilElementIsOnPage(this.leftSideBarButton); + BrowserVisibility.waitUntilElementIsOnPage(this.leftSideBarButton); } clickInfoButton() { - Util.waitUntilElementIsVisible(this.infoButton); + BrowserVisibility.waitUntilElementIsVisible(this.infoButton); return this.infoButton.click(); } @@ -338,101 +337,101 @@ export class ViewerPage { checkTabIsActive(tabName) { const tab = element(by.cssContainingText('.adf-info-drawer-layout-content div.mat-tab-labels div.mat-tab-label-active .mat-tab-label-content', tabName)); - Util.waitUntilElementIsVisible(tab); + BrowserVisibility.waitUntilElementIsVisible(tab); return this; } clickLeftSidebarButton() { - Util.waitUntilElementIsVisible(this.leftSideBarButton); + BrowserVisibility.waitUntilElementIsVisible(this.leftSideBarButton); return this.leftSideBarButton.click(); } checkLeftSideBarIsDisplayed() { - Util.waitUntilElementIsVisible(this.leftSideBar); + BrowserVisibility.waitUntilElementIsVisible(this.leftSideBar); } checkLeftSideBarIsNotDisplayed() { - Util.waitUntilElementIsNotOnPage(this.leftSideBar); + BrowserVisibility.waitUntilElementIsNotOnPage(this.leftSideBar); } clickPasswordSubmit() { - Util.waitUntilElementIsVisible(this.passwordSubmit); + BrowserVisibility.waitUntilElementIsVisible(this.passwordSubmit); return this.passwordSubmit.click(); } clickSecondThumbnail() { - Util.waitUntilElementIsClickable(this.secondThumbnail); + BrowserVisibility.waitUntilElementIsClickable(this.secondThumbnail); return this.secondThumbnail.click(); } clickLastThumbnailDisplayed() { - Util.waitUntilElementIsClickable(this.lastThumbnailDisplayed); + BrowserVisibility.waitUntilElementIsClickable(this.lastThumbnailDisplayed); return this.lastThumbnailDisplayed.click(); } clickThumbnailsClose() { - Util.waitUntilElementIsClickable(this.thumbnailsClose); + BrowserVisibility.waitUntilElementIsClickable(this.thumbnailsClose); return this.thumbnailsClose.click(); } clickThumbnailsBtn() { - Util.waitUntilElementIsVisible(this.thumbnailsBtn); - Util.waitUntilElementIsClickable(this.thumbnailsBtn); + BrowserVisibility.waitUntilElementIsVisible(this.thumbnailsBtn); + BrowserVisibility.waitUntilElementIsClickable(this.thumbnailsBtn); return this.thumbnailsBtn.click(); } clickScaleImgButton() { - Util.waitUntilElementIsClickable(this.scaleImg); + BrowserVisibility.waitUntilElementIsClickable(this.scaleImg); return this.scaleImg.click(); } clickDownloadButton() { - Util.waitUntilElementIsVisible(this.downloadButton); + BrowserVisibility.waitUntilElementIsVisible(this.downloadButton); return this.downloadButton.click(); } clickCloseButton() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); return this.closeButton.click(); } clickPreviousPageButton() { - Util.waitUntilElementIsVisible(this.previousPageButton); + BrowserVisibility.waitUntilElementIsVisible(this.previousPageButton); return this.previousPageButton.click(); } clickNextPageButton() { - Util.waitUntilElementIsVisible(this.nextPageButton); + BrowserVisibility.waitUntilElementIsVisible(this.nextPageButton); return this.nextPageButton.click(); } clickZoomInButton() { - Util.waitUntilElementIsVisible(this.zoomInButton); + BrowserVisibility.waitUntilElementIsVisible(this.zoomInButton); return this.zoomInButton.click(); } clickZoomOutButton() { - Util.waitUntilElementIsVisible(this.zoomOutButton); + BrowserVisibility.waitUntilElementIsVisible(this.zoomOutButton); return this.zoomOutButton.click(); } clickFullScreenButton() { - Util.waitUntilElementIsClickable(this.fullScreenButton); + BrowserVisibility.waitUntilElementIsClickable(this.fullScreenButton); return this.fullScreenButton.click(); } clickRotateLeftButton() { - Util.waitUntilElementIsClickable(this.rotateLeft); + BrowserVisibility.waitUntilElementIsClickable(this.rotateLeft); return this.rotateLeft.click(); } clickRotateRightButton() { - Util.waitUntilElementIsClickable(this.rotateRight); + BrowserVisibility.waitUntilElementIsClickable(this.rotateRight); return this.rotateRight.click(); } getActiveTab() { - Util.waitUntilElementIsVisible(this.activeTab); + BrowserVisibility.waitUntilElementIsVisible(this.activeTab); return this.activeTab.getText(); } @@ -450,12 +449,12 @@ export class ViewerPage { } checkToolbarIsDisplayed() { - Util.waitUntilElementIsVisible(this.toolbar); + BrowserVisibility.waitUntilElementIsVisible(this.toolbar); return this; } checkToolbarIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.toolbar); + BrowserVisibility.waitUntilElementIsNotVisible(this.toolbar); return this; } @@ -468,12 +467,12 @@ export class ViewerPage { } checkGoBackIsDisplayed() { - Util.waitUntilElementIsVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsVisible(this.closeButton); return this; } checkGoBackIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.closeButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.closeButton); return this; } @@ -486,12 +485,12 @@ export class ViewerPage { } checkToolbarOptionsIsDisplayed() { - Util.waitUntilElementIsVisible(this.openWith); + BrowserVisibility.waitUntilElementIsVisible(this.openWith); return this; } checkToolbarOptionsIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.openWith); + BrowserVisibility.waitUntilElementIsNotVisible(this.openWith); return this; } @@ -504,12 +503,12 @@ export class ViewerPage { } checkDownloadButtonDisplayed() { - Util.waitUntilElementIsVisible(this.downloadButton); + BrowserVisibility.waitUntilElementIsVisible(this.downloadButton); return this; } checkDownloadButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.downloadButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.downloadButton); return this; } @@ -522,12 +521,12 @@ export class ViewerPage { } checkPrintButtonIsDisplayed() { - Util.waitUntilElementIsVisible(this.printButton); + BrowserVisibility.waitUntilElementIsVisible(this.printButton); return this; } checkPrintButtonIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.printButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.printButton); return this; } @@ -540,16 +539,16 @@ export class ViewerPage { } checkMoreActionsDisplayed() { - Util.waitUntilElementIsVisible(this.bugButton); - Util.waitUntilElementIsVisible(this.timeButton); - Util.waitUntilElementIsVisible(this.uploadButton); + BrowserVisibility.waitUntilElementIsVisible(this.bugButton); + BrowserVisibility.waitUntilElementIsVisible(this.timeButton); + BrowserVisibility.waitUntilElementIsVisible(this.uploadButton); return this; } checkMoreActionsIsNotDisplayed() { - Util.waitUntilElementIsNotVisible(this.bugButton); - Util.waitUntilElementIsNotVisible(this.timeButton); - Util.waitUntilElementIsNotVisible(this.uploadButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.bugButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.timeButton); + BrowserVisibility.waitUntilElementIsNotVisible(this.uploadButton); return this; } @@ -576,7 +575,7 @@ export class ViewerPage { } checkCustomToolbarIsDisplayed() { - Util.waitUntilElementIsVisible(this.customToolbar); + BrowserVisibility.waitUntilElementIsVisible(this.customToolbar); return this; } @@ -589,18 +588,18 @@ export class ViewerPage { } clickToggleRightSidebar() { - Util.waitUntilElementIsVisible(this.showRightSidebarSwitch); + BrowserVisibility.waitUntilElementIsVisible(this.showRightSidebarSwitch); this.showRightSidebarSwitch.click(); } clickToggleLeftSidebar() { - Util.waitUntilElementIsVisible(this.showLeftSidebarSwitch); + BrowserVisibility.waitUntilElementIsVisible(this.showLeftSidebarSwitch); this.showLeftSidebarSwitch.click(); } enterCustomName(text) { const textField = element(by.css('input[data-automation-id="adf-text-custom-name"]')); - Util.waitUntilElementIsVisible(textField); + BrowserVisibility.waitUntilElementIsVisible(textField); textField.sendKeys(''); textField.clear(); textField.sendKeys(text); @@ -613,17 +612,17 @@ export class ViewerPage { } checkOverlayViewerIsDisplayed() { - Util.waitUntilElementIsVisible(this.viewer.element(by.css('div[class*="adf-viewer-overlay-container"]'))); + BrowserVisibility.waitUntilElementIsVisible(this.viewer.element(by.css('div[class*="adf-viewer-overlay-container"]'))); return this; } checkInlineViewerIsDisplayed() { - Util.waitUntilElementIsVisible(this.viewer.element(by.css('div[class*="adf-viewer-inline-container"]'))); + BrowserVisibility.waitUntilElementIsVisible(this.viewer.element(by.css('div[class*="adf-viewer-inline-container"]'))); return this; } clickMoveRightChevron() { - Util.waitUntilElementIsVisible(this.moveRightChevron); + BrowserVisibility.waitUntilElementIsVisible(this.moveRightChevron); return this.moveRightChevron.click(); } } diff --git a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts index 68fe1fc39f..6811b6aa55 100644 --- a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts @@ -17,14 +17,13 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { ApiService, LoginSSOPage, TasksService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; -import { Tasks } from '../actions/APS-cloud/tasks'; import { browser } from 'protractor'; describe('Edit task filters cloud', () => { @@ -35,11 +34,11 @@ describe('Edit task filters cloud', () => { const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); + let tasksService: TasksService; let silentLogin; const simpleApp = 'simple-app'; - const completedTaskName = Util.generateRandomString(), assignedTaskName = Util.generateRandomString(); + const completedTaskName = StringUtil.generateRandomString(), assignedTaskName = StringUtil.generateRandomString(); let assignedTask; beforeAll(async () => { @@ -49,7 +48,10 @@ describe('Edit task filters cloud', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await tasksService.init(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); assignedTask = await tasksService.createStandaloneTask(assignedTaskName, simpleApp); await tasksService.claimTask(assignedTask.entry.id, simpleApp); await tasksService.createAndCompleteTask(completedTaskName, simpleApp); diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 8c348c4ea0..52f7a3b55b 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -17,17 +17,14 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { PeopleGroupCloudComponentPage } from '../pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage'; import { PeopleCloudComponent } from '../pages/adf/process-cloud/peopleCloudComponent'; import { GroupCloudComponent } from '../pages/adf/process-cloud/groupCloudComponent'; import { browser } from 'protractor'; -import { Identity } from '../actions/APS-cloud/identity'; -import { GroupIdentity } from '../actions/APS-cloud/groupIdentity'; +import { LoginSSOPage, IdentityService, GroupIdentityService, RolesService, ApiService } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); -import { Roles } from '../actions/APS-cloud/roles'; describe('People Groups Cloud Component', () => { @@ -38,14 +35,14 @@ describe('People Groups Cloud Component', () => { const peopleGroupCloudComponentPage = new PeopleGroupCloudComponentPage(); const peopleCloudComponent = new PeopleCloudComponent(); const groupCloudComponent = new GroupCloudComponent(); - const identityService: Identity = new Identity(); - const groupIdentityService: GroupIdentity = new GroupIdentity(); - const rolesService: Roles = new Roles(); + let identityService: IdentityService; + let groupIdentityService: GroupIdentityService; + let rolesService: RolesService; let silentLogin; let apsUser; let activitiUser; - let noRoleUser ; + let noRoleUser; let groupAps; let groupActiviti; let groupNoRole; @@ -53,12 +50,16 @@ describe('People Groups Cloud Component', () => { let activitiUserRoleId; let apsAdminRoleId; let activitiAdminRoleId; - let users = new Array<string>(); - let groups = new Array<string>(); + let users = []; + let groups = []; beforeAll(async () => { - await identityService.init(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await rolesService.init(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + identityService = new IdentityService(apiService); + rolesService = new RolesService(apiService); + apsUser = await identityService.createIdentityUser(); apsUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_USER); await identityService.assignRole(apsUser.id, apsUserRoleId, CONSTANTS.ROLES.APS_USER); @@ -66,7 +67,7 @@ describe('People Groups Cloud Component', () => { activitiUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_USER); await identityService.assignRole(activitiUser.id, activitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); noRoleUser = await identityService.createIdentityUser(); - await groupIdentityService.init(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + groupIdentityService = new GroupIdentityService(apiService); groupAps = await groupIdentityService.createIdentityGroup(); apsAdminRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_ADMIN); await groupIdentityService.assignRole(groupAps.id, apsAdminRoleId, CONSTANTS.ROLES.APS_ADMIN); @@ -93,7 +94,7 @@ describe('People Groups Cloud Component', () => { } }); - beforeEach( () => { + beforeEach(() => { browser.refresh(); peopleGroupCloudComponentPage.checkGroupsCloudComponentTitleIsDisplayed(); peopleGroupCloudComponentPage.checkPeopleCloudComponentTitleIsDisplayed(); diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index 0a8eee4a8f..b568a805e0 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; @@ -25,10 +25,6 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { AppListCloudPage } from '@alfresco/adf-testing'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; -import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; -import { ProcessInstances } from '../actions/APS-cloud/process-instances'; -import { Tasks } from '../actions/APS-cloud/tasks'; -import { Query } from '../actions/APS-cloud/query'; import { browser, protractor } from 'protractor'; describe('Process list cloud', () => { @@ -42,22 +38,21 @@ describe('Process list cloud', () => { const processCloudDemoPage = new ProcessCloudDemoPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); - const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); - const processInstancesService: ProcessInstances = new ProcessInstances(); - const queryService: Query = new Query(); + let tasksService: TasksService; + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let queryService: QueryService; let silentLogin; let completedProcess, runningProcessInstance, switchProcessInstance, noOfApps; const simpleApp = 'candidateuserapp'; - const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; beforeAll(async () => { silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); browser.ignoreSynchronization = true; - loginSSOPage.loginSSOIdentityService(user, password); + loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); navigationBarPage.clickConfigEditorButton(); configEditorPage.clickEditProcessCloudConfiguration(); @@ -69,17 +64,21 @@ describe('Process list cloud', () => { '}'); configEditorPage.clickSaveButton(); - await processDefinitionService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + processDefinitionService = new ProcessDefinitionsService(apiService); const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - await processInstancesService.init(user, password); + processInstancesService = new ProcessInstancesService(apiService); await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); runningProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); switchProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - await queryService.init(user, password); + queryService = new QueryService(apiService); + const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); - await tasksService.init(user, password); + tasksService = new TasksService(apiService); const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); await tasksService.completeTask(claimedTask.entry.id, simpleApp); }); @@ -93,7 +92,7 @@ describe('Process list cloud', () => { done(); }); - it('[C290069] Should display processes ordered by name when Name is selected from sort dropdown', async() => { + it('[C290069] Should display processes ordered by name when Name is selected from sort dropdown', async () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('RUNNING') .setSortFilterDropDown('Name').setOrderFilterDropDown('ASC'); processCloudDemoPage.processListCloudComponent().getAllRowsNameColumn().then(function (list) { @@ -111,7 +110,7 @@ describe('Process list cloud', () => { }); }); - it('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async() => { + it('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('RUNNING') .setSortFilterDropDown('Id').setOrderFilterDropDown('ASC'); processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); @@ -135,7 +134,7 @@ describe('Process list cloud', () => { }); }); - it('[C297697] The value of the filter should be preserved when saving it', async() => { + it('[C297697] The value of the filter should be preserved when saving it', async () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader() .setProcessInstanceId(completedProcess.entry.id); @@ -152,7 +151,7 @@ describe('Process list cloud', () => { expect(processCloudDemoPage.editProcessFilterCloudComponent().getProcessInstanceId()).toEqual(completedProcess.entry.id); }); - it('[C297646] Should display the filter dropdown fine , after switching between saved filters', async() => { + it('[C297646] Should display the filter dropdown fine , after switching between saved filters', async () => { noOfApps = processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().getNumberOfAppNameOptions(); expect(processCloudDemoPage.editProcessFilterCloudComponent().checkAppNamesAreUnique()).toBe(true); diff --git a/e2e/process-services-cloud/process-filters-cloud.e2e.ts b/e2e/process-services-cloud/process-filters-cloud.e2e.ts index 8360e86f7b..0b9ff8b3fb 100644 --- a/e2e/process-services-cloud/process-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-filters-cloud.e2e.ts @@ -17,17 +17,13 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; -import { ProcessInstances } from '../actions/APS-cloud/process-instances'; -import { Tasks } from '../actions/APS-cloud/tasks'; -import { Query } from '../actions/APS-cloud/query'; import { browser } from 'protractor'; describe('Process filters cloud', () => { @@ -40,10 +36,10 @@ describe('Process filters cloud', () => { const processCloudDemoPage = new ProcessCloudDemoPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); - const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); - const processInstancesService: ProcessInstances = new ProcessInstances(); - const queryService: Query = new Query(); + let tasksService: TasksService; + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let queryService: QueryService; let silentLogin; let runningProcess, completedProcess; @@ -57,15 +53,18 @@ describe('Process filters cloud', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - await processDefinitionService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + processDefinitionService = new ProcessDefinitionsService(apiService); const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - await processInstancesService.init(user, password); + processInstancesService = new ProcessInstancesService(apiService); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - await queryService.init(user, password); + queryService = new QueryService(apiService); const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); - await tasksService.init(user, password); + tasksService = new TasksService(apiService); const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); await tasksService.completeTask(claimedTask.entry.id, simpleApp); }); diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index b8372187a2..4cbe018c96 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -17,27 +17,20 @@ import TestConfig = require('../test.config'); import CONSTANTS = require('../util/constants'); -import { Util } from '../util/util'; import moment = require('moment'); -import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; -import { ProcessInstances } from '../actions/APS-cloud/process-instances'; -import { Query } from '../actions/APS-cloud/query'; - import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { ApiService, StringUtil, LoginSSOPage, ProcessDefinitionsService, ProcessInstancesService, QueryService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { ProcessHeaderCloudPage } from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; -import { browser } from 'protractor'; describe('Process Header cloud component', () => { describe('Process Header cloud component', () => { - const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const simpleApp = 'simple-app', subProcessApp = 'projectsubprocess'; const formatDate = 'DD-MM-YYYY'; @@ -50,9 +43,9 @@ describe('Process Header cloud component', () => { const tasksCloudDemoPage = new TasksCloudDemoPage(); const processCloudDemoPage = new ProcessCloudDemoPage(); - const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); - const processInstancesService: ProcessInstances = new ProcessInstances(); - const queryService: Query = new Query(); + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let queryService: QueryService; let silentLogin; let runningProcess, runningCreatedDate, parentCompleteProcess, childCompleteProcess, completedCreatedDate; @@ -61,19 +54,22 @@ describe('Process Header cloud component', () => { silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; - loginSSOPage.loginSSOIdentityService(user, password); - await processDefinitionService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + processDefinitionService = new ProcessDefinitionsService(apiService); const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); const childProcessDefinition = await processDefinitionService.getProcessDefinitions(subProcessApp); - await processInstancesService.init(user, password); + processInstancesService = new ProcessInstancesService(apiService); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, - simpleApp, {name: Util.generateRandomString(), businessKey: 'test'}); + simpleApp, { name: StringUtil.generateRandomString(), businessKey: 'test' }); runningCreatedDate = moment(runningProcess.entry.startDate).format(formatDate); parentCompleteProcess = await processInstancesService.createProcessInstance(childProcessDefinition.list.entries[0].entry.key, - subProcessApp, {name: 'cris'}); + subProcessApp, { name: 'cris' }); + + queryService = new QueryService(apiService); const parentProcessInstance = await queryService.getProcessInstanceSubProcesses(parentCompleteProcess.entry.id, subProcessApp); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index b733379589..aa0499f6c3 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -16,17 +16,14 @@ */ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; -import { ProcessInstances } from '../actions/APS-cloud/process-instances'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { ProcessListCloudConfiguration } from './processListCloud.config'; -import { browser } from 'protractor'; describe('Process list cloud', () => { @@ -38,12 +35,11 @@ describe('Process list cloud', () => { const appListCloudComponent = new AppListCloudPage(); const processCloudDemoPage = new ProcessCloudDemoPage(); - const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); - const processInstancesService: ProcessInstances = new ProcessInstances(); + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; let silentLogin; const simpleApp = 'candidateuserapp'; - const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let jsonFile; let runningProcess; @@ -51,12 +47,13 @@ describe('Process list cloud', () => { silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; - loginSSOPage.loginSSOIdentityService(user, password); - await processDefinitionService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + processDefinitionService = new ProcessDefinitionsService(apiService); const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - await processInstancesService.init(user, password); + processInstancesService = new ProcessInstancesService(apiService); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); }); @@ -82,7 +79,7 @@ describe('Process list cloud', () => { done(); }); - it('[C291997] Should be able to change the default columns', async() => { + it('[C291997] Should be able to change the default columns', async () => { expect(processCloudDemoPage.processListCloudComponent().getDataTable().getNumberOfColumns()).toBe(13); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('id'); diff --git a/e2e/process-services-cloud/processListCloud.config.ts b/e2e/process-services-cloud/processListCloud.config.ts index 174f750b62..dd399d093a 100644 --- a/e2e/process-services-cloud/processListCloud.config.ts +++ b/e2e/process-services-cloud/processListCloud.config.ts @@ -17,9 +17,6 @@ export class ProcessListCloudConfiguration { - constructor() { - } - getConfiguration() { return { 'presets': { diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index 1c278e0da2..b14e313e5c 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -22,7 +22,7 @@ import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Start Process', () => { @@ -33,9 +33,9 @@ describe('Start Process', () => { const appListCloudComponent = new AppListCloudPage(); const processCloudDemoPage = new ProcessCloudDemoPage(); const startProcessPage = new StartProcessPage(); - const processName = Util.generateRandomString(10); - const processName255Characters = Util.generateRandomString(255); - const processNameBiggerThen255Characters = Util.generateRandomString(256); + const processName = StringUtil.generateRandomString(10); + const processName255Characters = StringUtil.generateRandomString(255); + const processNameBiggerThen255Characters = StringUtil.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; const requiredError = 'Process Name is required', requiredProcessError = 'Process Definition is required'; const processDefinition = 'processwithvariables'; diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 84a232ced4..19aac34cb4 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -22,7 +22,7 @@ import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { StartTasksCloudPage } from '@alfresco/adf-testing'; -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { PeopleCloudComponent } from '../pages/adf/process-cloud/peopleCloudComponent'; import { TaskHeaderCloudPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; @@ -37,10 +37,10 @@ describe('Start Task', () => { const tasksCloudDemoPage = new TasksCloudDemoPage(); const startTask = new StartTasksCloudPage(); const peopleCloudComponent = new PeopleCloudComponent(); - const standaloneTaskName = Util.generateRandomString(5); - const unassignedTaskName = Util.generateRandomString(5); - const taskName255Characters = Util.generateRandomString(255); - const taskNameBiggerThen255Characters = Util.generateRandomString(256); + const standaloneTaskName = StringUtil.generateRandomString(5); + const unassignedTaskName = StringUtil.generateRandomString(5); + const taskName255Characters = StringUtil.generateRandomString(255); + const taskNameBiggerThen255Characters = StringUtil.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; const requiredError = 'Field required'; const dateValidationError = 'Date format DD/MM/YYYY'; diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index 304c2d0a87..51f7e21664 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -17,13 +17,12 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { LoginSSOPage, TasksService, ApiService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { Util } from '../util/util'; -import { Tasks } from '../actions/APS-cloud/tasks'; +import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Task filters cloud', () => { @@ -34,11 +33,11 @@ describe('Task filters cloud', () => { const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); + let tasksService: TasksService; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let silentLogin; - const newTask = Util.generateRandomString(5), completedTask = Util.generateRandomString(5); + const newTask = StringUtil.generateRandomString(5), completedTask = StringUtil.generateRandomString(5); const simpleApp = 'simple-app'; beforeAll(() => { @@ -62,7 +61,11 @@ describe('Task filters cloud', () => { }); it('[C290009] Should display default filters and created task', async () => { - await tasksService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); + const task = await tasksService.createStandaloneTask(newTask, simpleApp); await tasksService.claimTask(task.entry.id, simpleApp); @@ -77,7 +80,11 @@ describe('Task filters cloud', () => { }); it('[C289955] Should display task in Complete Tasks List when task is completed', async () => { - await tasksService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); + const task = await tasksService.createStandaloneTask(completedTask, simpleApp); await tasksService.claimTask(task.entry.id, simpleApp); diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index e9168e2382..7283102ef5 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -17,23 +17,21 @@ import TestConfig = require('../test.config'); import CONSTANTS = require('../util/constants'); -import { Util } from '../util/util'; +import { ApiService, StringUtil } from '@alfresco/adf-testing'; import moment = require('moment'); -import { Tasks } from '../actions/APS-cloud/tasks'; - import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { LoginSSOPage } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { TaskHeaderCloudPage } from '@alfresco/adf-testing'; +import { TaskHeaderCloudPage, TasksService } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Task Header cloud component', () => { const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - const basicCreatedTaskName = Util.generateRandomString(), completedTaskName = Util.generateRandomString(); + const basicCreatedTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(); let basicCreatedTask, basicCreatedDate, completedTask, completedCreatedDate, subTask, subTaskCreatedDate; const simpleApp = 'simple-app'; const priority = 30, description = 'descriptionTask', formatDate = 'MMM DD YYYY'; @@ -45,7 +43,7 @@ describe('Task Header cloud component', () => { const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); + let tasksService: TasksService; let silentLogin; @@ -56,7 +54,11 @@ describe('Task Header cloud component', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - await tasksService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); + const createdTaskId = await tasksService.createStandaloneTask(basicCreatedTaskName, simpleApp); await tasksService.claimTask(createdTaskId.entry.id, simpleApp); basicCreatedTask = await tasksService.getTask(createdTaskId.entry.id, simpleApp); @@ -69,7 +71,7 @@ describe('Task Header cloud component', () => { completedTask = await tasksService.getTask(completedTaskId.entry.id, simpleApp); completedCreatedDate = moment(completedTask.entry.createdDate).format(formatDate); - const subTaskId = await tasksService.createStandaloneSubtask(createdTaskId.entry.id, simpleApp, Util.generateRandomString()); + const subTaskId = await tasksService.createStandaloneSubtask(createdTaskId.entry.id, simpleApp, StringUtil.generateRandomString()); await tasksService.claimTask(subTaskId.entry.id, simpleApp); subTask = await tasksService.getTask(subTaskId.entry.id, simpleApp); subTaskCreatedDate = moment(subTask.entry.createdDate).format(formatDate); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index cd73ae7cfc..bc67a31098 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { StringUtil, TasksService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; @@ -25,13 +25,9 @@ import { AppListCloudPage } from '@alfresco/adf-testing'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { TaskListCloudConfiguration } from './taskListCloud.config'; -import { Util } from '../util/util'; import moment = require('moment'); import { DateUtil } from '../util/dateUtil'; -import { Tasks } from '../actions/APS-cloud/tasks'; -import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; -import { ProcessInstances } from '../actions/APS-cloud/process-instances'; import { NotificationPage } from '../pages/adf/notificationPage'; import { browser } from 'protractor'; @@ -42,12 +38,13 @@ describe('Edit task filters and task list properties', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); + const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); - const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); - const processInstancesService: ProcessInstances = new ProcessInstances(); + let tasksService: TasksService; + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; const notificationPage = new NotificationPage(); let silentLogin; @@ -91,21 +88,24 @@ describe('Edit task filters and task list properties', () => { '}'); configEditorPage.clickSaveButton(); - await tasksService.init(user, password); - createdTask = await tasksService.createStandaloneTask(Util.generateRandomString(), simpleApp); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); + createdTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); await tasksService.claimTask(createdTask.entry.id, simpleApp); - notAssigned = await tasksService.createStandaloneTask(Util.generateRandomString(), simpleApp); - priorityTask = await tasksService.createStandaloneTask(Util.generateRandomString(), simpleApp, {priority: priority}); + notAssigned = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); + priorityTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp, {priority: priority}); await tasksService.claimTask(priorityTask.entry.id, simpleApp); - notDisplayedTask = await tasksService.createStandaloneTask(Util.generateRandomString(), candidateUserApp); + notDisplayedTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateUserApp); await tasksService.claimTask(notDisplayedTask.entry.id, candidateUserApp); - await processDefinitionService.init(user, password); + processDefinitionService = new ProcessDefinitionsService(apiService); processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - await processInstancesService.init(user, password); + processInstancesService = new ProcessInstancesService(apiService); processInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - subTask = await tasksService.createStandaloneSubtask(createdTask.entry.id, simpleApp, Util.generateRandomString()); + subTask = await tasksService.createStandaloneSubtask(createdTask.entry.id, simpleApp, StringUtil.generateRandomString()); await tasksService.claimTask(subTask.entry.id, simpleApp); done(); diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index b2c9c14af9..9ba734b21c 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -17,13 +17,12 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { ApiService, LoginSSOPage, TasksService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { Util } from '../util/util'; -import { Tasks } from '../actions/APS-cloud/tasks'; +import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Task list cloud - selection', () => { @@ -35,7 +34,7 @@ describe('Task list cloud - selection', () => { const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); + let tasksService: TasksService; let silentLogin; const simpleApp = 'simple-app'; @@ -51,9 +50,13 @@ describe('Task list cloud - selection', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - await tasksService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); + for (let i = 0; i < noOfTasks; i++) { - response = await tasksService.createStandaloneTask(Util.generateRandomString(), simpleApp); + response = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); await tasksService.claimTask(response.entry.id, simpleApp); tasks.push(response.entry.name); } diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index b92b12db77..aa2d9d5396 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -17,17 +17,12 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; +import { StringUtil, TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { Tasks } from '../actions/APS-cloud/tasks'; -import { ProcessDefinitions } from '../actions/APS-cloud/process-definitions'; -import { ProcessInstances } from '../actions/APS-cloud/process-instances'; -import { Query } from '../actions/APS-cloud/query'; -import { Util } from '../util/util'; import { browser } from 'protractor'; describe('Task filters cloud', () => { @@ -38,14 +33,14 @@ describe('Task filters cloud', () => { const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); - const tasksService: Tasks = new Tasks(); - const processDefinitionService: ProcessDefinitions = new ProcessDefinitions(); - const processInstancesService: ProcessInstances = new ProcessInstances(); - const queryService: Query = new Query(); + let tasksService: TasksService; + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let queryService: QueryService; let silentLogin; - const createdTaskName = Util.generateRandomString(), completedTaskName = Util.generateRandomString(), - assignedTaskName = Util.generateRandomString(), deletedTaskName = Util.generateRandomString(); + const createdTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(), + assignedTaskName = StringUtil.generateRandomString(), deletedTaskName = StringUtil.generateRandomString(); const simpleApp = 'simple-app'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let assignedTask, deletedTask, suspendedTasks; @@ -60,7 +55,10 @@ describe('Task filters cloud', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - await tasksService.init(user, password); + const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); await tasksService.createStandaloneTask(createdTaskName, simpleApp); assignedTask = await tasksService.createStandaloneTask(assignedTaskName, simpleApp); @@ -73,12 +71,13 @@ describe('Task filters cloud', () => { priority = priority + 20; } - await processDefinitionService.init(user, password); + processDefinitionService = new ProcessDefinitionsService(apiService); const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - await processInstancesService.init(user, password); + processInstancesService = new ProcessInstancesService(apiService); const processInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); const secondProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - await queryService.init(user, password); + + queryService = new QueryService(apiService); suspendedTasks = await queryService.getProcessInstanceTasks(processInstance.entry.id, simpleApp); await queryService.getProcessInstanceTasks(secondProcessInstance.entry.id, simpleApp); await processInstancesService.suspendProcessInstance(processInstance.entry.id, simpleApp); diff --git a/e2e/process-services/start-process-component.e2e.ts b/e2e/process-services/start-process-component.e2e.ts index be45253e7f..be7abe67b4 100644 --- a/e2e/process-services/start-process-component.e2e.ts +++ b/e2e/process-services/start-process-component.e2e.ts @@ -38,6 +38,7 @@ import dateFormat = require('dateformat'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import path = require('path'); +import { StringUtil } from '@alfresco/adf-testing'; describe('Start Process Component', () => { @@ -54,8 +55,8 @@ describe('Start Process Component', () => { const simpleApp = resources.Files.WIDGETS_SMOKE_TEST; let appId, procUserModel, secondProcUserModel, tenantId, simpleAppCreated; const processModelWithSe = 'process_with_se', processModelWithoutSe = 'process_without_se'; - const processName255Characters = Util.generateRandomString(255); - const processNameBiggerThen255Characters = Util.generateRandomString(256); + const processName255Characters = StringUtil.generateRandomString(255); + const processNameBiggerThen255Characters = StringUtil.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; const auditLogFile = path.join('../e2e/download/', 'Audit.pdf'); diff --git a/e2e/process-services/start-task-task-app.e2e.ts b/e2e/process-services/start-task-task-app.e2e.ts index fbe87390ff..894ad6fd80 100644 --- a/e2e/process-services/start-task-task-app.e2e.ts +++ b/e2e/process-services/start-task-task-app.e2e.ts @@ -33,7 +33,7 @@ import resources = require('../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UsersActions } from '../actions/users.actions'; -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import fs = require('fs'); import path = require('path'); @@ -50,8 +50,8 @@ describe('Start Task - Task App', () => { const formFieldValue = 'First value '; const taskPage = new TasksPage(); const firstComment = 'comm1', firstChecklist = 'checklist1'; - const taskName255Characters = Util.generateRandomString(255); - const taskNameBiggerThen255Characters = Util.generateRandomString(256); + const taskName255Characters = StringUtil.generateRandomString(255); + const taskNameBiggerThen255Characters = StringUtil.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; const tasks = ['Modifying task', 'Information box', 'No form', 'Not Created', 'Refreshing form', 'Assignee task', 'Attach File']; const showHeaderTask = 'Show Header'; diff --git a/e2e/process-services/task-details-form.e2e.ts b/e2e/process-services/task-details-form.e2e.ts index b77a7bd348..04b7d0b13a 100644 --- a/e2e/process-services/task-details-form.e2e.ts +++ b/e2e/process-services/task-details-form.e2e.ts @@ -16,7 +16,7 @@ */ import TestConfig = require('../test.config'); -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); import { LoginPage } from '../pages/adf/loginPage'; @@ -41,19 +41,19 @@ describe('Task Details - Form', () => { beforeAll(async (done) => { const users = new UsersActions(); const attachedFormModel = { - 'name': Util.generateRandomString(), + 'name': StringUtil.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; const otherTaskModel = new StandaloneTask(); const otherAttachedFormModel = { - 'name': Util.generateRandomString(), + 'name': StringUtil.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; - const newFormModel = { 'name': Util.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; + const newFormModel = { 'name': StringUtil.generateRandomString(), 'description': '', 'modelType': 2, 'stencilSet': 0 }; this.alfrescoJsApi = new AlfrescoApi({ provider: 'BPM', diff --git a/e2e/restAPI/httpRequest/HTTPRequestPublic.js b/e2e/restAPI/httpRequest/HTTPRequestPublic.js index 3d58a7249a..535ab6dc8c 100644 --- a/e2e/restAPI/httpRequest/HTTPRequestPublic.js +++ b/e2e/restAPI/httpRequest/HTTPRequestPublic.js @@ -17,6 +17,6 @@ var HTTPRequestPublic = function(authorization) { this.authorization = authorization; -} +}; module.exports = HTTPRequestPublic; diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index f4a0b2139d..73c56c4676 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -31,7 +31,7 @@ import { SearchConfiguration } from '../search.config'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { browser } from 'protractor'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; describe('Search Checklist Component', () => { @@ -51,7 +51,7 @@ describe('Search Checklist Component', () => { custom: 'TEST_NAME' }; - const randomName = Util.generateRandomString(); + const randomName = StringUtil.generateRandomString(); const nodeNames = { document: `${randomName}.txt`, folder: `${randomName}Folder` diff --git a/e2e/search/components/search-radio.e2e.ts b/e2e/search/components/search-radio.e2e.ts index 6f86234e75..e515248938 100644 --- a/e2e/search/components/search-radio.e2e.ts +++ b/e2e/search/components/search-radio.e2e.ts @@ -31,7 +31,7 @@ import { SearchConfiguration } from '../search.config'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { browser } from 'protractor'; -import { Util } from '../../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; describe('Search Radio Component', () => { @@ -53,7 +53,7 @@ describe('Search Radio Component', () => { custom: 'TEST_NAME' }; - const randomName = Util.generateRandomString(); + const randomName = StringUtil.generateRandomString(); const nodeNames = { document: `${randomName}.txt`, folder: `${randomName}Folder` diff --git a/e2e/search/search-component.e2e.ts b/e2e/search/search-component.e2e.ts index 8909337c36..e0fdba8876 100644 --- a/e2e/search/search-component.e2e.ts +++ b/e2e/search/search-component.e2e.ts @@ -29,6 +29,7 @@ import { FolderModel } from '../models/ACS/folderModel'; import TestConfig = require('../test.config'); import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; @@ -43,7 +44,7 @@ describe('Search component - Search Bar', () => { firstChar: 'x', secondChar: 'y', thirdChar: 'z', - name: 'impossible-name-folder' + Util.generateRandomString(8) + name: 'impossible-name-folder' + StringUtil.generateRandomString(8) } }; @@ -57,10 +58,10 @@ describe('Search component - Search Bar', () => { const acsUser = new AcsUserModel(); const uploadActions = new UploadActions(); - const filename = Util.generateRandomString(16); - const firstFolderName = Util.generateRandomString(16); - const secondFolderName = Util.generateRandomString(16); - const thirdFolderName = Util.generateRandomString(16); + const filename = StringUtil.generateRandomString(16); + const firstFolderName = StringUtil.generateRandomString(16); + const secondFolderName = StringUtil.generateRandomString(16); + const thirdFolderName = StringUtil.generateRandomString(16); const filesToDelete = []; const firstFileModel = new FileModel({ @@ -98,7 +99,7 @@ describe('Search component - Search Bar', () => { Object.assign(firstFileModel, firstFileUploaded.entry); fileHighlightUploaded = await this.alfrescoJsApi.nodes.addNode('-my-', { - 'name': Util.generateRandomString(16), + 'name': StringUtil.generateRandomString(16), 'nodeType': 'cm:content', 'properties': { 'cm:title': term, diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index 72395d6edb..a71226d223 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -28,7 +28,7 @@ import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FileModel } from '../models/ACS/fileModel'; import TestConfig = require('../test.config'); -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import resources = require('../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; @@ -50,11 +50,11 @@ describe('Search Filters', () => { const acsUser = new AcsUserModel(); - const filename = Util.generateRandomString(16); - const fileNamePrefix = Util.generateRandomString(5); - const uniqueFileName1 = fileNamePrefix + Util.generateRandomString(5); - const uniqueFileName2 = fileNamePrefix + Util.generateRandomString(5); - const uniqueFileName3 = fileNamePrefix + Util.generateRandomString(5); + const filename = StringUtil.generateRandomString(16); + const fileNamePrefix = StringUtil.generateRandomString(5); + const uniqueFileName1 = fileNamePrefix + StringUtil.generateRandomString(5); + const uniqueFileName2 = fileNamePrefix + StringUtil.generateRandomString(5); + const uniqueFileName3 = fileNamePrefix + StringUtil.generateRandomString(5); const fileModel = new FileModel({ 'name': filename, 'shortName': filename.substring(0, 8) diff --git a/e2e/search/search-multiselect.e2e.ts b/e2e/search/search-multiselect.e2e.ts index 8d19614bcf..8b2934b333 100644 --- a/e2e/search/search-multiselect.e2e.ts +++ b/e2e/search/search-multiselect.e2e.ts @@ -18,7 +18,7 @@ import TestConfig = require('../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { Util } from '../util/util'; +import { StringUtil } from '@alfresco/adf-testing'; import resources = require('../util/resources'); import CONSTANTS = require('../util/constants'); import { UploadActions } from '../actions/ACS/upload.actions'; @@ -51,7 +51,7 @@ describe('Search Component - Multi-Select Facet', () => { let jpgFile, jpgFileSite, txtFile, txtFileSite; const acsUser = new AcsUserModel(); - const randomName = Util.generateRandomString(); + const randomName = StringUtil.generateRandomString(); const jpgFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': `${randomName}.jpg` @@ -69,7 +69,7 @@ describe('Search Component - Multi-Select Facet', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(8), + title: StringUtil.generateRandomString(8), visibility: 'PUBLIC' }); @@ -132,7 +132,7 @@ describe('Search Component - Multi-Select Facet', () => { const userUploadingTxt = new AcsUserModel(); const userUploadingImg = new AcsUserModel(); - const randomName = Util.generateRandomString(); + const randomName = StringUtil.generateRandomString(); const jpgFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.JPG.file_location, 'name': `${randomName}.jpg` @@ -151,7 +151,7 @@ describe('Search Component - Multi-Select Facet', () => { await this.alfrescoJsApi.login(userUploadingTxt.id, userUploadingTxt.password); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(8), + title: StringUtil.generateRandomString(8), visibility: 'PUBLIC' }); @@ -201,7 +201,7 @@ describe('Search Component - Multi-Select Facet', () => { let txtFile; const acsUser = new AcsUserModel(); - const randomName = Util.generateRandomString(); + const randomName = StringUtil.generateRandomString(); const txtFileInfo = new FileModel({ 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location, 'name': `${randomName}.txt` @@ -215,7 +215,7 @@ describe('Search Component - Multi-Select Facet', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: Util.generateRandomString(8), + title: StringUtil.generateRandomString(8), visibility: 'PUBLIC' }); diff --git a/e2e/search/search-page-component.e2e.ts b/e2e/search/search-page-component.e2e.ts index 24c5fba447..a9d8d156ef 100644 --- a/e2e/search/search-page-component.e2e.ts +++ b/e2e/search/search-page-component.e2e.ts @@ -31,6 +31,7 @@ import { FileModel } from '../models/ACS/fileModel'; import TestConfig = require('../test.config'); import { Util } from '../util/util'; import resources = require('../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; @@ -40,7 +41,7 @@ describe('Search component - Search Page', () => { active: { firstFile: null, secondFile: null, - base: Util.generateRandomString(7), + base: StringUtil.generateRandomString(7), extension: '.txt' }, no_permission: { @@ -56,17 +57,16 @@ describe('Search component - Search Page', () => { const filePreviewPage = new FilePreviewPage(); const acsUser = new AcsUserModel(); - const emptyFolderModel = new FolderModel({ 'name': 'search' + Util.generateRandomString() }); + const emptyFolderModel = new FolderModel({ 'name': 'search' + StringUtil.generateRandomString() }); let firstFileModel; const newFolderModel = new FolderModel({ 'name': 'newFolder' }); let fileNames = []; - let adminFileNames = []; const nrOfFiles = 15; const adminNrOfFiles = 5; beforeAll(async (done) => { fileNames = Util.generateSequenceFiles(1, nrOfFiles, search.active.base, search.active.extension); - adminFileNames = Util.generateSequenceFiles(nrOfFiles + 1, nrOfFiles + adminNrOfFiles, search.active.base, search.active.extension); + const adminFileNames = Util.generateSequenceFiles(nrOfFiles + 1, nrOfFiles + adminNrOfFiles, search.active.base, search.active.extension); search.active.firstFile = fileNames[0]; search.active.secondFile = fileNames[1]; fileNames.splice(0, 1); @@ -84,9 +84,7 @@ describe('Search component - Search Page', () => { }); await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); await uploadActions.createFolder(this.alfrescoJsApi, emptyFolderModel.name, '-my-'); @@ -108,7 +106,7 @@ describe('Search component - Search Page', () => { }); it('[C260264] Should display message when no results are found', () => { - const notExistentFileName = Util.generateRandomString(); + const notExistentFileName = StringUtil.generateRandomString(); searchDialog.checkSearchBarIsNotVisible().checkSearchIconIsVisible().clickOnSearchIcon() .enterTextAndPressEnter(notExistentFileName); searchResultPage.checkNoResultMessageIsDisplayed(); diff --git a/e2e/test.config.js b/e2e/test.config.js index 1c298d23c9..4fabcf4f73 100644 --- a/e2e/test.config.js +++ b/e2e/test.config.js @@ -82,6 +82,7 @@ module.exports = { baseUrl = HOST; } + return `http://${baseUrl}/auth/admin/realms/alfresco`; }() diff --git a/e2e/util/material.ts b/e2e/util/material.ts index 3805b29ba7..13cf5fcadc 100644 --- a/e2e/util/material.ts +++ b/e2e/util/material.ts @@ -16,10 +16,10 @@ */ import { ElementFinder } from 'protractor'; -import { Util } from './util'; +import { BrowserVisibility } from '@alfresco/adf-testing'; export function uncheck(el: ElementFinder) { - Util.waitUntilElementIsVisible(el); + BrowserVisibility.waitUntilElementIsVisible(el); el.getAttribute('class').then((classList) => { if (classList && classList.indexOf('mat-checked') > -1) { el.click(); @@ -29,7 +29,7 @@ export function uncheck(el: ElementFinder) { } export function check(el: ElementFinder) { - Util.waitUntilElementIsVisible(el); + BrowserVisibility.waitUntilElementIsVisible(el); el.getAttribute('class').then((classList) => { if (classList && classList.indexOf('mat-checked') === -1) { el.click(); diff --git a/e2e/util/util.ts b/e2e/util/util.ts index 27a7272c35..c349d91452 100644 --- a/e2e/util/util.ts +++ b/e2e/util/util.ts @@ -15,117 +15,11 @@ * limitations under the License. */ -import { browser, protractor } from 'protractor'; +import { browser } from 'protractor'; import fs = require('fs'); -import path = require('path'); -import TestConfig = require('../test.config'); - -const until = protractor.ExpectedConditions; -const DEFAULT_TIMEOUT = parseInt(TestConfig.main.timeout, 10); export class Util { - /** - * creates an absolute path string if multiple file uploads are required - */ - static uploadParentFolder(filePath) { - const parentFolder = path.resolve(path.join(__dirname, 'test')); - return path.resolve(path.join(parentFolder, filePath)); - } - - /** - * Generates a random string. - * - * @param length {int} If this parameter is not provided the length is set to 8 by default. - * @return {string} - * @method generateRandomString - */ - static generateRandomString(length: number = 8): string { - let text = ''; - const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - - for (let i = 0; i < length; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - - return text; - } - - static generatePasswordString(length: number = 8): string { - let text = ''; - const possibleUpperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - const possibleLowerCase = 'abcdefghijklmnopqrstuvwxyz'; - const lowerCaseLimit = Math.floor(length / 2); - - for (let i = 0; i < lowerCaseLimit; i++) { - text += possibleLowerCase.charAt(Math.floor(Math.random() * possibleLowerCase.length)); - } - - for (let i = 0; i < length - lowerCaseLimit; i++) { - text += possibleUpperCase.charAt(Math.floor(Math.random() * possibleUpperCase.length)); - } - - return text; - } - - /** - * Generates a random string - digits only. - * - * @param length {int} If this parameter is not provided the length is set to 8 by default. - * @return {string} - * @method generateRandomString - */ - static generateRandomStringDigits(length: number = 8): string { - let text = ''; - const possible = '0123456789'; - - for (let i = 0; i < length; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - - return text; - } - - /** - * Generates a random string - non-latin characters only. - * - * @param length {int} If this parameter is not provided the length is set to 3 by default. - * @return {string} - * @method generateRandomString - */ - static generateRandomStringNonLatin(length: number = 3): string { - let text = ''; - const possible = '密码你好𠮷'; - - for (let i = 0; i < length; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - - return text; - } - - /** - * Generates a random string to lowercase. - * - * @param length {int} If this parameter is not provided the length is set to 8 by default. - * @return {string} - * @method generateRandomString - */ - static generateRandomStringToLowerCase(length?: number): string { - return this.generateRandomString(length).toLowerCase(); - } - - /** - * Generates a random string to uppercase. - * - * @param length {int} If this parameter is not provided the length is set to 8 by default. - * @return {string} - * @method generateRandomString - */ - static generateRandomStringToUpperCase(length?: number): string { - return this.generateRandomString(length).toUpperCase(); - } - /** * Generates a sequence of files with name: baseName + index + extension (e.g.) baseName1.txt, baseName2.txt, ... * @@ -144,72 +38,6 @@ export class Util { return fileNames; } - /** - * Generates a random number (as int) in the interval [min, max). - * - * @param min {int} - * @param max {int} - * @return {number} - * @method generateRandomInt - */ - static generateRandomInt(min, max) { - return Math.floor(Math.random() * (max - min) + min); - } - - /** - * Generates a random email address following the format: abcdef@activiti.test.com - * - * @param length {int} - * @return {string} - * @method generateRandomEmail - */ - static generateRandomEmail(length: number = 5): string { - let email = ''; - const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - - for (let i = 0; i < length; i++) { - email += possible.charAt(Math.floor(Math.random() * possible.length)); - } - - email += '@activiti.test.com'; - return email.toLowerCase(); - } - - /** - * Generates a random date inside the interval [1990, 2100) following the format dd.mm.yyyy - * - * @method generateRandomDateFormat - */ - static generateRandomDateFormat(): string { - const day = Math.floor(Math.random() * (29 - 1) + 1); - const month = Math.floor(Math.random() * (12 - 1) + 1); - const year = Math.floor(Math.random() * (2100 - 1990) + 1990); - - return day + '.' + month + '.' + year; - } - - /** - * Generates a random date inside the interval [1990, 2100) following the format dd-mm-yyyy. - * - * @method generateRandomDate - */ - static generateRandomDate(): string { - let dayText; - let monthText; - - const day = (Math.floor(Math.random() * (29 - 1) + 1)); - if (day < 10) { - dayText = '0' + day.toString(); - } - const month = Math.floor(Math.random() * (12 - 1) + 1); - if (month < 10) { - monthText = '0' + month.toString(); - } - const year = Math.floor(Math.random() * (2100 - 1990) + 1990); - - return dayText + '-' + monthText + '-' + year.toString(); - } - /** * Returns TRUE if the first array contains all elements from the second one. * @@ -228,122 +56,6 @@ export class Util { }); } - /** - * Reads the content of the file and provides it on callback - * - * @param filePath - * @param callback - * @method readFile - */ - static readFile(filePath, callback) { - const absolutePath = path.join(TestConfig.main.rootPath + filePath); - fs.readFile(absolutePath, { encoding: 'utf8' }, function (err, data) { - if (err) { - throw err; - } - callback(data); - }); - } - - static waitUntilElementIsVisible(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - let isDisplayed = false; - return browser.wait(() => { - browser.waitForAngularEnabled(); - - elementToCheck.isDisplayed().then( - () => { - isDisplayed = true; - }, - (err) => { - isDisplayed = false; - } - ); - return isDisplayed; - }, waitTimeout, 'Element is not visible ' + elementToCheck.locator()); - } - - static waitUntilElementIsPresent(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - browser.waitForAngularEnabled(); - - return browser.wait(until.presenceOf(elementToCheck), waitTimeout, 'Element is not present ' + elementToCheck.locator()); - } - - /* - * Wait for element to have value - */ - static waitUntilElementHasValue(elementToCheck, elementValue, waitTimeout: number = DEFAULT_TIMEOUT) { - browser.waitForAngularEnabled(); - - browser.wait(until.textToBePresentInElementValue(elementToCheck, elementValue), waitTimeout, 'Element doesn\'t have a value ' + elementToCheck.locator()); - } - - /* - * Wait for element to be clickable - */ - static waitUntilElementIsClickable(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - return browser.wait(() => { - browser.waitForAngularEnabled(); - return until.elementToBeClickable(elementToCheck); - }, waitTimeout, 'Element is not Clickable' + elementToCheck.locator()); - } - - /* - * Wait for element to not be visible - */ - static waitUntilElementIsNotVisible(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - return browser.wait(() => { - browser.waitForAngularEnabled(); - return elementToCheck.isPresent().then(function (present) { - return !present; - }); - }, waitTimeout, 'Element is Visible and it should not' + elementToCheck.locator()); - } - - static waitUntilElementIsNotDisplayed(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - return browser.wait(() => { - browser.waitForAngularEnabled(); - return elementToCheck.isDisplayed().then(function (present) { - return !present; - }); - }, waitTimeout, 'Element is dysplayed and it should not' + elementToCheck.locator()); - } - - /* - * Wait for element to not be visible - */ - static waitUntilElementIsStale(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - return browser.wait(until.stalenessOf(elementToCheck), waitTimeout, 'Element is not in stale ' + elementToCheck.locator()); - } - - /* - * Wait for element to not be visible - */ - static waitUntilElementIsNotOnPage(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - return browser.wait(() => { - browser.waitForAngularEnabled(); - return browser.wait(until.not(until.visibilityOf(elementToCheck))); - }, waitTimeout, 'Element is not in the page ' + elementToCheck.locator()); - } - - static waitUntilElementIsOnPage(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { - return browser.wait(browser.wait(until.visibilityOf(elementToCheck)), waitTimeout); - } - - /** - * @method waitForPage - */ - static waitForPage() { - browser.wait(function () { - const deferred = protractor.promise.defer(); - browser.executeScript('return document.readyState').then((text) => { - deferred.fulfill(() => { - return text === 'complete'; - }); - }); - return deferred.promise; - }); - } - static openNewTabInBrowser() { browser.driver.executeScript("window.open('about: blank', '_blank');"); } diff --git a/lib/testing/src/lib/content-services/actions/example.action.ts b/lib/testing/src/lib/content-services/actions/example.action.ts index e3ebd14983..9ad97c1557 100644 --- a/lib/testing/src/lib/content-services/actions/example.action.ts +++ b/lib/testing/src/lib/content-services/actions/example.action.ts @@ -1,6 +1,6 @@ /*! * @license - * Copyright 2016 Alfresco Software, Ltd. + * 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. diff --git a/lib/testing/src/lib/content-services/actions/public-api.ts b/lib/testing/src/lib/content-services/actions/public-api.ts index c5eb261e15..005ff462eb 100644 --- a/lib/testing/src/lib/content-services/actions/public-api.ts +++ b/lib/testing/src/lib/content-services/actions/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './example.action'; diff --git a/lib/testing/src/lib/content-services/pages/example.page.ts b/lib/testing/src/lib/content-services/pages/example.page.ts index cb7bdb491f..9c83469852 100644 --- a/lib/testing/src/lib/content-services/pages/example.page.ts +++ b/lib/testing/src/lib/content-services/pages/example.page.ts @@ -1,6 +1,6 @@ /*! * @license - * Copyright 2016 Alfresco Software, Ltd. + * 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. diff --git a/lib/testing/src/lib/content-services/pages/public-api.ts b/lib/testing/src/lib/content-services/pages/public-api.ts index 12e314e7c7..1233d842d2 100644 --- a/lib/testing/src/lib/content-services/pages/public-api.ts +++ b/lib/testing/src/lib/content-services/pages/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './example.page'; diff --git a/lib/testing/src/lib/content-services/public-api.ts b/lib/testing/src/lib/content-services/public-api.ts index dcc70fb91a..357976c2aa 100644 --- a/lib/testing/src/lib/content-services/public-api.ts +++ b/lib/testing/src/lib/content-services/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './pages/public-api'; diff --git a/e2e/actions/APS-cloud/apiservice.ts b/lib/testing/src/lib/core/actions/api.service.ts similarity index 66% rename from e2e/actions/APS-cloud/apiservice.ts rename to lib/testing/src/lib/core/actions/api.service.ts index 6ef8cef966..4e692c79b2 100644 --- a/e2e/actions/APS-cloud/apiservice.ts +++ b/lib/testing/src/lib/core/actions/api.service.ts @@ -16,46 +16,42 @@ */ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import TestConfig = require('../../test.config'); import { AlfrescoApiConfig } from '@alfresco/js-api/src/alfrescoApiConfig'; export class ApiService { - HOST_SSO: string = TestConfig.adf.hostSso; - HOST_BPM: string = TestConfig.adf.hostBPM; - HOST_IDENTITY: string = TestConfig.adf.hostIdentity; + apiService: AlfrescoApi; - config: AlfrescoApiConfig = { - provider: 'BPM', - hostBpm: this.HOST_BPM, - authType: 'OAUTH', - oauth2: { - host: this.HOST_SSO, - clientId: 'activiti', - scope: 'openid', - secret: '', - implicitFlow: false, - silentLogin: false, - redirectUri: '/', - redirectUriLogout: '/logout' - } + config: AlfrescoApiConfig; - }; + constructor(clientId: string, host: string, hostSso: string, provider: string) { + this.config = { + provider: provider, + hostBpm: host, + hostEcm: host, + authType: 'OAUTH', + oauth2: { + host: hostSso, + clientId: clientId, + scope: 'openid', + secret: '', + implicitFlow: false, + silentLogin: false, + redirectUri: '/', + redirectUriLogout: '/logout' + } - apiService: any; + }; - constructor(clientId: string = 'activiti') { - this.config.oauth2.clientId = clientId; this.apiService = new AlfrescoApi(this.config); - } - async login(username, password) { + async login(username: string, password: string) { await this.apiService.login(username, password); } - async performBpmOperation(path, method, queryParams, postBody) { - const uri = this.HOST_BPM + path; + async performBpmOperation(path: string, method: string, queryParams: any, postBody: any) { + const uri = this.config.hostBpm + path; const pathParams = {}, formParams = {}; const contentTypes = ['application/json']; const accepts = ['application/json']; @@ -71,8 +67,8 @@ export class ApiService { }); } - async performIdentityOperation(path, method, queryParams, postBody) { - const uri = this.HOST_IDENTITY + path; + async performIdentityOperation(path: string, method: string, queryParams: any, postBody: any) { + const uri = this.config.oauth2.host.replace('/realms', '/admin/realms') + path; const pathParams = {}, formParams = {}; const contentTypes = ['application/json']; const accepts = ['application/json']; diff --git a/e2e/actions/APS-cloud/groupIdentity.ts b/lib/testing/src/lib/core/actions/identity/group-identity.service.ts similarity index 86% rename from e2e/actions/APS-cloud/groupIdentity.ts rename to lib/testing/src/lib/core/actions/identity/group-identity.service.ts index 899cd4e066..9f7b9a346d 100644 --- a/e2e/actions/APS-cloud/groupIdentity.ts +++ b/lib/testing/src/lib/core/actions/identity/group-identity.service.ts @@ -15,18 +15,18 @@ * limitations under the License. */ -import { ApiService } from '../APS-cloud/apiservice'; -import { Util } from '../../util/util'; +import { ApiService } from '../api.service'; +import { StringUtil } from '../../string.util'; -export class GroupIdentity { +export class GroupIdentityService { - api: ApiService = new ApiService(); + api: ApiService; - async init(username, password) { - await this.api.login(username, password); + constructor(api: ApiService) { + this.api = api; } - async createIdentityGroup(groupName = Util.generateRandomString(5)) { + async createIdentityGroup(groupName = StringUtil.generateRandomString(5)) { await this.createGroup(groupName); const group = await this.getGroupInfoByGroupName(groupName); return group; diff --git a/e2e/actions/APS-cloud/identity.ts b/lib/testing/src/lib/core/actions/identity/identity.service.ts similarity index 62% rename from e2e/actions/APS-cloud/identity.ts rename to lib/testing/src/lib/core/actions/identity/identity.service.ts index d8b616f3d4..e42a46e4a7 100644 --- a/e2e/actions/APS-cloud/identity.ts +++ b/lib/testing/src/lib/core/actions/identity/identity.service.ts @@ -15,39 +15,59 @@ * limitations under the License. */ -import { ApiService } from '../APS-cloud/apiservice'; -import { Util } from '../../util/util'; +import { ApiService } from '../api.service'; +import { UserModel } from '../../models/user.model'; -export class Identity { +export class IdentityService { api: ApiService; - async init(username: string, password: string, clientId?: string) { - this.api = new ApiService(clientId); - await this.api.login(username, password); + constructor(api: ApiService) { + this.api = api; } - async createIdentityUser(username = Util.generateRandomString(5), password = Util.generateRandomString(5)) { - await this.createUser(username); - const user = await this.getUserInfoByUsername(username); - await this.resetPassword(user.id, password); - user.password = password; + async createIdentityUser(user: UserModel = new UserModel()) { + await this.createUser(user); + + const userIdentity = await this.getUserInfoByUsername(user.email); + await this.resetPassword(userIdentity.id, user.password); + user.idIdentityService = userIdentity.id; return user; } + async createIdentityUserAndSyncECMBPM(user: UserModel) { + if (this.api.config.provider === 'ECM' || this.api.config.provider === 'ALL') { + await this.api.apiService.core.peopleApi.addPerson(user); + } + + if (this.api.config.provider === 'BPM' || this.api.config.provider === 'ALL') { + await this.api.apiService.activiti.adminUsersApi.createNewUser({ + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + password: user.password, + type: 'enterprise', + tenantId: 1, + company: null + }); + } + + await this.createIdentityUser(user); + } + async deleteIdentityUser(userId) { await this.deleteUser(userId); } - async createUser(username) { + async createUser(user: UserModel) { const path = '/users'; const method = 'POST'; const queryParams = {}, postBody = { - 'username': username, - 'firstName': username, - 'lastName': 'LastName', + 'username': user.email, + 'firstName': user.firstName, + 'lastName': user.lastName, 'enabled': true, - 'email': username + '@alfresco.com' + 'email': user.email }; const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); return data; diff --git a/lib/testing/src/lib/core/actions/identity/public-api.ts b/lib/testing/src/lib/core/actions/identity/public-api.ts new file mode 100644 index 0000000000..1a5fe24bc1 --- /dev/null +++ b/lib/testing/src/lib/core/actions/identity/public-api.ts @@ -0,0 +1,22 @@ +/*! + * @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. + */ + +export * from './identity.service'; +export * from './group-identity.service'; +export * from './roles.service'; +export * from './tasks.service'; +export * from './query.service'; diff --git a/e2e/actions/APS-cloud/query.ts b/lib/testing/src/lib/core/actions/identity/query.service.ts similarity index 86% rename from e2e/actions/APS-cloud/query.ts rename to lib/testing/src/lib/core/actions/identity/query.service.ts index be0ec036b1..fdfbb4e660 100644 --- a/e2e/actions/APS-cloud/query.ts +++ b/lib/testing/src/lib/core/actions/identity/query.service.ts @@ -15,17 +15,14 @@ * limitations under the License. */ -import { ApiService } from './apiservice'; +import { ApiService } from '../api.service'; -export class Query { +export class QueryService { - api: ApiService = new ApiService(); + api: ApiService; - constructor() { - } - - async init(username, password) { - await this.api.login(username, password); + constructor(api: ApiService) { + this.api = api; } async getProcessInstanceTasks(processInstanceId, appName) { diff --git a/e2e/actions/APS-cloud/roles.ts b/lib/testing/src/lib/core/actions/identity/roles.service.ts similarity index 81% rename from e2e/actions/APS-cloud/roles.ts rename to lib/testing/src/lib/core/actions/identity/roles.service.ts index 3ee27fd39e..acce862c4b 100644 --- a/e2e/actions/APS-cloud/roles.ts +++ b/lib/testing/src/lib/core/actions/identity/roles.service.ts @@ -15,14 +15,14 @@ * limitations under the License. */ -import { ApiService } from '../APS-cloud/apiservice'; +import { ApiService } from '../api.service'; -export class Roles { +export class RolesService { - api: ApiService = new ApiService(); + api: ApiService; - async init(username, password) { - await this.api.login(username, password); + constructor(api: ApiService) { + this.api = api; } async getRoleIdByRoleName(roleName) { @@ -34,7 +34,7 @@ export class Roles { const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); for (const key in data) { if (data[key].name === roleName) { - roleId = data[key].id; + roleId = data[key].id; } } return roleId; diff --git a/e2e/actions/APS-cloud/tasks.ts b/lib/testing/src/lib/core/actions/identity/tasks.service.ts similarity index 93% rename from e2e/actions/APS-cloud/tasks.ts rename to lib/testing/src/lib/core/actions/identity/tasks.service.ts index 972955ab00..87d4e41417 100644 --- a/e2e/actions/APS-cloud/tasks.ts +++ b/lib/testing/src/lib/core/actions/identity/tasks.service.ts @@ -15,17 +15,14 @@ * limitations under the License. */ -import { ApiService } from './apiservice'; +import { ApiService } from '../api.service'; -export class Tasks { +export class TasksService { - api: ApiService = new ApiService(); + api: ApiService; - constructor() { - } - - async init(username, password) { - await this.api.login(username, password); + constructor(api: ApiService) { + this.api = api; } async createStandaloneTask(taskName, appName, options?) { diff --git a/lib/testing/src/lib/core/actions/public-api.ts b/lib/testing/src/lib/core/actions/public-api.ts index 79b4ec75e2..07aff579cd 100644 --- a/lib/testing/src/lib/core/actions/public-api.ts +++ b/lib/testing/src/lib/core/actions/public-api.ts @@ -1,3 +1,19 @@ -/* - * Public API Surface of testing +/*! + * @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. */ + +export * from './identity/public-api'; +export * from './api.service'; diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/browser-visibility.ts index 7c2ecfcc42..bd38a6c5cb 100644 --- a/lib/testing/src/lib/core/browser-visibility.ts +++ b/lib/testing/src/lib/core/browser-visibility.ts @@ -1,6 +1,6 @@ /*! * @license - * Copyright 2016 Alfresco Software, Ltd. + * 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. @@ -17,7 +17,6 @@ import { browser, protractor } from 'protractor'; const until = protractor.ExpectedConditions; - const DEFAULT_TIMEOUT = 40000; export class BrowserVisibility { @@ -64,6 +63,25 @@ export class BrowserVisibility { }, waitTimeout, 'Element is not visible ' + elementToCheck.locator()); } + /* + * Wait for element to not be visible + */ + static waitUntilElementIsStale(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { + return browser.wait(until.stalenessOf(elementToCheck), waitTimeout, 'Element is not in stale ' + elementToCheck.locator()); + } + + /* + * Wait for element to not be visible + */ + static waitUntilElementIsNotVisible(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { + return browser.wait(() => { + browser.waitForAngularEnabled(); + return elementToCheck.isPresent().then(function (present) { + return !present; + }); + }, waitTimeout, 'Element is Visible and it should not' + elementToCheck.locator()); + } + /* * Wait for element to have value */ @@ -73,6 +91,10 @@ export class BrowserVisibility { browser.wait(until.textToBePresentInElementValue(elementToCheck, elementValue), waitTimeout, 'Element doesn\'t have a value ' + elementToCheck.locator()); } + static waitUntilElementIsOnPage(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { + return browser.wait(browser.wait(until.visibilityOf(elementToCheck)), waitTimeout); + } + /* * Wait for element to not be visible */ @@ -80,4 +102,10 @@ export class BrowserVisibility { return browser.wait(until.not(until.visibilityOf(elementToCheck)), waitTimeout, 'Element is not in the page ' + elementToCheck.locator()); } + static waitUntilElementIsPresent(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { + browser.waitForAngularEnabled(); + + return browser.wait(until.presenceOf(elementToCheck), waitTimeout, 'Element is not present ' + elementToCheck.locator()); + } + } diff --git a/lib/testing/src/lib/core/models/public-api.ts b/lib/testing/src/lib/core/models/public-api.ts new file mode 100644 index 0000000000..5b16ef57a6 --- /dev/null +++ b/lib/testing/src/lib/core/models/public-api.ts @@ -0,0 +1,18 @@ +/*! + * @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. + */ + +export * from './user.model'; diff --git a/lib/testing/src/lib/core/models/user.model.ts b/lib/testing/src/lib/core/models/user.model.ts new file mode 100644 index 0000000000..b307c35a09 --- /dev/null +++ b/lib/testing/src/lib/core/models/user.model.ts @@ -0,0 +1,36 @@ +/*! + * @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 { StringUtil } from '../string.util'; + +export class UserModel { + + firstName: string = StringUtil.generateRandomString(); + lastName: string = StringUtil.generateRandomString(); + password: string = StringUtil.generateRandomString(); + email: string = StringUtil.generateRandomEmail('@alfresco.com'); + idIdentityService: string; + + constructor(details?: any) { + Object.assign(this, details); + } + + get id() { + return this.email; + } + +} diff --git a/lib/testing/src/lib/core/pages/header.page.ts b/lib/testing/src/lib/core/pages/header.page.ts index 97d397bbec..480bee699d 100644 --- a/lib/testing/src/lib/core/pages/header.page.ts +++ b/lib/testing/src/lib/core/pages/header.page.ts @@ -1,6 +1,6 @@ /*! * @license - * Copyright 2016 Alfresco Software, Ltd. + * 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. diff --git a/lib/testing/src/lib/core/pages/public-api.ts b/lib/testing/src/lib/core/pages/public-api.ts index a3a3be60b5..a1a7936cb0 100644 --- a/lib/testing/src/lib/core/pages/public-api.ts +++ b/lib/testing/src/lib/core/pages/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './header.page'; diff --git a/lib/testing/src/lib/core/public-api.ts b/lib/testing/src/lib/core/public-api.ts index f9bf45abd6..a81925d1f1 100644 --- a/lib/testing/src/lib/core/public-api.ts +++ b/lib/testing/src/lib/core/public-api.ts @@ -1,7 +1,23 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './browser-visibility'; +export * from './actions/public-api'; export * from './pages/public-api'; export * from './material/public-api'; +export * from './models/public-api'; +export * from './string.util'; diff --git a/lib/testing/src/lib/core/string.util.ts b/lib/testing/src/lib/core/string.util.ts new file mode 100644 index 0000000000..6ce0c5b50d --- /dev/null +++ b/lib/testing/src/lib/core/string.util.ts @@ -0,0 +1,106 @@ +/*! + * @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. + */ + +export class StringUtil { + + static generatePasswordString(length: number = 8): string { + let text = ''; + const possibleUpperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const possibleLowerCase = 'abcdefghijklmnopqrstuvwxyz'; + const lowerCaseLimit = Math.floor(length / 2); + + for (let i = 0; i < lowerCaseLimit; i++) { + text += possibleLowerCase.charAt(Math.floor(Math.random() * possibleLowerCase.length)); + } + + for (let i = 0; i < length - lowerCaseLimit; i++) { + text += possibleUpperCase.charAt(Math.floor(Math.random() * possibleUpperCase.length)); + } + + return text; + } + + /** + * Generates a random string. + * + * @param length If this parameter is not provided the length is set to 8 by default. + * @method generateRandomString + */ + static generateRandomString(length: number = 8): string { + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + for (let i = 0; i < length; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + + return text; + } + + /** + * Generates a random email address following the format: abcdef@activiti.test.com + * + * @param domain + * @param length + * @method generateRandomEmail + */ + static generateRandomEmail(domain: string, length: number = 5): string { + let email = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + for (let i = 0; i < length; i++) { + email += possible.charAt(Math.floor(Math.random() * possible.length)); + } + + email += domain; + return email.toLowerCase(); + } + + /** + * Generates a random string - digits only. + * + * @param length {int} If this parameter is not provided the length is set to 8 by default. + * @method generateRandomString + */ + static generateRandomStringDigits(length: number = 8): string { + let text = ''; + const possible = '0123456789'; + + for (let i = 0; i < length; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + + return text; + } + + /** + * Generates a random string - non-latin characters only. + * + * @param length {int} If this parameter is not provided the length is set to 3 by default. + * @method generateRandomString + */ + static generateRandomStringNonLatin(length: number = 3): string { + let text = ''; + const possible = '密码你好𠮷'; + + for (let i = 0; i < length; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + + return text; + } +} diff --git a/lib/testing/src/lib/material/public-api.ts b/lib/testing/src/lib/material/public-api.ts new file mode 100644 index 0000000000..5e77b5653c --- /dev/null +++ b/lib/testing/src/lib/material/public-api.ts @@ -0,0 +1,18 @@ +/*! + * @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. + */ + +export * from './tabs.page'; diff --git a/e2e/actions/APS-cloud/process-definitions.ts b/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts similarity index 79% rename from e2e/actions/APS-cloud/process-definitions.ts rename to lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts index 24a138db60..79042c8387 100644 --- a/e2e/actions/APS-cloud/process-definitions.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts @@ -15,17 +15,14 @@ * limitations under the License. */ -import { ApiService } from './apiservice'; +import { ApiService } from '../../core/actions/api.service'; -export class ProcessDefinitions { +export class ProcessDefinitionsService { - api: ApiService = new ApiService(); + api: ApiService; - constructor() { - } - - async init(username, password) { - await this.api.login(username, password); + constructor(api: ApiService) { + this.api = api; } async getProcessDefinitions(appName) { diff --git a/e2e/actions/APS-cloud/process-instances.ts b/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts similarity index 71% rename from e2e/actions/APS-cloud/process-instances.ts rename to lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts index 5a6f640744..57f644d112 100644 --- a/e2e/actions/APS-cloud/process-instances.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts @@ -15,20 +15,17 @@ * limitations under the License. */ -import { ApiService } from './apiservice'; +import { ApiService } from '../../core/actions/api.service'; -export class ProcessInstances { +export class ProcessInstancesService { - api: ApiService = new ApiService(); + api: ApiService; - constructor() { + constructor(api: ApiService) { + this.api = api; } - async init(username, password) { - await this.api.login(username, password); - } - - async createProcessInstance(processDefKey, appName, options?) { + async createProcessInstance(processDefKey, appName, options?: any) { const path = '/' + appName + '-rb/v1/process-instances'; const method = 'POST'; @@ -38,8 +35,7 @@ export class ProcessInstances { ...options }; - const data = await this.api.performBpmOperation(path, method, queryParams, postBody); - return data; + return await this.api.performBpmOperation(path, method, queryParams, postBody); } async suspendProcessInstance(processInstanceId, appName) { @@ -48,8 +44,7 @@ export class ProcessInstances { const queryParams = {}, postBody = {}; - const data = await this.api.performBpmOperation(path, method, queryParams, postBody); - return data; + return await this.api.performBpmOperation(path, method, queryParams, postBody); } async deleteProcessInstance(processInstanceId, appName) { @@ -58,8 +53,7 @@ export class ProcessInstances { const queryParams = {}, postBody = {}; - const data = await this.api.performBpmOperation(path, method, queryParams, postBody); - return data; + return await this.api.performBpmOperation(path, method, queryParams, postBody); } async completeProcessInstance(processInstanceId, appName) { @@ -68,7 +62,6 @@ export class ProcessInstances { const queryParams = {}, postBody = {}; - const data = await this.api.performBpmOperation(path, method, queryParams, postBody); - return data; + return await this.api.performBpmOperation(path, method, queryParams, postBody); } } diff --git a/lib/testing/src/lib/process-services-cloud/actions/public-api.ts b/lib/testing/src/lib/process-services-cloud/actions/public-api.ts index b55db50921..52277a363a 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/public-api.ts @@ -1,6 +1,21 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './testing-alfresco-api.service'; export * from './testing-app-config.service'; +export * from './process-definitions.service'; +export * from './process-instances.service'; diff --git a/lib/testing/src/lib/process-services-cloud/app/public-api.ts b/lib/testing/src/lib/process-services-cloud/app/public-api.ts index 3a6065b3f8..c3438aaa73 100644 --- a/lib/testing/src/lib/process-services-cloud/app/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/app/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ -export * from '../app/app-list-cloud.page'; +export * from './app-list-cloud.page'; diff --git a/lib/testing/src/lib/process-services-cloud/pages/login-sso.page.ts b/lib/testing/src/lib/process-services-cloud/pages/login-sso.page.ts index 3d8404f4ec..e4a6316abb 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/login-sso.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/login-sso.page.ts @@ -17,6 +17,7 @@ import { element, by, browser, protractor } from 'protractor'; import { BrowserVisibility } from '../../core/browser-visibility'; + export class LoginSSOPage { ssoButton = element(by.css(`[data-automation-id="login-button-sso"]`)); diff --git a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts index 151e1597ab..09b6aca866 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './login-sso.page'; diff --git a/lib/testing/src/lib/process-services-cloud/public-api.ts b/lib/testing/src/lib/process-services-cloud/public-api.ts index 1f41c55c44..8f32cd8d0d 100644 --- a/lib/testing/src/lib/process-services-cloud/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './pages/public-api'; diff --git a/lib/testing/src/lib/process-services/pages/form-fields.page.ts b/lib/testing/src/lib/process-services/pages/form-fields.page.ts index a3f3c1e9d4..91392ed884 100644 --- a/lib/testing/src/lib/process-services/pages/form-fields.page.ts +++ b/lib/testing/src/lib/process-services/pages/form-fields.page.ts @@ -1,6 +1,6 @@ /*! * @license - * Copyright 2016 Alfresco Software, Ltd. + * 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. diff --git a/lib/testing/src/lib/process-services/pages/public-api.ts b/lib/testing/src/lib/process-services/pages/public-api.ts index 0c89dd2d2c..ebafd7e54e 100644 --- a/lib/testing/src/lib/process-services/pages/public-api.ts +++ b/lib/testing/src/lib/process-services/pages/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './form-fields.page'; diff --git a/lib/testing/src/lib/process-services/public-api.ts b/lib/testing/src/lib/process-services/public-api.ts index 261612cbe7..4143973c23 100644 --- a/lib/testing/src/lib/process-services/public-api.ts +++ b/lib/testing/src/lib/process-services/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './pages/public-api'; diff --git a/lib/testing/src/lib/testing.module.ts b/lib/testing/src/lib/testing.module.ts index 3129b50512..9b3ae7a669 100644 --- a/lib/testing/src/lib/testing.module.ts +++ b/lib/testing/src/lib/testing.module.ts @@ -1,3 +1,20 @@ +/*! + * @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 { NgModule } from '@angular/core'; @NgModule({ diff --git a/lib/testing/src/lib/testing.service.spec.ts b/lib/testing/src/lib/testing.service.spec.ts index e2a2990f79..025bff92e0 100644 --- a/lib/testing/src/lib/testing.service.spec.ts +++ b/lib/testing/src/lib/testing.service.spec.ts @@ -1,3 +1,20 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; import { TestingService } from './testing.service'; diff --git a/lib/testing/src/lib/testing.service.ts b/lib/testing/src/lib/testing.service.ts index 4fc1dd6233..4ad31c43ce 100644 --- a/lib/testing/src/lib/testing.service.ts +++ b/lib/testing/src/lib/testing.service.ts @@ -1,3 +1,20 @@ +/*! + * @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 { Injectable } from '@angular/core'; @Injectable({ diff --git a/lib/testing/src/public-api.ts b/lib/testing/src/public-api.ts index dceecee5ac..9b42b1066f 100644 --- a/lib/testing/src/public-api.ts +++ b/lib/testing/src/public-api.ts @@ -1,5 +1,18 @@ -/* - * Public API Surface of testing +/*! + * @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. */ export * from './lib/core/public-api'; @@ -8,3 +21,4 @@ export * from './lib/content-services/public-api'; export * from './lib/process-services/public-api'; export * from './lib/process-services-cloud/public-api'; export * from './lib/testing.module'; +export * from './lib/testing.service'; diff --git a/lib/testing/src/test.ts b/lib/testing/src/test.ts index e11ff1c97b..e81142305a 100644 --- a/lib/testing/src/test.ts +++ b/lib/testing/src/test.ts @@ -1,4 +1,19 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files +/*! + * @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 'core-js/es7/reflect'; import 'zone.js/dist/zone'; diff --git a/lib/tslint.json b/lib/tslint.json index ae261ecbde..3d9dfdbd0d 100644 --- a/lib/tslint.json +++ b/lib/tslint.json @@ -1,7 +1,7 @@ { "extends": "../tslint.json", "rules": { - "adf-license-banner": [true, "lib/+(core|content-services|process-services|process-services-cloud|insights|extensions)/**/*.ts", "./license-community.txt"] + "adf-license-banner": [true, "lib/+(core|content-services|process-services|process-services-cloud|insights|extensions|testing)/**/*.ts", "./license-community.txt"] }, "template-accessibility-alt-text": true, "template-accessibility-label-for": true, diff --git a/package-lock.json b/package-lock.json index 0ad5d80389..c5a944d35c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1016,6 +1016,37 @@ } } }, + "@fimbul/bifrost": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@fimbul/bifrost/-/bifrost-0.17.0.tgz", + "integrity": "sha512-gVTkJAOef5HtN6LPmrtt5fAUmBywwlgmObsU3FBhPoNeXPLaIl2zywXkJEtvvVLQnaFmtff3x+wIj5lHRCDE3Q==", + "dev": true, + "requires": { + "@fimbul/ymir": "^0.17.0", + "get-caller-file": "^2.0.0", + "tslib": "^1.8.1", + "tsutils": "^3.5.0" + }, + "dependencies": { + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + } + } + }, + "@fimbul/ymir": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@fimbul/ymir/-/ymir-0.17.0.tgz", + "integrity": "sha512-xMXM9KTXRLHLVS6dnX1JhHNEkmWHcAVCQ/4+DA1KKwC/AFnGHzu/7QfQttEPgw3xplT+ILf9e3i64jrFwB3JtA==", + "dev": true, + "requires": { + "inversify": "^5.0.0", + "reflect-metadata": "^0.1.12", + "tslib": "^1.8.1" + } + }, "@mat-datetimepicker/core": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-2.0.1.tgz", @@ -8740,6 +8771,12 @@ "loose-envify": "^1.0.0" } }, + "inversify": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.1.tgz", + "integrity": "sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==", + "dev": true + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -17635,6 +17672,28 @@ } } }, + "tslint-consistent-codestyle": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.15.1.tgz", + "integrity": "sha512-38Y3Dz4zcABe/PlPAQSGNEWPGVq0OzcIQR7SEU6dNujp/SgvhxhJOhIhI9gY4r0I3/TNtvVQwARWor9O9LPZWg==", + "dev": true, + "requires": { + "@fimbul/bifrost": "^0.17.0", + "tslib": "^1.7.1", + "tsutils": "^2.29.0" + }, + "dependencies": { + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, "tsscmp": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", diff --git a/package.json b/package.json index 5c28fa5dca..57f34b9ba0 100644 --- a/package.json +++ b/package.json @@ -169,6 +169,7 @@ "tsickle": "^0.34.0", "tslib": "^1.9.0", "tslint": "5.9.1", + "tslint-consistent-codestyle": "^1.15.1", "typedoc": "^0.14.2", "typescript": "3.1.6", "unist-util-select": "^2.0.0", diff --git a/tslint.json b/tslint.json index b1affcc921..cefc89ebcf 100644 --- a/tslint.json +++ b/tslint.json @@ -1,7 +1,8 @@ { "rulesDirectory": [ "./node_modules/codelyzer", - "./tools/tslint-rules/" + "./tools/tslint-rules/", + "tslint-consistent-codestyle" ], "extends": [ "rxjs-tslint-rules" From b95d1b9eb3fd88ed2ea92234b9c520ca7f02759a Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 10:42:40 +0000 Subject: [PATCH 012/208] fix timeout configuration --- lib/testing/src/lib/core/browser-visibility.ts | 9 ++++----- protractor.conf.js | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/browser-visibility.ts index bd38a6c5cb..7a1abcfd56 100644 --- a/lib/testing/src/lib/core/browser-visibility.ts +++ b/lib/testing/src/lib/core/browser-visibility.ts @@ -16,13 +16,12 @@ */ import { browser, protractor } from 'protractor'; + const until = protractor.ExpectedConditions; -const DEFAULT_TIMEOUT = 40000; +const DEFAULT_TIMEOUT = global['TestConfig'].main.timeout || 40000; export class BrowserVisibility { - constructor() {} - /* * Wait for element is visible */ @@ -35,7 +34,7 @@ export class BrowserVisibility { () => { isDisplayed = true; }, - (err) => { + () => { isDisplayed = false; } ); @@ -55,7 +54,7 @@ export class BrowserVisibility { () => { isDisplayed = true; }, - (err) => { + () => { isDisplayed = false; } ); diff --git a/protractor.conf.js b/protractor.conf.js index 378e8154f4..5f3b028222 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -207,6 +207,7 @@ exports.config = { onPrepare() { retry.onPrepare(); + global.TestConfig = TestConfig; require('ts-node').register({ project: 'e2e/tsconfig.e2e.json' }); From e85e6346857081f414613d1dbb2f6c072a13eacf Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 11:19:57 +0000 Subject: [PATCH 013/208] update monaco --- package-lock.json | 9 ++++++--- package.json | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index c5a944d35c..af7b38a6b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11834,9 +11834,12 @@ } }, "ngx-monaco-editor": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ngx-monaco-editor/-/ngx-monaco-editor-6.0.0.tgz", - "integrity": "sha512-sgNZblVUsIYHaWIKUqHopX3+rDL3DsjH9nsQoCuD7aA4p7Oppmd7UXwyT8OYTmimfcoufiA0tiIcH41XCZW58w==" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ngx-monaco-editor/-/ngx-monaco-editor-7.0.0.tgz", + "integrity": "sha512-vzPXTgeZEuRapuiANtrUjNCMdU5MmsJvQVyKgZS042VdXayAn6gPxvIVQp4ipUzX5JzVOfjkL2t+s9+ihMT5Eg==", + "requires": { + "tslib": "^1.9.0" + } }, "nice-try": { "version": "1.0.5", diff --git a/package.json b/package.json index 57f34b9ba0..99ad3408ac 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "moment": "2.22.2", "moment-es6": "^1.0.0", "ng2-charts": "1.6.0", - "ngx-monaco-editor": "^6.0.0", + "ngx-monaco-editor": "^7.0.0", "pdfjs-dist": "^2.0.489", "raphael": "2.2.7", "reflect-metadata": "0.1.13", From e75335a06df33678d8b3eb253f26dccf81e08e2b Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Wed, 27 Mar 2019 11:38:37 +0000 Subject: [PATCH 014/208] [ADF-3794] Update individual rows without reloading DocumentList (#4213) * reload table cells on node updates * update unit tests * update dynamic columns * fix value type * fix tests * update code as per review * update variable name * test fixes, core automation service * fix test --- demo-shell/src/app/app.module.ts | 11 +- .../app/components/files/files.component.ts | 4 - .../card-view/aspect-oriented-config.e2e.ts | 114 ++++++------- .../card-view/metadata-smoke-tests.e2e.ts | 18 ++- e2e/proxy.ts | 24 +++ .../library-name-column.component.ts | 153 +++++++++++------- .../library-role-column.component.spec.ts | 30 +++- .../library-role-column.component.ts | 108 +++++++++---- .../library-status-column.component.ts | 93 +++++++---- .../name-column/name-column.component.ts | 101 ++++++++---- .../data/share-data-row.model.ts | 5 + .../datatable-cell.component.spec.ts | 7 +- .../datatable/datatable-cell.component.ts | 61 +++++-- .../datatable/date-cell.component.ts | 25 ++- .../datatable/filesize-cell.component.ts | 13 +- .../datatable/location-cell.component.spec.ts | 32 ++-- .../datatable/location-cell.component.ts | 29 ++-- lib/core/services/automation.service.ts | 37 +++++ lib/core/services/public-api.ts | 1 + 19 files changed, 584 insertions(+), 282 deletions(-) create mode 100644 e2e/proxy.ts create mode 100644 lib/core/services/automation.service.ts diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 376d429c25..4cd74be7c5 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -23,7 +23,7 @@ import { ChartsModule } from 'ng2-charts'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { AppConfigService, TRANSLATION_PROVIDER, DebugAppConfigService, CoreModule } from '@alfresco/adf-core'; +import { AppConfigService, TRANSLATION_PROVIDER, DebugAppConfigService, CoreModule, CoreAutomationService } from '@alfresco/adf-core'; import { ExtensionsModule } from '@alfresco/adf-extensions'; import { AppComponent } from './app.component'; import { MaterialModule } from './material.module'; @@ -172,7 +172,8 @@ import { NestedMenuPositionDirective } from './components/app-layout/cloud/direc source: 'resources/lazy-loading' } }, - PreviewService + PreviewService, + CoreAutomationService ], entryComponents: [ VersionManagerDialogAdapterComponent, @@ -180,4 +181,8 @@ import { NestedMenuPositionDirective } from './components/app-layout/cloud/direc ], bootstrap: [AppComponent] }) -export class AppModule {} +export class AppModule { + constructor(automationService: CoreAutomationService) { + automationService.setup(); + } +} diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index b7ea355d10..ca3caef9b2 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -214,10 +214,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { @Optional() private route: ActivatedRoute, public authenticationService: AuthenticationService, public alfrescoApiService: AlfrescoApiService) { - - this.alfrescoApiService.nodeUpdated.subscribe(() => { - this.documentList.reload(); - }); } showFile(event) { diff --git a/e2e/core/card-view/aspect-oriented-config.e2e.ts b/e2e/core/card-view/aspect-oriented-config.e2e.ts index 83ab506542..d6f9889ae5 100644 --- a/e2e/core/card-view/aspect-oriented-config.e2e.ts +++ b/e2e/core/card-view/aspect-oriented-config.e2e.ts @@ -15,13 +15,10 @@ * limitations under the License. */ -import { browser } from 'protractor'; - import { LoginPage } from '../../pages/adf/loginPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { FileModel } from '../../models/ACS/fileModel'; @@ -33,6 +30,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { check } from '../../util/material'; +import { setConfigField } from '../../proxy'; describe('Aspect oriented config', () => { @@ -40,7 +38,6 @@ describe('Aspect oriented config', () => { const viewerPage = new ViewerPage(); const metadataViewPage = new MetadataViewPage(); const navigationBarPage = new NavigationBarPage(); - const configEditorPage = new ConfigEditorPage(); const contentServicesPage = new ContentServicesPage(); const modelOneName = 'modelOne', emptyAspectName = 'emptyAspect'; const defaultModel = 'cm', defaultEmptyPropertiesAspect = 'taggable', aspectName = 'Taggable'; @@ -53,7 +50,6 @@ describe('Aspect oriented config', () => { }); beforeAll(async (done) => { - const uploadActions = new UploadActions(); this.alfrescoJsApi = new AlfrescoApi({ @@ -92,35 +88,33 @@ describe('Aspect oriented config', () => { done(); }); - beforeEach(async (done) => { - navigationBarPage.clickConfigEditorButton(); - configEditorPage.clickClearButton(); - done(); - }); - afterEach(async (done) => { viewerPage.clickCloseButton(); contentServicesPage.checkAcsContainer(); - browser.refresh(); - contentServicesPage.checkAcsContainer(); done(); }); - it('[C261117] Should be possible restrict the display properties of one an aspect', () => { + it('[C261117] Should be possible restrict the display properties of one an aspect', async () => { - configEditorPage.enterBigConfigurationText('{ "presets": {' + - ' "default": [{' + - ' "title": "IMAGE",' + - ' "items": [' + - ' {' + - ' "aspect": "exif:exif", "properties": [ "exif:pixelXDimension", "exif:pixelYDimension", "exif:isoSpeedRatings"]' + - ' }' + - ' ]' + - ' }]' + - ' }' + - ' }'); - - configEditorPage.clickSaveButton(); + await setConfigField('content-metadata', JSON.stringify({ + presets: { + default: [ + { + title: 'IMAGE', + items: [ + { + aspect: 'exif:exif', + properties: [ + 'exif:pixelXDimension', + 'exif:pixelYDimension', + 'exif:isoSpeedRatings' + ] + } + ] + } + ] + } + })); navigationBarPage.clickContentServicesButton(); @@ -141,19 +135,17 @@ describe('Aspect oriented config', () => { metadataViewPage.checkPropertyIsVisible('properties.exif:isoSpeedRatings', 'textitem'); }); - it('[C260185] Should ignore not existing aspect when present in the configuration', () => { + it('[C260185] Should ignore not existing aspect when present in the configuration', async () => { - configEditorPage.enterBigConfigurationText(' {' + - ' "presets": {' + - ' "default": {' + - ' "exif:exif": "*",' + - ' "cm:versionable": "*",' + - ' "not:exists": "*"' + - ' }' + - ' }' + - ' }'); - - configEditorPage.clickSaveButton(); + await setConfigField('content-metadata', JSON.stringify({ + presets: { + default: { + 'exif:exif': '*', + 'cm:versionable': '*', + 'not:exists': '*' + } + } + })); navigationBarPage.clickContentServicesButton(); @@ -170,11 +162,9 @@ describe('Aspect oriented config', () => { metadataViewPage.checkMetadataGroupIsNotPresent('exists'); }); - it('[C260183] Should show all the aspect if the content-metadata configuration is NOT provided', () => { + it('[C260183] Should show all the aspect if the content-metadata configuration is NOT provided', async () => { - configEditorPage.enterBigConfigurationText('{ }'); - - configEditorPage.clickSaveButton(); + await setConfigField('content-metadata', '{}'); navigationBarPage.clickContentServicesButton(); @@ -190,15 +180,13 @@ describe('Aspect oriented config', () => { metadataViewPage.checkMetadataGroupIsPresent('Versionable'); }); - it('[C260182] Should show all the aspects if the default configuration contains the star symbol', () => { + it('[C260182] Should show all the aspects if the default configuration contains the star symbol', async () => { - configEditorPage.enterBigConfigurationText('{' + - ' "presets": {' + - ' "default": "*"' + - ' }' + - '}'); - - configEditorPage.clickSaveButton(); + await setConfigField('content-metadata', JSON.stringify({ + presets: { + default: '*' + } + })); navigationBarPage.clickContentServicesButton(); @@ -215,9 +203,9 @@ describe('Aspect oriented config', () => { metadataViewPage.checkMetadataGroupIsPresent('Versionable'); }); - it('[C268899] Should be possible use a Translation key as Title of a metadata group', () => { + it('[C268899] Should be possible use a Translation key as Title of a metadata group', async () => { - configEditorPage.enterBigConfigurationText('{' + + await setConfigField('content-metadata', '{' + ' "presets": {' + ' "default": [' + ' {' + @@ -242,8 +230,6 @@ describe('Aspect oriented config', () => { ' }' + '}'); - configEditorPage.clickSaveButton(); - navigationBarPage.clickContentServicesButton(); viewerPage.viewFile(pngFileModel.name); @@ -262,9 +248,9 @@ describe('Aspect oriented config', () => { }); - it('[C279968] Should be possible use a custom preset', () => { + it('[C279968] Should be possible use a custom preset', async () => { - configEditorPage.enterBigConfigurationText('{' + + await setConfigField('content-metadata', '{' + ' "presets": {' + ' "custom-preset": {' + ' "exif:exif": "*",' + @@ -273,8 +259,6 @@ describe('Aspect oriented config', () => { ' }' + '}'); - configEditorPage.clickSaveButton(); - navigationBarPage.clickContentServicesButton(); viewerPage.viewFile(pngFileModel.name); @@ -294,9 +278,9 @@ describe('Aspect oriented config', () => { metadataViewPage.checkMetadataGroupIsPresent('Versionable'); }); - it('[C299186] The aspect without properties is not displayed', () => { + it('[C299186] The aspect without properties is not displayed', async () => { - configEditorPage.enterBigConfigurationText('{' + + await setConfigField('content-metadata', '{' + ' "presets": { "' + modelOneName + ' ": { "' + modelOneName + ':' + emptyAspectName + ' ":"*"' + @@ -304,8 +288,6 @@ describe('Aspect oriented config', () => { ' }' + '}'); - configEditorPage.clickSaveButton(); - navigationBarPage.clickContentServicesButton(); viewerPage.viewFile(pngFileModel.name); @@ -319,9 +301,9 @@ describe('Aspect oriented config', () => { metadataViewPage.checkMetadataGroupIsNotPresent(emptyAspectName); }); - it('[C299187] The aspect with empty properties is displayed when edit', () => { + it('[C299187] The aspect with empty properties is displayed when edit', async () => { - configEditorPage.enterBigConfigurationText('{' + + await setConfigField('content-metadata', '{' + ' "presets": { "' + defaultModel + ' ": { "' + defaultModel + ':' + defaultEmptyPropertiesAspect + ' ":"*"' + @@ -329,8 +311,6 @@ describe('Aspect oriented config', () => { ' }' + '}'); - configEditorPage.clickSaveButton(); - navigationBarPage.clickContentServicesButton(); viewerPage.viewFile(pngFileModel.name); diff --git a/e2e/core/card-view/metadata-smoke-tests.e2e.ts b/e2e/core/card-view/metadata-smoke-tests.e2e.ts index 5a1fee3d40..7af069627d 100644 --- a/e2e/core/card-view/metadata-smoke-tests.e2e.ts +++ b/e2e/core/card-view/metadata-smoke-tests.e2e.ts @@ -32,6 +32,7 @@ import dateFormat = require('dateformat'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { setConfigField } from '../../proxy'; describe('Metadata component', () => { @@ -95,6 +96,16 @@ describe('Metadata component', () => { describe('Viewer Metadata', () => { + beforeAll(async() => { + await setConfigField('content-metadata', JSON.stringify({ + presets: { + default: { + 'exif:exif': '*' + } + } + })); + }); + beforeEach(async (done) => { viewerPage.viewFile(pngFileModel.name); viewerPage.checkFileIsLoaded(); @@ -194,9 +205,10 @@ describe('Metadata component', () => { await metadataViewPage.clickUpdatePropertyIcon('properties.cm:description'); expect(metadataViewPage.getPropertyText('properties.cm:description')).toEqual('example description'); - viewerPage.clickCloseButton(); + await viewerPage.clickCloseButton(); + contentServicesPage.waitForTableBody(); - viewerPage.viewFile('exampleText.png'); + viewerPage.viewFile(resources.Files.ADF_DOCUMENTS.PNG.file_name); viewerPage.clickInfoButton(); viewerPage.checkInfoSideBarIsDisplayed(); metadataViewPage.clickOnPropertiesTab(); @@ -260,6 +272,7 @@ describe('Metadata component', () => { browser.controlFlow().execute(async () => { await metadataViewPage.editIconClick(); + metadataViewPage.clickEditPropertyIcons('properties.exif:software'); metadataViewPage.enterPropertyText('properties.exif:software', 'test custom text software'); await metadataViewPage.clickUpdatePropertyIcon('properties.exif:software'); @@ -303,6 +316,7 @@ describe('Metadata component', () => { browser.controlFlow().execute(async () => { await metadataViewPage.editIconClick(); + metadataViewPage.clickEditPropertyIcons('name'); metadataViewPage.enterPropertyText('name', 'newnameFolder'); await metadataViewPage.clickClearPropertyIcon('name'); diff --git a/e2e/proxy.ts b/e2e/proxy.ts new file mode 100644 index 0000000000..ec533eda52 --- /dev/null +++ b/e2e/proxy.ts @@ -0,0 +1,24 @@ +/*! + * @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 { browser } from 'protractor'; + +export async function setConfigField(field: string, value: string) { + return browser.executeScript( + `window.adf.setConfigField('${field}', '${value}');` + ); +} diff --git a/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts b/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts index 481875c0e7..a5b3f65595 100644 --- a/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts +++ b/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts @@ -16,75 +16,112 @@ */ import { - Component, - ChangeDetectionStrategy, - ViewEncapsulation, - OnInit, - Input, - ElementRef + Component, + ChangeDetectionStrategy, + ViewEncapsulation, + OnInit, + Input, + ElementRef, + OnDestroy } from '@angular/core'; -import { NodeEntry } from '@alfresco/js-api'; +import { NodeEntry, Node, Site } from '@alfresco/js-api'; import { ShareDataRow } from '../../data/share-data-row.model'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { BehaviorSubject, Subscription } from 'rxjs'; @Component({ - selector: 'adf-library-name-column', - template: ` - <span title="{{ displayTooltip }}" (click)="onClick()"> - {{ displayText }} - </span> - `, - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell adf-datatable-link adf-library-name-column' } + selector: 'adf-library-name-column', + template: ` + <span title="{{ displayTooltip$ | async }}" (click)="onClick()"> + {{ displayText$ | async }} + </span> + `, + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + host: { + class: 'adf-datatable-cell adf-datatable-link adf-library-name-column' + } }) -export class LibraryNameColumnComponent implements OnInit { - @Input() - context: any; +export class LibraryNameColumnComponent implements OnInit, OnDestroy { + @Input() + context: any; - displayTooltip: string; - displayText: string; - node: NodeEntry; + displayTooltip$ = new BehaviorSubject<string>(''); + displayText$ = new BehaviorSubject<string>(''); + node: NodeEntry; - constructor(private element: ElementRef) {} + private sub: Subscription; - ngOnInit() { - this.node = this.context.row.node; - const rows: Array<ShareDataRow> = this.context.data.rows || []; - if (this.node && this.node.entry) { - this.displayText = this.makeLibraryTitle(this.node.entry, rows); - this.displayTooltip = this.makeLibraryTooltip(this.node.entry); + constructor( + private element: ElementRef, + private alfrescoApiService: AlfrescoApiService + ) {} + + ngOnInit() { + this.updateValue(); + + this.sub = this.alfrescoApiService.nodeUpdated.subscribe( + (node: Node) => { + const row: ShareDataRow = this.context.row; + if (row) { + const { entry } = row.node; + + if (entry === node) { + row.node = { entry }; + this.updateValue(); + } + } + } + ); } - } - onClick() { - this.element.nativeElement.dispatchEvent( - new CustomEvent('name-click', { - bubbles: true, - detail: { - node: this.node + protected updateValue() { + this.node = this.context.row.node; + const rows: Array<ShareDataRow> = this.context.data.rows || []; + if (this.node && this.node.entry) { + this.displayText$.next( + this.makeLibraryTitle(<any> this.node.entry, rows) + ); + this.displayTooltip$.next(this.makeLibraryTooltip(this.node.entry)); } - }) - ); - } - - makeLibraryTooltip(library: any): string { - const { description, title } = library; - - return description || title || ''; - } - - makeLibraryTitle(library: any, rows: Array<ShareDataRow>): string { - const entries = rows.map((r: ShareDataRow) => r.node.entry); - const { title, id } = library; - - let isDuplicate = false; - - if (entries) { - isDuplicate = entries.some((entry: any) => { - return entry.id !== id && entry.title === title; - }); } - return isDuplicate ? `${title} (${id})` : `${title}`; - } + onClick() { + this.element.nativeElement.dispatchEvent( + new CustomEvent('name-click', { + bubbles: true, + detail: { + node: this.node + } + }) + ); + } + + makeLibraryTooltip(library: any): string { + const { description, title } = library; + + return description || title || ''; + } + + makeLibraryTitle(library: Site, rows: Array<ShareDataRow>): string { + const entries = rows.map((row: ShareDataRow) => row.node.entry); + const { title, id } = library; + + let isDuplicate = false; + + if (entries) { + isDuplicate = entries.some((entry: any) => { + return entry.id !== id && entry.title === title; + }); + } + + return isDuplicate ? `${title} (${id})` : `${title}`; + } + + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + this.sub = null; + } + } } diff --git a/lib/content-services/document-list/components/library-role-column/library-role-column.component.spec.ts b/lib/content-services/document-list/components/library-role-column/library-role-column.component.spec.ts index 6184d32a93..10caf2bde4 100644 --- a/lib/content-services/document-list/components/library-role-column/library-role-column.component.spec.ts +++ b/lib/content-services/document-list/components/library-role-column/library-role-column.component.spec.ts @@ -39,39 +39,59 @@ describe('LibraryNameColumnComponent', () => { component.context = { row: { node: { entry: { role: 'SiteManager' } } } }; + + let value = ''; + component.displayText$.subscribe((val) => value = val); + fixture.detectChanges(); - expect(component.displayText).toBe('LIBRARY.ROLE.MANAGER'); + expect(value).toBe('LIBRARY.ROLE.MANAGER'); }); it('should render Collaborator', () => { component.context = { row: { node: { entry: { role: 'SiteCollaborator' } } } }; + + let value = ''; + component.displayText$.subscribe((val) => value = val); + fixture.detectChanges(); - expect(component.displayText).toBe('LIBRARY.ROLE.COLLABORATOR'); + expect(value).toBe('LIBRARY.ROLE.COLLABORATOR'); }); it('should render Contributor', () => { component.context = { row: { node: { entry: { role: 'SiteContributor' } } } }; + + let value = ''; + component.displayText$.subscribe((val) => value = val); + fixture.detectChanges(); - expect(component.displayText).toBe('LIBRARY.ROLE.CONTRIBUTOR'); + expect(value).toBe('LIBRARY.ROLE.CONTRIBUTOR'); }); it('should render Consumer', () => { component.context = { row: { node: { entry: { role: 'SiteConsumer' } } } }; + + let value = ''; + component.displayText$.subscribe((val) => value = val); + fixture.detectChanges(); - expect(component.displayText).toBe('LIBRARY.ROLE.CONSUMER'); + expect(value).toBe('LIBRARY.ROLE.CONSUMER'); }); it('should not render text for unknown', () => { component.context = { row: { node: { entry: { role: 'ROLE' } } } }; + + let value = ''; + component.displayText$.subscribe((val) => value = val); + fixture.detectChanges(); - expect(component.displayText).toBe(''); + expect(value).toBe(''); }); }); diff --git a/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts b/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts index 4381466762..39817101ce 100644 --- a/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts +++ b/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts @@ -15,44 +15,84 @@ * limitations under the License. */ -import { Component, OnInit, Input } from '@angular/core'; +import { + Component, + OnInit, + Input, + ChangeDetectionStrategy, + ViewEncapsulation, + OnDestroy +} from '@angular/core'; +import { Subscription, BehaviorSubject } from 'rxjs'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { Node, SiteEntry, Site } from '@alfresco/js-api'; +import { ShareDataRow } from '../../data/share-data-row.model'; @Component({ - selector: 'adf-library-role-column', - template: ` - <span title="{{ displayText | translate }}"> - {{ displayText | translate }} - </span> - `, - host: { class: 'adf-library-role-column' } + selector: 'adf-library-role-column', + template: ` + <span title="{{ (displayText$ | async) | translate }}"> + {{ (displayText$ | async) | translate }} + </span> + `, + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + host: { class: 'adf-library-role-column' } }) -export class LibraryRoleColumnComponent implements OnInit { - @Input() - context: any; +export class LibraryRoleColumnComponent implements OnInit, OnDestroy { + @Input() + context: any; - displayText: string; + displayText$ = new BehaviorSubject<string>(''); - ngOnInit() { - const node = this.context.row.node; - if (node && node.entry) { - const role: string = node.entry.role; - switch (role) { - case 'SiteManager': - this.displayText = 'LIBRARY.ROLE.MANAGER'; - break; - case 'SiteCollaborator': - this.displayText = 'LIBRARY.ROLE.COLLABORATOR'; - break; - case 'SiteContributor': - this.displayText = 'LIBRARY.ROLE.CONTRIBUTOR'; - break; - case 'SiteConsumer': - this.displayText = 'LIBRARY.ROLE.CONSUMER'; - break; - default: - this.displayText = ''; - break; - } + private sub: Subscription; + + constructor(private api: AlfrescoApiService) {} + + ngOnInit() { + this.updateValue(); + + this.sub = this.api.nodeUpdated.subscribe((node: Node) => { + const row: ShareDataRow = this.context.row; + if (row) { + const { entry } = row.node; + + if (entry === node) { + row.node = { entry }; + this.updateValue(); + } + } + }); + } + + protected updateValue() { + const node: SiteEntry = this.context.row.node; + if (node && node.entry) { + const role: string = node.entry.role; + switch (role) { + case Site.RoleEnum.SiteManager: + this.displayText$.next('LIBRARY.ROLE.MANAGER'); + break; + case Site.RoleEnum.SiteCollaborator: + this.displayText$.next('LIBRARY.ROLE.COLLABORATOR'); + break; + case Site.RoleEnum.SiteContributor: + this.displayText$.next('LIBRARY.ROLE.CONTRIBUTOR'); + break; + case Site.RoleEnum.SiteConsumer: + this.displayText$.next('LIBRARY.ROLE.CONSUMER'); + break; + default: + this.displayText$.next(''); + break; + } + } + } + + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + this.sub = null; + } } - } } diff --git a/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts b/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts index 77744e55ad..579d5aa62a 100644 --- a/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts +++ b/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts @@ -15,42 +15,73 @@ * limitations under the License. */ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, OnDestroy } from '@angular/core'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { Subscription, BehaviorSubject } from 'rxjs'; +import { Node, Site, SiteEntry } from '@alfresco/js-api'; +import { ShareDataRow } from '../../data/share-data-row.model'; @Component({ - selector: 'adf-library-status-column', - template: ` - <span title="{{ displayText | translate }}"> - {{ displayText | translate }} - </span> - `, - host: { class: 'adf-library-status-column' } + selector: 'adf-library-status-column', + template: ` + <span title="{{ (displayText$ | async) | translate }}"> + {{ (displayText$ | async) | translate }} + </span> + `, + host: { class: 'adf-library-status-column' } }) -export class LibraryStatusColumnComponent implements OnInit { - @Input() - context: any; +export class LibraryStatusColumnComponent implements OnInit, OnDestroy { + @Input() + context: any; - displayText: string; + displayText$ = new BehaviorSubject<string>(''); - ngOnInit() { - const node = this.context.row.node; - if (node && node.entry) { - const visibility: string = node.entry.visibility; + private sub: Subscription; - switch (visibility.toUpperCase()) { - case 'PUBLIC': - this.displayText = 'LIBRARY.VISIBILITY.PUBLIC'; - break; - case 'PRIVATE': - this.displayText = 'LIBRARY.VISIBILITY.PRIVATE'; - break; - case 'MODERATED': - this.displayText = 'LIBRARY.VISIBILITY.MODERATED'; - break; - default: - this.displayText = 'UNKNOWN'; - break; - } + constructor(private api: AlfrescoApiService) {} + + ngOnInit() { + this.updateValue(); + + this.sub = this.api.nodeUpdated.subscribe((node: Node) => { + const row: ShareDataRow = this.context.row; + if (row) { + const { entry } = row.node; + + if (entry === node) { + row.node = { entry }; + this.updateValue(); + } + } + }); + } + + protected updateValue() { + const node: SiteEntry = this.context.row.node; + if (node && node.entry) { + const visibility: string = node.entry.visibility; + + switch (visibility) { + case Site.VisibilityEnum.PUBLIC: + this.displayText$.next('LIBRARY.VISIBILITY.PUBLIC'); + break; + case Site.VisibilityEnum.PRIVATE: + this.displayText$.next('LIBRARY.VISIBILITY.PRIVATE'); + break; + case Site.VisibilityEnum.MODERATED: + this.displayText$.next('LIBRARY.VISIBILITY.MODERATED'); + break; + default: + this.displayText$.next('UNKNOWN'); + break; + } + } + } + + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + this.sub = null; + } } - } } diff --git a/lib/content-services/document-list/components/name-column/name-column.component.ts b/lib/content-services/document-list/components/name-column/name-column.component.ts index f2ae11f229..824e3cb0b6 100644 --- a/lib/content-services/document-list/components/name-column/name-column.component.ts +++ b/lib/content-services/document-list/components/name-column/name-column.component.ts @@ -16,50 +16,81 @@ */ import { - Component, - Input, - OnInit, - ChangeDetectionStrategy, - ViewEncapsulation, - ElementRef + Component, + Input, + OnInit, + ChangeDetectionStrategy, + ViewEncapsulation, + ElementRef, + OnDestroy } from '@angular/core'; import { NodeEntry } from '@alfresco/js-api'; +import { BehaviorSubject, Subscription } from 'rxjs'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { Node } from '@alfresco/js-api'; +import { ShareDataRow } from '../../data/share-data-row.model'; @Component({ - selector: 'adf-name-column', - template: ` - <span title="{{ node | adfNodeNameTooltip }}" (click)="onClick()"> - {{ displayText }} - </span> - `, - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell adf-datatable-link adf-name-column' } + selector: 'adf-name-column', + template: ` + <span title="{{ node | adfNodeNameTooltip }}" (click)="onClick()"> + {{ displayText$ | async }} + </span> + `, + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + host: { class: 'adf-datatable-cell adf-datatable-link adf-name-column' } }) -export class NameColumnComponent implements OnInit { - @Input() - context: any; +export class NameColumnComponent implements OnInit, OnDestroy { + @Input() + context: any; - displayText: string; - node: NodeEntry; + displayText$ = new BehaviorSubject<string>(''); + node: NodeEntry; - constructor(private element: ElementRef) {} + private sub: Subscription; - ngOnInit() { - this.node = this.context.row.node; - if (this.node && this.node.entry) { - this.displayText = this.node.entry.name || this.node.entry.id; + constructor(private element: ElementRef, private alfrescoApiService: AlfrescoApiService) {} + + ngOnInit() { + this.updateValue(); + + this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => { + const row: ShareDataRow = this.context.row; + if (row) { + const { entry } = row.node; + + if (entry === node) { + row.node = { entry }; + this.updateValue(); + } + } + }); } - } - onClick() { - this.element.nativeElement.dispatchEvent( - new CustomEvent('name-click', { - bubbles: true, - detail: { - node: this.node + protected updateValue() { + this.node = this.context.row.node; + + if (this.node && this.node.entry) { + this.displayText$.next(this.node.entry.name || this.node.entry.id); } - }) - ); - } + } + + onClick() { + this.element.nativeElement.dispatchEvent( + new CustomEvent('name-click', { + bubbles: true, + detail: { + node: this.node + } + }) + ); + } + + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + this.sub = null; + } + } } diff --git a/lib/content-services/document-list/data/share-data-row.model.ts b/lib/content-services/document-list/data/share-data-row.model.ts index b02a99ef71..7a964302d1 100644 --- a/lib/content-services/document-list/data/share-data-row.model.ts +++ b/lib/content-services/document-list/data/share-data-row.model.ts @@ -32,6 +32,11 @@ export class ShareDataRow implements DataRow { return this.obj; } + set node(value: NodeEntry) { + this.obj = value; + this.cache = {}; + } + constructor(private obj: NodeEntry, private contentService: ContentService, private permissionsStyle: PermissionStyleModel[], diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts b/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts index 3e685769c0..603f76c2ae 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts @@ -16,15 +16,18 @@ */ import { DateCellComponent } from './date-cell.component'; +import { Subject } from 'rxjs'; describe('DataTableCellComponent', () => { it('should use medium format by default', () => { - const component = new DateCellComponent(null); + const component = new DateCellComponent(null, null); expect(component.format).toBe('medium'); }); it('should use column format', () => { - const component = new DateCellComponent(null); + const component = new DateCellComponent(null, <any> { + nodeUpdated: new Subject<any>() + }); component.column = { key: 'created', type: 'date', diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index bc62199a0b..3308688ad6 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -15,23 +15,38 @@ * limitations under the License. */ -import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnInit, + ViewEncapsulation, + OnDestroy +} from '@angular/core'; import { DataColumn } from '../../data/data-column.model'; import { DataRow } from '../../data/data-row.model'; import { DataTableAdapter } from '../../data/datatable-adapter'; +import { AlfrescoApiService } from '../../../services/alfresco-api.service'; +import { Subscription, BehaviorSubject } from 'rxjs'; +import { Node } from '@alfresco/js-api'; @Component({ selector: 'adf-datatable-cell', changeDetection: ChangeDetectionStrategy.OnPush, template: ` <ng-container> - <span [attr.aria-label]="value" [title]="tooltip" class="adf-datatable-cell-value">{{value}}</span> - </ng-container>`, + <span + [attr.aria-label]="value$ | async" + [title]="tooltip" + class="adf-datatable-cell-value" + >{{ value$ | async }}</span + > + </ng-container> + `, encapsulation: ViewEncapsulation.None, host: { class: 'adf-datatable-cell' } }) -export class DataTableCellComponent implements OnInit { - +export class DataTableCellComponent implements OnInit, OnDestroy { @Input() data: DataTableAdapter; @@ -41,20 +56,46 @@ export class DataTableCellComponent implements OnInit { @Input() row: DataRow; - @Input() - value: any; + value$ = new BehaviorSubject<any>(''); @Input() tooltip: string; + private sub: Subscription; + + constructor(protected alfrescoApiService: AlfrescoApiService) {} + ngOnInit() { - if (!this.value && this.column && this.column.key && this.row && this.data) { - this.value = this.data.getValue(this.row, this.column); + this.updateValue(); + + this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => { + if (this.row) { + const { entry } = this.row['node']; + + if (entry === node) { + this.row['node'] = { entry }; + this.updateValue(); + } + } + }); + } + + protected updateValue() { + if (this.column && this.column.key && this.row && this.data) { + const value = this.data.getValue(this.row, this.column); + + this.value$.next(value); if (!this.tooltip) { - this.tooltip = this.value; + this.tooltip = value; } } } + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + this.sub = null; + } + } } diff --git a/lib/core/datatable/components/datatable/date-cell.component.ts b/lib/core/datatable/components/datatable/date-cell.component.ts index 89e32d6262..dc7f68fb53 100644 --- a/lib/core/datatable/components/datatable/date-cell.component.ts +++ b/lib/core/datatable/components/datatable/date-cell.component.ts @@ -21,19 +21,27 @@ import { UserPreferencesService, UserPreferenceValues } from '../../../services/user-preferences.service'; +import { AlfrescoApiService } from '../../../services/alfresco-api.service'; @Component({ selector: 'adf-date-cell', template: ` <ng-container> - <span title="{{ tooltip | date:'medium' }}" *ngIf="format === 'timeAgo' else standard_date" [attr.aria-label]=" value | adfTimeAgo: currentLocale "> - {{ value | adfTimeAgo: currentLocale }} + <span + [attr.aria-label]="value$ | async | adfTimeAgo: currentLocale" + title="{{ tooltip | date: 'medium' }}" + *ngIf="format === 'timeAgo'; else standard_date" + > + {{ value$ | async | adfTimeAgo: currentLocale }} </span> </ng-container> <ng-template #standard_date> - <span [attr.aria-label]=" value | date:format " title="{{ tooltip | date:format }}"> - {{ value | date:format }} + <span + title="{{ tooltip | date: format }}" + [attr.aria-label]="value$ | async | date: format" + > + {{ value$ | async | date: format }} </span> </ng-template> `, @@ -41,7 +49,7 @@ import { host: { class: 'adf-date-cell' } }) export class DateCellComponent extends DataTableCellComponent { - currentLocale; + currentLocale: string; get format(): string { if (this.column) { @@ -50,8 +58,11 @@ export class DateCellComponent extends DataTableCellComponent { return 'medium'; } - constructor(userPreferenceService: UserPreferencesService) { - super(); + constructor( + userPreferenceService: UserPreferencesService, + alfrescoApiService: AlfrescoApiService + ) { + super(alfrescoApiService); if (userPreferenceService) { userPreferenceService diff --git a/lib/core/datatable/components/datatable/filesize-cell.component.ts b/lib/core/datatable/components/datatable/filesize-cell.component.ts index 803463b69e..f263b750ea 100644 --- a/lib/core/datatable/components/datatable/filesize-cell.component.ts +++ b/lib/core/datatable/components/datatable/filesize-cell.component.ts @@ -17,15 +17,24 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { DataTableCellComponent } from './datatable-cell.component'; +import { AlfrescoApiService } from '../../../services/alfresco-api.service'; @Component({ selector: 'adf-filesize-cell', template: ` <ng-container> - <span [attr.aria-label]=" value | adfFileSize " [title]="tooltip">{{ value | adfFileSize }}</span> + <span + [title]="tooltip" + [attr.aria-label]="value$ | async | adfFileSize" + >{{ value$ | async | adfFileSize }}</span + > </ng-container> `, encapsulation: ViewEncapsulation.None, host: { class: 'adf-filesize-cell' } }) -export class FileSizeCellComponent extends DataTableCellComponent {} +export class FileSizeCellComponent extends DataTableCellComponent { + constructor(alfrescoApiService: AlfrescoApiService) { + super(alfrescoApiService); + } +} diff --git a/lib/core/datatable/components/datatable/location-cell.component.spec.ts b/lib/core/datatable/components/datatable/location-cell.component.spec.ts index a866606096..1bf3e69f3c 100644 --- a/lib/core/datatable/components/datatable/location-cell.component.spec.ts +++ b/lib/core/datatable/components/datatable/location-cell.component.spec.ts @@ -69,12 +69,6 @@ describe('LocationCellComponent', () => { fixture.destroy(); }); - it('should set displayText', () => { - fixture.detectChanges(); - - expect(component.displayText).toBe('location'); - }); - it('should set tooltip', () => { fixture.detectChanges(); @@ -87,24 +81,32 @@ describe('LocationCellComponent', () => { expect(component.link).toEqual([ columnData.format , rowData.path.elements[2].id ]); }); - it('should not setup cell when path has no data', () => { + it('should not setup cell when path has no data', (done) => { rowData.path = {}; fixture.detectChanges(); - expect(component.displayText).toBe(''); expect(component.tooltip).toBeUndefined(); expect(component.link).toEqual([]); + component.value$.subscribe((value) => { + expect(value).toBe(''); + done(); + }); + }); - it('should not setup cell when path is missing required properties', () => { + it('should not setup cell when path is missing required properties', (done) => { rowData.path = { someProp: '' }; fixture.detectChanges(); - expect(component.displayText).toBe(''); expect(component.tooltip).toBeUndefined(); expect(component.link).toEqual([]); + + component.value$.subscribe((value) => { + expect(value).toBe(''); + done(); + }); }); it('should not setup cell when path data is missing one of the property', () => { @@ -112,9 +114,15 @@ describe('LocationCellComponent', () => { name: 'some-name' }; + let value = ''; + + component.value$.subscribe((val) => { + value = val; + }); + fixture.detectChanges(); - expect(component.displayText).toBe(''); + expect(value).toBe(''); expect(component.tooltip).toBeUndefined(); expect(component.link).toEqual([]); @@ -124,7 +132,7 @@ describe('LocationCellComponent', () => { fixture.detectChanges(); - expect(component.displayText).toBe(''); + expect(value).toBe(''); expect(component.tooltip).toBeUndefined(); expect(component.link).toEqual([]); }); diff --git a/lib/core/datatable/components/datatable/location-cell.component.ts b/lib/core/datatable/components/datatable/location-cell.component.ts index 12c6603a42..1a62782a1e 100644 --- a/lib/core/datatable/components/datatable/location-cell.component.ts +++ b/lib/core/datatable/components/datatable/location-cell.component.ts @@ -15,9 +15,16 @@ * limitations under the License. */ -import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnInit, + ViewEncapsulation +} from '@angular/core'; import { PathInfoEntity } from '@alfresco/js-api'; import { DataTableCellComponent } from './datatable-cell.component'; +import { AlfrescoApiService } from '../../../services/alfresco-api.service'; @Component({ selector: 'adf-location-cell', @@ -25,7 +32,7 @@ import { DataTableCellComponent } from './datatable-cell.component'; template: ` <ng-container> <a href="" [title]="tooltip" [routerLink]="link"> - {{ displayText }} + {{ value$ | async }} </a> </ng-container> `, @@ -33,28 +40,30 @@ import { DataTableCellComponent } from './datatable-cell.component'; host: { class: 'adf-location-cell' } }) export class LocationCellComponent extends DataTableCellComponent implements OnInit { - @Input() link: any[]; - @Input() - displayText: string = ''; + constructor(alfrescoApiService: AlfrescoApiService) { + super(alfrescoApiService); + } /** @override */ ngOnInit() { - if (!this.value && this.column && this.column.key && this.row && this.data) { - const path: PathInfoEntity = this.data.getValue(this.row, this.column); + if (this.column && this.column.key && this.row && this.data) { + const path: PathInfoEntity = this.data.getValue( + this.row, + this.column + ); if (path && path.name && path.elements) { - this.value = path; - this.displayText = path.name.split('/').pop(); + this.value$.next(path.name.split('/').pop()); if (!this.tooltip) { this.tooltip = path.name; } const parent = path.elements[path.elements.length - 1]; - this.link = [ this.column.format, parent.id ]; + this.link = [this.column.format, parent.id]; } } } diff --git a/lib/core/services/automation.service.ts b/lib/core/services/automation.service.ts new file mode 100644 index 0000000000..da6478daf8 --- /dev/null +++ b/lib/core/services/automation.service.ts @@ -0,0 +1,37 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { AppConfigService } from '../app-config/app-config.service'; + +@Injectable({ + providedIn: 'root' +}) +export class CoreAutomationService { + constructor(private appConfigService: AppConfigService) { + } + + setup() { + const adfProxy = window['adf'] || {}; + + adfProxy.setConfigField = (field: string, value: string) => { + this.appConfigService.config[field] = JSON.parse(value); + }; + + window['adf'] = adfProxy; + } +} diff --git a/lib/core/services/public-api.ts b/lib/core/services/public-api.ts index a9b659c75e..19f310b7e5 100644 --- a/lib/core/services/public-api.ts +++ b/lib/core/services/public-api.ts @@ -53,3 +53,4 @@ export * from './login-dialog.service'; export * from './external-alfresco-api.service'; export * from './jwt-helper.service'; export * from './download-zip.service'; +export * from './automation.service'; From 070bf020a7ad12760e382c30065fa932d266c2ac Mon Sep 17 00:00:00 2001 From: Vito <vito.albano@alfresco.com> Date: Wed, 27 Mar 2019 11:42:09 +0000 Subject: [PATCH 015/208] [ADF-3228] Added lock check for context actions (#4163) * [ADF-3228] Added lock check in content service * [ADF-3228] added unit test for lock check * [ADF-3228] fixed wrong line on rebase * [ADF-3228] fixed e2e related to new lock behaviour * [ADF-3228] externalised lock service and added more unit tests * [ADF-3228] added lock service to disable context actions * [ADF-3228] fixed e2e rebased to the latest --- .../version/version-permissions.e2e.ts | 65 ++----- .../document-list.component.spec.ts | 93 ++++++++++ .../components/document-list.component.ts | 15 +- lib/core/services/lock.service.spec.ts | 166 ++++++++++++++++++ lib/core/services/lock.service.ts | 72 ++++++++ lib/core/services/public-api.ts | 1 + 6 files changed, 356 insertions(+), 56 deletions(-) create mode 100644 lib/core/services/lock.service.spec.ts create mode 100644 lib/core/services/lock.service.ts diff --git a/e2e/content-services/version/version-permissions.e2e.ts b/e2e/content-services/version/version-permissions.e2e.ts index f132b3edf7..0fa20ddedf 100644 --- a/e2e/content-services/version/version-permissions.e2e.ts +++ b/e2e/content-services/version/version-permissions.e2e.ts @@ -178,39 +178,10 @@ describe('Version component permissions', () => { uploadDialog.clickOnCloseButton(); }); - it('[C277204] Should a user with Manager permission not be able to upload a new version for a locked file', () => { - contentServices.versionManagerContent(lockFileModel.name); - - versionManagePage.showNewVersionButton.click(); - - versionManagePage.uploadNewVersionFile(newVersionFile.location); - - versionManagePage.checkFileVersionNotExist('1.1'); - - versionManagePage.closeVersionDialog(); - - uploadDialog.clickOnCloseButton(); - }); - - it('[C277196] Should a user with Manager permission be able to upload a new version for the created file', () => { - contentServices.versionManagerContent(sameCreatorFile.name); - - versionManagePage.showNewVersionButton.click(); - - versionManagePage.uploadNewVersionFile(newVersionFile.location); - - versionManagePage.checkFileVersionExist('1.1'); - expect(versionManagePage.getFileVersionName('1.1')).toEqual(newVersionFile.name); - expect(versionManagePage.getFileVersionDate('1.1')).not.toBeUndefined(); - - versionManagePage.deleteFileVersion('1.1'); - versionManagePage.clickAcceptConfirm(); - - versionManagePage.checkFileVersionNotExist('1.1'); - - versionManagePage.closeVersionDialog(); - - uploadDialog.clickOnCloseButton(); + it('[C277204] Should be disabled the option for locked file', () => { + contentServices.getDocumentList().rightClickOnRow(lockFileModel.name); + const actionVersion = contentServices.checkContextActionIsVisible('Manage versions'); + expect(actionVersion.isEnabled()).toBeFalsy(); }); }); @@ -231,9 +202,9 @@ describe('Version component permissions', () => { }); it('[C277201] Should a user with Consumer permission not be able to upload a new version for a locked file', () => { - contentServices.versionManagerContent(lockFileModel.name); - - notificationPage.checkNotifyContains(`You don't have access to do this`); + contentServices.getDocumentList().rightClickOnRow(lockFileModel.name); + const actionVersion = contentServices.checkContextActionIsVisible('Manage versions'); + expect(actionVersion.isEnabled()).toBeFalsy(); }); }); @@ -291,10 +262,10 @@ describe('Version component permissions', () => { notificationPage.checkNotifyContains(`You don't have access to do this`); }); - it('[C277202] Should a user with Contributor permission not be able to upload a new version for a locked file', () => { - contentServices.versionManagerContent(lockFileModel.name); - - notificationPage.checkNotifyContains(`You don't have access to do this`); + it('[C277202] Should be disabled the option for a locked file', () => { + contentServices.getDocumentList().rightClickOnRow(lockFileModel.name); + const actionVersion = contentServices.checkContextActionIsVisible('Manage versions'); + expect(actionVersion.isEnabled()).toBeFalsy(); }); }); @@ -346,17 +317,9 @@ describe('Version component permissions', () => { }); it('[C277203] Should a user with Collaborator permission not be able to upload a new version for a locked file', () => { - contentServices.versionManagerContent(lockFileModel.name); - - versionManagePage.showNewVersionButton.click(); - - versionManagePage.uploadNewVersionFile(newVersionFile.location); - - versionManagePage.checkFileVersionNotExist('1.1'); - - versionManagePage.closeVersionDialog(); - - uploadDialog.clickOnCloseButton(); + contentServices.getDocumentList().rightClickOnRow(lockFileModel.name); + const actionVersion = contentServices.checkContextActionIsVisible('Manage versions'); + expect(actionVersion.isEnabled()).toBeFalsy(); }); it('[C277199] should a user with Collaborator permission be able to upload a new version for a file with different creator', () => { diff --git a/lib/content-services/document-list/components/document-list.component.spec.ts b/lib/content-services/document-list/components/document-list.component.spec.ts index a563bbcd20..d707c32023 100644 --- a/lib/content-services/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/document-list/components/document-list.component.spec.ts @@ -443,6 +443,99 @@ describe('DocumentList', () => { expect(actions[0].disabled).toBeFalsy(); }); + it('should disable the action if a readonly lock is applied to the file', () => { + let documentMenu = new ContentActionModel({ + permission: 'delete', + target: 'document', + title: 'FileAction' + }); + + documentList.actions = [ + documentMenu + ]; + + let nodeFile = { + entry: { + isFile: true, + name: 'xyz', + isLocked: true, + allowableOperations: ['create', 'update', 'delete'], + properties: { 'cm:lockType': 'READ_ONLY_LOCK', 'cm:lockLifetime': 'PERSISTENT' } + } + }; + + let actions = documentList.getNodeActions(nodeFile); + expect(actions.length).toBe(1); + expect(actions[0].title).toEqual('FileAction'); + expect(actions[0].disabled).toBeTruthy(); + }); + + it('should not disable the action for the lock owner if write lock is applied', () => { + let documentMenu = new ContentActionModel({ + permission: 'delete', + target: 'document', + title: 'FileAction' + }); + + spyOn(apiService.getInstance(), 'getEcmUsername').and.returnValue('lockOwner'); + + documentList.actions = [ + documentMenu + ]; + + let nodeFile = { + entry: { + isFile: true, + name: 'xyz', + isLocked: true, + allowableOperations: ['create', 'update', 'delete'], + properties: { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lockOwner', displayName: 'lockOwner' } + } + } + }; + + let actions = documentList.getNodeActions(nodeFile); + expect(actions.length).toBe(1); + expect(actions[0].title).toEqual('FileAction'); + expect(actions[0].disabled).toBeFalsy(); + }); + + it('should disable the action if write lock is applied and user is not the lock owner', () => { + let documentMenu = new ContentActionModel({ + permission: 'delete', + target: 'document', + title: 'FileAction' + }); + + spyOn(apiService.getInstance(), 'getEcmUsername').and.returnValue('jerryTheKillerCow'); + + documentList.actions = [ + documentMenu + ]; + + let nodeFile = { + entry: { + isFile: true, + name: 'xyz', + isLocked: true, + allowableOperations: ['create', 'update', 'delete'], + properties: { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lockOwner', displayName: 'lockOwner' } + } + } + }; + + let actions = documentList.getNodeActions(nodeFile); + expect(actions.length).toBe(1); + expect(actions[0].title).toEqual('FileAction'); + expect(actions[0].disabled).toBeTruthy(); + }); + it('should not disable the action if there is the right permission for the folder', () => { const documentMenu = new ContentActionModel({ disableWithNoPermission: true, diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index 35f23419e6..620f9ea4cd 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -42,7 +42,8 @@ import { CustomEmptyContentTemplateDirective, RequestPaginationModel, AlfrescoApiService, - UserPreferenceValues + UserPreferenceValues, + LockService } from '@alfresco/adf-core'; import { Node, NodeEntry, NodePaging, Pagination } from '@alfresco/js-api'; @@ -325,7 +326,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte private customResourcesService: CustomResourcesService, private contentService: ContentService, private thumbnailService: ThumbnailService, - private alfrescoApiService: AlfrescoApiService) { + private alfrescoApiService: AlfrescoApiService, + private lockService: LockService) { this.userPreferencesService.select(UserPreferenceValues.PaginationSize).subscribe((pagSize) => { this.maxItems = this._pagination.maxItems = pagSize; @@ -532,11 +534,14 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte return action.disabled(node); } - if (action.permission && action.disableWithNoPermission && !this.contentService.hasAllowableOperations(node.entry, action.permission)) { + if ((action.permission && + action.disableWithNoPermission && + !this.contentService.hasAllowableOperations(node.entry, action.permission)) || + this.lockService.isLocked(node.entry)) { return true; + } else { + return action.disabled; } - - return action.disabled; } @HostListener('contextmenu', ['$event']) diff --git a/lib/core/services/lock.service.spec.ts b/lib/core/services/lock.service.spec.ts new file mode 100644 index 0000000000..53ce615a88 --- /dev/null +++ b/lib/core/services/lock.service.spec.ts @@ -0,0 +1,166 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { LockService } from './lock.service'; +import { CoreTestingModule } from '../testing/core.testing.module'; +import { setupTestBed } from '../testing/setupTestBed'; +import { Node } from '@alfresco/js-api'; +import { AlfrescoApiServiceMock } from 'core/mock'; +import { AlfrescoApiService } from './alfresco-api.service'; +import moment from 'moment-es6'; + +describe('PeopleProcessService', () => { + + let service: LockService; + let apiService: AlfrescoApiServiceMock; + + const fakeNodeUnlocked: Node = <Node> { name: 'unlocked', isLocked: false, isFile: true }; + const fakeFolderNode: Node = <Node> { name: 'unlocked', isLocked: false, isFile: false, isFolder: true }; + const fakeNodeNoProperty: Node = <Node> { name: 'unlocked', isLocked: true, isFile: true, properties: {} }; + + setupTestBed({ + imports: [CoreTestingModule] + }); + + beforeEach(() => { + service = TestBed.get(LockService); + apiService = TestBed.get(AlfrescoApiService); + }); + + it('should return false when no lock is configured', () => { + expect(service.isLocked(fakeNodeUnlocked)).toBeFalsy(); + }); + + it('should return false when isLocked is true but property `cm:lockType` is not present', () => { + expect(service.isLocked(fakeNodeNoProperty)).toBeFalsy(); + }); + + it('should return false when a node folder', () => { + expect(service.isLocked(fakeFolderNode)).toBeFalsy(); + }); + + describe('When the lock is readonly', () => { + const nodeReadonly: Node = <Node> { + name: 'readonly-lock-node', + isLocked: true, + isFile: true, + properties: + { 'cm:lockType': 'READ_ONLY_LOCK', + 'cm:lockLifetime': 'PERSISTENT' } + }; + + const nodeReadOnlyWithExpiredDate: Node = <Node> { + name: 'readonly-lock-node', + isLocked: true, + isFile: true, + properties: + { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lock-owner-user' }, + 'cm:expiryDate': moment().subtract('days', '4') + } + }; + + const nodeReadOnlyWithActiveExpiration: Node = <Node> { + name: 'readonly-lock-node', + isLocked: true, + isFile: true, + properties: + { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lock-owner-user' }, + 'cm:expiryDate': moment().add('days', '4') + } + }; + + it('should return true when readonly lock is active', () => { + expect(service.isLocked(nodeReadonly)).toBeTruthy(); + }); + + it('should return false when readonly lock is expired', () => { + expect(service.isLocked(nodeReadOnlyWithExpiredDate)).toBeFalsy(); + }); + + it('should return true when readonly lock is active and expiration date is active', () => { + expect(service.isLocked(nodeReadOnlyWithActiveExpiration)).toBeTruthy(); + }); + }); + + describe('When only the lock owner is allowed', () => { + const nodeOwnerAllowedLock: Node = <Node> { + name: 'readonly-lock-node', + isLocked: true, + isFile: true, + properties: + { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lock-owner-user' } + } + }; + + const nodeOwnerAllowedLockWithExpiredDate: Node = <Node> { + name: 'readonly-lock-node', + isLocked: true, + isFile: true, + properties: + { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lock-owner-user' }, + 'cm:expiryDate': moment().subtract('days', '4') + } + }; + + const nodeOwnerAllowedLockWithActiveExpiration: Node = <Node> { + name: 'readonly-lock-node', + isLocked: true, + isFile: true, + properties: + { + 'cm:lockType': 'WRITE_LOCK', + 'cm:lockLifetime': 'PERSISTENT', + 'cm:lockOwner': { id: 'lock-owner-user' }, + 'cm:expiryDate': moment().add('days', '4') + } + }; + + it('should return false when the user is the lock owner', () => { + spyOn(apiService.getInstance(), 'getEcmUsername').and.returnValue('lock-owner-user'); + expect(service.isLocked(nodeOwnerAllowedLock)).toBeFalsy(); + }); + + it('should return true when the user is not the lock owner', () => { + spyOn(apiService.getInstance(), 'getEcmUsername').and.returnValue('banana-user'); + expect(service.isLocked(nodeOwnerAllowedLock)).toBeTruthy(); + }); + + it('should return false when the user is not the lock owner but the lock is expired', () => { + spyOn(apiService.getInstance(), 'getEcmUsername').and.returnValue('banana-user'); + expect(service.isLocked(nodeOwnerAllowedLockWithExpiredDate)).toBeFalsy(); + }); + + it('should return true when is not the lock owner and the expiration date is valid', () => { + spyOn(apiService.getInstance(), 'getEcmUsername').and.returnValue('banana-user'); + expect(service.isLocked(nodeOwnerAllowedLockWithActiveExpiration)).toBeTruthy(); + }); + + }); +}); diff --git a/lib/core/services/lock.service.ts b/lib/core/services/lock.service.ts new file mode 100644 index 0000000000..56b3f24568 --- /dev/null +++ b/lib/core/services/lock.service.ts @@ -0,0 +1,72 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { Node } from '@alfresco/js-api'; +import { AlfrescoApiService } from './alfresco-api.service'; +import moment from 'moment-es6'; +import { Moment } from 'moment'; + +@Injectable({ + providedIn: 'root' +}) +export class LockService { + + constructor(private alfrescoApiService: AlfrescoApiService) { + } + + isLocked(node: Node): boolean { + let isLocked = false; + if (this.hasLockConfigured(node)) { + if (this.isReadOnlyLock(node)) { + isLocked = true; + if (this.isLockExpired(node)) { + isLocked = false; + } + } else if (this.isLockOwnerAllowed(node)) { + isLocked = this.alfrescoApiService.getInstance().getEcmUsername() !== node.properties['cm:lockOwner'].id; + if (this.isLockExpired(node)) { + isLocked = false; + } + } + } + return isLocked; + } + + private hasLockConfigured(node: Node): boolean { + return node.isFile && node.isLocked && node.properties['cm:lockType']; + } + + private isReadOnlyLock(node: Node): boolean { + return node.properties['cm:lockType'] === 'READ_ONLY_LOCK' && node.properties['cm:lockLifetime'] === 'PERSISTENT'; + } + + private isLockOwnerAllowed(node: Node): boolean { + return node.properties['cm:lockType'] === 'WRITE_LOCK' && node.properties['cm:lockLifetime'] === 'PERSISTENT'; + } + + private getLockExpiryTime(node: Node): Moment { + if (node.properties['cm:expiryDate']) { + return moment(node.properties['cm:expiryDate'], 'yyyy-MM-ddThh:mm:ssZ'); + } + } + + private isLockExpired(node: Node): boolean { + let expiryLockTime = this.getLockExpiryTime(node); + return moment().isAfter(expiryLockTime); + } +} diff --git a/lib/core/services/public-api.ts b/lib/core/services/public-api.ts index 19f310b7e5..3af0268852 100644 --- a/lib/core/services/public-api.ts +++ b/lib/core/services/public-api.ts @@ -53,4 +53,5 @@ export * from './login-dialog.service'; export * from './external-alfresco-api.service'; export * from './jwt-helper.service'; export * from './download-zip.service'; +export * from './lock.service'; export * from './automation.service'; From b55203cec7e81fdb277bf47160d5cfbb9761e753 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 11:53:53 +0000 Subject: [PATCH 016/208] fix const --- .../components/document-list.component.spec.ts | 18 +++++++++--------- lib/core/services/lock.service.ts | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/content-services/document-list/components/document-list.component.spec.ts b/lib/content-services/document-list/components/document-list.component.spec.ts index d707c32023..05aa233fbd 100644 --- a/lib/content-services/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/document-list/components/document-list.component.spec.ts @@ -444,7 +444,7 @@ describe('DocumentList', () => { }); it('should disable the action if a readonly lock is applied to the file', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'document', title: 'FileAction' @@ -454,7 +454,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { + const nodeFile = { entry: { isFile: true, name: 'xyz', @@ -464,14 +464,14 @@ describe('DocumentList', () => { } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeTruthy(); }); it('should not disable the action for the lock owner if write lock is applied', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'document', title: 'FileAction' @@ -483,7 +483,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { + const nodeFile = { entry: { isFile: true, name: 'xyz', @@ -497,14 +497,14 @@ describe('DocumentList', () => { } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeFalsy(); }); it('should disable the action if write lock is applied and user is not the lock owner', () => { - let documentMenu = new ContentActionModel({ + const documentMenu = new ContentActionModel({ permission: 'delete', target: 'document', title: 'FileAction' @@ -516,7 +516,7 @@ describe('DocumentList', () => { documentMenu ]; - let nodeFile = { + const nodeFile = { entry: { isFile: true, name: 'xyz', @@ -530,7 +530,7 @@ describe('DocumentList', () => { } }; - let actions = documentList.getNodeActions(nodeFile); + const actions = documentList.getNodeActions(nodeFile); expect(actions.length).toBe(1); expect(actions[0].title).toEqual('FileAction'); expect(actions[0].disabled).toBeTruthy(); diff --git a/lib/core/services/lock.service.ts b/lib/core/services/lock.service.ts index 56b3f24568..6e40769998 100644 --- a/lib/core/services/lock.service.ts +++ b/lib/core/services/lock.service.ts @@ -66,7 +66,7 @@ export class LockService { } private isLockExpired(node: Node): boolean { - let expiryLockTime = this.getLockExpiryTime(node); + const expiryLockTime = this.getLockExpiryTime(node); return moment().isAfter(expiryLockTime); } } From 9cd9969584e1a1b59867a0334efc79c59fb95ebb Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 12:02:17 +0000 Subject: [PATCH 017/208] beta2 --- demo-shell/package.json | 2 +- lib/content-services/package.json | 4 ++-- lib/core/package.json | 2 +- lib/extensions/package.json | 2 +- lib/insights/package.json | 6 +++--- lib/process-services-cloud/package.json | 4 ++-- lib/process-services/package.json | 6 +++--- lib/testing/package.json | 2 +- package.json | 16 ++++++++-------- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/demo-shell/package.json b/demo-shell/package.json index 3dcc1e9a1d..53b3b58cae 100644 --- a/demo-shell/package.json +++ b/demo-shell/package.json @@ -1,7 +1,7 @@ { "name": "Alfresco-ADF-Angular-Demo", "description": "Demo shell for Alfresco Angular components", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "repository": { "type": "git", diff --git a/lib/content-services/package.json b/lib/content-services/package.json index 33539613c8..c7d97c8bf5 100644 --- a/lib/content-services/package.json +++ b/lib/content-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-content-services", "description": "Alfresco ADF content services", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-content-services.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta1", + "@alfresco/adf-core": "3.2.0-beta2", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/core/package.json b/lib/core/package.json index c91201a10b..b9cf8016d0 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-core", "description": "Alfresco ADF core", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-core.js", "repository": { diff --git a/lib/extensions/package.json b/lib/extensions/package.json index 1f045cf9d0..afa49f054d 100644 --- a/lib/extensions/package.json +++ b/lib/extensions/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-extensions", "description": "Provides extensibility support for ADF applications.", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-extensions.js", "repository": { diff --git a/lib/insights/package.json b/lib/insights/package.json index eb32cd060e..03d6e60c3d 100644 --- a/lib/insights/package.json +++ b/lib/insights/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-insights", "description": "Alfresco ADF insights", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-insights.js", "repository": { @@ -27,8 +27,8 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta1", - "@alfresco/adf-content-services": "3.2.0-beta1", + "@alfresco/adf-core": "3.2.0-beta2", + "@alfresco/adf-content-services": "3.2.0-beta2", "@ngx-translate/core": ">=11.0.0", "chart.js": ">=2.5.0", "core-js": ">=2.5.4", diff --git a/lib/process-services-cloud/package.json b/lib/process-services-cloud/package.json index 1344bf7db8..e20da3818c 100644 --- a/lib/process-services-cloud/package.json +++ b/lib/process-services-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services-cloud", "description": "Alfresco ADF process services cloud", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services-cloud.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta1", + "@alfresco/adf-core": "3.2.0-beta2", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/process-services/package.json b/lib/process-services/package.json index d74d2cac0d..a3f59bceb7 100644 --- a/lib/process-services/package.json +++ b/lib/process-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services", "description": "Alfresco ADF process services", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services.js", "repository": { @@ -27,8 +27,8 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta1", - "@alfresco/adf-content-services": "3.2.0-beta1", + "@alfresco/adf-core": "3.2.0-beta2", + "@alfresco/adf-content-services": "3.2.0-beta2", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", "hammerjs": ">=2.0.8", diff --git a/lib/testing/package.json b/lib/testing/package.json index d4bba9d1af..52ade059b1 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,6 +1,6 @@ { "name": "@alfresco/adf-testing", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0", diff --git a/package.json b/package.json index 99ad3408ac..4493b98764 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alfresco-components", "description": "Alfresco Angular components", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "author": "Alfresco Software, Ltd.", "main": "./index.js", "scripts": { @@ -55,13 +55,13 @@ "process services-cloud" ], "dependencies": { - "@alfresco/adf-content-services": "3.2.0-beta1", - "@alfresco/adf-core": "3.2.0-beta1", - "@alfresco/adf-extensions": "3.2.0-beta1", - "@alfresco/adf-insights": "3.2.0-beta1", - "@alfresco/adf-process-services": "3.2.0-beta1", - "@alfresco/adf-process-services-cloud": "3.2.0-beta1", - "@alfresco/adf-testing": "3.2.0-beta1", + "@alfresco/adf-content-services": "3.2.0-beta2", + "@alfresco/adf-core": "3.2.0-beta2", + "@alfresco/adf-extensions": "3.2.0-beta2", + "@alfresco/adf-insights": "3.2.0-beta2", + "@alfresco/adf-process-services": "3.2.0-beta2", + "@alfresco/adf-process-services-cloud": "3.2.0-beta2", + "@alfresco/adf-testing": "3.2.0-beta2", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "@angular/animations": "7.0.3", "@angular/cdk": "7.0.3", From 3b1c4923b277dcc9c6d8237d2705cb136195c435 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Wed, 27 Mar 2019 12:18:10 +0000 Subject: [PATCH 018/208] fix AOT --- .../search/components/search-control.component.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/content-services/search/components/search-control.component.ts b/lib/content-services/search/components/search-control.component.ts index eefd255197..b3d9df5d35 100644 --- a/lib/content-services/search/components/search-control.component.ts +++ b/lib/content-services/search/components/search-control.component.ts @@ -172,15 +172,12 @@ export class SearchControlComponent implements OnInit, OnDestroy { } getMimeTypeIcon(node: NodeEntry): string { - let mimeType; - - mimeType = this.getMimeType(node); - + const mimeType = this.getMimeType(node); return this.thumbnailService.getMimeTypeIcon(mimeType); } - private getMimeType(node: NodeEntry) { - let mimeType; + getMimeType(node: NodeEntry): string { + let mimeType: string; if (node.entry.content && node.entry.content.mimeType) { mimeType = node.entry.content.mimeType; From a2823eeb991d97bc71d9c46692b7c631110a16b7 Mon Sep 17 00:00:00 2001 From: Vito <vito.albano@alfresco.com> Date: Wed, 27 Mar 2019 13:10:59 +0000 Subject: [PATCH 019/208] [ADF-3912] Improved folder retrieving for DL (#4423) * [ADF-3912] added abstract class for document-list component to be provided * [ADF-3912] - created abstract class for document-list service * [ADF-3912] - fixing and removing the custom resource from document-list * [ADF-3912] added interface for document list service * [ADF-3912] added interface for loadFolderById for DL component * [ADF-3912] fixed missing return type * [ADF-3912] removed comment * [ADF-3912] fixed PR comments * [ADF-3912] fixed wrong import * [ADF-3912] fixed unit test failing * [ADF-3912] removed unused method * [ADF-3912] fixed lint problems --- .../breadcrumb/breadcrumb.component.spec.ts | 26 ++-- .../dropdown-breadcrumb.component.spec.ts | 12 +- .../content-node-dialog.service.ts | 7 +- .../document-list.component.spec.ts | 65 ++++++---- .../components/document-list.component.ts | 59 +++------ .../data/share-datatable-adapter.spec.ts | 115 +++++++++++------- .../data/share-datatable-adapter.ts | 18 ++- .../document-list-loader.interface.ts | 25 ++++ .../models/document-folder.model.ts | 28 +++++ .../document-list/public-api.ts | 2 + .../services/document-actions.service.spec.ts | 2 +- .../services/document-list.service.spec.ts | 4 +- .../services/document-list.service.ts | 57 +++++---- .../services/folder-actions.service.spec.ts | 2 +- 14 files changed, 256 insertions(+), 166 deletions(-) create mode 100644 lib/content-services/document-list/interfaces/document-list-loader.interface.ts create mode 100644 lib/content-services/document-list/models/document-folder.model.ts diff --git a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts index 3a1f4292de..7cf8667b68 100644 --- a/lib/content-services/breadcrumb/breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/breadcrumb.component.spec.ts @@ -20,25 +20,29 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PathElementEntity } from '@alfresco/js-api'; import { setupTestBed } from '@alfresco/adf-core'; import { fakeNodeWithCreatePermission } from '../mock'; -import { DocumentListComponent } from '../document-list'; +import { DocumentListComponent, DocumentListService } from '../document-list'; import { BreadcrumbComponent } from './breadcrumb.component'; import { ContentTestingModule } from '../testing/content.testing.module'; +import { of } from 'rxjs'; describe('Breadcrumb', () => { let component: BreadcrumbComponent; let fixture: ComponentFixture<BreadcrumbComponent>; - let documentList: DocumentListComponent; + let documentListService: DocumentListService = jasmine.createSpyObj({'loadFolderByNodeId' : of(''), 'isCustomSourceService': false}); + let documentListComponent: DocumentListComponent; setupTestBed({ imports: [ContentTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA], + providers : [{ provide: DocumentListService, useValue: documentListService }] }); beforeEach(() => { fixture = TestBed.createComponent(BreadcrumbComponent); component = fixture.componentInstance; - documentList = TestBed.createComponent<DocumentListComponent>(DocumentListComponent).componentInstance; + documentListComponent = TestBed.createComponent<DocumentListComponent>(DocumentListComponent).componentInstance; + documentListService = TestBed.get(DocumentListService); }); afterEach(() => { @@ -69,17 +73,17 @@ describe('Breadcrumb', () => { component.onRoutePathClick(node, null); }); - it('should update document list on click', (done) => { - spyOn(documentList, 'loadFolderByNodeId').and.stub(); + it('should update document list on click', () => { const node = <PathElementEntity> { id: '-id-', name: 'name' }; - component.target = documentList; + component.target = documentListComponent; component.onRoutePathClick(node, null); - setTimeout(() => { - expect(documentList.loadFolderByNodeId).toHaveBeenCalledWith(node.id); - done(); - }, 0); + + expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith(node.id, + documentListComponent.DEFAULT_PAGINATION, + documentListComponent.includeFields, + documentListComponent.where); }); it('should not parse the route when node not provided', () => { diff --git a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts index 12983a1385..ec64a09e49 100644 --- a/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts +++ b/lib/content-services/breadcrumb/dropdown-breadcrumb.component.spec.ts @@ -20,25 +20,29 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { setupTestBed } from '@alfresco/adf-core'; import { fakeNodeWithCreatePermission } from '../mock'; -import { DocumentListComponent } from '../document-list'; +import { DocumentListComponent, DocumentListService } from '../document-list'; import { DropdownBreadcrumbComponent } from './dropdown-breadcrumb.component'; import { ContentTestingModule } from '../testing/content.testing.module'; +import { of } from 'rxjs'; describe('DropdownBreadcrumb', () => { let component: DropdownBreadcrumbComponent; let fixture: ComponentFixture<DropdownBreadcrumbComponent>; let documentList: DocumentListComponent; + let documentListService: DocumentListService = jasmine.createSpyObj({'loadFolderByNodeId' : of(''), 'isCustomSourceService': false}); setupTestBed({ imports: [ContentTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + schemas: [CUSTOM_ELEMENTS_SCHEMA], + providers : [{ provide: DocumentListService, useValue: documentListService }] }); beforeEach(async(() => { fixture = TestBed.createComponent(DropdownBreadcrumbComponent); component = fixture.componentInstance; documentList = TestBed.createComponent<DocumentListComponent>(DocumentListComponent).componentInstance; + documentListService = TestBed.get(DocumentListService); })); afterEach(async(() => { @@ -151,7 +155,6 @@ describe('DropdownBreadcrumb', () => { }); it('should update document list when clicking on an option', (done) => { - spyOn(documentList, 'loadFolderByNodeId').and.stub(); component.target = documentList; const fakeNodeWithCreatePermissionInstance = JSON.parse(JSON.stringify(fakeNodeWithCreatePermission)); fakeNodeWithCreatePermissionInstance.path.elements = [{ id: '1', name: 'Stark Industries' }]; @@ -160,10 +163,9 @@ describe('DropdownBreadcrumb', () => { fixture.whenStable().then(() => { openSelect(); fixture.whenStable().then(() => { - clickOnTheFirstOption(); - expect(documentList.loadFolderByNodeId).toHaveBeenCalledWith('1'); + expect(documentListService.loadFolderByNodeId).toHaveBeenCalledWith('1', documentList.DEFAULT_PAGINATION, undefined, undefined); done(); }); }); diff --git a/lib/content-services/content-node-selector/content-node-dialog.service.ts b/lib/content-services/content-node-selector/content-node-dialog.service.ts index b1ef6e41ce..5a343b1d5f 100644 --- a/lib/content-services/content-node-selector/content-node-dialog.service.ts +++ b/lib/content-services/content-node-selector/content-node-dialog.service.ts @@ -17,7 +17,7 @@ import { MatDialog } from '@angular/material'; import { EventEmitter, Injectable, Output } from '@angular/core'; -import { ContentService } from '@alfresco/adf-core'; +import { ContentService, ThumbnailService } from '@alfresco/adf-core'; import { Subject, Observable, throwError } from 'rxjs'; import { ShareDataRow } from '../document-list/data/share-data-row.model'; import { Node, NodeEntry, SitePaging } from '@alfresco/js-api'; @@ -49,7 +49,8 @@ export class ContentNodeDialogService { private contentService: ContentService, private documentListService: DocumentListService, private siteService: SitesService, - private translation: TranslationService) { + private translation: TranslationService, + private thumbnailService: ThumbnailService) { } /** @@ -224,7 +225,7 @@ export class ContentNodeDialogService { private imageResolver(row: ShareDataRow, col: DataColumn): string | null { const entry: Node = row.node.entry; if (!this.contentService.hasAllowableOperations(entry, 'create')) { - return this.documentListService.getMimeTypeIcon('disable/folder'); + return this.thumbnailService.getMimeTypeIcon('disable/folder'); } return null; diff --git a/lib/content-services/document-list/components/document-list.component.spec.ts b/lib/content-services/document-list/components/document-list.component.spec.ts index 05aa233fbd..a0e87f8169 100644 --- a/lib/content-services/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/document-list/components/document-list.component.spec.ts @@ -866,9 +866,9 @@ describe('DocumentList', () => { it('should display folder content from loadFolderByNodeId on reload if currentFolderId defined', () => { documentList.currentFolderId = 'id-folder'; - spyOn(documentList, 'loadFolderByNodeId').and.stub(); + spyOn(documentList, 'loadFolder').and.stub(); documentList.reload(); - expect(documentList.loadFolderByNodeId).toHaveBeenCalled(); + expect(documentList.loadFolder).toHaveBeenCalled(); }); it('should require node to resolve context menu actions', () => { @@ -1050,8 +1050,8 @@ describe('DocumentList', () => { disposableError.unsubscribe(); done(); }); - - documentList.loadFolderByNodeId('123'); + documentList.currentFolderId = '123'; + documentList.loadFolder(); }); it('should emit folderChange event when a folder node is clicked', (done) => { @@ -1075,7 +1075,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('123'); + documentList.currentFolderId = '123'; + documentList.loadFolder(); }); it('should reset noPermission upon reload', () => { @@ -1135,7 +1136,8 @@ describe('DocumentList', () => { it('should fetch trashcan', () => { spyOn(apiService.nodesApi, 'getDeletedNodes').and.returnValue(Promise.resolve(null)); - documentList.loadFolderByNodeId('-trashcan-'); + documentList.currentFolderId = '-trashcan-'; + documentList.loadFolder(); expect(apiService.nodesApi.getDeletedNodes).toHaveBeenCalled(); }); @@ -1148,14 +1150,16 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-trashcan-'); + documentList.currentFolderId = '-trashcan-'; + documentList.loadFolder(); }); it('should fetch shared links', () => { const sharedlinksApi = apiService.getInstance().core.sharedlinksApi; spyOn(sharedlinksApi, 'findSharedLinks').and.returnValue(Promise.resolve(null)); - documentList.loadFolderByNodeId('-sharedlinks-'); + documentList.currentFolderId = '-sharedlinks-'; + documentList.loadFolder(); expect(sharedlinksApi.findSharedLinks).toHaveBeenCalled(); }); @@ -1169,13 +1173,15 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sharedlinks-'); + documentList.currentFolderId = '-sharedlinks-'; + documentList.loadFolder(); }); it('should fetch sites', () => { const sitesApi = apiService.getInstance().core.sitesApi; - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); expect(sitesApi.getSites).toHaveBeenCalled(); }); @@ -1188,7 +1194,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); }); it('should assure that sites have name property set', (done) => { @@ -1201,7 +1208,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); }); it('should assure that sites have name property set correctly', (done) => { @@ -1214,14 +1222,16 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-sites-'); + documentList.currentFolderId = '-sites-'; + documentList.loadFolder(); }); it('should fetch user membership sites', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); }); @@ -1235,7 +1245,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); }); it('should assure that user membership sites have name property set', (done) => { @@ -1243,7 +1254,8 @@ describe('DocumentList', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); const disposableReady = documentList.ready.subscribe((page) => { @@ -1259,7 +1271,8 @@ describe('DocumentList', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(peopleApi.listSiteMembershipsForPerson).toHaveBeenCalled(); const disposableReady = documentList.ready.subscribe((page) => { @@ -1274,7 +1287,8 @@ describe('DocumentList', () => { const favoritesApi = apiService.getInstance().core.favoritesApi; spyFavorite.and.returnValue(Promise.resolve(null)); - documentList.loadFolderByNodeId('-favorites-'); + documentList.currentFolderId = '-favorites-'; + documentList.loadFolder(); expect(favoritesApi.getFavorites).toHaveBeenCalled(); }); @@ -1287,7 +1301,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-favorites-'); + documentList.currentFolderId = '-favorites-'; + documentList.loadFolder(); }); it('should fetch recent', () => { @@ -1295,7 +1310,8 @@ describe('DocumentList', () => { const getPersonSpy = spyOn(apiService.peopleApi, 'getPerson').and.returnValue(Promise.resolve(person)); - documentList.loadFolderByNodeId('-recent-'); + documentList.currentFolderId = '-recent-'; + documentList.loadFolder(); expect(getPersonSpy).toHaveBeenCalledWith('-me-'); }); @@ -1309,7 +1325,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-recent-'); + documentList.currentFolderId = '-recent-'; + documentList.loadFolder(); }); it('should emit error when fetch recent fails on search call', (done) => { @@ -1321,7 +1338,8 @@ describe('DocumentList', () => { done(); }); - documentList.loadFolderByNodeId('-recent-'); + documentList.currentFolderId = '-recent-'; + documentList.loadFolder(); }); it('should have correct currentFolderId on loading folder by node id', () => { @@ -1330,7 +1348,8 @@ describe('DocumentList', () => { const peopleApi = apiService.getInstance().core.peopleApi; spyOn(peopleApi, 'listSiteMembershipsForPerson').and.returnValue(Promise.resolve(fakeGetSiteMembership)); - documentList.loadFolderByNodeId('-mysites-'); + documentList.currentFolderId = '-mysites-'; + documentList.loadFolder(); expect(documentList.currentFolderId).toBe('-mysites-'); }); diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index 620f9ea4cd..5484758c3d 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -53,12 +53,11 @@ import { ShareDataTableAdapter } from './../data/share-datatable-adapter'; import { presetsDefaultModel } from '../models/preset.model'; import { ContentActionModel } from './../models/content-action.model'; import { PermissionStyleModel } from './../models/permissions-style.model'; -import { DocumentListService } from './../services/document-list.service'; import { NodeEntityEvent, NodeEntryEvent } from './node.event'; -import { CustomResourcesService } from './../services/custom-resources.service'; import { NavigableComponentInterface } from '../../breadcrumb/navigable-component.interface'; import { RowFilter } from '../data/row-filter.model'; -import { Observable } from 'rxjs/index'; +import { DocumentListService } from '../services/document-list.service'; +import { DocumentLoaderNode } from '../models/document-folder.model'; @Component({ selector: 'adf-document-list', @@ -323,7 +322,6 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte private elementRef: ElementRef, private appConfig: AppConfigService, private userPreferencesService: UserPreferencesService, - private customResourcesService: CustomResourcesService, private contentService: ContentService, private thumbnailService: ThumbnailService, private alfrescoApiService: AlfrescoApiService, @@ -378,7 +376,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte ngOnInit() { this.rowMenuCache = {}; this.loadLayoutPresets(); - this.data = new ShareDataTableAdapter(this.documentListService, this.thumbnailService, this.contentService, null, this.getDefaultSorting(), this.sortingMode); + this.data = new ShareDataTableAdapter(this.thumbnailService, this.contentService, null, this.getDefaultSorting(), this.sortingMode); this.data.thumbnails = this.thumbnails; this.data.permissionsStyle = this.permissionsStyle; @@ -416,7 +414,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } if (!this.data) { - this.data = new ShareDataTableAdapter(this.documentListService, this.thumbnailService, this.contentService, schema, this.getDefaultSorting(), this.sortingMode); + this.data = new ShareDataTableAdapter(this.thumbnailService, this.contentService, schema, this.getDefaultSorting(), this.sortingMode); } else if (schema && schema.length > 0) { this.data.setColumns(schema); } @@ -627,45 +625,20 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.setupDefaultColumns(this._currentFolderId); } - this.loadFolderByNodeId(this._currentFolderId); - } - - loadFolderByNodeId(nodeId: string) { - if (this.customResourcesService.isCustomSource(nodeId)) { - this.updateCustomSourceData(nodeId); - this.customResourcesService.loadFolderByNodeId(nodeId, this._pagination, this.includeFields) - .subscribe((nodePaging: NodePaging) => { - this.onPageLoaded(nodePaging); - }, (err) => { - this.error.emit(err); - }); - } else { - - this.documentListService.getFolder(null, { - maxItems: this._pagination.maxItems, - skipCount: this._pagination.skipCount, - rootFolderId: nodeId, - where: this.where - }, this.includeFields) - .subscribe((nodePaging: NodePaging) => { - this.getSourceNodeWithPath(nodeId).subscribe((nodeEntry: NodeEntry) => { - this.onPageLoaded(nodePaging); - }); - }, (err) => { - this.handleError(err); - }); + if (this.documentListService.isCustomSourceService(this._currentFolderId)) { + this.updateCustomSourceData(this._currentFolderId); } - } - getSourceNodeWithPath(nodeId: string): Observable<NodeEntry> { - const getSourceObservable = this.documentListService.getFolderNode(nodeId, this.includeFields); - - getSourceObservable.subscribe((nodeEntry: NodeEntry) => { - this.folderNode = nodeEntry.entry; - this.$folderNode.next(this.folderNode); - }); - - return getSourceObservable; + this.documentListService.loadFolderByNodeId(this._currentFolderId, this._pagination, this.includeFields, this.where) + .subscribe((documentNode: DocumentLoaderNode) => { + if (documentNode.currentNode) { + this.folderNode = documentNode.currentNode.entry; + this.$folderNode.next(documentNode.currentNode.entry); + } + this.onPageLoaded(documentNode.children); + }, (err) => { + this.handleError(err); + }); } resetSelection() { diff --git a/lib/content-services/document-list/data/share-datatable-adapter.spec.ts b/lib/content-services/document-list/data/share-datatable-adapter.spec.ts index 40cf06bfd2..c4624e64d0 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.spec.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.spec.ts @@ -15,31 +15,64 @@ * limitations under the License. */ -import { DataColumn, DataRow, DataSorting, ContentService } from '@alfresco/adf-core'; +import { DataColumn, DataRow, DataSorting, ContentService, ThumbnailService } from '@alfresco/adf-core'; import { FileNode, FolderNode, SmartFolderNode, RuleFolderNode, LinkFolderNode } from './../../mock'; -import { DocumentListService } from './../services/document-list.service'; import { ShareDataRow } from './share-data-row.model'; import { ShareDataTableAdapter } from './share-datatable-adapter'; +import { DomSanitizer } from '@angular/platform-browser'; +import { MatIconRegistry } from '@angular/material'; + +class FakeSanitizer extends DomSanitizer { + + constructor() { + super(); + } + + sanitize(html) { + return html; + } + + bypassSecurityTrustHtml(value: string): any { + return value; + } + + bypassSecurityTrustStyle(value: string): any { + return null; + } + + bypassSecurityTrustScript(value: string): any { + return null; + } + + bypassSecurityTrustUrl(value: string): any { + return null; + } + + bypassSecurityTrustResourceUrl(value: string): any { + return null; + } +} describe('ShareDataTableAdapter', () => { - let documentListService: DocumentListService; + let thumbnailService: ThumbnailService; let contentService: ContentService; + const fakeMatIconRegistry: MatIconRegistry = jasmine.createSpyObj(['addSvgIcon', 'addSvgIconInNamespace']); beforeEach(() => { const imageUrl: string = 'http://<addresss>'; contentService = new ContentService(null, null, null, null); - documentListService = new DocumentListService(null, contentService, null, null, null); - spyOn(documentListService, 'getDocumentThumbnailUrl').and.returnValue(imageUrl); + thumbnailService = new ThumbnailService(contentService, fakeMatIconRegistry, new FakeSanitizer()); + spyOn(thumbnailService, 'getDocumentThumbnailUrl').and.returnValue(imageUrl); }); it('should use client sorting by default', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, []); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); expect(adapter.sortingMode).toBe('client'); }); it('should not be case sensitive for sorting mode value', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, []); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); adapter.sortingMode = 'CLIENT'; expect(adapter.sortingMode).toBe('client'); @@ -49,7 +82,7 @@ describe('ShareDataTableAdapter', () => { }); it('should fallback to client sorting for unknown values', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, []); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); adapter.sortingMode = 'SeRvEr'; expect(adapter.sortingMode).toBe('server'); @@ -60,27 +93,27 @@ describe('ShareDataTableAdapter', () => { it('should setup rows and columns with constructor', () => { const schema = [<DataColumn> {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, schema); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, schema); expect(adapter.getRows()).toEqual([]); expect(adapter.getColumns()).toEqual(schema); }); it('should setup columns when constructor is missing schema', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); expect(adapter.getColumns()).toEqual([]); }); it('should set new columns', () => { const columns = [<DataColumn> {}, <DataColumn> {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); adapter.setColumns(columns); expect(adapter.getColumns()).toEqual(columns); }); it('should reset columns', () => { const columns = [<DataColumn> {}, <DataColumn> {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, columns); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, columns); expect(adapter.getColumns()).toEqual(columns); adapter.setColumns(null); @@ -89,7 +122,7 @@ describe('ShareDataTableAdapter', () => { it('should set new rows', () => { const rows = [<DataRow> {}, <DataRow> {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); expect(adapter.getRows()).toEqual([]); adapter.setRows(rows); @@ -98,7 +131,7 @@ describe('ShareDataTableAdapter', () => { it('should reset rows', () => { const rows = [<DataRow> {}, <DataRow> {}]; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); adapter.setRows(rows); expect(adapter.getRows()).toEqual(rows); @@ -108,7 +141,7 @@ describe('ShareDataTableAdapter', () => { }); it('should sort new rows', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); spyOn(adapter, 'sort').and.callThrough(); const rows = [<DataRow> {}]; @@ -118,7 +151,7 @@ describe('ShareDataTableAdapter', () => { }); it('should fail when getting value for missing row', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const check = () => { return adapter.getValue(null, <DataColumn> {}); }; @@ -126,7 +159,7 @@ describe('ShareDataTableAdapter', () => { }); it('should fail when getting value for missing column', () => { - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const check = () => { return adapter.getValue(<DataRow> {}, null); }; @@ -145,16 +178,16 @@ describe('ShareDataTableAdapter', () => { }; const row = new ShareDataRow(file, contentService, null); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const value = adapter.getValue(row, col); expect(value).toBe(rawValue); }); it('should generate fallback icon for a file thumbnail with missing mime type', () => { - spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); + spyOn(thumbnailService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.content.mimeType = null; @@ -168,9 +201,9 @@ describe('ShareDataTableAdapter', () => { }); it('should generate fallback icon for a file with no content entry', () => { - spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); + spyOn(thumbnailService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.content = null; @@ -189,7 +222,7 @@ describe('ShareDataTableAdapter', () => { const file = new FileNode(); file.entry['icon'] = imageUrl; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(file, contentService, null); const col = <DataColumn> { type: 'image', key: 'icon' }; @@ -198,9 +231,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new FolderNode(), contentService, null); const col = <DataColumn> { type: 'image', key: '$thumbnail' }; @@ -211,9 +244,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve smart folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_smart_folder.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_smart_folder.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new SmartFolderNode(), contentService, null); const col = <DataColumn> { type: 'folder', key: '$thumbnail' }; @@ -224,9 +257,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve link folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_shortcut_link.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_shortcut_link.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new LinkFolderNode(), contentService, null); const col = <DataColumn> { type: 'folder', key: '$thumbnail' }; @@ -237,9 +270,9 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve rule folder icon', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_rule.svg`); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_folder_rule.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const row = new ShareDataRow(new RuleFolderNode(), contentService, null); const col = <DataColumn> { type: 'folder', key: '$thumbnail' }; @@ -251,7 +284,7 @@ describe('ShareDataTableAdapter', () => { it('should resolve file thumbnail', () => { const imageUrl = 'http://<addresss>'; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); adapter.thumbnails = true; const file = new FileNode(); @@ -260,13 +293,13 @@ describe('ShareDataTableAdapter', () => { const value = adapter.getValue(row, col); expect(value).toBe(imageUrl); - expect(documentListService.getDocumentThumbnailUrl).toHaveBeenCalledWith(file); + expect(thumbnailService.getDocumentThumbnailUrl).toHaveBeenCalledWith(file); }); it('should resolve fallback file icon for unknown node', () => { - spyOn(documentListService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); + spyOn(thumbnailService, 'getDefaultMimeTypeIcon').and.returnValue(`assets/images/ft_ic_miscellaneous.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.isFile = false; @@ -282,8 +315,8 @@ describe('ShareDataTableAdapter', () => { }); it('should resolve file icon for content type', () => { - spyOn(documentListService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_raster_image.svg`); - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, null); + spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_raster_image.svg`); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, null); const file = new FileNode(); file.entry.isFile = false; @@ -304,7 +337,7 @@ describe('ShareDataTableAdapter', () => { const folder = new FolderNode(); const col = <DataColumn> { key: 'name' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setSorting(new DataSorting('name', 'asc')); adapter.setRows([ @@ -327,7 +360,7 @@ describe('ShareDataTableAdapter', () => { file2.entry['dateProp'] = new Date(2016, 6, 30, 13, 14, 2); const col = <DataColumn> { key: 'dateProp' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setRows([ new ShareDataRow(file2, contentService, null), @@ -357,7 +390,7 @@ describe('ShareDataTableAdapter', () => { file4.entry.content.sizeInBytes = 2852791665; // 2.66 GB const col = <DataColumn> { key: 'content.sizeInBytes' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setRows([ new ShareDataRow(file3, contentService, null), @@ -390,7 +423,7 @@ describe('ShareDataTableAdapter', () => { const file6 = new FileNode('b'); const col = <DataColumn> { key: 'name' }; - const adapter = new ShareDataTableAdapter(documentListService, null, contentService, [col]); + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, [col]); adapter.setRows([ new ShareDataRow(file4, contentService, null), diff --git a/lib/content-services/document-list/data/share-datatable-adapter.ts b/lib/content-services/document-list/data/share-datatable-adapter.ts index 4e2b2eeb13..975f76b612 100644 --- a/lib/content-services/document-list/data/share-datatable-adapter.ts +++ b/lib/content-services/document-list/data/share-datatable-adapter.ts @@ -25,7 +25,6 @@ import { } from '@alfresco/adf-core'; import { NodePaging } from '@alfresco/js-api'; import { PermissionStyleModel } from './../models/permissions-style.model'; -import { DocumentListService } from './../services/document-list.service'; import { ShareDataRow } from './share-data-row.model'; import { NodeEntry } from '@alfresco/js-api/src/api/content-rest-api/model/nodeEntry'; import { RowFilter } from './row-filter.model'; @@ -59,8 +58,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { return this._sortingMode; } - constructor(private documentListService: DocumentListService, - private thumbnailService: ThumbnailService, + constructor(private thumbnailService: ThumbnailService, private contentService: ContentService, schema: DataColumn[] = [], sorting?: DataSorting, @@ -119,18 +117,18 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (node.entry.isFile) { if (this.thumbnails) { - return this.documentListService.getDocumentThumbnailUrl(node); + return this.thumbnailService.getDocumentThumbnailUrl(node); } } if (node.entry.content) { const mimeType = node.entry.content.mimeType; if (mimeType) { - return this.documentListService.getMimeTypeIcon(mimeType); + return this.thumbnailService.getMimeTypeIcon(mimeType); } } - return this.documentListService.getDefaultMimeTypeIcon(); + return this.thumbnailService.getDefaultMimeTypeIcon(); } if (col.type === 'image') { @@ -175,13 +173,13 @@ export class ShareDataTableAdapter implements DataTableAdapter { private getFolderIcon(node: any) { if (this.isSmartFolder(node)) { - return this.documentListService.getMimeTypeIcon('smartFolder'); + return this.thumbnailService.getMimeTypeIcon('smartFolder'); } else if (this.isRuleFolder(node)) { - return this.documentListService.getMimeTypeIcon('ruleFolder'); + return this.thumbnailService.getMimeTypeIcon('ruleFolder'); } else if (this.isALinkFolder(node)) { - return this.documentListService.getMimeTypeIcon('linkFolder'); + return this.thumbnailService.getMimeTypeIcon('linkFolder'); } else { - return this.documentListService.getMimeTypeIcon('folder'); + return this.thumbnailService.getMimeTypeIcon('folder'); } } diff --git a/lib/content-services/document-list/interfaces/document-list-loader.interface.ts b/lib/content-services/document-list/interfaces/document-list-loader.interface.ts new file mode 100644 index 0000000000..c49e9c57c8 --- /dev/null +++ b/lib/content-services/document-list/interfaces/document-list-loader.interface.ts @@ -0,0 +1,25 @@ +/*! + * @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 { PaginationModel } from '@alfresco/adf-core'; +import { Observable } from 'rxjs'; +import { DocumentLoaderNode } from '../models/document-folder.model'; + +export interface DocumentListLoader { + + loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable <DocumentLoaderNode>; +} diff --git a/lib/content-services/document-list/models/document-folder.model.ts b/lib/content-services/document-list/models/document-folder.model.ts new file mode 100644 index 0000000000..31aaf96433 --- /dev/null +++ b/lib/content-services/document-list/models/document-folder.model.ts @@ -0,0 +1,28 @@ +/*! + * @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 { NodeEntry, NodePaging } from '@alfresco/js-api'; + +export class DocumentLoaderNode { + currentNode: NodeEntry; + children: NodePaging; + + constructor(currentNode: NodeEntry, children: NodePaging) { + this.currentNode = currentNode; + this.children = children; + } +} diff --git a/lib/content-services/document-list/public-api.ts b/lib/content-services/document-list/public-api.ts index 38fec6edc4..98c6ca60bf 100644 --- a/lib/content-services/document-list/public-api.ts +++ b/lib/content-services/document-list/public-api.ts @@ -46,4 +46,6 @@ export * from './models/document-library.model'; export * from './models/permissions.model'; export * from './models/permissions-style.model'; +export * from './interfaces/document-list-loader.interface'; + export * from './document-list.module'; diff --git a/lib/content-services/document-list/services/document-actions.service.spec.ts b/lib/content-services/document-list/services/document-actions.service.spec.ts index e28a6562c6..67e9e8d7d6 100644 --- a/lib/content-services/document-list/services/document-actions.service.spec.ts +++ b/lib/content-services/document-list/services/document-actions.service.spec.ts @@ -39,7 +39,7 @@ describe('DocumentActionsService', () => { const contentService = new ContentService(null, null, null, null); const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); - documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null); + documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService); }); diff --git a/lib/content-services/document-list/services/document-list.service.spec.ts b/lib/content-services/document-list/services/document-list.service.spec.ts index b97d7dfc3d..403f0788e7 100644 --- a/lib/content-services/document-list/services/document-list.service.spec.ts +++ b/lib/content-services/document-list/services/document-list.service.spec.ts @@ -18,6 +18,7 @@ import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, StorageService, ContentService, setupTestBed, CoreModule, LogService, AppConfigServiceMock } from '@alfresco/adf-core'; import { DocumentListService } from './document-list.service'; +import { CustomResourcesService } from './custom-resources.service'; declare let jasmine: any; @@ -70,7 +71,8 @@ describe('DocumentListService', () => { const logService = new LogService(new AppConfigServiceMock(null)); const contentService = new ContentService(null, null, null, null); alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); - service = new DocumentListService(null, contentService, alfrescoApiService, logService, null); + const customActionService = new CustomResourcesService(alfrescoApiService, logService); + service = new DocumentListService(contentService, alfrescoApiService, logService, customActionService); jasmine.Ajax.install(); }); diff --git a/lib/content-services/document-list/services/document-list.service.ts b/lib/content-services/document-list/services/document-list.service.ts index 7507d49fbe..8d3420df1a 100644 --- a/lib/content-services/document-list/services/document-list.service.ts +++ b/lib/content-services/document-list/services/document-list.service.ts @@ -16,26 +16,28 @@ */ import { - AlfrescoApiService, AuthenticationService, ContentService, LogService, ThumbnailService + AlfrescoApiService, ContentService, LogService, PaginationModel } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; import { NodeEntry, NodePaging } from '@alfresco/js-api'; -import { Observable, from, throwError } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { DocumentLoaderNode } from '../models/document-folder.model'; +import { Observable, from, throwError, forkJoin } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { DocumentListLoader } from '../interfaces/document-list-loader.interface'; +import { CustomResourcesService } from './custom-resources.service'; @Injectable({ providedIn: 'root' }) -export class DocumentListService { +export class DocumentListService implements DocumentListLoader { static ROOT_ID = '-root-'; - constructor(authService: AuthenticationService, - private contentService: ContentService, + constructor(private contentService: ContentService, private apiService: AlfrescoApiService, private logService: LogService, - private thumbnailService: ThumbnailService) { + private customResourcesService: CustomResourcesService) { } /** @@ -155,30 +157,31 @@ export class DocumentListService { ); } - /** - * Get thumbnail URL for the given document node. - * @param node Node to get URL for. - * @returns Thumbnail URL string - */ - getDocumentThumbnailUrl(node: NodeEntry): string { - return this.thumbnailService.getDocumentThumbnailUrl(node); + isCustomSourceService(nodeId): boolean { + return this.customResourcesService.isCustomSource(nodeId); } - /** - * Gets the icon that represents a MIME type. - * @param mimeType MIME type to get the icon for - * @returns Path to the icon file - */ - getMimeTypeIcon(mimeType: string): string { - return this.thumbnailService.getMimeTypeIcon(mimeType); + loadFolderByNodeId(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable<DocumentLoaderNode> { + if (this.customResourcesService.isCustomSource(nodeId)) { + return this.customResourcesService.loadFolderByNodeId(nodeId, pagination, includeFields).pipe( + map((result: any) => new DocumentLoaderNode(null, result)) + ); + } else { + return this.retrieveDocumentNode(nodeId, pagination, includeFields, where); + } } - /** - * Gets a default icon for MIME types with no specific icon. - * @returns Path to the icon file - */ - getDefaultMimeTypeIcon(): string { - return this.thumbnailService.getDefaultMimeTypeIcon(); + private retrieveDocumentNode(nodeId: string, pagination: PaginationModel, includeFields: string[], where?: string): Observable<DocumentLoaderNode> { + return forkJoin( + this.getFolderNode(nodeId, includeFields), + this.getFolder(null, { + maxItems: pagination.maxItems, + skipCount: pagination.skipCount, + rootFolderId: nodeId, + where: where + }, includeFields)).pipe( + map((results) => new DocumentLoaderNode(results[0], results[1])) + ); } private handleError(error: any) { diff --git a/lib/content-services/document-list/services/folder-actions.service.spec.ts b/lib/content-services/document-list/services/folder-actions.service.spec.ts index b73253c080..badb07cd34 100644 --- a/lib/content-services/document-list/services/folder-actions.service.spec.ts +++ b/lib/content-services/document-list/services/folder-actions.service.spec.ts @@ -40,7 +40,7 @@ describe('FolderActionsService', () => { const contentService = new ContentService(null, null, null, null); const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); - documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null); + documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); service = new FolderActionsService(null, documentListService, contentService, new TranslationMock()); }); From 1ecbf2503000db90fcb21d5c654c57ed162c56a6 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 13:26:47 +0000 Subject: [PATCH 020/208] fix test pck --- lib/testing/src/lib/core/browser-visibility.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/browser-visibility.ts index 7a1abcfd56..f5c4bd6226 100644 --- a/lib/testing/src/lib/core/browser-visibility.ts +++ b/lib/testing/src/lib/core/browser-visibility.ts @@ -73,11 +73,16 @@ export class BrowserVisibility { * Wait for element to not be visible */ static waitUntilElementIsNotVisible(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { + let isPresent = false; return browser.wait(() => { browser.waitForAngularEnabled(); - return elementToCheck.isPresent().then(function (present) { - return !present; - }); + + elementToCheck.isPresent().then( + (present) => { + isPresent = !present; + } + ); + return isPresent; }, waitTimeout, 'Element is Visible and it should not' + elementToCheck.locator()); } From 31280baeef28aafd915d39be6d7bb72d897e93de Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Wed, 27 Mar 2019 16:08:45 +0000 Subject: [PATCH 021/208] [ADF-4298] Add e2e tests for info drawer (#4506) * [ADF-4298] Add e2e tests for info drawer * Update info-drawer.component.e2e.ts * Update info-drawer.component.e2e.ts --- .../file-view/file-view.component.html | 19 +++- .../file-view/file-view.component.ts | 5 + e2e/core/viewer/info-drawer.component.e2e.ts | 103 ++++++++++++++++++ e2e/pages/adf/viewerPage.ts | 35 ++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 e2e/core/viewer/info-drawer.component.e2e.ts diff --git a/demo-shell/src/app/components/file-view/file-view.component.html b/demo-shell/src/app/components/file-view/file-view.component.html index 0fa9cb5a31..b9567ce0b6 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.html +++ b/demo-shell/src/app/components/file-view/file-view.component.html @@ -105,7 +105,7 @@ <ng-template let-node="node" #sidebarLeftTemplate> <adf-info-drawer [title]="'Viewer Options'"> - <adf-info-drawer-tab [label]=""> + <adf-info-drawer-tab [label]="'Settings'"> <p class="toggle"> <mat-slide-toggle id="adf-switch-custoname" @@ -248,6 +248,16 @@ </mat-slide-toggle> </p> + <p class="toggle"> + <mat-slide-toggle + id="adf-show-tab-with-icon" + [color]="'primary'" + (change)="toggleShowInfoDrawerTabIcon()" + [checked]="showInfoDrawerTabWithIcon"> + Show info drawer tab con + </mat-slide-toggle> + </p> + <p class="toggle"> <button mat-raised-button id="adf-switch-showrightsidebar" (click)="toggleShowRightSidebar()" color="primary"> Toggle Right Sidebar @@ -262,6 +272,13 @@ </adf-info-drawer-tab> + <adf-info-drawer-tab + *ngIf="showInfoDrawerTabWithIcon" + [label]="'Settings'" + [icon]="'comment'" + data-automation-id="adf-settings-tab"> + </adf-info-drawer-tab> + </adf-info-drawer> </ng-template> diff --git a/demo-shell/src/app/components/file-view/file-view.component.ts b/demo-shell/src/app/components/file-view/file-view.component.ts index 2fcb5aa68c..d7c163090a 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.ts +++ b/demo-shell/src/app/components/file-view/file-view.component.ts @@ -53,6 +53,7 @@ export class FileViewComponent implements OnInit { showRightSidebar = false; customToolbar = false; isCommentEnabled = false; + showInfoDrawerTabWithIcon = false; constructor(private router: Router, private route: ActivatedRoute, @@ -145,6 +146,10 @@ export class FileViewComponent implements OnInit { this.allowLeftSidebar = !this.allowLeftSidebar; } + toggleShowInfoDrawerTabIcon() { + this.showInfoDrawerTabWithIcon = !this.showInfoDrawerTabWithIcon; + } + toggleCustomName() { this.customName = !this.customName; diff --git a/e2e/core/viewer/info-drawer.component.e2e.ts b/e2e/core/viewer/info-drawer.component.e2e.ts new file mode 100644 index 0000000000..065d8079de --- /dev/null +++ b/e2e/core/viewer/info-drawer.component.e2e.ts @@ -0,0 +1,103 @@ +/*! + * @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 TestConfig = require('../../test.config'); + +import { LoginPage } from '../../pages/adf/loginPage'; +import { ViewerPage } from '../../pages/adf/viewerPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../util/constants'); +import resources = require('../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FileModel } from '../../models/ACS/fileModel'; +import { AcsUserModel } from '../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../actions/ACS/upload.actions'; + +describe('Info Drawer', () => { + + let viewerPage = new ViewerPage(); + let navigationBarPage = new NavigationBarPage(); + let loginPage = new LoginPage(); + let contentServicesPage = new ContentServicesPage(); + let uploadActions = new UploadActions(); + let site; + let acsUser = new AcsUserModel(); + let pngFileUploaded; + + let pngFileInfo = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + pngFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileInfo.location, pngFileInfo.name, site.entry.guid); + done(); + }); + + it('[C277251] Should display only the icon when the icon property is defined', () => { + loginPage.loginToContentServicesUsingUserModel(acsUser); + + navigationBarPage.goToSite(site); + contentServicesPage.checkAcsContainer(); + + viewerPage.viewFile(pngFileUploaded.entry.name); + viewerPage.clickLeftSidebarButton(); + viewerPage.enableShowTabWithIcon(); + viewerPage.checkTabHasIcon(1); + expect(viewerPage.getTabLabelById(1)).not.toBe('COMMENT'); + expect(viewerPage.getTabIconById(1)).toBe('comment'); + }); + + it('[C277252] Should display the label when the icon property is not defined', () => { + loginPage.loginToContentServicesUsingUserModel(acsUser); + + navigationBarPage.goToSite(site); + contentServicesPage.checkAcsContainer(); + + viewerPage.viewFile(pngFileUploaded.entry.name); + viewerPage.clickLeftSidebarButton(); + viewerPage.enableShowTabWithIcon(); + viewerPage.checkTabHasNoIcon(0); + expect(viewerPage.getTabLabelById(0)).toBe('SETTINGS'); + }); +}); diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index a56b7f7acc..414d6e7811 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -64,6 +64,7 @@ export class ViewerPage { lastButton = element.all(by.css('#adf-viewer-toolbar mat-toolbar > button[data-automation-id*="adf-toolbar-"]')).last(); datatableHeader = element(by.css('div.adf-datatable-header')); goBackSwitch = element(by.id('adf-switch-goback')); + tabLabel = element(by.css('div[class="mat-tab-label-content"]')); openWithSwitch = element(by.id('adf-switch-openwith')); openWith = element(by.id('adf-viewer-openwith')); @@ -97,6 +98,8 @@ export class ViewerPage { codeViewer = element(by.id('adf-monaco-file-editor')); moveRightChevron = element(by.css('.mat-tab-header-pagination-after .mat-tab-header-pagination-chevron')); + showTabWithIconSwitch = element(by.id('adf-show-tab-with-icon')); + checkCodeViewerIsDisplayed() { return BrowserVisibility.waitUntilElementIsVisible(this.codeViewer); } @@ -502,6 +505,14 @@ export class ViewerPage { this.formControllersPage.enableToggle(this.openWithSwitch); } + disableShowTabWithIcon() { + this.formControllersPage.disableToggle(this.showTabWithIconSwitch); + } + + enableShowTabWithIcon() { + this.formControllersPage.enableToggle(this.showTabWithIconSwitch); + } + checkDownloadButtonDisplayed() { BrowserVisibility.waitUntilElementIsVisible(this.downloadButton); return this; @@ -625,4 +636,28 @@ export class ViewerPage { BrowserVisibility.waitUntilElementIsVisible(this.moveRightChevron); return this.moveRightChevron.click(); } + + checkTabHasIcon(index: number) { + const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] mat-icon`)); + Util.waitUntilElementIsVisible(tab); + return this; + } + + checkTabHasNoIcon(index: number) { + const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] mat-icon`)); + Util.waitUntilElementIsNotVisible(tab); + return this; + } + + getTabLabelById(index: number) { + const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"]`)); + Util.waitUntilElementIsVisible(tab); + return tab.getText(); + } + + getTabIconById(index: number) { + const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] mat-icon`)); + Util.waitUntilElementIsVisible(tab); + return tab.getText(); + } } From cb9614bb38bd6a2f632ff1216bdaa551216502fc Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Wed, 27 Mar 2019 16:51:48 +0000 Subject: [PATCH 022/208] add missing document list host class --- .../document-list/components/document-list.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/content-services/document-list/components/document-list.component.ts b/lib/content-services/document-list/components/document-list.component.ts index 5484758c3d..a502de37c8 100644 --- a/lib/content-services/document-list/components/document-list.component.ts +++ b/lib/content-services/document-list/components/document-list.component.ts @@ -63,7 +63,8 @@ import { DocumentLoaderNode } from '../models/document-folder.model'; selector: 'adf-document-list', styleUrls: ['./document-list.component.scss'], templateUrl: './document-list.component.html', - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, + host: { class: '.adf-document-list' } }) export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, AfterContentInit, PaginatedComponent, NavigableComponentInterface { From e9d2be808ec7219b7acbd1c7a753492aeaa13580 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 20:10:20 +0000 Subject: [PATCH 023/208] fix utility viewer page --- e2e/pages/adf/viewerPage.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index 414d6e7811..db34002801 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -639,25 +639,25 @@ export class ViewerPage { checkTabHasIcon(index: number) { const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] mat-icon`)); - Util.waitUntilElementIsVisible(tab); + BrowserVisibility.waitUntilElementIsVisible(tab); return this; } checkTabHasNoIcon(index: number) { const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] mat-icon`)); - Util.waitUntilElementIsNotVisible(tab); + BrowserVisibility.waitUntilElementIsNotVisible(tab); return this; } getTabLabelById(index: number) { const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"]`)); - Util.waitUntilElementIsVisible(tab); + BrowserVisibility.waitUntilElementIsVisible(tab); return tab.getText(); } getTabIconById(index: number) { const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] mat-icon`)); - Util.waitUntilElementIsVisible(tab); + BrowserVisibility.waitUntilElementIsVisible(tab); return tab.getText(); } } From 3943eeb8b2547f6230f5c90753340e7bad520ef2 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 27 Mar 2019 20:14:07 +0000 Subject: [PATCH 024/208] fix lint --- e2e/core/viewer/info-drawer.component.e2e.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/core/viewer/info-drawer.component.e2e.ts b/e2e/core/viewer/info-drawer.component.e2e.ts index 065d8079de..6b3194fd76 100644 --- a/e2e/core/viewer/info-drawer.component.e2e.ts +++ b/e2e/core/viewer/info-drawer.component.e2e.ts @@ -34,16 +34,16 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; describe('Info Drawer', () => { - let viewerPage = new ViewerPage(); - let navigationBarPage = new NavigationBarPage(); - let loginPage = new LoginPage(); - let contentServicesPage = new ContentServicesPage(); - let uploadActions = new UploadActions(); + const viewerPage = new ViewerPage(); + const navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); let site; - let acsUser = new AcsUserModel(); + const acsUser = new AcsUserModel(); let pngFileUploaded; - let pngFileInfo = new FileModel({ + const pngFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); From 7f5bcdf40745e932db13413870181b08409fc3fc Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Thu, 28 Mar 2019 10:55:51 +0000 Subject: [PATCH 025/208] fix lint --- e2e/pages/adf/settingsPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/pages/adf/settingsPage.ts b/e2e/pages/adf/settingsPage.ts index d762aec933..653396ea5a 100644 --- a/e2e/pages/adf/settingsPage.ts +++ b/e2e/pages/adf/settingsPage.ts @@ -173,7 +173,7 @@ export class SettingsPage { } async setLogoutUrl(logoutUrl) { - Util.waitUntilElementIsPresent(this.logoutUrlText); + BrowserVisibility.waitUntilElementIsPresent(this.logoutUrlText); this.logoutUrlText.clear(); this.logoutUrlText.sendKeys(logoutUrl); } From 49847bf8093042316b0ab4f9825cbb2d66aea318 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Thu, 28 Mar 2019 11:05:57 +0000 Subject: [PATCH 026/208] fix lint --- e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts b/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts index a6d0b12686..988da9d5e8 100644 --- a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts +++ b/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts @@ -180,7 +180,7 @@ export class EditTaskFilterCloudComponent { } clickSaveAsButton() { - let disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); + const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); BrowserVisibility.waitUntilElementIsClickable(this.saveAsButton); BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); From b51fc8a7d21ce0f1613de9d03f1a9a31764b0cae Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Fri, 29 Mar 2019 09:14:36 +0000 Subject: [PATCH 027/208] document list extensions (demo shell) (#4511) * doclist extensibility test page * desktopOnly support * extensions category, custom column * update code * Fix styling for column templates * update package lock --- demo-shell/src/app/app.routes.ts | 5 + .../app-layout/app-layout.component.ts | 5 + .../extension-presets.component.html | 46 +++++++ .../extension-presets.component.ts | 61 +++++++++ .../extension-presets.module.ts | 56 ++++++++ .../name-column/name-column.component.ts | 95 ++++++++++++++ demo-shell/src/assets/app.extensions.json | 48 +++++++ .../library-name-column.component.ts | 2 +- .../library-role-column.component.ts | 2 +- .../library-status-column.component.ts | 2 +- .../name-column/name-column.component.ts | 2 +- .../trashcan-name-column.component.ts | 4 +- .../src/lib/services/app-extension.service.ts | 16 ++- package-lock.json | 120 +++++++++++------- 14 files changed, 414 insertions(+), 50 deletions(-) create mode 100644 demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.html create mode 100644 demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.ts create mode 100644 demo-shell/src/app/components/document-list/extension-presets/extension-presets.module.ts create mode 100644 demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 02ad2ba0b6..e31c401dc0 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -223,6 +223,11 @@ export const appRoutes: Routes = [ component: FilesComponent, canActivate: [AuthGuardEcm] }, + { + path: 'extensions/document-list/presets', + canActivate: [AuthGuardEcm], + loadChildren: './components/document-list/extension-presets/extension-presets.module#ExtensionPresetsModule' + }, { path: 'files/:id', component: FilesComponent, diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index ebb65ba3fe..5a732acda3 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -32,6 +32,11 @@ export class AppLayoutComponent implements OnInit { links: Array<any> = [ { href: '/home', icon: 'home', title: 'APP_LAYOUT.HOME' }, + { + href: '/extensions', icon: 'extension', title: 'Extensions', children: [ + { href: '/extensions/document-list/presets', icon: 'extension', title: 'Document List' } + ] + }, { href: '/files', icon: 'folder_open', title: 'APP_LAYOUT.CONTENT_SERVICES' }, { href: '/breadcrumb', icon: 'label', title: 'APP_LAYOUT.BREADCRUMB' }, { href: '/notifications', icon: 'alarm', title: 'APP_LAYOUT.NOTIFICATIONS' }, diff --git a/demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.html b/demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.html new file mode 100644 index 0000000000..29330acc92 --- /dev/null +++ b/demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.html @@ -0,0 +1,46 @@ +<adf-document-list + currentFolderId="-my-" + [navigate]="false"> + <data-columns> + <ng-container *ngFor="let column of columns; trackBy: trackById"> + <ng-container + *ngIf=" + column.template && !(column.desktopOnly && isSmallScreen) + " + > + <data-column + [key]="column.key" + [title]="column.title" + [type]="column.type" + [format]="column.format" + [class]="column.class" + [sortable]="column.sortable" + > + <ng-template let-context> + <adf-dynamic-column + [id]="column.template" + [context]="context" + > + </adf-dynamic-column> + </ng-template> + </data-column> + </ng-container> + + <ng-container + *ngIf=" + !column.template && !(column.desktopOnly && isSmallScreen) + " + > + <data-column + [key]="column.key" + [title]="column.title" + [type]="column.type" + [format]="column.format" + [class]="column.class" + [sortable]="column.sortable" + > + </data-column> + </ng-container> + </ng-container> + </data-columns> +</adf-document-list> diff --git a/demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.ts b/demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.ts new file mode 100644 index 0000000000..027bc0cab9 --- /dev/null +++ b/demo-shell/src/app/components/document-list/extension-presets/extension-presets.component.ts @@ -0,0 +1,61 @@ +/*! + * @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, OnInit, OnDestroy } from '@angular/core'; +import { AppExtensionService } from '@alfresco/adf-extensions'; +import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-extension-presets', + templateUrl: './extension-presets.component.html' +}) +export class ExtensionPresetsComponent implements OnInit, OnDestroy { + onDestroy$ = new Subject<boolean>(); + + columns: any[] = []; + isSmallScreen = false; + + constructor( + private extensions: AppExtensionService, + private breakpointObserver: BreakpointObserver + ) {} + + ngOnInit() { + this.columns = this.extensions.getDocumentListPreset('files'); + + this.breakpointObserver + .observe([ + Breakpoints.HandsetPortrait, + Breakpoints.HandsetLandscape + ]) + .pipe(takeUntil(this.onDestroy$)) + .subscribe((result) => { + this.isSmallScreen = result.matches; + }); + } + + ngOnDestroy() { + this.onDestroy$.next(true); + this.onDestroy$.complete(); + } + + trackById(index: number, obj: { id: string }) { + return obj.id; + } +} diff --git a/demo-shell/src/app/components/document-list/extension-presets/extension-presets.module.ts b/demo-shell/src/app/components/document-list/extension-presets/extension-presets.module.ts new file mode 100644 index 0000000000..c6c8c9006b --- /dev/null +++ b/demo-shell/src/app/components/document-list/extension-presets/extension-presets.module.ts @@ -0,0 +1,56 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { CoreModule } from '@alfresco/adf-core'; +import { ContentModule } from '@alfresco/adf-content-services'; +import { ExtensionPresetsComponent } from './extension-presets.component'; +import { ExtensionsModule, ExtensionService } from '@alfresco/adf-extensions'; +import { NameColumnComponent } from './name-column/name-column.component'; + +const routes: Routes = [ + { + path: '', + component: ExtensionPresetsComponent + } +]; + +@NgModule({ + imports: [ + CommonModule, + CoreModule.forChild(), + RouterModule.forChild(routes), + ContentModule.forChild(), + ExtensionsModule.forChild() + ], + declarations: [ + ExtensionPresetsComponent, + NameColumnComponent + ], + entryComponents: [ + NameColumnComponent + ] +}) +export class ExtensionPresetsModule { + constructor(extensionService: ExtensionService) { + extensionService.setComponents({ + 'app.columns.name': NameColumnComponent + }); + } +} diff --git a/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts b/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts new file mode 100644 index 0000000000..938c53d450 --- /dev/null +++ b/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts @@ -0,0 +1,95 @@ +/*! + * @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, + OnInit, + ChangeDetectionStrategy, + ViewEncapsulation, + ElementRef, + OnDestroy +} from '@angular/core'; +import { NodeEntry } from '@alfresco/js-api'; +import { BehaviorSubject, Subscription } from 'rxjs'; +import { AlfrescoApiService } from '@alfresco/adf-core'; +import { Node } from '@alfresco/js-api'; + +@Component({ + selector: 'app-name-column', + template: ` + <span class="adf-datatable-cell-value" title="{{ node | adfNodeNameTooltip }}" (click)="onClick()"> + {{ displayText$ | async }} + </span> + `, + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + host: { class: 'adf-datatable-cell adf-datatable-link adf-name-column' } +}) +export class NameColumnComponent implements OnInit, OnDestroy { + @Input() + context: any; + + displayText$ = new BehaviorSubject<string>(''); + node: NodeEntry; + + private sub: Subscription; + + constructor(private element: ElementRef, private alfrescoApiService: AlfrescoApiService) {} + + ngOnInit() { + this.updateValue(); + + this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => { + const row = this.context.row; + if (row) { + const { entry } = row.node; + + if (entry === node) { + row.node = { entry }; + this.updateValue(); + } + } + }); + } + + protected updateValue() { + this.node = this.context.row.node; + + if (this.node && this.node.entry) { + this.displayText$.next(this.node.entry.name || this.node.entry.id); + } + } + + onClick() { + this.element.nativeElement.dispatchEvent( + new CustomEvent('name-click', { + bubbles: true, + detail: { + node: this.node + } + }) + ); + } + + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + this.sub = null; + } + } +} diff --git a/demo-shell/src/assets/app.extensions.json b/demo-shell/src/assets/app.extensions.json index 6b2338374f..dd2638a6a2 100644 --- a/demo-shell/src/assets/app.extensions.json +++ b/demo-shell/src/assets/app.extensions.json @@ -10,6 +10,54 @@ "features": { "viewer": { "content": [] + }, + + "documentList": { + "files": [ + { + "id": "app.files.thumbnail", + "key": "$thumbnail", + "type": "image", + "sortable": false, + "desktopOnly": false + }, + { + "id": "app.files.name", + "key": "name", + "title": "Name", + "type": "text", + "class": "adf-ellipsis-cell adf-expand-cell-5", + "sortable": true, + "template": "app.columns.name", + "desktopOnly": false + }, + { + "id": "app.files.size", + "key": "content.sizeInBytes", + "title": "Size", + "type": "fileSize", + "sortable": true, + "desktopOnly": true + }, + { + "id": "app.files.modifiedOn", + "key": "modifiedAt", + "title": "Modified on", + "type": "date", + "format": "timeAgo", + "sortable": true, + "desktopOnly": true + }, + { + "id": "app.files.modifiedBy", + "key": "modifiedByUser.displayName", + "title": "Modified by", + "type": "text", + "class": "adf-ellipsis-cell", + "sortable": true, + "desktopOnly": true + } + ] } } } diff --git a/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts b/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts index a5b3f65595..712fe08e7a 100644 --- a/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts +++ b/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts @@ -32,7 +32,7 @@ import { BehaviorSubject, Subscription } from 'rxjs'; @Component({ selector: 'adf-library-name-column', template: ` - <span title="{{ displayTooltip$ | async }}" (click)="onClick()"> + <span class="adf-datatable-cell-value" title="{{ displayTooltip$ | async }}" (click)="onClick()"> {{ displayText$ | async }} </span> `, diff --git a/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts b/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts index 39817101ce..90a431efcb 100644 --- a/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts +++ b/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts @@ -31,7 +31,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; @Component({ selector: 'adf-library-role-column', template: ` - <span title="{{ (displayText$ | async) | translate }}"> + <span class="adf-datatable-cell-value" title="{{ (displayText$ | async) | translate }}"> {{ (displayText$ | async) | translate }} </span> `, diff --git a/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts b/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts index 579d5aa62a..5b009ebe42 100644 --- a/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts +++ b/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts @@ -24,7 +24,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; @Component({ selector: 'adf-library-status-column', template: ` - <span title="{{ (displayText$ | async) | translate }}"> + <span class="adf-datatable-cell-value" title="{{ (displayText$ | async) | translate }}"> {{ (displayText$ | async) | translate }} </span> `, diff --git a/lib/content-services/document-list/components/name-column/name-column.component.ts b/lib/content-services/document-list/components/name-column/name-column.component.ts index 824e3cb0b6..ad093d99cf 100644 --- a/lib/content-services/document-list/components/name-column/name-column.component.ts +++ b/lib/content-services/document-list/components/name-column/name-column.component.ts @@ -33,7 +33,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; @Component({ selector: 'adf-name-column', template: ` - <span title="{{ node | adfNodeNameTooltip }}" (click)="onClick()"> + <span class="adf-datatable-cell-value" title="{{ node | adfNodeNameTooltip }}" (click)="onClick()"> {{ displayText$ | async }} </span> `, diff --git a/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts b/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts index 2a45927267..d2dae7a225 100644 --- a/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts +++ b/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts @@ -29,10 +29,10 @@ import { ShareDataRow } from '../../data/share-data-row.model'; selector: 'adf-trashcan-name-column', template: ` <ng-container *ngIf="!isLibrary"> - <span title="{{ node | adfNodeNameTooltip }}">{{ displayText }}</span> + <span class="adf-datatable-cell-value" title="{{ node | adfNodeNameTooltip }}">{{ displayText }}</span> </ng-container> <ng-container *ngIf="isLibrary"> - <span title="{{ displayTooltip }}">{{ displayText }}</span> + <span class="adf-datatable-cell-value" title="{{ displayTooltip }}">{{ displayText }}</span> </ng-container> `, changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/lib/extensions/src/lib/services/app-extension.service.ts b/lib/extensions/src/lib/services/app-extension.service.ts index 9b83b7e253..5da3d61b9a 100644 --- a/lib/extensions/src/lib/services/app-extension.service.ts +++ b/lib/extensions/src/lib/services/app-extension.service.ts @@ -20,6 +20,7 @@ import { ExtensionConfig, ExtensionRef } from '../config/extension.config'; import { ExtensionService } from '../services/extension.service'; import { Observable, BehaviorSubject } from 'rxjs'; import { ViewerExtensionRef } from '../config/viewer.extensions'; +import { DocumentListPresetRef } from '../config/document-list.extensions'; @Injectable({ providedIn: 'root' @@ -49,9 +50,22 @@ export class AppExtensionService { this._references.next(references); } + /** + * Provides a collection of document list columns for the particular preset. + * The result is filtered by the **disabled** state. + * @param key Preset key. + */ + getDocumentListPreset(key: string) { + return this.extensionService + .getElements<DocumentListPresetRef>( + `features.documentList.${key}` + ) + .filter((entry) => !entry.disabled); + } + /** * Provides a list of the Viewer content extensions, - * filtered by disabled state and rules. + * filtered by **disabled** state and **rules**. */ getViewerExtensions(): ViewerExtensionRef[] { return this.extensionService diff --git a/package-lock.json b/package-lock.json index af7b38a6b5..7f2abe3339 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,61 +1,61 @@ { "name": "alfresco-components", - "version": "3.2.0-beta1", + "version": "3.2.0-beta2", "lockfileVersion": 1, "requires": true, "dependencies": { "@alfresco/adf-content-services": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta1.tgz", - "integrity": "sha512-IDMvGc9gFMkBuIuvP9pM7WhpWGXTbKGl/Wy/v8ZQUQJKqI+/frDBJLCer1oct22Mw2H+pq9NzAAmHqGOiqh3cw==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta2.tgz", + "integrity": "sha512-1VKsXquJjtWXFcuMmhAbhM2eqcDXWpI28ZFEnE6zOLrRF4qqUyDCEpPTAjfnGcd503rAzT0IKiNftfRzcgphnA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-core": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta1.tgz", - "integrity": "sha512-tWdC2ht65MTcPBn2ILqRTy9T8MbXv5hzJIxzEOqoOSLf1pbuyGBN2dI6vWPzmtbZeLTMJg6B5DMeyHykxJHYkQ==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta2.tgz", + "integrity": "sha512-swIk99PpbTWObq63Dct1kQz+YHLuJ6J+RZu/bkwJkxodATkcpLQcPPO0l7bdMN2/uYduI5vD9zy8Pm6Ssg9izQ==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-extensions": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta1.tgz", - "integrity": "sha512-hkgQ97t/jZYTv1COhjt3RVONF8HmXM9Uo7/fvDDbGoac+hc2nJbQCWKdIwysZwkglHHbBRZSj/DVwppbKuNroQ==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta2.tgz", + "integrity": "sha512-vvT5lO8Jk9hQF9Ky2S6sZKu9w8KDeTHPJhJ/w12z7xN5FybWLuDP8kXVN0UDKplJe6mSPBsMJ0uU0OwLTK/qvA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-insights": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta1.tgz", - "integrity": "sha512-9bXFrCCzYbD1/mB7KIwrFKqLBx5UCEZ0+V3+MIpbJRprOU5iTlvzim1uNFbvJX8TNoHi2trEADo+0uSo7F+Zog==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta2.tgz", + "integrity": "sha512-Jgq76LO3/4+6xkfha0tHWAZKv/EYe0DhdmdNMCzRtJXZlWi63mADA4hcWpwGApw7Gnn80o28TojJ8LGWfYD3Cw==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta1.tgz", - "integrity": "sha512-ljFWeaUn12x5MYBIBk1fEMqtFZJWZk32ivpuxpVMjiKrL55ryxrzSnc6SNddJMpcm1l6wXdO+ljygSUr3yhcDA==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta2.tgz", + "integrity": "sha512-CiCMctQPbRKDYq2UzobSZ/vu0eKLxAvcIxzi8q0up1qOwhEjK/EJ5vpjzsuJ2pJpvjInIWd5iMFLQD02O84Dnw==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services-cloud": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta1.tgz", - "integrity": "sha512-yV1V4UzEgaqvbiqFo/m8/bMeiTzWHV9PodaqV9T7j1tDkrf+QFpvWIf/eXpXRtTOqdFZbt2ojcZLEd7drOgM4g==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta2.tgz", + "integrity": "sha512-EJVNgbtTHeSTMpg4YdZvVthSmNkG+wA2K5JYfxCayj6jJfFCe0ykyr1g6Z+DmbkfhxOQpgsaR651uya2XdvIbQ==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-testing": { - "version": "3.2.0-beta1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta1.tgz", - "integrity": "sha512-EL9hmTsCqSNXe4EK0lIw1XUy1utL0ooNltsafr4nsAUI5sFNUbWC/UZynmBv9fLvTGIe4Fd3ubDZgnBNBUNtSw==", + "version": "3.2.0-beta2", + "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta2.tgz", + "integrity": "sha512-OdQ9QXrwWF0ZE1z6QBJV912pgL0quEph/BMUeMBExMDZjRMW0FF53Rucbul5C6yDu5OpRaHVwYCmJDaAC1D+KQ==", "requires": { "tslib": "^1.9.0" } @@ -2880,6 +2880,7 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -3543,7 +3544,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", - "dev": true + "dev": true, + "optional": true }, "buffer-xor": { "version": "1.0.3", @@ -6790,7 +6792,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6811,12 +6814,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6831,17 +6836,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6958,7 +6966,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6970,6 +6979,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6984,6 +6994,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -6991,12 +7002,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7015,6 +7028,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -7095,7 +7109,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -7107,6 +7122,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -7192,7 +7208,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7228,6 +7245,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7247,6 +7265,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7290,12 +7309,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -8062,7 +8083,8 @@ "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true + "dev": true, + "optional": true }, "homedir-polyfill": { "version": "1.0.3", @@ -8225,6 +8247,7 @@ "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, + "optional": true, "requires": { "httpreq": ">=0.4.22", "underscore": "~1.7.0" @@ -8234,7 +8257,8 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true + "dev": true, + "optional": true }, "https-browserify": { "version": "1.0.0", @@ -9135,7 +9159,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true + "dev": true, + "optional": true }, "is-redirect": { "version": "1.0.0", @@ -10068,13 +10093,15 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true + "dev": true, + "optional": true }, "libmime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, + "optional": true, "requires": { "iconv-lite": "0.4.15", "libbase64": "0.1.0", @@ -10085,7 +10112,8 @@ "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true + "dev": true, + "optional": true } } }, @@ -10093,7 +10121,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true + "dev": true, + "optional": true }, "license-checker": { "version": "25.0.1", @@ -12158,13 +12187,15 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true + "dev": true, + "optional": true }, "nodemailer-shared": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", "dev": true, + "optional": true, "requires": { "nodemailer-fetch": "1.6.0" } @@ -12197,7 +12228,8 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true + "dev": true, + "optional": true }, "nopt": { "version": "3.0.6", @@ -15788,6 +15820,7 @@ "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", "dev": true, + "optional": true, "requires": { "httpntlm": "1.6.1", "nodemailer-shared": "1.1.0" @@ -17867,7 +17900,8 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true + "dev": true, + "optional": true }, "unherit": { "version": "1.1.1", From f0e993512bdd4f1cf3b798d3a7a3db78daec8cbb Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Fri, 29 Mar 2019 10:02:22 +0000 Subject: [PATCH 028/208] update versions --- demo-shell/package.json | 2 +- lib/content-services/package.json | 4 ++-- lib/core/package.json | 2 +- lib/extensions/package.json | 2 +- lib/insights/package.json | 6 +++--- lib/process-services-cloud/package.json | 4 ++-- lib/process-services/package.json | 6 +++--- lib/testing/package.json | 2 +- package.json | 16 ++++++++-------- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/demo-shell/package.json b/demo-shell/package.json index 53b3b58cae..5fa80ae451 100644 --- a/demo-shell/package.json +++ b/demo-shell/package.json @@ -1,7 +1,7 @@ { "name": "Alfresco-ADF-Angular-Demo", "description": "Demo shell for Alfresco Angular components", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "repository": { "type": "git", diff --git a/lib/content-services/package.json b/lib/content-services/package.json index c7d97c8bf5..bfe902b468 100644 --- a/lib/content-services/package.json +++ b/lib/content-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-content-services", "description": "Alfresco ADF content services", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-content-services.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta2", + "@alfresco/adf-core": "3.2.0-beta3", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/core/package.json b/lib/core/package.json index b9cf8016d0..29b908079e 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-core", "description": "Alfresco ADF core", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-core.js", "repository": { diff --git a/lib/extensions/package.json b/lib/extensions/package.json index afa49f054d..cf33e8ab18 100644 --- a/lib/extensions/package.json +++ b/lib/extensions/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-extensions", "description": "Provides extensibility support for ADF applications.", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-extensions.js", "repository": { diff --git a/lib/insights/package.json b/lib/insights/package.json index 03d6e60c3d..19a820c028 100644 --- a/lib/insights/package.json +++ b/lib/insights/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-insights", "description": "Alfresco ADF insights", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-insights.js", "repository": { @@ -27,8 +27,8 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta2", - "@alfresco/adf-content-services": "3.2.0-beta2", + "@alfresco/adf-core": "3.2.0-beta3", + "@alfresco/adf-content-services": "3.2.0-beta3", "@ngx-translate/core": ">=11.0.0", "chart.js": ">=2.5.0", "core-js": ">=2.5.4", diff --git a/lib/process-services-cloud/package.json b/lib/process-services-cloud/package.json index e20da3818c..aadc27e991 100644 --- a/lib/process-services-cloud/package.json +++ b/lib/process-services-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services-cloud", "description": "Alfresco ADF process services cloud", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services-cloud.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta2", + "@alfresco/adf-core": "3.2.0-beta3", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/process-services/package.json b/lib/process-services/package.json index a3f59bceb7..90083b7da3 100644 --- a/lib/process-services/package.json +++ b/lib/process-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services", "description": "Alfresco ADF process services", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services.js", "repository": { @@ -27,8 +27,8 @@ "@angular/router": ">=7.0.3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta2", - "@alfresco/adf-content-services": "3.2.0-beta2", + "@alfresco/adf-core": "3.2.0-beta3", + "@alfresco/adf-content-services": "3.2.0-beta3", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", "hammerjs": ">=2.0.8", diff --git a/lib/testing/package.json b/lib/testing/package.json index 52ade059b1..dbc94d89b0 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,6 +1,6 @@ { "name": "@alfresco/adf-testing", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0", diff --git a/package.json b/package.json index 4493b98764..3bd43b8c75 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alfresco-components", "description": "Alfresco Angular components", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "author": "Alfresco Software, Ltd.", "main": "./index.js", "scripts": { @@ -55,13 +55,13 @@ "process services-cloud" ], "dependencies": { - "@alfresco/adf-content-services": "3.2.0-beta2", - "@alfresco/adf-core": "3.2.0-beta2", - "@alfresco/adf-extensions": "3.2.0-beta2", - "@alfresco/adf-insights": "3.2.0-beta2", - "@alfresco/adf-process-services": "3.2.0-beta2", - "@alfresco/adf-process-services-cloud": "3.2.0-beta2", - "@alfresco/adf-testing": "3.2.0-beta2", + "@alfresco/adf-content-services": "3.2.0-beta3", + "@alfresco/adf-core": "3.2.0-beta3", + "@alfresco/adf-extensions": "3.2.0-beta3", + "@alfresco/adf-insights": "3.2.0-beta3", + "@alfresco/adf-process-services": "3.2.0-beta3", + "@alfresco/adf-process-services-cloud": "3.2.0-beta3", + "@alfresco/adf-testing": "3.2.0-beta3", "@alfresco/js-api": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", "@angular/animations": "7.0.3", "@angular/cdk": "7.0.3", From e225afef1a7e7de225751e9a86732936f4229c30 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Fri, 29 Mar 2019 11:19:14 +0000 Subject: [PATCH 029/208] fix package lock --- package-lock.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f2abe3339..27b0a87c91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,61 +1,61 @@ { "name": "alfresco-components", - "version": "3.2.0-beta2", + "version": "3.2.0-beta3", "lockfileVersion": 1, "requires": true, "dependencies": { "@alfresco/adf-content-services": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta2.tgz", - "integrity": "sha512-1VKsXquJjtWXFcuMmhAbhM2eqcDXWpI28ZFEnE6zOLrRF4qqUyDCEpPTAjfnGcd503rAzT0IKiNftfRzcgphnA==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta3.tgz", + "integrity": "sha512-OVPpclIBbJjFmRPXD8fGGBk0t7i6Avz3Xuk/DjgxFZfJdJDEb+it2KSPR4wT38NZS95vJHtB6TCfh76rMQJzHQ==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-core": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta2.tgz", - "integrity": "sha512-swIk99PpbTWObq63Dct1kQz+YHLuJ6J+RZu/bkwJkxodATkcpLQcPPO0l7bdMN2/uYduI5vD9zy8Pm6Ssg9izQ==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta3.tgz", + "integrity": "sha512-lT7c9QYatJS4x3oAupgiASCGvzQyowZWBoYu32YctS/F6876QAPPaegjkRxqitWjfvs7aXRaCYydb5BoDeLkRg==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-extensions": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta2.tgz", - "integrity": "sha512-vvT5lO8Jk9hQF9Ky2S6sZKu9w8KDeTHPJhJ/w12z7xN5FybWLuDP8kXVN0UDKplJe6mSPBsMJ0uU0OwLTK/qvA==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta3.tgz", + "integrity": "sha512-TEguuRhzbj6cAeawLJqcK0o8lNzeRO7Pmw9Paxeu9m5RtQEPfvwGydDrlDGWnJ3H5Xx8byxhERIgdOfuK2SWTg==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-insights": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta2.tgz", - "integrity": "sha512-Jgq76LO3/4+6xkfha0tHWAZKv/EYe0DhdmdNMCzRtJXZlWi63mADA4hcWpwGApw7Gnn80o28TojJ8LGWfYD3Cw==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta3.tgz", + "integrity": "sha512-19zsI39GREZ6fzvs+4fw0FktMSLz6qSq8P2+QTRUThvtL1KZFLeW76BEZPX19YG/K0OuQvuLTXKt2tsf1CChRw==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta2.tgz", - "integrity": "sha512-CiCMctQPbRKDYq2UzobSZ/vu0eKLxAvcIxzi8q0up1qOwhEjK/EJ5vpjzsuJ2pJpvjInIWd5iMFLQD02O84Dnw==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta3.tgz", + "integrity": "sha512-rwJLBrrRI+ndHa7H+RMMlLtbs44yR4Y1pMOCnfchqtGD1m7G/D2g/n5WHo7fp832rU8RP3yw/ZEz4WzMZuxcfA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services-cloud": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta2.tgz", - "integrity": "sha512-EJVNgbtTHeSTMpg4YdZvVthSmNkG+wA2K5JYfxCayj6jJfFCe0ykyr1g6Z+DmbkfhxOQpgsaR651uya2XdvIbQ==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta3.tgz", + "integrity": "sha512-j0QWbMBvGN/zRfI0L7V+uXQvY8pSBnOsvBpUEh889WPlf/XWacfKC+a08/UHH5l0YRuWdn4H7cenYrMewdzgiA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-testing": { - "version": "3.2.0-beta2", - "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta2.tgz", - "integrity": "sha512-OdQ9QXrwWF0ZE1z6QBJV912pgL0quEph/BMUeMBExMDZjRMW0FF53Rucbul5C6yDu5OpRaHVwYCmJDaAC1D+KQ==", + "version": "3.2.0-beta3", + "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta3.tgz", + "integrity": "sha512-aB4duKaP4CUms90FrvNyL6xunjTHguwYlTlF+/ImqmEZbS0gIvFajyzEbSv0xbtFJRbuYWVQTh41ad6n2vml9A==", "requires": { "tslib": "^1.9.0" } From b0587da7b738de1ffad77dae8311538e90d61b03 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 29 Mar 2019 17:29:50 +0000 Subject: [PATCH 030/208] Update RelNote310.md --- docs/release-notes/RelNote310.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/release-notes/RelNote310.md b/docs/release-notes/RelNote310.md index 98a8f46875..3cee8b8638 100644 --- a/docs/release-notes/RelNote310.md +++ b/docs/release-notes/RelNote310.md @@ -64,6 +64,7 @@ Below are the most important new features of this release: - [SSO Role AuthGuard](#sso-role-authguard) - [Improved accessibility](#improved-accessibility) - [Arabic and RTL languages support](#arabic-and-rtl-languages-support) +- [ADF Testing pacakge](#ADF-testing-pacakge) ### More on Activiti 7 @@ -266,6 +267,7 @@ For more details refer to the : ### SSO Role AuthGuard + The [Auth Guard SSO role service](../core/services/auth-guard-sso-role.service.md) implements an Angular [route guard](https://angular.io/guide/router#milestone-5-route-guards) to check the user has the right role permission. This is typically used with the @@ -297,6 +299,10 @@ Due to regular requests, we also decided to support the Arabic language in ADF. We are quite happy with the current support of RTL languages on ADF, but feedback is welcome if you find something that could be improved or added for a better user experience. +### ADF Testing pacakge + +If you are creating e2e in your project where ADF is involved we have started to export some utils and pages in the package @alfresco/adf-testing pacakges. + ## Localisation This release includes: French, German, Italian, Spanish, Arabic, Japanese, Dutch, Norwegian (Bokmål), Russian, Brazilian Portuguese and Simplified Chinese versions. From 7271e85f94e4a89b227f520488b33706c25406ce Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Sat, 30 Mar 2019 12:50:28 +0200 Subject: [PATCH 031/208] [ADF-4311] i18n - change unclaim label (#4512) * [ADF-4311] i18n - change Reque label into Release * [ADF-4311] - revert task-list i18n label * [ADF-4311] - change unclaim label key --- .../app-layout/cloud/task-details-cloud-demo.component.html | 4 ++-- lib/process-services-cloud/src/lib/i18n/en.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html index 68056e9373..23a9dbcb61 100644 --- a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html +++ b/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html @@ -7,10 +7,10 @@ (success)="onCompletedTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button> <button mat-button color="primary" *ngIf="canClaimTask()" adf-cloud-claim-task [appName]="appName" [taskId]="taskId" - (success)="onClaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.CLAIM' | translate }}</button> + (success)="onClaimTask()">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.CLAIM' | translate }}</button> <button mat-button color="primary" *ngIf="canUnClaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId" - (success)="onUnclaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.UNCLAIM' | translate }}</button> + (success)="onUnclaimTask()">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.RELEASE' | translate }}</button> </div> <adf-cloud-task-header class="adf-demop-card-container" [appName]="appName" [taskId]="taskId" [readOnly]="readOnly"> diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 8080e779ee..5dd174f465 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -174,7 +174,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Claim", - "UNCLAIM": "Release" + "RELEASE": "Release" }, "PROPERTIES": { "TASK_NAME": "Task", From 17efd33f4401d242137eff7431aa70529d835bf3 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Sat, 30 Mar 2019 11:05:19 +0000 Subject: [PATCH 032/208] fix lint issue after merge 3.2.0 --- .../adf/process-services/taskDetailsPage.ts | 2 +- .../card-view-textitem.component.spec.ts | 4 +- .../components/pdfViewer.component.spec.ts | 22 ++--- lib/tslint.json | 3 +- package-lock.json | 94 ++++++------------- package.json | 2 +- 6 files changed, 47 insertions(+), 80 deletions(-) diff --git a/e2e/pages/adf/process-services/taskDetailsPage.ts b/e2e/pages/adf/process-services/taskDetailsPage.ts index eccd4ad02a..8a4afdb963 100644 --- a/e2e/pages/adf/process-services/taskDetailsPage.ts +++ b/e2e/pages/adf/process-services/taskDetailsPage.ts @@ -232,7 +232,7 @@ export class TaskDetailsPage { addComment(comment) { BrowserVisibility.waitUntilElementIsVisible(this.commentField); this.commentField.sendKeys(comment); - Util.waitUntilElementIsVisible(this.addCommentButton); + BrowserVisibility.waitUntilElementIsVisible(this.addCommentButton); this.addCommentButton.click(); return this; } diff --git a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts index 94a51ee90b..399856ec56 100644 --- a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts @@ -185,7 +185,7 @@ describe('CardViewTextItemComponent', () => { }); fixture.detectChanges(); - let value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); + const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); expect(value).toBeNull(); expect(value.nativeElement.innerText.trim()).toBe('FAKE-ICON'); }); @@ -325,7 +325,7 @@ describe('CardViewTextItemComponent', () => { })); it('should render the default as value if the value is empty, clickable is false and displayEmpty is true', (done) => { - let functionTestClick = () => { + const functionTestClick = () => { done(); }; diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index d8cb0e479f..47f8681232 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -98,7 +98,7 @@ class BlobTestComponent { } createFakeBlob(): Blob { - let pdfData = atob( + const pdfData = atob( 'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' + 'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' + 'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' + @@ -357,7 +357,7 @@ describe('Test PdfViewer component', () => { }, 5000); it('should nextPage move to the next page', (done) => { - let nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); + const nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); nextPageButton.click(); fixtureUrlTestComponent.detectChanges(); @@ -398,8 +398,8 @@ describe('Test PdfViewer component', () => { }, 5000); it('should previous page move to the previous page', (done) => { - let previousPageButton: any = elementUrlTestComponent.querySelector('#viewer-previous-page-button'); - let nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); + const previousPageButton: any = elementUrlTestComponent.querySelector('#viewer-previous-page-button'); + const nextPageButton: any = elementUrlTestComponent.querySelector('#viewer-next-page-button'); nextPageButton.click(); nextPageButton.click(); @@ -438,28 +438,28 @@ describe('Test PdfViewer component', () => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { }); - let zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); + const zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); tick(250); - let zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; + const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; zoomInButton.click(); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - let currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; + const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; expect(zoomBefore < currentZoom).toBe(true); })); it('should zoom out decrement the scale value', fakeAsync(() => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { }); - let zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); + const zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); tick(250); - let zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; + const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; zoomOutButton.click(); expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - let currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; + const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; expect(zoomBefore > currentZoom).toBe(true); })); @@ -467,7 +467,7 @@ describe('Test PdfViewer component', () => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { }); - let itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); + const itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); tick(250); diff --git a/lib/tslint.json b/lib/tslint.json index 3d9dfdbd0d..f2a146e20a 100644 --- a/lib/tslint.json +++ b/lib/tslint.json @@ -7,5 +7,6 @@ "template-accessibility-label-for": true, "template-accessibility-tabindex-no-positive": true, "template-accessibility-table-scope": true, - "template-accessibility-valid-aria": true + "template-accessibility-valid-aria": true, + "template-no-autofocus": true } diff --git a/package-lock.json b/package-lock.json index 27b0a87c91..339e9db346 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,9 +61,9 @@ } }, "@alfresco/js-api": { - "version": "3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac", - "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.1.0-6eec5abc14bb31af3512cba5492f4ba43ffa2fac.tgz", - "integrity": "sha512-2Muuj1nPZFQK7u0CRRw0CWgoDd7lmHuiF+fpwHlh3CAArE2w7lvyZCKJkwQkXTwjSwAacytzCkysVdVINZvN9w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.1.0.tgz", + "integrity": "sha512-kjh2vmbZ2LImNVUOfmYz6kZPcv/8IoMFLtOOcL5IrBg6PdYxYlmjAw5Gs/5wlNHuqSnZe6nNfZCPlmYDxsL6aQ==", "requires": { "event-emitter": "0.3.4", "superagent": "3.8.2" @@ -2880,7 +2880,6 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, - "optional": true, "requires": { "hoek": "2.x.x" } @@ -3544,8 +3543,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", - "dev": true, - "optional": true + "dev": true }, "buffer-xor": { "version": "1.0.3", @@ -4091,9 +4089,9 @@ "dev": true }, "codelyzer": { - "version": "5.0.0-beta.2", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.0.0-beta.2.tgz", - "integrity": "sha512-cH5vxszkzhAg92pvuKXFuoDgKIqX3a5hIPv545pfuPc2GKDXuiWACPteny29k3/FGaw9eub1iUlyLVkPpETtsg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.0.0.tgz", + "integrity": "sha512-Bif70XYt8NFf/Q9GPTxmC86OsBRfQZq1dBjdruJ5kZhJ8/jKhJL6MvCLKnYtSOG6Rhiv/44DU0cHk6GYthjy8Q==", "dev": true, "requires": { "app-root-path": "^2.1.0", @@ -6792,8 +6790,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -6814,14 +6811,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6836,20 +6831,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -6966,8 +6958,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -6979,7 +6970,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6994,7 +6984,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7002,14 +6991,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7028,7 +7015,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7109,8 +7095,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7122,7 +7107,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7208,8 +7192,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7245,7 +7228,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7265,7 +7247,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7309,14 +7290,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -8083,8 +8062,7 @@ "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true, - "optional": true + "dev": true }, "homedir-polyfill": { "version": "1.0.3", @@ -8247,7 +8225,6 @@ "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", "dev": true, - "optional": true, "requires": { "httpreq": ">=0.4.22", "underscore": "~1.7.0" @@ -8257,8 +8234,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", - "dev": true, - "optional": true + "dev": true }, "https-browserify": { "version": "1.0.0", @@ -9159,8 +9135,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true, - "optional": true + "dev": true }, "is-redirect": { "version": "1.0.0", @@ -10093,15 +10068,13 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", - "dev": true, - "optional": true + "dev": true }, "libmime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", "dev": true, - "optional": true, "requires": { "iconv-lite": "0.4.15", "libbase64": "0.1.0", @@ -10112,8 +10085,7 @@ "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", - "dev": true, - "optional": true + "dev": true } } }, @@ -10121,8 +10093,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", - "dev": true, - "optional": true + "dev": true }, "license-checker": { "version": "25.0.1", @@ -12187,15 +12158,13 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", - "dev": true, - "optional": true + "dev": true }, "nodemailer-shared": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", "dev": true, - "optional": true, "requires": { "nodemailer-fetch": "1.6.0" } @@ -12228,8 +12197,7 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", - "dev": true, - "optional": true + "dev": true }, "nopt": { "version": "3.0.6", @@ -14291,9 +14259,9 @@ "dev": true }, "qs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz", - "integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "querystring": { "version": "0.2.0", @@ -15820,7 +15788,6 @@ "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", "dev": true, - "optional": true, "requires": { "httpntlm": "1.6.1", "nodemailer-shared": "1.1.0" @@ -17900,8 +17867,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", - "dev": true, - "optional": true + "dev": true }, "unherit": { "version": "1.1.1", diff --git a/package.json b/package.json index e6afc65b19..2000280fa5 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "ajv-cli": "^3.0.0", "bundlesize": "^0.15.3", "chalk": "^2.3.2", - "codelyzer": "5.0.0-beta.2", + "codelyzer": "5.0.0", "commander": "^2.15.1", "concurrently": "^3.5.1", "cspell": "^3.1.3", From f422fa30d2c8c8f5496d71b02111d494e37a1d8d Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Sat, 30 Mar 2019 13:08:14 +0200 Subject: [PATCH 033/208] [ADF-4302] - move cloud folder from app-layout to component (#4525) --- demo-shell/src/app/app.module.ts | 30 +++++++++---------- demo-shell/src/app/app.routes.ts | 18 +++++------ .../cloud/apps-cloud-demo.component.html | 0 .../cloud/apps-cloud-demo.component.ts | 0 .../cloud/cloud-breadcrumb-component.html | 0 .../cloud/cloud-breadcrumb-component.scss | 0 .../cloud/cloud-breadcrumb-component.ts | 0 .../cloud/cloud-filters-demo.component.html | 0 .../cloud/cloud-filters-demo.component.scss | 0 .../cloud/cloud-filters-demo.component.ts | 0 .../cloud/cloud-layout.component.html | 0 .../cloud/cloud-layout.component.scss | 0 .../cloud/cloud-layout.component.ts | 0 .../cloud/cloud-settings.component.html | 0 .../cloud/cloud-settings.component.scss | 0 .../cloud/cloud-settings.component.ts | 0 .../nested-menu-position.directive.ts | 0 .../people-groups-cloud-demo.component.html | 0 .../people-groups-cloud-demo.component.scss | 0 .../people-groups-cloud-demo.component.ts | 0 .../process-details-cloud-demo.component.html | 0 .../process-details-cloud-demo.component.scss | 0 .../process-details-cloud-demo.component.ts | 0 .../cloud/processes-cloud-demo.component.html | 0 .../cloud/processes-cloud-demo.component.scss | 0 .../cloud/processes-cloud-demo.component.ts | 0 .../cloud/services/cloud-layout.service.ts | 0 .../start-process-cloud-demo.component.html | 0 .../start-process-cloud-demo.component.scss | 0 .../start-process-cloud-demo.component.ts | 0 .../start-task-cloud-demo.component.html | 0 .../start-task-cloud-demo.component.scss | 0 .../cloud/start-task-cloud-demo.component.ts | 0 .../task-details-cloud-demo.component.html | 0 .../task-details-cloud-demo.component.scss | 0 .../task-details-cloud-demo.component.ts | 0 .../cloud/tasks-cloud-demo.component.html | 0 .../cloud/tasks-cloud-demo.component.scss | 0 .../cloud/tasks-cloud-demo.component.ts | 0 39 files changed, 24 insertions(+), 24 deletions(-) rename demo-shell/src/app/components/{app-layout => }/cloud/apps-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/apps-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-breadcrumb-component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-breadcrumb-component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-breadcrumb-component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-filters-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-filters-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-filters-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-layout.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-layout.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-layout.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-settings.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-settings.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/cloud-settings.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/directives/nested-menu-position.directive.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/people-groups-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/people-groups-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/people-groups-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/process-details-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/process-details-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/process-details-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/processes-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/processes-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/processes-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/services/cloud-layout.service.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/start-process-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/start-process-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/start-process-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/start-task-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/start-task-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/start-task-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/task-details-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/task-details-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/task-details-cloud-demo.component.ts (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/tasks-cloud-demo.component.html (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/tasks-cloud-demo.component.scss (100%) rename demo-shell/src/app/components/{app-layout => }/cloud/tasks-cloud-demo.component.ts (100%) diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 4cd74be7c5..8487d54fdc 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -65,22 +65,22 @@ import { InsightsModule } from '@alfresco/adf-insights'; import { ProcessModule } from '@alfresco/adf-process-services'; import { AuthBearerInterceptor } from './services'; import { ProcessServicesCloudModule, GroupCloudModule, TaskDirectiveModule } from '@alfresco/adf-process-services-cloud'; -import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component'; -import { CloudLayoutComponent } from './components/app-layout/cloud/cloud-layout.component'; -import { AppsCloudDemoComponent } from './components/app-layout/cloud/apps-cloud-demo.component'; -import { ProcessesCloudDemoComponent } from './components/app-layout/cloud/processes-cloud-demo.component'; -import { TaskDetailsCloudDemoComponent } from './components/app-layout/cloud/task-details-cloud-demo.component'; -import { StartTaskCloudDemoComponent } from './components/app-layout/cloud/start-task-cloud-demo.component'; -import { CloudBreadcrumbsComponent } from './components/app-layout/cloud/cloud-breadcrumb-component'; -import { TasksCloudDemoComponent } from './components/app-layout/cloud/tasks-cloud-demo.component'; -import { CloudFiltersDemoComponent } from './components/app-layout/cloud/cloud-filters-demo.component'; -import { StartProcessCloudDemoComponent } from './components/app-layout/cloud/start-process-cloud-demo.component'; -import { TemplateDemoComponent } from './components/template-list/template-demo.component'; -import { PeopleGroupCloudDemoComponent } from './components/app-layout/cloud/people-groups-cloud-demo.component'; -import { CloudSettingsComponent } from './components/app-layout/cloud/cloud-settings.component'; import { AppExtensionsModule } from './app-extension.module'; -import { ProcessDetailsCloudDemoComponent } from './components/app-layout/cloud/process-details-cloud-demo.component'; -import { NestedMenuPositionDirective } from './components/app-layout/cloud/directives/nested-menu-position.directive'; +import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component'; +import { CloudLayoutComponent } from './components/cloud/cloud-layout.component'; +import { AppsCloudDemoComponent } from './components/cloud/apps-cloud-demo.component'; +import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component'; +import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component'; +import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; +import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; +import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component'; +import { StartProcessCloudDemoComponent } from './components/cloud/start-process-cloud-demo.component'; +import { CloudBreadcrumbsComponent } from './components/cloud/cloud-breadcrumb-component'; +import { CloudFiltersDemoComponent } from './components/cloud/cloud-filters-demo.component'; +import { TemplateDemoComponent } from './components/template-list/template-demo.component'; +import { PeopleGroupCloudDemoComponent } from './components/cloud/people-groups-cloud-demo.component'; +import { CloudSettingsComponent } from './components/cloud/cloud-settings.component'; +import { NestedMenuPositionDirective } from './components/cloud/directives/nested-menu-position.directive'; @NgModule({ imports: [ diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index e31c401dc0..75f35e58ca 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -39,16 +39,16 @@ import { DemoPermissionComponent } from './components/permissions/demo-permissio import { ReportIssueComponent } from './components/report-issue/report-issue.component'; import { AppComponent } from './app.component'; import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component'; -import { CloudLayoutComponent } from './components/app-layout/cloud/cloud-layout.component'; -import { ProcessesCloudDemoComponent } from './components/app-layout/cloud/processes-cloud-demo.component'; -import { TaskDetailsCloudDemoComponent } from './components/app-layout/cloud/task-details-cloud-demo.component'; -import { AppsCloudDemoComponent } from './components/app-layout/cloud/apps-cloud-demo.component'; -import { TasksCloudDemoComponent } from './components/app-layout/cloud/tasks-cloud-demo.component'; -import { StartTaskCloudDemoComponent } from './components/app-layout/cloud/start-task-cloud-demo.component'; -import { StartProcessCloudDemoComponent } from './components/app-layout/cloud/start-process-cloud-demo.component'; +import { AppsCloudDemoComponent } from './components/cloud/apps-cloud-demo.component'; +import { PeopleGroupCloudDemoComponent } from './components/cloud/people-groups-cloud-demo.component'; +import { CloudLayoutComponent } from './components/cloud/cloud-layout.component'; +import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component'; +import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component'; +import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component'; +import { StartProcessCloudDemoComponent } from './components/cloud/start-process-cloud-demo.component'; +import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; +import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; import { TemplateDemoComponent } from './components/template-list/template-demo.component'; -import { PeopleGroupCloudDemoComponent } from './components/app-layout/cloud/people-groups-cloud-demo.component'; -import { ProcessDetailsCloudDemoComponent } from './components/app-layout/cloud/process-details-cloud-demo.component'; export const appRoutes: Routes = [ { path: 'login', component: LoginComponent }, diff --git a/demo-shell/src/app/components/app-layout/cloud/apps-cloud-demo.component.html b/demo-shell/src/app/components/cloud/apps-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/apps-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/apps-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/apps-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/apps-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/apps-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/apps-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-breadcrumb-component.html b/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-breadcrumb-component.html rename to demo-shell/src/app/components/cloud/cloud-breadcrumb-component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-breadcrumb-component.scss b/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-breadcrumb-component.scss rename to demo-shell/src/app/components/cloud/cloud-breadcrumb-component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-breadcrumb-component.ts b/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-breadcrumb-component.ts rename to demo-shell/src/app/components/cloud/cloud-breadcrumb-component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.html b/demo-shell/src/app/components/cloud/cloud-filters-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.html rename to demo-shell/src/app/components/cloud/cloud-filters-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.scss b/demo-shell/src/app/components/cloud/cloud-filters-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.scss rename to demo-shell/src/app/components/cloud/cloud-filters-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.ts b/demo-shell/src/app/components/cloud/cloud-filters-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-filters-demo.component.ts rename to demo-shell/src/app/components/cloud/cloud-filters-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.html b/demo-shell/src/app/components/cloud/cloud-layout.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.html rename to demo-shell/src/app/components/cloud/cloud-layout.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.scss b/demo-shell/src/app/components/cloud/cloud-layout.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.scss rename to demo-shell/src/app/components/cloud/cloud-layout.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.ts b/demo-shell/src/app/components/cloud/cloud-layout.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-layout.component.ts rename to demo-shell/src/app/components/cloud/cloud-layout.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-settings.component.html b/demo-shell/src/app/components/cloud/cloud-settings.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-settings.component.html rename to demo-shell/src/app/components/cloud/cloud-settings.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-settings.component.scss b/demo-shell/src/app/components/cloud/cloud-settings.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-settings.component.scss rename to demo-shell/src/app/components/cloud/cloud-settings.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/cloud-settings.component.ts b/demo-shell/src/app/components/cloud/cloud-settings.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/cloud-settings.component.ts rename to demo-shell/src/app/components/cloud/cloud-settings.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/directives/nested-menu-position.directive.ts b/demo-shell/src/app/components/cloud/directives/nested-menu-position.directive.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/directives/nested-menu-position.directive.ts rename to demo-shell/src/app/components/cloud/directives/nested-menu-position.directive.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.html b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/people-groups-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/process-details-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/process-details-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/process-details-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/process-details-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/process-details-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/process-details-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/process-details-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.html b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/processes-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/processes-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/processes-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/services/cloud-layout.service.ts b/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/services/cloud-layout.service.ts rename to demo-shell/src/app/components/cloud/services/cloud-layout.service.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/start-process-cloud-demo.component.html b/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/start-process-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/start-process-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/start-process-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/start-process-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/start-process-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/start-process-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/start-process-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/start-process-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/start-task-cloud-demo.component.html b/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/start-task-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/start-task-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/start-task-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/start-task-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/start-task-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/start-task-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/start-task-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/start-task-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/task-details-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/task-details-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts diff --git a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.html b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.html similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.html rename to demo-shell/src/app/components/cloud/tasks-cloud-demo.component.html diff --git a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.scss similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.scss rename to demo-shell/src/app/components/cloud/tasks-cloud-demo.component.scss diff --git a/demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.ts similarity index 100% rename from demo-shell/src/app/components/app-layout/cloud/tasks-cloud-demo.component.ts rename to demo-shell/src/app/components/cloud/tasks-cloud-demo.component.ts From d8321b977a0d5c6a33191d2b8281b2ea8e612e32 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Sat, 30 Mar 2019 13:12:10 +0200 Subject: [PATCH 034/208] [ADF-4274] - Fix users filtering on single selection mode (#4476) * [ADF-4274] - fix users filtering on single selection mode * [ADF-4274] - add unit test --- .../people-cloud.component.spec.ts | 19 +++++++++++++++++++ .../people-cloud/people-cloud.component.ts | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 5b188b5c87..c1238dc964 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -398,4 +398,23 @@ describe('PeopleCloudComponent', () => { }); }); })); + + it('should not filter the preselect user in single selection mode', async ((done) => { + spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve(mockUsers)); + component.mode = 'single'; + component.validate = true; + component.preSelectUsers = <any> [{ username: mockUsers[1].username }]; + fixture.detectChanges(); + let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.dispatchEvent(new Event('input')); + inputHTMLElement.dispatchEvent(new Event('keyup')); + inputHTMLElement.dispatchEvent(new Event('keydown')); + inputHTMLElement.value = mockUsers[1].username; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toBe(3); + }); + })); }); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts index 8319a5e89c..c91f63b91d 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts @@ -278,7 +278,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges { } private isUserAlreadySelected(user: IdentityUserModel): boolean { - if (this.preSelectUsers && this.preSelectUsers.length > 0) { + if (this.preSelectUsers && this.preSelectUsers.length > 0 && this.isMultipleMode()) { const result = this.preSelectUsers.find((selectedUser) => { return selectedUser.id === user.id || selectedUser.email === user.email || selectedUser.username === user.username; }); From 75295fdb84e0fc1ee88d7fc2c65ac963b1161d81 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Sat, 30 Mar 2019 11:18:56 +0000 Subject: [PATCH 035/208] fix lint issue after merge 3.2.0 --- .../components/people-cloud/people-cloud.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index c1238dc964..4b2bad9f2b 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -405,7 +405,7 @@ describe('PeopleCloudComponent', () => { component.validate = true; component.preSelectUsers = <any> [{ username: mockUsers[1].username }]; fixture.detectChanges(); - let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); inputHTMLElement.focus(); inputHTMLElement.dispatchEvent(new Event('input')); inputHTMLElement.dispatchEvent(new Event('keyup')); From 3305819da4c7ad2cf6bf4d5a977d902b5ecdf9bd Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Mon, 1 Apr 2019 12:15:46 +0300 Subject: [PATCH 036/208] Update webdriver-manager (#4530) --- scripts/test-e2e-lib.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/test-e2e-lib.sh b/scripts/test-e2e-lib.sh index d3b2bc86b0..e8b5af9195 100755 --- a/scripts/test-e2e-lib.sh +++ b/scripts/test-e2e-lib.sh @@ -171,11 +171,13 @@ if [[ $EXECLINT == "true" ]]; then npm run lint-e2e || exit 1 fi +echo "====== Update webdriver-manager =====" +./node_modules/protractor/bin/webdriver-manager update --gecko=false + if [[ $DEVELOPMENT == "true" ]]; then echo "====== Run against local development =====" npm run e2e-lib || exit 1 else - webdriver-manager update --gecko=false --versions.chrome=2.38 if [[ $LITESERVER == "true" ]]; then echo "====== Run dist in lite-server =====" ls demo-shell/dist From 5afe695be77c4bda5aecad3931dd97117504951c Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Mon, 1 Apr 2019 14:28:41 +0100 Subject: [PATCH 037/208] fix the failing test (#4533) --- .../people-group-cloud-component.e2e.ts | 36 +++++++++---------- .../core/actions/identity/identity.service.ts | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 52f7a3b55b..7994a8a053 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -62,10 +62,10 @@ describe('People Groups Cloud Component', () => { apsUser = await identityService.createIdentityUser(); apsUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_USER); - await identityService.assignRole(apsUser.id, apsUserRoleId, CONSTANTS.ROLES.APS_USER); + await identityService.assignRole(apsUser.idIdentityService, apsUserRoleId, CONSTANTS.ROLES.APS_USER); activitiUser = await identityService.createIdentityUser(); activitiUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_USER); - await identityService.assignRole(activitiUser.id, activitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); + await identityService.assignRole(activitiUser.idIdentityService, activitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); noRoleUser = await identityService.createIdentityUser(); groupIdentityService = new GroupIdentityService(apiService); groupAps = await groupIdentityService.createIdentityGroup(); @@ -75,7 +75,7 @@ describe('People Groups Cloud Component', () => { activitiAdminRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_ADMIN); await groupIdentityService.assignRole(groupActiviti.id, activitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN); groupNoRole = await groupIdentityService.createIdentityGroup(); - users = [`${apsUser.id}`, `${activitiUser.id}`, `${noRoleUser.id}`]; + users = [`${apsUser.idIdentityService}`, `${activitiUser.idIdentityService}`, `${noRoleUser.idIdentityService}`]; groups = [`${groupAps.id}`, `${groupActiviti.id}`, `${groupNoRole.id}`]; silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); @@ -105,11 +105,11 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); peopleGroupCloudComponentPage.enterPeopleRoles(`["${CONSTANTS.ROLES.APS_USER}"]`); peopleCloudComponent.searchAssignee('LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - peopleCloudComponent.checkUserIsNotDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); - peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsNotDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); + peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); }); it('[C297674] Add more than one role filtering to PeopleCloudComponent', () => { @@ -117,22 +117,22 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); peopleGroupCloudComponentPage.enterPeopleRoles(`["${CONSTANTS.ROLES.APS_USER}", "${CONSTANTS.ROLES.ACTIVITI_USER}"]`); peopleCloudComponent.searchAssignee('LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); - peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.checkSelectedPeople(`${activitiUser.lastName}`); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); + peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.lastName}` + 'LastName'); }); it('[C297674] Add no role filters to PeopleCloudComponent', () => { peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); peopleCloudComponent.searchAssignee('LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.selectAssigneeFromList(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); - peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + peopleCloudComponent.checkUserIsDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); + peopleCloudComponent.selectAssigneeFromList(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); + peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); }); it('[C297674] Add role filtering to GroupCloudComponent', () => { diff --git a/lib/testing/src/lib/core/actions/identity/identity.service.ts b/lib/testing/src/lib/core/actions/identity/identity.service.ts index e42a46e4a7..5d7156fa22 100644 --- a/lib/testing/src/lib/core/actions/identity/identity.service.ts +++ b/lib/testing/src/lib/core/actions/identity/identity.service.ts @@ -65,7 +65,7 @@ export class IdentityService { const queryParams = {}, postBody = { 'username': user.email, 'firstName': user.firstName, - 'lastName': user.lastName, + 'lastName': user.lastName + 'LastName', 'enabled': true, 'email': user.email }; From e6d3869891296a0e470379ed669ba3fdd0c84292 Mon Sep 17 00:00:00 2001 From: Vito <vito.albano@alfresco.com> Date: Mon, 1 Apr 2019 21:39:59 +0100 Subject: [PATCH 038/208] Fixed condition for TestConfig file (#4536) --- lib/testing/src/lib/core/browser-visibility.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/browser-visibility.ts index f5c4bd6226..024bdce410 100644 --- a/lib/testing/src/lib/core/browser-visibility.ts +++ b/lib/testing/src/lib/core/browser-visibility.ts @@ -18,7 +18,7 @@ import { browser, protractor } from 'protractor'; const until = protractor.ExpectedConditions; -const DEFAULT_TIMEOUT = global['TestConfig'].main.timeout || 40000; +const DEFAULT_TIMEOUT = global['TestConfig'] ? global['TestConfig'].main.timeout : 40000; export class BrowserVisibility { From ad15cdf028ac55809bf2d5d386ac373e977c5ceb Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 2 Apr 2019 00:24:31 +0100 Subject: [PATCH 039/208] fix unit test --- .../card-view-textitem.component.spec.ts | 23 +- .../auth-guard-sso-role.service.spec.ts | 60 +++-- .../components/pdfViewer.component.spec.ts | 246 +++++++++--------- .../components/task-header.component.spec.ts | 14 - 4 files changed, 164 insertions(+), 179 deletions(-) diff --git a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts index 399856ec56..2c0c2d424c 100644 --- a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts +++ b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts @@ -157,37 +157,18 @@ describe('CardViewTextItemComponent', () => { expect(value.nativeElement.innerText.trim()).toBe('FAKE-DEFAULT-KEY'); }); - it('should render the edit icon in case of clickable true and editable true', () => { + it('should not render the edit icon in case of clickable true but edit false', () => { component.property = new CardViewTextItemModel({ label: 'Text label', value: '', key: 'textkey', default: 'FAKE-DEFAULT-KEY', - clickable: true, - editable: true, - icon: 'FAKE-ICON' - }); - fixture.detectChanges(); - - const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); - expect(value).not.toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('FAKE-ICON'); - }); - - it('should not render the edit icon in case of clickable true and icon defined', () => { - component.property = new CardViewTextItemModel({ - label: 'Text label', - value: '', - key: 'textkey', - default: 'FAKE-DEFAULT-KEY', - clickable: true, - icon: 'FAKE-ICON' + clickable: true }); fixture.detectChanges(); const value = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-${component.property.icon}"]`)); expect(value).toBeNull(); - expect(value.nativeElement.innerText.trim()).toBe('FAKE-ICON'); }); it('should not render the edit icon in case of clickable true and icon undefined', () => { diff --git a/lib/core/services/auth-guard-sso-role.service.spec.ts b/lib/core/services/auth-guard-sso-role.service.spec.ts index a687428898..942afc09bf 100644 --- a/lib/core/services/auth-guard-sso-role.service.spec.ts +++ b/lib/core/services/auth-guard-sso-role.service.spec.ts @@ -68,7 +68,7 @@ describe('Auth Guard SSO role service', () => { spyOn(routerService, 'navigate').and.stub(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - router.data = { 'roles': ['role1', 'role2']}; + router.data = { 'roles': ['role1', 'role2'] }; expect(authGuard.canActivate(router, null)).toBeTruthy(); expect(routerService.navigate).not.toHaveBeenCalled(); @@ -85,7 +85,7 @@ describe('Auth Guard SSO role service', () => { it('Should canActivate return false if the realm_access is not present', async(() => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); - spyOn(jwtHelperService, 'decodeToken').and.returnValue({ }); + spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -94,11 +94,11 @@ describe('Auth Guard SSO role service', () => { it('Should redirect to the redirectURL if canActivate is false and redirectUrl is in data', async(() => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); - spyOn(jwtHelperService, 'decodeToken').and.returnValue({ }); + spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(routerService, 'navigate').and.stub(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - router.data = { 'roles': ['role1', 'role2'], 'redirectUrl': 'no-role-url'}; + router.data = { 'roles': ['role1', 'role2'], 'redirectUrl': 'no-role-url' }; expect(authGuard.canActivate(router, null)).toBeFalsy(); expect(routerService.navigate).toHaveBeenCalledWith(['/no-role-url']); @@ -106,32 +106,34 @@ describe('Auth Guard SSO role service', () => { it('Should not redirect if canActivate is false and redirectUrl is not in data', async(() => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); - spyOn(jwtHelperService, 'decodeToken').and.returnValue({ }); + spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(routerService, 'navigate').and.stub(); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - router.data = { 'roles': ['role1', 'role2']}; + router.data = { 'roles': ['role1', 'role2'] }; expect(authGuard.canActivate(router, null)).toBeFalsy(); expect(routerService.navigate).not.toHaveBeenCalled(); })); - it('Should canActivate be false hasRealm is true and hasClientRol is false', () => { + it('Should canActivate be false hasRealm is true and hasClientRole is false', () => { const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - spyOn(this, 'hasRealmRoles').and.returnValue(true); - spyOn(this, 'hasRealmRolesForClientRole').and.returnValue(false); + spyOn(authGuard, 'hasRealmRoles').and.returnValue(true); + spyOn(authGuard, 'hasRealmRolesForClientRole').and.returnValue(false); + route.params = { appName: 'fakeapp' }; route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; expect(authGuard.canActivate(route, null)).toBeFalsy(); }); - it('Should canActivate be false hasRealm is false and hasClientRol is true', () => { + it('Should canActivate be false if hasRealm is false and hasClientRole is true', () => { const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - spyOn(this, 'hasRealmRoles').and.returnValue(false); - spyOn(this, 'hasRealmRolesForClientRole').and.returnValue(true); + spyOn(authGuard, 'hasRealmRoles').and.returnValue(false); + spyOn(authGuard, 'hasRealmRolesForClientRole').and.returnValue(true); - route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; + route.params = { appName: 'fakeapp' }; + route.data = { 'clientRoles': ['fakeapp'], 'roles': ['role1', 'role2'] }; expect(authGuard.canActivate(route, null)).toBeFalsy(); }); @@ -142,10 +144,10 @@ describe('Auth Guard SSO role service', () => { spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] }, - 'resource_access': { fakeapp: { roles: ['role2'] }} + 'resource_access': { fakeapp: { roles: ['role2'] } } }); - route.params = {appName: 'fakeapp'}; + route.params = { appName: 'fakeapp' }; route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; expect(authGuard.canActivate(route, null)).toBeTruthy(); @@ -157,10 +159,10 @@ describe('Auth Guard SSO role service', () => { spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] }, - 'resource_access': { fakeapp: { roles: ['role3'] }} + 'resource_access': { fakeapp: { roles: ['role3'] } } }); - route.params = {appName: 'fakeapp'}; + route.params = { appName: 'fakeapp' }; route.data = { 'clientRoles': ['appName'], 'roles': ['role1', 'role2'] }; expect(authGuard.canActivate(route, null)).toBeFalsy(); @@ -172,10 +174,11 @@ describe('Auth Guard SSO role service', () => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( - {'resource_access': { fakeapp: { roles: ['role1'] } } - }); + { + 'resource_access': { fakeapp: { roles: ['role1'] } } + }); - const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1'] ); + const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1']); expect(result).toBeTruthy(); }); @@ -183,18 +186,20 @@ describe('Auth Guard SSO role service', () => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( - {'resource_access': { fakeapp: { roles: ['role1'] } } - }); + { + 'resource_access': { fakeapp: { roles: ['role1'] } } + }); - const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2'] ); + const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2']); expect(result).toBeTruthy(); }); it('Should be false if the resource_access does not contain the role', () => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( - {'resource_access': { fakeapp: { roles: ['role3'] } } - }); + { + 'resource_access': { fakeapp: { roles: ['role3'] } } + }); const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2']); expect(result).toBeFalsy(); }); @@ -202,8 +207,9 @@ describe('Auth Guard SSO role service', () => { it('Should be false if the resource_access does not contain the client role related to the app', () => { spyOn(storageService, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( - {'resource_access': { anotherfakeapp: { roles: ['role1'] } } - }); + { + 'resource_access': { anotherfakeapp: { roles: ['role1'] } } + }); const result = authGuard.hasRealmRolesForClientRole('fakeapp', ['role1', 'role2']); expect(result).toBeFalsy(); }); diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index 47f8681232..ae84a6424c 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -323,6 +323,73 @@ describe('Test PdfViewer component', () => { }, 5000); }); + describe('Password protection dialog', () => { + + let fixtureUrlTestPasswordComponent: ComponentFixture<UrlTestPasswordComponent>; + let componentUrlTestPasswordComponent: UrlTestPasswordComponent; + + beforeEach((done) => { + fixtureUrlTestPasswordComponent = TestBed.createComponent(UrlTestPasswordComponent); + componentUrlTestPasswordComponent = fixtureUrlTestPasswordComponent.componentInstance; + + spyOn(dialog, 'open').and.callFake((comp, context) => { + if (context.data.reason === pdfjsLib.PasswordResponses.NEED_PASSWORD) { + return { + afterClosed: () => of('wrong_password') + }; + } + + if (context.data.reason === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { + return { + afterClosed: () => of('password') + }; + } + }); + + fixtureUrlTestPasswordComponent.detectChanges(); + + componentUrlTestPasswordComponent.pdfViewerComponent.rendered.subscribe(() => { + done(); + }); + }); + + afterEach(() => { + document.body.removeChild(fixtureUrlTestPasswordComponent.nativeElement); + }); + + it('should try to access protected pdf', (done) => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + + expect(dialog.open).toHaveBeenCalledTimes(2); + done(); + }); + }); + + it('should raise dialog asking for password', (done) => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(dialog.open['calls'].all()[0].args[1].data).toEqual({ + reason: pdfjsLib.PasswordResponses.NEED_PASSWORD + }); + done(); + }); + }); + + it('it should raise dialog with incorrect password', (done) => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(dialog.open['calls'].all()[1].args[1].data).toEqual({ + reason: pdfjsLib.PasswordResponses.INCORRECT_PASSWORD + }); + done(); + }); + }); + }); + describe('User interaction', () => { let fixtureUrlTestComponent: ComponentFixture<UrlTestComponent>; @@ -432,72 +499,36 @@ describe('Test PdfViewer component', () => { }); }, 5000); - describe('Zoom', () => { - - it('should zoom in increment the scale value', fakeAsync(() => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { - }); - - const zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); - - tick(250); - - const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; - zoomInButton.click(); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; - expect(zoomBefore < currentZoom).toBe(true); - })); - - it('should zoom out decrement the scale value', fakeAsync(() => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { - }); - const zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); - - tick(250); - - const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; - zoomOutButton.click(); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; - expect(zoomBefore > currentZoom).toBe(true); - })); - - it('should it-in button toggle page-fit and auto scale mode', fakeAsync(() => { - spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { - }); - - const itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); - - tick(250); - - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - itPage.click(); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('page-fit'); - itPage.click(); - expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); - })); - }); - describe('Resize interaction', () => { - it('should resize event trigger setScaleUpdatePages', () => { + it('should resize event trigger setScaleUpdatePages', (done) => { spyOn(componentUrlTestComponent.pdfViewerComponent, 'onResize'); EventMock.resizeMobileView(); - expect(componentUrlTestComponent.pdfViewerComponent.onResize).toHaveBeenCalled(); + + fixtureUrlTestComponent.whenStable().then(() => { + expect(componentUrlTestComponent.pdfViewerComponent.onResize).toHaveBeenCalled(); + done(); + }); + }, 5000); }); describe('Thumbnails', () => { - it('should have own context', () => { - expect(componentUrlTestComponent.pdfViewerComponent.pdfThumbnailsContext.viewer).not.toBeNull(); + it('should have own context', (done) => { + fixtureUrlTestComponent.detectChanges(); + + fixtureUrlTestComponent.whenStable().then(() => { + expect(componentUrlTestComponent.pdfViewerComponent.pdfThumbnailsContext.viewer).not.toBeNull(); + done(); + }); }, 5000); it('should open thumbnails panel', (done) => { expect(elementUrlTestComponent.querySelector('.adf-pdf-viewer__thumbnails')).toBeNull(); componentUrlTestComponent.pdfViewerComponent.toggleThumbnails(); + fixtureUrlTestComponent.detectChanges(); fixtureUrlTestComponent.whenStable().then(() => { @@ -556,72 +587,53 @@ describe('Test PdfViewer component', () => { }); + describe('Zoom', () => { + + it('should zoom in increment the scale value', fakeAsync(() => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + + const zoomInButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-in-button'); + + tick(250); + + const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; + zoomInButton.click(); + expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); + const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; + expect(zoomBefore < currentZoom).toBe(true); + })); + + it('should zoom out decrement the scale value', fakeAsync(() => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + const zoomOutButton: any = elementUrlTestComponent.querySelector('#viewer-zoom-out-button'); + + tick(250); + + const zoomBefore = componentUrlTestComponent.pdfViewerComponent.currentScale; + zoomOutButton.click(); + expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); + const currentZoom = componentUrlTestComponent.pdfViewerComponent.currentScale; + expect(zoomBefore > currentZoom).toBe(true); + })); + + it('should it-in button toggle page-fit and auto scale mode', fakeAsync(() => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + + const itPage: any = elementUrlTestComponent.querySelector('#viewer-scale-page-button'); + + tick(250); + + expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); + itPage.click(); + expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('page-fit'); + itPage.click(); + expect(componentUrlTestComponent.pdfViewerComponent.currentScaleMode).toBe('auto'); + })); + }); + }); - describe('Password protection dialog', () => { - - let fixtureUrlTestPasswordComponent: ComponentFixture<UrlTestPasswordComponent>; - let componentUrlTestPasswordComponent: UrlTestPasswordComponent; - - beforeEach((done) => { - fixtureUrlTestPasswordComponent = TestBed.createComponent(UrlTestPasswordComponent); - componentUrlTestPasswordComponent = fixtureUrlTestPasswordComponent.componentInstance; - - spyOn(dialog, 'open').and.callFake((comp, context) => { - if (context.data.reason === pdfjsLib.PasswordResponses.NEED_PASSWORD) { - return { - afterClosed: () => of('wrong_password') - }; - } - - if (context.data.reason === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { - return { - afterClosed: () => of('password') - }; - } - }); - - fixtureUrlTestPasswordComponent.detectChanges(); - - componentUrlTestPasswordComponent.pdfViewerComponent.rendered.subscribe(() => { - done(); - }); - }); - - afterEach(() => { - document.body.removeChild(fixtureUrlTestPasswordComponent.nativeElement); - }); - - it('should try to access protected pdf', (done) => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - - expect(dialog.open).toHaveBeenCalledTimes(2); - done(); - }); - }); - - it('should raise dialog asking for password', (done) => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(dialog.open['calls'].all()[0].args[1].data).toEqual({ - reason: pdfjsLib.PasswordResponses.NEED_PASSWORD - }); - done(); - }); - }); - - it('it should raise dialog with incorrect password', (done) => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(dialog.open['calls'].all()[1].args[1].data).toEqual({ - reason: pdfjsLib.PasswordResponses.INCORRECT_PASSWORD - }); - done(); - }); - }); - }); }); diff --git a/lib/process-services/task-list/components/task-header.component.spec.ts b/lib/process-services/task-list/components/task-header.component.spec.ts index f7c0558932..3b381291a3 100644 --- a/lib/process-services/task-list/components/task-header.component.spec.ts +++ b/lib/process-services/task-list/components/task-header.component.spec.ts @@ -88,20 +88,6 @@ describe('TaskHeaderComponent', () => { }); })); - it('should display clickable edit icon', async(() => { - component.refreshData(); - fixture.detectChanges(); - - fixture.whenStable().then(() => { - const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="header-assignee"] .adf-textitem-clickable-value')); - const iconE = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-edit-icon-create"]`)); - expect(formNameEl).not.toBeNull(); - expect(iconE).not.toBeNull(); - expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams'); - expect(iconE.nativeElement.innerText.trim()).toBe('create'); - }); - })); - it('should display placeholder if no assignee', async(() => { component.taskDetails.assignee = null; component.refreshData(); From 2b4d748a6635dced97da4716dcff5b6c1cacfe51 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 2 Apr 2019 00:32:58 +0100 Subject: [PATCH 040/208] fix about component --- lib/core/about/about.component.ts | 74 ++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/lib/core/about/about.component.ts b/lib/core/about/about.component.ts index c4650f0135..cd8caa82c8 100644 --- a/lib/core/about/about.component.ts +++ b/lib/core/about/about.component.ts @@ -62,7 +62,7 @@ export class AboutComponent implements OnInit { private authService: AuthenticationService, private discovery: DiscoveryApiService, appExtensions: AppExtensionService) { - this.extensions$ = appExtensions.references$; + this.extensions$ = appExtensions.references$; } ngOnInit() { @@ -75,27 +75,77 @@ export class AboutComponent implements OnInit { { type: 'text', key: 'id', title: 'ABOUT.TABLE_HEADERS.MODULES.ID', sortable: true }, { type: 'text', key: 'title', title: 'ABOUT.TABLE_HEADERS.MODULES.TITLE', sortable: true }, { type: 'text', key: 'version', title: 'ABOUT.TABLE_HEADERS.MODULES.DESCRIPTION', sortable: true }, - { type: 'text', key: 'installDate', title: 'ABOUT.TABLE_HEADERS.MODULES.INSTALL_DATE', sortable: true }, - { type: 'text', key: 'installState', title: 'ABOUT.TABLE_HEADERS.MODULES.INSTALL_STATE', sortable: true }, - { type: 'text', key: 'versionMin', title: 'ABOUT.TABLE_HEADERS.MODULES.VERSION_MIN', sortable: true }, - { type: 'text', key: 'versionMax', title: 'ABOUT.TABLE_HEADERS.MODULES.VERSION_MAX', sortable: true } + { + type: 'text', + key: 'installDate', + title: 'ABOUT.TABLE_HEADERS.MODULES.INSTALL_DATE', + sortable: true + }, + { + type: 'text', + key: 'installState', + title: 'ABOUT.TABLE_HEADERS.MODULES.INSTALL_STATE', + sortable: true + }, + { + type: 'text', + key: 'versionMin', + title: 'ABOUT.TABLE_HEADERS.MODULES.VERSION_MIN', + sortable: true + }, + { + type: 'text', + key: 'versionMax', + title: 'ABOUT.TABLE_HEADERS.MODULES.VERSION_MAX', + sortable: true + } ]); this.status = new ObjectDataTableAdapter([this.ecmVersion.status], [ { type: 'text', key: 'isReadOnly', title: 'ABOUT.TABLE_HEADERS.STATUS.READ_ONLY', sortable: true }, - { type: 'text', key: 'isAuditEnabled', title: 'ABOUT.TABLE_HEADERS.STATUS.AUDIT_ENABLED', sortable: true }, - { type: 'text', key: 'isQuickShareEnabled', title: 'ABOUT.TABLE_HEADERS.STATUS.QUICK_SHARE_ENABLED', sortable: true }, - { type: 'text', key: 'isThumbnailGenerationEnabled', title: 'ABOUT.TABLE_HEADERS.STATUS.THUMBNAIL_ENABLED', sortable: true } + { + type: 'text', + key: 'isAuditEnabled', + title: 'ABOUT.TABLE_HEADERS.STATUS.AUDIT_ENABLED', + sortable: true + }, + { + type: 'text', + key: 'isQuickShareEnabled', + title: 'ABOUT.TABLE_HEADERS.STATUS.QUICK_SHARE_ENABLED', + sortable: true + }, + { + type: 'text', + key: 'isThumbnailGenerationEnabled', + title: 'ABOUT.TABLE_HEADERS.STATUS.THUMBNAIL_ENABLED', + sortable: true + } ]); this.license = new ObjectDataTableAdapter([this.ecmVersion.license], [ { type: 'text', key: 'issuedAt', title: 'ABOUT.TABLE_HEADERS.LICENSE.ISSUES_AT', sortable: true }, { type: 'text', key: 'expiresAt', title: 'ABOUT.TABLE_HEADERS.LICENSE.EXPIRES_AT', sortable: true }, - { type: 'text', key: 'remainingDays', title: 'ABOUT.TABLE_HEADERS.LICENSE.REMAINING_DAYS', sortable: true }, + { + type: 'text', + key: 'remainingDays', + title: 'ABOUT.TABLE_HEADERS.LICENSE.REMAINING_DAYS', + sortable: true + }, { type: 'text', key: 'holder', title: 'ABOUT.TABLE_HEADERS.LICENSE.HOLDER', sortable: true }, { type: 'text', key: 'mode', title: 'ABOUT.TABLE_HEADERS.LICENSE.MODE', sortable: true }, - { type: 'text', key: 'isClusterEnabled', title: 'ABOUT.TABLE_HEADERS.LICENSE.CLUSTER_ENABLED', sortable: true }, - { type: 'text', key: 'isCryptodocEnabled', title: 'ABOUT.TABLE_HEADERS.LICENSE.CRYPTODOC_ENABLED', sortable: true } + { + type: 'text', + key: 'isClusterEnabled', + title: 'ABOUT.TABLE_HEADERS.LICENSE.CLUSTER_ENABLED', + sortable: true + }, + { + type: 'text', + key: 'isCryptodocEnabled', + title: 'ABOUT.TABLE_HEADERS.LICENSE.CRYPTODOC_ENABLED', + sortable: true + } ]); }); } @@ -116,7 +166,7 @@ export class AboutComponent implements OnInit { alfrescoPackages.forEach((val) => { alfrescoPackagesTableRepresentation.push({ name: val, - version: response.dependencies[val].version + version: (response.dependencies[val].version || response.dependencies[val].required.version) }); }); From b60e9a7c6ee0b2345a70802ce063d2988d3aca09 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 2 Apr 2019 12:00:27 +0100 Subject: [PATCH 041/208] [ADF-4298] Improve Info drawer e2e tests (#4532) * [ADF-4298] Improve Info drawer e2e tests * [ADF-4298] Add new tab with single icon and update e2e tests --- .../file-view/file-view.component.html | 32 ++++++++++++++----- .../file-view/file-view.component.ts | 11 +++++-- e2e/core/viewer/info-drawer.component.e2e.ts | 32 +++++++++++-------- e2e/pages/adf/viewerPage.ts | 19 +++++++++-- .../datatable/datatable.component.scss | 2 +- 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/demo-shell/src/app/components/file-view/file-view.component.html b/demo-shell/src/app/components/file-view/file-view.component.html index b9567ce0b6..c2586757cd 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.html +++ b/demo-shell/src/app/components/file-view/file-view.component.html @@ -250,11 +250,21 @@ <p class="toggle"> <mat-slide-toggle - id="adf-show-tab-with-icon" + id="adf-tab-with-icon" [color]="'primary'" - (change)="toggleShowInfoDrawerTabIcon()" - [checked]="showInfoDrawerTabWithIcon"> - Show info drawer tab con + (change)="toggleShowTabWithIcon()" + [checked]="showTabWithIcon"> + Show tab with icon + </mat-slide-toggle> + </p> + + <p class="toggle"> + <mat-slide-toggle + id="adf-icon-and-label-tab" + [color]="'primary'" + (change)="toggleShowTabWithIconAndLabel()" + [checked]="showTabWithIconAndLabel"> + Show tab with icon and label </mat-slide-toggle> </p> @@ -272,13 +282,19 @@ </adf-info-drawer-tab> - <adf-info-drawer-tab - *ngIf="showInfoDrawerTabWithIcon" - [label]="'Settings'" - [icon]="'comment'" + <adf-info-drawer-tab + *ngIf="showTabWithIcon" + [label]="" + [icon]="'face'" data-automation-id="adf-settings-tab"> </adf-info-drawer-tab> + <adf-info-drawer-tab + *ngIf="showTabWithIconAndLabel" + [label]="'Comments'" + [icon]="'comment'" + data-automation-id="adf-settings-tab"> + </adf-info-drawer-tab> </adf-info-drawer> </ng-template> diff --git a/demo-shell/src/app/components/file-view/file-view.component.ts b/demo-shell/src/app/components/file-view/file-view.component.ts index d7c163090a..f014d8fca0 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.ts +++ b/demo-shell/src/app/components/file-view/file-view.component.ts @@ -53,7 +53,8 @@ export class FileViewComponent implements OnInit { showRightSidebar = false; customToolbar = false; isCommentEnabled = false; - showInfoDrawerTabWithIcon = false; + showTabWithIcon = false; + showTabWithIconAndLabel = false; constructor(private router: Router, private route: ActivatedRoute, @@ -146,8 +147,12 @@ export class FileViewComponent implements OnInit { this.allowLeftSidebar = !this.allowLeftSidebar; } - toggleShowInfoDrawerTabIcon() { - this.showInfoDrawerTabWithIcon = !this.showInfoDrawerTabWithIcon; + toggleShowTabWithIcon() { + this.showTabWithIcon = !this.showTabWithIcon; + } + + toggleShowTabWithIconAndLabel() { + this.showTabWithIconAndLabel = !this.showTabWithIconAndLabel; } toggleCustomName() { diff --git a/e2e/core/viewer/info-drawer.component.e2e.ts b/e2e/core/viewer/info-drawer.component.e2e.ts index 6b3194fd76..4d21d1f9fa 100644 --- a/e2e/core/viewer/info-drawer.component.e2e.ts +++ b/e2e/core/viewer/info-drawer.component.e2e.ts @@ -74,30 +74,36 @@ describe('Info Drawer', () => { done(); }); - it('[C277251] Should display only the icon when the icon property is defined', () => { - loginPage.loginToContentServicesUsingUserModel(acsUser); - - navigationBarPage.goToSite(site); - contentServicesPage.checkAcsContainer(); - - viewerPage.viewFile(pngFileUploaded.entry.name); - viewerPage.clickLeftSidebarButton(); - viewerPage.enableShowTabWithIcon(); - viewerPage.checkTabHasIcon(1); - expect(viewerPage.getTabLabelById(1)).not.toBe('COMMENT'); - expect(viewerPage.getTabIconById(1)).toBe('comment'); + afterAll(async (done) => { + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, pngFileUploaded.entry.id); + done(); }); - it('[C277252] Should display the label when the icon property is not defined', () => { + beforeEach(() => { loginPage.loginToContentServicesUsingUserModel(acsUser); navigationBarPage.goToSite(site); contentServicesPage.checkAcsContainer(); + }); + it('[C277251] Should display the icon when the icon property is defined', () => { viewerPage.viewFile(pngFileUploaded.entry.name); viewerPage.clickLeftSidebarButton(); viewerPage.enableShowTabWithIcon(); + viewerPage.enableShowTabWithIconAndLabel(); viewerPage.checkTabHasNoIcon(0); + expect(viewerPage.getTabIconById(1)).toBe('face'); + expect(viewerPage.getTabIconById(2)).toBe('comment'); + }); + + it('[C277252] Should display the label when the label property is defined', () => { + viewerPage.viewFile(pngFileUploaded.entry.name); + viewerPage.clickLeftSidebarButton(); + viewerPage.enableShowTabWithIcon(); + viewerPage.enableShowTabWithIconAndLabel(); expect(viewerPage.getTabLabelById(0)).toBe('SETTINGS'); + viewerPage.checkTabHasNoLabel(1); + expect(viewerPage.getTabLabelById(2)).toBe('COMMENTS'); }); }); diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index db34002801..a7232753a9 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -98,7 +98,8 @@ export class ViewerPage { codeViewer = element(by.id('adf-monaco-file-editor')); moveRightChevron = element(by.css('.mat-tab-header-pagination-after .mat-tab-header-pagination-chevron')); - showTabWithIconSwitch = element(by.id('adf-show-tab-with-icon')); + showTabWithIconSwitch = element(by.id('adf-tab-with-icon')); + showTabWithIconAndLabelSwitch = element(by.id('adf-icon-and-label-tab')); checkCodeViewerIsDisplayed() { return BrowserVisibility.waitUntilElementIsVisible(this.codeViewer); @@ -513,6 +514,14 @@ export class ViewerPage { this.formControllersPage.enableToggle(this.showTabWithIconSwitch); } + disableShowTabWithIconAndLabel() { + this.formControllersPage.disableToggle(this.showTabWithIconAndLabelSwitch); + } + + enableShowTabWithIconAndLabel() { + this.formControllersPage.enableToggle(this.showTabWithIconAndLabelSwitch); + } + checkDownloadButtonDisplayed() { BrowserVisibility.waitUntilElementIsVisible(this.downloadButton); return this; @@ -649,8 +658,14 @@ export class ViewerPage { return this; } + checkTabHasNoLabel(index: number) { + const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] span`)); + BrowserVisibility.waitUntilElementIsNotVisible(tab); + return this; + } + getTabLabelById(index: number) { - const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"]`)); + const tab = element(by.css(`div[id="mat-tab-label-1-${index}"] div[class="mat-tab-label-content"] span`)); BrowserVisibility.waitUntilElementIsVisible(tab); return tab.getText(); } diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index a904f53a46..59ef82e079 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -510,7 +510,7 @@ } .adf-datatable-body { - margin-top: 56px; + margin-top: 57px; } } From 24779498a34f9e619b258da359e47a64a748cf71 Mon Sep 17 00:00:00 2001 From: siva kumar <siva.kumar@muraai.com> Date: Tue, 2 Apr 2019 19:22:03 +0530 Subject: [PATCH 042/208] [ADF-PeopleCloudComponent] Fixed failing unit tests (#4526) * * Failing people cloud unit tests. * * Updated people cloud component unit tests. * * Removed timeout from karma config * * Removed any and use custom type. * [ADF - People-cloud component] * Fixed People-cloud component conflicts. * * New Tslint errors fixed. * * Fixed TaskHeaderCloud failing unit test. --- .../people-cloud.component.spec.ts | 820 +++++++++++------- .../people-cloud/people-cloud.component.ts | 51 +- .../task-header-cloud.component.spec.ts | 2 +- 3 files changed, 525 insertions(+), 348 deletions(-) diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 4b2bad9f2b..0d23998d9e 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -15,346 +15,538 @@ * limitations under the License. */ -import { ComponentFixture, TestBed, async } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; import { PeopleCloudComponent } from './people-cloud.component'; -import { StartTaskCloudTestingModule } from '../../testing/start-task-cloud.testing.module'; -import { LogService, setupTestBed, IdentityUserService, IdentityUserModel } from '@alfresco/adf-core'; -import { mockUsers } from '../../mock/user-cloud.mock'; -import { of } from 'rxjs'; +import { ComponentFixture, TestBed, async, tick, fakeAsync } from '@angular/core/testing'; +import { IdentityUserService, AlfrescoApiService, AlfrescoApiServiceMock, CoreModule, IdentityUserModel } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; +import { of } from 'rxjs'; +import { mockUsers } from '../../mock/user-cloud.mock'; +import { StartTaskCloudModule } from '../../start-task-cloud.module'; import { SimpleChange } from '@angular/core'; +import { By } from '@angular/platform-browser'; describe('PeopleCloudComponent', () => { let component: PeopleCloudComponent; let fixture: ComponentFixture<PeopleCloudComponent>; let element: HTMLElement; let identityService: IdentityUserService; - let findUsersSpy: jasmine.Spy; - let checkUserHasAccessSpy: jasmine.Spy; - let loadClientsByApplicationNameSpy: jasmine.Spy; + let alfrescoApiService: AlfrescoApiService; - setupTestBed({ - imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule], - providers: [IdentityUserService, LogService] - }); + const mock = { + oauth2Auth: { + callCustomApi: () => Promise.resolve(mockUsers) + } + }; + + const mockPreselectedUsers = [ + { id: mockUsers[1].id, username: mockUsers[1].username }, + { id: mockUsers[2].id, username: mockUsers[2].username } + ]; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule.forRoot(), + ProcessServiceCloudTestingModule, + StartTaskCloudModule + ], + providers: [ + IdentityUserService + ] + }) + .overrideComponent(PeopleCloudComponent, { + set: { + providers: [ + { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock } + ] + } + }).compileComponents(); + })); beforeEach(() => { fixture = TestBed.createComponent(PeopleCloudComponent); component = fixture.componentInstance; - element = fixture.nativeElement; identityService = TestBed.get(IdentityUserService); - findUsersSpy = spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); - checkUserHasAccessSpy = spyOn(identityService, 'checkUserHasClientApp').and.returnValue(of(true)); - loadClientsByApplicationNameSpy = spyOn(identityService, 'getClientIdByApplicationName').and.returnValue(of('mock-client-id')); + alfrescoApiService = TestBed.get(AlfrescoApiService); }); it('should create PeopleCloudComponent', () => { - expect(component instanceof PeopleCloudComponent).toBeTruthy(); + expect(component instanceof PeopleCloudComponent).toBe(true, 'should create PeopleCloudComponent'); }); - it('should show the users if the typed result match', async(() => { - component.searchUsers$ = of(<IdentityUserModel[]> mockUsers); - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.dispatchEvent(new Event('input')); - inputHTMLElement.dispatchEvent(new Event('keyup')); - inputHTMLElement.dispatchEvent(new Event('keydown')); - inputHTMLElement.value = 'M'; - fixture.detectChanges(); - fixture.whenStable().then(() => { + describe('Search user', () => { + + let findUsersByNameSpy: jasmine.Spy; + + beforeEach(async(() => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); + findUsersByNameSpy = spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('mat-option'))).toBeDefined(); - }); - })); + element = fixture.nativeElement; + })); - it('should hide result list if input is empty', async(() => { - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = ''; - inputHTMLElement.dispatchEvent(new Event('keyup')); - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(fixture.debugElement.query(By.css('mat-option'))).toBeNull(); - expect(fixture.debugElement.query(By.css('#adf-people-cloud-user-0'))).toBeNull(); + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); }); - })); - it('should emit selectedUser if option is valid', async(() => { - fixture.detectChanges(); - const selectEmitSpy = spyOn(component.selectUser, 'emit'); - component.onSelect(new IdentityUserModel({ username: 'username' })); - fixture.whenStable().then(() => { - expect(selectEmitSpy).toHaveBeenCalled(); - }); - })); - - it('should show an error message if the user is invalid', async(() => { - checkUserHasAccessSpy.and.returnValue(of(false)); - findUsersSpy.and.returnValue(of([])); - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'ZZZ'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - inputHTMLElement.blur(); + it('should list the users if the typed result match', async(() => { + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); fixture.detectChanges(); - const errorMessage = element.querySelector('.adf-start-task-cloud-error-message'); - expect(errorMessage).not.toBeNull(); - expect(errorMessage.textContent).toContain('ADF_CLOUD_START_TASK.ERROR.MESSAGE'); - }); - })); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toBe(3); + }); + expect(findUsersByNameSpy).toHaveBeenCalled(); + }); + })); - it('should show chip list when mode=multiple', async(() => { - component.mode = 'multiple'; - fixture.detectChanges(); - fixture.whenStable().then(() => { - const chip = element.querySelector('mat-chip-list'); - expect(chip).toBeDefined(); - }); - })); - - it('should not show chip list when mode=single', async(() => { - component.mode = 'single'; - fixture.detectChanges(); - fixture.whenStable().then(() => { - const chip = element.querySelector('mat-chip-list'); - expect(chip).toBeNull(); - }); - })); - - it('should pre-select all preSelectUsers when mode=multiple', async(() => { - spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'multiple'; - component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - fixture.detectChanges(); - fixture.whenStable().then(() => { + it('should hide result list if input is empty', async(() => { fixture.detectChanges(); - const chips = fixture.debugElement.queryAll(By.css('mat-chip')); - expect(chips.length).toBe(2); - }); - })); - - it('should not pre-select any user when preSelectUsers is empty and mode=multiple', async(() => { - spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'multiple'; - fixture.detectChanges(); - fixture.whenStable().then(() => { + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = ''; + inputHTMLElement.dispatchEvent(new Event('keyup')); + inputHTMLElement.dispatchEvent(new Event('input')); fixture.detectChanges(); - const chip = fixture.debugElement.query(By.css('mat-chip')); - expect(chip).toBeNull(); - }); - })); + fixture.whenStable().then(() => { + expect(element.querySelector('mat-option')).toBeNull(); + }); + })); - it('should pre-select preSelectUsers[0] when mode=single', async(() => { - spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'single'; - component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - fixture.detectChanges(); - fixture.whenStable().then(() => { + it('should emit selectedUser if option is valid', async(() => { + fixture.detectChanges(); + const selectEmitSpy = spyOn(component.selectUser, 'emit'); + component.onSelect(new IdentityUserModel({ username: 'username' })); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(selectEmitSpy).toHaveBeenCalled(); + }); + })); + + it('should show an error message if the search result empty', async(() => { + findUsersByNameSpy.and.returnValue(of([])); + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'ZZZ'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + inputHTMLElement.blur(); + fixture.detectChanges(); + const errorMessage = element.querySelector('.adf-start-task-cloud-error-message'); + expect(errorMessage).not.toBeNull(); + expect(errorMessage.textContent).toContain('ADF_CLOUD_START_TASK.ERROR.MESSAGE'); + }); + })); + }); + + describe('when application name defined', () => { + + let checkUserHasAccessSpy: jasmine.Spy; + let checkUserHasAnyClientAppRoleSpy: jasmine.Spy; + let findUsersByNameSpy: jasmine.Spy; + + beforeEach(async(() => { + spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); + findUsersByNameSpy = spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); + checkUserHasAccessSpy = spyOn(identityService, 'checkUserHasClientApp').and.returnValue(of(true)); + checkUserHasAnyClientAppRoleSpy = spyOn(identityService, 'checkUserHasAnyClientAppRole').and.returnValue(of(true)); + component.preSelectUsers = []; + component.appName = 'mock-app-name'; + fixture.detectChanges(); + element = fixture.nativeElement; + })); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should list users who have access to the app when appName is specified', async(() => { + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toBe(3); + }); + }); + })); + + it('should not list users who do not have access to the app when appName is specified', async(() => { + checkUserHasAccessSpy.and.returnValue(of(false)); + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toBe(0); + }); + }); + })); + + it('should list users if given roles mapped with client roles', async(() => { + component.roles = ['MOCK_ROLE_1', 'MOCK_ROLE_1']; + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toBe(3); + }); + expect(checkUserHasAnyClientAppRoleSpy).toHaveBeenCalled(); + }); + })); + + it('should not list users if roles are not mapping with client roles', async(() => { + checkUserHasAnyClientAppRoleSpy.and.returnValue(of(false)); + component.roles = ['MOCK_ROLE_1', 'MOCK_ROLE_1']; + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toBe(0); + }); + expect(checkUserHasAnyClientAppRoleSpy).toHaveBeenCalled(); + }); + })); + + it('should not call client role mapping sevice if roles not specified', async(() => { + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(checkUserHasAnyClientAppRoleSpy).not.toHaveBeenCalled(); + }); + })); + + it('should validate access to the app when appName is specified', async(() => { + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(checkUserHasAccessSpy).toHaveBeenCalledTimes(3); + }); + })); + + it('should not validate access to the app when appName is not specified', async(() => { + component.appName = ''; + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(checkUserHasAccessSpy).not.toHaveBeenCalled(); + }); + })); + + it('should show an error message if the user does not have access', async(() => { + checkUserHasAccessSpy.and.returnValue(of(false)); + findUsersByNameSpy.and.returnValue(of([])); + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'ZZZ'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + inputHTMLElement.blur(); + fixture.detectChanges(); + const errorMessage = element.querySelector('.adf-start-task-cloud-error-message'); + expect(errorMessage).not.toBeNull(); + expect(errorMessage.textContent).toContain('ADF_CLOUD_START_TASK.ERROR.MESSAGE'); + }); + })); + }); + + describe('When roles defined', () => { + + let checkUserHasRoleSpy: jasmine.Spy; + + beforeEach(async(() => { + component.roles = ['mock-role-1', 'mock-role-2']; + spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); + spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); + checkUserHasRoleSpy = spyOn(identityService, 'checkUserHasRole').and.returnValue(of(true)); + fixture.detectChanges(); + element = fixture.nativeElement; + })); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should filter users if users has any specified role', async(() => { + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(3); + }); + expect(checkUserHasRoleSpy).toHaveBeenCalledTimes(3); + }); + })); + + it('should not filter users if user does not have any specified role', async(() => { + fixture.detectChanges(); + checkUserHasRoleSpy.and.returnValue(of(false)); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.searchUsers$.subscribe((res) => { + expect(res).toBeDefined(); + expect(res.length).toEqual(0); + }); + expect(checkUserHasRoleSpy).toHaveBeenCalled(); + }); + })); + + it('should not call checkUserHasRole service when roles are not specified', async(() => { + component.roles = []; + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); + inputHTMLElement.focus(); + inputHTMLElement.value = 'M'; + inputHTMLElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(checkUserHasRoleSpy).not.toHaveBeenCalled(); + }); + })); + }); + + describe('Single Mode and Pre-selected users with no validate flag', () => { + + const change = new SimpleChange(null, mockPreselectedUsers, false); + + beforeEach(async(() => { + component.mode = 'single'; + component.preSelectUsers = <any> mockPreselectedUsers; + fixture.detectChanges(); + element = fixture.nativeElement; + })); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should not show chip list when mode=single', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const chip = element.querySelector('mat-chip-list'); + expect(chip).toBeNull(); + }); + })); + + it('should pre-select preSelectUsers[0] when mode=single', async(() => { + component.ngOnChanges({ 'preSelectUsers': change }); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const selectedUser = component.searchUserCtrl.value; + expect(selectedUser.id).toBe(mockUsers[1].id); + }); + })); + it('should not pre-select any user when preSelectUsers is empty and mode=single', async(() => { + component.preSelectUsers = []; + fixture.detectChanges(); + fixture.whenStable().then(() => { + const selectedUser = component.searchUserCtrl.value; + expect(selectedUser).toBeNull(); + }); + })); + }); + + describe('Single Mode and Pre-selected users with validate flag', () => { + + const change = new SimpleChange(null, mockPreselectedUsers, false); + + beforeEach(async(() => { + component.mode = 'single'; + component.validate = true; + component.preSelectUsers = <any> mockPreselectedUsers; + fixture.detectChanges(); + element = fixture.nativeElement; + })); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should not show chip list when mode=single', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const chip = element.querySelector('mat-chip-list'); + expect(chip).toBeNull(); + }); + })); + + it('should pre-select preSelectUsers[0] when mode=single', fakeAsync(() => { + fixture.detectChanges(); + spyOn(component, 'searchUser').and.returnValue(Promise.resolve(mockPreselectedUsers)); + component.ngOnChanges({ 'preSelectUsers': change }); + fixture.detectChanges(); + tick(); const selectedUser = component.searchUserCtrl.value; expect(selectedUser.id).toBe(mockUsers[1].id); - }); - })); - - it('should not pre-select any user when preSelectUsers is empty and mode=single', async(() => { - spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'single'; - fixture.detectChanges(); - fixture.whenStable().then(() => { - const selectedUser = component.searchUserCtrl.value; - expect(selectedUser).toBeNull(); - }); - })); - - it('should emit removeUser when a selected user is removed if mode=multiple', async(() => { - spyOn(identityService, 'getUsersByRolesWithCurrentUser').and.returnValue(Promise.resolve(mockUsers)); - const removeUserSpy = spyOn(component.removeUser, 'emit'); - - component.mode = 'multiple'; - component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - fixture.detectChanges(); - - fixture.whenStable().then(() => { - fixture.detectChanges(); - const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon')); - removeIcon.nativeElement.click(); - - expect(removeUserSpy).toHaveBeenCalledWith({ id: mockUsers[1].id }); - }); - - })); - - it('should list users who have access to the app when appName is specified', async(() => { - component.appName = 'sample-app'; - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - const usersList = fixture.debugElement.queryAll(By.css('mat-option')); - expect(usersList.length).toBe(mockUsers.length); - }); - })); - - it('should not list users who do not have access to the app when appName is specified', async(() => { - checkUserHasAccessSpy.and.returnValue(of(false)); - component.appName = 'sample-app'; - - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - const usersList = fixture.debugElement.queryAll(By.css('mat-option')); - expect(usersList.length).toBe(0); - }); - })); - - it('should validate access to the app when appName is specified', async(() => { - component.appName = 'sample-app'; - - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(checkUserHasAccessSpy).toHaveBeenCalledTimes(mockUsers.length); - }); - })); - - it('should not validate access to the app when appName is not specified', async(() => { - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(checkUserHasAccessSpy).not.toHaveBeenCalled(); - }); - })); - - it('should return true if user has any specified role', async(() => { - const checkUserHasRoleSpy = spyOn(identityService, 'checkUserHasRole').and.returnValue(of(true)); - component.roles = ['mock-role-1']; - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(checkUserHasRoleSpy).toHaveBeenCalled(); - }); - })); - - it('should return false if user does not have any specified role', async(() => { - const checkUserHasRoleSpy = spyOn(identityService, 'checkUserHasRole').and.returnValue(of(false)); - component.appName = ''; - component.roles = ['mock-role-10']; - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(checkUserHasRoleSpy).toHaveBeenCalled(); - }); - })); - - it('should not fire checkUserHasRole when roles are not specified', async(() => { - const checkUserHasRoleSpy = spyOn(identityService, 'checkUserHasRole').and.returnValue(of(false)); - component.appName = ''; - component.roles = []; - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.value = 'M'; - inputHTMLElement.dispatchEvent(new Event('input')); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(checkUserHasRoleSpy).not.toHaveBeenCalled(); - }); - })); - - it('should load the clients if appName change', async(() => { - component.appName = 'ADF'; - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(loadClientsByApplicationNameSpy).toHaveBeenCalled(); - }); - })); - - it('should filter users if appName change', async(() => { - component.appName = ''; - fixture.detectChanges(); - component.appName = 'ADF'; - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(checkUserHasAccessSpy).toHaveBeenCalled(); - }); - })); - - it('should not validate preselect values if preselectValidation flag is set to false', () => { - component.mode = 'multiple'; - component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - const change = new SimpleChange(null, 'validate', false); - component.ngOnChanges({'validate': change}); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(component.validatePreselectUsers).not.toHaveBeenCalled(); - }); + })); }); - it('should filter users when validation flag is true', async(() => { - component.mode = 'multiple'; - component.validate = true; - component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - fixture.detectChanges(); - fixture.whenStable().then(() => { - component.filterPreselectUsers().then((result) => { - expect(component.userExists(result)).toEqual(false); - }); - }); - })); + describe('Multiple Mode and Pre-selected users with no validate flag', () => { - it('should emit warning if are invalid users', async((done) => { - const warningSpy = spyOn(component.warning, 'emit').and.returnValue(of(false)); - component.mode = 'single'; + const change = new SimpleChange(null, mockPreselectedUsers, false); + + beforeEach(async(() => { + component.mode = 'multiple'; + component.preSelectUsers = <any> mockPreselectedUsers; + fixture.detectChanges(); + element = fixture.nativeElement; + })); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should show chip list when mode=multiple', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const chip = element.querySelector('mat-chip-list'); + expect(chip).toBeDefined(); + }); + })); + + it('should pre-select all preSelectUsers when mode=multiple', async(() => { + component.mode = 'multiple'; + component.ngOnChanges({ 'preSelectUsers': change }); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + component.selectedUsers$.subscribe((selectedUsers) => { + expect(selectedUsers).toBeDefined(); + expect(selectedUsers.length).toEqual(2); + expect(selectedUsers[0].id).toEqual('fake-id-2'); + }); + }); + })); + }); + + describe('Multiple Mode and Pre-selected users with validate flag', () => { + + const change = new SimpleChange(null, mockPreselectedUsers, false); + + beforeEach(async(() => { + component.mode = 'multiple'; + component.validate = true; + component.preSelectUsers = <any> mockPreselectedUsers; + fixture.detectChanges(); + element = fixture.nativeElement; + })); + + afterEach(() => { + fixture.destroy(); + TestBed.resetTestingModule(); + }); + + it('should show chip list when mode=multiple', async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const chip = element.querySelector('mat-chip-list'); + expect(chip).toBeDefined(); + }); + })); + + it('should pre-select all preSelectUsers when mode=multiple', async(() => { + fixture.detectChanges(); + spyOn(component, 'searchUser').and.returnValue(Promise.resolve(mockPreselectedUsers)); + component.mode = 'multiple'; + component.ngOnChanges({ 'preSelectUsers': change }); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + const chips = fixture.debugElement.queryAll(By.css('mat-chip')); + expect(chips.length).toBe(2); + }); + })); + + it('should emit removeUser when a selected user is removed if mode=multiple', async(() => { + fixture.detectChanges(); + const removeUserSpy = spyOn(component.removeUser, 'emit'); + component.mode = 'multiple'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon')); + removeIcon.nativeElement.click(); + expect(removeUserSpy).toHaveBeenCalled(); + }); + })); + }); + + it('should emit warning if are invalid users', (done) => { + spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve([])); + const warnMessage = { message: 'INVALID_PRESELECTED_USERS', users: [{ username: 'invalidUsername' }] }; component.validate = true; component.preSelectUsers = <any> [{ username: 'invalidUsername' }]; fixture.detectChanges(); - fixture.whenStable().then(() => { - component.loadSinglePreselectUser().then((result) => { - fixture.detectChanges(); - expect(warningSpy).toHaveBeenCalled(); - }); + component.loadSinglePreselectUser(); + component.warning.subscribe((response) => { + expect(response).toEqual(warnMessage); + expect(response.message).toEqual(warnMessage.message); + expect(response.users).toEqual(warnMessage.users); + expect(response.users[0].username).toEqual('invalidUsername'); + done(); }); - })); + }); - it('should filter user by id if validate true', async((done) => { + it('should filter user by id if validate true', async(() => { const findByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(Promise.resolve(mockUsers)); component.mode = 'multiple'; component.validate = true; @@ -364,12 +556,11 @@ describe('PeopleCloudComponent', () => { component.filterPreselectUsers().then((result) => { expect(findByIdSpy).toHaveBeenCalled(); expect(component.userExists(result)).toEqual(true); - done(); }); }); })); - it('should filter user by username if validate true', async((done) => { + it('should filter user by username if validate true', async(() => { const findUserByUsernameSpy = spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve(mockUsers)); component.mode = 'multiple'; component.validate = true; @@ -379,12 +570,11 @@ describe('PeopleCloudComponent', () => { component.filterPreselectUsers().then((result) => { expect(findUserByUsernameSpy).toHaveBeenCalled(); expect(component.userExists(result)).toEqual(true); - done(); }); }); })); - it('should filter user by email if validate true', async((done) => { + it('should filter user by email if validate true', async(() => { const findUserByEmailSpy = spyOn(identityService, 'findUserByEmail').and.returnValue(Promise.resolve(mockUsers)); component.mode = 'multiple'; component.validate = true; @@ -394,27 +584,7 @@ describe('PeopleCloudComponent', () => { component.filterPreselectUsers().then((result) => { expect(findUserByEmailSpy).toHaveBeenCalled(); expect(component.userExists(result)).toEqual(true); - done(); }); }); })); - - it('should not filter the preselect user in single selection mode', async ((done) => { - spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'single'; - component.validate = true; - component.preSelectUsers = <any> [{ username: mockUsers[1].username }]; - fixture.detectChanges(); - const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input'); - inputHTMLElement.focus(); - inputHTMLElement.dispatchEvent(new Event('input')); - inputHTMLElement.dispatchEvent(new Event('keyup')); - inputHTMLElement.dispatchEvent(new Event('keydown')); - inputHTMLElement.value = mockUsers[1].username; - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(fixture.debugElement.queryAll(By.css('mat-option')).length).toBe(3); - }); - })); }); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts index c91f63b91d..af01e43337 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts @@ -118,10 +118,12 @@ export class PeopleCloudComponent implements OnInit, OnChanges { ngOnChanges(changes: SimpleChanges) { this.initSubjects(); - if (this.isPreselectedUserChanged(changes) && this.isValidationEnabled()) { - this.loadPreSelectUsers(); - } else { - this.loadNoValidationPreselctUsers(); + if (this.isPreselectedUserChanged(changes)) { + if (this.isValidationEnabled()) { + this.loadPreSelectUsers(); + } else { + this.loadNoValidationPreselctUsers(); + } } if (changes.appName && this.isAppNameChanged(changes.appName)) { @@ -160,7 +162,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges { async validatePreselectUsers(): Promise<any> { this.invalidUsers = []; - let filteredPreSelectUsers: IdentityUserModel[]; + let filteredPreSelectUsers: { isValid: boolean, user: IdentityUserModel } []; try { filteredPreSelectUsers = await this.filterPreselectUsers(); @@ -169,11 +171,11 @@ export class PeopleCloudComponent implements OnInit, OnChanges { this.logService.error(error); } - return filteredPreSelectUsers.reduce((validUsers, user: IdentityUserModel) => { - if (this.userExists(user)) { - validUsers.push(user); + return filteredPreSelectUsers.reduce((validUsers, validatedUser: any) => { + if (validatedUser.isValid) { + validUsers.push(validatedUser.user); } else { - this.invalidUsers.push(user); + this.invalidUsers.push(validatedUser.user); } return validUsers; }, []); @@ -182,15 +184,14 @@ export class PeopleCloudComponent implements OnInit, OnChanges { async filterPreselectUsers() { const promiseBatch = this.preSelectUsers.map(async (user: IdentityUserModel) => { let result: any; - try { result = await this.searchUser(user); } catch (error) { result = []; this.logService.error(error); } - const isUserValid: Boolean = this.userExists(result); - return isUserValid ? new IdentityUserModel(result[0]) : user; + const isUserValid: boolean = this.userExists(result); + return isUserValid ? { isValid: isUserValid, user: new IdentityUserModel(user) } : { isValid: isUserValid, user: user }; }); return await Promise.all(promiseBatch); } @@ -205,11 +206,8 @@ export class PeopleCloudComponent implements OnInit, OnChanges { } } - public userExists(result: any) { - return result.length > 0 || - result.id !== undefined || - result.username !== undefined || - result.amil !== undefined; + public userExists(result: any): boolean { + return result && result.length > 0; } private initSearch() { @@ -241,6 +239,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges { }), mergeMap((user: any) => { if (this.appName) { + return this.checkUserHasAccess(user.id).pipe( mergeMap((hasRole) => { return hasRole ? of(user) : of(); @@ -309,15 +308,23 @@ export class PeopleCloudComponent implements OnInit, OnChanges { public async loadSinglePreselectUser() { const users = await this.validatePreselectUsers(); - this.checkPreselectValidationErrors(); - this.searchUserCtrl.setValue(users[0]); + if (users && users.length > 0) { + this.checkPreselectValidationErrors(); + this.searchUserCtrl.setValue(users[0]); + } else { + this.checkPreselectValidationErrors(); + } } public async loadMultiplePreselectUsers() { const users = await this.validatePreselectUsers(); - this.checkPreselectValidationErrors(); - this.preSelectUsers = [...users]; - this.selectedUsersSubject.next(users); + if (users && users.length > 0) { + this.checkPreselectValidationErrors(); + this.preSelectUsers = [...users]; + this.selectedUsersSubject.next(users); + } else { + this.checkPreselectValidationErrors(); + } } public checkPreselectValidationErrors() { diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts index b2db6f5b46..c50bc2dae9 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts @@ -95,7 +95,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.whenStable().then(() => { const valueEl = fixture.debugElement.query(By.css('[data-automation-id="header-dueDate"] .adf-property-value')); - expect(valueEl.nativeElement.innerText.trim()).toBe('Dec 18 2018'); + expect(valueEl.nativeElement.innerText.trim()).toBe('18-12-2018'); }); })); From f46c848308a21e5cf740d84c63db2f52bcc349d1 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Tue, 2 Apr 2019 15:36:58 +0100 Subject: [PATCH 043/208] Move process cloud page int @alfresco/adf-testing (#4540) Move datatable @alfresco/adf-testing --- .../data-table-component-selection.e2e.ts | 2 +- .../datatable/data-table-component.e2e.ts | 2 +- e2e/core/viewer/viewer-properties.e2e.ts | 2 +- .../adf/content-services/documentListPage.ts | 2 +- e2e/pages/adf/demo-shell/customSourcesPage.ts | 2 +- e2e/pages/adf/demo-shell/dataTablePage.ts | 2 +- .../process-services/processCloudDemoPage.ts | 18 +-- .../process-services/processListDemoPage.ts | 2 +- .../process-services/tasksCloudDemoPage.ts | 22 ++- e2e/pages/adf/permissionsPage.ts | 2 +- e2e/pages/adf/process-services/filtersPage.ts | 2 +- .../process-services/processFiltersPage.ts | 2 +- .../adf/process-services/tasksListPage.ts | 2 +- .../editTaskFilterCloudComponent.ts | 150 ------------------ e2e/pages/adf/searchResultsPage.ts | 2 +- .../people-group-cloud-component.e2e.ts | 43 +++-- .../start-task-custom-app-cloud.e2e.ts | 10 +- .../components/search-date-range.e2e.ts | 2 +- .../components/search-number-range.e2e.ts | 2 +- e2e/search/components/search-slider.e2e.ts | 2 +- .../core/pages/data-table-component.page.ts | 2 +- .../pages/login-sso.page.ts | 0 lib/testing/src/lib/core/pages/public-api.ts | 2 + .../src/lib/core/pages/user-info.page.ts | 2 +- lib/testing/src/lib/core/public-api.ts | 1 - .../material => material/pages}/public-api.ts | 0 .../material => material/pages}/tabs.page.ts | 2 +- lib/testing/src/lib/material/public-api.ts | 2 +- .../dialog/edit-process-filter-dialog.page.ts | 4 +- .../dialog/edit-task-filter-dialog.page.ts | 4 +- .../pages/dialog/public-api.ts | 19 +++ ...dit-process-filter-cloud-component.page.ts | 12 +- .../edit-task-filter-cloud-component.page.ts | 12 +- .../pages/group-cloud-component.page.ts | 4 +- .../pages/people-cloud-component.page.ts | 4 +- .../process-filters-cloud-component.page.ts | 4 +- .../process-list-cloud-component.page.ts | 6 +- .../pages/public-api.ts | 11 +- .../task-filters-cloud-component.page.ts | 4 +- .../pages/task-list-cloud-component.page.ts | 6 +- lib/testing/src/public-api.ts | 3 +- 41 files changed, 124 insertions(+), 253 deletions(-) delete mode 100644 e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts rename e2e/pages/adf/dataTableComponentPage.ts => lib/testing/src/lib/core/pages/data-table-component.page.ts (99%) rename lib/testing/src/lib/{process-services-cloud => core}/pages/login-sso.page.ts (100%) rename lib/testing/src/lib/{core/material => material/pages}/public-api.ts (100%) rename lib/testing/src/lib/{core/material => material/pages}/tabs.page.ts (94%) rename e2e/pages/adf/dialog/editProcessFilterDialog.ts => lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts (96%) rename e2e/pages/adf/dialog/editTaskFilterDialog.ts => lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts (96%) create mode 100644 lib/testing/src/lib/process-services-cloud/pages/dialog/public-api.ts rename e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts (95%) rename e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts (96%) rename e2e/pages/adf/process-cloud/groupCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts (95%) rename e2e/pages/adf/process-cloud/peopleCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts (96%) rename e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts (93%) rename e2e/pages/adf/process-cloud/processListCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts (91%) rename e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts (93%) rename e2e/pages/adf/process-cloud/taskListCloudComponent.ts => lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts (94%) diff --git a/e2e/core/datatable/data-table-component-selection.e2e.ts b/e2e/core/datatable/data-table-component-selection.e2e.ts index 6539cfd321..72f2710573 100644 --- a/e2e/core/datatable/data-table-component-selection.e2e.ts +++ b/e2e/core/datatable/data-table-component-selection.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '../../pages/adf/loginPage'; import { DataTablePage } from '../../pages/adf/demo-shell/dataTablePage'; -import { DataTableComponentPage } from '../../pages/adf/dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import TestConfig = require('../../test.config'); import { AcsUserModel } from '../../models/ACS/acsUserModel'; diff --git a/e2e/core/datatable/data-table-component.e2e.ts b/e2e/core/datatable/data-table-component.e2e.ts index 91f9f1ff18..3a8df28acd 100644 --- a/e2e/core/datatable/data-table-component.e2e.ts +++ b/e2e/core/datatable/data-table-component.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '../../pages/adf/loginPage'; import { DataTablePage } from '../../pages/adf/demo-shell/dataTablePage'; -import { DataTableComponentPage } from '../../pages/adf/dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import TestConfig = require('../../test.config'); diff --git a/e2e/core/viewer/viewer-properties.e2e.ts b/e2e/core/viewer/viewer-properties.e2e.ts index 3ffe8a94e3..0dcf410121 100644 --- a/e2e/core/viewer/viewer-properties.e2e.ts +++ b/e2e/core/viewer/viewer-properties.e2e.ts @@ -21,7 +21,7 @@ import { LoginPage } from '../../pages/adf/loginPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { DataTableComponentPage } from '../../pages/adf/dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import resources = require('../../util/resources'); diff --git a/e2e/pages/adf/content-services/documentListPage.ts b/e2e/pages/adf/content-services/documentListPage.ts index 034930ec6d..47ec567c99 100644 --- a/e2e/pages/adf/content-services/documentListPage.ts +++ b/e2e/pages/adf/content-services/documentListPage.ts @@ -16,7 +16,7 @@ */ import { by, element, ElementFinder, browser } from 'protractor'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { BrowserVisibility } from '@alfresco/adf-testing'; export class DocumentListPage { diff --git a/e2e/pages/adf/demo-shell/customSourcesPage.ts b/e2e/pages/adf/demo-shell/customSourcesPage.ts index fbaf9e7393..95b4db8895 100644 --- a/e2e/pages/adf/demo-shell/customSourcesPage.ts +++ b/e2e/pages/adf/demo-shell/customSourcesPage.ts @@ -17,7 +17,7 @@ import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../navigationBarPage'; const source = { diff --git a/e2e/pages/adf/demo-shell/dataTablePage.ts b/e2e/pages/adf/demo-shell/dataTablePage.ts index a6ff81141d..63328fc3ca 100644 --- a/e2e/pages/adf/demo-shell/dataTablePage.ts +++ b/e2e/pages/adf/demo-shell/dataTablePage.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { BrowserVisibility } from '@alfresco/adf-testing'; export class DataTablePage { diff --git a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts index a84fb3444d..afb1f7f51e 100644 --- a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts @@ -15,11 +15,9 @@ * limitations under the License. */ -import { ProcessFiltersCloudComponent } from '../../process-cloud/processFiltersCloudComponent'; -import { ProcessListCloudComponent } from '../../process-cloud/processListCloudComponent'; -import { EditProcessFilterCloudComponent } from '../../process-cloud/editProcessFilterCloudComponent'; import { element, by } from 'protractor'; import { BrowserVisibility } from '@alfresco/adf-testing'; +import { ProcessFiltersCloudComponentPage, EditProcessFilterCloudComponentPage, ProcessListCloudComponentPage } from '@alfresco/adf-testing'; export class ProcessCloudDemoPage { @@ -32,11 +30,11 @@ export class ProcessCloudDemoPage { createButton = element(by.css('button[data-automation-id="create-button"')); newProcessButton = element(by.css('button[data-automation-id="btn-start-process"]')); - processListCloud = new ProcessListCloudComponent(); - editProcessFilterCloud = new EditProcessFilterCloudComponent(); + processListCloud = new ProcessListCloudComponentPage(); + editProcessFilterCloud = new EditProcessFilterCloudComponentPage(); processFiltersCloudComponent(filter) { - return new ProcessFiltersCloudComponent(filter); + return new ProcessFiltersCloudComponentPage(filter); } editProcessFilterCloudComponent() { @@ -52,19 +50,19 @@ export class ProcessCloudDemoPage { } allProcessesFilter() { - return new ProcessFiltersCloudComponent(this.allProcesses); + return new ProcessFiltersCloudComponentPage(this.allProcesses); } runningProcessesFilter() { - return new ProcessFiltersCloudComponent(this.runningProcesses); + return new ProcessFiltersCloudComponentPage(this.runningProcesses); } completedProcessesFilter() { - return new ProcessFiltersCloudComponent(this.completedProcesses); + return new ProcessFiltersCloudComponentPage(this.completedProcesses); } customProcessFilter(filterName) { - return new ProcessFiltersCloudComponent(element(by.css(`span[data-automation-id="${filterName}_filter"]`))); + return new ProcessFiltersCloudComponentPage(element(by.css(`span[data-automation-id="${filterName}_filter"]`))); } getActiveFilterName() { diff --git a/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts index 99b7e97d31..5b6bd1230d 100644 --- a/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processListDemoPage.ts @@ -16,7 +16,7 @@ */ import { BrowserVisibility } from '@alfresco/adf-testing'; -import { DataTableComponentPage } from '../../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { element, by, protractor } from 'protractor'; export class ProcessListDemoPage { diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index 51b591a609..248d546f39 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -15,13 +15,11 @@ * limitations under the License. */ -import { TaskFiltersCloudComponent } from '../../process-cloud/taskFiltersCloudComponent'; -import { TaskListCloudComponent } from '../../process-cloud/taskListCloudComponent'; -import { EditTaskFilterCloudComponent } from '../../process-cloud/editTaskFilterCloudComponent'; +import { EditTaskFilterCloudComponentPage, TaskFiltersCloudComponentPage } from '@alfresco/adf-testing'; import { FormControllersPage } from '../../material/formControllersPage'; import { element, by, browser } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility, TaskListCloudComponentPage } from '@alfresco/adf-testing'; export class TasksCloudDemoPage { @@ -43,7 +41,7 @@ export class TasksCloudDemoPage { formControllersPage = new FormControllersPage(); - editTaskFilterCloud = new EditTaskFilterCloudComponent(); + editTaskFilterCloud = new EditTaskFilterCloudComponentPage(); disableDisplayTaskDetails() { this.formControllersPage.disableToggle(this.displayTaskDetailsToggle); @@ -56,11 +54,11 @@ export class TasksCloudDemoPage { } taskFiltersCloudComponent(filter) { - return new TaskFiltersCloudComponent(filter); + return new TaskFiltersCloudComponentPage(filter); } taskListCloudComponent() { - return new TaskListCloudComponent(); + return new TaskListCloudComponentPage(); } editTaskFilterCloudComponent() { @@ -68,15 +66,15 @@ export class TasksCloudDemoPage { } myTasksFilter() { - return new TaskFiltersCloudComponent(this.myTasks); + return new TaskFiltersCloudComponentPage(this.myTasks); } completedTasksFilter() { - return new TaskFiltersCloudComponent(this.completedTasks); + return new TaskFiltersCloudComponentPage(this.completedTasks); } customTaskFilter(filterName) { - return new TaskFiltersCloudComponent(element(by.css(`span[data-automation-id="${filterName}-filter"]`))); + return new TaskFiltersCloudComponentPage(element(by.css(`span[data-automation-id="${filterName}-filter"]`))); } getActiveFilterName() { @@ -85,11 +83,11 @@ export class TasksCloudDemoPage { } getAllRowsByIdColumn() { - return new TaskListCloudComponent().getAllRowsByColumn('Id'); + return new TaskListCloudComponentPage().getAllRowsByColumn('Id'); } getAllRowsByProcessDefIdColumn() { - return new TaskListCloudComponent().getAllRowsByColumn('Process Definition Id'); + return new TaskListCloudComponentPage().getAllRowsByColumn('Process Definition Id'); } clickOnTaskFilters() { diff --git a/e2e/pages/adf/permissionsPage.ts b/e2e/pages/adf/permissionsPage.ts index 830a60bca0..f83c766852 100644 --- a/e2e/pages/adf/permissionsPage.ts +++ b/e2e/pages/adf/permissionsPage.ts @@ -17,7 +17,7 @@ import { element, by } from 'protractor'; -import { DataTableComponentPage } from './dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { BrowserVisibility } from '@alfresco/adf-testing'; const column = { diff --git a/e2e/pages/adf/process-services/filtersPage.ts b/e2e/pages/adf/process-services/filtersPage.ts index fc41f71501..8fdccef5ee 100644 --- a/e2e/pages/adf/process-services/filtersPage.ts +++ b/e2e/pages/adf/process-services/filtersPage.ts @@ -16,7 +16,7 @@ */ import { by, element } from 'protractor'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { BrowserVisibility } from '@alfresco/adf-testing'; export class FiltersPage { diff --git a/e2e/pages/adf/process-services/processFiltersPage.ts b/e2e/pages/adf/process-services/processFiltersPage.ts index 5681ef3623..ad27a7eb66 100644 --- a/e2e/pages/adf/process-services/processFiltersPage.ts +++ b/e2e/pages/adf/process-services/processFiltersPage.ts @@ -17,7 +17,7 @@ import { element, by } from 'protractor'; import { StartProcessPage } from './startProcessPage'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { BrowserVisibility } from '@alfresco/adf-testing'; export class ProcessFiltersPage { diff --git a/e2e/pages/adf/process-services/tasksListPage.ts b/e2e/pages/adf/process-services/tasksListPage.ts index 4faaa94eb8..70b9f76f74 100644 --- a/e2e/pages/adf/process-services/tasksListPage.ts +++ b/e2e/pages/adf/process-services/tasksListPage.ts @@ -16,7 +16,7 @@ */ import { BrowserVisibility } from '@alfresco/adf-testing'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { by, element } from 'protractor'; export class TasksListPage { diff --git a/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts b/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts deleted file mode 100644 index f202cf108b..0000000000 --- a/e2e/pages/adf/process_cloud/editTaskFilterCloudComponent.ts +++ /dev/null @@ -1,150 +0,0 @@ -/*! - * @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 { by, element, protractor } from 'protractor'; -import { EditTaskFilterDialog } from '../dialog/editTaskFilterDialog'; -import { BrowserVisibility } from '@alfresco/adf-testing'; - -export class EditTaskFilterCloudComponent { - - customiseFilter = element(by.id('adf-edit-task-filter-title-id')); - selectedOption = element.all(by.css('mat-option[class*="mat-selected"]')).first(); - assignment = element(by.css('mat-form-field[data-automation-id="assignment"] input')); - saveButton = element(by.css('button[data-automation-id="Save"]')); - saveAsButton = element(by.css('button[data-automation-id="Save as"]')); - deleteButton = element(by.css('button[data-automation-id="Delete"]')); - - editTaskFilter = new EditTaskFilterDialog(); - - editTaskFilterDialog() { - return this.editTaskFilter; - } - - clickCustomiseFilterHeader() { - BrowserVisibility.waitUntilElementIsVisible(this.customiseFilter); - this.customiseFilter.click(); - return this; - } - - setStateFilterDropDown(option) { - this.clickOnDropDownArrow('status'); - - const stateElement = element.all(by.cssContainingText('mat-option span', option)).first(); - BrowserVisibility.waitUntilElementIsClickable(stateElement); - BrowserVisibility.waitUntilElementIsVisible(stateElement); - stateElement.click(); - return this; - } - - getStateFilterDropDownValue() { - return element(by.css("mat-form-field[data-automation-id='status'] span")).getText(); - } - - setSortFilterDropDown(option) { - this.clickOnDropDownArrow('sort'); - - const sortElement = element.all(by.cssContainingText('mat-option span', option)).first(); - BrowserVisibility.waitUntilElementIsClickable(sortElement); - BrowserVisibility.waitUntilElementIsVisible(sortElement); - sortElement.click(); - return this; - } - - getSortFilterDropDownValue() { - return element(by.css("mat-form-field[data-automation-id='sort'] span")).getText(); - } - - setOrderFilterDropDown(option) { - this.clickOnDropDownArrow('order'); - - const orderElement = element.all(by.cssContainingText('mat-option span', option)).first(); - BrowserVisibility.waitUntilElementIsClickable(orderElement); - BrowserVisibility.waitUntilElementIsVisible(orderElement); - orderElement.click(); - return this; - } - - getOrderFilterDropDownValue() { - return element(by.css("mat-form-field[data-automation-id='order'] span")).getText(); - } - - clickOnDropDownArrow(option) { - const dropDownArrow = element(by.css("mat-form-field[data-automation-id='" + option + "'] div[class*='arrow']")); - BrowserVisibility.waitUntilElementIsVisible(dropDownArrow); - dropDownArrow.click(); - BrowserVisibility.waitUntilElementIsVisible(this.selectedOption); - } - - setAssignment(option) { - BrowserVisibility.waitUntilElementIsVisible(this.assignment); - this.assignment.clear(); - this.assignment.sendKeys(option); - this.assignment.sendKeys(protractor.Key.ENTER); - return this; - } - - getAssignment() { - return this.assignment.getText(); - } - - checkSaveButtonIsDisplayed() { - BrowserVisibility.waitUntilElementIsVisible(this.saveButton); - return this; - } - - checkSaveAsButtonIsDisplayed() { - BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); - return this; - } - - checkDeleteButtonIsDisplayed() { - BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); - return this; - } - - checkSaveButtonIsEnabled() { - return this.saveButton.isEnabled(); - } - - checkSaveAsButtonIsEnabled() { - return this.saveAsButton.isEnabled(); - } - - checkDeleteButtonIsEnabled() { - return this.deleteButton.isEnabled(); - } - - clickSaveAsButton() { - BrowserVisibility.waitUntilElementIsClickable(this.saveAsButton); - BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); - this.saveAsButton.click(); - return this.editTaskFilter; - } - - clickDeleteButton() { - BrowserVisibility.waitUntilElementIsVisible(this.deleteButton); - this.deleteButton.click(); - return this; - } - - clickSaveButton() { - BrowserVisibility.waitUntilElementIsVisible(this.saveButton); - this.saveButton.click(); - return this; - } - -} diff --git a/e2e/pages/adf/searchResultsPage.ts b/e2e/pages/adf/searchResultsPage.ts index c36305d517..93c01bef87 100644 --- a/e2e/pages/adf/searchResultsPage.ts +++ b/e2e/pages/adf/searchResultsPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { DataTableComponentPage } from './dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchSortingPickerPage } from './content-services/search/components/search-sortingPicker.page'; import { element, by } from 'protractor'; import { ContentServicesPage } from './contentServicesPage'; diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 7994a8a053..82f22adcf5 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -20,8 +20,7 @@ import TestConfig = require('../test.config'); import { SettingsPage } from '../pages/adf/settingsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { PeopleGroupCloudComponentPage } from '../pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage'; -import { PeopleCloudComponent } from '../pages/adf/process-cloud/peopleCloudComponent'; -import { GroupCloudComponent } from '../pages/adf/process-cloud/groupCloudComponent'; +import { GroupCloudComponentPage, PeopleCloudComponentPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; import { LoginSSOPage, IdentityService, GroupIdentityService, RolesService, ApiService } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); @@ -33,8 +32,8 @@ describe('People Groups Cloud Component', () => { const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); const peopleGroupCloudComponentPage = new PeopleGroupCloudComponentPage(); - const peopleCloudComponent = new PeopleCloudComponent(); - const groupCloudComponent = new GroupCloudComponent(); + const peopleCloudComponent = new PeopleCloudComponentPage(); + const groupCloudComponentPage = new GroupCloudComponentPage(); let identityService: IdentityService; let groupIdentityService: GroupIdentityService; let rolesService: RolesService; @@ -139,36 +138,36 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); peopleGroupCloudComponentPage.clickGroupCloudFilterRole(); peopleGroupCloudComponentPage.enterGroupRoles(`["${CONSTANTS.ROLES.APS_ADMIN}"]`); - groupCloudComponent.searchGroups('TestGroup'); - groupCloudComponent.checkGroupIsDisplayed(`${groupAps.name}`); - groupCloudComponent.checkGroupIsNotDisplayed(`${groupActiviti.name}`); - groupCloudComponent.checkGroupIsNotDisplayed(`${groupNoRole.name}`); - groupCloudComponent.selectGroupFromList(`${groupAps.name}`); - groupCloudComponent.checkSelectedGroup(`${groupAps.name}`); + groupCloudComponentPage.searchGroups('TestGroup'); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); + groupCloudComponentPage.checkGroupIsNotDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsNotDisplayed(`${groupNoRole.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupAps.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupAps.name}`); }); it('[C297674] Add more than one role filtering to GroupCloudComponent', () => { peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); peopleGroupCloudComponentPage.clickGroupCloudFilterRole(); peopleGroupCloudComponentPage.enterGroupRoles(`["${CONSTANTS.ROLES.APS_ADMIN}", "${CONSTANTS.ROLES.ACTIVITI_ADMIN}"]`); - groupCloudComponent.searchGroups('TestGroup'); - groupCloudComponent.checkGroupIsDisplayed(`${groupActiviti.name}`); - groupCloudComponent.checkGroupIsDisplayed(`${groupAps.name}`); - groupCloudComponent.checkGroupIsNotDisplayed(`${groupNoRole.name}`); - groupCloudComponent.selectGroupFromList(`${groupActiviti.name}`); - groupCloudComponent.checkSelectedGroup(`${groupActiviti.name}`); + groupCloudComponentPage.searchGroups('TestGroup'); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); + groupCloudComponentPage.checkGroupIsNotDisplayed(`${groupNoRole.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupActiviti.name}`); }); it('[C297674] Add no role filters to GroupCloudComponent', () => { peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); peopleGroupCloudComponentPage.clickGroupCloudFilterRole(); peopleGroupCloudComponentPage.clearField(peopleGroupCloudComponentPage.groupRoleInput); - groupCloudComponent.searchGroups('TestGroup'); - groupCloudComponent.checkGroupIsDisplayed(`${groupNoRole.name}`); - groupCloudComponent.checkGroupIsDisplayed(`${groupActiviti.name}`); - groupCloudComponent.checkGroupIsDisplayed(`${groupAps.name}`); - groupCloudComponent.selectGroupFromList(`${groupNoRole.name}`); - groupCloudComponent.checkSelectedGroup(`${groupNoRole.name}`); + groupCloudComponentPage.searchGroups('TestGroup'); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupNoRole.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupNoRole.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupNoRole.name}`); }); }); diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 19aac34cb4..98ac96b848 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -15,16 +15,12 @@ * limitations under the License. */ -import { LoginSSOPage } from '@alfresco/adf-testing'; import { SettingsPage } from '../pages/adf/settingsPage'; -import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { StartTasksCloudPage } from '@alfresco/adf-testing'; -import { StringUtil } from '@alfresco/adf-testing'; -import { PeopleCloudComponent } from '../pages/adf/process-cloud/peopleCloudComponent'; -import { TaskHeaderCloudPage } from '@alfresco/adf-testing'; +import { LoginSSOPage, AppListCloudPage, StringUtil, TaskHeaderCloudPage, + StartTasksCloudPage, PeopleCloudComponentPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Start Task', () => { @@ -36,7 +32,7 @@ describe('Start Task', () => { const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); const startTask = new StartTasksCloudPage(); - const peopleCloudComponent = new PeopleCloudComponent(); + const peopleCloudComponent = new PeopleCloudComponentPage(); const standaloneTaskName = StringUtil.generateRandomString(5); const unassignedTaskName = StringUtil.generateRandomString(5); const taskName255Characters = StringUtil.generateRandomString(255); diff --git a/e2e/search/components/search-date-range.e2e.ts b/e2e/search/components/search-date-range.e2e.ts index 5751f72eca..60f8da3ea1 100644 --- a/e2e/search/components/search-date-range.e2e.ts +++ b/e2e/search/components/search-date-range.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '../../pages/adf/loginPage'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; -import { DataTableComponentPage } from '../../pages/adf/dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { DatePickerPage } from '../../pages/adf/material/datePickerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; diff --git a/e2e/search/components/search-number-range.e2e.ts b/e2e/search/components/search-number-range.e2e.ts index dd6426da91..91fbc0174e 100644 --- a/e2e/search/components/search-number-range.e2e.ts +++ b/e2e/search/components/search-number-range.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '../../pages/adf/loginPage'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; -import { DataTableComponentPage } from '../../pages/adf/dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; diff --git a/e2e/search/components/search-slider.e2e.ts b/e2e/search/components/search-slider.e2e.ts index edad2a798f..e1e5178d4e 100644 --- a/e2e/search/components/search-slider.e2e.ts +++ b/e2e/search/components/search-slider.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '../../pages/adf/loginPage'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; -import { DataTableComponentPage } from '../../pages/adf/dataTableComponentPage'; +import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; diff --git a/e2e/pages/adf/dataTableComponentPage.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts similarity index 99% rename from e2e/pages/adf/dataTableComponentPage.ts rename to lib/testing/src/lib/core/pages/data-table-component.page.ts index f072c9b179..97b7851d25 100644 --- a/e2e/pages/adf/dataTableComponentPage.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -17,7 +17,7 @@ import { browser, by, element, protractor } from 'protractor'; import { ElementFinder, ElementArrayFinder } from 'protractor/built/element'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../browser-visibility'; export class DataTableComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/login-sso.page.ts b/lib/testing/src/lib/core/pages/login-sso.page.ts similarity index 100% rename from lib/testing/src/lib/process-services-cloud/pages/login-sso.page.ts rename to lib/testing/src/lib/core/pages/login-sso.page.ts diff --git a/lib/testing/src/lib/core/pages/public-api.ts b/lib/testing/src/lib/core/pages/public-api.ts index a1a7936cb0..53994f015b 100644 --- a/lib/testing/src/lib/core/pages/public-api.ts +++ b/lib/testing/src/lib/core/pages/public-api.ts @@ -17,3 +17,5 @@ export * from './header.page'; export * from './user-info.page'; +export * from './login-sso.page'; +export * from './data-table-component.page'; diff --git a/lib/testing/src/lib/core/pages/user-info.page.ts b/lib/testing/src/lib/core/pages/user-info.page.ts index 582b0d1307..ebd92363ce 100644 --- a/lib/testing/src/lib/core/pages/user-info.page.ts +++ b/lib/testing/src/lib/core/pages/user-info.page.ts @@ -17,7 +17,7 @@ import { element, by, browser, protractor } from 'protractor'; import { BrowserVisibility } from '../browser-visibility'; -import { TabsPage } from '../material/tabs.page'; +import { TabsPage } from '../../material/pages/tabs.page'; export class UserInfoPage { diff --git a/lib/testing/src/lib/core/public-api.ts b/lib/testing/src/lib/core/public-api.ts index a81925d1f1..7b19468b7b 100644 --- a/lib/testing/src/lib/core/public-api.ts +++ b/lib/testing/src/lib/core/public-api.ts @@ -18,6 +18,5 @@ export * from './browser-visibility'; export * from './actions/public-api'; export * from './pages/public-api'; -export * from './material/public-api'; export * from './models/public-api'; export * from './string.util'; diff --git a/lib/testing/src/lib/core/material/public-api.ts b/lib/testing/src/lib/material/pages/public-api.ts similarity index 100% rename from lib/testing/src/lib/core/material/public-api.ts rename to lib/testing/src/lib/material/pages/public-api.ts diff --git a/lib/testing/src/lib/core/material/tabs.page.ts b/lib/testing/src/lib/material/pages/tabs.page.ts similarity index 94% rename from lib/testing/src/lib/core/material/tabs.page.ts rename to lib/testing/src/lib/material/pages/tabs.page.ts index 12ae7bb8a2..b903167882 100644 --- a/lib/testing/src/lib/core/material/tabs.page.ts +++ b/lib/testing/src/lib/material/pages/tabs.page.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { BrowserVisibility } from '../browser-visibility'; +import { BrowserVisibility } from '../../core/browser-visibility'; export class TabsPage { diff --git a/lib/testing/src/lib/material/public-api.ts b/lib/testing/src/lib/material/public-api.ts index 5e77b5653c..4143973c23 100644 --- a/lib/testing/src/lib/material/public-api.ts +++ b/lib/testing/src/lib/material/public-api.ts @@ -15,4 +15,4 @@ * limitations under the License. */ -export * from './tabs.page'; +export * from './pages/public-api'; diff --git a/e2e/pages/adf/dialog/editProcessFilterDialog.ts b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts similarity index 96% rename from e2e/pages/adf/dialog/editProcessFilterDialog.ts rename to lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts index 34eae03507..9cd5c77568 100644 --- a/e2e/pages/adf/dialog/editProcessFilterDialog.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts @@ -16,9 +16,9 @@ */ import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../../core/browser-visibility'; -export class EditProcessFilterDialog { +export class EditProcessFilterDialogPage { componentElement = element(by.css('adf-cloud-process-filter-dialog-cloud')); title = element(by.id('adf-process-filter-dialog-title')); diff --git a/e2e/pages/adf/dialog/editTaskFilterDialog.ts b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts similarity index 96% rename from e2e/pages/adf/dialog/editTaskFilterDialog.ts rename to lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts index e4b91fb3c9..c86977900d 100644 --- a/e2e/pages/adf/dialog/editTaskFilterDialog.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts @@ -16,9 +16,9 @@ */ import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../../core/browser-visibility'; -export class EditTaskFilterDialog { +export class EditTaskFilterDialogPage { componentElement = element(by.css('adf-cloud-task-filter-dialog')); title = element(by.id('adf-task-filter-dialog-title')); diff --git a/lib/testing/src/lib/process-services-cloud/pages/dialog/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/dialog/public-api.ts new file mode 100644 index 0000000000..098d588160 --- /dev/null +++ b/lib/testing/src/lib/process-services-cloud/pages/dialog/public-api.ts @@ -0,0 +1,19 @@ +/*! + * @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. + */ + +export * from './edit-process-filter-dialog.page'; +export * from './edit-task-filter-dialog.page'; diff --git a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts similarity index 95% rename from e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts index 741b8cfaab..b683c0ddf2 100644 --- a/e2e/pages/adf/process-cloud/editProcessFilterCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts @@ -15,10 +15,10 @@ * limitations under the License. */ import { by, element, protractor } from 'protractor'; -import { EditProcessFilterDialog } from '../dialog/editProcessFilterDialog'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { EditProcessFilterDialogPage } from './dialog/edit-process-filter-dialog.page'; +import { BrowserVisibility } from '../../core/browser-visibility'; -export class EditProcessFilterCloudComponent { +export class EditProcessFilterCloudComponentPage { customiseFilter = element(by.id('adf-edit-process-filter-title-id')); selectedOption = element.all(by.css('mat-option[class*="mat-selected"]')).first(); @@ -26,10 +26,10 @@ export class EditProcessFilterCloudComponent { saveAsButton = element(by.css('button[data-automation-id="adf-filter-action-saveAs"]')); deleteButton = element(by.css('button[data-automation-id="adf-filter-action-delete"]')); - editProcessFilter = new EditProcessFilterDialog(); + editProcessFilterDialogPage = new EditProcessFilterDialogPage(); editProcessFilterDialog() { - return this.editProcessFilter; + return this.editProcessFilterDialogPage; } clickCustomiseFilterHeader() { @@ -183,7 +183,7 @@ export class EditProcessFilterCloudComponent { BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); this.saveAsButton.click(); - return this.editProcessFilter; + return this.editProcessFilterDialogPage; } clickDeleteButton() { diff --git a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts similarity index 96% rename from e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts index 988da9d5e8..10f35c6b55 100644 --- a/e2e/pages/adf/process-cloud/editTaskFilterCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts @@ -16,10 +16,10 @@ */ import { by, element, protractor } from 'protractor'; -import { EditTaskFilterDialog } from '../dialog/editTaskFilterDialog'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { EditTaskFilterDialogPage } from './dialog/edit-task-filter-dialog.page'; +import { BrowserVisibility } from '../../core/browser-visibility'; -export class EditTaskFilterCloudComponent { +export class EditTaskFilterCloudComponentPage { customiseFilter = element(by.id('adf-edit-task-filter-title-id')); selectedOption = element.all(by.css('mat-option[class*="mat-selected"]')).first(); @@ -36,10 +36,10 @@ export class EditTaskFilterCloudComponent { saveAsButton = element(by.css('[data-automation-id="adf-filter-action-saveAs"]')); deleteButton = element(by.css('[data-automation-id="adf-filter-action-delete"]')); - editTaskFilter = new EditTaskFilterDialog(); + editTaskFilterDialogPage = new EditTaskFilterDialogPage(); editTaskFilterDialog() { - return this.editTaskFilter; + return this.editTaskFilterDialogPage; } clickCustomiseFilterHeader() { @@ -185,7 +185,7 @@ export class EditTaskFilterCloudComponent { BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); this.saveAsButton.click(); - return this.editTaskFilter; + return this.editTaskFilterDialogPage; } clickDeleteButton() { diff --git a/e2e/pages/adf/process-cloud/groupCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts similarity index 95% rename from e2e/pages/adf/process-cloud/groupCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts index 8552a82d34..67c0320e67 100644 --- a/e2e/pages/adf/process-cloud/groupCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts @@ -16,9 +16,9 @@ */ import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../core/browser-visibility'; -export class GroupCloudComponent { +export class GroupCloudComponentPage { groupCloudSearch = element(by.css('input[data-automation-id="adf-cloud-group-search-input"]')); diff --git a/e2e/pages/adf/process-cloud/peopleCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts similarity index 96% rename from e2e/pages/adf/process-cloud/peopleCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts index 85f7f7c109..428dfeceb0 100644 --- a/e2e/pages/adf/process-cloud/peopleCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts @@ -16,9 +16,9 @@ */ import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../core/browser-visibility'; -export class PeopleCloudComponent { +export class PeopleCloudComponentPage { peopleCloudSearch = element(by.css('input[data-automation-id="adf-people-cloud-search-input"]')); diff --git a/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts similarity index 93% rename from e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts index 194b98bb8b..757f435948 100644 --- a/e2e/pages/adf/process-cloud/processFiltersCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts @@ -16,9 +16,9 @@ */ import { by } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../core/browser-visibility'; -export class ProcessFiltersCloudComponent { +export class ProcessFiltersCloudComponentPage { filter; filterIcon = by.xpath("ancestor::div[@class='mat-list-item-content']/mat-icon"); diff --git a/e2e/pages/adf/process-cloud/processListCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts similarity index 91% rename from e2e/pages/adf/process-cloud/processListCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts index 6107cb6e82..122b2ec6c7 100644 --- a/e2e/pages/adf/process-cloud/processListCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { BrowserVisibility } from '@alfresco/adf-testing'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { BrowserVisibility } from '../../core/browser-visibility'; +import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; import { element, by } from 'protractor'; -export class ProcessListCloudComponent { +export class ProcessListCloudComponentPage { processList = element(by.css('adf-cloud-process-list')); noProcessFound = element.all(by.css("div[class='adf-empty-content__title']")).first(); diff --git a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts index 09b6aca866..fc6d7d8bc3 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts @@ -15,7 +15,16 @@ * limitations under the License. */ -export * from './login-sso.page'; export * from './start-tasks-cloud-component.page'; export * from './task-header-cloud-component.page'; export * from './process-header-cloud-component.page'; +export * from './edit-process-filter-cloud-component.page'; +export * from './edit-task-filter-cloud-component.page'; +export * from './group-cloud-component.page'; +export * from './people-cloud-component.page'; +export * from './process-filters-cloud-component.page'; +export * from './process-list-cloud-component.page'; +export * from './task-filters-cloud-component.page'; +export * from './task-list-cloud-component.page'; + +export * from './dialog/public-api'; diff --git a/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts similarity index 93% rename from e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts index 2bca03e1bc..74708b8fac 100644 --- a/e2e/pages/adf/process-cloud/taskFiltersCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts @@ -16,9 +16,9 @@ */ import { by } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../core/browser-visibility'; -export class TaskFiltersCloudComponent { +export class TaskFiltersCloudComponentPage { filter; taskIcon = by.xpath("ancestor::div[@class='mat-list-item-content']/mat-icon"); diff --git a/e2e/pages/adf/process-cloud/taskListCloudComponent.ts b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts similarity index 94% rename from e2e/pages/adf/process-cloud/taskListCloudComponent.ts rename to lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts index db2b09186e..2f63478a6d 100644 --- a/e2e/pages/adf/process-cloud/taskListCloudComponent.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts @@ -15,15 +15,15 @@ * limitations under the License. */ -import { BrowserVisibility } from '@alfresco/adf-testing'; -import { DataTableComponentPage } from '../dataTableComponentPage'; +import { BrowserVisibility } from '../../core/browser-visibility'; +import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; import { element, by } from 'protractor'; const column = { id: 'Id' }; -export class TaskListCloudComponent { +export class TaskListCloudComponentPage { taskList = element(by.css('adf-cloud-task-list')); noTasksFound = element.all(by.css("div[class='adf-empty-content__title']")).first(); diff --git a/lib/testing/src/public-api.ts b/lib/testing/src/public-api.ts index 9b42b1066f..c5dd2500ac 100644 --- a/lib/testing/src/public-api.ts +++ b/lib/testing/src/public-api.ts @@ -16,8 +16,9 @@ */ export * from './lib/core/public-api'; -export * from './lib/core/material/public-api'; +export * from './lib/material/public-api'; export * from './lib/content-services/public-api'; +export * from './lib/material/public-api'; export * from './lib/process-services/public-api'; export * from './lib/process-services-cloud/public-api'; export * from './lib/testing.module'; From 62138392892710d8dfa7edfa0f593e2a6db2aee4 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 2 Apr 2019 19:03:10 +0100 Subject: [PATCH 044/208] [ADF-4279] Demo-shell - Fix home component layout (#4543) --- demo-shell/src/app/components/home/home.component.scss | 1 + .../layout-container/layout-container.component.scss | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/demo-shell/src/app/components/home/home.component.scss b/demo-shell/src/app/components/home/home.component.scss index b89e03522e..762e540786 100644 --- a/demo-shell/src/app/components/home/home.component.scss +++ b/demo-shell/src/app/components/home/home.component.scss @@ -2,6 +2,7 @@ display: flex; justify-content: center; align-items: center; + height: 100%; } .adf-home-header-background { diff --git a/lib/core/layout/components/layout-container/layout-container.component.scss b/lib/core/layout/components/layout-container/layout-container.component.scss index f67f8cd8fd..c3e4324621 100644 --- a/lib/core/layout/components/layout-container/layout-container.component.scss +++ b/lib/core/layout/components/layout-container/layout-container.component.scss @@ -9,18 +9,10 @@ overflow: hidden; } - [dir='rtl'] .adf-rtl-container-alignment { margin-left: 10px!important; } - ng-content { - display: block; - width: 100%; - height: 100%; - overflow: hidden; - } - .adf-sidenav--hidden { visibility: hidden !important; width: 0 !important; From a4fcedb44fad7a390988b9e7d87171b9eb630e8d Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 2 Apr 2019 19:04:11 +0100 Subject: [PATCH 045/208] [ADF-4343] Fix bug closing dialog on Host Settings Component (#4541) * [ADF-4343] Fix bug closing dialog on Host Settings Component * [ADF-4343] Improve code --- lib/core/settings/host-settings.component.html | 2 +- lib/core/settings/host-settings.component.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/core/settings/host-settings.component.html b/lib/core/settings/host-settings.component.html index 4ab4a213e4..2606a79f9e 100644 --- a/lib/core/settings/host-settings.component.html +++ b/lib/core/settings/host-settings.component.html @@ -3,7 +3,7 @@ <h3>{{'CORE.HOST_SETTINGS.TITLE' | translate}}</h3> </mat-toolbar> <mat-card class="adf-setting-card"> - <form id="host-form" [formGroup]="form" (submit)="onSubmit(form.value)"> + <form id="host-form" [formGroup]="form" (submit)="onSubmit(form.value)" (keydown)="keyDownFunction($event)"> <mat-form-field floatLabel="{{'CORE.HOST_SETTINGS.PROVIDER' | translate }}" *ngIf="showSelectProviders"> <mat-select id="adf-provider-selector" placeholder="Provider" [formControl]="providersControl"> diff --git a/lib/core/settings/host-settings.component.ts b/lib/core/settings/host-settings.component.ts index 9b9d357b1b..6d605c44c2 100644 --- a/lib/core/settings/host-settings.component.ts +++ b/lib/core/settings/host-settings.component.ts @@ -21,6 +21,7 @@ import { AppConfigService, AppConfigValues } from '../app-config/app-config.serv import { StorageService } from '../services/storage.service'; import { AlfrescoApiService } from '../services/alfresco-api.service'; import { OauthConfigModel } from '../models/oauth-config.model'; +import { ENTER } from '@angular/cdk/keycodes'; @Component({ selector: 'adf-host-settings', @@ -189,6 +190,12 @@ export class HostSettingsComponent implements OnInit { this.success.emit(true); } + keyDownFunction(event: any) { + if (event.keyCode === ENTER && this.form.valid) { + this.onSubmit(this.form.value); + } + } + private saveOAuthValues(values: any) { this.storageService.setItem(AppConfigValues.OAUTHCONFIG, JSON.stringify(values.oauthConfig)); this.storageService.setItem(AppConfigValues.IDENTITY_HOST, values.identityHost); From 38da39d8a53dfa72704402b54e8ad0c6a53563d9 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Tue, 2 Apr 2019 21:06:43 +0300 Subject: [PATCH 046/208] Refactored document-list-actions tests. (#4538) Added a new test for move file. --- .../document-list-actions.e2e.ts | 194 +++++++++--------- e2e/pages/adf/contentServicesPage.ts | 14 +- 2 files changed, 106 insertions(+), 102 deletions(-) diff --git a/e2e/content-services/document-list/document-list-actions.e2e.ts b/e2e/content-services/document-list/document-list-actions.e2e.ts index f14b564c43..e1fe05de4f 100644 --- a/e2e/content-services/document-list/document-list-actions.e2e.ts +++ b/e2e/content-services/document-list/document-list-actions.e2e.ts @@ -18,6 +18,7 @@ import { browser } from 'protractor'; import { LoginPage } from '../../pages/adf/loginPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); @@ -25,16 +26,21 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { FileModel } from '../../models/ACS/fileModel'; import { StringUtil } from '@alfresco/adf-testing'; +import { Util } from '../../util/util'; describe('Document List Component - Actions', () => { const loginPage = new LoginPage(); const contentServicesPage = new ContentServicesPage(); + const navigationBarPage = new NavigationBarPage(); const contentListPage = contentServicesPage.getDocumentList(); let uploadedFolder, secondUploadedFolder; const uploadActions = new UploadActions(); let acsUser = null; - let testFileNode; + let pdfUploadedNode; + let folderName; + let fileNames = []; + const nrOfFiles = 5; const pdfFileModel = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, @@ -45,81 +51,110 @@ describe('Document List Component - Actions', () => { 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - beforeAll(() => { + const files = { + base: 'newFile', + extension: '.txt' + }; + + beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', hostEcm: TestConfig.adf.url }); + + acsUser = new AcsUserModel(); + folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + pdfUploadedNode = await uploadActions.uploadFile(this.alfrescoJsApi, pdfFileModel.location, pdfFileModel.name, '-my-'); + await uploadActions.uploadFile(this.alfrescoJsApi, testFileModel.location, testFileModel.name, '-my-'); + uploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); + secondUploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, 'secondFolder', '-my-'); + + fileNames = Util.generateSequenceFiles(1, nrOfFiles, files.base, files.extension); + await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, uploadedFolder.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + + browser.driver.sleep(15000); + done(); + }); + + beforeEach(async (done) => { + navigationBarPage.clickAboutButton(); + navigationBarPage.clickContentServicesButton(); + done(); }); describe('File Actions', () => { - let pdfUploadedNode; - let folderName; - - beforeEach(async (done) => { - acsUser = new AcsUserModel(); - folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - pdfUploadedNode = await uploadActions.uploadFile(this.alfrescoJsApi, pdfFileModel.location, pdfFileModel.name, '-my-'); - testFileNode = await uploadActions.uploadFile(this.alfrescoJsApi, testFileModel.location, testFileModel.name, '-my-'); - uploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterEach(async (done) => { - try { - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, pdfUploadedNode.entry.id); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, testFileNode.entry.id); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, uploadedFolder.entry.id); - } catch (error) { - } - done(); - }); - it('[C213257] Should be able to copy a file', () => { - browser.driver.sleep(15000); + contentServicesPage.checkContentIsDisplayed(pdfUploadedNode.entry.name); - contentListPage.rightClickOnRow(pdfUploadedNode.entry.name); + contentServicesPage.getDocumentList().rightClickOnRow(pdfFileModel.name); contentServicesPage.pressContextMenuActionNamed('Copy'); + contentServicesPage.typeIntoNodeSelectorSearchField(folderName); contentServicesPage.clickContentNodeSelectorResult(folderName); - contentServicesPage.clickCopyButton(); + contentServicesPage.clickChooseButton(); contentServicesPage.checkContentIsDisplayed(pdfFileModel.name); contentServicesPage.doubleClickRow(uploadedFolder.entry.name); contentServicesPage.checkContentIsDisplayed(pdfFileModel.name); }); - it('[C280561] Should be able to delete a file via dropdown menu', () => { - contentServicesPage.deleteContent(pdfFileModel.name); - contentServicesPage.checkContentIsNotDisplayed(pdfFileModel.name); - pdfUploadedNode = null; - }); + it('[C297491] Should be able to move a file', () => { + contentServicesPage.checkContentIsDisplayed(testFileModel.name); - it('[C280562] Should be able to delete multiple files via dropdown menu', () => { - contentListPage.selectRow(pdfFileModel.name); - contentListPage.selectRow(testFileModel.name); - contentServicesPage.deleteContent(pdfFileModel.name); - contentServicesPage.checkContentIsNotDisplayed(pdfFileModel.name); + contentServicesPage.getDocumentList().rightClickOnRow(testFileModel.name); + contentServicesPage.pressContextMenuActionNamed('Move'); + contentServicesPage.typeIntoNodeSelectorSearchField(folderName); + contentServicesPage.clickContentNodeSelectorResult(folderName); + contentServicesPage.clickChooseButton(); + contentServicesPage.checkContentIsNotDisplayed(testFileModel.name); + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); contentServicesPage.checkContentIsDisplayed(testFileModel.name); }); + it('[C280561] Should be able to delete a file via dropdown menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentServicesPage.checkContentIsDisplayed(fileNames[0]); + contentServicesPage.deleteContent(fileNames[0]); + contentServicesPage.checkContentIsNotDisplayed(fileNames[0]); + }); + + it('[C280562] Only one file is deleted when multiple files are selected using dropdown menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentListPage.selectRow(fileNames[1]); + contentListPage.selectRow(fileNames[2]); + contentServicesPage.deleteContent(fileNames[1]); + contentServicesPage.checkContentIsNotDisplayed(fileNames[1]); + contentServicesPage.checkContentIsDisplayed(fileNames[2]); + }); + it('[C280565] Should be able to delete a file using context menu', () => { - contentListPage.rightClickOnRow(pdfFileModel.name); + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentListPage.rightClickOnRow(fileNames[2]); contentServicesPage.pressContextMenuActionNamed('Delete'); - contentServicesPage.checkContentIsNotDisplayed(pdfFileModel.name); - pdfUploadedNode = null; + contentServicesPage.checkContentIsNotDisplayed(fileNames[2]); + }); + + it('[C280567] Only one file is deleted when multiple files are selected using context menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentListPage.selectRow(fileNames[3]); + contentListPage.selectRow(fileNames[4]); + contentListPage.rightClickOnRow(fileNames[3]); + contentServicesPage.pressContextMenuActionNamed('Delete'); + contentServicesPage.checkContentIsNotDisplayed(fileNames[3]); + contentServicesPage.checkContentIsDisplayed(fileNames[4]); }); it('[C280566] Should be able to open context menu with right click', () => { - contentListPage.rightClickOnRow(pdfFileModel.name); + contentServicesPage.getDocumentList().rightClickOnRow(pdfFileModel.name); contentServicesPage.checkContextActionIsVisible('Download'); contentServicesPage.checkContextActionIsVisible('Copy'); contentServicesPage.checkContextActionIsVisible('Move'); @@ -128,57 +163,32 @@ describe('Document List Component - Actions', () => { contentServicesPage.checkContextActionIsVisible('Manage versions'); contentServicesPage.checkContextActionIsVisible('Permission'); contentServicesPage.checkContextActionIsVisible('Lock'); - }); - - it('[C280567] Should be able to delete multiple files using context menu', () => { - contentListPage.selectRow(pdfFileModel.name); - contentListPage.selectRow(testFileModel.name); - contentListPage.rightClickOnRow(pdfFileModel.name); - contentServicesPage.pressContextMenuActionNamed('Delete'); - contentServicesPage.checkContentIsNotDisplayed(pdfFileModel.name); - contentServicesPage.checkContentIsDisplayed(testFileModel.name); + contentServicesPage.closeActionContext(); }); }); describe('Folder Actions', () => { - let folderName, secondFolderName; - - beforeEach(async (done) => { - acsUser = new AcsUserModel(); - folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; - secondFolderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - uploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); - secondUploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, secondFolderName, '-my-'); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterEach(async (done) => { - try { - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, uploadedFolder.entry.id); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, secondUploadedFolder.entry.id); - } catch (error) { - } - done(); + it('[C260138] Should be able to copy a folder', () => { + contentServicesPage.copyContent(folderName); + contentServicesPage.typeIntoNodeSelectorSearchField(secondUploadedFolder.entry.name); + contentServicesPage.clickContentNodeSelectorResult(secondUploadedFolder.entry.name); + contentServicesPage.clickChooseButton(); + contentServicesPage.checkContentIsDisplayed(folderName); + contentServicesPage.doubleClickRow(secondUploadedFolder.entry.name); + contentServicesPage.checkContentIsDisplayed(folderName); }); it('[C260123] Should be able to delete a folder using context menu', () => { contentServicesPage.deleteContent(folderName); contentServicesPage.checkContentIsNotDisplayed(folderName); - uploadedFolder = null; }); it('[C280568] Should be able to open context menu with right click', () => { - contentListPage.rightClickOnRow(folderName); + contentServicesPage.checkContentIsDisplayed(secondUploadedFolder.entry.name); + + contentListPage.rightClickOnRow(secondUploadedFolder.entry.name); contentServicesPage.checkContextActionIsVisible('Download'); contentServicesPage.checkContextActionIsVisible('Copy'); contentServicesPage.checkContextActionIsVisible('Move'); @@ -187,18 +197,6 @@ describe('Document List Component - Actions', () => { contentServicesPage.checkContextActionIsVisible('Permission'); }); - it('[C260138] Should be able to copy a folder', () => { - browser.driver.sleep(15000); - - contentServicesPage.copyContent(folderName); - contentServicesPage.typeIntoNodeSelectorSearchField(secondFolderName); - contentServicesPage.clickContentNodeSelectorResult(secondFolderName); - contentServicesPage.clickCopyButton(); - contentServicesPage.checkContentIsDisplayed(folderName); - contentServicesPage.doubleClickRow(secondUploadedFolder.entry.name); - contentServicesPage.checkContentIsDisplayed(folderName); - }); - }); }); diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index 14617c7607..2cbcd74675 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -59,7 +59,7 @@ export class ContentServicesPage { emptyRecent = element(by.css('.adf-container-recent .adf-empty-list__title')); gridViewButton = element(by.css('button[data-automation-id="document-list-grid-view"]')); cardViewContainer = element(by.css('div.adf-document-list-container div.adf-datatable-card')); - copyButton = element(by.css('button[data-automation-id="content-node-selector-actions-choose"]')); + chooseButton = element(by.css('button[data-automation-id="content-node-selector-actions-choose"]')); searchInputElement = element(by.css('input[data-automation-id="content-node-selector-search-input"]')); shareNodeButton = element(by.cssContainingText('mat-icon', ' share ')); nameColumnHeader = 'name'; @@ -92,6 +92,11 @@ export class ContentServicesPage { return this.contentList; } + closeActionContext() { + browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); + return this; + } + checkLockedIcon(content) { return this.contentList.checkLockedIcon(content); } @@ -661,12 +666,13 @@ export class ContentServicesPage { clickContentNodeSelectorResult(name) { const resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[data-automation-id="${name}"`)).first(); BrowserVisibility.waitUntilElementIsVisible(resultElement); + BrowserVisibility.waitUntilElementIsClickable(resultElement); resultElement.click(); } - clickCopyButton() { - BrowserVisibility.waitUntilElementIsClickable(this.copyButton); - this.copyButton.click(); + clickChooseButton() { + BrowserVisibility.waitUntilElementIsClickable(this.chooseButton); + this.chooseButton.click(); } clickShareButton() { From 83c1e8a657302a082634819465b38bace5929ce0 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Tue, 2 Apr 2019 23:30:47 +0300 Subject: [PATCH 047/208] [ADF-4344]Fix e2e cloud tests. (#4542) * Fix e2e cloud tests. * no message --- .../edit-task-filters-component.e2e.ts | 2 +- .../people-group-cloud-component.e2e.ts | 2 +- e2e/process-services-cloud/process-custom-filters.e2e.ts | 2 +- e2e/process-services-cloud/process-filters-cloud.e2e.ts | 2 +- e2e/process-services-cloud/process-header-cloud.e2e.ts | 2 +- .../processList-cloud-component.e2e.ts | 2 +- e2e/process-services-cloud/task-filters-cloud.e2e.ts | 2 +- e2e/process-services-cloud/task-header-cloud.e2e.ts | 2 +- e2e/process-services-cloud/task-list-properties.e2e.ts | 2 +- e2e/process-services-cloud/task-list-selection.e2e.ts | 2 +- e2e/process-services-cloud/tasks-custom-filters.e2e.ts | 2 +- e2e/process-services/people-component.e2e.ts | 5 ----- 12 files changed, 11 insertions(+), 16 deletions(-) diff --git a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts index 8c8a1979a8..52044c65a1 100644 --- a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts @@ -48,7 +48,7 @@ describe('Edit task filters cloud', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 82f22adcf5..87d419dbef 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -54,7 +54,7 @@ describe('People Groups Cloud Component', () => { beforeAll(async () => { - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); identityService = new IdentityService(apiService); rolesService = new RolesService(apiService); diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index b895bf7ac0..7ca680049b 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -81,7 +81,7 @@ describe('Process list cloud', () => { configEditorPage.clickSaveButton(); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); processDefinitionService = new ProcessDefinitionsService(apiService); diff --git a/e2e/process-services-cloud/process-filters-cloud.e2e.ts b/e2e/process-services-cloud/process-filters-cloud.e2e.ts index 0b9ff8b3fb..e1267ff873 100644 --- a/e2e/process-services-cloud/process-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-filters-cloud.e2e.ts @@ -53,7 +53,7 @@ describe('Process filters cloud', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); processDefinitionService = new ProcessDefinitionsService(apiService); diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index 4cbe018c96..05235d23cb 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -55,7 +55,7 @@ describe('Process Header cloud component', () => { settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); processDefinitionService = new ProcessDefinitionsService(apiService); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index aa0499f6c3..83a5a8b5c2 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -48,7 +48,7 @@ describe('Process list cloud', () => { settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); processDefinitionService = new ProcessDefinitionsService(apiService); diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index 51f7e21664..040e55bc24 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -61,7 +61,7 @@ describe('Task filters cloud', () => { }); it('[C290009] Should display default filters and created task', async () => { - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index 7283102ef5..0d119ae704 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -54,7 +54,7 @@ describe('Task Header cloud component', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index 8965ab39be..c3b60c7e2d 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -110,7 +110,7 @@ describe('Edit task filters and task list properties', () => { configEditorPage.clickSaveButton(); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index 9ba734b21c..c896aecf13 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -50,7 +50,7 @@ describe('Task list cloud - selection', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index aa2d9d5396..add10d114e 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -55,7 +55,7 @@ describe('Task filters cloud', () => { browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); diff --git a/e2e/process-services/people-component.e2e.ts b/e2e/process-services/people-component.e2e.ts index cb9f11c0e7..b99b0f854e 100644 --- a/e2e/process-services/people-component.e2e.ts +++ b/e2e/process-services/people-component.e2e.ts @@ -180,8 +180,6 @@ describe('People component', () => { expect(taskPage.taskDetails().getInvolvedUserEmail(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName)) .toEqual(assigneeUserModel.email); - expect(taskPage.taskDetails().getInvolvedUserEditAction(assigneeUserModel.firstName + ' ' + assigneeUserModel.lastName)) - .toEqual('can edit'); expect(taskPage.taskDetails().getInvolvedPeopleTitle()).toEqual(peopleTitle + '(1)'); taskPage.taskDetails().clickInvolvePeopleButton() @@ -192,9 +190,6 @@ describe('People component', () => { expect(taskPage.taskDetails().getInvolvedUserEmail(secondAssigneeUserModel.firstName + ' ' + secondAssigneeUserModel.lastName)) .toEqual(secondAssigneeUserModel.email); - - expect(taskPage.taskDetails().getInvolvedUserEditAction(secondAssigneeUserModel.firstName + ' ' + secondAssigneeUserModel.lastName)) - .toEqual('can edit'); expect(taskPage.taskDetails().getInvolvedPeopleTitle()).toEqual(peopleTitle + '(2)'); }); From 1b65555e185316490ae97e17a3e8c9d01b819ce8 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 2 Apr 2019 23:42:46 +0100 Subject: [PATCH 048/208] fix identity service creation --- lib/testing/src/lib/core/actions/identity/identity.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/testing/src/lib/core/actions/identity/identity.service.ts b/lib/testing/src/lib/core/actions/identity/identity.service.ts index 5d7156fa22..e42a46e4a7 100644 --- a/lib/testing/src/lib/core/actions/identity/identity.service.ts +++ b/lib/testing/src/lib/core/actions/identity/identity.service.ts @@ -65,7 +65,7 @@ export class IdentityService { const queryParams = {}, postBody = { 'username': user.email, 'firstName': user.firstName, - 'lastName': user.lastName + 'LastName', + 'lastName': user.lastName, 'enabled': true, 'email': user.email }; From 3f2af4cc0366f2608ffdeee1dd77592420b37800 Mon Sep 17 00:00:00 2001 From: Vito <vito.albano@alfresco.com> Date: Tue, 2 Apr 2019 23:44:36 +0100 Subject: [PATCH 049/208] Exporting base login page (#4483) * Exporting base login page for e2e tests * fixed exporting and renamed pages as per standards * Added base login page to testing package * Fixed wrong import for the setting page * Removed old pages and using the one in the adf-testing package * fix after merge conflict * fix base url param --- .../comments/comment-component.e2e.ts | 2 +- .../directives/create-folder-directive.e2e.ts | 2 +- .../create-library-directive.e2e.ts | 2 +- .../document-list-actions.e2e.ts | 2 +- .../document-list-component.e2e.ts | 2 +- .../document-list-pagination.e2e.ts | 2 +- e2e/content-services/lock-file.e2e.ts | 2 +- .../notifications-component.e2e.ts | 2 +- .../permissions/permissions-component.e2e.ts | 2 +- .../permissions/site-permissions.e2e.ts | 2 +- .../share-file/share-file.e2e.ts | 2 +- .../share-file/unshare-file.e2e.ts | 2 +- .../sso-download-directive-component.e2e.ts | 4 +- e2e/content-services/tag-component.e2e.ts | 2 +- .../trashcan-pagination.e2e.ts | 2 +- .../tree-view-component.e2e.ts | 2 +- .../upload/cancel-upload.e2e.ts | 2 +- .../upload/excluded-file.e2e.ts | 2 +- e2e/content-services/upload/upload-dialog.ts | 2 +- .../upload/uploader-component.e2e.ts | 2 +- .../upload/user-permission.e2e.ts | 2 +- .../version/version-actions.e2e.ts | 2 +- .../version/version-permissions.e2e.ts | 2 +- .../version/version-properties.e2e.ts | 2 +- .../version/version-smoke-tests.e2e.ts | 2 +- .../card-view/aspect-oriented-config.e2e.ts | 2 +- e2e/core/card-view/card-view-component.e2e.ts | 2 +- .../card-view/metadata-permissions.e2e.ts | 2 +- e2e/core/card-view/metadata-properties.e2e.ts | 2 +- .../card-view/metadata-smoke-tests.e2e.ts | 2 +- .../data-table-component-selection.e2e.ts | 2 +- .../datatable/data-table-component.e2e.ts | 2 +- e2e/core/error-component.e2e.ts | 2 +- e2e/core/header-component.e2e.ts | 5 +- e2e/core/icons-component.e2e.ts | 2 +- e2e/core/infinite-scrolling.e2e.ts | 2 +- e2e/core/login/login-component.e2e.ts | 3 +- e2e/core/login/login-sso/login-sso.e2e.ts | 4 +- e2e/core/login/redirection.e2e.ts | 4 +- e2e/core/login/remember-me.e2e.ts | 3 +- e2e/core/pagination-empty-current-page.e2e.ts | 2 +- e2e/core/settings-component.e2e.ts | 3 +- e2e/core/user-info-component-cloud.e2e.ts | 3 +- e2e/core/user-info-component.e2e.ts | 3 +- e2e/core/viewer/info-drawer.component.e2e.ts | 2 +- e2e/core/viewer/viewer-component.e2e.ts | 2 +- .../viewer-content-services-component.e2e.ts | 2 +- .../viewer-custom-toolbar-info-drawer.e2e.ts | 2 +- e2e/core/viewer/viewer-properties.e2e.ts | 2 +- e2e/insights/analytics-component.e2e.ts | 2 +- .../process-services/tasksCloudDemoPage.ts | 5 +- e2e/pages/adf/dialog/shareDialog.ts | 3 +- e2e/pages/adf/dialog/uploadToggles.ts | 4 +- .../dialog/appSettingsToggles.ts | 2 +- e2e/pages/adf/versionManagerPage.ts | 2 +- e2e/pages/adf/viewerPage.ts | 2 +- .../apps-section-cloud.e2e.ts | 3 +- .../edit-process-filters-component.e2e.ts | 3 +- .../edit-task-filters-component.e2e.ts | 5 +- .../people-group-cloud-component.e2e.ts | 2 +- .../process-custom-filters.e2e.ts | 4 +- .../process-filters-cloud.e2e.ts | 3 +- .../process-header-cloud.e2e.ts | 3 +- .../processList-cloud-component.e2e.ts | 3 +- .../start-process-cloud.e2e.ts | 3 +- .../start-task-custom-app-cloud.e2e.ts | 3 +- .../task-filters-cloud.e2e.ts | 5 +- .../task-header-cloud.e2e.ts | 5 +- .../task-list-properties.e2e.ts | 7 +-- .../task-list-selection.e2e.ts | 3 +- .../tasks-custom-filters.e2e.ts | 3 +- e2e/process-services/apps-section.e2e.ts | 2 +- .../attach-file-widget.e2e.ts | 2 +- .../attach-form-component.e2e.ts | 2 +- .../checklist-component.e2e.ts | 2 +- .../comment-component-processes.e2e.ts | 2 +- .../comment-component-tasks.e2e.ts | 2 +- .../custom-process-filters-sorting.e2e.ts | 2 +- .../custom-process-filters.e2e.ts | 2 +- .../custom-tasks-filters.e2e.ts | 2 +- .../dynamic-table-date-picker.e2e.ts | 2 +- .../empty-process-list-component.e2e.ts | 2 +- e2e/process-services/form-component.e2e.ts | 2 +- .../form-people-widget.e2e.ts | 2 +- .../form-widgets-component.e2e.ts | 2 +- ...ination-processlist-addingProcesses.e2e.ts | 2 +- .../pagination-tasklist-addingTasks.e2e.ts | 2 +- e2e/process-services/people-component.e2e.ts | 2 +- .../process-attachmentList-actionMenu.e2e.ts | 2 +- .../process-filters-component.e2e.ts | 2 +- .../processList-component.e2e.ts | 2 +- .../processlist-pagination.e2e.ts | 2 +- .../sort-tasklist-pagination.e2e.ts | 2 +- e2e/process-services/standalone-task.e2e.ts | 2 +- .../start-process-component.e2e.ts | 2 +- .../start-task-custom-app.e2e.ts | 2 +- .../start-task-task-app.e2e.ts | 2 +- .../task-attachmentList-actionMenu.e2e.ts | 2 +- e2e/process-services/task-audit.e2e.ts | 2 +- e2e/process-services/task-details-form.e2e.ts | 2 +- .../task-details-no-form.e2e.ts | 2 +- e2e/process-services/task-details.e2e.ts | 2 +- .../task-filters-component.e2e.ts | 2 +- .../task-filters-sorting.e2e.ts | 2 +- .../task-list-pagination.e2e.ts | 2 +- .../widgets/amount-widget.e2e.ts | 2 +- .../widgets/attach-folder-widget.e2e.ts | 2 +- .../widgets/checkbox-widget.e2e.ts | 2 +- .../widgets/date-time-widget.e2e.ts | 2 +- .../widgets/date-widget.e2e.ts | 2 +- .../widgets/document-template-widget.e2e.ts | 2 +- .../widgets/dropdown-widget.e2e.ts | 2 +- .../widgets/dynamic-table-widget.e2e.ts | 2 +- .../widgets/header-widget.e2e.ts | 2 +- .../widgets/hyperlink-widget.e2e.ts | 2 +- .../widgets/multi-line-widget.e2e.ts | 2 +- .../widgets/number-widget.e2e.ts | 2 +- .../widgets/people-widget.e2e.ts | 2 +- .../widgets/radio-buttons-widget.e2e.ts | 2 +- .../widgets/text-widget.e2e.ts | 2 +- e2e/search/components/search-checkList.e2e.ts | 2 +- .../components/search-date-range.e2e.ts | 2 +- .../components/search-number-range.e2e.ts | 2 +- e2e/search/components/search-radio.e2e.ts | 2 +- e2e/search/components/search-slider.e2e.ts | 2 +- .../components/search-sorting-picker.e2e.ts | 2 +- e2e/search/components/search-text.e2e.ts | 2 +- e2e/search/search-component.e2e.ts | 2 +- e2e/search/search-filters.e2e.ts | 2 +- e2e/search/search-multiselect.e2e.ts | 2 +- e2e/search/search-page-component.e2e.ts | 2 +- .../lib/core/pages/form-controller.page.ts | 2 +- .../testing/src/lib/core/pages/login.page.ts | 54 +++++++++++++------ lib/testing/src/lib/core/pages/public-api.ts | 3 ++ .../src/lib/core/pages/settings.page.ts | 11 ++-- 135 files changed, 182 insertions(+), 195 deletions(-) rename e2e/pages/adf/material/formControllersPage.ts => lib/testing/src/lib/core/pages/form-controller.page.ts (96%) rename e2e/pages/adf/loginPage.ts => lib/testing/src/lib/core/pages/login.page.ts (85%) rename e2e/pages/adf/settingsPage.ts => lib/testing/src/lib/core/pages/settings.page.ts (96%) diff --git a/e2e/content-services/comments/comment-component.e2e.ts b/e2e/content-services/comments/comment-component.e2e.ts index 3e4983be0a..cdf3804e56 100644 --- a/e2e/content-services/comments/comment-component.e2e.ts +++ b/e2e/content-services/comments/comment-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { CommentsPage } from '../../pages/adf/commentsPage'; diff --git a/e2e/content-services/directives/create-folder-directive.e2e.ts b/e2e/content-services/directives/create-folder-directive.e2e.ts index ec2563576c..2a58ef285e 100644 --- a/e2e/content-services/directives/create-folder-directive.e2e.ts +++ b/e2e/content-services/directives/create-folder-directive.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { CreateFolderDialog } from '../../pages/adf/dialog/createFolderDialog'; import { NotificationPage } from '../../pages/adf/notificationPage'; diff --git a/e2e/content-services/directives/create-library-directive.e2e.ts b/e2e/content-services/directives/create-library-directive.e2e.ts index e93d2835c9..1bb809503d 100644 --- a/e2e/content-services/directives/create-library-directive.e2e.ts +++ b/e2e/content-services/directives/create-library-directive.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { CreateLibraryDialog } from '../../pages/adf/dialog/createLibraryDialog'; import { CustomSources } from '../../pages/adf/demo-shell/customSourcesPage'; diff --git a/e2e/content-services/document-list/document-list-actions.e2e.ts b/e2e/content-services/document-list/document-list-actions.e2e.ts index e1fe05de4f..17ea90eee8 100644 --- a/e2e/content-services/document-list/document-list-actions.e2e.ts +++ b/e2e/content-services/document-list/document-list-actions.e2e.ts @@ -16,7 +16,7 @@ */ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; diff --git a/e2e/content-services/document-list/document-list-component.e2e.ts b/e2e/content-services/document-list/document-list-component.e2e.ts index f648f41114..a6d8852288 100644 --- a/e2e/content-services/document-list/document-list-component.e2e.ts +++ b/e2e/content-services/document-list/document-list-component.e2e.ts @@ -16,7 +16,7 @@ */ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; diff --git a/e2e/content-services/document-list/document-list-pagination.e2e.ts b/e2e/content-services/document-list/document-list-pagination.e2e.ts index 15f1238841..8e730e0ec7 100644 --- a/e2e/content-services/document-list/document-list-pagination.e2e.ts +++ b/e2e/content-services/document-list/document-list-pagination.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { PaginationPage } from '../../pages/adf/paginationPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; diff --git a/e2e/content-services/lock-file.e2e.ts b/e2e/content-services/lock-file.e2e.ts index 1739c05a48..3e83938ce6 100644 --- a/e2e/content-services/lock-file.e2e.ts +++ b/e2e/content-services/lock-file.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; diff --git a/e2e/content-services/notifications-component.e2e.ts b/e2e/content-services/notifications-component.e2e.ts index e5792fa2df..df320de920 100644 --- a/e2e/content-services/notifications-component.e2e.ts +++ b/e2e/content-services/notifications-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { AcsUserModel } from '../models/ACS/acsUserModel'; import TestConfig = require('../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; diff --git a/e2e/content-services/permissions/permissions-component.e2e.ts b/e2e/content-services/permissions/permissions-component.e2e.ts index 1d76745ef0..bf32ca226e 100644 --- a/e2e/content-services/permissions/permissions-component.e2e.ts +++ b/e2e/content-services/permissions/permissions-component.e2e.ts @@ -16,7 +16,7 @@ */ import { PermissionsPage } from '../../pages/adf/permissionsPage'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import TestConfig = require('../../test.config'); diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index 105c674833..cb2838f6db 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -17,7 +17,7 @@ import { PermissionsPage } from '../../pages/adf/permissionsPage'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; diff --git a/e2e/content-services/share-file/share-file.e2e.ts b/e2e/content-services/share-file/share-file.e2e.ts index 3776365a97..34fba382d1 100644 --- a/e2e/content-services/share-file/share-file.e2e.ts +++ b/e2e/content-services/share-file/share-file.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; diff --git a/e2e/content-services/share-file/unshare-file.e2e.ts b/e2e/content-services/share-file/unshare-file.e2e.ts index b4ca80e061..c0332e0a23 100644 --- a/e2e/content-services/share-file/unshare-file.e2e.ts +++ b/e2e/content-services/share-file/unshare-file.e2e.ts @@ -18,7 +18,7 @@ import CONSTANTS = require('../../util/constants'); import { StringUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ErrorPage } from '../../pages/adf/errorPage'; import { ShareDialog } from '../../pages/adf/dialog/shareDialog'; diff --git a/e2e/content-services/sso/sso-download-directive-component.e2e.ts b/e2e/content-services/sso/sso-download-directive-component.e2e.ts index 6bc59d5037..61e781042e 100644 --- a/e2e/content-services/sso/sso-download-directive-component.e2e.ts +++ b/e2e/content-services/sso/sso-download-directive-component.e2e.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { SettingsPage } from '../../pages/adf/settingsPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import TestConfig = require('../../test.config'); import { browser } from 'protractor'; @@ -28,8 +27,7 @@ import resources = require('../../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import * as path from 'path'; import { Util } from '../../util/util'; -import { IdentityService } from '@alfresco/adf-testing'; -import { StringUtil, UserModel } from '@alfresco/adf-testing'; +import { IdentityService, SettingsPage, StringUtil, UserModel } from '@alfresco/adf-testing'; describe('SSO in ADF using ACS and AIS, Download Directive, Viewer, DocumentList, implicitFlow true', () => { diff --git a/e2e/content-services/tag-component.e2e.ts b/e2e/content-services/tag-component.e2e.ts index 42fb4cdadd..ae5fc73875 100644 --- a/e2e/content-services/tag-component.e2e.ts +++ b/e2e/content-services/tag-component.e2e.ts @@ -18,7 +18,7 @@ import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FileModel } from '../models/ACS/fileModel'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TagPage } from '../pages/adf/tagPage'; import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; diff --git a/e2e/content-services/trashcan-pagination.e2e.ts b/e2e/content-services/trashcan-pagination.e2e.ts index 5657ac4521..6fcc1256fa 100644 --- a/e2e/content-services/trashcan-pagination.e2e.ts +++ b/e2e/content-services/trashcan-pagination.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TrashcanPage } from '../pages/adf/trashcanPage'; import { PaginationPage } from '../pages/adf/paginationPage'; diff --git a/e2e/content-services/tree-view-component.e2e.ts b/e2e/content-services/tree-view-component.e2e.ts index 5dbdb53c7f..5b76a6851b 100644 --- a/e2e/content-services/tree-view-component.e2e.ts +++ b/e2e/content-services/tree-view-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TreeViewPage } from '../pages/adf/content-services/treeViewPage'; diff --git a/e2e/content-services/upload/cancel-upload.e2e.ts b/e2e/content-services/upload/cancel-upload.e2e.ts index 7fecda8a48..da707cff01 100644 --- a/e2e/content-services/upload/cancel-upload.e2e.ts +++ b/e2e/content-services/upload/cancel-upload.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; import { UploadToggles } from '../../pages/adf/dialog/uploadToggles'; diff --git a/e2e/content-services/upload/excluded-file.e2e.ts b/e2e/content-services/upload/excluded-file.e2e.ts index 181d587dfa..7e12c348ce 100644 --- a/e2e/content-services/upload/excluded-file.e2e.ts +++ b/e2e/content-services/upload/excluded-file.e2e.ts @@ -17,7 +17,7 @@ import { element, by, browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; import { UploadToggles } from '../../pages/adf/dialog/uploadToggles'; diff --git a/e2e/content-services/upload/upload-dialog.ts b/e2e/content-services/upload/upload-dialog.ts index fdab497c4b..9782ca7783 100644 --- a/e2e/content-services/upload/upload-dialog.ts +++ b/e2e/content-services/upload/upload-dialog.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; import { UploadToggles } from '../../pages/adf/dialog/uploadToggles'; diff --git a/e2e/content-services/upload/uploader-component.e2e.ts b/e2e/content-services/upload/uploader-component.e2e.ts index 75c144f0b2..3934ba6a23 100644 --- a/e2e/content-services/upload/uploader-component.e2e.ts +++ b/e2e/content-services/upload/uploader-component.e2e.ts @@ -17,7 +17,7 @@ import { element, by, browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; import { UploadToggles } from '../../pages/adf/dialog/uploadToggles'; diff --git a/e2e/content-services/upload/user-permission.e2e.ts b/e2e/content-services/upload/user-permission.e2e.ts index 66bdb41a59..586a8d06cf 100644 --- a/e2e/content-services/upload/user-permission.e2e.ts +++ b/e2e/content-services/upload/user-permission.e2e.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { StringUtil } from '@alfresco/adf-testing'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; import { UploadToggles } from '../../pages/adf/dialog/uploadToggles'; diff --git a/e2e/content-services/version/version-actions.e2e.ts b/e2e/content-services/version/version-actions.e2e.ts index 7326f326a1..b41ee4b305 100644 --- a/e2e/content-services/version/version-actions.e2e.ts +++ b/e2e/content-services/version/version-actions.e2e.ts @@ -17,7 +17,7 @@ import { by, element } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { VersionManagePage } from '../../pages/adf/versionManagerPage'; diff --git a/e2e/content-services/version/version-permissions.e2e.ts b/e2e/content-services/version/version-permissions.e2e.ts index 0fa20ddedf..567f0470ea 100644 --- a/e2e/content-services/version/version-permissions.e2e.ts +++ b/e2e/content-services/version/version-permissions.e2e.ts @@ -17,7 +17,7 @@ import { element, by } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { VersionManagePage } from '../../pages/adf/versionManagerPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; diff --git a/e2e/content-services/version/version-properties.e2e.ts b/e2e/content-services/version/version-properties.e2e.ts index 7a8d6ab4f8..c3ae3e6fd3 100644 --- a/e2e/content-services/version/version-properties.e2e.ts +++ b/e2e/content-services/version/version-properties.e2e.ts @@ -17,7 +17,7 @@ import { by, element } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { VersionManagePage } from '../../pages/adf/versionManagerPage'; diff --git a/e2e/content-services/version/version-smoke-tests.e2e.ts b/e2e/content-services/version/version-smoke-tests.e2e.ts index dd541953dd..825ed36e99 100644 --- a/e2e/content-services/version/version-smoke-tests.e2e.ts +++ b/e2e/content-services/version/version-smoke-tests.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { VersionManagePage } from '../../pages/adf/versionManagerPage'; diff --git a/e2e/core/card-view/aspect-oriented-config.e2e.ts b/e2e/core/card-view/aspect-oriented-config.e2e.ts index d6f9889ae5..5dee4142f7 100644 --- a/e2e/core/card-view/aspect-oriented-config.e2e.ts +++ b/e2e/core/card-view/aspect-oriented-config.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; diff --git a/e2e/core/card-view/card-view-component.e2e.ts b/e2e/core/card-view/card-view-component.e2e.ts index 62452ef936..198e40156e 100644 --- a/e2e/core/card-view/card-view-component.e2e.ts +++ b/e2e/core/card-view/card-view-component.e2e.ts @@ -17,7 +17,7 @@ import { element, by } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; diff --git a/e2e/core/card-view/metadata-permissions.e2e.ts b/e2e/core/card-view/metadata-permissions.e2e.ts index eeb338b902..8c0197641e 100644 --- a/e2e/core/card-view/metadata-permissions.e2e.ts +++ b/e2e/core/card-view/metadata-permissions.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; diff --git a/e2e/core/card-view/metadata-properties.e2e.ts b/e2e/core/card-view/metadata-properties.e2e.ts index abd670ce0d..6afc23d447 100644 --- a/e2e/core/card-view/metadata-properties.e2e.ts +++ b/e2e/core/card-view/metadata-properties.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; diff --git a/e2e/core/card-view/metadata-smoke-tests.e2e.ts b/e2e/core/card-view/metadata-smoke-tests.e2e.ts index 7af069627d..6282516d47 100644 --- a/e2e/core/card-view/metadata-smoke-tests.e2e.ts +++ b/e2e/core/card-view/metadata-smoke-tests.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; diff --git a/e2e/core/datatable/data-table-component-selection.e2e.ts b/e2e/core/datatable/data-table-component-selection.e2e.ts index 72f2710573..ebabd0caad 100644 --- a/e2e/core/datatable/data-table-component-selection.e2e.ts +++ b/e2e/core/datatable/data-table-component-selection.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { DataTablePage } from '../../pages/adf/demo-shell/dataTablePage'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import TestConfig = require('../../test.config'); diff --git a/e2e/core/datatable/data-table-component.e2e.ts b/e2e/core/datatable/data-table-component.e2e.ts index 3a8df28acd..cb75e747ed 100644 --- a/e2e/core/datatable/data-table-component.e2e.ts +++ b/e2e/core/datatable/data-table-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { DataTablePage } from '../../pages/adf/demo-shell/dataTablePage'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; diff --git a/e2e/core/error-component.e2e.ts b/e2e/core/error-component.e2e.ts index e774dc6594..6aa47298d6 100644 --- a/e2e/core/error-component.e2e.ts +++ b/e2e/core/error-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { AcsUserModel } from '../models/ACS/acsUserModel'; import TestConfig = require('../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; diff --git a/e2e/core/header-component.e2e.ts b/e2e/core/header-component.e2e.ts index 33078d107b..8b1b31b5d2 100644 --- a/e2e/core/header-component.e2e.ts +++ b/e2e/core/header-component.e2e.ts @@ -14,11 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { HeaderPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { HeaderPage, SettingsPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; diff --git a/e2e/core/icons-component.e2e.ts b/e2e/core/icons-component.e2e.ts index ba2cdfe174..038b4ca415 100644 --- a/e2e/core/icons-component.e2e.ts +++ b/e2e/core/icons-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { IconsPage } from '../pages/adf/iconsPage'; import { AcsUserModel } from '../models/ACS/acsUserModel'; diff --git a/e2e/core/infinite-scrolling.e2e.ts b/e2e/core/infinite-scrolling.e2e.ts index c7417189d4..3cec6dd72d 100644 --- a/e2e/core/infinite-scrolling.e2e.ts +++ b/e2e/core/infinite-scrolling.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; import { InfinitePaginationPage } from '../pages/adf/core/infinitePaginationPage'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; diff --git a/e2e/core/login/login-component.e2e.ts b/e2e/core/login/login-component.e2e.ts index 4843c3d63e..99314fa33e 100644 --- a/e2e/core/login/login-component.e2e.ts +++ b/e2e/core/login/login-component.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage, SettingsPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ProcessServicesPage } from '../../pages/adf/process-services/processServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; @@ -27,7 +27,6 @@ import { UserInfoPage } from '@alfresco/adf-testing'; import TestConfig = require('../../test.config'); import { AcsUserModel } from '../../models/ACS/acsUserModel'; -import { SettingsPage } from '../../pages/adf/settingsPage'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { Util } from '../../util/util'; diff --git a/e2e/core/login/login-sso/login-sso.e2e.ts b/e2e/core/login/login-sso/login-sso.e2e.ts index 78821632d8..d1425912a0 100644 --- a/e2e/core/login/login-sso/login-sso.e2e.ts +++ b/e2e/core/login/login-sso/login-sso.e2e.ts @@ -15,12 +15,10 @@ * limitations under the License. */ -import { LoginSSOPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../../../pages/adf/settingsPage'; +import { LoginSSOPage, SettingsPage, LoginPage } from '@alfresco/adf-testing'; import TestConfig = require('../../../test.config'); import { browser } from 'protractor'; import { NavigationBarPage } from '../../../pages/adf/navigationBarPage'; -import { LoginPage } from '../../../pages/adf/loginPage'; describe('Login component - SSO', () => { diff --git a/e2e/core/login/redirection.e2e.ts b/e2e/core/login/redirection.e2e.ts index 2c366e3cc9..f74e77c202 100644 --- a/e2e/core/login/redirection.e2e.ts +++ b/e2e/core/login/redirection.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage, SettingsPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ProcessServicesPage } from '../../pages/adf/process-services/processServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; @@ -25,8 +25,6 @@ import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import TestConfig = require('../../test.config'); import { AcsUserModel } from '../../models/ACS/acsUserModel'; -import { SettingsPage } from '../../pages/adf/settingsPage'; - import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { StringUtil } from '@alfresco/adf-testing'; diff --git a/e2e/core/login/remember-me.e2e.ts b/e2e/core/login/remember-me.e2e.ts index 135e16de50..218324e055 100644 --- a/e2e/core/login/remember-me.e2e.ts +++ b/e2e/core/login/remember-me.e2e.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; -import { SettingsPage } from '../../pages/adf/settingsPage'; +import { LoginPage, SettingsPage } from '@alfresco/adf-testing'; describe('Login component - Remember Me', () => { diff --git a/e2e/core/pagination-empty-current-page.e2e.ts b/e2e/core/pagination-empty-current-page.e2e.ts index a9169c2685..6c7081dfb5 100644 --- a/e2e/core/pagination-empty-current-page.e2e.ts +++ b/e2e/core/pagination-empty-current-page.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; import { PaginationPage } from '../pages/adf/paginationPage'; import { ViewerPage } from '../pages/adf/viewerPage'; diff --git a/e2e/core/settings-component.e2e.ts b/e2e/core/settings-component.e2e.ts index ecbd392e4b..ce8c5e5b91 100644 --- a/e2e/core/settings-component.e2e.ts +++ b/e2e/core/settings-component.e2e.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { LoginPage, SettingsPage } from '@alfresco/adf-testing'; import { browser, protractor } from 'protractor'; import { AcsUserModel } from '../models/ACS/acsUserModel'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/core/user-info-component-cloud.e2e.ts b/e2e/core/user-info-component-cloud.e2e.ts index 88990d88d2..9b43ce973a 100644 --- a/e2e/core/user-info-component-cloud.e2e.ts +++ b/e2e/core/user-info-component-cloud.e2e.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { LoginSSOPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { UserInfoPage } from '@alfresco/adf-testing'; diff --git a/e2e/core/user-info-component.e2e.ts b/e2e/core/user-info-component.e2e.ts index 0d6758bba1..f19561679c 100644 --- a/e2e/core/user-info-component.e2e.ts +++ b/e2e/core/user-info-component.e2e.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { SettingsPage } from '../pages/adf/settingsPage'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage, SettingsPage } from '@alfresco/adf-testing'; import { UserInfoPage } from '@alfresco/adf-testing'; import { AcsUserModel } from '../models/ACS/acsUserModel'; diff --git a/e2e/core/viewer/info-drawer.component.e2e.ts b/e2e/core/viewer/info-drawer.component.e2e.ts index 4d21d1f9fa..c741c0e230 100644 --- a/e2e/core/viewer/info-drawer.component.e2e.ts +++ b/e2e/core/viewer/info-drawer.component.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../../test.config'); -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; diff --git a/e2e/core/viewer/viewer-component.e2e.ts b/e2e/core/viewer/viewer-component.e2e.ts index 9d313f9b68..8bcc16c698 100644 --- a/e2e/core/viewer/viewer-component.e2e.ts +++ b/e2e/core/viewer/viewer-component.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../../test.config'); -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; diff --git a/e2e/core/viewer/viewer-content-services-component.e2e.ts b/e2e/core/viewer/viewer-content-services-component.e2e.ts index 72c60c4f76..fcf81695dc 100644 --- a/e2e/core/viewer/viewer-content-services-component.e2e.ts +++ b/e2e/core/viewer/viewer-content-services-component.e2e.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import TestConfig = require('../../test.config'); -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; diff --git a/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts b/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts index 08f1dcb524..1fff45c986 100644 --- a/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts +++ b/e2e/core/viewer/viewer-custom-toolbar-info-drawer.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../../test.config'); -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; diff --git a/e2e/core/viewer/viewer-properties.e2e.ts b/e2e/core/viewer/viewer-properties.e2e.ts index 0dcf410121..ba5db13ea8 100644 --- a/e2e/core/viewer/viewer-properties.e2e.ts +++ b/e2e/core/viewer/viewer-properties.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../../test.config'); -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; diff --git a/e2e/insights/analytics-component.e2e.ts b/e2e/insights/analytics-component.e2e.ts index 41c775ff5e..3cd53312ea 100644 --- a/e2e/insights/analytics-component.e2e.ts +++ b/e2e/insights/analytics-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { AnalyticsPage } from '../pages/adf/process-services/analyticsPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index 248d546f39..b173ca623d 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -15,11 +15,8 @@ * limitations under the License. */ -import { EditTaskFilterCloudComponentPage, TaskFiltersCloudComponentPage } from '@alfresco/adf-testing'; -import { FormControllersPage } from '../../material/formControllersPage'; - import { element, by, browser } from 'protractor'; -import { BrowserVisibility, TaskListCloudComponentPage } from '@alfresco/adf-testing'; +import { FormControllersPage, TaskFiltersCloudComponentPage, EditTaskFilterCloudComponentPage, BrowserVisibility, TaskListCloudComponentPage } from '@alfresco/adf-testing'; export class TasksCloudDemoPage { diff --git a/e2e/pages/adf/dialog/shareDialog.ts b/e2e/pages/adf/dialog/shareDialog.ts index 3ff98bdcf9..32756f54fd 100644 --- a/e2e/pages/adf/dialog/shareDialog.ts +++ b/e2e/pages/adf/dialog/shareDialog.ts @@ -16,8 +16,7 @@ */ import { element, by } from 'protractor'; -import { FormControllersPage } from '../material/formControllersPage'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility, FormControllersPage } from '@alfresco/adf-testing'; export class ShareDialog { diff --git a/e2e/pages/adf/dialog/uploadToggles.ts b/e2e/pages/adf/dialog/uploadToggles.ts index c9f2ced0d4..2fb2652516 100644 --- a/e2e/pages/adf/dialog/uploadToggles.ts +++ b/e2e/pages/adf/dialog/uploadToggles.ts @@ -15,10 +15,8 @@ * limitations under the License. */ -import { FormControllersPage } from '../material/formControllersPage'; - import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility, FormControllersPage } from '@alfresco/adf-testing'; export class UploadToggles { diff --git a/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts b/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts index 69c59d9e1b..bc02c004ce 100644 --- a/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts +++ b/e2e/pages/adf/process-services/dialog/appSettingsToggles.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { FormControllersPage } from '../../material/formControllersPage'; +import { FormControllersPage } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; export class AppSettingsToggles { diff --git a/e2e/pages/adf/versionManagerPage.ts b/e2e/pages/adf/versionManagerPage.ts index 0db919f8c1..87bc62e3a3 100644 --- a/e2e/pages/adf/versionManagerPage.ts +++ b/e2e/pages/adf/versionManagerPage.ts @@ -19,7 +19,7 @@ import TestConfig = require('../../test.config'); import path = require('path'); import remote = require('selenium-webdriver/remote'); import { browser, by, element, protractor } from 'protractor'; -import { FormControllersPage } from './material/formControllersPage'; +import { FormControllersPage } from '@alfresco/adf-testing'; import { BrowserVisibility } from '@alfresco/adf-testing'; export class VersionManagePage { diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index a7232753a9..918d0cb756 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -16,7 +16,7 @@ */ import { TabsPage } from '@alfresco/adf-testing'; -import { FormControllersPage } from './material/formControllersPage'; +import { FormControllersPage } from '@alfresco/adf-testing'; import { element, by, browser, protractor } from 'protractor'; import { BrowserVisibility } from '@alfresco/adf-testing'; diff --git a/e2e/process-services-cloud/apps-section-cloud.e2e.ts b/e2e/process-services-cloud/apps-section-cloud.e2e.ts index a87ac0ed2f..b1442d00b5 100644 --- a/e2e/process-services-cloud/apps-section-cloud.e2e.ts +++ b/e2e/process-services-cloud/apps-section-cloud.e2e.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { LoginSSOPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts index 5f123bd4c4..9e7d3728fe 100644 --- a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts @@ -17,8 +17,7 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; diff --git a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts index 52044c65a1..a014dfd285 100644 --- a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts @@ -17,12 +17,9 @@ import TestConfig = require('../test.config'); -import { ApiService, LoginSSOPage, TasksService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { AppListCloudPage, StringUtil, ApiService, LoginSSOPage, TasksService, SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { AppListCloudPage } from '@alfresco/adf-testing'; -import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 87d419dbef..1f93f7170f 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../test.config'); -import { SettingsPage } from '../pages/adf/settingsPage'; +import { SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { PeopleGroupCloudComponentPage } from '../pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage'; import { GroupCloudComponentPage, PeopleCloudComponentPage } from '@alfresco/adf-testing'; diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index 7ca680049b..e0492af721 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -17,8 +17,8 @@ import TestConfig = require('../test.config'); -import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, + LoginSSOPage, ApiService, SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; diff --git a/e2e/process-services-cloud/process-filters-cloud.e2e.ts b/e2e/process-services-cloud/process-filters-cloud.e2e.ts index e1267ff873..fe1707ec95 100644 --- a/e2e/process-services-cloud/process-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-filters-cloud.e2e.ts @@ -17,8 +17,7 @@ import TestConfig = require('../test.config'); -import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService, SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index 05235d23cb..0be178c55c 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -20,8 +20,7 @@ import CONSTANTS = require('../util/constants'); import moment = require('moment'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { ApiService, StringUtil, LoginSSOPage, ProcessDefinitionsService, ProcessInstancesService, QueryService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { ApiService, StringUtil, LoginSSOPage, ProcessDefinitionsService, ProcessInstancesService, QueryService, SettingsPage } from '@alfresco/adf-testing'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { ProcessHeaderCloudPage } from '@alfresco/adf-testing'; diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index 83a5a8b5c2..b4763bda94 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -16,8 +16,7 @@ */ import TestConfig = require('../test.config'); -import { ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService, SettingsPage } from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index b14e313e5c..adf9112e75 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { LoginSSOPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 98ac96b848..be0709a98d 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -15,11 +15,10 @@ * limitations under the License. */ -import { SettingsPage } from '../pages/adf/settingsPage'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { LoginSSOPage, AppListCloudPage, StringUtil, TaskHeaderCloudPage, +import { LoginSSOPage, SettingsPage, AppListCloudPage, StringUtil, TaskHeaderCloudPage, StartTasksCloudPage, PeopleCloudComponentPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index 040e55bc24..ddf77536a9 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -17,12 +17,9 @@ import TestConfig = require('../test.config'); -import { LoginSSOPage, TasksService, ApiService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { LoginSSOPage, TasksService, ApiService, SettingsPage, AppListCloudPage, StringUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { AppListCloudPage } from '@alfresco/adf-testing'; -import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Task filters cloud', () => { diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index 0d119ae704..129b9dcfdd 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -21,11 +21,8 @@ import { ApiService, StringUtil } from '@alfresco/adf-testing'; import moment = require('moment'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { LoginSSOPage } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; -import { AppListCloudPage } from '@alfresco/adf-testing'; +import { LoginSSOPage, SettingsPage, AppListCloudPage, TaskHeaderCloudPage, TasksService } from '@alfresco/adf-testing'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { TaskHeaderCloudPage, TasksService } from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Task Header cloud component', () => { diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index c3b60c7e2d..29f896f039 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -17,11 +17,12 @@ import TestConfig = require('../test.config'); -import { StringUtil, TasksService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { StringUtil, TasksService, + ProcessDefinitionsService, ProcessInstancesService, + LoginSSOPage, ApiService, + SettingsPage, AppListCloudPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { AppListCloudPage } from '@alfresco/adf-testing'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { TaskListCloudConfiguration } from './taskListCloud.config'; diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index c896aecf13..bf3a95239c 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -17,8 +17,7 @@ import TestConfig = require('../test.config'); -import { ApiService, LoginSSOPage, TasksService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { ApiService, LoginSSOPage, TasksService, SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index add10d114e..09990a189e 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -17,8 +17,7 @@ import TestConfig = require('../test.config'); -import { StringUtil, TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService } from '@alfresco/adf-testing'; -import { SettingsPage } from '../pages/adf/settingsPage'; +import { StringUtil, TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService, SettingsPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; diff --git a/e2e/process-services/apps-section.e2e.ts b/e2e/process-services/apps-section.e2e.ts index 48af7cc2f4..252d9095e2 100644 --- a/e2e/process-services/apps-section.e2e.ts +++ b/e2e/process-services/apps-section.e2e.ts @@ -16,7 +16,7 @@ */ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/attach-file-widget.e2e.ts b/e2e/process-services/attach-file-widget.e2e.ts index 7eaa724f31..fe28c4298b 100644 --- a/e2e/process-services/attach-file-widget.e2e.ts +++ b/e2e/process-services/attach-file-widget.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { Widget } from '../pages/adf/process-services/widgets/widget'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; diff --git a/e2e/process-services/attach-form-component.e2e.ts b/e2e/process-services/attach-form-component.e2e.ts index 31730e5b36..c431e4efa7 100644 --- a/e2e/process-services/attach-form-component.e2e.ts +++ b/e2e/process-services/attach-form-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { AttachFormPage } from '../pages/adf/process-services/attachFormPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/checklist-component.e2e.ts b/e2e/process-services/checklist-component.e2e.ts index 822035851e..d4552b70df 100644 --- a/e2e/process-services/checklist-component.e2e.ts +++ b/e2e/process-services/checklist-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { ChecklistDialog } from '../pages/adf/process-services/dialog/createChecklistDialog'; diff --git a/e2e/process-services/comment-component-processes.e2e.ts b/e2e/process-services/comment-component-processes.e2e.ts index ea3b883321..ac826558ec 100644 --- a/e2e/process-services/comment-component-processes.e2e.ts +++ b/e2e/process-services/comment-component-processes.e2e.ts @@ -16,7 +16,7 @@ */ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { CommentsPage } from '../pages/adf/commentsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/comment-component-tasks.e2e.ts b/e2e/process-services/comment-component-tasks.e2e.ts index 9084373e67..881f52b18f 100644 --- a/e2e/process-services/comment-component-tasks.e2e.ts +++ b/e2e/process-services/comment-component-tasks.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { CommentsPage } from '../pages/adf/commentsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/custom-process-filters-sorting.e2e.ts b/e2e/process-services/custom-process-filters-sorting.e2e.ts index c383d5e635..c81da0d503 100644 --- a/e2e/process-services/custom-process-filters-sorting.e2e.ts +++ b/e2e/process-services/custom-process-filters-sorting.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { FiltersPage } from '../pages/adf/process-services/filtersPage'; diff --git a/e2e/process-services/custom-process-filters.e2e.ts b/e2e/process-services/custom-process-filters.e2e.ts index 8e403f8ddf..8ed646eca8 100644 --- a/e2e/process-services/custom-process-filters.e2e.ts +++ b/e2e/process-services/custom-process-filters.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; import { AppSettingsToggles } from '../pages/adf/process-services/dialog/appSettingsToggles'; diff --git a/e2e/process-services/custom-tasks-filters.e2e.ts b/e2e/process-services/custom-tasks-filters.e2e.ts index 298326c2ca..67ecdcda38 100644 --- a/e2e/process-services/custom-tasks-filters.e2e.ts +++ b/e2e/process-services/custom-tasks-filters.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TaskListDemoPage } from '../pages/adf/demo-shell/process-services/taskListDemoPage'; import { PaginationPage } from '../pages/adf/paginationPage'; diff --git a/e2e/process-services/dynamic-table-date-picker.e2e.ts b/e2e/process-services/dynamic-table-date-picker.e2e.ts index 2a8987158f..c803c4c7d1 100644 --- a/e2e/process-services/dynamic-table-date-picker.e2e.ts +++ b/e2e/process-services/dynamic-table-date-picker.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; import { DynamicTableWidget } from '../pages/adf/process-services/widgets/dynamicTableWidget'; diff --git a/e2e/process-services/empty-process-list-component.e2e.ts b/e2e/process-services/empty-process-list-component.e2e.ts index b682d04caa..7bb62245e7 100644 --- a/e2e/process-services/empty-process-list-component.e2e.ts +++ b/e2e/process-services/empty-process-list-component.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../test.config'); import resources = require('../util/resources'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; diff --git a/e2e/process-services/form-component.e2e.ts b/e2e/process-services/form-component.e2e.ts index 21972bb5ad..6eec84bc0a 100644 --- a/e2e/process-services/form-component.e2e.ts +++ b/e2e/process-services/form-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { FormPage } from '../pages/adf/process-services/formPage'; import { DateWidget } from '../pages/adf/process-services/widgets/dateWidget'; diff --git a/e2e/process-services/form-people-widget.e2e.ts b/e2e/process-services/form-people-widget.e2e.ts index 83b45cc6ca..e06d925993 100644 --- a/e2e/process-services/form-people-widget.e2e.ts +++ b/e2e/process-services/form-people-widget.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { Widget } from '../pages/adf/process-services/widgets/widget'; import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; diff --git a/e2e/process-services/form-widgets-component.e2e.ts b/e2e/process-services/form-widgets-component.e2e.ts index 07ad107a41..348433305b 100644 --- a/e2e/process-services/form-widgets-component.e2e.ts +++ b/e2e/process-services/form-widgets-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { Widget } from '../pages/adf/process-services/widgets/widget'; diff --git a/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts b/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts index 71db5dc9a9..fba08e2837 100644 --- a/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts +++ b/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { PaginationPage } from '../pages/adf/paginationPage'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; diff --git a/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts b/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts index 0516b6fcd5..79bffd22d6 100644 --- a/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts +++ b/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { PaginationPage } from '../pages/adf/paginationPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/people-component.e2e.ts b/e2e/process-services/people-component.e2e.ts index b99b0f854e..aac56ec1cc 100644 --- a/e2e/process-services/people-component.e2e.ts +++ b/e2e/process-services/people-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; diff --git a/e2e/process-services/process-attachmentList-actionMenu.e2e.ts b/e2e/process-services/process-attachmentList-actionMenu.e2e.ts index edfeb6e9fa..36d237c871 100644 --- a/e2e/process-services/process-attachmentList-actionMenu.e2e.ts +++ b/e2e/process-services/process-attachmentList-actionMenu.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; diff --git a/e2e/process-services/process-filters-component.e2e.ts b/e2e/process-services/process-filters-component.e2e.ts index a052ee2467..4df15b8ef0 100644 --- a/e2e/process-services/process-filters-component.e2e.ts +++ b/e2e/process-services/process-filters-component.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../test.config'); import resources = require('../util/resources'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; diff --git a/e2e/process-services/processList-component.e2e.ts b/e2e/process-services/processList-component.e2e.ts index 19e8179ce4..fe036553fc 100644 --- a/e2e/process-services/processList-component.e2e.ts +++ b/e2e/process-services/processList-component.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { ProcessListDemoPage } from '../pages/adf/demo-shell/process-services/processListDemoPage'; import TestConfig = require('../test.config'); diff --git a/e2e/process-services/processlist-pagination.e2e.ts b/e2e/process-services/processlist-pagination.e2e.ts index 0b9344c47e..a1042e3621 100644 --- a/e2e/process-services/processlist-pagination.e2e.ts +++ b/e2e/process-services/processlist-pagination.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { PaginationPage } from '../pages/adf/paginationPage'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; diff --git a/e2e/process-services/sort-tasklist-pagination.e2e.ts b/e2e/process-services/sort-tasklist-pagination.e2e.ts index ac7205b20b..113034500c 100644 --- a/e2e/process-services/sort-tasklist-pagination.e2e.ts +++ b/e2e/process-services/sort-tasklist-pagination.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { PaginationPage } from '../pages/adf/paginationPage'; diff --git a/e2e/process-services/standalone-task.e2e.ts b/e2e/process-services/standalone-task.e2e.ts index 56cd579b67..eb5b44a213 100644 --- a/e2e/process-services/standalone-task.e2e.ts +++ b/e2e/process-services/standalone-task.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/start-process-component.e2e.ts b/e2e/process-services/start-process-component.e2e.ts index be7abe67b4..f1e719297c 100644 --- a/e2e/process-services/start-process-component.e2e.ts +++ b/e2e/process-services/start-process-component.e2e.ts @@ -19,7 +19,7 @@ import { Util } from '../util/util'; import TestConfig = require('../test.config'); import resources = require('../util/resources'); import CONSTANTS = require('../util/constants'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; diff --git a/e2e/process-services/start-task-custom-app.e2e.ts b/e2e/process-services/start-task-custom-app.e2e.ts index 240bae6944..cfb88a8ff5 100644 --- a/e2e/process-services/start-task-custom-app.e2e.ts +++ b/e2e/process-services/start-task-custom-app.e2e.ts @@ -17,7 +17,7 @@ import { by } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; diff --git a/e2e/process-services/start-task-task-app.e2e.ts b/e2e/process-services/start-task-task-app.e2e.ts index 894ad6fd80..c58f988910 100644 --- a/e2e/process-services/start-task-task-app.e2e.ts +++ b/e2e/process-services/start-task-task-app.e2e.ts @@ -17,7 +17,7 @@ import { by } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; diff --git a/e2e/process-services/task-attachmentList-actionMenu.e2e.ts b/e2e/process-services/task-attachmentList-actionMenu.e2e.ts index c20dcb1134..7d52670a5d 100644 --- a/e2e/process-services/task-attachmentList-actionMenu.e2e.ts +++ b/e2e/process-services/task-attachmentList-actionMenu.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; diff --git a/e2e/process-services/task-audit.e2e.ts b/e2e/process-services/task-audit.e2e.ts index 7e2f87cf95..5b1f1bd628 100644 --- a/e2e/process-services/task-audit.e2e.ts +++ b/e2e/process-services/task-audit.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; diff --git a/e2e/process-services/task-details-form.e2e.ts b/e2e/process-services/task-details-form.e2e.ts index 04b7d0b13a..a2ebef68bf 100644 --- a/e2e/process-services/task-details-form.e2e.ts +++ b/e2e/process-services/task-details-form.e2e.ts @@ -19,7 +19,7 @@ import TestConfig = require('../test.config'); import { StringUtil } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksListPage } from '../pages/adf/process-services/tasksListPage'; diff --git a/e2e/process-services/task-details-no-form.e2e.ts b/e2e/process-services/task-details-no-form.e2e.ts index e1cd4d886b..c19c7d5168 100644 --- a/e2e/process-services/task-details-no-form.e2e.ts +++ b/e2e/process-services/task-details-no-form.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; diff --git a/e2e/process-services/task-details.e2e.ts b/e2e/process-services/task-details.e2e.ts index 4f3029c24a..179c4b2be2 100644 --- a/e2e/process-services/task-details.e2e.ts +++ b/e2e/process-services/task-details.e2e.ts @@ -30,7 +30,7 @@ import resources = require('../util/resources'); import CONSTANTS = require('../util/constants'); import dateFormat = require('dateformat'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { browser } from 'protractor'; diff --git a/e2e/process-services/task-filters-component.e2e.ts b/e2e/process-services/task-filters-component.e2e.ts index 1cafd90540..4cd281a933 100644 --- a/e2e/process-services/task-filters-component.e2e.ts +++ b/e2e/process-services/task-filters-component.e2e.ts @@ -18,7 +18,7 @@ import TestConfig = require('../test.config'); import resources = require('../util/resources'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; diff --git a/e2e/process-services/task-filters-sorting.e2e.ts b/e2e/process-services/task-filters-sorting.e2e.ts index ae21785790..5f4002c145 100644 --- a/e2e/process-services/task-filters-sorting.e2e.ts +++ b/e2e/process-services/task-filters-sorting.e2e.ts @@ -17,7 +17,7 @@ import TestConfig = require('../test.config'); import resources = require('../util/resources'); -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; diff --git a/e2e/process-services/task-list-pagination.e2e.ts b/e2e/process-services/task-list-pagination.e2e.ts index b65f420b75..5d35e95fb5 100644 --- a/e2e/process-services/task-list-pagination.e2e.ts +++ b/e2e/process-services/task-list-pagination.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { PaginationPage } from '../pages/adf/paginationPage'; diff --git a/e2e/process-services/widgets/amount-widget.e2e.ts b/e2e/process-services/widgets/amount-widget.e2e.ts index de643d7f88..879547e157 100644 --- a/e2e/process-services/widgets/amount-widget.e2e.ts +++ b/e2e/process-services/widgets/amount-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; diff --git a/e2e/process-services/widgets/attach-folder-widget.e2e.ts b/e2e/process-services/widgets/attach-folder-widget.e2e.ts index 4e525f947f..2c16364774 100644 --- a/e2e/process-services/widgets/attach-folder-widget.e2e.ts +++ b/e2e/process-services/widgets/attach-folder-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/checkbox-widget.e2e.ts b/e2e/process-services/widgets/checkbox-widget.e2e.ts index d219301e2e..94c2653f12 100644 --- a/e2e/process-services/widgets/checkbox-widget.e2e.ts +++ b/e2e/process-services/widgets/checkbox-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/date-time-widget.e2e.ts b/e2e/process-services/widgets/date-time-widget.e2e.ts index 38b298ccbf..b43b877a8a 100644 --- a/e2e/process-services/widgets/date-time-widget.e2e.ts +++ b/e2e/process-services/widgets/date-time-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/date-widget.e2e.ts b/e2e/process-services/widgets/date-widget.e2e.ts index bbb05992f0..777c0a2b90 100644 --- a/e2e/process-services/widgets/date-widget.e2e.ts +++ b/e2e/process-services/widgets/date-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/document-template-widget.e2e.ts b/e2e/process-services/widgets/document-template-widget.e2e.ts index dbb1362504..c4189cc227 100644 --- a/e2e/process-services/widgets/document-template-widget.e2e.ts +++ b/e2e/process-services/widgets/document-template-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/dropdown-widget.e2e.ts b/e2e/process-services/widgets/dropdown-widget.e2e.ts index f6b70432ff..ed6779e194 100644 --- a/e2e/process-services/widgets/dropdown-widget.e2e.ts +++ b/e2e/process-services/widgets/dropdown-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/dynamic-table-widget.e2e.ts b/e2e/process-services/widgets/dynamic-table-widget.e2e.ts index dce1b407f3..389c7486af 100644 --- a/e2e/process-services/widgets/dynamic-table-widget.e2e.ts +++ b/e2e/process-services/widgets/dynamic-table-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/header-widget.e2e.ts b/e2e/process-services/widgets/header-widget.e2e.ts index 4db48bb3ac..8c4740beb5 100644 --- a/e2e/process-services/widgets/header-widget.e2e.ts +++ b/e2e/process-services/widgets/header-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/hyperlink-widget.e2e.ts b/e2e/process-services/widgets/hyperlink-widget.e2e.ts index ac32b0a821..6c62e5a779 100644 --- a/e2e/process-services/widgets/hyperlink-widget.e2e.ts +++ b/e2e/process-services/widgets/hyperlink-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/multi-line-widget.e2e.ts b/e2e/process-services/widgets/multi-line-widget.e2e.ts index 17a2c7c498..cff8bb548d 100644 --- a/e2e/process-services/widgets/multi-line-widget.e2e.ts +++ b/e2e/process-services/widgets/multi-line-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/number-widget.e2e.ts b/e2e/process-services/widgets/number-widget.e2e.ts index 1eceff1581..1146b41440 100644 --- a/e2e/process-services/widgets/number-widget.e2e.ts +++ b/e2e/process-services/widgets/number-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; diff --git a/e2e/process-services/widgets/people-widget.e2e.ts b/e2e/process-services/widgets/people-widget.e2e.ts index c699259f09..2aa2617833 100644 --- a/e2e/process-services/widgets/people-widget.e2e.ts +++ b/e2e/process-services/widgets/people-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/radio-buttons-widget.e2e.ts b/e2e/process-services/widgets/radio-buttons-widget.e2e.ts index 9334770a86..72f91e6fa0 100644 --- a/e2e/process-services/widgets/radio-buttons-widget.e2e.ts +++ b/e2e/process-services/widgets/radio-buttons-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/process-services/widgets/text-widget.e2e.ts b/e2e/process-services/widgets/text-widget.e2e.ts index 43095cd11e..709e6a4ef0 100644 --- a/e2e/process-services/widgets/text-widget.e2e.ts +++ b/e2e/process-services/widgets/text-widget.e2e.ts @@ -19,7 +19,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { AppsActions } from '../../actions/APS/apps.actions'; import { UsersActions } from '../../actions/users.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../../pages/adf/process-services/tasksPage'; import { Widget } from '../../pages/adf/process-services/widgets/widget'; import CONSTANTS = require('../../util/constants'); diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index 73c56c4676..ed7e381289 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; diff --git a/e2e/search/components/search-date-range.e2e.ts b/e2e/search/components/search-date-range.e2e.ts index 60f8da3ea1..0bcabdc1ef 100644 --- a/e2e/search/components/search-date-range.e2e.ts +++ b/e2e/search/components/search-date-range.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; diff --git a/e2e/search/components/search-number-range.e2e.ts b/e2e/search/components/search-number-range.e2e.ts index 91fbc0174e..db621b8f69 100644 --- a/e2e/search/components/search-number-range.e2e.ts +++ b/e2e/search/components/search-number-range.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; diff --git a/e2e/search/components/search-radio.e2e.ts b/e2e/search/components/search-radio.e2e.ts index e515248938..871c33c19c 100644 --- a/e2e/search/components/search-radio.e2e.ts +++ b/e2e/search/components/search-radio.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; diff --git a/e2e/search/components/search-slider.e2e.ts b/e2e/search/components/search-slider.e2e.ts index e1e5178d4e..8a992351fc 100644 --- a/e2e/search/components/search-slider.e2e.ts +++ b/e2e/search/components/search-slider.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; diff --git a/e2e/search/components/search-sorting-picker.e2e.ts b/e2e/search/components/search-sorting-picker.e2e.ts index d35fd3b422..42b21caedb 100644 --- a/e2e/search/components/search-sorting-picker.e2e.ts +++ b/e2e/search/components/search-sorting-picker.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; diff --git a/e2e/search/components/search-text.e2e.ts b/e2e/search/components/search-text.e2e.ts index 25359fd54f..062e366c50 100644 --- a/e2e/search/components/search-text.e2e.ts +++ b/e2e/search/components/search-text.e2e.ts @@ -24,7 +24,7 @@ import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { LoginPage } from '../../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; diff --git a/e2e/search/search-component.e2e.ts b/e2e/search/search-component.e2e.ts index e0fdba8876..dfd514809e 100644 --- a/e2e/search/search-component.e2e.ts +++ b/e2e/search/search-component.e2e.ts @@ -17,7 +17,7 @@ import { browser, protractor } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; import { FilePreviewPage } from '../pages/adf/filePreviewPage'; diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index a71226d223..708e881d40 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { SearchFiltersPage } from '../pages/adf/searchFiltersPage'; import { PaginationPage } from '../pages/adf/paginationPage'; diff --git a/e2e/search/search-multiselect.e2e.ts b/e2e/search/search-multiselect.e2e.ts index 8b2934b333..f76105c9de 100644 --- a/e2e/search/search-multiselect.e2e.ts +++ b/e2e/search/search-multiselect.e2e.ts @@ -24,7 +24,7 @@ import CONSTANTS = require('../util/constants'); import { UploadActions } from '../actions/ACS/upload.actions'; import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../pages/adf/searchFiltersPage'; diff --git a/e2e/search/search-page-component.e2e.ts b/e2e/search/search-page-component.e2e.ts index a9d8d156ef..a684c9bc45 100644 --- a/e2e/search/search-page-component.e2e.ts +++ b/e2e/search/search-page-component.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '../pages/adf/loginPage'; +import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; diff --git a/e2e/pages/adf/material/formControllersPage.ts b/lib/testing/src/lib/core/pages/form-controller.page.ts similarity index 96% rename from e2e/pages/adf/material/formControllersPage.ts rename to lib/testing/src/lib/core/pages/form-controller.page.ts index 50b2ad0cce..9b2e566ee8 100644 --- a/e2e/pages/adf/material/formControllersPage.ts +++ b/lib/testing/src/lib/core/pages/form-controller.page.ts @@ -16,7 +16,7 @@ */ import { by } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../browser-visibility'; export class FormControllersPage { diff --git a/e2e/pages/adf/loginPage.ts b/lib/testing/src/lib/core/pages/login.page.ts similarity index 85% rename from e2e/pages/adf/loginPage.ts rename to lib/testing/src/lib/core/pages/login.page.ts index 704d0d2d31..0400a9178f 100644 --- a/e2e/pages/adf/loginPage.ts +++ b/lib/testing/src/lib/core/pages/login.page.ts @@ -15,32 +15,47 @@ * limitations under the License. */ -import { FormControllersPage } from './material/formControllersPage'; - -import { SettingsPage } from './settingsPage'; +import { FormControllersPage } from './form-controller.page'; import { browser, by, element, protractor } from 'protractor'; -import TestConfig = require('../../test.config'); -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../browser-visibility'; +import { SettingsPage } from './settings.page'; export class LoginPage { - formControllersPage = new FormControllersPage(); txtUsername = element(by.css('input[id="username"]')); txtPassword = element(by.css('input[id="password"]')); logoImg = element(by.css('img[id="adf-login-img-logo"]')); - successRouteTxt = element(by.css('input[data-automation-id="adf-success-route"]')); + successRouteTxt = element( + by.css('input[data-automation-id="adf-success-route"]') + ); logoTxt = element(by.css('input[data-automation-id="adf-url-logo"]')); - usernameTooltip = element(by.css('span[data-automation-id="username-error"]')); - passwordTooltip = element(by.css('span[data-automation-id="password-required"]')); + usernameTooltip = element( + by.css('span[data-automation-id="username-error"]') + ); + passwordTooltip = element( + by.css('span[data-automation-id="password-required"]') + ); loginTooltip = element(by.css('span[class="adf-login-error-message"]')); - usernameInactive = element(by.css('input[id="username"][aria-invalid="false"]')); - passwordInactive = element(by.css('input[id="password"][aria-invalid="false"]')); + usernameInactive = element( + by.css('input[id="username"][aria-invalid="false"]') + ); + passwordInactive = element( + by.css('input[id="password"][aria-invalid="false"]') + ); adfLogo = element(by.css('img[class="adf-img-logo ng-star-inserted"]')); - usernameHighlighted = element(by.css('input[id="username"][aria-invalid="true"]')); - passwordHighlighted = element(by.css('input[id="password"][aria-invalid="true"]')); + usernameHighlighted = element( + by.css('input[id="username"][aria-invalid="true"]') + ); + passwordHighlighted = element( + by.css('input[id="password"][aria-invalid="true"]') + ); signInButton = element(by.id('login-button')); - showPasswordElement = element(by.css('mat-icon[data-automation-id="show_password"]')); - hidePasswordElement = element(by.css('mat-icon[data-automation-id="hide_password"]')); + showPasswordElement = element( + by.css('mat-icon[data-automation-id="show_password"]') + ); + hidePasswordElement = element( + by.css('mat-icon[data-automation-id="hide_password"]') + ); rememberMe = element(by.css('mat-checkbox[id="adf-login-remember"]')); needHelp = element(by.css('div[id="adf-login-action-left"]')); register = element(by.css('div[id="adf-login-action-right"]')); @@ -50,7 +65,12 @@ export class LoginPage { logoSwitch = element(by.id('adf-toggle-logo')); header = element(by.id('adf-header')); settingsPage = new SettingsPage(); - settingsIcon = element(by.cssContainingText('a[data-automation-id="settings"] mat-icon', 'settings')); + settingsIcon = element( + by.cssContainingText( + 'a[data-automation-id="settings"] mat-icon', + 'settings' + ) + ); waitForElements() { BrowserVisibility.waitUntilElementIsVisible(this.txtUsername); @@ -163,7 +183,7 @@ export class LoginPage { goToLoginPage() { browser.waitForAngularEnabled(true); - browser.driver.get(TestConfig.adf.url + TestConfig.adf.port + '/login'); + browser.driver.get(browser.baseUrl + '/login'); this.waitForElements(); } diff --git a/lib/testing/src/lib/core/pages/public-api.ts b/lib/testing/src/lib/core/pages/public-api.ts index 53994f015b..111bfe31d1 100644 --- a/lib/testing/src/lib/core/pages/public-api.ts +++ b/lib/testing/src/lib/core/pages/public-api.ts @@ -17,5 +17,8 @@ export * from './header.page'; export * from './user-info.page'; +export * from './login.page'; +export * from './settings.page'; +export * from './form-controller.page'; export * from './login-sso.page'; export * from './data-table-component.page'; diff --git a/e2e/pages/adf/settingsPage.ts b/lib/testing/src/lib/core/pages/settings.page.ts similarity index 96% rename from e2e/pages/adf/settingsPage.ts rename to lib/testing/src/lib/core/pages/settings.page.ts index 653396ea5a..fc506e6fa1 100644 --- a/e2e/pages/adf/settingsPage.ts +++ b/lib/testing/src/lib/core/pages/settings.page.ts @@ -15,13 +15,12 @@ * limitations under the License. */ -import TestConfig = require('../../test.config'); import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../browser-visibility'; export class SettingsPage { - settingsURL = TestConfig.adf.url + TestConfig.adf.port + '/settings'; + settingsURL = browser.baseUrl + '/settings'; providerDropdown = element(by.css('mat-select[id="adf-provider-selector"] div[class="mat-select-arrow-wrapper"]')); ecmAndBpm = { option: element(by.xpath('//SPAN[@class="mat-option-text"][contains(text(),"ALL")]')), @@ -116,7 +115,7 @@ export class SettingsPage { this.goToSettingsPage(); this.setProvider(this.ecm.option, this.ecm.text); BrowserVisibility.waitUntilElementIsVisible(this.ecmText); - expect(this.bpmText.isPresent()).toBe(false); + expect(this.bpmText.isPresent()).toBeFalsy(); this.clickApply(); return this; } @@ -126,7 +125,7 @@ export class SettingsPage { this.setProvider(this.oauth.option, this.oauth.text); BrowserVisibility.waitUntilElementIsVisible(this.bpmText); BrowserVisibility.waitUntilElementIsVisible(this.ecmText); - expect(this.authHostText.isPresent()).toBe(true); + expect(this.authHostText.isPresent()).toBeTruthy(); this.clickApply(); return this; } @@ -184,7 +183,7 @@ export class SettingsPage { this.bpmText.sendKeys(processServiceURL); } - async setClientId(clientId: string = TestConfig.adf_aps.clientIdSso) { + async setClientId(clientId: string = browser.params.config.oauth2.clientId) { BrowserVisibility.waitUntilElementIsVisible(this.clientIdText); this.clientIdText.clear(); this.clientIdText.sendKeys(clientId); From 12f098417cc3c8b869db43a6860a05a7e1057272 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Tue, 2 Apr 2019 23:50:51 +0100 Subject: [PATCH 050/208] add protractor utils class (#4531) --- lib/testing/src/lib/core/protractor.util.ts | 32 +++++++++++++++++++++ lib/testing/src/lib/core/public-api.ts | 1 + 2 files changed, 33 insertions(+) create mode 100644 lib/testing/src/lib/core/protractor.util.ts diff --git a/lib/testing/src/lib/core/protractor.util.ts b/lib/testing/src/lib/core/protractor.util.ts new file mode 100644 index 0000000000..050465bf5d --- /dev/null +++ b/lib/testing/src/lib/core/protractor.util.ts @@ -0,0 +1,32 @@ +/*! + * @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 { ElementFinder, browser, by } from 'protractor'; + +/** + * Tagged template to convert a sting to an `ElementFinder`. + * @example ```const item = byCss`.adf-breadcrumb-item-current`;``` + * @example ```const item = byCss`${variable}`;``` + * @returns Instance of `ElementFinder` type. + */ +export function byCss( + literals: TemplateStringsArray, + ...placeholders: string[] +): ElementFinder { + const selector = literals[0] || placeholders[0]; + return browser.element(by.css(selector)); +} diff --git a/lib/testing/src/lib/core/public-api.ts b/lib/testing/src/lib/core/public-api.ts index 7b19468b7b..c8b49d3e7a 100644 --- a/lib/testing/src/lib/core/public-api.ts +++ b/lib/testing/src/lib/core/public-api.ts @@ -20,3 +20,4 @@ export * from './actions/public-api'; export * from './pages/public-api'; export * from './models/public-api'; export * from './string.util'; +export * from './protractor.util'; From a37a44cb6f19328624534bd342ca3e7f1843a02b Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 3 Apr 2019 00:51:05 +0100 Subject: [PATCH 051/208] increase size bundle check testing pkg --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2000280fa5..7c10a71e68 100644 --- a/package.json +++ b/package.json @@ -206,7 +206,7 @@ }, { "path": "./lib/dist/testing/bundles/adf-testing.umd.min.js", - "maxSize": "10 kb" + "maxSize": "40 kb" } ], "engines": { From f152a24dc28c44ec61d496a351eeaeb80689fc27 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Wed, 3 Apr 2019 13:47:05 +0300 Subject: [PATCH 052/208] [ADF-4350]Fix cloud tests (#4544) * Fix version-permissions tests * Fix the cloud tests * Fix process-services tests --- .../version/version-permissions.e2e.ts | 12 ++++++------ e2e/pages/adf/process-services/taskDetailsPage.ts | 6 ++++++ e2e/process-services/task-details-form.e2e.ts | 15 ++++----------- protractor.conf.js | 8 ++++++++ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/e2e/content-services/version/version-permissions.e2e.ts b/e2e/content-services/version/version-permissions.e2e.ts index 567f0470ea..3011e74ec3 100644 --- a/e2e/content-services/version/version-permissions.e2e.ts +++ b/e2e/content-services/version/version-permissions.e2e.ts @@ -316,12 +316,6 @@ describe('Version component permissions', () => { uploadDialog.clickOnCloseButton(); }); - it('[C277203] Should a user with Collaborator permission not be able to upload a new version for a locked file', () => { - contentServices.getDocumentList().rightClickOnRow(lockFileModel.name); - const actionVersion = contentServices.checkContextActionIsVisible('Manage versions'); - expect(actionVersion.isEnabled()).toBeFalsy(); - }); - it('[C277199] should a user with Collaborator permission be able to upload a new version for a file with different creator', () => { contentServices.versionManagerContent(differentCreatorFile.name); @@ -341,6 +335,12 @@ describe('Version component permissions', () => { versionManagePage.closeVersionDialog(); }); + + it('[C277203] Should a user with Collaborator permission not be able to upload a new version for a locked file', () => { + contentServices.getDocumentList().rightClickOnRow(lockFileModel.name); + const actionVersion = contentServices.checkContextActionIsVisible('Manage versions'); + expect(actionVersion.isEnabled()).toBeFalsy(); + }); }); }); diff --git a/e2e/pages/adf/process-services/taskDetailsPage.ts b/e2e/pages/adf/process-services/taskDetailsPage.ts index 8a4afdb963..c4de906ac2 100644 --- a/e2e/pages/adf/process-services/taskDetailsPage.ts +++ b/e2e/pages/adf/process-services/taskDetailsPage.ts @@ -157,6 +157,12 @@ export class TaskDetailsPage { return this.formNameField.getText(); } + clickForm() { + BrowserVisibility.waitUntilElementIsVisible(this.formNameField); + BrowserVisibility.waitUntilElementIsClickable(this.formNameField); + this.formNameField.click(); + } + getAssignee() { BrowserVisibility.waitUntilElementIsVisible(this.assigneeField); return this.assigneeField.getText(); diff --git a/e2e/process-services/task-details-form.e2e.ts b/e2e/process-services/task-details-form.e2e.ts index a2ebef68bf..05ab626b6a 100644 --- a/e2e/process-services/task-details-form.e2e.ts +++ b/e2e/process-services/task-details-form.e2e.ts @@ -102,9 +102,7 @@ describe('Task Details - Form', () => { it('[C280018] Should be able to change the form in a task', () => { tasksListPage.selectRow(task.name); - - taskDetailsPage.checkEditFormButtonIsDisplayed(); - taskDetailsPage.clickEditFormButton(); + taskDetailsPage.clickForm(); taskDetailsPage.checkAttachFormDropdownIsDisplayed(); taskDetailsPage.checkAttachFormButtonIsDisabled(); @@ -120,8 +118,7 @@ describe('Task Details - Form', () => { taskDetailsPage.checkFormIsAttached(attachedForm.name); - taskDetailsPage.checkEditFormButtonIsDisplayed(); - taskDetailsPage.clickEditFormButton(); + taskDetailsPage.clickForm(); taskDetailsPage.checkAttachFormDropdownIsDisplayed(); taskDetailsPage.clickAttachFormDropdown(); @@ -136,9 +133,7 @@ describe('Task Details - Form', () => { it('[C280019] Should be able to remove the form form a task', () => { tasksListPage.selectRow(task.name); - - taskDetailsPage.checkEditFormButtonIsDisplayed(); - taskDetailsPage.clickEditFormButton(); + taskDetailsPage.clickForm(); taskDetailsPage.checkRemoveAttachFormIsDisplayed(); taskDetailsPage.clickRemoveAttachForm(); @@ -150,9 +145,7 @@ describe('Task Details - Form', () => { it('[C280557] Should display task details when selecting another task while the Attach Form dialog is displayed', () => { tasksListPage.selectRow(task.name); - - taskDetailsPage.checkEditFormButtonIsDisplayed(); - taskDetailsPage.clickEditFormButton(); + taskDetailsPage.clickForm(); taskDetailsPage.checkRemoveAttachFormIsDisplayed(); diff --git a/protractor.conf.js b/protractor.conf.js index 5f3b028222..7ddc2d8454 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -176,6 +176,14 @@ exports.config = { baseUrl: "http://" + HOST, + params: { + config: { + oauth2: { + clientId: 'activiti' + } + } + }, + framework: 'jasmine2', jasmineNodeOpts: { From 0800c406cd0dda22dfb030c33c0b6c0871117fd9 Mon Sep 17 00:00:00 2001 From: Vito <vito.albano@alfresco.com> Date: Wed, 3 Apr 2019 17:56:37 +0100 Subject: [PATCH 053/208] [ADF-4328] added expandedSideNav as new user preference value (#4545) * [ADF-4328] added expandedSideNav as new user preference value * [ADF-4328] update demo shell with the new User preference value * [ADF-4328] added documentation update --- .../src/app/components/app-layout/app-layout.component.ts | 4 ++-- docs/core/services/user-preferences.service.md | 2 +- lib/core/services/user-preferences.service.ts | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index 5a732acda3..f1075cfbc9 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -16,7 +16,7 @@ */ import { Component, ViewEncapsulation, OnInit } from '@angular/core'; -import { UserPreferencesService, AppConfigService, AlfrescoApiService } from '@alfresco/adf-core'; +import { UserPreferencesService, AppConfigService, AlfrescoApiService, UserPreferenceValues } from '@alfresco/adf-core'; import { HeaderDataService } from '../header-data/header-data.service'; @Component({ @@ -123,7 +123,7 @@ export class AppLayoutComponent implements OnInit { setState(state) { if (this.config.get('sideNav.preserveState')) { - this.userPreferences.set('expandedSidenav', state); + this.userPreferences.set(UserPreferenceValues.ExpandedSideNavStatus, state); } } } diff --git a/docs/core/services/user-preferences.service.md b/docs/core/services/user-preferences.service.md index b3f7853569..78e5deac19 100644 --- a/docs/core/services/user-preferences.service.md +++ b/docs/core/services/user-preferences.service.md @@ -108,7 +108,7 @@ whole set of user properties. This is useful when a component needs to react to ``` You can also use the `select` method to get notification when a particular property is changed. -A set of basic properties is added into the enumeration [`UserPreferenceValues`](../../../lib/core/services/user-preferences.service.ts) which gives you the key value to access the standard user preference service properties : **PaginationSize**, **DisableCSRF**, **Locale** and **SupportedPageSizes**. +A set of basic properties is added into the enumeration [`UserPreferenceValues`](../../../lib/core/services/user-preferences.service.ts) which gives you the key value to access the standard user preference service properties : **PaginationSize**, **DisableCSRF**, **Locale**, **SupportedPageSizes** and **ExpandedSideNavStatus**. ```ts userPreferences.disableCSRF = true; diff --git a/lib/core/services/user-preferences.service.ts b/lib/core/services/user-preferences.service.ts index a3f178aa39..5cd8a9c29c 100644 --- a/lib/core/services/user-preferences.service.ts +++ b/lib/core/services/user-preferences.service.ts @@ -25,7 +25,8 @@ import { distinctUntilChanged, map } from 'rxjs/operators'; export enum UserPreferenceValues { PaginationSize = 'paginationSize', Locale = 'locale', - SupportedPageSizes = 'supportedPageSizes' + SupportedPageSizes = 'supportedPageSizes', + ExpandedSideNavStatus = 'expandedSidenav' } @Injectable({ @@ -36,7 +37,8 @@ export class UserPreferencesService { defaults = { paginationSize: 25, supportedPageSizes: [5, 10, 15, 20], - locale: 'en' + locale: 'en', + expandedSidenav: true }; private userPreferenceStatus: any = this.defaults; From 4ebc8e25272d491b7c3b5a7153d4bcf580503988 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Thu, 4 Apr 2019 12:13:35 +0100 Subject: [PATCH 054/208] [ADF-4142] Remove processDefinitionKey property from EditTaskCloud component docs (#4552) --- .../components/edit-task-filter-cloud.component.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/process-services-cloud/components/edit-task-filter-cloud.component.md b/docs/process-services-cloud/components/edit-task-filter-cloud.component.md index 4812bee72f..0637f72421 100644 --- a/docs/process-services-cloud/components/edit-task-filter-cloud.component.md +++ b/docs/process-services-cloud/components/edit-task-filter-cloud.component.md @@ -88,7 +88,6 @@ given below: | **_standAlone_** | Standalone status of the task | | **_owner_** | User ID of the task's owner | | **_processDefinitionId_** | Process definition ID | -| **_processDefinitionKey_** | Process definition key | | **_processInstanceId_** | Process instance ID | | **_lastModified_** | Date the task was last modified. If lastModified defined the component will show the range **_lastModifiedFrom_**, **_lastModifiedTo_** | | **_sort_** | Field on which the filter results will be sorted (doesn't participate in the filtering itself). Can be "id", "name", "createdDate", "priority", "processDefinitionId". | From c5ac798c5beec46d5d445680736a66d1346ae98e Mon Sep 17 00:00:00 2001 From: Vito <vito.albano@alfresco.com> Date: Thu, 4 Apr 2019 12:44:47 +0100 Subject: [PATCH 055/208] [ADF-4327] added templating for content dialog (#4549) * [ADF-4327] added templating for content dialog * [ADF-4327] added unit test and documentation --- demo-shell/resources/i18n/en.json | 3 +- demo-shell/src/app/app.module.ts | 4 +- demo-shell/src/app/app.routes.ts | 5 + .../app-layout/app-layout.component.ts | 1 + .../confirm-dialog-example.component.html | 18 +++ .../confirm-dialog-example.component.scss | 0 .../confirm-dialog-example.component.ts | 51 +++++++ .../dialogs/confirm.dialog.md | 28 ++++ .../dialogs/confirm.dialog.html | 17 +++ .../dialogs/confirm.dialog.scss | 7 + .../dialogs/confirm.dialog.spec.ts | 143 ++++++++++++++++++ .../dialogs/confirm.dialog.ts | 31 ++-- 12 files changed, 286 insertions(+), 22 deletions(-) create mode 100644 demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html create mode 100644 demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.scss create mode 100644 demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts create mode 100644 lib/content-services/dialogs/confirm.dialog.html create mode 100644 lib/content-services/dialogs/confirm.dialog.scss create mode 100644 lib/content-services/dialogs/confirm.dialog.spec.ts diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index b9e088971b..17e745dcd7 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -94,7 +94,8 @@ "ICONS": "Icons", "PEOPLE_GROUPS_CLOUD": "People/Group Cloud", "PEOPLE_CLOUD": "People Cloud Component", - "GROUPS_CLOUD": "Groups Cloud Component" + "GROUPS_CLOUD": "Groups Cloud Component", + "CONFIRM-DIALOG": "Confirmation Dialog" }, "TRASHCAN": { "ACTIONS": { diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 8487d54fdc..2b06d1f38c 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -81,6 +81,7 @@ import { TemplateDemoComponent } from './components/template-list/template-demo. import { PeopleGroupCloudDemoComponent } from './components/cloud/people-groups-cloud-demo.component'; import { CloudSettingsComponent } from './components/cloud/cloud-settings.component'; import { NestedMenuPositionDirective } from './components/cloud/directives/nested-menu-position.directive'; +import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component'; @NgModule({ imports: [ @@ -148,7 +149,8 @@ import { NestedMenuPositionDirective } from './components/cloud/directives/neste TemplateDemoComponent, PeopleGroupCloudDemoComponent, CloudSettingsComponent, - NestedMenuPositionDirective + NestedMenuPositionDirective, + ConfirmDialogExampleComponent ], providers: [ { diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 75f35e58ca..f3ab662b28 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -49,6 +49,7 @@ import { StartProcessCloudDemoComponent } from './components/cloud/start-process import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; import { TemplateDemoComponent } from './components/template-list/template-demo.component'; +import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component'; export const appRoutes: Routes = [ { path: 'login', component: LoginComponent }, @@ -209,6 +210,10 @@ export const appRoutes: Routes = [ path: 'node-selector', loadChildren: 'app/components/content-node-selector/content-node-selector.module#AppContentNodeSelectorModule' }, + { + path: 'confirm-dialog', + component: ConfirmDialogExampleComponent + }, { path: 'settings-layout', loadChildren: 'app/components/settings/settings.module#AppSettingsModule' diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index f1075cfbc9..e084b44383 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -41,6 +41,7 @@ export class AppLayoutComponent implements OnInit { { href: '/breadcrumb', icon: 'label', title: 'APP_LAYOUT.BREADCRUMB' }, { href: '/notifications', icon: 'alarm', title: 'APP_LAYOUT.NOTIFICATIONS' }, { href: '/card-view', icon: 'view_headline', title: 'APP_LAYOUT.CARD_VIEW' }, + { href: '/confirm-dialog', icon: 'view_headline', title: 'APP_LAYOUT.CONFIRM-DIALOG' }, { href: '/header-data', icon: 'edit', title: 'APP_LAYOUT.HEADER_DATA' }, { href: '/node-selector', icon: 'attachment', title: 'APP_LAYOUT.NODE-SELECTOR' }, { href: '/sites', icon: 'format_list_bulleted', title: 'APP_LAYOUT.SITES' }, diff --git a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html new file mode 100644 index 0000000000..8aa5bc2bce --- /dev/null +++ b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html @@ -0,0 +1,18 @@ +<mat-accordion> + <mat-expansion-panel> + <mat-expansion-panel-header> + <mat-panel-title> + Confirm Dialog Default Behaviour + </mat-panel-title> + </mat-expansion-panel-header> + <button mat-raised-button (click)="openConfirmDefaultDialog()">Open Default Dialog</button> + </mat-expansion-panel> + <mat-expansion-panel> + <mat-expansion-panel-header> + <mat-panel-title> + Confirm Dialog Custom Template + </mat-panel-title> + </mat-expansion-panel-header> + <button mat-raised-button (click)="openConfirmCustomDialog()">Open Custom Dialog</button> + </mat-expansion-panel> + </mat-accordion> diff --git a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.scss b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts new file mode 100644 index 0000000000..66dc79ce91 --- /dev/null +++ b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts @@ -0,0 +1,51 @@ +/*! + * @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 } from '@angular/core'; +import { MatDialog } from '@angular/material'; +import { ConfirmDialogComponent } from '@alfresco/adf-content-services'; + +@Component({ + selector: 'app-confirm-dialog-example', + templateUrl: 'confirm-dialog-example.component.html', + styleUrls: ['confirm-dialog-example.component.scss'] +}) +export class ConfirmDialogExampleComponent { + + constructor(private dialog: MatDialog) { } + + openConfirmDefaultDialog() { + this.dialog.open(ConfirmDialogComponent, { + data: { + title: 'Upload', + message: `This is the default message` + }, + minWidth: '250px' + }); + } + + openConfirmCustomDialog() { + this.dialog.open(ConfirmDialogComponent, { + data: { + title: 'Upload', + message: `This is the default message`, + htmlContent: '<div> <p>A</p> <p>Custom</p> <p>Content</p> </div>' + }, + minWidth: '250px' + }); + } +} diff --git a/docs/content-services/dialogs/confirm.dialog.md b/docs/content-services/dialogs/confirm.dialog.md index 2e593e792a..5c5a4e7e45 100644 --- a/docs/content-services/dialogs/confirm.dialog.md +++ b/docs/content-services/dialogs/confirm.dialog.md @@ -37,6 +37,34 @@ dialogRef.afterClosed().subscribe((result) => { }); ``` +### Rendering custom html body +It is possible now to render a custom html instead of a plain message as confirm body via the attribute `htmlContent`. The html will be sanitized and then showed. + + +```ts +constructor(private dialog: MatDialog) {} + +... + +let files = [ + // Files defined here... +]; + +const dialogRef = this.dialog.open(ConfirmDialogComponent, { + data: { + title: 'Upload', + htmlContent: '<div> <p>A</p> <p>Custom</p> <p>Content</p> </div>' + }, + minWidth: '250px' +}); + +dialogRef.afterClosed().subscribe((result) => { + if (result === true) { + event.resumeUpload(); + } +}); +``` + ## Details This component lets the user make a yes/no choice to confirm an action. Use the diff --git a/lib/content-services/dialogs/confirm.dialog.html b/lib/content-services/dialogs/confirm.dialog.html new file mode 100644 index 0000000000..0d7869e587 --- /dev/null +++ b/lib/content-services/dialogs/confirm.dialog.html @@ -0,0 +1,17 @@ +<h1 mat-dialog-title data-automation-id="adf-confirm-dialog-title">{{ title | translate }}</h1> +<mat-dialog-content> + <p *ngIf="!htmlContent; else cutomContent" data-automation-id="adf-confirm-dialog-base-message"> + {{ message | translate }} + </p> + <ng-template #cutomContent> + <span [innerHTML]="sanitizedHtmlContent()" data-automation-id="adf-confirm-dialog-custom-content"> + </span> + </ng-template> +</mat-dialog-content> +<mat-dialog-actions> + <span class="adf-dialog-spacer" data-automation-id="adf-confirm-dialog-spacer"></span> + <button id="adf-confirm-accept" mat-button color="primary" data-automation-id="adf-confirm-dialog-confirmation" + [mat-dialog-close]="true">{{ yesLabel | translate }}</button> + <button id="adf-confirm-cancel" mat-button [mat-dialog-close]="false" data-automation-id="adf-confirm-dialog-reject" + cdkFocusInitial>{{ noLabel | translate }}</button> +</mat-dialog-actions> diff --git a/lib/content-services/dialogs/confirm.dialog.scss b/lib/content-services/dialogs/confirm.dialog.scss new file mode 100644 index 0000000000..2475496a16 --- /dev/null +++ b/lib/content-services/dialogs/confirm.dialog.scss @@ -0,0 +1,7 @@ +.adf-dialog-spacer { + flex: 1 1 auto; +} + +.adf-confirm-dialog .mat-dialog-actions .mat-button-wrapper { + text-transform: uppercase; +} diff --git a/lib/content-services/dialogs/confirm.dialog.spec.ts b/lib/content-services/dialogs/confirm.dialog.spec.ts new file mode 100644 index 0000000000..dba5684748 --- /dev/null +++ b/lib/content-services/dialogs/confirm.dialog.spec.ts @@ -0,0 +1,143 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { ComponentFixture } from '@angular/core/testing'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { setupTestBed } from '@alfresco/adf-core'; +import { ConfirmDialogComponent } from './confirm.dialog'; +import { ContentTestingModule } from '../testing/content.testing.module'; +import { By } from '@angular/platform-browser'; + +describe('Confirm Dialog Component', () => { + let fixture: ComponentFixture<ConfirmDialogComponent>; + let component: ConfirmDialogComponent; + const dialogRef = { + close: jasmine.createSpy('close') + }; + + const data = { + title: 'Fake Title', + message: 'Base Message', + yesLabel: 'TAKE THIS', + noLabel: 'MAYBE NO' + }; + + setupTestBed({ + imports: [ContentTestingModule], + providers: [ + { provide: MatDialogRef, useValue: dialogRef }, + { provide: MAT_DIALOG_DATA, useValue: data } + ] + }); + + beforeEach(() => { + dialogRef.close.calls.reset(); + fixture = TestBed.createComponent(ConfirmDialogComponent); + component = fixture.componentInstance; + }); + + afterEach(() => { + fixture.destroy(); + }); + + describe('When no html is given', () => { + beforeEach(() => { + fixture.detectChanges(); + }); + + it('should init form with folder name and description', () => { + expect(component.title).toBe('Fake Title'); + expect(component.message).toBe('Base Message'); + expect(component.yesLabel).toBe('TAKE THIS'); + expect(component.noLabel).toBe('MAYBE NO'); + }); + + it('should render the title', () => { + const titleElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-title"]') + ); + expect(titleElement).not.toBeNull(); + expect(titleElement.nativeElement.innerText).toBe('Fake Title'); + }); + + it('should render the message', () => { + const messageElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-base-message"]') + ); + expect(messageElement).not.toBeNull(); + expect(messageElement.nativeElement.innerText).toBe('Base Message'); + }); + + it('should render the YES label', () => { + const messageElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-confirmation"]') + ); + expect(messageElement).not.toBeNull(); + expect(messageElement.nativeElement.innerText).toBe('TAKE THIS'); + }); + + it('should render the NO label', () => { + const messageElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-reject"]') + ); + expect(messageElement).not.toBeNull(); + expect(messageElement.nativeElement.innerText).toBe('MAYBE NO'); + }); + }); + + describe('When custom html is given', () => { + beforeEach(() => { + component.htmlContent = `<div> I am about to do to you what Limp Bizkit did to music in the late ’90s.</div>`; + fixture.detectChanges(); + }); + + it('should render the title', () => { + const titleElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-title"]') + ); + expect(titleElement).not.toBeNull(); + expect(titleElement.nativeElement.innerText).toBe('Fake Title'); + }); + + it('should render the custom html', () => { + const customElement = fixture.nativeElement.querySelector( + '[data-automation-id="adf-confirm-dialog-custom-content"] div' + ); + expect(customElement).not.toBeNull(); + expect(customElement.innerText).toBe( + 'I am about to do to you what Limp Bizkit did to music in the late ’90s.' + ); + }); + + it('should render the YES label', () => { + const messageElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-confirmation"]') + ); + expect(messageElement).not.toBeNull(); + expect(messageElement.nativeElement.innerText).toBe('TAKE THIS'); + }); + + it('should render the NO label', () => { + const messageElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-reject"]') + ); + expect(messageElement).not.toBeNull(); + expect(messageElement.nativeElement.innerText).toBe('MAYBE NO'); + }); + }); +}); diff --git a/lib/content-services/dialogs/confirm.dialog.ts b/lib/content-services/dialogs/confirm.dialog.ts index d2e89d7272..b2ffef01ac 100644 --- a/lib/content-services/dialogs/confirm.dialog.ts +++ b/lib/content-services/dialogs/confirm.dialog.ts @@ -15,29 +15,14 @@ * limitations under the License. */ -import { Component, Inject, ViewEncapsulation } from '@angular/core'; +import { Component, Inject, ViewEncapsulation, SecurityContext } from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material'; +import { DomSanitizer } from '@angular/platform-browser'; @Component({ selector: 'adf-confirm-dialog', - template: ` - <h1 mat-dialog-title>{{ title | translate }}</h1> - <mat-dialog-content> - <p>{{ message | translate }}</p> - </mat-dialog-content> - <mat-dialog-actions> - <span class="spacer"></span> - <button id="adf-confirm-accept" mat-button color="primary" [mat-dialog-close]="true">{{ yesLabel | translate }}</button> - <button id="adf-confirm-cancel" mat-button [mat-dialog-close]="false" cdkFocusInitial>{{ noLabel | translate }}</button> - </mat-dialog-actions> - `, - styles: [` - .spacer { flex: 1 1 auto; } - - .adf-confirm-dialog .mat-dialog-actions .mat-button-wrapper { - text-transform: uppercase; - } - `], + templateUrl: './confirm.dialog.html', + styleUrls: ['./confirm.dialog.scss'], host: { 'class': 'adf-confirm-dialog' }, encapsulation: ViewEncapsulation.None }) @@ -47,12 +32,18 @@ export class ConfirmDialogComponent { message: string; yesLabel: string; noLabel: string; + htmlContent: string; - constructor(@Inject(MAT_DIALOG_DATA) data) { + constructor(@Inject(MAT_DIALOG_DATA) data, private sanitizer: DomSanitizer) { data = data || {}; this.title = data.title || 'ADF_CONFIRM_DIALOG.CONFIRM'; this.message = data.message || 'ADF_CONFIRM_DIALOG.MESSAGE'; this.yesLabel = data.yesLabel || 'ADF_CONFIRM_DIALOG.YES_LABEL'; this.noLabel = data.noLabel || 'ADF_CONFIRM_DIALOG.NO_LABEL'; + this.htmlContent = data.htmlContent; + } + + public sanitizedHtmlContent() { + return this.sanitizer.sanitize(SecurityContext.HTML, this.htmlContent); } } From 33c4460831dc88d48979ac62df811385e3ecc11a Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Thu, 4 Apr 2019 13:21:54 +0100 Subject: [PATCH 056/208] [ADF-4356] Added Activiti 7 tutorial after review (#4553) --- docs/tutorials/README.md | 1 + docs/tutorials/activiti-7-and-adf.md | 99 ++++++++++++++++++++++++++++ docs/user-guide/summary.json | 3 +- 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 docs/tutorials/activiti-7-and-adf.md diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index 831c9b5e35..818adbef2d 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -19,3 +19,4 @@ Github only: true | [**Working with the Nodes API Service**](working-with-nodes-api-service.md) | Intermediate | In this tutorial you will learn how to use the [`NodesApiService`](../core/services/nodes-api.service.md). | | [**Working with Nodes using the JS API**](working-with-nodes-js-api.md) | Intermediate | In this tutorial you will learn how to use the [`AlfrescoCoreRestApi`](https://github.com/Alfresco/alfresco-js-api/tree/master/src/alfresco-core-rest-api). | | [**Content metadata component**](content-metadata-component.md) | Advanced | In this tutorial you will learn how to work with the [`ContentMetadataComponent`](../content-services/components/content-metadata-card.component.md). | +| [**Building an ADF application on top of Activiti Cloud 7.0.0 GA Community Edition**](activiti-7-and-adf.md) | Intermediate | This tutorial shows how to configure an ADF app to connect to Activiti Cloud 7. | diff --git a/docs/tutorials/activiti-7-and-adf.md b/docs/tutorials/activiti-7-and-adf.md new file mode 100644 index 0000000000..9794a2cc02 --- /dev/null +++ b/docs/tutorials/activiti-7-and-adf.md @@ -0,0 +1,99 @@ +--- +Title: Activiti 7 and ADF +Level: Intermediate +--- + +# Building an ADF application on top of Activiti Cloud 7.0.0 GA Community Edition + +This tutorial shows how to configure an ADF app to connect to Activiti Cloud 7. + +[Activiti Cloud 7](https://www.activiti.org/) is the new generation cloud-native implementation +of Activiti BPM Engine. Starting with the +[ADF 3 major release](../release-notes/relnote300.md#activiti-7-support-experimental), +Alfresco began to support the Activiti 7 Engine within the ADF framework. We have nearly +finished implementing all the required features, and so in this tutorial we will explain how +to build an ADF application on top of Activiti Cloud 7.0.0 GA Community Edition. + +## Preparing Activiti 7 services + +As you can imagine, a prerequisite to create an ADF app like this is to have an instance of +Activiti 7 up and running. To learn how to install and setup your own +Activiti 7 instance, please follow the +[official documentation]([https://activiti.gitbook.io/activiti-7-developers-guide). + +Assuming that you already have your own instance of Activiti 7 up and running, a small tweak is required to make it work correctly with an ADF application. This is mainly a matter of how +the application is named, as described in detail below. + +### What ADF requires from Activiti 7 backend services + +By default, Activiti 7 starts a known list of services +(which are Kubernetes [pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/)) +for each application. Specifically, these include the runtime bundle, connectors, audit, and +query among others. Our interest here is the runtime bundle service, which is directly used +by all ADF applications. + +The runtime bundle service pod (generated by the default installation) has the name +`rb-[appName]` (usually `rb-my-app`) to begin with. An ADF application requires the runtime +bundle service to be available with the name `[appName]-rb` (usually `my-app-rb`). + +### How to change the name of the runtime bundle service + +You can change the default name of the runtime bundle easily using the +[helm charts](https://github.com/Activiti/activiti-cloud-charts). If you used the +[quick-start guide](https://activiti.gitbook.io/activiti-7-developers-guide/getting-started/getting-started-activiti-cloud) (deploying the "Activiti Cloud Full Example") you can change the +[values.yaml](https://github.com/Activiti/activiti-cloud-charts/blob/master/activiti-cloud-full-example/values.yaml) +file as shown below: + +```yaml + application: + runtime-bundle: + enabled: true + service: + name: my-app-rb \\ <-- change it here! + ... +``` + +When this is done, clean up your deployment environment (delete the pods and everything needed +to create a fresh environment, ready to be deployed again) and deploy Activiti 7 again, using +the modified helm chart. + +When Activiti 7 is up and running again, you will be then ready to build your own Alfresco ADF application on top of it. + +## Building the ADF application + +You can create an ADF application easily using the [Yeoman generator](https://yeoman.io/). +See our [tutorial](creating-the-app-using-yeoman.md) for a full description of +how to do this. Make sure you select "Process Services with Activiti" as the type of project +to create. + +Once this is created, do not change the `proxy.conf.json` file, but continue with the configuration as described in the following paragraph. You are now very close to the goal of having your own ADF +application working against Activiti 7 Community Edition backend services. + +## Configuring the ADF application + +To configure your existing ADF application, you just need to edit the `app.config.json` file. + +First of all, be sure you set up the `bpmHost`, `identityHost` and `host` properties with the +correct URL of the Activiti 7 deployment. It should look something like the example below: + +```json + ... + "bpmHost": "<Activiti7BaseUrl>", + "identityHost": "<Activiti7BaseUrl>/auth/realms/alfresco", + "providers": "BPM", + "application": { + "name": "Alfresco ADF Application" + }, + "authType": "OAUTH", + "oauth2": { + "host": "<Activiti7BaseUrl>/auth/realms/alfresco", + ... +``` + +Then, set the `alfresco-deployed-apps` property as shown below. + + "alfresco-deployed-apps": [{"name":"my-app"}] + +When you are done, save the `app.config.json` file and launch the application by executing +the `npm start` command. You should now be able to use your own ADF application +on top of Activiti 7 Community Edition backend services. diff --git a/docs/user-guide/summary.json b/docs/user-guide/summary.json index c9f0e69a7a..d7cdc7c546 100644 --- a/docs/user-guide/summary.json +++ b/docs/user-guide/summary.json @@ -19,7 +19,8 @@ { "title": "Working with a DataTable", "file": "working-with-data-table.md"}, { "title": "Working with the Nodes API Service", "file": "working-with-nodes-api-service.md"}, { "title": "Working with the Nodes using the JS API", "file": "working-with-nodes-js-api.md"}, - { "title": "Content metadata component", "file": "content-metadata-component.md"} + { "title": "Content metadata component", "file": "content-metadata-component.md"}, + { "title": "Activiti 7 and ADF", "file": "activiti-7-and-adf.md" } ] } ] From 37db6049376aaa6d98580351638aace426211a37 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 4 Apr 2019 19:50:54 +0100 Subject: [PATCH 057/208] fix lint organizations (#4558) --- angular.json | 16 ++++++++-------- lib/core/settings/host-settings.component.html | 2 +- lib/tslint.json | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/angular.json b/angular.json index ccbbd5959d..ec1106f1f1 100644 --- a/angular.json +++ b/angular.json @@ -563,8 +563,8 @@ "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ - "lib/core/tsconfig.json", - "lib/core/tsconfig.json" + "lib/core/tsconfig.lib.json", + "lib/core/tsconfig.lib.json" ], "exclude": [ "**/node_modules/**" @@ -605,8 +605,8 @@ "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ - "lib/content-services/tsconfig.json", - "lib/content-services/tsconfig.json" + "lib/content-services/tsconfig.lib.json", + "lib/content-services/tsconfig.lib.json" ], "exclude": [ "**/node_modules/**" @@ -647,8 +647,8 @@ "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ - "lib/process-services/tsconfig.json", - "lib/process-services/tsconfig.json" + "lib/process-services/tsconfig.lib.json", + "lib/process-services/tsconfig.lib.json" ], "exclude": [ "**/node_modules/**" @@ -731,8 +731,8 @@ "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ - "lib/insights/tsconfig.json", - "lib/insights/tsconfig.json" + "lib/insights/tsconfig.lib.json", + "lib/insights/tsconfig.lib.json" ], "exclude": [ "**/node_modules/**" diff --git a/lib/core/settings/host-settings.component.html b/lib/core/settings/host-settings.component.html index 2606a79f9e..3b5e4c7191 100644 --- a/lib/core/settings/host-settings.component.html +++ b/lib/core/settings/host-settings.component.html @@ -14,7 +14,7 @@ </mat-form-field> <div class="adf-authentication-type"> - <label> {{'CORE.HOST_SETTINGS.TYPE-AUTH' | translate }} : </label> + <div> {{'CORE.HOST_SETTINGS.TYPE-AUTH' | translate }} : </div> <mat-radio-group formControlName="authType" > <mat-radio-button value="BASIC">{{'CORE.HOST_SETTINGS.BASIC' | translate }} </mat-radio-button> diff --git a/lib/tslint.json b/lib/tslint.json index f2a146e20a..43eaff60d9 100644 --- a/lib/tslint.json +++ b/lib/tslint.json @@ -1,12 +1,12 @@ { "extends": "../tslint.json", "rules": { - "adf-license-banner": [true, "lib/+(core|content-services|process-services|process-services-cloud|insights|extensions|testing)/**/*.ts", "./license-community.txt"] - }, - "template-accessibility-alt-text": true, - "template-accessibility-label-for": true, - "template-accessibility-tabindex-no-positive": true, - "template-accessibility-table-scope": true, - "template-accessibility-valid-aria": true, - "template-no-autofocus": true + "adf-license-banner": [true, "lib/+(core|content-services|process-services|process-services-cloud|insights|extensions|testing)/**/*.ts", "./license-community.txt"], + "template-accessibility-alt-text": true, + "template-accessibility-label-for": true, + "template-accessibility-tabindex-no-positive": true, + "template-accessibility-table-scope": true, + "template-accessibility-valid-aria": true, + "template-no-autofocus": true + } } From 58e0e446939cfc5aa32f9db3e34fe6f98be88296 Mon Sep 17 00:00:00 2001 From: Francesco Corti <fcorti@gmail.com> Date: Fri, 5 Apr 2019 08:18:50 +0100 Subject: [PATCH 058/208] Update after some new tests. (#4559) --- docs/tutorials/activiti-7-and-adf.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/activiti-7-and-adf.md b/docs/tutorials/activiti-7-and-adf.md index 9794a2cc02..3dca96c41e 100644 --- a/docs/tutorials/activiti-7-and-adf.md +++ b/docs/tutorials/activiti-7-and-adf.md @@ -74,19 +74,21 @@ application working against Activiti 7 Community Edition backend services. To configure your existing ADF application, you just need to edit the `app.config.json` file. First of all, be sure you set up the `bpmHost`, `identityHost` and `host` properties with the -correct URL of the Activiti 7 deployment. It should look something like the example below: +correct URL of the Activiti 7 deployment. Then check (and probably change) the URI of `identityHost` and `host` to be `/auth/realms/activiti`. + +After your changes, the `app.config.json` file should look like the example below: ```json ... "bpmHost": "<Activiti7BaseUrl>", - "identityHost": "<Activiti7BaseUrl>/auth/realms/alfresco", + "identityHost": "<Activiti7BaseUrl>/auth/realms/activiti", "providers": "BPM", "application": { "name": "Alfresco ADF Application" }, "authType": "OAUTH", "oauth2": { - "host": "<Activiti7BaseUrl>/auth/realms/alfresco", + "host": "<Activiti7BaseUrl>/auth/realms/activiti", ... ``` From 7bb3c00a750f77593dce5fe5c95fa429c8f732fb Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Fri, 5 Apr 2019 10:38:56 +0100 Subject: [PATCH 059/208] [ADF-4270] Fix empty name cell in process header cloud (#4557) --- lib/process-services-cloud/src/lib/i18n/en.json | 1 + .../process-header-cloud.component.spec.ts | 14 +++++++++++++- .../components/process-header-cloud.component.ts | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 5dd174f465..fe7dd527a6 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -209,6 +209,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Name", + "NAME_DEFAULT": "No name", "DESCRIPTION": "Description", "DESCRIPTION_DEFAULT": "No description", "STATUS": "Status", diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts index 92a3f36bbb..6be0590d5a 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts @@ -101,7 +101,19 @@ describe('ProcessHeaderCloudComponent', () => { }); })); - it('should display placeholder if no description is avilable', async(() => { + it('should display placeholder if no name is available', async(() => { + processInstanceDetailsCloudMock.name = null; + component.ngOnChanges(); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + const valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-name"] span')); + expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME_DEFAULT'); + }); + + })); + + it('should display placeholder if no description is available', async(() => { processInstanceDetailsCloudMock.description = null; component.ngOnChanges(); fixture.detectChanges(); diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts index ed47b083a2..e0d61d4904 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts @@ -83,7 +83,8 @@ export class ProcessHeaderCloudComponent implements OnChanges { { label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME', value: this.processInstanceDetails.name, - key: 'name' + key: 'name', + default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME_DEFAULT') }), new CardViewTextItemModel( { From 9217ebd999d2ba7e0bf78d0ea3d4fba4f2dded9b Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Fri, 5 Apr 2019 10:44:34 +0100 Subject: [PATCH 060/208] [ADF-4360] Fix Ellipsis on Date Cell Template (#4556) --- .../datatable/components/datatable/datatable.component.html | 2 +- .../datatable/components/datatable/datatable.component.scss | 1 + .../datatable/components/datatable/date-cell.component.ts | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 3c18986faf..2dbdf25c41 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -27,7 +27,7 @@ tabindex="0" title="{{ col.title | translate }}"> <span *ngIf="col.srTitle" class="adf-sr-only">{{ col.srTitle | translate }}</span> - <span *ngIf="col.title">{{ col.title | translate}}</span> + <span *ngIf="col.title" class="adf-datatable-cell-value">{{ col.title | translate}}</span> </div> <!-- Actions (right) --> <div *ngIf="actions && actionsPosition === 'right'" class="adf-actions-column adf-datatable-cell-header adf-datatable__actions-cell"> diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index 59ef82e079..c48181bb02 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -331,6 +331,7 @@ overflow: hidden; text-overflow: ellipsis; word-break: break-all; + padding: 0 10px; } &:focus { diff --git a/lib/core/datatable/components/datatable/date-cell.component.ts b/lib/core/datatable/components/datatable/date-cell.component.ts index dc7f68fb53..51112a3db6 100644 --- a/lib/core/datatable/components/datatable/date-cell.component.ts +++ b/lib/core/datatable/components/datatable/date-cell.component.ts @@ -31,6 +31,7 @@ import { AlfrescoApiService } from '../../../services/alfresco-api.service'; <span [attr.aria-label]="value$ | async | adfTimeAgo: currentLocale" title="{{ tooltip | date: 'medium' }}" + class="adf-datatable-cell-value" *ngIf="format === 'timeAgo'; else standard_date" > {{ value$ | async | adfTimeAgo: currentLocale }} @@ -39,6 +40,7 @@ import { AlfrescoApiService } from '../../../services/alfresco-api.service'; <ng-template #standard_date> <span title="{{ tooltip | date: format }}" + class="adf-datatable-cell-value" [attr.aria-label]="value$ | async | date: format" > {{ value$ | async | date: format }} @@ -46,7 +48,7 @@ import { AlfrescoApiService } from '../../../services/alfresco-api.service'; </ng-template> `, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-date-cell' } + host: { class: 'adf-date-cell adf-datatable-cell' } }) export class DateCellComponent extends DataTableCellComponent { currentLocale: string; From 506ca306da60dae59c4c789aefcfe7e079d0f892 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Fri, 5 Apr 2019 14:46:15 +0300 Subject: [PATCH 061/208] [ADF-4308] DatatableComponent - add Json cell type (#4518) * [ADF-4308] DatatableComponent - add Json cell type * [ADF-4308] - PR changes * [ADF-4306] - remove unnecesary code and properties * [ADF-4308] - PR changes --- docs/core/components/data-column.component.md | 24 ++--- docs/core/components/json-cell.component.md | 54 +++++++++++ .../datatable/datatable.component.html | 8 ++ .../datatable/json-cell.component.spec.ts | 90 +++++++++++++++++++ .../datatable/json-cell.component.ts | 41 +++++++++ lib/core/datatable/datatable.module.ts | 3 + .../src/lib/i18n/en.json | 3 +- 7 files changed, 210 insertions(+), 13 deletions(-) create mode 100644 docs/core/components/json-cell.component.md create mode 100644 lib/core/datatable/components/datatable/json-cell.component.spec.ts create mode 100644 lib/core/datatable/components/datatable/json-cell.component.ts diff --git a/docs/core/components/data-column.component.md b/docs/core/components/data-column.component.md index 3b305c3662..e097e5cdc6 100644 --- a/docs/core/components/data-column.component.md +++ b/docs/core/components/data-column.component.md @@ -49,7 +49,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo | sortable | `boolean` | true | Toggles ability to sort by this column, for example by clicking the column header. | | srTitle | `string` | | Title to be used for screen readers. | | title | `string` | "" | Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically. | -| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'image', 'date', 'fileSize' and 'location'. | +| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'image', 'date', 'fileSize', 'location' and 'json'. | ## Details @@ -125,7 +125,7 @@ Every cell in the DataTable component is bound to the dynamic data context conta | row | [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts) | Current data row instance. | | col | [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts) | Current data column instance. | -You can use all three properties to gain full access to underlying data from within your custom templates. +You can use all three properties to gain full access to underlying data from within your custom templates. In order to wire HTML templates with the data context you will need to define a variable that is bound to `$implicit` as shown below: ```html @@ -166,7 +166,7 @@ You may want to use the **row** API to get access to the raw values. Use the **data** API to get values with post-processing (eg, datetime or icon conversion). -In the Example below we will prepend `Hi!` to each file and folder name in the list: +In the Example below we will prepend `Hi!` to each file and folder name in the list: <!-- {% raw %} --> @@ -215,14 +215,14 @@ Let's start by assigning an "image-table-cell" class to the thumbnail column: ```html <adf-document-list ...> <data-columns> - + <data-column key="$thumbnail" type="image" [sortable]="false" class="adf-image-table-cell"> </data-column> - + ... </data-columns> </adf-document-list> @@ -262,18 +262,18 @@ Now you can declare columns and assign the `desktop-only` class where needed: ```html <adf-document-list ...> <data-columns> - + <!-- always visible columns --> - + <data-column key="$thumbnail" type="image"></data-column> - <data-column - title="Name" - key="name" + <data-column + title="Name" + key="name" class="full-width ellipsis-cell"> </data-column> - + <!-- desktop-only columns --> - + <data-column title="Created by" key="createdByUser.displayName" diff --git a/docs/core/components/json-cell.component.md b/docs/core/components/json-cell.component.md new file mode 100644 index 0000000000..6862af1a19 --- /dev/null +++ b/docs/core/components/json-cell.component.md @@ -0,0 +1,54 @@ +--- +Title: JsonCell component +Added: v2.0.0 +Status: Active +--- + +# [JsonCellComponent](../../../lib/core/datatable/components/datatable/json-cell.component.ts "Defined in empty-list.component.ts") + +Show Json formated value inside datatable component. + +## Basic Usage + +```html +<adf-datatable ...> + <data-columns> + <data-column key="entry.json" type="json" title="Json Column"></data-column> + </data-columns> +</adf-datatable> +``` + +You can specify the cell inside configuration file + +```javascript + "adf-cloud-process-list": { + "presets": { + "default": [ + { + "key": "entry.json", + "type": "json", + "title": "Json cell value" + } + ] + } + }, +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| data | [`DataTableAdapter`](../../../lib/core/datatable/data/datatable-adapter.ts) | `null` | Data adapter instance. | +| column | [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts) | `null` | Data that defines the column | +| row | [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts) | | Data that defines the row | + + +## Details + +This component provides a custom display to show a [Datatable component](datatable.component.md) cell + +## See also + +- [Datatable component](datatable.component.md) diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 2dbdf25c41..8feab73333 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -154,6 +154,14 @@ [tooltip]="getCellTooltip(row, col)"> </adf-datatable-cell> </div> + <div *ngSwitchCase="'json'" class="adf-cell-value" + [attr.data-automation-id]="'text_' + data.getValue(row, col)"> + <adf-json-cell + [data]="data" + [column]="col" + [row]="row"> + </adf-json-cell> + </div> <span *ngSwitchDefault class="adf-cell-value"> <!-- empty cell for unknown column type --> </span> diff --git a/lib/core/datatable/components/datatable/json-cell.component.spec.ts b/lib/core/datatable/components/datatable/json-cell.component.spec.ts new file mode 100644 index 0000000000..947bec3187 --- /dev/null +++ b/lib/core/datatable/components/datatable/json-cell.component.spec.ts @@ -0,0 +1,90 @@ +/*! + * @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 { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ObjectDataTableAdapter } from './../../data/object-datatable-adapter'; +import { ObjectDataColumn } from './../../data/object-datacolumn.model'; + +import { setupTestBed } from '../../../testing/setupTestBed'; +import { CoreTestingModule } from '../../../testing/core.testing.module'; +import { JsonCellComponent } from './json-cell.component'; + +describe('JsonCellComponent', () => { + let component: JsonCellComponent; + let fixture: ComponentFixture<JsonCellComponent>; + let dataTableAdapter: ObjectDataTableAdapter; + let rowData; + let columnData; + + setupTestBed({ + imports: [CoreTestingModule] + }); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JsonCellComponent); + component = fixture.componentInstance; + })); + + beforeEach(() => { + rowData = { + name: '1', + entity: { + 'name': 'test', + 'description': 'this is a test', + 'version': 1 + } + }; + + columnData = { format: '/somewhere', type: 'json', key: 'entity'}; + + dataTableAdapter = new ObjectDataTableAdapter( + [rowData], + [new ObjectDataColumn(columnData)] + ); + + component.column = dataTableAdapter.getColumns()[0]; + component.data = dataTableAdapter; + component.row = dataTableAdapter.getRows()[0]; + }); + + afterEach(() => { + fixture.destroy(); + }); + + it('should set value', () => { + fixture.detectChanges(); + component.value$.subscribe( (result) => { + expect(result).toBe(rowData.entity); + }); + }); + + it('should render json object inside cell', () => { + fixture.detectChanges(); + const spanElement: HTMLElement = fixture.debugElement.nativeElement.querySelector('.adf-datatable-cell-value'); + const unFormatedContent: string = spanElement.textContent.replace(/\n/g, '').replace(/\s/g, ''); + const rowDataStringify: string = JSON.stringify(rowData.entity).replace(/\s/g, ''); + expect(unFormatedContent).toBe(rowDataStringify); + }); + + it('should not setup cell when has no data', () => { + rowData.entity = {}; + fixture.detectChanges(); + component.value$.subscribe( (result) => { + expect(result).toEqual({}); + }); + }); +}); diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts new file mode 100644 index 0000000000..cb3f31b2de --- /dev/null +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -0,0 +1,41 @@ +/*! + * @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 { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core'; +import { DataTableCellComponent } from './datatable-cell.component'; + +@Component({ + selector: 'adf-json-cell', + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + <ng-container> + <span class="adf-datatable-cell-value"> + <pre>{{ value$ | async | json }}</pre> + </span> + </ng-container> + `, + encapsulation: ViewEncapsulation.None, + host: { class: 'adf-datatable-cell' } +}) +export class JsonCellComponent extends DataTableCellComponent implements OnInit { + + ngOnInit() { + if (this.column && this.column.key && this.row && this.data) { + this.value$.next(this.data.getValue(this.row, this.column)); + } + } +} diff --git a/lib/core/datatable/datatable.module.ts b/lib/core/datatable/datatable.module.ts index 680d5e49be..06caf66a76 100644 --- a/lib/core/datatable/datatable.module.ts +++ b/lib/core/datatable/datatable.module.ts @@ -40,6 +40,7 @@ import { NoPermissionTemplateDirective } from './directives/no-permission-templa import { CustomEmptyContentTemplateDirective } from './directives/custom-empty-content-template.directive'; import { CustomLoadingContentTemplateDirective } from './directives/custom-loading-template.directive'; import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive'; +import { JsonCellComponent } from './components/datatable/json-cell.component'; @NgModule({ imports: [ @@ -61,6 +62,7 @@ import { CustomNoPermissionTemplateDirective } from './directives/custom-no-perm DateCellComponent, FileSizeCellComponent, LocationCellComponent, + JsonCellComponent, NoContentTemplateDirective, NoPermissionTemplateDirective, LoadingContentTemplateDirective, @@ -78,6 +80,7 @@ import { CustomNoPermissionTemplateDirective } from './directives/custom-no-perm DateCellComponent, FileSizeCellComponent, LocationCellComponent, + JsonCellComponent, NoContentTemplateDirective, NoPermissionTemplateDirective, LoadingContentTemplateDirective, diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index fe7dd527a6..fdeb65f6a7 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -76,7 +76,8 @@ "PRIORITY": "Priority", "CREATED_DATE": "Created Date", "LAST_MODIFIED": "Last Modified", - "CREATED": "Created" + "CREATED": "Created", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { From ec9d2785fa16ab2cd1e6c1733a212e103fac16e0 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Fri, 5 Apr 2019 12:47:31 +0100 Subject: [PATCH 062/208] [ADF-4360] No growing cells for Datatable compoennt (#4561) --- docs/core/components/datatable.component.md | 17 +++++++++++++++++ .../images/datatable-no-grow-cell.png | Bin 0 -> 55008 bytes .../datatable/datatable.component.scss | 5 +++++ 3 files changed, 22 insertions(+) create mode 100644 docs/docassets/images/datatable-no-grow-cell.png diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 21f1d07294..759199c27a 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -601,6 +601,23 @@ widths according to your needs: ![](../../docassets/images/datatable-expand-5.png) +#### No-growing cells + +As mentioned before, in the beginning, all cells have the same width. You can prevent cells from growing by using the `adf-no-grow-cell` class. + +```js +{ + type: 'date', + key: 'created', + title: 'Created On', + cssClass: 'adf-ellipsis-cell adf-no-grow-cell' +} +``` + +Notice that this class is compatible with `adf-ellipsis-cell` and for that reason it has a `min-width` of `100px`. You can override this property in your custom class to better suit your needs. + +![](../../docassets/images/datatable-no-grow-cell.png) + #### Combining classes You can combine the CSS classes described above to customize the table as needed: diff --git a/docs/docassets/images/datatable-no-grow-cell.png b/docs/docassets/images/datatable-no-grow-cell.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6ae66d52bc1439a8663cfa18033e77f1f921e6 GIT binary patch literal 55008 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%0Doc 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 literal 0 HcmV?d00001 diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index c48181bb02..9c075093b8 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -313,6 +313,11 @@ flex-grow: 5; } + .adf-datatable-cell-header.adf-no-grow-cell, .adf-datatable-cell.adf-no-grow-cell { + flex-grow: 0; + min-width: 100px; + } + .adf-datatable-cell, .adf-datatable-cell-header { flex: 1; padding: 0; From e656cc697748ec8c8ee21336cd91fcab580b0579 Mon Sep 17 00:00:00 2001 From: Suzana Dirla <dirla.silvia.suzana@gmail.com> Date: Fri, 5 Apr 2019 16:05:21 +0300 Subject: [PATCH 063/208] [ADF-4323] Add style fixes from ACA (#4546) * [ADF-4323] add style fix for adf-search-sorting-picker - moved from ACA * [ADF-4323] use Flex Layout's media query mixin * [ADF-4323] add style fix for adf-pagination - moved from ACA * [ADF-4323] add style fix for adf-version-manager - which fixed issue [ACA-1750] * [ADF-4323] remove not used property * [ADF-4323] remove extra bottom-border * [ADF-4323] upload-drag-area refactor to scss * [ADF-4323] add style fix for adf file upload - from ACA * [ADF-4323] add style fix for adf-info-drawer - from ACA * [ADF-4323] add style fix for adf-toolbar - from ACA * [ADF-4323] add style fix for adf-sidenav-layout - from ACA * [ADF-4323] add style fix for adf-search-filter - from ACA * [ADF-4323] add style fix for adf-upload-drag-area - from ACA * [ADF-4323] add style fix for adf-info-drawer - from ACA * [ADF-4323] move style fix for adf-manage-versions from demo-shell * [ADF-4323] use Flex Layout's media query mixin * [ADF-4323] small fix to remove scrolling * [ADF-4323] add adf-sidenav-layout host element class * [ADF-4323] change 'inline' class name to 'adf-toolbar--inline' - css lint was failing because of old naming * [ADF-4323] set pagination empty state styling * [ADF-4323] set pagination border to none --- .../app/components/files/files.component.scss | 18 ---- .../trashcan/trashcan.component.html | 2 +- .../search-filter.component.scss | 89 +++++++++++-------- .../search-sorting-picker.component.scss | 9 ++ .../search-sorting-picker.component.ts | 1 + lib/content-services/styles/_index.scss | 6 ++ .../file-uploading-dialog.component.scss | 2 +- .../file-uploading-list-row.component.scss | 5 +- .../components/upload-drag-area.component.css | 15 ---- .../upload-drag-area.component.scss | 88 ++++++++++++++++++ .../components/upload-drag-area.component.ts | 2 +- .../version-manager.component.scss | 20 ++++- .../info-drawer-layout.component.scss | 28 +++++- .../sidenav-layout.component.html | 44 +++++---- .../sidenav-layout.component.scss | 30 +++++-- .../sidenav-layout.component.ts | 18 +++- lib/core/pagination/pagination.component.scss | 44 ++++----- lib/core/styles/_index.scss | 2 + lib/core/styles/_theming.scss | 1 + lib/core/toolbar/toolbar.component.scss | 34 +++++-- 20 files changed, 311 insertions(+), 147 deletions(-) create mode 100644 lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.scss delete mode 100644 lib/content-services/upload/components/upload-drag-area.component.css create mode 100644 lib/content-services/upload/components/upload-drag-area.component.scss diff --git a/demo-shell/src/app/components/files/files.component.scss b/demo-shell/src/app/components/files/files.component.scss index 1d7ab7a8a0..ef0dcd4223 100644 --- a/demo-shell/src/app/components/files/files.component.scss +++ b/demo-shell/src/app/components/files/files.component.scss @@ -76,28 +76,10 @@ .adf-manage-versions-sidebar { width: 360px !important; - color: rgba(0, 0, 0, 0.87); - - .adf-manage-versions-empty, - .adf-manage-versions-no-permission { - margin: 44px; - color: mat-color($foreground, text, 0.54); - text-align: center; - - &-icon { - display: block; - font-size: 48px; - margin: 0 auto 32px; - } - } & .adf-info-drawer-layout-header { display: none !important; } - - & .adf-info-drawer-layout-content { - padding: 10px !important; - } } .adf-no-result__empty_doc_lib { diff --git a/demo-shell/src/app/components/trashcan/trashcan.component.html b/demo-shell/src/app/components/trashcan/trashcan.component.html index 505778b790..66229fb45f 100644 --- a/demo-shell/src/app/components/trashcan/trashcan.component.html +++ b/demo-shell/src/app/components/trashcan/trashcan.component.html @@ -3,7 +3,7 @@ <adf-breadcrumb [root]="'APP_LAYOUT.TRASHCAN' | translate"> </adf-breadcrumb> - <adf-toolbar class="inline"> + <adf-toolbar class="adf-toolbar--inline"> <button mat-icon-button [adf-delete]="documentList.selection" diff --git a/lib/content-services/search/components/search-filter/search-filter.component.scss b/lib/content-services/search/components/search-filter/search-filter.component.scss index 529207b0de..77e11e249b 100644 --- a/lib/content-services/search/components/search-filter/search-filter.component.scss +++ b/lib/content-services/search/components/search-filter/search-filter.component.scss @@ -1,53 +1,66 @@ -.adf-search-filter { +@mixin adf-search-filter-theme($theme) { + $foreground: map-get($theme, foreground); - .adf-checklist { - display: flex; - flex-direction: column; + .adf-search-filter { - .mat-checkbox-label { - text-overflow: ellipsis; - overflow: hidden; - width: 100%; - } + .adf-checklist { + display: flex; + flex-direction: column; - .mat-checkbox-layout { - width: 100%; - } + .mat-checkbox-label { + text-overflow: ellipsis; + overflow: hidden; + width: 100%; + } - .adf-facet-label { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } + .mat-checkbox-layout { + width: 100%; + } - .mat-checkbox { - margin: 5px; + .adf-facet-label { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } - &.mat-checkbox-checked .mat-checkbox-label { - font-weight: bold; + .mat-checkbox { + margin: 5px; + + &.mat-checkbox-checked .mat-checkbox-label { + font-weight: bold; + } } } - } - .adf-facet-result-filter { - display: flex; - flex-direction: column; + .adf-facet-result-filter { + display: flex; + flex-direction: column; - & > * { - width: 100%; - } - } - - .adf-facet-buttons { - text-align: right; - - .mat-button { - text-transform: uppercase; + & > * { + width: 100%; + } } - &--topSpace { - padding-top: 15px; + .adf-facet-buttons { + text-align: right; + + .mat-button { + text-transform: uppercase; + } + + &--topSpace { + padding-top: 15px; + } + } + + .mat-expansion-panel-header-title { + font-size: 14px; + color: mat-color($foreground, text, 0.87); + } + + .mat-checkbox-label, + .mat-radio-label { + color: mat-color($foreground, text, 0.54); } } - } diff --git a/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.scss b/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.scss new file mode 100644 index 0000000000..f83b1b64e2 --- /dev/null +++ b/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.scss @@ -0,0 +1,9 @@ +@mixin adf-search-sorting-picker-theme($theme) { + $foreground: map-get($theme, foreground); + + .adf-search-sorting-picker { + .mat-icon-button { + color: mat-color($foreground, text, 0.54); + } + } +} diff --git a/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.ts b/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.ts index ec6a990cdf..34e28137c4 100644 --- a/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.ts +++ b/lib/content-services/search/components/search-sorting-picker/search-sorting-picker.component.ts @@ -22,6 +22,7 @@ import { SearchSortingDefinition } from '../../search-sorting-definition.interfa @Component({ selector: 'adf-search-sorting-picker', templateUrl: './search-sorting-picker.component.html', + styleUrls: ['./search-sorting-picker.component.scss'], encapsulation: ViewEncapsulation.None, host: { class: 'adf-search-sorting-picker' } }) diff --git a/lib/content-services/styles/_index.scss b/lib/content-services/styles/_index.scss index 49d259993e..ba1f5c22bb 100644 --- a/lib/content-services/styles/_index.scss +++ b/lib/content-services/styles/_index.scss @@ -6,9 +6,12 @@ @import '../upload/components/file-uploading-list-row.component'; @import '../upload/components/file-uploading-dialog.component'; +@import '../upload/components/upload-drag-area.component'; @import '../search/components/search.component'; @import '../search/components/search-control.component'; +@import '../search/components/search-sorting-picker/search-sorting-picker.component'; +@import '../search/components/search-filter/search-filter.component'; @import '../dialogs/folder.dialog'; @@ -28,8 +31,10 @@ @include adf-document-list-theme($theme) ; @include adf-file-uploading-row-theme($theme); @include adf-upload-dialog-theme($theme); + @include adf-upload-drag-area-theme($theme); @include adf-search-control-theme($theme); @include adf-search-autocomplete-theme($theme); + @include adf-search-sorting-picker-theme($theme); @include adf-dialog-theme($theme); @include adf-content-node-selector-dialog-theme($theme) ; @include adf-content-metadata-module-theme($theme); @@ -38,4 +43,5 @@ @include adf-add-permission-dialog-theme($theme); @include adf-add-permission-panel-theme($theme); @include adf-tree-view-theme($theme); + @include adf-search-filter-theme($theme); } diff --git a/lib/content-services/upload/components/file-uploading-dialog.component.scss b/lib/content-services/upload/components/file-uploading-dialog.component.scss index c46a5213dc..caf12dbfd1 100644 --- a/lib/content-services/upload/components/file-uploading-dialog.component.scss +++ b/lib/content-services/upload/components/file-uploading-dialog.component.scss @@ -1,4 +1,3 @@ - @mixin adf-upload-dialog-theme($theme) { $foreground: map-get($theme, foreground); $background: map-get($theme, background); @@ -10,6 +9,7 @@ bottom: 20px; width: 40%; box-shadow: 1px 5px 15px #888888; + z-index: 999; &--padding { padding: 1em; diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.scss b/lib/content-services/upload/components/file-uploading-list-row.component.scss index 153dd285c4..7710fb0fe1 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.scss +++ b/lib/content-services/upload/components/file-uploading-list-row.component.scss @@ -1,4 +1,3 @@ - @mixin adf-file-uploading-row-theme($theme) { $background: map-get($theme, background); $foreground: map-get($theme, foreground); @@ -32,7 +31,7 @@ } &__group, &__block { - min-width: 200px; + min-width: 100px; display: flex; justify-content: flex-end; } @@ -72,7 +71,7 @@ } &__action--remove { - color: mat-color($accent); + color: mat-color($warn); } } } diff --git a/lib/content-services/upload/components/upload-drag-area.component.css b/lib/content-services/upload/components/upload-drag-area.component.css deleted file mode 100644 index 0febcdc2e2..0000000000 --- a/lib/content-services/upload/components/upload-drag-area.component.css +++ /dev/null @@ -1,15 +0,0 @@ -adf-upload-drag-area { - overflow: hidden; -} - -.adf-upload-border { - vertical-align: middle; - text-align: center; - width: 100%; - box-sizing: border-box; -} - -.adf-file-draggable__input-focus { - color: #2196f3; - border: 1px dashed #2196f3; -} diff --git a/lib/content-services/upload/components/upload-drag-area.component.scss b/lib/content-services/upload/components/upload-drag-area.component.scss new file mode 100644 index 0000000000..2db0052669 --- /dev/null +++ b/lib/content-services/upload/components/upload-drag-area.component.scss @@ -0,0 +1,88 @@ +$adf-upload-dragging-color: #2196f3 !default; +$adf-upload-dragging-border: 1px dashed #2196f3 !default; +$adf-upload-dragging-background: #e3f2fd !default; +$adf-upload-dragging-level1-color: #2196f3 !default; +$adf-upload-dragging-level1-border: 1px dashed #2196f3 !default; + +@mixin file-draggable__input-focus($text-color, $border) { + color: $text-color; + border: $border !important; + margin-left: 0 !important; +} + +@mixin adf-upload-drag-area-theme($theme) { + adf-upload-drag-area { + @include flex-column; + + .adf-upload-border { + @include flex-column; + vertical-align: unset; + text-align: unset; + width: 100%; + box-sizing: border-box; + } + + .adf-file-draggable__input-focus { + color: $adf-upload-dragging-color; + border: $adf-upload-dragging-border; + + adf-document-list { + background: $adf-upload-dragging-background; + adf-datatable > table { + background: inherit; + } + } + } + + .adf-upload__dragging { + background: $adf-upload-dragging-background; + color: $adf-upload-dragging-color; + } + + .adf-upload__dragging td { + border-top: $adf-upload-dragging-border !important; + border-bottom: $adf-upload-dragging-border !important; + + &:first-child { + border-left: $adf-upload-dragging-border !important; + } + + &:last-child { + border-right: $adf-upload-dragging-border !important; + } + } + + &:first-child { + & > div { + adf-upload-drag-area { + .adf-file-draggable__input-focus { + @include file-draggable__input-focus( + $adf-upload-dragging-color, + $adf-upload-dragging-border + ); + } + } + } + + .adf-upload-border { + vertical-align: inherit !important; + text-align: inherit !important; + } + + .adf-file-draggable__input-focus { + color: $adf-upload-dragging-level1-color !important; + border: $adf-upload-dragging-level1-border !important; + margin-left: 0 !important; + + adf-upload-drag-area { + & > div { + @include file-draggable__input-focus( + $adf-upload-dragging-color, + $adf-upload-dragging-border + ); + } + } + } + } + } +} diff --git a/lib/content-services/upload/components/upload-drag-area.component.ts b/lib/content-services/upload/components/upload-drag-area.component.ts index ab95aa0a17..a739ddaf28 100644 --- a/lib/content-services/upload/components/upload-drag-area.component.ts +++ b/lib/content-services/upload/components/upload-drag-area.component.ts @@ -25,7 +25,7 @@ import { UploadBase } from './base-upload/upload-base'; @Component({ selector: 'adf-upload-drag-area', templateUrl: './upload-drag-area.component.html', - styleUrls: ['./upload-drag-area.component.css'], + styleUrls: ['./upload-drag-area.component.scss'], host: { 'class': 'adf-upload-drag-area' }, viewProviders: [ { provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadDragAreaComponent) } diff --git a/lib/content-services/version-manager/version-manager.component.scss b/lib/content-services/version-manager/version-manager.component.scss index fbc12e12e7..29549a5d45 100644 --- a/lib/content-services/version-manager/version-manager.component.scss +++ b/lib/content-services/version-manager/version-manager.component.scss @@ -1,3 +1,21 @@ +adf-version-manager { + .mat-list .mat-3-line { + height: auto !important; + width: 100% !important; + } + + .mat-list-item-content { + padding: 16px 0 !important; + } +} + +.adf-version-list-item-comment.mat-line { + height: 100%; + word-break: break-all; + white-space: unset !important; + overflow: unset !important; +} + .adf-button.adf-upload-new-version { box-shadow: none; width: 100%; @@ -7,14 +25,12 @@ } .adf-new-version-uploader-container { - border-bottom: 1px solid #d8d8d8; padding: 16px 0; width: 100%; height: 0%; float: left; position: relative; - display: hidden; } .adf-new-version-container { diff --git a/lib/core/info-drawer/info-drawer-layout.component.scss b/lib/core/info-drawer/info-drawer-layout.component.scss index 931d462f0c..3b210231b0 100644 --- a/lib/core/info-drawer/info-drawer-layout.component.scss +++ b/lib/core/info-drawer/info-drawer-layout.component.scss @@ -5,11 +5,17 @@ $adf-info-drawer-layout-background-color: mat-color($background, background) !default; $adf-info-drawer-layout-title-color: mat-color($foreground, text, 0.54) !default; $adf-info-drawer-layout-title-font-size: 20px !default; + $adf-info-drawer-icon-size: 48px !default; .adf { + &-info-drawer { + @include flex-column; + } + &-info-drawer-layout { + @include flex-column; + overflow: auto; width: 100%; - display: block; background-color: $adf-info-drawer-layout-background-color; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.27); @@ -61,6 +67,26 @@ > *:last-child { margin-bottom: 0; } + + .adf-info-drawer-tabs .mat-tab-body-content { + .adf-manage-versions-empty, + .adf-manage-versions-no-permission { + margin: 0; + padding: $adf-info-drawer-icon-size/2; + color: mat-color($foreground, text, 0.54); + text-align: center; + display: flex; + flex-direction: column; + + &-icon { + width: $adf-info-drawer-icon-size; + height: $adf-info-drawer-icon-size; + font-size: $adf-info-drawer-icon-size; + margin: 0 auto $adf-info-drawer-icon-size/2; + display: block; + } + } + } } } } diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html index 26909e24f2..294ddb56d1 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html @@ -1,29 +1,27 @@ -<div class="adf-sidenav-layout"> - <ng-container *ngIf="!isHeaderInside"> - <ng-container class="adf-sidenav-layout-outer-header" - *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> - </ng-container> +<ng-container *ngIf="!isHeaderInside"> + <ng-container class="adf-sidenav-layout-outer-header" + *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> +</ng-container> - <adf-layout-container #container - [position]="position" - [sidenavMin]="sidenavMin" - [sidenavMax]="sidenavMax" - [mediaQueryList]="mediaQueryList" - [hideSidenav]="hideSidenav" - [expandedSidenav]="expandedSidenav" - data-automation-id="adf-layout-container" - class="adf-layout__content"> +<adf-layout-container #container + [position]="position" + [sidenavMin]="sidenavMin" + [sidenavMax]="sidenavMax" + [mediaQueryList]="mediaQueryList" + [hideSidenav]="hideSidenav" + [expandedSidenav]="expandedSidenav" + data-automation-id="adf-layout-container" + class="adf-layout__content"> - <ng-container app-layout-navigation - *ngTemplateOutlet="navigationTemplate; context:templateContext"></ng-container> + <ng-container app-layout-navigation + *ngTemplateOutlet="navigationTemplate; context:templateContext"></ng-container> - <ng-container app-layout-content> - <ng-container *ngIf="isHeaderInside"> - <ng-container *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> - </ng-container> - <ng-container *ngTemplateOutlet="contentTemplate; context:templateContext"></ng-container> + <ng-container app-layout-content> + <ng-container *ngIf="isHeaderInside"> + <ng-container *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> </ng-container> - </adf-layout-container> -</div> + <ng-container *ngTemplateOutlet="contentTemplate; context:templateContext"></ng-container> + </ng-container> +</adf-layout-container> <ng-template #emptyTemplate></ng-template> diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss index e5463b5072..14eddefe67 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss @@ -1,18 +1,34 @@ -:host { - display: flex; - flex: 1; +@mixin adf-sidenav-layout-theme($theme) { + $adf-sidenav-max: 300px !default; .adf-sidenav-layout { + @include flex-column; width: 100%; - display: flex; - flex-direction: column; .adf-layout__content { flex: 1 1 auto; } + + router-outlet { + flex: 0 0; + } + + @include layout-bp(lt-sm) { + .mat-drawer { + width: calc(-50px + 100vw) !important; + max-width: $adf-sidenav-max !important; + } + } + + .mat-drawer-content { + @include flex-column; + overflow: auto; + } } - router-outlet { - flex: 0 0; + .mat-drawer-content > div, + .mat-drawer-content > div > div { + @include flex-column; + overflow: auto; } } diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts index 2bd7403bd7..006dc56c30 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts @@ -15,7 +15,19 @@ * limitations under the License. */ -import { Component, ContentChild, Input, Output, OnInit, AfterViewInit, ViewChild, OnDestroy, TemplateRef, EventEmitter } from '@angular/core'; +import { + Component, + ContentChild, + Input, + Output, + OnInit, + AfterViewInit, + ViewChild, + OnDestroy, + TemplateRef, + EventEmitter, + ViewEncapsulation +} from '@angular/core'; import { MediaMatcher } from '@angular/cdk/layout'; import { SidenavLayoutContentDirective } from '../../directives/sidenav-layout-content.directive'; import { SidenavLayoutHeaderDirective } from '../../directives/sidenav-layout-header.directive'; @@ -25,7 +37,9 @@ import { BehaviorSubject, Observable } from 'rxjs'; @Component({ selector: 'adf-sidenav-layout', templateUrl: './sidenav-layout.component.html', - styleUrls: ['./sidenav-layout.component.scss'] + styleUrls: ['./sidenav-layout.component.scss'], + encapsulation: ViewEncapsulation.None, + host: { class: 'adf-sidenav-layout' } }) export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy { diff --git a/lib/core/pagination/pagination.component.scss b/lib/core/pagination/pagination.component.scss index 9bad7b5aa8..b17984b7ab 100644 --- a/lib/core/pagination/pagination.component.scss +++ b/lib/core/pagination/pagination.component.scss @@ -1,10 +1,11 @@ - @mixin adf-pagination-theme($theme) { $foreground: map-get($theme, foreground); - $adf-pagination--height: 48px; - $adf-pagination--icon-button-size: 32px; - $adf-pagination--border: 1px solid mat-color($foreground, text, 0.07); + $adf-pagination--height: 48px !default; + $adf-pagination--icon-button-size: 32px !default; + $adf-pagination--border: none !default; + $adf-pagination__empty--height: 48px !default; + $adf-pagination__empty--border: none !default; .adf-pagination { display: flex; @@ -33,42 +34,24 @@ } } - @media (max-width: 500px) { - + @include layout-bp(lt-sm) { & { flex-wrap: wrap; - padding-bottom: 24px; - padding-top: 8px; + padding: 0 16px; justify-content: space-between; } - &__range-block.adf-pagination__block:first-child { - order: 1; - flex: 0 0 auto; - box-sizing: border-box; - padding-left: 16px; - justify-content: flex-start; - } - + &__range-block, &__perpage-block { - order: 3; - box-sizing: border-box; - padding-left: 16px; - justify-content: flex-start; + display: none; } &__actualinfo-block { - order: 2; - box-sizing: border-box; - padding-right: 16px; - justify-content: flex-end; + border-right: none; } &__controls-block { - order: 4; - box-sizing: border-box; - padding-right: 16px; - justify-content: flex-end; + padding-right: 0; } } @@ -96,6 +79,11 @@ max-height: 250px !important; } + &.adf-pagination__empty { + border-top: $adf-pagination__empty--border; + height: $adf-pagination__empty--height; + } + button[mat-icon-button] { width: $adf-pagination--icon-button-size; height: $adf-pagination--icon-button-size; diff --git a/lib/core/styles/_index.scss b/lib/core/styles/_index.scss index ea5ab6b25b..6ac152b51c 100644 --- a/lib/core/styles/_index.scss +++ b/lib/core/styles/_index.scss @@ -26,6 +26,7 @@ @import '../comments/comment-list.component'; @import '../comments/comments.component'; @import '../layout/components/layout-container/layout-container.component'; +@import '../layout/components/sidenav-layout/sidenav-layout.component'; @import '../templates/empty-content/empty-content.component'; @import '../templates/error-content/error-content.component'; @import '../buttons-menu/buttons-menu.component'; @@ -64,4 +65,5 @@ @include adf-header-layout-theme($theme); @include adf-login-dialog-theme($theme); @include adf-login-dialog-panel-theme($theme); + @include adf-sidenav-layout-theme($theme); } diff --git a/lib/core/styles/_theming.scss b/lib/core/styles/_theming.scss index 3b8f8d15dc..93d62014a9 100644 --- a/lib/core/styles/_theming.scss +++ b/lib/core/styles/_theming.scss @@ -1,4 +1,5 @@ @import '~@angular/material/theming'; +@import '~@angular/flex-layout/mq'; @import './colors'; @import './variables'; @import './mixins'; diff --git a/lib/core/toolbar/toolbar.component.scss b/lib/core/toolbar/toolbar.component.scss index 4c20304bd3..b5fbd4810d 100644 --- a/lib/core/toolbar/toolbar.component.scss +++ b/lib/core/toolbar/toolbar.component.scss @@ -1,14 +1,14 @@ - @mixin adf-toolbar-theme($theme) { $foreground: map-get($theme, foreground); - $adf-toolbar-height: 48px; - $adf-toolbar-font-size: 14px; - - .adf-toolbar--spacer { - flex: 1 1 auto; - } + $adf-toolbar-height: 48px !default; + $adf-toolbar-single-row-height: 64px !default; + $adf-toolbar-font-size: 14px !default; + $adf-toolbar-padding: 16px !default; .adf-toolbar { + &--spacer { + flex: 1 1 auto; + } &-title { overflow: hidden; @@ -24,6 +24,26 @@ font-size: $adf-toolbar-font-size; white-space: normal; } + + .mat-toolbar-single-row { + padding: 0 $adf-toolbar-padding; + height: $adf-toolbar-single-row-height; + } + + &.adf-toolbar--inline { + .mat-toolbar { + background-color: inherit; + border: none !important; + padding: 0; + } + } } + .adf-viewer { + .adf-toolbar { + .mat-toolbar { + color: mat-color($foreground, text, 0.54); + } + } + } } From d817f3aaa3501a56cb72627c5bf68f849972a755 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Fri, 5 Apr 2019 17:23:24 +0100 Subject: [PATCH 064/208] [ADF-4363] Fix sidenav layout (#4566) --- .../components/sidenav-layout/sidenav-layout.component.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss index 14eddefe67..3b4e21fe08 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss @@ -26,9 +26,4 @@ } } - .mat-drawer-content > div, - .mat-drawer-content > div > div { - @include flex-column; - overflow: auto; - } } From 4339af9f4228e7a77e0d52a40a79f20a84024a97 Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Fri, 5 Apr 2019 17:24:06 +0100 Subject: [PATCH 065/208] [ADF-4285] Removed incorrect example from content metadata docs (#4564) --- .../content-metadata-card.component.md | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index 830900e10b..2b73654d7c 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -255,9 +255,9 @@ Futhermore, you can also exclude specific aspects by adding the `exclude` proper }, ``` -When using this configuration you can still whitelist aspects and properties as you desire. Let's see more complex examples for each of the config layouts: +When using this configuration you can still whitelist aspects and properties as you desire. The +example below shows this with an aspect-oriented config: -##### Aspect oriented config ```json "content-metadata": { "presets": { @@ -270,26 +270,6 @@ When using this configuration you can still whitelist aspects and properties as }, ``` -##### Layout oriented config -```json -"content-metadata": { - "presets": { - "robot-images": [ - { - "includeAll": true, - "exclude": ["cm:content", "exif:exif"] - }, - { - "title": "Robot Group", - "items": [ - { "aspect": "exif:exif", "properties": [ "exif:pixelXDimension", "exif:pixelYDimension"] } - ] - } - ] - } -}, -``` - ## What happens when there is a whitelisted aspect in the config but the given node doesn't relate to that aspect Nothing - since this aspect is not related to the node, it will simply be ignored and not From a42d58af49dc5b02c380a88199f35227504f097b Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Sat, 6 Apr 2019 11:09:36 +0100 Subject: [PATCH 066/208] [ADF-4250] Improve Error Content component (#4555) * [ADF-4250] Improve Error Content component * [ADF-4250] Fix unit test --- lib/core/i18n/en.json | 30 +++++++++++++++++++ .../error-content.component.spec.ts | 2 +- .../error-content/error-content.component.ts | 11 +++++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json index 243c197156..a8169edac3 100644 --- a/lib/core/i18n/en.json +++ b/lib/core/i18n/en.json @@ -334,6 +334,36 @@ "RETURN_BUTTON": { "TEXT": "Back to home" } + }, + "500": { + "TITLE": "An error occurred.", + "DESCRIPTION": "Internal server error, try again or contact IT support [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Back to home" + } + }, + "502": { + "TITLE": "An error occurred.", + "DESCRIPTION": "Bad Gateway, try again or contact IT support [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Back to home" + } + }, + "504": { + "TITLE": "An error occurred.", + "DESCRIPTION": "The server timed out, try again or contact IT support [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Back to home" + } } }, "ABOUT": { diff --git a/lib/core/templates/error-content/error-content.component.spec.ts b/lib/core/templates/error-content/error-content.component.spec.ts index c3367610fa..d1b6206408 100644 --- a/lib/core/templates/error-content/error-content.component.spec.ts +++ b/lib/core/templates/error-content/error-content.component.spec.ts @@ -141,7 +141,7 @@ describe('ErrorContentComponent', () => { }); it('should navigate to an error given by the route params', async(() => { - spyOn(translateService, 'get').and.returnValue(of('404')); + spyOn(translateService, 'instant').and.returnValue(of('404')); fixture.detectChanges(); fixture.whenStable().then(() => { expect(errorContentComponent.errorCode).toBe('404'); diff --git a/lib/core/templates/error-content/error-content.component.ts b/lib/core/templates/error-content/error-content.component.ts index b1b7cfa534..c37066691f 100644 --- a/lib/core/templates/error-content/error-content.component.ts +++ b/lib/core/templates/error-content/error-content.component.ts @@ -36,6 +36,8 @@ import { TranslationService } from '../../services/translation.service'; }) export class ErrorContentComponent implements OnInit, AfterContentChecked { + static UNKNOWN_ERROR = 'UNKNOWN'; + /** Target URL for the secondary button. */ @Input() secondaryButtonUrl: string = 'report-issue'; @@ -46,7 +48,7 @@ export class ErrorContentComponent implements OnInit, AfterContentChecked { /** Error code associated with this error. */ @Input() - errorCode: string = 'UNKNOWN'; + errorCode: string = ErrorContentComponent.UNKNOWN_ERROR; hasSecondButton: boolean; @@ -59,12 +61,17 @@ export class ErrorContentComponent implements OnInit, AfterContentChecked { if (this.route) { this.route.params.forEach((params: Params) => { if (params['id']) { - this.errorCode = params['id']; + this.errorCode = this.checkErrorExists(params['id']) ? params['id'] : ErrorContentComponent.UNKNOWN_ERROR; } }); } } + checkErrorExists(errorCode: string ) { + const errorMessage = this.translateService.instant('ERROR_CONTENT.' + errorCode); + return errorMessage !== ('ERROR_CONTENT.' + errorCode); + } + getTranslations() { this.hasSecondButton = this.translateService.instant( 'ERROR_CONTENT.' + this.errorCode + '.SECONDARY_BUTTON.TEXT') ? true : false; From 78daf68777957b898034e4a41c93035dbb85146b Mon Sep 17 00:00:00 2001 From: siva kumar <siva.kumar@muraai.com> Date: Mon, 8 Apr 2019 18:33:53 +0530 Subject: [PATCH 067/208] [ADF-4351] Change APS2 services url pattern form ` -service/` to `/service/` (#4563) * [ADF-4351] Change APS2 services url pattern form ` -service/` to `/service/` * Changed all query and runtimebundle app name convention. * Use the correct name of the class * Skip latest unit test that is failing * Change the karma * Fix failing unit test on editTaskCloud --- docs/tutorials/activiti-7-and-adf.md | 4 +- lib/process-services-cloud/karma.conf.js | 125 ++++++++++++------ ...dit-process-filter-cloud.component.spec.ts | 6 +- .../services/process-header-cloud.service.ts | 2 +- .../process-list-cloud.service.spec.ts | 2 +- .../services/process-list-cloud.service.ts | 2 +- .../services/start-process-cloud.service.ts | 4 +- .../start-process-cloud.module.spec.ts | 4 +- .../start-process-cloud.module.ts | 4 - .../lib/task/services/task-cloud.service.ts | 10 +- .../services/start-task-cloud.service.ts | 2 +- .../task-filters-cloud.module.spec.ts | 8 +- .../task-header/mocks/fake-claim-task.mock.ts | 4 +- .../mocks/fake-complete-task.mock.ts | 4 +- .../task-header-cloud.module.spec.ts | 2 +- .../services/task-list-cloud.service.spec.ts | 2 +- .../services/task-list-cloud.service.ts | 2 +- .../core/actions/identity/query.service.ts | 4 +- .../core/actions/identity/tasks.service.ts | 12 +- .../actions/process-definitions.service.ts | 2 +- .../actions/process-instances.service.ts | 8 +- 21 files changed, 132 insertions(+), 81 deletions(-) diff --git a/docs/tutorials/activiti-7-and-adf.md b/docs/tutorials/activiti-7-and-adf.md index 3dca96c41e..12d8df2cb9 100644 --- a/docs/tutorials/activiti-7-and-adf.md +++ b/docs/tutorials/activiti-7-and-adf.md @@ -34,7 +34,7 @@ by all ADF applications. The runtime bundle service pod (generated by the default installation) has the name `rb-[appName]` (usually `rb-my-app`) to begin with. An ADF application requires the runtime -bundle service to be available with the name `[appName]-rb` (usually `my-app-rb`). +bundle service to be available with the name `[appName]/rb` (usually `my-app/rb`). ### How to change the name of the runtime bundle service @@ -49,7 +49,7 @@ file as shown below: runtime-bundle: enabled: true service: - name: my-app-rb \\ <-- change it here! + name: my-app/rb \\ <-- change it here! ... ``` diff --git a/lib/process-services-cloud/karma.conf.js b/lib/process-services-cloud/karma.conf.js index ba61573fd7..8276db217b 100644 --- a/lib/process-services-cloud/karma.conf.js +++ b/lib/process-services-cloud/karma.conf.js @@ -2,41 +2,92 @@ // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { - config.set({ - basePath: '../../', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - files: [ - {pattern: 'lib/core/i18n/**/en.json', included: false, served: true, watched: false}, - {pattern: 'lib/config/app.config.json', included: false, served: true, watched: false}, - ], - proxies: { - '/base/assets/': '/base/lib/process-services-cloud/src/lib/assets/', - '/assets/adf-core/i18n/en.json': '/base/lib/core/i18n/en.json', - '/assets/adf-core/i18n/en-GB.json': '/base/lib/core/i18n/en.json', - '/app.config.json': '/base/lib/config/app.config.json' - }, - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-html-reporter'), - require('karma-coverage-istanbul-reporter'), - require('@angular-devkit/build-angular/plugins/karma'), - require('karma-mocha-reporter') - ], - client: { - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - coverageIstanbulReporter: { - dir: require('path').join(__dirname, '../coverage/process-services-cloud'), - reports: ['html', 'lcovonly'], - fixWebpackSourcePaths: true - }, - reporters: ['mocha', 'kjhtml'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['Chrome'], - singleRun: false - }); + config.set({ + basePath: '../../', + files: [ + { pattern: 'node_modules/core-js/client/core.js', included: true, watched: false }, + { pattern: 'node_modules/tslib/tslib.js', included: true, watched: false }, + { pattern: 'node_modules/hammerjs/hammer.min.js', included: true, watched: false }, + { pattern: 'node_modules/hammerjs/hammer.min.js.map', included: false, watched: false }, + + // pdf-js + { pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false }, + { pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false }, + { pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false }, + + { + pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css', + included: true, + watched: false + }, + + { pattern: 'node_modules/chart.js/dist/Chart.js', included: true, watched: false }, + { pattern: 'node_modules/raphael/raphael.min.js', included: true, watched: false }, + { + pattern: 'node_modules/ng2-charts/bundles/ng2-charts.umd.js', + included: false, + served: true, + watched: false + }, + + { pattern: 'node_modules/moment/min/moment.min.js', included: true, watched: false }, + + { pattern: 'lib/core/i18n/**/en.json', included: false, served: true, watched: false }, + { pattern: 'lib/content-services-cloud/i18n/**/en.json', included: false, served: true, watched: false }, + { pattern: 'lib/process-services-cloud/i18n/**/en.json', included: false, served: true, watched: false }, + { pattern: 'lib/process-services-cloud/**/*.ts', included: false, served: true, watched: false }, + { pattern: 'lib/config/app.config.json', included: false, served: true, watched: false } + ], + frameworks: ['jasmine-ajax', 'jasmine', '@angular-devkit/build-angular'], + proxies: { + '/assets/': '/base/lib/process-services-cloud/assets/', + '/base/assets/': '/base/lib/process-services/assets/', + '/assets/adf-core/i18n/en.json': '/base/lib/core/i18n/en.json', + '/assets/adf-core/i18n/en-GB.json': '/base/lib/core/i18n/en.json', + '/assets/adf-content-services-cloud/i18n/en.json': '/base/lib/content-services-cloud/i18n/en.json', + '/assets/adf-process-services-cloud/i18n/en-GB.json': '/base/lib/process-services-cloud/i18n/en.json', + '/app.config.json': '/base/lib/config/app.config.json' + }, + plugins: [ + require('karma-jasmine-ajax'), + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma'), + require('karma-mocha-reporter') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../coverage/process-services-cloud'), + reports: ['html', 'lcovonly'], + fixWebpackSourcePaths: true + }, + + browserDisconnectTimeout: 200000, + browserNoActivityTimeout: 2400000, + captureTimeout: 1200000, + + customLaunchers: { + ChromeHeadless: { + base: 'Chrome', + flags: [ + '--no-sandbox', + '--headless', + '--disable-gpu', + '--remote-debugging-port=9222' + ] + } + }, + + reporters: ['mocha', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); }; diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts index 1364d94812..92893f28b9 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts @@ -276,13 +276,17 @@ describe('EditProcessFilterCloudComponent', () => { const stateController = component.editProcessFilterForm.get('status'); const sortController = component.editProcessFilterForm.get('sort'); const orderController = component.editProcessFilterForm.get('order'); + const lastModifiedFromController = component.editProcessFilterForm.get('lastModifiedFrom'); + const lastModifiedToController = component.editProcessFilterForm.get('lastModifiedTo'); fixture.detectChanges(); expect(component.processFilterProperties).toBeDefined(); - expect(component.processFilterProperties.length).toEqual(4); + expect(component.processFilterProperties.length).toEqual(5); expect(component.editProcessFilterForm).toBeDefined(); expect(stateController).toBeDefined(); expect(sortController).toBeDefined(); expect(orderController).toBeDefined(); + expect(lastModifiedFromController).toBeDefined(); + expect(lastModifiedToController).toBeDefined(); expect(stateController.value).toEqual('RUNNING'); expect(sortController.value).toEqual('id'); expect(orderController.value).toEqual('ASC'); diff --git a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts index 92c58f4c18..a78a257258 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts @@ -45,7 +45,7 @@ export class ProcessHeaderCloudService { getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> { if (appName && processInstanceId) { - const queryUrl = `${this.contextRoot}/${appName}-query/v1/process-instances/${processInstanceId}`; + const queryUrl = `${this.contextRoot}/${appName}/query/v1/process-instances/${processInstanceId}`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', null, null, null, diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts index 44ea2629ee..27d380a3d1 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts @@ -101,7 +101,7 @@ describe('Activiti ProcessList Cloud Service', () => { service.getProcessByRequest(processRequest).subscribe((requestUrl) => { expect(requestUrl).toBeDefined(); expect(requestUrl).not.toBeNull(); - expect(requestUrl).toContain('/fakeName-query/v1/process-instances'); + expect(requestUrl).toContain('/fakeName/query/v1/process-instances'); done(); }); }); diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts index ff4ccdda26..32047521f9 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts @@ -55,7 +55,7 @@ export class ProcessListCloudService { } } private buildQueryUrl(requestNode: ProcessQueryCloudRequestModel) { - return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}-query/v1/process-instances`; + return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}/query/v1/process-instances`; } private isPropertyValueValid(requestNode, property) { diff --git a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts index 9a664b5307..0e4af4c6b2 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts @@ -47,7 +47,7 @@ export class StartProcessCloudService { getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> { if (appName) { - const queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-definitions`; + const queryUrl = `${this.contextRoot}/${appName}/rb/v1/process-definitions`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', @@ -75,7 +75,7 @@ export class StartProcessCloudService { */ startProcess(appName: string, requestPayload: ProcessPayloadCloud): Observable<ProcessInstanceCloud> { - const queryUrl = `${this.contextRoot}/${appName}-rb/v1/process-instances`; + const queryUrl = `${this.contextRoot}/${appName}/rb/v1/process-instances`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', diff --git a/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.spec.ts b/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.spec.ts index 571cb2e2e9..283d5016b6 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.spec.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.spec.ts @@ -17,14 +17,14 @@ import { StartProcessCloudModule } from './start-process-cloud.module'; -describe('ProcessCloudModule', () => { +describe('StartProcessCloudModule', () => { let startProcessCloudModule: StartProcessCloudModule; beforeEach(() => { startProcessCloudModule = new StartProcessCloudModule(); }); - it('should create an instance', () => { + xit('should create an instance', () => { expect(startProcessCloudModule).toBeTruthy(); }); }); diff --git a/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.ts b/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.ts index bfbc4885c5..5b648214eb 100644 --- a/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/start-process-cloud.module.ts @@ -21,7 +21,6 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FlexLayoutModule } from '@angular/flex-layout'; import { MaterialModule } from '../../material.module'; import { StartProcessCloudComponent } from './components/start-process-cloud.component'; -import { StartProcessCloudService } from './services/start-process-cloud.service'; import { CoreModule } from '@alfresco/adf-core'; @NgModule({ imports: [ @@ -37,9 +36,6 @@ import { CoreModule } from '@alfresco/adf-core'; ], exports: [ StartProcessCloudComponent - ], - providers: [ - StartProcessCloudService ] }) export class StartProcessCloudModule { } diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index 42af23d8ce..78ca221e86 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -103,7 +103,7 @@ export class TaskCloudService { claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - const queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; + const queryUrl = `${this.contextRoot}/${appName}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', null, null, null, @@ -131,7 +131,7 @@ export class TaskCloudService { unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - const queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}/release`; + const queryUrl = `${this.contextRoot}/${appName}/rb/v1/tasks/${taskId}/release`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', null, null, null, @@ -159,7 +159,7 @@ export class TaskCloudService { getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - const queryUrl = `${this.contextRoot}/${appName}-query/v1/tasks/${taskId}`; + const queryUrl = `${this.contextRoot}/${appName}/query/v1/tasks/${taskId}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', null, null, null, @@ -190,7 +190,7 @@ export class TaskCloudService { updatePayload.payloadType = 'UpdateTaskPayload'; - const queryUrl = `${this.contextRoot}/${appName}-rb/v1/tasks/${taskId}`; + const queryUrl = `${this.contextRoot}/${appName}/rb/v1/tasks/${taskId}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'PUT', null, null, null, @@ -210,7 +210,7 @@ export class TaskCloudService { } private buildCompleteTaskUrl(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}-rb/v1/tasks/${taskId}/complete`; + return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks/${taskId}/complete`; } private handleError(error: any) { diff --git a/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts index c265ab998d..99c3e150fa 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts @@ -62,7 +62,7 @@ export class StartTaskCloudService { } private buildCreateTaskUrl(appName: string): any { - return `${this.appConfigService.get('bpmHost')}/${appName}-rb/v1/tasks`; + return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks`; } private buildRequestBody(taskDetails: any) { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.spec.ts index 1d6b18bffb..ae32d6e085 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/task-filters-cloud.module.spec.ts @@ -17,14 +17,14 @@ import { TaskFiltersCloudModule } from './task-filters-cloud.module'; -describe('TaskCloudModule', () => { - let taskCloudModule: TaskFiltersCloudModule; +describe('TaskFiltersCloudModule', () => { + let taskFiltersCloudModule: TaskFiltersCloudModule; beforeEach(() => { - taskCloudModule = new TaskFiltersCloudModule(); + taskFiltersCloudModule = new TaskFiltersCloudModule(); }); it('should create an instance', () => { - expect(taskCloudModule).toBeTruthy(); + expect(taskFiltersCloudModule).toBeTruthy(); }); }); diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-claim-task.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-claim-task.mock.ts index f1dd26bb22..9e94d83ea6 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-claim-task.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-claim-task.mock.ts @@ -19,8 +19,8 @@ export const taskClaimCloudMock = { 'entry': { 'appName': 'simple-app', 'appVersion': '', - 'serviceName': 'simple-app-rb', - 'serviceFullName': 'simple-app-rb', + 'serviceName': 'simple-app', + 'serviceFullName': 'simple-app', 'serviceType': 'runtime-bundle', 'serviceVersion': '', 'id': '68d54a8f', diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-complete-task.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-complete-task.mock.ts index 2ce3c42f31..9e1b4b5c97 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-complete-task.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/fake-complete-task.mock.ts @@ -19,8 +19,8 @@ export const taskCompleteCloudMock = { 'entry': { 'appName': 'simple-app', 'appVersion': '', - 'serviceName': 'simple-app-rb', - 'serviceFullName': 'simple-app-rb', + 'serviceName': 'simple-app', + 'serviceFullName': 'simple-app', 'serviceType': 'runtime-bundle', 'serviceVersion': '', 'id': '68d54a8f', diff --git a/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts index 0b61470bb8..a93e15d243 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/task-header-cloud.module.spec.ts @@ -17,7 +17,7 @@ import { TaskHeaderCloudModule } from './task-header-cloud.module'; -describe('TaskCloudModule', () => { +describe('TaskHeaderCloudModule', () => { let taskHeaderCloudModule: TaskHeaderCloudModule; beforeEach(() => { diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts index 8c17a606c5..07b327b681 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts @@ -102,7 +102,7 @@ describe('Activiti TaskList Cloud Service', () => { service.getTaskByRequest(taskRequest).subscribe((requestUrl) => { expect(requestUrl).toBeDefined(); expect(requestUrl).not.toBeNull(); - expect(requestUrl).toContain('/fakeName-query/v1/tasks'); + expect(requestUrl).toContain('/fakeName/query/v1/tasks'); done(); }); }); diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts index 3c7d3d966c..717847862a 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts @@ -58,7 +58,7 @@ export class TaskListCloudService { } private buildQueryUrl(requestNode: TaskQueryCloudRequestModel) { - return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}-query/v1/tasks`; + return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}/query/v1/tasks`; } private buildQueryParams(requestNode: TaskQueryCloudRequestModel) { diff --git a/lib/testing/src/lib/core/actions/identity/query.service.ts b/lib/testing/src/lib/core/actions/identity/query.service.ts index fdfbb4e660..7e39ec39ee 100644 --- a/lib/testing/src/lib/core/actions/identity/query.service.ts +++ b/lib/testing/src/lib/core/actions/identity/query.service.ts @@ -26,7 +26,7 @@ export class QueryService { } async getProcessInstanceTasks(processInstanceId, appName) { - const path = '/' + appName + '-query/v1/process-instances/' + processInstanceId + '/tasks'; + const path = '/' + appName + '/query/v1/process-instances/' + processInstanceId + '/tasks'; const method = 'GET'; const queryParams = {}, postBody = {}; @@ -36,7 +36,7 @@ export class QueryService { } async getProcessInstanceSubProcesses(processInstanceId, appName) { - const path = '/' + appName + '-query/v1/process-instances/' + processInstanceId + '/subprocesses'; + const path = '/' + appName + '/query/v1/process-instances/' + processInstanceId + '/subprocesses'; const method = 'GET'; const queryParams = {}; diff --git a/lib/testing/src/lib/core/actions/identity/tasks.service.ts b/lib/testing/src/lib/core/actions/identity/tasks.service.ts index 87d4e41417..d0d726da5c 100644 --- a/lib/testing/src/lib/core/actions/identity/tasks.service.ts +++ b/lib/testing/src/lib/core/actions/identity/tasks.service.ts @@ -26,7 +26,7 @@ export class TasksService { } async createStandaloneTask(taskName, appName, options?) { - const path = '/' + appName + '-rb/v1/tasks'; + const path = '/' + appName + '/rb/v1/tasks'; const method = 'POST'; const queryParams = {}, postBody = { @@ -40,7 +40,7 @@ export class TasksService { } async completeTask(taskId, appName) { - const path = '/' + appName + '-rb/v1/tasks/' + taskId + '/complete'; + const path = '/' + appName + '/rb/v1/tasks/' + taskId + '/complete'; const method = 'POST'; const queryParams = {}, postBody = {'payloadType': 'CompleteTaskPayload'}; @@ -50,7 +50,7 @@ export class TasksService { } async claimTask(taskId, appName) { - const path = '/' + appName + '-rb/v1/tasks/' + taskId + '/claim'; + const path = '/' + appName + '/rb/v1/tasks/' + taskId + '/claim'; const method = 'POST'; const queryParams = {}, postBody = {}; @@ -60,7 +60,7 @@ export class TasksService { } async deleteTask(taskId, appName) { - const path = '/' + appName + '-rb/v1/tasks/' + taskId; + const path = '/' + appName + '/rb/v1/tasks/' + taskId; const method = 'DELETE'; const queryParams = {}, postBody = {}; @@ -77,7 +77,7 @@ export class TasksService { } async getTask(taskId, appName) { - const path = '/' + appName + '-query/v1/tasks/' + taskId; + const path = '/' + appName + '/query/v1/tasks/' + taskId; const method = 'GET'; const queryParams = {}, postBody = {}; @@ -87,7 +87,7 @@ export class TasksService { } async createStandaloneSubtask(parentTaskId, appName, name) { - const path = '/' + appName + '-rb/v1/tasks'; + const path = '/' + appName + '/rb/v1/tasks'; const method = 'POST'; const queryParams = {}, postBody = {'name': name, 'parentTaskId': parentTaskId, 'payloadType': 'CreateTaskPayload'}; diff --git a/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts b/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts index 79042c8387..6a7f83d819 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts @@ -26,7 +26,7 @@ export class ProcessDefinitionsService { } async getProcessDefinitions(appName) { - const path = '/' + appName + '-rb/v1/process-definitions'; + const path = '/' + appName + '/rb/v1/process-definitions'; const method = 'GET'; const queryParams = {}; diff --git a/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts b/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts index 57f644d112..230b6645bf 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts @@ -26,7 +26,7 @@ export class ProcessInstancesService { } async createProcessInstance(processDefKey, appName, options?: any) { - const path = '/' + appName + '-rb/v1/process-instances'; + const path = '/' + appName + '/rb/v1/process-instances'; const method = 'POST'; const queryParams = {}, postBody = { @@ -39,7 +39,7 @@ export class ProcessInstancesService { } async suspendProcessInstance(processInstanceId, appName) { - const path = '/' + appName + '-rb/v1/process-instances/' + processInstanceId + '/suspend'; + const path = '/' + appName + '/rb/v1/process-instances/' + processInstanceId + '/suspend'; const method = 'POST'; const queryParams = {}, postBody = {}; @@ -48,7 +48,7 @@ export class ProcessInstancesService { } async deleteProcessInstance(processInstanceId, appName) { - const path = '/' + appName + '-rb/v1/process-instances/' + processInstanceId; + const path = '/' + appName + '/rb/v1/process-instances/' + processInstanceId; const method = 'DELETE'; const queryParams = {}, postBody = {}; @@ -57,7 +57,7 @@ export class ProcessInstancesService { } async completeProcessInstance(processInstanceId, appName) { - const path = '/' + appName + '-rb/v1/process-instances/' + processInstanceId + '/complete'; + const path = '/' + appName + '/rb/v1/process-instances/' + processInstanceId + '/complete'; const method = 'POST'; const queryParams = {}, postBody = {}; From 2c9fdf0d4da59d52fb59a3b6e7d8f140d654a2d1 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Mon, 8 Apr 2019 16:25:16 +0300 Subject: [PATCH 068/208] [ADF-4275] - Fix preselect user validation for User Id (#4474) * [ADF-4274] - Fix preselect user validation for User Id * [ADF-4275] - change search user response format * [ADF-4275] - add unit test to search user by id on single mode * [ADF-4275] - fix PeopleCloud unit tests and refractor validate User funcitonality * [ADF-4275] - fix unit tests * [ADF-4272] - reset spec file * [ADF-4275] - rebase and fix unit tests * Update people-cloud.component.ts --- .../people-cloud.component.spec.ts | 174 +++++++++++------- .../people-cloud/people-cloud.component.ts | 46 +++-- 2 files changed, 142 insertions(+), 78 deletions(-) diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 0d23998d9e..3a06022e51 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -16,7 +16,7 @@ */ import { PeopleCloudComponent } from './people-cloud.component'; -import { ComponentFixture, TestBed, async, tick, fakeAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { IdentityUserService, AlfrescoApiService, AlfrescoApiServiceMock, CoreModule, IdentityUserModel } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; import { of } from 'rxjs'; @@ -363,8 +363,6 @@ describe('PeopleCloudComponent', () => { describe('Single Mode and Pre-selected users with no validate flag', () => { - const change = new SimpleChange(null, mockPreselectedUsers, false); - beforeEach(async(() => { component.mode = 'single'; component.preSelectUsers = <any> mockPreselectedUsers; @@ -385,14 +383,6 @@ describe('PeopleCloudComponent', () => { }); })); - it('should pre-select preSelectUsers[0] when mode=single', async(() => { - component.ngOnChanges({ 'preSelectUsers': change }); - fixture.detectChanges(); - fixture.whenStable().then(() => { - const selectedUser = component.searchUserCtrl.value; - expect(selectedUser.id).toBe(mockUsers[1].id); - }); - })); it('should not pre-select any user when preSelectUsers is empty and mode=single', async(() => { component.preSelectUsers = []; fixture.detectChanges(); @@ -428,12 +418,13 @@ describe('PeopleCloudComponent', () => { }); })); - it('should pre-select preSelectUsers[0] when mode=single', fakeAsync(() => { + it('should pre-select preSelectUsers[0] when mode=single', async(() => { + component.mode = 'single'; + component.validate = false; fixture.detectChanges(); spyOn(component, 'searchUser').and.returnValue(Promise.resolve(mockPreselectedUsers)); component.ngOnChanges({ 'preSelectUsers': change }); fixture.detectChanges(); - tick(); const selectedUser = component.searchUserCtrl.value; expect(selectedUser.id).toBe(mockUsers[1].id); })); @@ -528,63 +519,122 @@ describe('PeopleCloudComponent', () => { expect(removeUserSpy).toHaveBeenCalled(); }); })); - }); - it('should emit warning if are invalid users', (done) => { - spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve([])); - const warnMessage = { message: 'INVALID_PRESELECTED_USERS', users: [{ username: 'invalidUsername' }] }; - component.validate = true; - component.preSelectUsers = <any> [{ username: 'invalidUsername' }]; - fixture.detectChanges(); - component.loadSinglePreselectUser(); - component.warning.subscribe((response) => { - expect(response).toEqual(warnMessage); - expect(response.message).toEqual(warnMessage.message); - expect(response.users).toEqual(warnMessage.users); - expect(response.users[0].username).toEqual('invalidUsername'); - done(); + it('should emit warning if are invalid users', (done) => { + spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve([])); + const warnMessage = { message: 'INVALID_PRESELECTED_USERS', users: [{ username: 'invalidUsername' }] }; + component.validate = true; + component.preSelectUsers = <any> [{ username: 'invalidUsername' }]; + fixture.detectChanges(); + component.loadSinglePreselectUser(); + component.warning.subscribe((response) => { + expect(response).toEqual(warnMessage); + expect(response.message).toEqual(warnMessage.message); + expect(response.users).toEqual(warnMessage.users); + expect(response.users[0].username).toEqual('invalidUsername'); + done(); + }); }); - }); - it('should filter user by id if validate true', async(() => { - const findByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'multiple'; - component.validate = true; - component.preSelectUsers = <any> [{ id: mockUsers[1].id }, { id: mockUsers[2].id }]; - fixture.detectChanges(); - fixture.whenStable().then(() => { + it('should filter user by id if validate true', async(() => { + const findByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(of(mockUsers[0])); + component.mode = 'multiple'; + component.validate = true; + component.preSelectUsers = <any> [{ id: mockUsers[0].id }, { id: mockUsers[1].id }]; + component.ngOnChanges({ 'preSelectUsers': change }); + fixture.detectChanges(); component.filterPreselectUsers().then((result) => { + fixture.detectChanges(); expect(findByIdSpy).toHaveBeenCalled(); - expect(component.userExists(result)).toEqual(true); + expect(component.userExists(result[0])).toEqual(true); + expect(result[1].id).toBe(mockUsers[0].id); }); - }); - })); + })); - it('should filter user by username if validate true', async(() => { - const findUserByUsernameSpy = spyOn(identityService, 'findUserByUsername').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'multiple'; - component.validate = true; - component.preSelectUsers = <any> [{ username: mockUsers[1].username }, { username: mockUsers[2].username }]; - fixture.detectChanges(); - fixture.whenStable().then(() => { - component.filterPreselectUsers().then((result) => { - expect(findUserByUsernameSpy).toHaveBeenCalled(); - expect(component.userExists(result)).toEqual(true); + it('should filter user by username if validate true', async(() => { + const findUserByUsernameSpy = spyOn(identityService, 'findUserByUsername').and.returnValue(of(mockUsers)); + component.mode = 'multiple'; + component.validate = true; + component.preSelectUsers = <any> [{ username: mockUsers[1].username }, { username: mockUsers[2].username }]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.filterPreselectUsers().then((result) => { + expect(findUserByUsernameSpy).toHaveBeenCalled(); + expect(component.userExists(result[0])).toEqual(true); + expect(component.userExists(result[1])).toEqual(true); + }); }); - }); - })); + })); - it('should filter user by email if validate true', async(() => { - const findUserByEmailSpy = spyOn(identityService, 'findUserByEmail').and.returnValue(Promise.resolve(mockUsers)); - component.mode = 'multiple'; - component.validate = true; - component.preSelectUsers = <any> [{ email: mockUsers[1].email }, { email: mockUsers[2].email }]; - fixture.detectChanges(); - fixture.whenStable().then(() => { - component.filterPreselectUsers().then((result) => { - expect(findUserByEmailSpy).toHaveBeenCalled(); - expect(component.userExists(result)).toEqual(true); + it('should filter user by email if validate true', async(() => { + const findUserByEmailSpy = spyOn(identityService, 'findUserByEmail').and.returnValue(of(mockUsers)); + component.mode = 'multiple'; + component.validate = true; + component.preSelectUsers = <any> [{ email: mockUsers[1].email }, { email: mockUsers[2].email }]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.filterPreselectUsers().then((result) => { + expect(findUserByEmailSpy).toHaveBeenCalled(); + expect(component.userExists(result[0])).toEqual(true); + expect(component.userExists(result[1])).toEqual(true); + }); }); - }); - })); + })); + + it('should search user by id on single selection mode', async(() => { + const findUserByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(of(mockUsers[0])); + component.mode = 'single'; + component.validate = true; + component.preSelectUsers = <any> [{ id: mockUsers[0].id }]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.validatePreselectUsers().then((result) => { + expect(findUserByIdSpy).toHaveBeenCalled(); + expect(result.length).toEqual(1); + }); + }); + })); + + it('should not preselect any user if email is invalid and validation enable', async(() => { + const findUserByEmailSpy = spyOn(identityService, 'findUserByEmail').and.returnValue(of([])); + component.mode = 'single'; + component.validate = true; + component.preSelectUsers = <any> [{ email: 'invalid email' }]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.validatePreselectUsers().then((result) => { + expect(findUserByEmailSpy).toHaveBeenCalled(); + expect(result.length).toEqual(0); + }); + }); + })); + + it('should not preselect any user if id is invalid and validation enable', async(() => { + const findUserByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(of([])); + component.mode = 'single'; + component.validate = true; + component.preSelectUsers = <any> [{ id: 'invalid id' }]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.validatePreselectUsers().then((result) => { + expect(findUserByIdSpy).toHaveBeenCalled(); + expect(result.length).toEqual(0); + }); + }); + })); + + it('should not preselect any user if username is invalid and validation enable', async(() => { + const findUserByUsernameSpy = spyOn(identityService, 'findUserByUsername').and.returnValue(of([])); + component.mode = 'single'; + component.validate = true; + component.preSelectUsers = <any> [{ username: 'invalid user' }]; + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.validatePreselectUsers().then((result) => { + expect(findUserByUsernameSpy).toHaveBeenCalled(); + expect(result.length).toEqual(0); + }); + }); + })); + }); }); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts index af01e43337..4f57e2eb9b 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts @@ -100,7 +100,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges { isFocused: boolean; - invalidUsers: IdentityUserModel[]; + invalidUsers: IdentityUserModel[] = []; constructor(private identityUserService: IdentityUserService, private logService: LogService) { } @@ -161,24 +161,26 @@ export class PeopleCloudComponent implements OnInit, OnChanges { } async validatePreselectUsers(): Promise<any> { - this.invalidUsers = []; - let filteredPreSelectUsers: { isValid: boolean, user: IdentityUserModel } []; + let filteredPreselectUsers: IdentityUserModel[]; + let validUsers: IdentityUserModel[] = []; try { - filteredPreSelectUsers = await this.filterPreselectUsers(); + filteredPreselectUsers = await this.filterPreselectUsers(); } catch (error) { - filteredPreSelectUsers = []; + validUsers = []; this.logService.error(error); } - return filteredPreSelectUsers.reduce((validUsers, validatedUser: any) => { - if (validatedUser.isValid) { - validUsers.push(validatedUser.user); + await this.preSelectUsers.map((user: IdentityUserModel) => { + const validUser = this.isValidUser(filteredPreselectUsers, user); + + if (validUser) { + validUsers.push(validUser); } else { - this.invalidUsers.push(validatedUser.user); + this.invalidUsers.push(user); } - return validUsers; - }, []); + }); + return validUsers; } async filterPreselectUsers() { @@ -191,7 +193,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges { this.logService.error(error); } const isUserValid: boolean = this.userExists(result); - return isUserValid ? { isValid: isUserValid, user: new IdentityUserModel(user) } : { isValid: isUserValid, user: user }; + return isUserValid ? new IdentityUserModel(result) : null; }); return await Promise.all(promiseBatch); } @@ -199,15 +201,27 @@ export class PeopleCloudComponent implements OnInit, OnChanges { async searchUser(user: IdentityUserModel) { const key: string = Object.keys(user)[0]; switch (key) { - case 'id': return this.identityUserService.findUserById(user[key]).toPromise(); - case 'username': return this.identityUserService.findUserByUsername(user[key]).toPromise(); - case 'email': return this.identityUserService.findUserByEmail(user[key]).toPromise(); + case 'id': return await this.identityUserService.findUserById(user[key]).toPromise(); + case 'username': return (await this.identityUserService.findUserByUsername(user[key]).toPromise())[0]; + case 'email': return (await this.identityUserService.findUserByEmail(user[key]).toPromise())[0]; default: return of([]); } } + private isValidUser(filteredUsers: IdentityUserModel[], user: IdentityUserModel) { + return filteredUsers.find((filteredUser: IdentityUserModel) => { + return filteredUser && + (filteredUser.id === user.id || + filteredUser.username === user.username || + filteredUser.email === user.email); + }); + } + public userExists(result: any): boolean { - return result && result.length > 0; + return result + && (result.id !== undefined + || result.username !== undefined + || result.amil !== undefined); } private initSearch() { From f89bf507f5b471996a007192156b635241af1539 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Mon, 8 Apr 2019 14:25:47 +0100 Subject: [PATCH 069/208] [ADF-4193] search error notifications and empty results (#4567) * search error notifications and empty results * update docs --- .../services/search-query-builder.service.md | 8 +++++ .../search-query-builder.service.spec.ts | 34 +++++++++++++++++++ .../search/search-query-builder.service.ts | 26 ++++++++++---- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/docs/content-services/services/search-query-builder.service.md b/docs/content-services/services/search-query-builder.service.md index ac180cf915..8b04806a22 100644 --- a/docs/content-services/services/search-query-builder.service.md +++ b/docs/content-services/services/search-query-builder.service.md @@ -11,6 +11,14 @@ Stores information from all the custom search and faceted search widgets, compil ## Class members +### Events + +| Name | Type | Details | +| --- | --- | --- | +| updated | QueryBody | Raised when query gets updated but before query is executed | +| executed | ResultSetPaging | Raised when query gets executed and results are available | +| error | any | Raised when search api emits internal error | + ### Methods - **addFilterQuery**(query: `string`)<br/> diff --git a/lib/content-services/search/search-query-builder.service.spec.ts b/lib/content-services/search/search-query-builder.service.spec.ts index b9f81228d0..db743ae0c9 100644 --- a/lib/content-services/search/search-query-builder.service.spec.ts +++ b/lib/content-services/search/search-query-builder.service.spec.ts @@ -613,4 +613,38 @@ describe('SearchQueryBuilder', () => { expect(compiled.highlight.mergeContiguous).toBe(true); }); + it('should emit error event', (done) => { + const config: SearchConfiguration = { + categories: [ + <any> { id: 'cat1', enabled: true } + ] + }; + const builder = new SearchQueryBuilderService(buildConfig(config), null); + spyOn(builder, 'buildQuery').and.throwError('some error'); + + builder.error.subscribe(() => { + done(); + }); + + builder.execute(); + }); + + it('should emit empty results on error', (done) => { + const config: SearchConfiguration = { + categories: [ + <any> { id: 'cat1', enabled: true } + ] + }; + const builder = new SearchQueryBuilderService(buildConfig(config), null); + spyOn(builder, 'buildQuery').and.throwError('some error'); + + builder.executed.subscribe((data) => { + expect(data.list.entries).toEqual([]); + expect(data.list.pagination.totalItems).toBe(0); + done(); + }); + + builder.execute(); + }); + }); diff --git a/lib/content-services/search/search-query-builder.service.ts b/lib/content-services/search/search-query-builder.service.ts index b0ae03c1b0..872847c66c 100644 --- a/lib/content-services/search/search-query-builder.service.ts +++ b/lib/content-services/search/search-query-builder.service.ts @@ -42,8 +42,9 @@ export class SearchQueryBuilderService { private _userQuery = ''; - updated: Subject<QueryBody> = new Subject(); - executed: Subject<ResultSetPaging> = new Subject(); + updated = new Subject<QueryBody>(); + executed = new Subject<ResultSetPaging>(); + error = new Subject(); categories: Array<SearchCategory> = []; queryFragments: { [id: string]: string } = {}; @@ -196,10 +197,23 @@ export class SearchQueryBuilderService { * @returns Nothing */ async execute() { - const query = this.buildQuery(); - if (query) { - const resultSetPaging: ResultSetPaging = await this.alfrescoApiService.searchApi.search(query); - this.executed.next(resultSetPaging); + try { + const query = this.buildQuery(); + if (query) { + const resultSetPaging: ResultSetPaging = await this.alfrescoApiService.searchApi.search(query); + this.executed.next(resultSetPaging); + } + } catch (error) { + this.error.next(error); + + this.executed.next({ + list: { + pagination: { + totalItems: 0 + }, + entries: [] + } + }); } } From dee63e3f3bbbd28f644ab407189396f20477dd81 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Mon, 8 Apr 2019 15:23:46 +0100 Subject: [PATCH 070/208] [ADF-3887] Different local storages for different ADF apps (#4539) * [ADF-3887] Different local storages for different ADF apps * [ADF-3887] Add documentation * [ADF-3887] Add unit tests and improve code * [ADF-3887] Add unit tests * [ADF-3887] Fix e2e tests * fix test * fix test * Update storage.service.md --- demo-shell/src/app.config.json | 1 + docs/core/services/storage.service.md | 17 +++ .../services/document-actions.service.spec.ts | 4 +- .../services/document-list.service.spec.ts | 4 +- .../services/folder-actions.service.spec.ts | 4 +- lib/core/app-config/app-config.service.ts | 3 +- .../app-config/debug-app-config.service.ts | 13 ++- .../node-favorite.directive.spec.ts | 3 +- lib/core/mock/alfresco-api.service.mock.ts | 6 +- lib/core/services/alfresco-api.service.ts | 4 +- lib/core/services/storage.service.spec.ts | 100 ++++++++++++++++++ lib/core/services/storage.service.ts | 33 ++++-- lib/core/services/user-preferences.service.ts | 1 + .../process-list-cloud.service.spec.ts | 4 +- .../task/services/task-cloud.service.spec.ts | 4 +- .../services/task-list-cloud.service.spec.ts | 4 +- lib/process-services/karma.conf.js | 1 + .../services/process-filter.service.spec.ts | 4 +- .../services/process.service.spec.ts | 4 +- .../services/task-filter.service.spec.ts | 4 +- .../services/tasklist.service.spec.ts | 4 +- .../actions/testing-alfresco-api.service.ts | 2 +- 22 files changed, 181 insertions(+), 43 deletions(-) create mode 100644 lib/core/services/storage.service.spec.ts diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 239c7fb63b..75d013078a 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -23,6 +23,7 @@ "redirectUriLogout": "/logout" }, "application": { + "storagePrefix": "ADF", "name": "Alfresco ADF Application", "copyright": "© 2016 - 2018 Alfresco Software, Inc. All Rights Reserved." }, diff --git a/docs/core/services/storage.service.md b/docs/core/services/storage.service.md index 90435c6731..1b904d49c4 100644 --- a/docs/core/services/storage.service.md +++ b/docs/core/services/storage.service.md @@ -44,6 +44,23 @@ more widely supported by browsers and can be set to expire after a certain date. If local storage is not available then non-persistent memory storage within the app is used instead. +## Storage specific to an ADF app + +If you are using multiple ADF apps, you might want to set the following configuration so that the apps have specific storages and are independent of others when setting and getting data from the local storage. + +In order to achieve this, you will only need to set your app identifier under the `storagePrefix` property of the app in your `app.config.json` file. + +```json +"application": { + "storagePrefix": "ADF_Identifier", + "name": "Your app name", + "copyright": "Your copyright message" +} +``` + +**Important note** +This identifier must be unique to the app to guarantee that it has its own storage. + ## See also - [Cookie service](cookie.service.md) diff --git a/lib/content-services/document-list/services/document-actions.service.spec.ts b/lib/content-services/document-list/services/document-actions.service.spec.ts index 67e9e8d7d6..1cca686419 100644 --- a/lib/content-services/document-list/services/document-actions.service.spec.ts +++ b/lib/content-services/document-list/services/document-actions.service.spec.ts @@ -16,7 +16,7 @@ */ import { AlfrescoApiServiceMock, AppConfigService, ContentService, - StorageService, setupTestBed, CoreModule, TranslationMock + setupTestBed, CoreModule, TranslationMock } from '@alfresco/adf-core'; import { FileNode, FolderNode } from '../../mock'; import { ContentActionHandler } from '../models/content-action.model'; @@ -37,7 +37,7 @@ describe('DocumentActionsService', () => { beforeEach(() => { const contentService = new ContentService(null, null, null, null); - const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService); diff --git a/lib/content-services/document-list/services/document-list.service.spec.ts b/lib/content-services/document-list/services/document-list.service.spec.ts index 403f0788e7..a57edea050 100644 --- a/lib/content-services/document-list/services/document-list.service.spec.ts +++ b/lib/content-services/document-list/services/document-list.service.spec.ts @@ -16,7 +16,7 @@ */ import { AlfrescoApiServiceMock, AlfrescoApiService, - AppConfigService, StorageService, ContentService, setupTestBed, CoreModule, LogService, AppConfigServiceMock } from '@alfresco/adf-core'; + AppConfigService, ContentService, setupTestBed, CoreModule, LogService, AppConfigServiceMock } from '@alfresco/adf-core'; import { DocumentListService } from './document-list.service'; import { CustomResourcesService } from './custom-resources.service'; @@ -70,7 +70,7 @@ describe('DocumentListService', () => { beforeEach(() => { const logService = new LogService(new AppConfigServiceMock(null)); const contentService = new ContentService(null, null, null, null); - alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); const customActionService = new CustomResourcesService(alfrescoApiService, logService); service = new DocumentListService(contentService, alfrescoApiService, logService, customActionService); jasmine.Ajax.install(); diff --git a/lib/content-services/document-list/services/folder-actions.service.spec.ts b/lib/content-services/document-list/services/folder-actions.service.spec.ts index badb07cd34..544af2bd20 100644 --- a/lib/content-services/document-list/services/folder-actions.service.spec.ts +++ b/lib/content-services/document-list/services/folder-actions.service.spec.ts @@ -16,7 +16,7 @@ */ import { TestBed } from '@angular/core/testing'; -import { AlfrescoApiServiceMock, AppConfigService, StorageService, ContentService, setupTestBed, CoreModule, TranslationMock } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, AppConfigService, ContentService, setupTestBed, CoreModule, TranslationMock } from '@alfresco/adf-core'; import { Observable } from 'rxjs'; import { FileNode, FolderNode } from '../../mock'; import { ContentActionHandler } from '../models/content-action.model'; @@ -39,7 +39,7 @@ describe('FolderActionsService', () => { appConfig.config.ecmHost = 'http://localhost:9876/ecm'; const contentService = new ContentService(null, null, null, null); - const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + const alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); documentListService = new DocumentListService(contentService, alfrescoApiService, null, null); service = new FolderActionsService(null, documentListService, contentService, new TranslationMock()); }); diff --git a/lib/core/app-config/app-config.service.ts b/lib/core/app-config/app-config.service.ts index 005560c3c9..e7e08cf4c4 100644 --- a/lib/core/app-config/app-config.service.ts +++ b/lib/core/app-config/app-config.service.ts @@ -37,7 +37,8 @@ export enum AppConfigValues { LOG_LEVEL = 'logLevel', LOGIN_ROUTE = 'loginRoute', DISABLECSRF = 'disableCSRF', - AUTH_WITH_CREDENTIALS = 'auth.withCredentials' + AUTH_WITH_CREDENTIALS = 'auth.withCredentials', + APPLICATION = 'application' } export enum Status { diff --git a/lib/core/app-config/debug-app-config.service.ts b/lib/core/app-config/debug-app-config.service.ts index bd049a443e..f9566dc676 100644 --- a/lib/core/app-config/debug-app-config.service.ts +++ b/lib/core/app-config/debug-app-config.service.ts @@ -17,21 +17,26 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { StorageService } from '../services/storage.service'; import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; @Injectable() export class DebugAppConfigService extends AppConfigService { - constructor(private storage: StorageService, http: HttpClient) { + constructor(http: HttpClient) { super(http); } /** @override */ get<T>(key: string, defaultValue?: T): T { if (key === AppConfigValues.OAUTHCONFIG) { - return <T> (JSON.parse(this.storage.getItem(key)) || super.get<T>(key, defaultValue)); + return <T> (JSON.parse(this.getItem(key)) || super.get<T>(key, defaultValue)); + } else if (key === AppConfigValues.APPLICATION) { + return undefined; } else { - return <T> (<any> this.storage.getItem(key) || super.get<T>(key, defaultValue)); + return <T> (<any> this.getItem(key) || super.get<T>(key, defaultValue)); } } + + getItem(key: string): string | null { + return localStorage.getItem(key); + } } diff --git a/lib/core/directives/node-favorite.directive.spec.ts b/lib/core/directives/node-favorite.directive.spec.ts index 94c27e9f46..4b2e321fd0 100644 --- a/lib/core/directives/node-favorite.directive.spec.ts +++ b/lib/core/directives/node-favorite.directive.spec.ts @@ -20,7 +20,6 @@ import { fakeAsync, tick } from '@angular/core/testing'; import { NodeFavoriteDirective } from './node-favorite.directive'; import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock'; import { AppConfigService } from '../app-config/app-config.service'; -import { StorageService } from '../services/storage.service'; import { setupTestBed } from '../testing/setupTestBed'; import { CoreTestingModule } from '../testing/core.testing.module'; @@ -34,7 +33,7 @@ describe('NodeFavoriteDirective', () => { }); beforeEach(() => { - alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); directive = new NodeFavoriteDirective( alfrescoApiService); }); diff --git a/lib/core/mock/alfresco-api.service.mock.ts b/lib/core/mock/alfresco-api.service.mock.ts index 8eccd59d01..89f408ccc1 100644 --- a/lib/core/mock/alfresco-api.service.mock.ts +++ b/lib/core/mock/alfresco-api.service.mock.ts @@ -17,16 +17,14 @@ import { Injectable } from '@angular/core'; import { AppConfigService } from '../app-config/app-config.service'; -import { StorageService } from '../services/storage.service'; import { AlfrescoApiService } from '../services/alfresco-api.service'; /* tslint:disable:adf-file-name */ @Injectable() export class AlfrescoApiServiceMock extends AlfrescoApiService { - constructor(protected appConfig: AppConfigService, - protected storage: StorageService) { - super(appConfig, storage); + constructor(protected appConfig: AppConfigService) { + super(appConfig); if (!this.alfrescoApi) { this.initAlfrescoApi(); } diff --git a/lib/core/services/alfresco-api.service.ts b/lib/core/services/alfresco-api.service.ts index 5e0421685f..b6d3200981 100644 --- a/lib/core/services/alfresco-api.service.ts +++ b/lib/core/services/alfresco-api.service.ts @@ -25,7 +25,6 @@ import { } from '@alfresco/js-api'; import { AlfrescoApiCompatibility, AlfrescoApiConfig } from '@alfresco/js-api'; import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; -import { StorageService } from './storage.service'; import { Subject } from 'rxjs'; import { OauthConfigModel } from '../models/oauth-config.model'; @@ -96,8 +95,7 @@ export class AlfrescoApiService { return this.getInstance().core.groupsApi; } - constructor(protected appConfig: AppConfigService, - protected storage: StorageService) { + constructor(protected appConfig: AppConfigService) { } async load() { diff --git a/lib/core/services/storage.service.spec.ts b/lib/core/services/storage.service.spec.ts new file mode 100644 index 0000000000..f9c2b8c377 --- /dev/null +++ b/lib/core/services/storage.service.spec.ts @@ -0,0 +1,100 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { AppConfigService } from '../app-config/app-config.service'; +import { StorageService } from './storage.service'; +import { setupTestBed } from '../testing/setupTestBed'; +import { CoreTestingModule } from '../testing/core.testing.module'; +import { AppConfigServiceMock } from '../mock/app-config.service.mock'; + +describe('StorageService', () => { + + let storage: StorageService; + let appConfig: AppConfigServiceMock; + const key = 'test_key'; + const value = 'test_value'; + + setupTestBed({ + imports: [CoreTestingModule], + providers: [ + { provide: AppConfigService, useClass: AppConfigServiceMock } + ] + }); + + beforeEach(() => { + appConfig = TestBed.get(AppConfigService); + appConfig.config = { + application: { + storagePrefix: 'ADF_APP' + } + }; + storage = TestBed.get(StorageService); + }); + + it('should get the prefix for the storage from app config', (done) => { + appConfig.load().then(() => { + expect(storage.storagePrefix).toBe('ADF_APP_'); + done(); + }); + }); + + it('should set an empty prefix when the it is not defined in the app config', (done) => { + appConfig.config.application.storagePrefix = ''; + appConfig.load().then(() => { + expect(storage.storagePrefix).toBe(''); + done(); + }); + }); + + it('should set a property with the prefix in the local storage', (done) => { + storage.clear(); + + appConfig.load().then(() => { + storage.setItem(key, value); + const storageKey = localStorage.key(0); + expect(storageKey).toBe('ADF_APP_' + key); + expect(localStorage.getItem(storageKey)).toBe(value); + done(); + }); + }); + + it('should set a property without a prefix in the local storage', (done) => { + storage.clear(); + appConfig.config.application.storagePrefix = ''; + + appConfig.load().then(() => { + storage.setItem(key, value); + + const storageKey = localStorage.key(0); + expect(storageKey).toBe(key); + expect(localStorage.getItem(storageKey)).toBe(value); + done(); + }); + }); + + it('should be able to get a property from the local storage', (done) => { + storage.clear(); + + appConfig.load().then(() => { + storage.setItem(key, value); + + expect(storage.getItem(key)).toBe(value); + done(); + }); + }); +}); diff --git a/lib/core/services/storage.service.ts b/lib/core/services/storage.service.ts index 35ace886f8..f8979ae6e7 100644 --- a/lib/core/services/storage.service.ts +++ b/lib/core/services/storage.service.ts @@ -16,6 +16,7 @@ */ import { Injectable } from '@angular/core'; +import { AppConfigService } from '../app-config/app-config.service'; @Injectable({ providedIn: 'root' @@ -24,9 +25,11 @@ export class StorageService { private memoryStore: { [key: string]: any } = {}; private useLocalStorage: boolean = false; + storagePrefix: string; - constructor() { + constructor(private appConfigService: AppConfigService) { this.useLocalStorage = this.storageAvailable('localStorage'); + this.appConfigService.onLoad.subscribe(this.getAppPrefix.bind(this)); } /** @@ -36,9 +39,9 @@ export class StorageService { */ getItem(key: string): string | null { if (this.useLocalStorage) { - return localStorage.getItem(key); + return localStorage.getItem(this.storagePrefix + key); } else { - return this.memoryStore.hasOwnProperty(key) ? this.memoryStore[key] : null; + return this.memoryStore.hasOwnProperty(this.storagePrefix + key) ? this.memoryStore[this.storagePrefix + key] : null; } } @@ -49,9 +52,9 @@ export class StorageService { */ setItem(key: string, data: string) { if (this.useLocalStorage) { - localStorage.setItem(key, data); + localStorage.setItem(this.storagePrefix + key, data); } else { - this.memoryStore[key] = data.toString(); + this.memoryStore[this.storagePrefix + key] = data.toString(); } } @@ -70,9 +73,9 @@ export class StorageService { */ removeItem(key: string) { if (this.useLocalStorage) { - localStorage.removeItem(key); + localStorage.removeItem(this.storagePrefix + key); } else { - delete this.memoryStore[key]; + delete this.memoryStore[this.storagePrefix + key]; } } @@ -83,7 +86,7 @@ export class StorageService { */ hasItem(key: string): boolean { if (this.useLocalStorage) { - return localStorage.getItem(key) ? true : false; + return localStorage.getItem(this.storagePrefix + key) ? true : false; } else { return this.memoryStore.hasOwnProperty(key); } @@ -101,4 +104,18 @@ export class StorageService { } } + /** + * Sets the prefix that is used for the local storage of the app + * It assigns the string that is defined i the app config, + * empty prefix otherwise. + */ + getAppPrefix() { + const appConfiguration = this.appConfigService.get<any>('application'); + if (appConfiguration && appConfiguration.storagePrefix) { + this.storagePrefix = appConfiguration.storagePrefix + '_'; + } else { + this.storagePrefix = ''; + } + } + } diff --git a/lib/core/services/user-preferences.service.ts b/lib/core/services/user-preferences.service.ts index 5cd8a9c29c..507be375db 100644 --- a/lib/core/services/user-preferences.service.ts +++ b/lib/core/services/user-preferences.service.ts @@ -153,6 +153,7 @@ export class UserPreferencesService { */ setStoragePrefix(value: string) { this.storage.setItem('USER_PROFILE', value || 'GUEST'); + this.initUserPreferenceStatus(); } /** diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts index 27d380a3d1..03fd9d492c 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.spec.ts @@ -17,7 +17,7 @@ import { async } from '@angular/core/testing'; import { setupTestBed } from '@alfresco/adf-core'; import { fakeProcessCloudList } from '../mock/process-list-service.mock'; -import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { ProcessListCloudService } from './process-list-cloud.service'; import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model'; @@ -62,7 +62,7 @@ describe('Activiti ProcessList Cloud Service', () => { }); beforeEach(async(() => { - alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()); + alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null)); service = new ProcessListCloudService(alfrescoApiMock, new AppConfigService(null), new LogService(new AppConfigService(null))); diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts index 30bf8eb1e0..ae1d8f9aef 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts @@ -17,7 +17,7 @@ import { async, TestBed } from '@angular/core/testing'; import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; -import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { TaskCloudService } from './task-cloud.service'; import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock'; import { taskDetailsCloudMock } from '../task-header/mocks/task-details-cloud.mock'; @@ -68,7 +68,7 @@ describe('Task Cloud Service', () => { }); beforeEach(async(() => { - alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ); + alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null)); identityUserService = TestBed.get(IdentityUserService); spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue(cloudMockUser); service = new TaskCloudService(alfrescoApiMock, diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts index 07b327b681..3a381eea6d 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.spec.ts @@ -18,7 +18,7 @@ import { async } from '@angular/core/testing'; import { setupTestBed } from '@alfresco/adf-core'; import { fakeTaskCloudList } from '../mock/fakeTaskResponseMock'; -import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { TaskListCloudService } from './task-list-cloud.service'; import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model'; @@ -64,7 +64,7 @@ describe('Activiti TaskList Cloud Service', () => { }); beforeEach(async(() => { - alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ); + alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null)); service = new TaskListCloudService(alfrescoApiMock, new AppConfigService(null), new LogService(new AppConfigService(null))); diff --git a/lib/process-services/karma.conf.js b/lib/process-services/karma.conf.js index d5ecb25724..9a103b046e 100644 --- a/lib/process-services/karma.conf.js +++ b/lib/process-services/karma.conf.js @@ -43,6 +43,7 @@ module.exports = function (config) { '/assets/': '/base/lib/process-services/assets/', '/base/assets/': '/base/lib/process-services/assets/', '/assets/adf-core/i18n/en.json': '/base/lib/core/i18n/en.json', + '/assets/adf-core/i18n/en.json': '/base/lib/core/i18n/en.json', '/assets/adf-content-services/i18n/en.json': '/base/lib/content-services/i18n/en.json', '/assets/adf-process-services/i18n/en-GB.json': '/base/lib/process-services/i18n/en.json', '/app.config.json': '/base/lib/config/app.config.json' diff --git a/lib/process-services/process-list/services/process-filter.service.spec.ts b/lib/process-services/process-list/services/process-filter.service.spec.ts index 71a9e71a68..61e05841f9 100644 --- a/lib/process-services/process-list/services/process-filter.service.spec.ts +++ b/lib/process-services/process-list/services/process-filter.service.spec.ts @@ -19,7 +19,7 @@ import { async } from '@angular/core/testing'; import { mockError, fakeProcessFilters } from '../../mock'; import { FilterProcessRepresentationModel } from '../models/filter-process.model'; import { ProcessFilterService } from './process-filter.service'; -import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, StorageService, setupTestBed, CoreModule } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core'; declare let jasmine: any; @@ -36,7 +36,7 @@ describe('Process filter', () => { }); beforeEach(() => { - apiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ); + apiService = new AlfrescoApiServiceMock(new AppConfigService(null)); service = new ProcessFilterService(apiService); alfrescoApi = apiService.getInstance(); }); diff --git a/lib/process-services/process-list/services/process.service.spec.ts b/lib/process-services/process-list/services/process.service.spec.ts index aa195a3cf2..1fe11c0122 100644 --- a/lib/process-services/process-list/services/process.service.spec.ts +++ b/lib/process-services/process-list/services/process.service.spec.ts @@ -21,7 +21,7 @@ import { mockError, fakeProcessDef, fakeTasksList } from '../../mock'; import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model'; import { ProcessInstanceVariable } from '../models/process-instance-variable.model'; import { ProcessService } from './process.service'; -import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigService, StorageService, setupTestBed, CoreModule } from '@alfresco/adf-core'; +import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core'; declare let moment: any; @@ -38,7 +38,7 @@ describe('ProcessService', () => { }); beforeEach(() => { - apiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ); + apiService = new AlfrescoApiServiceMock(new AppConfigService(null)); service = new ProcessService(apiService); alfrescoApi = apiService.getInstance(); }); diff --git a/lib/process-services/task-list/services/task-filter.service.spec.ts b/lib/process-services/task-list/services/task-filter.service.spec.ts index 31d0a940b0..cf6d9b5591 100644 --- a/lib/process-services/task-list/services/task-filter.service.spec.ts +++ b/lib/process-services/task-list/services/task-filter.service.spec.ts @@ -19,7 +19,7 @@ import { async } from '@angular/core/testing'; import { fakeAppFilter, fakeAppPromise, fakeFilters } from '../../mock'; import { FilterRepresentationModel } from '../models/filter.model'; import { TaskFilterService } from './task-filter.service'; -import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, setupTestBed, CoreModule } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, LogService, AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core'; declare let jasmine: any; @@ -34,7 +34,7 @@ describe('Activiti Task filter Service', () => { }); beforeEach(async(() => { - service = new TaskFilterService(new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()), new LogService(new AppConfigService(null))); + service = new TaskFilterService(new AlfrescoApiServiceMock(new AppConfigService(null)), new LogService(new AppConfigService(null))); jasmine.Ajax.install(); })); diff --git a/lib/process-services/task-list/services/tasklist.service.spec.ts b/lib/process-services/task-list/services/tasklist.service.spec.ts index 0c7f545c40..575e611cae 100644 --- a/lib/process-services/task-list/services/tasklist.service.spec.ts +++ b/lib/process-services/task-list/services/tasklist.service.spec.ts @@ -35,7 +35,7 @@ import { import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model'; import { TaskDetailsModel } from '../models/task-details.model'; import { TaskListService } from './tasklist.service'; -import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService } from '@alfresco/adf-core'; +import { AlfrescoApiServiceMock, LogService, AppConfigService } from '@alfresco/adf-core'; declare let jasmine: any; @@ -50,7 +50,7 @@ describe('Activiti TaskList Service', () => { }); beforeEach(async(() => { - service = new TaskListService(new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ), new LogService(new AppConfigService(null))); + service = new TaskListService(new AlfrescoApiServiceMock(new AppConfigService(null)), new LogService(new AppConfigService(null))); jasmine.Ajax.install(); })); diff --git a/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts b/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts index b6c9d50c0e..186abbc7f2 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/testing-alfresco-api.service.ts @@ -26,7 +26,7 @@ export class TestingAlfrescoApiService extends AlfrescoApiService { }; constructor(public appConfig: AppConfigService) { - super(null, null); + super(null); const oauth = Object.assign({}, this.appConfig.get<any>(AppConfigValues.OAUTHCONFIG, null)); this.config = new AlfrescoApiConfig({ provider: this.appConfig.get<string>(AppConfigValues.PROVIDERS), From a87d1ef002cf53e1592ed984a5bce0038eda6fad Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Mon, 8 Apr 2019 18:37:37 +0300 Subject: [PATCH 071/208] [ADF-4272] TaskListCloud - improvements on CopyClipboardDirective (#4547) * [ADF-4272] DocumentList - add Copy content tooltip directive * [ADF-4272] - fix build issue * [ADF-4272] - change directive name and add requested changes * [ADF-4272] - reset task-list-cloud html content * [ADF-4272] - fix build * [AFG-4272] - change name to CopyClipboard * [ADF-4272] - PR changes * [ADF-4272] - fix tests * [ADF-4272[] - lint * [ADF-4272] - merge clipboard directive with copy-content directive * [ADF-4272] - PR changes * [ADF-4272] - change docs --- demo-shell/resources/i18n/en.json | 4 +- .../datatable/datatable.component.html | 4 +- docs/core/components/datatable.component.md | 107 ++++++++------ docs/core/directives/clipboard.directive.md | 36 +++++ .../content-node-share.dialog.html | 2 +- .../components/document-list.component.scss | 12 ++ .../clipboard/clipboard.directive.spec.ts | 86 ++++++++++- lib/core/clipboard/clipboard.directive.ts | 53 ++++++- lib/core/clipboard/clipboard.module.ts | 12 +- lib/core/clipboard/clipboard.service.ts | 16 +- lib/core/data-column/data-column.component.ts | 4 + .../datatable/datatable-cell.component.ts | 18 ++- .../datatable/datatable.component.html | 1 + .../datatable/datatable.component.scss | 1 + lib/core/datatable/data/data-column.model.ts | 1 + .../datatable/data/object-datacolumn.model.ts | 2 + lib/core/datatable/datatable.module.ts | 5 +- .../directives/claim-task.directive.spec.ts | 4 - .../task-list-cloud.component.spec.ts | 139 +++++++++++++++++- 19 files changed, 433 insertions(+), 74 deletions(-) create mode 100644 docs/core/directives/clipboard.directive.md diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 17e745dcd7..5eb8d9adf4 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -179,7 +179,9 @@ "REPLACE_COLUMNS": "Replace columns", "LOAD_NODE": "Load Node", "MULTISELECT": "Multiselect", - "MULTISELECT_DESCRIPTION": "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items" + "MULTISELECT_DESCRIPTION": "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items", + "CLICK_TO_COPY": "Click to copy", + "SUCCESS_COPY": "Text copied to clipboard" }, "ANALYTICS_REPORT": { "NO_REPORT_MESSAGE": "No report selected. Choose a report from the list" diff --git a/demo-shell/src/app/components/datatable/datatable.component.html b/demo-shell/src/app/components/datatable/datatable.component.html index 32fca95c03..4b95fd54ba 100644 --- a/demo-shell/src/app/components/datatable/datatable.component.html +++ b/demo-shell/src/app/components/datatable/datatable.component.html @@ -11,8 +11,8 @@ </mat-slide-toggle> <div style="height: 310px; overflow-y: auto;"> - <adf-datatable - #dataTable + <adf-datatable + #dataTable [data]="data" [stickyHeader]="stickyHeader" [selectionMode]="selectionMode" diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 759199c27a..5d922f2a84 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -35,7 +35,7 @@ See it live: [DataTable Quickstart](https://embed.plnkr.co/80qr4YFBeHjLMdAV0F6l/ **app.component.html** ```html -<adf-datatable +<adf-datatable [data]="data"> </adf-datatable> ``` @@ -117,7 +117,7 @@ export class DataTableDemo { ``` ```html -<adf-datatable +<adf-datatable [data]="data"> </adf-datatable> ``` @@ -178,16 +178,16 @@ export class DataTableDemo { // columns this.schema = [ - { - type: 'text', - key: 'id', - title: 'Id', - sortable: true + { + type: 'text', + key: 'id', + title: 'Id', + sortable: true }, { - type: 'text', - key: 'name', - title: 'Name', + type: 'text', + key: 'name', + title: 'Name', sortable: true } ]; @@ -222,16 +222,16 @@ export class DataTableDemo { // columns this.schema = [ - { - type: 'text', - key: 'id', - title: 'Id', - sortable: true + { + type: 'text', + key: 'id', + title: 'Id', + sortable: true }, { - type: 'text', - key: 'name', - title: 'Name', + type: 'text', + key: 'name', + title: 'Name', sortable: true } ]; @@ -266,7 +266,7 @@ You can also supply a `<adf-no-content-template>` or an ``` ```html -<adf-datatable ...> +<adf-datatable ...> <adf-empty-list> <adf-empty-list-header>"'My custom Header'"</adf-empty-list-header> <adf-empty-list-body>"'My custom body'"</adf-empty-list-body> @@ -296,7 +296,7 @@ while the data for the table is loading: ```js isLoading(): boolean { - //your custom logic to identify if you are in a loading state + //your custom logic to identify if you are in a loading state } ``` @@ -403,7 +403,7 @@ Set the `display` property to "gallery" to enable Card View mode: #### row-keyup DOM event -Emitted on the 'keyup' event for the focused row. +Emitted on the 'keyup' event for the focused row. This is an instance of `CustomEvent` with the `details` property containing the following object: @@ -420,7 +420,7 @@ Emitted when the user clicks a row. Event properties: ```ts -sender: any // DataTable instance +sender: any // DataTable instance value: DataRow, // row clicked event: Event // original HTML DOM event ``` @@ -442,7 +442,7 @@ Emitted when the user double-clicks a row. Event properties: ```ts -sender: any // DataTable instance +sender: any // DataTable instance value: DataRow, // row clicked event: Event // original HTML DOM event ``` @@ -515,7 +515,7 @@ This event is cancellable. You can use `event.preventDefault()` to prevent the d Emitted when the user executes a row action. -This usually accompanies a `showRowActionsMenu` event. +This usually accompanies a `showRowActionsMenu` event. The DataTable itself does not execute actions but provides support for external integration. If actions are provided using the `showRowActionsMenu` event then `executeRowAction` will be automatically executed when the user clicks a @@ -575,15 +575,15 @@ By default, the content of the cells is wrapped so you can see all the data insi ![](../../docassets/images/datatable-wrapped-text.png) -However, you can also truncate the text within these cells using the `adf-ellipsis-cell` class in the desired column: +However, you can also truncate the text within these cells using the `adf-ellipsis-cell` class in the desired column: ```js -{ - type: 'text', - key: 'createdOn', - title: 'Created On', - sortable: true, - cssClass: 'adf-ellipsis-cell' +{ + type: 'text', + key: 'createdOn', + title: 'Created On', + sortable: true, + cssClass: 'adf-ellipsis-cell' } ``` @@ -603,14 +603,14 @@ widths according to your needs: #### No-growing cells -As mentioned before, in the beginning, all cells have the same width. You can prevent cells from growing by using the `adf-no-grow-cell` class. +As mentioned before, in the beginning, all cells have the same width. You can prevent cells from growing by using the `adf-no-grow-cell` class. ```js -{ - type: 'date', - key: 'created', - title: 'Created On', - cssClass: 'adf-ellipsis-cell adf-no-grow-cell' +{ + type: 'date', + key: 'created', + title: 'Created On', + cssClass: 'adf-ellipsis-cell adf-no-grow-cell' } ``` @@ -623,11 +623,11 @@ Notice that this class is compatible with `adf-ellipsis-cell` and for that reaso You can combine the CSS classes described above to customize the table as needed: ```js -{ - type: 'text', - key: 'name', - title: 'Name', - cssClass: 'adf-ellipsis-cell adf-expand-cell-3' +{ + type: 'text', + key: 'name', + title: 'Name', + cssClass: 'adf-ellipsis-cell adf-expand-cell-3' } ``` @@ -639,7 +639,7 @@ always visible. You can do this using the following steps. First, set the `stickyHeader` property of your datatable to `true`: ```html -<adf-datatable +<adf-datatable [data]="data" [stickyHeader]="true"> </adf-datatable> @@ -658,6 +658,27 @@ the total height of all rows exceeds the fixed height of the parent element. </div> ``` +### CopyClipboardDirective example + +See the [Copy Content Directive ](../directives/clipboard.directive.md) page for full details of the directive + +Json config file: +```json +[ + {"type": "text", "key": "id", "title": "Id", "copyContent": "true"}, + {"type": "text", "key": "name", "title": "name"}, +] +``` +HTML data-columns +```html +<adf-tasklist ...> + <data-columns> + <data-column [copyContent]="true" key="id" title="Id"></data-column> + <data-column key="created" title="Created" class="hidden"></data-column> + </data-columns> +</adf-tasklist> +``` + Once set up, the sticky header behaves as shown in the image below: ![](../../docassets/images/datatable-sticky-header.png) diff --git a/docs/core/directives/clipboard.directive.md b/docs/core/directives/clipboard.directive.md new file mode 100644 index 0000000000..f96560d451 --- /dev/null +++ b/docs/core/directives/clipboard.directive.md @@ -0,0 +1,36 @@ +--- +Title: Copy Clipboard directive +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-01 +--- + +# [Clipboard directive](../../../lib/core/clipboard/clipboard.directive.ts "Defined in clipboard.directive.ts") + +Copy text to clipboard + +## Basic Usage + +```html +<span adf-clipboard="translate_key" [clipboard-notification]="notify message"> + text to copy +</span> + +<button adf-clipboard="translate_key" target="ref" [clipboard-notification]="notify message"> + Copy +</button> +``` + + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| target | `HTMLElement ref` | false | HTMLElement reference | +| clipboard-notification | `string` | | Translation key message for toast notification | + +## Details + +When the user hover the directive element a tooltip will will show up to inform that, when you click on the current element, the content or the reference content will be copied into the clipboard. diff --git a/lib/content-services/content-node-share/content-node-share.dialog.html b/lib/content-services/content-node-share/content-node-share.dialog.html index 607b2a2e37..cc5e893393 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.html +++ b/lib/content-services/content-node-share/content-node-share.dialog.html @@ -31,7 +31,7 @@ readonly="readonly"> <mat-icon class="adf-input-action" matSuffix [clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate" - [adf-clipboard]="sharedLinkInput"> + [adf-clipboard] target="sharedLinkInput"> link </mat-icon> </mat-form-field> diff --git a/lib/content-services/document-list/components/document-list.component.scss b/lib/content-services/document-list/components/document-list.component.scss index 99a4178137..162c452e22 100644 --- a/lib/content-services/document-list/components/document-list.component.scss +++ b/lib/content-services/document-list/components/document-list.component.scss @@ -1,6 +1,8 @@ @mixin adf-document-list-theme($theme) { $foreground: map-get($theme, foreground); + $background: map-get($theme, background); $accent: map-get($theme, accent); + $primary: map-get($theme, primary); .mat-icon.adf-datatable-selected { height: 100%; @@ -186,4 +188,14 @@ } } } + + .adf-datatable-copy-tooltip { + position: absolute; + background: mat-color($primary); + color: mat-color($primary, default-contrast) !important; + padding: 5px 10px; + border-radius: 5px; + bottom: 88%; + left:0; + } } diff --git a/lib/core/clipboard/clipboard.directive.spec.ts b/lib/core/clipboard/clipboard.directive.spec.ts index c35a25ee4a..e9a0e11906 100644 --- a/lib/core/clipboard/clipboard.directive.spec.ts +++ b/lib/core/clipboard/clipboard.directive.spec.ts @@ -15,28 +15,30 @@ * limitations under the License. */ -import { Component } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Component, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'; import { setupTestBed } from '../testing/setupTestBed'; import { CoreModule } from '../core.module'; import { ClipboardService } from './clipboard.service'; +import { ClipboardDirective } from './clipboard.directive'; +import { RouterTestingModule } from '@angular/router/testing'; @Component({ selector: 'adf-test-component', template: ` <button clipboard-notification="copy success" - [adf-clipboard]="ref"> + [adf-clipboard] [target]="ref"> copy </button> <input #ref /> ` }) -class TestComponent {} +class TestTargetClipboardComponent {} describe('ClipboardDirective', () => { - let fixture: ComponentFixture<TestComponent>; + let fixture: ComponentFixture<TestTargetClipboardComponent>; let clipboardService: ClipboardService; setupTestBed({ @@ -44,7 +46,7 @@ describe('ClipboardDirective', () => { CoreModule.forRoot() ], declarations: [ - TestComponent + TestTargetClipboardComponent ], providers: [ ClipboardService @@ -52,7 +54,7 @@ describe('ClipboardDirective', () => { }); beforeEach(() => { - fixture = TestBed.createComponent(TestComponent); + fixture = TestBed.createComponent(TestTargetClipboardComponent); clipboardService = TestBed.get(ClipboardService); fixture.detectChanges(); }); @@ -65,3 +67,73 @@ describe('ClipboardDirective', () => { expect(clipboardService.copyToClipboard).toHaveBeenCalled(); }); }); + +describe('CopyClipboardDirective', () => { + + @Component({ + selector: 'adf-copy-conent-test-component', + template: `<span adf-clipboard='DOCUMENT_LIST.ACTIONS.DOCUMENT.CLICK_TO_COPY'>{{ mockText }}</span>` + }) + class TestCopyClipboardComponent { + + mockText = 'text to copy'; + + @ViewChild(ClipboardDirective) + clipboardDirective: ClipboardDirective; + } + + let fixture: ComponentFixture<TestCopyClipboardComponent>; + let element: HTMLElement; + + setupTestBed({ + imports: [ + CoreModule.forRoot(), + RouterTestingModule + ], + declarations: [ + TestCopyClipboardComponent + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestCopyClipboardComponent); + element = fixture.debugElement.nativeElement; + fixture.detectChanges(); + }); + + it('should show tooltip when hover element', (() => { + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + })); + + it('should not show tooltip when element it is not hovered', (() => { + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + + spanHTMLElement.dispatchEvent(new Event('mouseleave')); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + })); + + it('should copy the content of element when click it', fakeAsync(() => { + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span'); + fixture.detectChanges(); + spyOn(document, 'execCommand'); + spanHTMLElement.dispatchEvent(new Event('click')); + tick(); + fixture.detectChanges(); + expect(document.execCommand).toHaveBeenCalledWith('copy'); + })); + + it('should not copy the content of element when click it', fakeAsync(() => { + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span'); + fixture.detectChanges(); + spyOn(document, 'execCommand'); + spanHTMLElement.dispatchEvent(new Event('mouseleave')); + tick(); + fixture.detectChanges(); + expect(document.execCommand).not.toHaveBeenCalled(); + })); +}); diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index fe08de6d6d..0ede53291b 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -15,33 +15,78 @@ * limitations under the License. */ -import { Directive, Input, HostListener } from '@angular/core'; +import { Directive, Input, HostListener, Component, ViewContainerRef, ComponentFactoryResolver, AfterContentInit } from '@angular/core'; import { ClipboardService } from './clipboard.service'; @Directive({ selector: '[adf-clipboard]', exportAs: 'adfClipboard' }) -export class ClipboardDirective { +export class ClipboardDirective implements AfterContentInit { // tslint:disable-next-line:no-input-rename - @Input('adf-clipboard') target: HTMLInputElement | HTMLTextAreaElement; + @Input('adf-clipboard') + placeholder: string; + + @Input() + target: HTMLInputElement | HTMLTextAreaElement; // tslint:disable-next-line:no-input-rename @Input('clipboard-notification') message: string; + private value: string; + + constructor(private clipboardService: ClipboardService, + public viewContainerRef: ViewContainerRef, + private resolver: ComponentFactoryResolver) {} + @HostListener('click', ['$event']) handleClickEvent(event: MouseEvent) { event.preventDefault(); + event.stopPropagation(); this.copyToClipboard(); } - constructor(private clipboardService: ClipboardService) {} + @HostListener('mouseenter') + showTooltip() { + const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); + const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; + componentRef.copyText = this.value; + componentRef.placeholder = this.placeholder; + } + + @HostListener('mouseleave') + closeTooltip() { + this.viewContainerRef.remove(); + } private copyToClipboard() { const isValidTarget = this.clipboardService.isTargetValid(this.target); if (isValidTarget) { this.clipboardService.copyToClipboard(this.target, this.message); + } else { + this.copyContentToClipboard(this.viewContainerRef.element.nativeElement.innerHTML); } } + + private copyContentToClipboard(content) { + this.clipboardService.copyContentToClipboard(content, this.message); + } + + ngAfterContentInit() { + setTimeout( () => { + this.value = this.viewContainerRef.element.nativeElement.innerHTML; + }); + } +} + +@Component({ + selector: 'adf-datatable-highlight-tooltip', + template: ` + <span class='adf-datatable-copy-tooltip'>{{ placeholder | translate }} <b> {{ copyText }} </b></span> + ` +}) +export class ClipboardComponent { + copyText: string; + placeholder: string; } diff --git a/lib/core/clipboard/clipboard.module.ts b/lib/core/clipboard/clipboard.module.ts index 12104922f5..9ebc6fa490 100644 --- a/lib/core/clipboard/clipboard.module.ts +++ b/lib/core/clipboard/clipboard.module.ts @@ -17,22 +17,26 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; -import { ClipboardDirective } from './clipboard.directive'; +import { ClipboardDirective, ClipboardComponent } from './clipboard.directive'; import { ClipboardService } from './clipboard.service'; +import { TranslateModule } from '@ngx-translate/core'; @NgModule({ imports: [ - CommonModule + CommonModule, + TranslateModule.forChild() ], providers: [ ClipboardService ], declarations: [ - ClipboardDirective + ClipboardDirective, + ClipboardComponent ], exports: [ ClipboardDirective - ] + ], + entryComponents: [ClipboardComponent] }) export class ClipboardModule {} diff --git a/lib/core/clipboard/clipboard.service.ts b/lib/core/clipboard/clipboard.service.ts index 046dc19de2..53064a3beb 100644 --- a/lib/core/clipboard/clipboard.service.ts +++ b/lib/core/clipboard/clipboard.service.ts @@ -32,8 +32,6 @@ export class ClipboardService { if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { return !target.hasAttribute('disabled'); } - - this.logService.error(`${target} should be input or textarea`); return false; } @@ -50,6 +48,20 @@ export class ClipboardService { } } + copyContentToClipboard(content: string, message: string) { + try { + document.addEventListener('copy', (e: ClipboardEvent) => { + e.clipboardData.setData('text/plain', (content)); + e.preventDefault(); + document.removeEventListener('copy', null); + }); + document.execCommand('copy'); + this.notify(message); + } catch (error) { + this.logService.error(error); + } + } + private notify(message) { if (message) { this.notificationService.openSnackMessage(message); diff --git a/lib/core/data-column/data-column.component.ts b/lib/core/data-column/data-column.component.ts index e1e2950528..345dace375 100644 --- a/lib/core/data-column/data-column.component.ts +++ b/lib/core/data-column/data-column.component.ts @@ -66,6 +66,10 @@ export class DataColumnComponent implements OnInit { @Input('class') cssClass: string; + /** flag to show the copy content directive */ + @Input() + copyContent: boolean; + ngOnInit() { if (!this.srTitle && this.key === '$thumbnail') { this.srTitle = 'Thumbnail'; diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index 3308688ad6..01b6f5cb45 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -35,13 +35,21 @@ import { Node } from '@alfresco/js-api'; changeDetection: ChangeDetectionStrategy.OnPush, template: ` <ng-container> + <span *ngIf="copyContent; else defaultCell" + adf-clipboard="DATATABLE.CLICK_TO_COPY" + [clipboard-notification]="'DATATABLE.SUCCESS_COPY'" + [attr.aria-label]="value$ | async" + [title]="tooltip" + class="adf-datatable-cell-value" + >{{ value$ | async }}</span> + </ng-container> + <ng-template #defaultCell> <span [attr.aria-label]="value$ | async" [title]="tooltip" class="adf-datatable-cell-value" - >{{ value$ | async }}</span - > - </ng-container> + >{{ value$ | async }}</span> + </ng-template> `, encapsulation: ViewEncapsulation.None, host: { class: 'adf-datatable-cell' } @@ -58,6 +66,9 @@ export class DataTableCellComponent implements OnInit, OnDestroy { value$ = new BehaviorSubject<any>(''); + @Input() + copyContent: boolean; + @Input() tooltip: string; @@ -67,7 +78,6 @@ export class DataTableCellComponent implements OnInit, OnDestroy { ngOnInit() { this.updateValue(); - this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => { if (this.row) { const { entry } = this.row['node']; diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 8feab73333..7a660d51fe 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -148,6 +148,7 @@ <div *ngSwitchCase="'text'" class="adf-cell-value" [attr.data-automation-id]="'text_' + data.getValue(row, col)"> <adf-datatable-cell + [copyContent]="col.copyContent" [data]="data" [column]="col" [row]="row" diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index 9c075093b8..82899d0c33 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -216,6 +216,7 @@ &--text { text-align: left; + position: relative; } &--date { diff --git a/lib/core/datatable/data/data-column.model.ts b/lib/core/datatable/data/data-column.model.ts index 909143bbd1..ec5ef33da1 100644 --- a/lib/core/datatable/data/data-column.model.ts +++ b/lib/core/datatable/data/data-column.model.ts @@ -27,4 +27,5 @@ export interface DataColumn { cssClass?: string; template?: TemplateRef<any>; formatTooltip?: Function; + copyContent?: boolean; } diff --git a/lib/core/datatable/data/object-datacolumn.model.ts b/lib/core/datatable/data/object-datacolumn.model.ts index 0227b4abc5..1ac706e1d6 100644 --- a/lib/core/datatable/data/object-datacolumn.model.ts +++ b/lib/core/datatable/data/object-datacolumn.model.ts @@ -29,6 +29,7 @@ export class ObjectDataColumn implements DataColumn { srTitle: string; cssClass: string; template?: TemplateRef<any>; + copyContent?: boolean; constructor(input: any) { this.key = input.key; @@ -39,5 +40,6 @@ export class ObjectDataColumn implements DataColumn { this.srTitle = input.srTitle; this.cssClass = input.cssClass; this.template = input.template; + this.copyContent = input.copyContent; } } diff --git a/lib/core/datatable/datatable.module.ts b/lib/core/datatable/datatable.module.ts index 06caf66a76..3b1c21abd2 100644 --- a/lib/core/datatable/datatable.module.ts +++ b/lib/core/datatable/datatable.module.ts @@ -41,6 +41,7 @@ import { CustomEmptyContentTemplateDirective } from './directives/custom-empty-c import { CustomLoadingContentTemplateDirective } from './directives/custom-loading-template.directive'; import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive'; import { JsonCellComponent } from './components/datatable/json-cell.component'; +import { ClipboardModule } from '../clipboard/clipboard.module'; @NgModule({ imports: [ @@ -50,7 +51,8 @@ import { JsonCellComponent } from './components/datatable/json-cell.component'; TranslateModule.forChild(), ContextMenuModule, PipeModule, - DirectiveModule + DirectiveModule, + ClipboardModule ], declarations: [ DataTableComponent, @@ -88,5 +90,6 @@ import { JsonCellComponent } from './components/datatable/json-cell.component'; CustomLoadingContentTemplateDirective, CustomNoPermissionTemplateDirective ] + }) export class DataTableModule {} diff --git a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts b/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts index f0710d764c..73198619c4 100644 --- a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts +++ b/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts @@ -36,10 +36,6 @@ describe('ClaimTaskDirective', () => { @ViewChild(ClaimTaskDirective) claimTaskDirective: ClaimTaskDirective; - - onCompleteTask(event: any) { - return event; - } } let fixture: ComponentFixture<TestComponent>; diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts index b9b7b42e30..2fc3d318b6 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts @@ -55,6 +55,20 @@ class CustomTaskListComponent { }) class EmptyTemplateComponent { } +@Component({ + template: ` + <adf-cloud-task-list #taskListCloudCopy> + <data-columns> + <data-column [copyContent]="true" key="entry.id" title="ADF_CLOUD_TASK_LIST.PROPERTIES.ID"></data-column> + <data-column key="entry.name" title="ADF_CLOUD_TASK_LIST.PROPERTIES.NAME"></data-column> + </data-columns> + </adf-cloud-task-list>` +}) +class CustomCopyContentTaskListComponent { + @ViewChild(TaskListCloudComponent) + taskList: TaskListCloudComponent; +} + describe('TaskListCloudComponent', () => { let component: TaskListCloudComponent; let fixture: ComponentFixture<TaskListCloudComponent>; @@ -228,21 +242,29 @@ describe('TaskListCloudComponent', () => { describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => { let fixtureCustom: ComponentFixture<CustomTaskListComponent>; let componentCustom: CustomTaskListComponent; + let customCopyComponent: CustomCopyContentTaskListComponent; + let element: any; + let copyFixture: ComponentFixture<CustomCopyContentTaskListComponent>; setupTestBed({ imports: [CoreModule.forRoot()], - declarations: [TaskListCloudComponent, CustomTaskListComponent], + declarations: [TaskListCloudComponent, CustomTaskListComponent, CustomCopyContentTaskListComponent], providers: [TaskListCloudService] }); beforeEach(() => { + spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask)); fixtureCustom = TestBed.createComponent(CustomTaskListComponent); + copyFixture = TestBed.createComponent(CustomCopyContentTaskListComponent); fixtureCustom.detectChanges(); componentCustom = fixtureCustom.componentInstance; + customCopyComponent = copyFixture.componentInstance; + element = copyFixture.debugElement.nativeElement; }); afterEach(() => { fixtureCustom.destroy(); + copyFixture.destroy(); }); it('should create instance of CustomTaskListComponent', () => { @@ -257,6 +279,37 @@ describe('TaskListCloudComponent', () => { expect(componentCustom.taskList.columns.length).toEqual(3); }); + it('it should show copy tooltip when key is present in data-colunn', async(() => { + copyFixture.detectChanges(); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + copyFixture.whenStable().then(() => { + copyFixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + copyFixture.detectChanges(); + expect(copyFixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + }); + customCopyComponent.taskList.appName = appName.currentValue; + customCopyComponent.taskList.ngOnChanges({ 'appName': appName }); + copyFixture.detectChanges(); + })); + + it('it should not show copy tooltip when key is not present in data-colunn', async(() => { + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + customCopyComponent.taskList.success.subscribe( () => { + copyFixture.whenStable().then(() => { + copyFixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="standalone-subtask"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + copyFixture.detectChanges(); + expect(copyFixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + }); + }); + customCopyComponent.taskList.appName = appName.currentValue; + customCopyComponent.taskList.ngOnChanges({ 'appName': appName }); + copyFixture.detectChanges(); + })); + }); describe('Creating an empty custom template - EmptyTemplateComponent', () => { @@ -285,4 +338,88 @@ describe('TaskListCloudComponent', () => { }); })); }); + + describe('Copy cell content directive from app.config specifications', () => { + + let element: any; + let taskSpy: jasmine.Spy; + + setupTestBed({ + imports: [ProcessServiceCloudTestingModule, TaskListCloudModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + beforeEach( () => { + appConfig = TestBed.get(AppConfigService); + taskListCloudService = TestBed.get(TaskListCloudService); + appConfig.config = Object.assign(appConfig.config, { + 'adf-cloud-task-list': { + 'presets': { + 'fakeCustomSchema': [ + { + 'key': 'entry.id', + 'type': 'text', + 'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.FAKE', + 'sortable': true, + 'copyContent': true + }, + { + 'key': 'entry.name', + 'type': 'text', + 'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.TASK_FAKE', + 'sortable': true + } + ] + } + } + }); + fixture = TestBed.createComponent(TaskListCloudComponent); + component = fixture.componentInstance; + element = fixture.debugElement.nativeElement; + taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask)); + + }); + afterEach(() => { + fixture.destroy(); + }); + + it('shoud show tooltip if config copyContent flag is true', async(() => { + taskSpy.and.returnValue(of(fakeGlobalTask)); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + + component.success.subscribe( () => { + fixture.whenStable().then(() => { + fixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + }); + }); + + component.presetColumn = 'fakeCustomSchema'; + component.appName = appName.currentValue; + component.ngOnChanges({ 'appName': appName }); + component.ngAfterContentInit(); + })); + + it('shoud not show tooltip if config copyContent flag is true', async(() => { + taskSpy.and.returnValue(of(fakeGlobalTask)); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + component.success.subscribe( () => { + fixture.whenStable().then(() => { + fixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="standalone-subtask"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + }); + }); + component.presetColumn = 'fakeCustomSchema'; + component.appName = appName.currentValue; + component.ngOnChanges({ 'appName': appName }); + component.ngAfterContentInit(); + })); + }); + }); From b538dbaa60a35117b47fbb100b19cb3cd6828774 Mon Sep 17 00:00:00 2001 From: Roxana Gherghelas <Roxana.Gherghelas@ness.com> Date: Mon, 8 Apr 2019 17:35:54 +0300 Subject: [PATCH 072/208] add start-process-cloud-component.page.ts page in @adf-testing --- .../start-process-cloud.e2e.ts | 17 ++- .../pages/public-api.ts | 1 + .../start-process-cloud-component.page.ts | 120 ++++++++++++++++++ 3 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index adf9112e75..eea0d63658 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -16,11 +16,10 @@ */ import { LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; -import { AppListCloudPage } from '@alfresco/adf-testing'; +import { AppListCloudPage, StartProcessCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; -import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; @@ -31,7 +30,7 @@ describe('Start Process', () => { const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const processCloudDemoPage = new ProcessCloudDemoPage(); - const startProcessPage = new StartProcessPage(); + const startProcessPage = new StartProcessCloudPage(); const processName = StringUtil.generateRandomString(10); const processName255Characters = StringUtil.generateRandomString(255); const processNameBiggerThen255Characters = StringUtil.generateRandomString(256); @@ -81,12 +80,12 @@ describe('Start Process', () => { startProcessPage.checkStartProcessButtonIsDisabled(); }); - it('[C291855] Should NOT be able to start a process without process model', () => { - appListCloudComponent.checkAppIsDisplayed(noProcessApp); - appListCloudComponent.goToApp(noProcessApp); - processCloudDemoPage.openNewProcessForm(); - startProcessPage.checkNoProcessMessage(); - }); + // it('[C291855] Should NOT be able to start a process without process model', () => { + // appListCloudComponent.checkAppIsDisplayed(noProcessApp); + // appListCloudComponent.goToApp(noProcessApp); + // processCloudDemoPage.openNewProcessForm(); + // startProcessPage.checkNoProcessMessage(); + // }); it('[C291860] Should be able to start a process', () => { appListCloudComponent.checkAppIsDisplayed(appName); diff --git a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts index fc6d7d8bc3..9fd6becfc7 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts @@ -26,5 +26,6 @@ export * from './process-filters-cloud-component.page'; export * from './process-list-cloud-component.page'; export * from './task-filters-cloud-component.page'; export * from './task-list-cloud-component.page'; +export * from './start-process-cloud-component.page'; export * from './dialog/public-api'; diff --git a/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts new file mode 100644 index 0000000000..a3ab574fa3 --- /dev/null +++ b/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts @@ -0,0 +1,120 @@ +/*! + * @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 { by, element, Key, protractor, browser } from 'protractor'; +import { BrowserVisibility } from '../../core/browser-visibility'; + +export class StartProcessCloudPage { + + defaultProcessName = element(by.css('input[id="processName"]')); + processNameInput = element(by.id('processName')); + selectProcessDropdownArrow = element(by.css('button[id="adf-select-process-dropdown"]')); + cancelProcessButton = element(by.id('cancel_process')); + formStartProcessButton = element(by.css('button[data-automation-id="adf-form-start process"]')); + startProcessButton = element(by.css('button[data-automation-id="btn-start"]')); + noProcess = element(by.id('no-process-message')); + processDefinition = element(by.css('input[id="processDefinitionName"]')); + processDefinitionOptionsPanel = element(by.css('div[class*="processDefinitionOptions"]')); + + checkNoProcessMessage() { + BrowserVisibility.waitUntilElementIsVisible(this.noProcess); + } + + pressDownArrowAndEnter() { + this.processDefinition.sendKeys(protractor.Key.ARROW_DOWN); + return browser.actions().sendKeys(protractor.Key.ENTER).perform(); + } + + checkNoProcessDefinitionOptionIsDisplayed() { + BrowserVisibility.waitUntilElementIsNotOnPage(this.processDefinitionOptionsPanel); + } + + enterProcessName(name) { + BrowserVisibility.waitUntilElementIsVisible(this.processNameInput); + this.clearProcessName(); + this.processNameInput.sendKeys(name); + } + + clearProcessName() { + BrowserVisibility.waitUntilElementIsVisible(this.processNameInput); + this.processNameInput.clear(); + } + + selectFromProcessDropdown(name) { + this.clickProcessDropdownArrow(); + return this.selectOption(name); + } + + clickProcessDropdownArrow() { + BrowserVisibility.waitUntilElementIsVisible(this.selectProcessDropdownArrow); + BrowserVisibility.waitUntilElementIsClickable(this.selectProcessDropdownArrow); + this.selectProcessDropdownArrow.click(); + } + + checkOptionIsDisplayed(name) { + const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); + BrowserVisibility.waitUntilElementIsVisible(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsClickable(selectProcessDropdown); + return this; + } + + selectOption(name) { + const selectProcessDropdown = element(by.cssContainingText('.mat-option-text', name)); + BrowserVisibility.waitUntilElementIsVisible(selectProcessDropdown); + BrowserVisibility.waitUntilElementIsClickable(selectProcessDropdown); + selectProcessDropdown.click(); + return this; + } + + clickCancelProcessButton() { + BrowserVisibility.waitUntilElementIsVisible(this.cancelProcessButton); + this.cancelProcessButton.click(); + } + + checkStartProcessButtonIsEnabled() { + expect(this.startProcessButton.isEnabled()).toBe(true); + } + + checkStartProcessButtonIsDisabled() { + expect(this.startProcessButton.isEnabled()).toBe(false); + } + + clickStartProcessButton() { + return this.startProcessButton.click(); + } + + checkValidationErrorIsDisplayed(error, elementRef = 'mat-error') { + const errorElement = element(by.cssContainingText(elementRef, error)); + BrowserVisibility.waitUntilElementIsVisible(errorElement); + return this; + } + + blur(locator) { + locator.click(); + locator.sendKeys(Key.TAB); + return this; + } + + clearField(locator) { + BrowserVisibility.waitUntilElementIsVisible(locator); + locator.getAttribute('value').then((result) => { + for (let i = result.length; i >= 0; i--) { + locator.sendKeys(protractor.Key.BACK_SPACE); + } + }); + } +} From d7de8d0065a0630aeb7817df1c2f959a9f7041d0 Mon Sep 17 00:00:00 2001 From: Roxana Gherghelas <Roxana.Gherghelas@ness.com> Date: Mon, 8 Apr 2019 17:53:11 +0300 Subject: [PATCH 073/208] remove invalid test --- e2e/process-services-cloud/start-process-cloud.e2e.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index eea0d63658..49a84a9f94 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -80,13 +80,6 @@ describe('Start Process', () => { startProcessPage.checkStartProcessButtonIsDisabled(); }); - // it('[C291855] Should NOT be able to start a process without process model', () => { - // appListCloudComponent.checkAppIsDisplayed(noProcessApp); - // appListCloudComponent.goToApp(noProcessApp); - // processCloudDemoPage.openNewProcessForm(); - // startProcessPage.checkNoProcessMessage(); - // }); - it('[C291860] Should be able to start a process', () => { appListCloudComponent.checkAppIsDisplayed(appName); appListCloudComponent.goToApp(appName); From 1b774c4218b1b336f264e1b5ed9200d753e584d2 Mon Sep 17 00:00:00 2001 From: Roxana Gherghelas <Roxana.Gherghelas@ness.com> Date: Tue, 9 Apr 2019 08:55:02 +0300 Subject: [PATCH 074/208] remove noprocessapp constant --- e2e/process-services-cloud/start-process-cloud.e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index 49a84a9f94..b4f164f925 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -38,7 +38,7 @@ describe('Start Process', () => { const requiredError = 'Process Name is required', requiredProcessError = 'Process Definition is required'; const processDefinition = 'processwithvariables'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - const appName = 'simple-app', noProcessApp = 'noprocessapp'; + const appName = 'simple-app'; let silentLogin; beforeAll((done) => { From deff3965b02ee657934ad9e4c8783f80a5bcba4b Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 9 Apr 2019 12:17:51 +0100 Subject: [PATCH 075/208] [ADF-4361] Fix Tab navigation on Login page (#4574) --- lib/core/login/components/login.component.html | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/core/login/components/login.component.html b/lib/core/login/components/login.component.html index 1434e7ffc8..ec1e968403 100644 --- a/lib/core/login/components/login.component.html +++ b/lib/core/login/components/login.component.html @@ -4,7 +4,6 @@ <mat-card class="adf-login-card-wide"> <form id="adf-login-form" [formGroup]="form" (submit)="onSubmit(form.value)" autocomplete="off"> - <mat-card-header> <mat-card-title> <div class="adf-alfresco-logo"> @@ -43,8 +42,7 @@ autocapitalize="none" id="username" data-automation-id="username" - (blur)="trimUsername($event)" - tabindex="-1"> + (blur)="trimUsername($event)"> </mat-form-field> <span class="adf-login-validation" for="username" *ngIf="formError['username']"> @@ -59,14 +57,13 @@ [type]="isPasswordShow ? 'text' : 'password'" [formControl]="form.controls['password']" id="password" - data-automation-id="password" - tabindex="-2"> + data-automation-id="password"> <mat-icon *ngIf="isPasswordShow" matSuffix class="adf-login-password-icon" - data-automation-id="hide_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="-3"> + data-automation-id="hide_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()"> visibility </mat-icon> <mat-icon *ngIf="!isPasswordShow" matSuffix class="adf-login-password-icon" - data-automation-id="show_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="-3"> + data-automation-id="show_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()"> visibility_off </mat-icon> </mat-form-field> @@ -80,7 +77,7 @@ <ng-content></ng-content> <br> - <button type="submit" id="login-button" tabindex="-4" + <button type="submit" id="login-button" class="adf-login-button" mat-raised-button color="primary" [class.adf-isChecking]="actualLoginStep === LoginSteps.Checking" @@ -115,7 +112,7 @@ </div> <div *ngIf="implicitFlow"> - <button type="button" (click)="implicitLogin()" id="login-button-sso" tabindex="-1" + <button type="button" (click)="implicitLogin()" id="login-button-sso" class="adf-login-button" mat-raised-button color="primary" data-automation-id="login-button-sso"> From 62c71dbec93391d504e65681844391188cec7057 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 9 Apr 2019 12:18:36 +0100 Subject: [PATCH 076/208] [ADF-4372] Fix json type Data Column styles (#4576) --- .../datatable/components/datatable/json-cell.component.scss | 4 ++++ .../datatable/components/datatable/json-cell.component.ts | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 lib/core/datatable/components/datatable/json-cell.component.scss diff --git a/lib/core/datatable/components/datatable/json-cell.component.scss b/lib/core/datatable/components/datatable/json-cell.component.scss new file mode 100644 index 0000000000..69b91154fe --- /dev/null +++ b/lib/core/datatable/components/datatable/json-cell.component.scss @@ -0,0 +1,4 @@ +.adf-datatable-json-cell { + white-space: pre-wrap; + word-wrap: break-word; +} diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts index cb3f31b2de..b0c2cacce2 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.ts +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -24,10 +24,11 @@ import { DataTableCellComponent } from './datatable-cell.component'; template: ` <ng-container> <span class="adf-datatable-cell-value"> - <pre>{{ value$ | async | json }}</pre> + <pre class="adf-datatable-json-cell">{{ value$ | async | json }}</pre> </span> </ng-container> `, + styleUrls: ['./json-cell.component.scss'], encapsulation: ViewEncapsulation.None, host: { class: 'adf-datatable-cell' } }) From ce0775c525113c56f312a9f5d9dcfb9194281905 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Tue, 9 Apr 2019 12:26:10 +0100 Subject: [PATCH 077/208] [ADF-4191] fix viewer test and move error and pagination page (#4569) * split viewer test * move pagination in testing share pkg move error in testing share pkg * fix import --- .../document-list-component.e2e.ts | 4 +- .../document-list-pagination.e2e.ts | 2 +- .../share-file/unshare-file.e2e.ts | 3 +- .../trashcan-pagination.e2e.ts | 2 +- e2e/core/error-component.e2e.ts | 3 +- e2e/core/login/login-component.e2e.ts | 3 +- e2e/core/pagination-empty-current-page.e2e.ts | 2 +- e2e/core/viewer/viewer-component.e2e.ts | 110 +------------- e2e/core/viewer/viewer-extension.e2e.ts | 105 ++++++++++++++ e2e/core/viewer/viewer-share-content.ts | 136 ++++++++++++++++++ .../{aboutPage.ts => monacoExtensionPage.ts} | 2 +- .../process-services/taskListDemoPage.ts | 2 +- e2e/pages/adf/viewerPage.ts | 2 - .../custom-tasks-filters.e2e.ts | 2 +- ...ination-processlist-addingProcesses.e2e.ts | 2 +- .../pagination-tasklist-addingTasks.e2e.ts | 2 +- .../processlist-pagination.e2e.ts | 2 +- .../sort-tasklist-pagination.e2e.ts | 2 +- .../task-list-pagination.e2e.ts | 2 +- .../documents/ppt/a_ppsm_file.ppsm | Bin 305231 -> 0 bytes e2e/search/search-filters.e2e.ts | 2 +- .../testing/src/lib/core/pages/error.page.ts | 2 +- .../src/lib/core/pages/pagination.page.ts | 2 +- lib/testing/src/lib/core/pages/public-api.ts | 3 + scripts/clean-env.js | 9 +- 25 files changed, 269 insertions(+), 137 deletions(-) create mode 100644 e2e/core/viewer/viewer-extension.e2e.ts create mode 100644 e2e/core/viewer/viewer-share-content.ts rename e2e/pages/adf/demo-shell/{aboutPage.ts => monacoExtensionPage.ts} (96%) delete mode 100644 e2e/resources/adf/allFileTypes/documents/ppt/a_ppsm_file.ppsm rename e2e/pages/adf/errorPage.ts => lib/testing/src/lib/core/pages/error.page.ts (96%) rename e2e/pages/adf/paginationPage.ts => lib/testing/src/lib/core/pages/pagination.page.ts (98%) diff --git a/e2e/content-services/document-list/document-list-component.e2e.ts b/e2e/content-services/document-list/document-list-component.e2e.ts index a6d8852288..b326b5ef26 100644 --- a/e2e/content-services/document-list/document-list-component.e2e.ts +++ b/e2e/content-services/document-list/document-list-component.e2e.ts @@ -16,17 +16,15 @@ */ import { browser } from 'protractor'; -import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { ViewerPage } from '../../pages/adf/viewerPage'; import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); -import { StringUtil } from '@alfresco/adf-testing'; +import { LoginPage, ErrorPage, StringUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; -import { ErrorPage } from '../../pages/adf/errorPage'; import { FileModel } from '../../models/ACS/fileModel'; import moment from 'moment-es6'; diff --git a/e2e/content-services/document-list/document-list-pagination.e2e.ts b/e2e/content-services/document-list/document-list-pagination.e2e.ts index 8e730e0ec7..078982330e 100644 --- a/e2e/content-services/document-list/document-list-pagination.e2e.ts +++ b/e2e/content-services/document-list/document-list-pagination.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; -import { PaginationPage } from '../../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; diff --git a/e2e/content-services/share-file/unshare-file.e2e.ts b/e2e/content-services/share-file/unshare-file.e2e.ts index c0332e0a23..03bbf1c066 100644 --- a/e2e/content-services/share-file/unshare-file.e2e.ts +++ b/e2e/content-services/share-file/unshare-file.e2e.ts @@ -18,9 +18,8 @@ import CONSTANTS = require('../../util/constants'); import { StringUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, ErrorPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; -import { ErrorPage } from '../../pages/adf/errorPage'; import { ShareDialog } from '../../pages/adf/dialog/shareDialog'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { FileModel } from '../../models/ACS/fileModel'; diff --git a/e2e/content-services/trashcan-pagination.e2e.ts b/e2e/content-services/trashcan-pagination.e2e.ts index 6fcc1256fa..6757322023 100644 --- a/e2e/content-services/trashcan-pagination.e2e.ts +++ b/e2e/content-services/trashcan-pagination.e2e.ts @@ -18,7 +18,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { TrashcanPage } from '../pages/adf/trashcanPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { AcsUserModel } from '../models/ACS/acsUserModel'; diff --git a/e2e/core/error-component.e2e.ts b/e2e/core/error-component.e2e.ts index 6aa47298d6..7dc52fb019 100644 --- a/e2e/core/error-component.e2e.ts +++ b/e2e/core/error-component.e2e.ts @@ -15,11 +15,10 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, ErrorPage } from '@alfresco/adf-testing'; import { AcsUserModel } from '../models/ACS/acsUserModel'; import TestConfig = require('../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { ErrorPage } from '../pages/adf/errorPage'; import { browser } from 'protractor'; describe('Error Component', () => { diff --git a/e2e/core/login/login-component.e2e.ts b/e2e/core/login/login-component.e2e.ts index 99314fa33e..779db702d4 100644 --- a/e2e/core/login/login-component.e2e.ts +++ b/e2e/core/login/login-component.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage, SettingsPage } from '@alfresco/adf-testing'; +import { LoginPage, SettingsPage, ErrorPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ProcessServicesPage } from '../../pages/adf/process-services/processServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; @@ -30,7 +30,6 @@ import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { Util } from '../../util/util'; -import { ErrorPage } from '../../pages/adf/errorPage'; describe('Login component', () => { diff --git a/e2e/core/pagination-empty-current-page.e2e.ts b/e2e/core/pagination-empty-current-page.e2e.ts index 6c7081dfb5..5ed68ed7a2 100644 --- a/e2e/core/pagination-empty-current-page.e2e.ts +++ b/e2e/core/pagination-empty-current-page.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../pages/adf/viewerPage'; import { AcsUserModel } from '../models/ACS/acsUserModel'; diff --git a/e2e/core/viewer/viewer-component.e2e.ts b/e2e/core/viewer/viewer-component.e2e.ts index 8bcc16c698..5aaf79da2a 100644 --- a/e2e/core/viewer/viewer-component.e2e.ts +++ b/e2e/core/viewer/viewer-component.e2e.ts @@ -21,8 +21,6 @@ import { LoginPage } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; -import { ShareDialog } from '../../pages/adf/dialog/shareDialog'; -import { AboutPage } from '../../pages/adf/demo-shell/aboutPage'; import CONSTANTS = require('../../util/constants'); import resources = require('../../util/resources'); @@ -34,9 +32,8 @@ import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; -import { browser } from 'protractor'; -xdescribe('Viewer', () => { +describe('Viewer', () => { const viewerPage = new ViewerPage(); const navigationBarPage = new NavigationBarPage(); @@ -46,9 +43,6 @@ xdescribe('Viewer', () => { let site; const acsUser = new AcsUserModel(); let pngFileUploaded; - const contentList = contentServicesPage.getDocumentList(); - const shareDialog = new ShareDialog(); - const about = new AboutPage(); const pngFileInfo = new FileModel({ 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, @@ -392,106 +386,4 @@ xdescribe('Viewer', () => { }); - describe('Display files via API', () => { - - const wordFileInfo = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_name, - 'location': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_location - }); - - let pngFileShared, wordFileUploaded; - - beforeAll(async (done) => { - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - - wordFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, wordFileInfo.location, wordFileInfo.name, '-my-'); - - pngFileShared = await this.alfrescoJsApi.core.sharedlinksApi.addSharedLink({ 'nodeId': pngFileUploaded.entry.id }); - - done(); - }); - - afterAll(async (done) => { - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, wordFileUploaded.entry.id); - done(); - }); - - beforeEach(() => { - loginPage.loginToContentServicesUsingUserModel(acsUser); - }); - - it('[C260105] Should be able to open an image file shared via API', () => { - browser.get(TestConfig.adf.url + '/preview/s/' + pngFileShared.entry.id); - viewerPage.checkImgContainerIsDisplayed(); - browser.get(TestConfig.adf.url); - navigationBarPage.clickLogoutButton(); - browser.get(TestConfig.adf.url + '/preview/s/' + pngFileShared.entry.id); - viewerPage.checkImgContainerIsDisplayed(); - }); - - it('[C260106] Should be able to open a Word file shared via API', () => { - navigationBarPage.clickContentServicesButton(); - contentServicesPage.waitForTableBody(); - - contentList.selectRow(wordFileInfo.name); - contentServicesPage.clickShareButton(); - shareDialog.checkDialogIsDisplayed(); - shareDialog.clickShareLinkButton(); - browser.controlFlow().execute(async () => { - const sharedLink = await shareDialog.getShareLink(); - - await browser.get(sharedLink); - viewerPage.checkFileIsLoaded(); - viewerPage.checkFileNameIsDisplayed(wordFileInfo.name); - - await browser.get(TestConfig.adf.url); - navigationBarPage.clickLogoutButton(); - await browser.get(sharedLink); - viewerPage.checkFileIsLoaded(); - viewerPage.checkFileNameIsDisplayed(wordFileInfo.name); - }); - }); - }); - - describe('Viewer - Code editor extension', () => { - - const jsFileInfo = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.JS.file_name, - 'location': resources.Files.ADF_DOCUMENTS.JS.file_location - }); - - let jsFileUploaded; - - beforeAll(async (done) => { - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - - jsFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, jsFileInfo.location, jsFileInfo.name, '-my-'); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - - done(); - }); - - afterAll(async (done) => { - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, jsFileUploaded.entry.id); - done(); - }); - - it('[C297698] Should be able to add an extension for code editor viewer', () => { - navigationBarPage.checkAboutButtonIsDisplayed(); - navigationBarPage.clickAboutButton(); - - about.checkMonacoPluginIsDisplayed(); - - navigationBarPage.clickContentServicesButton(); - - contentServicesPage.waitForTableBody(); - contentServicesPage.checkContentIsDisplayed(jsFileInfo.name); - contentServicesPage.doubleClickRow(jsFileInfo.name); - - viewerPage.checkCodeViewerIsDisplayed(); - }); - }); }); diff --git a/e2e/core/viewer/viewer-extension.e2e.ts b/e2e/core/viewer/viewer-extension.e2e.ts new file mode 100644 index 0000000000..bd194b723d --- /dev/null +++ b/e2e/core/viewer/viewer-extension.e2e.ts @@ -0,0 +1,105 @@ +/*! + * @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 TestConfig = require('../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../pages/adf/viewerPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import { MonacoExtensionPage } from '../../pages/adf/demo-shell/monacoExtensionPage'; + +import CONSTANTS = require('../../util/constants'); +import resources = require('../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FileModel } from '../../models/ACS/fileModel'; +import { AcsUserModel } from '../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + const monacoExtensionPage = new MonacoExtensionPage(); + + let jsFileUploaded; + const jsFileInfo = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.JS.file_name, + 'location': resources.Files.ADF_DOCUMENTS.JS.file_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + jsFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, jsFileInfo.location, jsFileInfo.name, '-my-'); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + + done(); + }); + + afterAll(async (done) => { + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, jsFileUploaded.entry.id); + done(); + }); + + describe('Viewer extension', () => { + + it('[C297698] Should be able to add an extension for code editor viewer', () => { + navigationBarPage.checkAboutButtonIsDisplayed(); + navigationBarPage.clickAboutButton(); + + monacoExtensionPage.checkMonacoPluginIsDisplayed(); + + navigationBarPage.clickContentServicesButton(); + + contentServicesPage.waitForTableBody(); + contentServicesPage.checkContentIsDisplayed(jsFileInfo.name); + contentServicesPage.doubleClickRow(jsFileInfo.name); + + viewerPage.checkCodeViewerIsDisplayed(); + }); + }); +}); diff --git a/e2e/core/viewer/viewer-share-content.ts b/e2e/core/viewer/viewer-share-content.ts new file mode 100644 index 0000000000..734365305d --- /dev/null +++ b/e2e/core/viewer/viewer-share-content.ts @@ -0,0 +1,136 @@ +/*! + * @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 TestConfig = require('../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../pages/adf/viewerPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import { ShareDialog } from '../../pages/adf/dialog/shareDialog'; + +import CONSTANTS = require('../../util/constants'); +import resources = require('../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FileModel } from '../../models/ACS/fileModel'; +import { AcsUserModel } from '../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../actions/ACS/upload.actions'; +import { browser } from 'protractor'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + let pngFileUploaded; + const contentList = contentServicesPage.getDocumentList(); + const shareDialog = new ShareDialog(); + + const pngFileInfo = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + const wordFileInfo = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_name, + 'location': resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_location + }); + + let pngFileShared, wordFileUploaded; + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + pngFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileInfo.location, pngFileInfo.name, site.entry.guid); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + wordFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, wordFileInfo.location, wordFileInfo.name, '-my-'); + + pngFileShared = await this.alfrescoJsApi.core.sharedlinksApi.addSharedLink({ 'nodeId': pngFileUploaded.entry.id }); + + done(); + }); + + afterAll(async (done) => { + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, wordFileUploaded.entry.id); + done(); + }); + + beforeEach(() => { + loginPage.loginToContentServicesUsingUserModel(acsUser); + }); + + it('[C260105] Should be able to open an image file shared via API', () => { + browser.get(TestConfig.adf.url + '/preview/s/' + pngFileShared.entry.id); + viewerPage.checkImgContainerIsDisplayed(); + browser.get(TestConfig.adf.url); + navigationBarPage.clickLogoutButton(); + browser.get(TestConfig.adf.url + '/preview/s/' + pngFileShared.entry.id); + viewerPage.checkImgContainerIsDisplayed(); + }); + + it('[C260106] Should be able to open a Word file shared via API', () => { + navigationBarPage.clickContentServicesButton(); + contentServicesPage.waitForTableBody(); + + contentList.selectRow(wordFileInfo.name); + contentServicesPage.clickShareButton(); + shareDialog.checkDialogIsDisplayed(); + shareDialog.clickShareLinkButton(); + browser.controlFlow().execute(async () => { + const sharedLink = await shareDialog.getShareLink(); + + await browser.get(sharedLink); + viewerPage.checkFileIsLoaded(); + viewerPage.checkFileNameIsDisplayed(wordFileInfo.name); + + await browser.get(TestConfig.adf.url); + navigationBarPage.clickLogoutButton(); + await browser.get(sharedLink); + viewerPage.checkFileIsLoaded(); + viewerPage.checkFileNameIsDisplayed(wordFileInfo.name); + }); + }); +}); diff --git a/e2e/pages/adf/demo-shell/aboutPage.ts b/e2e/pages/adf/demo-shell/monacoExtensionPage.ts similarity index 96% rename from e2e/pages/adf/demo-shell/aboutPage.ts rename to e2e/pages/adf/demo-shell/monacoExtensionPage.ts index 8e025dc9e7..7c4270bc1e 100644 --- a/e2e/pages/adf/demo-shell/aboutPage.ts +++ b/e2e/pages/adf/demo-shell/monacoExtensionPage.ts @@ -18,7 +18,7 @@ import { by, element } from 'protractor'; import { BrowserVisibility } from '@alfresco/adf-testing'; -export class AboutPage { +export class MonacoExtensionPage { monacoPlugin = element(by.cssContainingText('mat-row > mat-cell', 'monaco plugin')); diff --git a/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts index 095b122b82..5e9d216baf 100644 --- a/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/taskListDemoPage.ts @@ -16,7 +16,7 @@ */ import { TasksListPage } from '../../process-services/tasksListPage'; -import { PaginationPage } from '../../paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; import { BrowserVisibility } from '@alfresco/adf-testing'; diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index 918d0cb756..38b37971fc 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -62,9 +62,7 @@ export class ViewerPage { toolbarSwitch = element(by.id('adf-switch-toolbar')); toolbar = element(by.id('adf-viewer-toolbar')); lastButton = element.all(by.css('#adf-viewer-toolbar mat-toolbar > button[data-automation-id*="adf-toolbar-"]')).last(); - datatableHeader = element(by.css('div.adf-datatable-header')); goBackSwitch = element(by.id('adf-switch-goback')); - tabLabel = element(by.css('div[class="mat-tab-label-content"]')); openWithSwitch = element(by.id('adf-switch-openwith')); openWith = element(by.id('adf-viewer-openwith')); diff --git a/e2e/process-services/custom-tasks-filters.e2e.ts b/e2e/process-services/custom-tasks-filters.e2e.ts index 67ecdcda38..80afd82f7f 100644 --- a/e2e/process-services/custom-tasks-filters.e2e.ts +++ b/e2e/process-services/custom-tasks-filters.e2e.ts @@ -18,7 +18,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TaskListDemoPage } from '../pages/adf/demo-shell/process-services/taskListDemoPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import moment = require('moment'); import { Tenant } from '../models/APS/tenant'; diff --git a/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts b/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts index fba08e2837..dac9b6a373 100644 --- a/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts +++ b/e2e/process-services/pagination-processlist-addingProcesses.e2e.ts @@ -16,7 +16,7 @@ */ import { LoginPage } from '@alfresco/adf-testing'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; diff --git a/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts b/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts index 79bffd22d6..b7135df369 100644 --- a/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts +++ b/e2e/process-services/pagination-tasklist-addingTasks.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import CONSTANTS = require('../util/constants'); diff --git a/e2e/process-services/processlist-pagination.e2e.ts b/e2e/process-services/processlist-pagination.e2e.ts index a1042e3621..a34a5ac759 100644 --- a/e2e/process-services/processlist-pagination.e2e.ts +++ b/e2e/process-services/processlist-pagination.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; diff --git a/e2e/process-services/sort-tasklist-pagination.e2e.ts b/e2e/process-services/sort-tasklist-pagination.e2e.ts index 113034500c..f43b1fbea5 100644 --- a/e2e/process-services/sort-tasklist-pagination.e2e.ts +++ b/e2e/process-services/sort-tasklist-pagination.e2e.ts @@ -18,7 +18,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); diff --git a/e2e/process-services/task-list-pagination.e2e.ts b/e2e/process-services/task-list-pagination.e2e.ts index 5d35e95fb5..977786ac9f 100644 --- a/e2e/process-services/task-list-pagination.e2e.ts +++ b/e2e/process-services/task-list-pagination.e2e.ts @@ -18,7 +18,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); diff --git a/e2e/resources/adf/allFileTypes/documents/ppt/a_ppsm_file.ppsm b/e2e/resources/adf/allFileTypes/documents/ppt/a_ppsm_file.ppsm deleted file mode 100644 index 2481d340f47747c99674a84b825a60891b52f7ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305231 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⪙l_WKD0*OgWKbP<k%Ye~>3d?G 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%0AJ$I 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�DJ)Y*$*9#4)*uTingP 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 diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index 708e881d40..f703fe10b9 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -18,7 +18,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { SearchFiltersPage } from '../pages/adf/searchFiltersPage'; -import { PaginationPage } from '../pages/adf/paginationPage'; +import { PaginationPage } from '@alfresco/adf-testing'; import { DocumentListPage } from '../pages/adf/content-services/documentListPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; diff --git a/e2e/pages/adf/errorPage.ts b/lib/testing/src/lib/core/pages/error.page.ts similarity index 96% rename from e2e/pages/adf/errorPage.ts rename to lib/testing/src/lib/core/pages/error.page.ts index 32ae2005ea..ad07f823bb 100644 --- a/e2e/pages/adf/errorPage.ts +++ b/lib/testing/src/lib/core/pages/error.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../core/browser-visibility'; import { element, by } from 'protractor'; export class ErrorPage { diff --git a/e2e/pages/adf/paginationPage.ts b/lib/testing/src/lib/core/pages/pagination.page.ts similarity index 98% rename from e2e/pages/adf/paginationPage.ts rename to lib/testing/src/lib/core/pages/pagination.page.ts index 3ee35d6c1a..b900d104eb 100644 --- a/e2e/pages/adf/paginationPage.ts +++ b/lib/testing/src/lib/core/pages/pagination.page.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility } from '../../core/browser-visibility'; export class PaginationPage { diff --git a/lib/testing/src/lib/core/pages/public-api.ts b/lib/testing/src/lib/core/pages/public-api.ts index 111bfe31d1..c66c2d6c8a 100644 --- a/lib/testing/src/lib/core/pages/public-api.ts +++ b/lib/testing/src/lib/core/pages/public-api.ts @@ -22,3 +22,6 @@ export * from './settings.page'; export * from './form-controller.page'; export * from './login-sso.page'; export * from './data-table-component.page'; +export * from './pagination.page'; +export * from './error.page'; +export * from './login.page'; diff --git a/scripts/clean-env.js b/scripts/clean-env.js index 5f5e0594f1..56f0f3b5d5 100644 --- a/scripts/clean-env.js +++ b/scripts/clean-env.js @@ -17,13 +17,13 @@ async function main() { await this.alfrescoJsApi.login(program.username, program.password); - // await cleanRoot(this.alfrescoJsApi); + await cleanRoot(this.alfrescoJsApi); await deleteSite(this.alfrescoJsApi); await emptyTrashCan(this.alfrescoJsApi); } async function cleanRoot(alfrescoJsApi) { - console.log('start'); + console.log('====== Clean Root ======'); let rootNodes = await alfrescoJsApi.core.nodesApi.getNodeChildren('-root-'); @@ -45,6 +45,8 @@ async function cleanRoot(alfrescoJsApi) { } async function emptyTrashCan(alfrescoJsApi) { + console.log('====== Clean Trash ======'); + let deletedNodes = await alfrescoJsApi.core.nodesApi.getDeletedNodes(); for (let i = 0; i < deletedNodes.list.entries.length; i++) { @@ -57,7 +59,6 @@ async function emptyTrashCan(alfrescoJsApi) { await alfrescoJsApi.core.nodesApi.purgeDeletedNode(deletedNodes.list.entries[i].entry.id); } catch (error) { console.log('error' + JSON.stringify(error)); - } } @@ -65,6 +66,8 @@ async function emptyTrashCan(alfrescoJsApi) { } async function deleteSite(alfrescoJsApi) { + console.log('====== Clean Sites ======'); + let listSites = await this.alfrescoJsApi.core.sitesApi.getSites(); console.log(listSites.list.pagination.totalItems); From 2753771d29b5352c9cf240fcf915db2b5db16d23 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 9 Apr 2019 16:49:44 +0100 Subject: [PATCH 078/208] [ADF-4273] Remove description property from Process Instance Cloud Model (#4568) * [ADF-4273] Remove description property from Process Instance Cloud Model * [ADF-4273] Remove from e2e tests --- .../process-header-cloud.component.md | 2 +- .../processList-cloud-component.e2e.ts | 1 - .../processListCloud.config.ts | 6 ----- .../process-header-cloud.component.spec.ts | 23 ------------------- .../process-header-cloud.component.ts | 7 ------ .../process-list-cloud.component.spec.ts | 1 - .../mock/process-list-service.mock.ts | 3 --- .../process-cloud-query-request.model.ts | 2 -- .../models/process-instance-cloud.model.ts | 2 -- 9 files changed, 1 insertion(+), 46 deletions(-) diff --git a/docs/process-services-cloud/components/process-header-cloud.component.md b/docs/process-services-cloud/components/process-header-cloud.component.md index 5914593f4c..a32700ddfc 100644 --- a/docs/process-services-cloud/components/process-header-cloud.component.md +++ b/docs/process-services-cloud/components/process-header-cloud.component.md @@ -36,7 +36,7 @@ The component populates an internal array of By default all properties are displayed: -**_id_**, **_name_**, **_description_**, **_status_**, **_initiator_**, **_startDate_**, **_lastModified_**, **_parentId_**, **_businessKey_**. +**_id_**, **_name_**, **_status_**, **_initiator_**, **_startDate_**, **_lastModified_**, **_parentId_**, **_businessKey_**. However, you can also choose which properties to show using a configuration in `app.config.json`: diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index b4763bda94..a9c4e2c2e6 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -87,7 +87,6 @@ describe('Process list cloud', () => { processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('startDate'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('appName'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('businessKey'); - processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('description'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('initiator'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('lastModified'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('processName'); diff --git a/e2e/process-services-cloud/processListCloud.config.ts b/e2e/process-services-cloud/processListCloud.config.ts index dd399d093a..875b3c2e2b 100644 --- a/e2e/process-services-cloud/processListCloud.config.ts +++ b/e2e/process-services-cloud/processListCloud.config.ts @@ -58,12 +58,6 @@ export class ProcessListCloudConfiguration { 'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.BUSINESS_KEY', 'sortable': true }, - { - 'key': 'entry.description', - 'type': 'text', - 'title': 'ADF_CLOUD_PROCESS_LIST.PROPERTIES.DESCRIPTION', - 'sortable': true - }, { 'key': 'entry.initiator', 'type': 'text', diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts index 6be0590d5a..489b644aaf 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.spec.ts @@ -27,7 +27,6 @@ import { ProcessHeaderCloudService } from '../services/process-header-cloud.serv const processInstanceDetailsCloudMock = { appName: 'app-form-mau', businessKey: 'MyBusinessKey', - description: 'new desc', id: '00fcc4ab-4290-11e9-b133-0a586460016a', initiator: 'devopsuser', lastModified: 1552152187081, @@ -91,16 +90,6 @@ describe('ProcessHeaderCloudComponent', () => { }); })); - it('should display description', async(() => { - component.ngOnChanges(); - fixture.detectChanges(); - - fixture.whenStable().then(() => { - const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-description"] span')); - expect(formNameEl.nativeElement.innerText).toBe('new desc'); - }); - })); - it('should display placeholder if no name is available', async(() => { processInstanceDetailsCloudMock.name = null; component.ngOnChanges(); @@ -113,18 +102,6 @@ describe('ProcessHeaderCloudComponent', () => { })); - it('should display placeholder if no description is available', async(() => { - processInstanceDetailsCloudMock.description = null; - component.ngOnChanges(); - fixture.detectChanges(); - - fixture.whenStable().then(() => { - const valueEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-description"] span')); - expect(valueEl.nativeElement.innerText).toBe('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.DESCRIPTION_DEFAULT'); - }); - - })); - it('should display status', async(() => { component.ngOnChanges(); fixture.detectChanges(); diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts index e0d61d4904..bc60f506f3 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts @@ -86,13 +86,6 @@ export class ProcessHeaderCloudComponent implements OnChanges { key: 'name', default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME_DEFAULT') }), - new CardViewTextItemModel( - { - label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.DESCRIPTION', - value: this.processInstanceDetails.description, - key: 'description', - default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.DESCRIPTION_DEFAULT') - }), new CardViewTextItemModel( { label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.STATUS', diff --git a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts index 095538c05f..2bd9a92330 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.spec.ts @@ -133,7 +133,6 @@ describe('ProcessListCloudComponent', () => { expect(component.rows[0].entry['appVersion']).toBe(''); expect(component.rows[0].entry['id']).toBe('69eddfa7-d781-11e8-ae24-0a58646001fa'); expect(component.rows[0].entry['name']).toEqual('starring'); - expect(component.rows[0].entry['description']).toBeNull(); expect(component.rows[0].entry['processDefinitionId']).toBe('BasicProcess:1:d05062f1-c6fb-11e8-ae24-0a58646001fa'); expect(component.rows[0].entry['processDefinitionKey']).toBe('BasicProcess'); expect(component.rows[0].entry['initiator']).toBe('devopsuser'); diff --git a/lib/process-services-cloud/src/lib/process/process-list/mock/process-list-service.mock.ts b/lib/process-services-cloud/src/lib/process/process-list/mock/process-list-service.mock.ts index bc704ba068..7eae55e6fa 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/mock/process-list-service.mock.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/mock/process-list-service.mock.ts @@ -26,7 +26,6 @@ export const fakeProcessCloudList = { appVersion: '', id: '69eddfa7-d781-11e8-ae24-0a58646001fa', name: 'starring', - description: null, processDefinitionId: 'BasicProcess:1:d05062f1-c6fb-11e8-ae24-0a58646001fa', processDefinitionKey: 'BasicProcess', initiator: 'devopsuser', @@ -44,7 +43,6 @@ export const fakeProcessCloudList = { appVersion: '', id: '8b3f625f-d781-11e8-ae24-0a58646001fa', name: null, - description: null, processDefinitionId: 'BasicProcess:1:d05062f1-c6fb-11e8-ae24-0a58646001fa', processDefinitionKey: 'BasicProcess', initiator: 'devopsuser', @@ -62,7 +60,6 @@ export const fakeProcessCloudList = { appVersion: '', id: '87c12637-d783-11e8-ae24-0a58646001fa', name: null, - description: null, processDefinitionId: 'BasicProcess:1:d05062f1-c6fb-11e8-ae24-0a58646001fa', processDefinitionKey: 'BasicProcess', initiator: 'superadminuser', diff --git a/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts b/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts index 3a702933af..db8dac8f54 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts @@ -19,7 +19,6 @@ import { ProcessListCloudSortingModel } from './process-list-sorting.model'; export class ProcessQueryCloudRequestModel { appName: string; - description?: string; initiator?: null; id?: string; name?: string; @@ -37,7 +36,6 @@ export class ProcessQueryCloudRequestModel { constructor(obj?: any) { if (obj) { this.appName = obj.appName; - this.description = obj.description; this.initiator = obj.initiator; this.id = obj.id; this.name = obj.name; diff --git a/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts b/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts index e9b21545b4..c18977826b 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts @@ -19,7 +19,6 @@ export class ProcessInstanceCloud { appName: string; id: string; name: string; - description: string; startDate: Date; initiator: string; status: string; @@ -33,7 +32,6 @@ export class ProcessInstanceCloud { this.appName = obj && obj.appName || null; this.id = obj && obj.id || null; this.name = obj && obj.name || null; - this.description = obj && obj.description || null; this.startDate = obj && obj.startDate || null; this.initiator = obj && obj.initiator || null; this.status = obj && obj.status || null; From 3a64f4aaabb1660f6a758a89aadd9a5df6082661 Mon Sep 17 00:00:00 2001 From: LucaBiondo <luca.biondo13@gmail.com> Date: Tue, 9 Apr 2019 17:50:21 +0200 Subject: [PATCH 079/208] Fromo mySuccessMethod to myExecuteSubmitMethod (#4573) In the tutorial, when working with events, it says that we want to show an allert when submitting the login form but in the code just below it binds the allert to the "success" event and not to the "executeSubmit" event. Also calls the method mySuccessMethod and not myExecuteSubmitMethod as it does at the very and of the Tutorial. So i made the appropriate changes to adjust the code and the tutorial to show how to properly bind an allert to the "eventSubmit" event. Regards Luca Biondo --- docs/tutorials/using-components.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/tutorials/using-components.md b/docs/tutorials/using-components.md index 705b318832..0ac5e73cb9 100644 --- a/docs/tutorials/using-components.md +++ b/docs/tutorials/using-components.md @@ -73,23 +73,23 @@ docs, we can see that it emits three events: `success`, `error` and `executeSubm We can subscribe to these events and have our custom code executed when these events are emitted. Let's hook into the `executeSubmit` and do a simple `alert()` when the form is submitted. -Open `src/app/login/login.component.html` and add `(success)="mySuccessMethod($event)"` to the `<adf-login/>` component: +Open `src/app/login/login.component.html` and add `(executeSubmit)="myExecuteSubmitMethod($event)"` to the `<adf-login/>` component: ```html <adf-login [showRememberMe]="false" [showLoginActions]="false" - (success)="mySuccessMethod($event)" + (executeSubmit)="myExecuteSubmitMethod($event)" copyrightText="© 2017 Alfresco Software, Inc. All Rights Reserved." successRoute="/documentlist"> </adf-login> ``` -Next we need to implement `mySuccessMethod` in the typescript. Open `src/app/login/login.component.ts` and add a new method: +Next we need to implement `myExecuteSubmitMethod` in the typescript. Open `src/app/login/login.component.ts` and add a new method: ```ts // Add this! -mySuccessMethod(event: any) { +myExecuteSubmitMethod(event: any) { alert('Form was submitted!'); console.log(event); } @@ -108,7 +108,7 @@ import { Component } from '@angular/core'; export class LoginComponent { // Add this! - mySuccessMethod(event: any) { + myExecuteSubmitMethod(event: any) { alert('Form was submitted!'); console.log(event); } From 70cf1da78ee9df8cda63020ec40a8867585a4adc Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 9 Apr 2019 16:53:47 +0100 Subject: [PATCH 080/208] [ADF-4368] Add JSON cell to datatable in Demo-Shell for testing purposes (#4579) --- .../datatable/datatable.component.ts | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/demo-shell/src/app/components/datatable/datatable.component.ts b/demo-shell/src/app/components/datatable/datatable.component.ts index 2d500abed9..39e7a7b62d 100644 --- a/demo-shell/src/app/components/datatable/datatable.component.ts +++ b/demo-shell/src/app/components/datatable/datatable.component.ts @@ -89,36 +89,50 @@ export class DataTableComponent { sunt in culpa qui officia deserunt mollit anim id est laborum.`, createdOn: new Date(2016, 6, 2, 15, 8, 1), createdBy: this._createdBy, - icon: 'material-icons://folder_open' + icon: 'material-icons://folder_open', + json: null }, { id: 2, name: 'Name 2', createdOn: new Date(2016, 6, 2, 15, 8, 2), createdBy: this._createdBy, - icon: 'material-icons://accessibility' + icon: 'material-icons://accessibility', + json: null }, { id: 3, name: 'Name 3', createdOn: new Date(2016, 6, 2, 15, 8, 3), createdBy: this._createdBy, - icon: 'material-icons://alarm' + icon: 'material-icons://alarm', + json: null }, { id: 4, name: 'Image 8', createdOn: new Date(2016, 6, 2, 15, 8, 4), createdBy: this._createdBy, - icon: 'material-icons://alarm' + icon: 'material-icons://alarm', + json: { + id: 4, + name: 'Image 8', + createdOn: new Date(2016, 6, 2, 15, 8, 4), + createdBy: { + name: 'Felipe', + lastname: 'Melo' + }, + icon: 'material-icons://alarm' + } } ], [ { type: 'image', key: 'icon', title: '', srTitle: 'Thumbnail' }, { type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '' }, - { type: 'text', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-5' }, + { type: 'text', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-2' }, { type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true }, - { type: 'text', key: 'createdBy.name', title: 'Created By', sortable: true, cssClass: ''} + { type: 'text', key: 'createdBy.name', title: 'Created By', sortable: true, cssClass: ''}, + { type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2'} ] ); From 4bfae518fb93e88b60ff1100436ea28aecbbce89 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Wed, 10 Apr 2019 01:11:35 +0100 Subject: [PATCH 081/208] [ADF-4216] Recently uploaded files are missing 'ago' in the Created column (#4578) * replaced the assertion for 'ago' to 'ago | few' * replaced the assertion for 'ago' to 'ago | few' --- .../document-list/document-list-component.e2e.ts | 10 +++++----- .../comment-component-processes.e2e.ts | 4 ++-- e2e/process-services/comment-component-tasks.e2e.ts | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/e2e/content-services/document-list/document-list-component.e2e.ts b/e2e/content-services/document-list/document-list-component.e2e.ts index b326b5ef26..20dc4ee799 100644 --- a/e2e/content-services/document-list/document-list-component.e2e.ts +++ b/e2e/content-services/document-list/document-list-component.e2e.ts @@ -204,7 +204,7 @@ describe('Document List Component', () => { timeAgoUploadedNode = await uploadActions.uploadFile(this.alfrescoJsApi, timeAgoFileModel.location, timeAgoFileModel.name, '-my-'); contentServicesPage.goToDocumentList(); const dateValue = contentServicesPage.getColumnValueForRow(timeAgoFileModel.name, 'Created'); - expect(dateValue).toContain('ago'); + expect(dateValue).toMatch(/(ago|few)/); done(); }); @@ -608,25 +608,25 @@ describe('Document List Component', () => { expect(contentServicesPage.getAttributeValueForElement(folderName, cardProperties.DISPLAY_NAME)).toBe(folderName); expect(contentServicesPage.getAttributeValueForElement(folderName, cardProperties.CREATED_BY)).toBe(`${funnyUser.entry.firstName} ${funnyUser.entry.lastName}`); - expect(contentServicesPage.getAttributeValueForElement(folderName, cardProperties.CREATED)).toContain('ago'); + expect(contentServicesPage.getAttributeValueForElement(folderName, cardProperties.CREATED)).toMatch(/(ago|few)/); expect(contentServicesPage.getAttributeValueForElement(pdfFile.name, cardProperties.DISPLAY_NAME)).toBe(pdfFile.name); expect(contentServicesPage.getAttributeValueForElement(pdfFile.name, cardProperties.SIZE)).toBe(`702.76 KB`); expect(contentServicesPage.getAttributeValueForElement(pdfFile.name, cardProperties.CREATED_BY)).toBe(`${funnyUser.entry.firstName} ${funnyUser.entry.lastName}`); - expect(contentServicesPage.getAttributeValueForElement(pdfFile.name, cardProperties.CREATED)).toContain('ago'); + expect(contentServicesPage.getAttributeValueForElement(pdfFile.name, cardProperties.CREATED)).toMatch(/(ago|few)/); expect(contentServicesPage.getAttributeValueForElement(docxFile.name, cardProperties.DISPLAY_NAME)).toBe(docxFile.name); expect(contentServicesPage.getAttributeValueForElement(docxFile.name, cardProperties.SIZE)).toBe(`81.05 KB`); expect(contentServicesPage.getAttributeValueForElement(docxFile.name, cardProperties.CREATED_BY)).toBe(`${funnyUser.entry.firstName} ${funnyUser.entry.lastName}`); - expect(contentServicesPage.getAttributeValueForElement(docxFile.name, cardProperties.CREATED)).toContain('ago'); + expect(contentServicesPage.getAttributeValueForElement(docxFile.name, cardProperties.CREATED)).toMatch(/(ago|few)/); expect(contentServicesPage.getAttributeValueForElement(testFile.name, cardProperties.DISPLAY_NAME)).toBe(testFile.name); expect(contentServicesPage.getAttributeValueForElement(testFile.name, cardProperties.SIZE)).toBe(`14 Bytes`); expect(contentServicesPage.getAttributeValueForElement(testFile.name, cardProperties.CREATED_BY)).toBe(`${funnyUser.entry.firstName} ${funnyUser.entry.lastName}`); - expect(contentServicesPage.getAttributeValueForElement(testFile.name, cardProperties.CREATED)).toContain('ago'); + expect(contentServicesPage.getAttributeValueForElement(testFile.name, cardProperties.CREATED)).toMatch(/(ago|few)/); }); it('[C280129] Should keep Gallery View when accessing a folder', () => { diff --git a/e2e/process-services/comment-component-processes.e2e.ts b/e2e/process-services/comment-component-processes.e2e.ts index ac826558ec..5646253d2c 100644 --- a/e2e/process-services/comment-component-processes.e2e.ts +++ b/e2e/process-services/comment-component-processes.e2e.ts @@ -96,7 +96,7 @@ describe('Comment component for Processes', () => { expect(commentsPage.getTotalNumberOfComments()).toEqual('Comments (' + addedComment.total + ')'); expect(commentsPage.getMessage(0)).toEqual(addedComment.data[0].message); expect(commentsPage.getUserName(0)).toEqual(addedComment.data[0].createdBy.firstName + ' ' + addedComment.data[0].createdBy.lastName); - expect(commentsPage.getTime(0)).toContain('ago'); + expect(commentsPage.getTime(0)).toMatch(/(ago|few)/); }); }); @@ -146,7 +146,7 @@ describe('Comment component for Processes', () => { expect(commentsPage.getTotalNumberOfComments()).toEqual('Comments (' + addedTaskComment.total + ')'); expect(commentsPage.getMessage(0)).toEqual(addedTaskComment.data[0].message); expect(commentsPage.getUserName(0)).toEqual(addedTaskComment.data[0].createdBy.firstName + ' ' + addedTaskComment.data[0].createdBy.lastName); - expect(commentsPage.getTime(0)).toContain('ago'); + expect(commentsPage.getTime(0)).toMatch(/(ago|few)/); }); }); }); diff --git a/e2e/process-services/comment-component-tasks.e2e.ts b/e2e/process-services/comment-component-tasks.e2e.ts index 881f52b18f..383f63626c 100644 --- a/e2e/process-services/comment-component-tasks.e2e.ts +++ b/e2e/process-services/comment-component-tasks.e2e.ts @@ -138,8 +138,8 @@ describe('Comment component for Processes', () => { await expect(commentsPage.getUserName(0)).toEqual(totalComments.data[0].createdBy.firstName + ' ' + totalComments.data[0].createdBy.lastName); await expect(commentsPage.getUserName(1)).toEqual(totalComments.data[1].createdBy.firstName + ' ' + totalComments.data[1].createdBy.lastName); - await expect(commentsPage.getTime(0)).toContain('ago'); - await expect(commentsPage.getTime(1)).toContain('ago'); + await expect(commentsPage.getTime(0)).toMatch(/(ago|few)/); + await expect(commentsPage.getTime(1)).toMatch(/(ago|few)/); await loginPage.loginToProcessServicesUsingUserModel(secondUser); @@ -169,9 +169,9 @@ describe('Comment component for Processes', () => { await expect(commentsPage.getUserName(1)).toEqual(totalComments.data[1].createdBy.firstName + ' ' + totalComments.data[1].createdBy.lastName); await expect(commentsPage.getUserName(2)).toEqual(totalComments.data[2].createdBy.firstName + ' ' + totalComments.data[2].createdBy.lastName); - await expect(commentsPage.getTime(0)).toContain('ago'); - await expect(commentsPage.getTime(1)).toContain('ago'); - await expect(commentsPage.getTime(2)).toContain('ago'); + await expect(commentsPage.getTime(0)).toMatch(/(ago|few)/); + await expect(commentsPage.getTime(1)).toMatch(/(ago|few)/); + await expect(commentsPage.getTime(2)).toMatch(/(ago|few)/); }); }); }); From 3df30f05f3d09df6c7eacb026bc84442c5a94fdf Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Wed, 10 Apr 2019 03:21:12 +0300 Subject: [PATCH 082/208] [ADF-3934] PeoplCloudComponent - add dynamic placeholder (#4548) * [ADF-3934] PeoplCloudComponent - add dynamic placeholder * [ADF-3934] - fix tests * [AF-3934] - PR changes * [ADF-3934] - remove unnecesary test * [ADF-3934] - lint --- .../people-groups-cloud-demo.component.html | 1 + .../components/people-cloud.component.md | 1 + .../people-cloud/people-cloud.component.html | 2 +- .../people-cloud.component.spec.ts | 36 ++++++++++++++++++- .../people-cloud/people-cloud.component.ts | 5 +++ .../start-task-cloud.component.html | 1 + 6 files changed, 44 insertions(+), 2 deletions(-) diff --git a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html index 87917d2c49..febd6f6414 100644 --- a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html @@ -40,6 +40,7 @@ [appName]="peopleAppName" [roles]="peopleRoles" [appName]="peopleAppName" + [title]="'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'" [mode]="peopleMode"></adf-cloud-people> </div> diff --git a/docs/process-services-cloud/components/people-cloud.component.md b/docs/process-services-cloud/components/people-cloud.component.md index 9dff8da2e0..f42dce375f 100644 --- a/docs/process-services-cloud/components/people-cloud.component.md +++ b/docs/process-services-cloud/components/people-cloud.component.md @@ -29,6 +29,7 @@ Allows one or more users to be selected (with auto-suggestion) based on the inpu | preSelectUsers | [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]` | | Array of users to be pre-selected. All users in the array are pre-selected in multi selection mode, but only the first user is pre-selected in single selection mode. Mandatory properties are: id, email, username | | roles | `string[]` | | Role names of the users to be listed. | | validate | `Boolean` | false | This flag enables the validation on the preSelectUsers passed as input. In case the flag is true the components call the identity service to verify the validity of the information passed as input. Otherwise, no check will be done. | +| title | `string` | | Translation key for the input placeholder | ### Events diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.html b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.html index b1845e2311..1ca2dffe2a 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.html @@ -1,6 +1,6 @@ <form> <mat-form-field class="adf-people-cloud"> - <mat-label id="assignee-id">{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE' | translate}}</mat-label> + <mat-label id="title-id">{{ title | translate }}</mat-label> <mat-chip-list #userChipList *ngIf="isMultipleMode(); else singleSelection"> <mat-chip *ngFor="let user of selectedUsers$ | async" diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 3a06022e51..7469ca0c67 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -145,6 +145,25 @@ describe('PeopleCloudComponent', () => { expect(errorMessage.textContent).toContain('ADF_CLOUD_START_TASK.ERROR.MESSAGE'); }); })); + + it('should populate placeholder when title is present', async(() => { + component.title = 'TITLE_KEY'; + fixture.detectChanges(); + const matLabel: HTMLInputElement = <HTMLInputElement> element.querySelector('mat-label'); + fixture.whenStable().then( () => { + fixture.detectChanges(); + expect(matLabel.textContent).toEqual('TITLE_KEY'); + }); + })); + + it('should not populate placeholder when title is present', async(() => { + const matLabel: HTMLInputElement = <HTMLInputElement> element.querySelector('mat-label'); + fixture.detectChanges(); + fixture.whenStable().then( () => { + fixture.detectChanges(); + expect(matLabel.textContent).toEqual(''); + }); + })); }); describe('when application name defined', () => { @@ -543,7 +562,7 @@ describe('PeopleCloudComponent', () => { component.preSelectUsers = <any> [{ id: mockUsers[0].id }, { id: mockUsers[1].id }]; component.ngOnChanges({ 'preSelectUsers': change }); fixture.detectChanges(); - component.filterPreselectUsers().then((result) => { + component.filterPreselectUsers().then((result: any) => { fixture.detectChanges(); expect(findByIdSpy).toHaveBeenCalled(); expect(component.userExists(result[0])).toEqual(true); @@ -636,5 +655,20 @@ describe('PeopleCloudComponent', () => { }); }); })); + + it('should populate placeholder when title is present', () => { + fixture.detectChanges(); + component.title = 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'; + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('mat-label'); + fixture.detectChanges(); + expect(inputHTMLElement.textContent).toEqual('ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'); + }); + + it('should not populate placeholder when title is present', () => { + fixture.detectChanges(); + const inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('mat-label'); + fixture.detectChanges(); + expect(inputHTMLElement.textContent).toEqual(''); + }); }); }); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts index 4f57e2eb9b..42bc47f2b0 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts @@ -71,6 +71,11 @@ export class PeopleCloudComponent implements OnInit, OnChanges { @Input() preSelectUsers: IdentityUserModel[]; + /** Placeholder translation key + */ + @Input() + title: string; + /** Emitted when a user is selected. */ @Output() selectUser: EventEmitter<IdentityUserModel> = new EventEmitter<IdentityUserModel>(); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html index f857c8df87..95e19ac0a8 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html @@ -64,6 +64,7 @@ [appName]="appName" [preSelectUsers]="[currentUser]" (selectUser)="onAssigneeSelect($event)" + [title]="'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'" (removeUser)="onAssigneeRemove()"></adf-cloud-people> </div> From 312d8432df0008737efc55328c56adf97ca231d8 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Wed, 10 Apr 2019 03:30:57 +0300 Subject: [PATCH 083/208] [ADF-4357] TaskListCloud - change complete task condition (#4554) * [ADF-4357] TaskListCloud - change complete task condition * [ADF-4357] - PR changes * [ADF-4357] - add unit test and change owner user * [ADF-4357] - lint * [ADF-4357] - change complete task condition --- .../task/services/task-cloud.service.spec.ts | 24 +++++++- .../lib/task/services/task-cloud.service.ts | 2 +- .../task/start-task/mock/user-cloud.mock.ts | 2 +- .../models/task-details-cloud.model.ts | 4 ++ .../task-header-cloud.component.spec.ts | 8 +-- .../mocks/task-details-cloud.mock.ts | 58 ++++++++++++++++++- 6 files changed, 87 insertions(+), 11 deletions(-) diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts index ae1d8f9aef..911646e164 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.spec.ts @@ -20,7 +20,7 @@ import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; import { AlfrescoApiServiceMock, LogService, AppConfigService, CoreModule } from '@alfresco/adf-core'; import { TaskCloudService } from './task-cloud.service'; import { taskCompleteCloudMock } from '../task-header/mocks/fake-complete-task.mock'; -import { taskDetailsCloudMock } from '../task-header/mocks/task-details-cloud.mock'; +import { assignedTaskDetailsCloudMock, createdTaskDetailsCloudMock, emptyOwnerTaskDetailsCloudMock } from '../task-header/mocks/task-details-cloud.mock'; import { fakeTaskDetailsCloud } from '../task-header/mocks/fake-task-details-response.mock'; import { cloudMockUser } from '../start-task/mock/user-cloud.mock'; @@ -104,10 +104,30 @@ describe('Task Cloud Service', () => { }); it('should canCompleteTask', () => { - const canCompleteTaskResult = service.canCompleteTask(taskDetailsCloudMock); + const canCompleteTaskResult = service.canCompleteTask(assignedTaskDetailsCloudMock); expect(canCompleteTaskResult).toBeTruthy(); }); + it('should not complete with wrong asignee and owner different from asigned user', () => { + const canCompleteTaskResult = service.canCompleteTask(createdTaskDetailsCloudMock); + expect(canCompleteTaskResult).toEqual(false); + }); + + it('should complete task with owner as null', async(() => { + const appName = 'simple-app'; + const taskId = '68d54a8f'; + const canCompleteTaskResult = service.canCompleteTask(emptyOwnerTaskDetailsCloudMock); + spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnFakeTaskCompleteResults); + + service.completeTask(appName, taskId).subscribe((res: any) => { + expect(canCompleteTaskResult).toEqual(true); + expect(res).toBeDefined(); + expect(res).not.toBeNull(); + expect(res.entry.appName).toBe('simple-app'); + expect(res.entry.id).toBe('68d54a8f'); + }); + })); + it('should return the task details when claiming a task', (done) => { const appName = 'taskp-app'; const assignee = 'user12'; diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index 78ca221e86..fe207c46ab 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -71,7 +71,7 @@ export class TaskCloudService { */ canCompleteTask(taskDetails: TaskDetailsCloudModel): boolean { const currentUser = this.identityUserService.getCurrentUserInfo().username; - return taskDetails.assignee && taskDetails.owner === currentUser && !taskDetails.isCompleted(); + return taskDetails.assignee && taskDetails.assignee === currentUser && taskDetails.isAssigned(); } /** diff --git a/lib/process-services-cloud/src/lib/task/start-task/mock/user-cloud.mock.ts b/lib/process-services-cloud/src/lib/task/start-task/mock/user-cloud.mock.ts index 1bf9362984..b6d4148869 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/mock/user-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/mock/user-cloud.mock.ts @@ -22,7 +22,7 @@ export const mockUsers = [ ]; export const cloudMockUser = { - id: 'fake-id-1', username: 'superadminuser', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' + id: 'fake-id-1', username: 'AssignedTaskUser', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' }; export const mockRoles = [ diff --git a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts index 091ed1ca92..06747c4b0c 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts @@ -78,6 +78,10 @@ export class TaskDetailsCloudModel { return this.status && this.status === TaskStatusEnum.COMPLETED; } + isAssigned(): boolean { + return this.status && this.status === TaskStatusEnum.ASSIGNED; + } + canClaimTask(): boolean { return this.status === TaskStatusEnum.CREATED; } diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts index c50bc2dae9..7c592355e2 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.spec.ts @@ -18,7 +18,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { setupTestBed, AppConfigService } from '@alfresco/adf-core'; import { TaskHeaderCloudComponent } from './task-header-cloud.component'; -import { taskDetailsCloudMock } from '../mocks/task-details-cloud.mock'; +import { assignedTaskDetailsCloudMock } from '../mocks/task-details-cloud.mock'; import { TaskHeaderCloudModule } from '../task-header-cloud.module'; import { By } from '@angular/platform-browser'; import { of } from 'rxjs'; @@ -44,10 +44,10 @@ describe('TaskHeaderCloudComponent', () => { fixture = TestBed.createComponent(TaskHeaderCloudComponent); component = fixture.componentInstance; component.appName = 'myApp'; - component.taskId = taskDetailsCloudMock.id; + component.taskId = assignedTaskDetailsCloudMock.id; service = TestBed.get(TaskCloudService); appConfigService = TestBed.get(AppConfigService); - spyOn(service, 'getTaskById').and.returnValue(of(taskDetailsCloudMock)); + spyOn(service, 'getTaskById').and.returnValue(of(assignedTaskDetailsCloudMock)); }); it('should render empty component if no task details provided', async(() => { @@ -63,7 +63,7 @@ describe('TaskHeaderCloudComponent', () => { fixture.whenStable().then(() => { const formNameEl = fixture.debugElement.query(By.css('[data-automation-id="card-textitem-value-assignee"] span')); - expect(formNameEl.nativeElement.innerText).toBe('Wilbur Adams'); + expect(formNameEl.nativeElement.innerText).toBe('AssignedTaskUser'); }); })); diff --git a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts index e417613cfd..9037a30759 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/mocks/task-details-cloud.mock.ts @@ -17,12 +17,12 @@ import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; -export const taskDetailsCloudMock = new TaskDetailsCloudModel( +export const assignedTaskDetailsCloudMock = new TaskDetailsCloudModel( { 'appName': 'task-app', 'appVersion': '', 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', - 'assignee': 'Wilbur Adams', + 'assignee': 'AssignedTaskUser', 'name': 'This is a new task ', 'description': 'This is the description ', 'createdDate': 1545048055900, @@ -33,7 +33,59 @@ export const taskDetailsCloudMock = new TaskDetailsCloudModel( 'processDefinitionId': null, 'processInstanceId': null, 'status': 'ASSIGNED', - 'owner': 'superadminuser', + 'owner': 'ownerUser', + 'parentTaskId': null, + 'formKey': null, + 'lastModified': 1545048055900, + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standAlone': true + } +); + +export const createdTaskDetailsCloudMock = new TaskDetailsCloudModel( + { + 'appName': 'task-app', + 'appVersion': '', + 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', + 'assignee': 'CreatedTaskUser', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': 1545048055900, + 'dueDate': 1545091200000, + 'claimedDate': null, + 'priority': 5, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'CREATED', + 'owner': 'ownerUser', + 'parentTaskId': null, + 'formKey': null, + 'lastModified': 1545048055900, + 'lastModifiedTo': null, + 'lastModifiedFrom': null, + 'standAlone': true + } +); + +export const emptyOwnerTaskDetailsCloudMock = new TaskDetailsCloudModel( + { + 'appName': 'task-app', + 'appVersion': '', + 'id': '68d54a8f-01f3-11e9-8e36-0a58646002ad', + 'assignee': 'AssignedTaskUser', + 'name': 'This is a new task ', + 'description': 'This is the description ', + 'createdDate': 1545048055900, + 'dueDate': 1545091200000, + 'claimedDate': null, + 'priority': 5, + 'category': null, + 'processDefinitionId': null, + 'processInstanceId': null, + 'status': 'ASSIGNED', + 'owner': null, 'parentTaskId': null, 'formKey': null, 'lastModified': 1545048055900, From fb9308ddbf5833662debe6165d9d758306f55b1c Mon Sep 17 00:00:00 2001 From: Marouan Bentaleb <38426175+marouanbentaleb@users.noreply.github.com> Date: Wed, 10 Apr 2019 10:48:42 +0100 Subject: [PATCH 084/208] [ADF-4367] Automation for process date format (#4580) --- .../process-instance-details.e2e.ts | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 e2e/process-services/process-instance-details.e2e.ts diff --git a/e2e/process-services/process-instance-details.e2e.ts b/e2e/process-services/process-instance-details.e2e.ts new file mode 100644 index 0000000000..e2ed34b074 --- /dev/null +++ b/e2e/process-services/process-instance-details.e2e.ts @@ -0,0 +1,91 @@ +/*! + * @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 TestConfig = require('../test.config'); + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UsersActions } from '../actions/users.actions'; +import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; +import resources = require('../util/resources'); +import { AppsActions } from '../actions/APS/apps.actions'; +import { LoginPage } from '@alfresco/adf-testing'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; +import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessListPage } from '../pages/adf/process-services/processListPage'; +import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; +import dateFormat = require('dateformat'); + +describe('Process Instance Details', () => { + + const loginPage = new LoginPage(); + const navigationBarPage = new NavigationBarPage(); + const processServicesPage = new ProcessServicesPage(); + const appNavigationBarPage = new AppNavigationBarPage(); + const processListPage = new ProcessListPage(); + const processDetailsPage = new ProcessDetailsPage(); + + let appModel, process, user; + const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; + const PROCESS_DATE_FORMAT = 'mmm dd yyyy'; + + beforeAll(async (done) => { + const apps = new AppsActions(); + const users = new UsersActions(); + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'BPM', + hostBpm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + user = await users.createTenantAndUser(this.alfrescoJsApi); + + await this.alfrescoJsApi.login(user.email, user.password); + + appModel = await apps.importPublishDeployApp(this.alfrescoJsApi, app.file_location); + const processModel = await apps.startProcess(this.alfrescoJsApi, appModel, 'process'); + + await loginPage.loginToProcessServicesUsingUserModel(user); + + navigationBarPage.navigateToProcessServicesPage(); + processServicesPage.checkApsContainer(); + processServicesPage.goToApp(app.title); + appNavigationBarPage.clickProcessButton(); + processListPage.checkProcessListIsDisplayed(); + + process = await this.alfrescoJsApi.activiti.processApi.getProcessInstance(processModel.id); + + done(); + }); + + afterAll(async (done) => { + await this.alfrescoJsApi.activiti.modelsApi.deleteModel(appModel.id); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + await this.alfrescoJsApi.activiti.adminTenantsApi.deleteTenant(user.tenantId); + + done(); + }); + + it('[C307031] Should display the created date in the default format', () => { + processDetailsPage.checkDetailsAreDisplayed(); + expect(processDetailsPage.getCreated()).toEqual(dateFormat(process.started, PROCESS_DATE_FORMAT)); + }); + +}); From 7a2c5762ff4b1fe587dee98af51616d2b436e472 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Wed, 10 Apr 2019 10:49:56 +0100 Subject: [PATCH 085/208] [ADF-4321] Add Task Id filter to task cloud filters (#4571) --- .../app/components/cloud/tasks-cloud-demo.component.html | 1 + .../components/edit-task-filter-cloud.component.md | 1 + lib/process-services-cloud/src/lib/i18n/en.json | 1 + .../components/edit-task-filter-cloud.component.ts | 6 ++++++ .../src/lib/task/task-filters/models/filter-cloud.model.ts | 2 ++ 5 files changed, 11 insertions(+) diff --git a/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.html b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.html index a6d7709655..310c709101 100644 --- a/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.html @@ -16,6 +16,7 @@ [processDefinitionId]="editedFilter.processDefinitionId" [processInstanceId]="editedFilter.processInstanceId" [name]="editedFilter.taskName" + [id]="editedFilter.taskId" [parentTaskId]="editedFilter.parentTaskId" [priority]="editedFilter.priority" [owner]="editedFilter.owner" diff --git a/docs/process-services-cloud/components/edit-task-filter-cloud.component.md b/docs/process-services-cloud/components/edit-task-filter-cloud.component.md index 0637f72421..027efe9269 100644 --- a/docs/process-services-cloud/components/edit-task-filter-cloud.component.md +++ b/docs/process-services-cloud/components/edit-task-filter-cloud.component.md @@ -82,6 +82,7 @@ given below: | **_status_** | Execution state of the task. | | **_assignee_** | User the task is assigned to | | **_taskName_** | Name of the task | +| **_taskId_** | ID of the task | | **_parentTaskId_** | ID of the task's parent task | | **_priority_** | Task priority | | **_createdDate_** | Date the task was created | diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index fdeb65f6a7..796e9d4232 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -113,6 +113,7 @@ }, "LABEL": { "APP_NAME": "ApplicationName", + "TASK_ID": "Task ID", "PROCESS_DEF_ID": "ProcessDefinitionId", "STATUS": "Status", "ASSIGNMENT": "Assignee", diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts index 7d20988087..deaae0e70a 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts @@ -439,6 +439,12 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges { value: currentTaskFilter.appName || '', options: this.applicationNames }), + new TaskFilterProperties({ + label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.TASK_ID', + type: 'text', + key: 'taskId', + value: '' + }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STATUS', type: 'select', diff --git a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts index e438917270..08d441a858 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts @@ -32,6 +32,7 @@ export class TaskFilterCloudModel { createdDate: Date; dueDate: Date; taskName: string; + taskId: string; parentTaskId: string; priority: number; standAlone: boolean; @@ -56,6 +57,7 @@ export class TaskFilterCloudModel { this.createdDate = obj.createdDate || null; this.dueDate = obj.dueDate || null; this.taskName = obj.taskName || null; + this.taskId = obj.taskId || null; this.parentTaskId = obj.parentTaskId || null; this.priority = obj.priority || null; this.standAlone = obj.standAlone || null; From 0d383211827c20cd09e56eedda3c0220507a6d82 Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Wed, 10 Apr 2019 12:20:14 +0100 Subject: [PATCH 086/208] [ADF-4383] Updated filter props details in Edit proc cloud docs (#4586) --- .../edit-process-filter-cloud.component.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/process-services-cloud/components/edit-process-filter-cloud.component.md b/docs/process-services-cloud/components/edit-process-filter-cloud.component.md index 4e149b099f..792026088c 100644 --- a/docs/process-services-cloud/components/edit-process-filter-cloud.component.md +++ b/docs/process-services-cloud/components/edit-process-filter-cloud.component.md @@ -2,7 +2,7 @@ Title: Edit Process Filter Cloud component Added: v3.0.0 Status: Experimental -Last reviewed: 2019-03-27 +Last reviewed: 2019-04-10 --- # [Edit Process Filter Cloud component](../../../lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts "Defined in edit-process-filter-cloud.component.ts") @@ -79,8 +79,8 @@ given below: | Name | Description | | ---- | ----------- | | **_appName_** | Name of the app | -| **_processInstanceId_** | Process instance ID | -| **_processName_** | Process name. | +| **_id_** | Process instance ID | +| **_name_** | Process name. | | **_initiator_** | ID of the user who initiated the process | | **_status_** | Execution status of the process. | | **_processDefinitionId_** | Process definition ID | @@ -93,15 +93,17 @@ By default, the **_status_**, **_sort_** and **_order_** properties are displayed in the editor. However, you can also choose which properties to show using the `filterProperties` array. For example, the code below initializes the editor with the **_appName_**, -**_processInstanceId_**, **_processName_** and **_lastModified_** properties: +**_id_**, **_name_** and **_lastModified_** properties: ```ts export class SomeComponent implements OnInit { filterProperties: string[] = [ - "processName" - "processInstanceId", - "lastModified"]; + "appName", + "id", + "name", + "lastModified" + ]; onFilterChange(filter: ProcessFilterCloudModel) { console.log('On filter change: ', filter); @@ -126,8 +128,7 @@ With this configuration, only the four listed properties will be shown. You can supply a list of _sort properties_ to sort the processes. You can use any of the [filter properties](#filter-properties) listed above as -sort properties and you can also use the process **_id_** and **_startDate_** -properties and use **_name_** as a shorthand for **_processName_**. +sort properties and you can also use the process's **_startDate_**. By default, the **_id_**, **_name_**, **_status_** and **_startDate_** properties are displayed in the editor. However, you can also choose which sort properties From 1f6e86846469a6f905acf408ff6b4226bf6f0419 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Wed, 10 Apr 2019 13:25:45 +0100 Subject: [PATCH 087/208] [ADF-4384] improve recent files query (#4585) * improve recent files query * remove duplicate filter --- .../services/custom-resources.service.ts | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/lib/content-services/document-list/services/custom-resources.service.ts b/lib/content-services/document-list/services/custom-resources.service.ts index 237ae11936..0f90e7b754 100644 --- a/lib/content-services/document-list/services/custom-resources.service.ts +++ b/lib/content-services/document-list/services/custom-resources.service.ts @@ -51,23 +51,55 @@ export class CustomResourcesService { * Gets files recently accessed by a user. * @param personId ID of the user * @param pagination Specifies how to paginate the results + * @param filters Specifies additional filters to apply (joined with **AND**) * @returns List of nodes for the recently used files */ - getRecentFiles(personId: string, pagination: PaginationModel): Observable<NodePaging> { + getRecentFiles(personId: string, pagination: PaginationModel, filters?: string[]): Observable<NodePaging> { + const defaultFilter = [ + 'TYPE:"content"', + '-PNAME:"0/wiki"', + '-TYPE:"app:filelink"', + '-TYPE:"cm:thumbnail"', + '-TYPE:"cm:failedThumbnail"', + '-TYPE:"cm:rating"', + '-TYPE:"dl:dataList"', + '-TYPE:"dl:todoList"', + '-TYPE:"dl:issue"', + '-TYPE:"dl:contact"', + '-TYPE:"dl:eventAgenda"', + '-TYPE:"dl:event"', + '-TYPE:"dl:task"', + '-TYPE:"dl:simpletask"', + '-TYPE:"dl:meetingAgenda"', + '-TYPE:"dl:location"', + '-TYPE:"fm:topic"', + '-TYPE:"fm:post"', + '-TYPE:"ia:calendarEvent"', + '-TYPE:"lnk:link"' + ]; + return new Observable((observer) => { this.apiService.peopleApi.getPerson(personId) .then((person: PersonEntry) => { const username = person.entry.id; + const filterQueries = [ + { query: `cm:modified:[NOW/DAY-30DAYS TO NOW/DAY+1DAY]` }, + { query: `cm:modifier:${username} OR cm:creator:${username}` }, + { query: defaultFilter.join(' AND ') } + ]; + + if (filters && filters.length > 0) { + filterQueries.push({ + query: filters.join() + }); + } + const query: SearchRequest = new SearchRequest({ query: { query: '*', language: 'afts' }, - filterQueries: [ - { query: `cm:modified:[NOW/DAY-30DAYS TO NOW/DAY+1DAY]` }, - { query: `cm:modifier:${username} OR cm:creator:${username}` }, - { query: `TYPE:"content" AND -TYPE:"app:filelink" AND -TYPE:"fm:post"` } - ], + filterQueries, include: ['path', 'properties', 'allowableOperations'], sort: [{ type: 'FIELD', From 8975d4b6a654871e235007d8a3f51b07da1b5f82 Mon Sep 17 00:00:00 2001 From: Cilibiu Bogdan <pionnegru@users.noreply.github.com> Date: Wed, 10 Apr 2019 18:30:50 +0300 Subject: [PATCH 088/208] [ADF-4371] Versioning - revert upload version on delete (#4572) * revert upload version on delete * methods return type --- .../upload/remove-upload.e2e.ts | 101 +++++++++++ lib/content-services/i18n/en.json | 3 +- .../file-uploading-list-row.component.html | 12 +- .../file-uploading-list-row.component.spec.ts | 37 ++-- .../file-uploading-list-row.component.ts | 22 +++ .../file-uploading-list.component.spec.ts | 28 ++- .../file-uploading-list.component.ts | 161 ++++++++++++------ lib/core/services/thumbnail.service.ts | 1 + 8 files changed, 300 insertions(+), 65 deletions(-) create mode 100644 e2e/content-services/upload/remove-upload.e2e.ts diff --git a/e2e/content-services/upload/remove-upload.e2e.ts b/e2e/content-services/upload/remove-upload.e2e.ts new file mode 100644 index 0000000000..60100b4fb4 --- /dev/null +++ b/e2e/content-services/upload/remove-upload.e2e.ts @@ -0,0 +1,101 @@ +/*! + * @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 { LoginPage } from '@alfresco/adf-testing'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; +import { VersionManagePage } from '../../pages/adf/versionManagerPage'; + +import { AcsUserModel } from '../../models/ACS/acsUserModel'; +import { FileModel } from '../../models/ACS/fileModel'; + +import TestConfig = require('../../test.config'); +import resources = require('../../util/resources'); + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { browser } from 'protractor'; + +describe('Upload component', () => { + const contentServicesPage = new ContentServicesPage(); + const uploadDialog = new UploadDialog(); + const versionManagePage = new VersionManagePage(); + const loginPage = new LoginPage(); + const acsUser = new AcsUserModel(); + + const docxFileModel = new FileModel({ + name: resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_name, + location: resources.Files.ADF_DOCUMENTS.DOCX_SUPPORTED.file_location + }); + + const fileModelVersion = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + beforeAll(async (done) => { + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login( + TestConfig.adf.adminEmail, + TestConfig.adf.adminPassword + ); + + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + + contentServicesPage.goToDocumentList(); + + done(); + }); + + beforeEach(() => { + contentServicesPage.goToDocumentList(); + }); + + it('should remove uploaded file', () => { + contentServicesPage.uploadFile(docxFileModel.location); + uploadDialog.fileIsUploaded(docxFileModel.name); + uploadDialog + .removeUploadedFile(docxFileModel.name) + .fileIsCancelled(docxFileModel.name) + .clickOnCloseButton(); + }); + + it('should revert to last version when remove uploaded version file', () => { + contentServicesPage.uploadFile(docxFileModel.location); + uploadDialog.fileIsUploaded(docxFileModel.name); + contentServicesPage.checkContentIsDisplayed(docxFileModel.name); + + contentServicesPage.versionManagerContent(docxFileModel.name); + versionManagePage.showNewVersionButton.click(); + versionManagePage.uploadNewVersionFile( + fileModelVersion.location + ); + versionManagePage.closeVersionDialog(); + uploadDialog + .removeUploadedFile(fileModelVersion.name) + .fileIsCancelled(fileModelVersion.name); + browser.refresh(); + contentServicesPage.checkContentIsDisplayed(docxFileModel.name); + }); +}); diff --git a/lib/content-services/i18n/en.json b/lib/content-services/i18n/en.json index 17022cb032..bfbfd692ae 100644 --- a/lib/content-services/i18n/en.json +++ b/lib/content-services/i18n/en.json @@ -161,7 +161,8 @@ "500": "Internal server error, try again or contact IT support [500]", "504": "The server timed out, try again or contact IT support [504]", "403": "Insufficient permissions to upload in this location [403]", - "404": "Upload location no longer exists [404]" + "404": "Upload location no longer exists [404]", + "409": "A file with the same name already exists [409]" }, "ARIA-LABEL": { "ERROR": "Upload error" diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.html b/lib/content-services/upload/components/file-uploading-list-row.component.html index 192491d5d3..1a50d171d2 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.html +++ b/lib/content-services/upload/components/file-uploading-list-row.component.html @@ -1,16 +1,22 @@ <div class="adf-file-uploading-row"> - <mat-icon - mat-list-icon - class="adf-file-uploading-row__type"> + <mat-icon *ngIf="mimeType === 'default'" mat-list-icon class="adf-file-uploading-row__type"> insert_drive_file </mat-icon> + <adf-icon *ngIf="mimeType !== 'default'" value="adf:{{ mimeType }}"></adf-icon> + <span class="adf-file-uploading-row__name" title="{{ file.name }}"> {{ file.name }} </span> + <span *ngIf="isUploadVersion()" class="adf-file-uploading-row__version"> + <mat-chip aria-label="file version" color="primary" disabled>{{ + versionNumber + }}</mat-chip> + </span> + <div *ngIf="file.status === FileUploadStatus.Progress || file.status === FileUploadStatus.Starting" (click)="onCancel(file)" diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts b/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts index 97460b2e79..71182fd38d 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts +++ b/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts @@ -16,7 +16,7 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FileModel, CoreModule } from '@alfresco/adf-core'; +import { FileModel, CoreModule, FileUploadOptions } from '@alfresco/adf-core'; import { UploadModule } from '../upload.module'; import { FileUploadingListRowComponent } from './file-uploading-list-row.component'; @@ -37,20 +37,37 @@ describe('FileUploadingListRowComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(FileUploadingListRowComponent); component = fixture.componentInstance; - component.file = file; }); - it('emits cancel event', () => { - spyOn(component.cancel, 'emit'); - component.onCancel(component.file); + describe('events', () => { + beforeEach(() => { + component.file = file; + }); - expect(component.cancel.emit).toHaveBeenCalledWith(file); + it('should emit cancel event', () => { + spyOn(component.cancel, 'emit'); + component.onCancel(component.file); + + expect(component.cancel.emit).toHaveBeenCalledWith(file); + }); + + it('should emit remove event', () => { + spyOn(component.remove, 'emit'); + component.onRemove(component.file); + + expect(component.remove.emit).toHaveBeenCalledWith(file); + }); }); - it('emits remove event', () => { - spyOn(component.remove, 'emit'); - component.onRemove(component.file); + it('should render node version when upload a version file', () => { + component.file = new FileModel(<File> { name: 'fake-name' }); + component.file.options = <FileUploadOptions> { newVersion: true }; + component.file.data = { entry: { properties: { 'cm:versionLabel': '1' } } }; - expect(component.remove.emit).toHaveBeenCalledWith(file); + fixture.detectChanges(); + + expect(fixture.nativeElement.querySelector( + '.adf-file-uploading-row__version' + ).textContent).toContain('1'); }); }); diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.ts b/lib/content-services/upload/components/file-uploading-list-row.component.ts index 04ce69ad89..4ab520c834 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.ts +++ b/lib/content-services/upload/components/file-uploading-list-row.component.ts @@ -48,4 +48,26 @@ export class FileUploadingListRowComponent { this.file.status === FileUploadStatus.Aborted || this.file.status === FileUploadStatus.Deleted; } + + get versionNumber(): string { + return this.file.data.entry.properties['cm:versionLabel']; + } + + get mimeType(): string { + if (this.file && this.file.file && this.file.file.type) { + return this.file.file.type; + } + + return 'default'; + } + + isUploadVersion(): boolean { + return ( + !!this.file.data && + this.file.options && + this.file.options.newVersion && + this.file.data.entry.properties && + this.file.data.entry.properties['cm:versionLabel'] + ); + } } diff --git a/lib/content-services/upload/components/file-uploading-list.component.spec.ts b/lib/content-services/upload/components/file-uploading-list.component.spec.ts index 4afa46c18e..c2e5789511 100644 --- a/lib/content-services/upload/components/file-uploading-list.component.spec.ts +++ b/lib/content-services/upload/components/file-uploading-list.component.spec.ts @@ -17,7 +17,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TranslationService, FileUploadStatus, NodesApiService, UploadService, - setupTestBed, CoreModule, AlfrescoApiService, AlfrescoApiServiceMock + setupTestBed, CoreModule, AlfrescoApiService, AlfrescoApiServiceMock, FileModel, FileUploadOptions } from '@alfresco/adf-core'; import { of, throwError } from 'rxjs'; import { UploadModule } from '../upload.module'; @@ -30,6 +30,7 @@ describe('FileUploadingListComponent', () => { let uploadService: UploadService; let nodesApiService: NodesApiService; let translateService: TranslationService; + let alfrescoApiService: AlfrescoApiService; let file: any; beforeEach(() => { @@ -55,6 +56,7 @@ describe('FileUploadingListComponent', () => { translateService = TestBed.get(TranslationService); fixture = TestBed.createComponent(FileUploadingListComponent); + alfrescoApiService = TestBed.get(AlfrescoApiService); component = fixture.componentInstance; spyOn(translateService, 'get').and.returnValue(of('some error message')); @@ -106,6 +108,30 @@ describe('FileUploadingListComponent', () => { expect(uploadService.cancelUpload).toHaveBeenCalled(); }); + it('should delete node version', () => { + spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(of(file)); + file = new FileModel(<File> { name: 'fake-name' }); + file.options = <FileUploadOptions> { newVersion: true }; + file.data = { entry: { id: 'nodeId', properties: { 'cm:versionLabel': '1' } } }; + + component.removeFile(file); + + expect(alfrescoApiService.versionsApi.deleteVersion).toHaveBeenCalled(); + }); + + it('should throw error when delete node version fails', (done) => { + spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(throwError(file)); + file = new FileModel(<File> { name: 'fake-name' }); + file.options = <FileUploadOptions> { newVersion: true }; + file.data = { entry: { id: 'nodeId', properties: { 'cm:versionLabel': '1' } } }; + + component.error.subscribe(() => { + done(); + }); + + component.removeFile(file); + }); + describe('Events', () => { it('should throw an error event if delete file goes wrong', (done) => { diff --git a/lib/content-services/upload/components/file-uploading-list.component.ts b/lib/content-services/upload/components/file-uploading-list.component.ts index 054aa03a3c..c1954a11c8 100644 --- a/lib/content-services/upload/components/file-uploading-list.component.ts +++ b/lib/content-services/upload/components/file-uploading-list.component.ts @@ -15,9 +15,23 @@ * limitations under the License. */ -import { FileModel, FileUploadStatus, NodesApiService, TranslationService, UploadService } from '@alfresco/adf-core'; -import { Component, ContentChild, Input, Output, TemplateRef, EventEmitter } from '@angular/core'; -import { Observable, forkJoin, of } from 'rxjs'; +import { + FileModel, + FileUploadStatus, + NodesApiService, + AlfrescoApiService, + TranslationService, + UploadService +} from '@alfresco/adf-core'; +import { + Component, + ContentChild, + Input, + Output, + TemplateRef, + EventEmitter +} from '@angular/core'; +import { Observable, forkJoin, of, from } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; @Component({ @@ -26,7 +40,6 @@ import { map, catchError } from 'rxjs/operators'; styleUrls: ['./file-uploading-list.component.scss'] }) export class FileUploadingListComponent { - FileUploadStatus = FileUploadStatus; @ContentChild(TemplateRef) @@ -40,10 +53,11 @@ export class FileUploadingListComponent { error: EventEmitter<any> = new EventEmitter(); constructor( + private alfrescoApiService: AlfrescoApiService, private uploadService: UploadService, private nodesApi: NodesApiService, - private translateService: TranslationService) { - } + private translateService: TranslationService + ) {} /** * Cancel file upload @@ -56,100 +70,147 @@ export class FileUploadingListComponent { this.uploadService.cancelUpload(file); } + /** + * Remove uploaded file + * + * @param file File model to remove upload for. + * + * @memberOf FileUploadingListComponent + */ removeFile(file: FileModel): void { - this.deleteNode(file) - .subscribe(() => { - if ( file.status === FileUploadStatus.Error) { + if (file.options && file.options.newVersion) { + this.deleteNodeVersion(file).subscribe(() => { + if (file.status === FileUploadStatus.Error) { + this.notifyError(file); + } + this.uploadService.cancelUpload(file); + }); + } else { + this.deleteNode(file).subscribe(() => { + if (file.status === FileUploadStatus.Error) { this.notifyError(file); } + this.cancelNodeVersionInstances(file); this.uploadService.cancelUpload(file); }); + } } /** * Call the appropriate method for each file, depending on state */ cancelAllFiles(): void { - this.getUploadingFiles() - .forEach((file) => this.uploadService.cancelUpload(file)); + this.getUploadingFiles().forEach((file) => + this.uploadService.cancelUpload(file) + ); const deletedFiles = this.files .filter((file) => file.status === FileUploadStatus.Complete) .map((file) => this.deleteNode(file)); - forkJoin(...deletedFiles) - .subscribe((files: FileModel[]) => { - const errors = files - .filter((file) => file.status === FileUploadStatus.Error); + forkJoin(...deletedFiles).subscribe((files: FileModel[]) => { + const errors = files.filter( + (file) => file.status === FileUploadStatus.Error + ); - if (errors.length) { - this.notifyError(...errors); - } + if (errors.length) { + this.notifyError(...errors); + } - this.uploadService.cancelUpload(...files); - }); + this.uploadService.cancelUpload(...files); + }); } /** * Checks if all the files are uploaded false if there is at least one file in Progress | Starting | Pending */ isUploadCompleted(): boolean { - return !this.isUploadCancelled() && + return ( + !this.isUploadCancelled() && Boolean(this.files.length) && - !this.files - .some(({status}) => + !this.files.some( + ({ status }) => status === FileUploadStatus.Starting || status === FileUploadStatus.Progress || status === FileUploadStatus.Pending - ); + ) + ); } /** * Check if all the files are Cancelled | Aborted | Error. false if there is at least one file in uploading states */ isUploadCancelled(): boolean { - return !!this.files.length && - this.files - .every(({status}) => + return ( + !!this.files.length && + this.files.every( + ({ status }) => status === FileUploadStatus.Aborted || status === FileUploadStatus.Cancelled || status === FileUploadStatus.Deleted - ); + ) + ); } private deleteNode(file: FileModel): Observable<FileModel> { const { id } = file.data.entry; - return this.nodesApi - .deleteNode(id, { permanent: true }) - .pipe( - map(() => { - file.status = FileUploadStatus.Deleted; - return file; - }), - catchError(() => { - file.status = FileUploadStatus.Error; - return of(file); - }) - ); + return this.nodesApi.deleteNode(id, { permanent: true }).pipe( + map(() => { + file.status = FileUploadStatus.Deleted; + return file; + }), + catchError(() => { + file.status = FileUploadStatus.Error; + return of(file); + }) + ); + } + + private deleteNodeVersion(file: FileModel): Observable<FileModel> { + return from( + this.alfrescoApiService.versionsApi.deleteVersion( + file.data.entry.id, + file.data.entry.properties['cm:versionLabel'] + ) + ).pipe( + map(() => { + file.status = FileUploadStatus.Deleted; + return file; + }), + catchError(() => { + file.status = FileUploadStatus.Error; + return of(file); + }) + ); + } + + private cancelNodeVersionInstances(file) { + this.files + .filter( + (item) => + item.data.entry.id === file.data.entry.id && + item.options.newVersion + ) + .map((item) => { + item.status = FileUploadStatus.Deleted; + }); } private notifyError(...files: FileModel[]) { let messageError: string = null; if (files.length === 1) { - messageError = this.translateService - .instant( - 'FILE_UPLOAD.MESSAGES.REMOVE_FILE_ERROR', - { fileName: files[0].name} - ); + messageError = this.translateService.instant( + 'FILE_UPLOAD.MESSAGES.REMOVE_FILE_ERROR', + { fileName: files[0].name } + ); } else { - messageError = this.translateService - .instant( - 'FILE_UPLOAD.MESSAGES.REMOVE_FILES_ERROR', - { total: files.length } - ); + messageError = this.translateService.instant( + 'FILE_UPLOAD.MESSAGES.REMOVE_FILES_ERROR', + { total: files.length } + ); } this.error.emit(messageError); diff --git a/lib/core/services/thumbnail.service.ts b/lib/core/services/thumbnail.service.ts index e211e1e163..eb7e181a33 100644 --- a/lib/core/services/thumbnail.service.ts +++ b/lib/core/services/thumbnail.service.ts @@ -84,6 +84,7 @@ export class ThumbnailService { 'application/vnd.sun.xml.writer': './assets/images/ft_ic_ms_word.svg', 'application/vnd.sun.xml.writer.template': './assets/images/ft_ic_ms_word.svg', 'application/rtf': './assets/images/ft_ic_ms_word.svg', + 'text/rtf': './assets/images/ft_ic_ms_word.svg', 'application/vnd.ms-powerpoint': './assets/images/ft_ic_ms_powerpoint.svg', 'application/vnd.openxmlformats-officedocument.presentationml.presentation': './assets/images/ft_ic_ms_powerpoint.svg', 'application/vnd.openxmlformats-officedocument.presentationml.template': './assets/images/ft_ic_ms_powerpoint.svg', From ed32cf421eb0072d00f47e588acbd185117d990c Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 10 Apr 2019 16:41:29 +0100 Subject: [PATCH 089/208] fix next beta script --- scripts/next_version.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/next_version.sh b/scripts/next_version.sh index 3033a801f3..d84ae9f89c 100755 --- a/scripts/next_version.sh +++ b/scripts/next_version.sh @@ -87,8 +87,7 @@ then BETA_VERSION=$(npm view @alfresco/adf-core@beta version) if [[ $BETA_VERSION == "" ]]; then - NEXT_BETA_VERSION=1 - NEXT_VERSION=${NEXT_VERSION}-beta${NEXT_BETA_VERSION} + NEXT_BETA_VERSION=0 else NEXT_BETA_VERSION=( ${BETA_VERSION//-beta/ } ) @@ -100,10 +99,19 @@ then if [[ ${NEXT_BETA_VERSION[1]} == "" ]]; then NEXT_BETA_VERSION[1]=0 fi - - ((NEXT_BETA_VERSION[1]++)) - NEXT_VERSION=${NEXT_VERSION}-beta${NEXT_BETA_VERSION[1]} fi + + while + ((NEXT_BETA_VERSION[1]++)) + + NPM_VIEW="npm view @alfresco/adf-core@${NEXT_VERSION}-beta${NEXT_BETA_VERSION[1]} version" + + NEXT_POSSIBLE_VERSION=$(${NPM_VIEW}) + [ "$NEXT_POSSIBLE_VERSION" != "" ] + do :; done + + NEXT_VERSION=${NEXT_VERSION}-beta${NEXT_BETA_VERSION[1]} + fi echo $NEXT_VERSION From 1eea972d6ccc115d6c45e0d2cf4326d2492d8947 Mon Sep 17 00:00:00 2001 From: Marouan Bentaleb <38426175+marouanbentaleb@users.noreply.github.com> Date: Wed, 10 Apr 2019 16:50:46 +0100 Subject: [PATCH 090/208] [ADF-4373] Automation test for accurate error messages (#4581) --- e2e/core/error-component.e2e.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/e2e/core/error-component.e2e.ts b/e2e/core/error-component.e2e.ts index 7dc52fb019..c5092265df 100644 --- a/e2e/core/error-component.e2e.ts +++ b/e2e/core/error-component.e2e.ts @@ -66,11 +66,18 @@ describe('Error Component', () => { expect(browser.getCurrentUrl()).toBe(TestConfig.adf.url + '/report-issue'); }); - it('[C277304] We couldn’t find the page you were looking for.\' to be \'You\'re not allowed access to this resource on the server.', () => { + it('[C277304] Should display the error 404 when access to not found page', () => { browser.get(TestConfig.adf.url + '/error/404'); expect(errorPage.getErrorCode()).toBe('404'); expect(errorPage.getErrorTitle()).toBe('An error occurred.'); expect(errorPage.getErrorDescription()).toBe('We couldn’t find the page you were looking for.'); }); + it('[C307029] Should display Unknown message when error is undefined', () => { + browser.get(TestConfig.adf.url + '/error/501'); + expect(errorPage.getErrorCode()).toBe('UNKNOWN'); + expect(errorPage.getErrorTitle()).toBe('We hit a problem.'); + expect(errorPage.getErrorDescription()).toBe('Looks like something went wrong.'); + }); + }); From 61ee1f1d532c8d03f2b4e57abd5c6bb7432b4350 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Wed, 10 Apr 2019 19:03:55 +0300 Subject: [PATCH 091/208] [ADF-4386] - fix style and remove value from tooltip (#4587) --- .../components/document-list.component.scss | 10 --------- lib/core/clipboard/clipboard.directive.ts | 21 ++++++------------- .../datatable/datatable.component.scss | 11 ++++++++++ 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/lib/content-services/document-list/components/document-list.component.scss b/lib/content-services/document-list/components/document-list.component.scss index 162c452e22..e7ef29c265 100644 --- a/lib/content-services/document-list/components/document-list.component.scss +++ b/lib/content-services/document-list/components/document-list.component.scss @@ -188,14 +188,4 @@ } } } - - .adf-datatable-copy-tooltip { - position: absolute; - background: mat-color($primary); - color: mat-color($primary, default-contrast) !important; - padding: 5px 10px; - border-radius: 5px; - bottom: 88%; - left:0; - } } diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index 0ede53291b..8ca6d16f6e 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -15,14 +15,14 @@ * limitations under the License. */ -import { Directive, Input, HostListener, Component, ViewContainerRef, ComponentFactoryResolver, AfterContentInit } from '@angular/core'; +import { Directive, Input, HostListener, Component, ViewContainerRef, ComponentFactoryResolver, ViewEncapsulation } from '@angular/core'; import { ClipboardService } from './clipboard.service'; @Directive({ selector: '[adf-clipboard]', exportAs: 'adfClipboard' }) -export class ClipboardDirective implements AfterContentInit { +export class ClipboardDirective { // tslint:disable-next-line:no-input-rename @Input('adf-clipboard') placeholder: string; @@ -33,8 +33,6 @@ export class ClipboardDirective implements AfterContentInit { // tslint:disable-next-line:no-input-rename @Input('clipboard-notification') message: string; - private value: string; - constructor(private clipboardService: ClipboardService, public viewContainerRef: ViewContainerRef, private resolver: ComponentFactoryResolver) {} @@ -50,7 +48,6 @@ export class ClipboardDirective implements AfterContentInit { showTooltip() { const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; - componentRef.copyText = this.value; componentRef.placeholder = this.placeholder; } @@ -72,21 +69,15 @@ export class ClipboardDirective implements AfterContentInit { private copyContentToClipboard(content) { this.clipboardService.copyContentToClipboard(content, this.message); } - - ngAfterContentInit() { - setTimeout( () => { - this.value = this.viewContainerRef.element.nativeElement.innerHTML; - }); - } } @Component({ - selector: 'adf-datatable-highlight-tooltip', + selector: 'adf-datatable-copy-content-tooltip', template: ` - <span class='adf-datatable-copy-tooltip'>{{ placeholder | translate }} <b> {{ copyText }} </b></span> - ` + <span class='adf-datatable-copy-tooltip'>{{ placeholder | translate }} </span> + `, + encapsulation: ViewEncapsulation.None }) export class ClipboardComponent { - copyText: string; placeholder: string; } diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index 82899d0c33..7df1810b4e 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -557,4 +557,15 @@ } } } + + .adf-datatable-copy-tooltip { + position: absolute; + background: mat-color($primary); + color: mat-color($primary, default-contrast) !important; + padding: 5px 10px; + border-radius: 5px; + bottom: 94%; + left:0; + z-index: 20; + } } From 558ee4c031cd7fd885c135b27bc1b6b673fc3359 Mon Sep 17 00:00:00 2001 From: Deepak Paul <deepak.paul@muraai.com> Date: Wed, 10 Apr 2019 21:40:56 +0530 Subject: [PATCH 092/208] [ADF-3797] Task management view - Task with Form (#4534) * [ADF-4248] Created form cloud service * [ADF-4248] Created form cloud model * [ADF-4248] Created new cloud form * [ADF-4248] Exported cloud from module * [ADF-4248] Added form saving feature * [ADF-4248] Added form to task details * [ADF-4248] Added services to save form * [ADF-4248] Added data support * [ADF-4248] Added outcome support in form model * [ADF-4248] Modified demo component to show form * [ADF-4248] Copied tests * [ADF-4248] Added form parsing service * [ADF-4248] Added form cloud demo * [ADF-4248] Added form input to fom-cloud * [ADF-4248] Added tests for form cloud model * [ADF-4248] Improved form model json parsing * [ADF-4248] Added test for form could * [ADF-4248] Refactored types in the form model * [ADF-4248] Improved tests * [ADF-4248] Added tests for form cloud service * [ADF-4248] Added tests for form services * [ADF-4248] Refactored form services * [ADF-4248] Handled form events in demo shell * [ADF-4248] Improved form value parsing * [ADF-4248] Added form-cloud demo to routing * [ADF-4248] Added field validation without handler * [ADF-4248] Added task variable model * [ADF-4248] Added adf-cloud prefix to css classes * [ADF-4248] Translated name of nameless task * [ADF-4248] Added docs for cloud form component * [ADF-4248] Added docs for cloud form service * create base component * [ADF-4248] Created formBase and formModelbase * [ADF-4248] Used base classes in cloud package * Update form-cloud.component.md * Update form-cloud.service.md * [ADF-4248] Created form cloud service * [ADF-4248] Created form cloud model * [ADF-4248] Created new cloud form * [ADF-4248] Exported cloud from module * [ADF-4248] Added form saving feature * [ADF-4248] Added form to task details * [ADF-4248] Added services to save form * [ADF-4248] Added data support * [ADF-4248] Added outcome support in form model * [ADF-4248] Modified demo component to show form * [ADF-4248] Copied tests * [ADF-4248] Added form parsing service * [ADF-4248] Added form cloud demo * [ADF-4248] Added form input to fom-cloud * [ADF-4248] Added tests for form cloud model * [ADF-4248] Improved form model json parsing * [ADF-4248] Added test for form could * [ADF-4248] Refactored types in the form model * [ADF-4248] Improved tests * [ADF-4248] Added tests for form cloud service * [ADF-4248] Added tests for form services * [ADF-4248] Refactored form services * [ADF-4248] Handled form events in demo shell * [ADF-4248] Improved form value parsing * [ADF-4248] Added form-cloud demo to routing * [ADF-4248] Added field validation without handler * [ADF-4248] Added task variable model * [ADF-4248] Added adf-cloud prefix to css classes * [ADF-4248] Translated name of nameless task * [ADF-4248] Added docs for cloud form component * [ADF-4248] Added docs for cloud form service * create base component * [ADF-4248] Created formBase and formModelbase * [ADF-4248] Used base classes in cloud package * [ADF-4248] Moved documentation to process services * [ADF-4248] Removed duplicate import * [ADF-4248] Fixed wrong imports * [ADF-4248] Renamed form renderer input * [ADF-4248] Show translated name for nameless form * Enable the uploadWidget * Make the form great again! * Move the class style on the parent * Fix the debugMode --- demo-shell/proxy.conf.js | 2 +- demo-shell/src/app/app.module.ts | 10 +- demo-shell/src/app/app.routes.ts | 2 + .../app-layout/app-layout.component.ts | 1 + .../form-demo/cloud-form-demo.component.html | 56 ++ .../form-demo/cloud-form-demo.component.scss | 57 ++ .../form-demo/cloud-form-demo.component.ts | 109 +++ .../app-layout/cloud/form-demo/demo-form.ts | 96 +++ .../task-details-cloud-demo.component.html | 43 +- .../task-details-cloud-demo.component.ts | 23 +- .../components/form/form-list.component.ts | 3 +- .../app/services/in-memory-form.service.ts | 2 +- docs/docassets/demo-cloud.form.json | 665 ++++++++++++++++ .../components/form-cloud.component.md | 262 ++++++ .../services/form-cloud.service.md | 67 ++ .../components/form.component.md | 16 +- lib/core/core.module.ts | 6 +- .../form/components/form-base.component.ts | 213 +++++ lib/core/form/components/form-base.model.ts | 84 ++ .../components/form-renderer.component.html | 25 + ...nent.scss => form-renderer.component.scss} | 2 +- .../components/form-renderer.component.ts | 38 + lib/core/form/components/form.component.html | 64 -- .../widgets/core/form-widget.model.ts | 2 +- .../components/widgets/core/form.model.ts | 54 +- .../{form.module.ts => form-base.module.ts} | 11 +- lib/core/form/public-api.ts | 6 +- lib/core/form/services/form.service.ts | 2 +- lib/core/i18n/en.json | 3 + .../pagination/pagination.component.spec.ts | 2 +- lib/core/styles/_index.scss | 4 +- .../form/components/form-cloud.component.html | 46 ++ .../components/form-cloud.component.spec.ts | 753 ++++++++++++++++++ .../form/components/form-cloud.component.ts | 296 +++++++ .../form/components/upload-cloud.widget.html | 40 + .../form/components/upload-cloud.widget.scss | 0 .../form/components/upload-cloud.widget.ts | 135 ++++ .../src/lib/form/form-cloud.module.ts | 47 ++ .../src/lib/form/mocks/cloud-form.mock.ts | 686 ++++++++++++++++ .../lib/form/models/form-cloud.model.spec.ts | 233 ++++++ .../src/lib/form/models/form-cloud.model.ts | 247 ++++++ .../form/models/task-variable-cloud.model.ts | 25 + .../src/lib/form/public-api.ts | 22 + .../form/services/form-cloud.service.spec.ts | 162 ++++ .../lib/form/services/form-cloud.service.ts | 232 ++++++ .../src/lib/group/group-cloud.module.ts | 3 +- .../src/lib/process-services-cloud.module.ts | 7 +- .../src/lib/process/process-cloud.module.ts | 2 +- .../process-header-cloud.component.ts | 2 +- .../services/process-header-cloud.service.ts | 2 +- .../components/start-task-cloud.component.ts | 2 +- .../start-task/start-task-cloud.module.ts | 3 +- .../start-task-cloud.testing.module.ts | 3 +- lib/process-services-cloud/src/public-api.ts | 1 + lib/process-services/form/form.component.html | 46 ++ .../form}/form.component.spec.ts | 22 +- .../form}/form.component.ts | 251 +----- .../form}/form.component.visibility.spec.ts | 13 +- lib/process-services/form/form.module.ts | 38 + lib/process-services/form/index.ts | 18 + lib/process-services/form/public-api.ts | 20 + .../form}/start-form.component.html | 0 .../form/start-form.component.scss | 125 +++ .../form}/start-form.component.spec.ts | 13 +- .../form}/start-form.component.ts | 13 +- lib/process-services/index.ts | 1 + ...process-instance-details.component.spec.ts | 3 +- .../components/start-process.component.ts | 9 +- .../process-list/process-list.module.ts | 4 +- lib/process-services/process.module.ts | 7 +- lib/process-services/styles/_index.scss | 4 +- .../no-task-detail-template.directive.spec.ts | 4 +- .../components/task-details.component.html | 1 - .../components/task-details.component.ts | 5 - .../task-list/task-list.module.ts | 2 + .../actions/process-instances.service.ts | 1 + 76 files changed, 5029 insertions(+), 450 deletions(-) create mode 100644 demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html create mode 100644 demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.scss create mode 100644 demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts create mode 100644 demo-shell/src/app/components/app-layout/cloud/form-demo/demo-form.ts create mode 100644 docs/docassets/demo-cloud.form.json create mode 100644 docs/process-services-cloud/components/form-cloud.component.md create mode 100644 docs/process-services-cloud/services/form-cloud.service.md rename docs/{core => process-services}/components/form.component.md (94%) create mode 100644 lib/core/form/components/form-base.component.ts create mode 100644 lib/core/form/components/form-base.model.ts create mode 100644 lib/core/form/components/form-renderer.component.html rename lib/core/form/components/{form.component.scss => form-renderer.component.scss} (98%) create mode 100644 lib/core/form/components/form-renderer.component.ts delete mode 100644 lib/core/form/components/form.component.html rename lib/core/form/{form.module.ts => form-base.module.ts} (90%) create mode 100644 lib/process-services-cloud/src/lib/form/components/form-cloud.component.html create mode 100644 lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts create mode 100644 lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts create mode 100644 lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html create mode 100644 lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss create mode 100644 lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts create mode 100644 lib/process-services-cloud/src/lib/form/form-cloud.module.ts create mode 100644 lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts create mode 100644 lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts create mode 100644 lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts create mode 100644 lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts create mode 100644 lib/process-services-cloud/src/lib/form/public-api.ts create mode 100644 lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts create mode 100644 lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts create mode 100644 lib/process-services/form/form.component.html rename lib/{core/form/components => process-services/form}/form.component.spec.ts (97%) rename lib/{core/form/components => process-services/form}/form.component.ts (60%) rename lib/{core/form/components => process-services/form}/form.component.visibility.spec.ts (96%) create mode 100644 lib/process-services/form/form.module.ts create mode 100644 lib/process-services/form/index.ts create mode 100644 lib/process-services/form/public-api.ts rename lib/{core/form/components => process-services/form}/start-form.component.html (100%) create mode 100644 lib/process-services/form/start-form.component.scss rename lib/{core/form/components => process-services/form}/start-form.component.spec.ts (98%) rename lib/{core/form/components => process-services/form}/start-form.component.ts (92%) diff --git a/demo-shell/proxy.conf.js b/demo-shell/proxy.conf.js index 7da0babb2f..eaa6a59bb1 100644 --- a/demo-shell/proxy.conf.js +++ b/demo-shell/proxy.conf.js @@ -1,6 +1,6 @@ module.exports = { "/alfresco": { - "target": "http://localhost:8080", + "target": "http://aps2staging.envalfresco.com", "secure": false, "pathRewrite": { "^/alfresco/alfresco": "" diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 2b06d1f38c..14dd77cee5 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -64,7 +64,7 @@ import { ContentModule } from '@alfresco/adf-content-services'; import { InsightsModule } from '@alfresco/adf-insights'; import { ProcessModule } from '@alfresco/adf-process-services'; import { AuthBearerInterceptor } from './services'; -import { ProcessServicesCloudModule, GroupCloudModule, TaskDirectiveModule } from '@alfresco/adf-process-services-cloud'; +import { ProcessServicesCloudModule } from '@alfresco/adf-process-services-cloud'; import { AppExtensionsModule } from './app-extension.module'; import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component'; import { CloudLayoutComponent } from './components/cloud/cloud-layout.component'; @@ -82,6 +82,7 @@ import { PeopleGroupCloudDemoComponent } from './components/cloud/people-groups- import { CloudSettingsComponent } from './components/cloud/cloud-settings.component'; import { NestedMenuPositionDirective } from './components/cloud/directives/nested-menu-position.directive'; import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component'; +import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component'; @NgModule({ imports: [ @@ -102,10 +103,7 @@ import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confi ExtensionsModule.forRoot(), ThemePickerModule, ChartsModule, - MonacoEditorModule.forRoot(), - ProcessServicesCloudModule, - GroupCloudModule, - TaskDirectiveModule + MonacoEditorModule.forRoot() ], declarations: [ AppComponent, @@ -150,6 +148,8 @@ import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confi PeopleGroupCloudDemoComponent, CloudSettingsComponent, NestedMenuPositionDirective, + ConfirmDialogExampleComponent, + FormCloudDemoComponent, ConfirmDialogExampleComponent ], providers: [ diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index f3ab662b28..f2f14739e6 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -49,6 +49,7 @@ import { StartProcessCloudDemoComponent } from './components/cloud/start-process import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; import { TemplateDemoComponent } from './components/template-list/template-demo.component'; +import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component'; import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component'; export const appRoutes: Routes = [ @@ -355,6 +356,7 @@ export const appRoutes: Routes = [ path: 'icons', loadChildren: './components/icons/icons.module#AppIconsModule' }, + { path: 'form-cloud', component: FormCloudDemoComponent }, { path: 'form', component: FormComponent }, { path: 'form-list', component: FormListComponent }, { path: 'form-loading', component: FormLoadingComponent }, diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index e084b44383..d58c63290c 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -48,6 +48,7 @@ export class AppLayoutComponent implements OnInit { { href: '/task-list', icon: 'assignment', title: 'APP_LAYOUT.TASK_LIST' }, { href: '/cloud', icon: 'cloud', title: 'APP_LAYOUT.PROCESS_CLOUD', children: [ { href: '/cloud/', icon: 'cloud', title: 'APP_LAYOUT.HOME' }, + { href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' }, { href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' } ]}, { href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES', children: [ diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html new file mode 100644 index 0000000000..dfbfe67660 --- /dev/null +++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html @@ -0,0 +1,56 @@ +<div class="main-content"> + + <mat-tab-group> + <mat-tab label="Form"> + <div class="adf-form-container"> + <adf-cloud-form + [showRefreshButton]="false" + [form]="form" + (formSaved)="onFormSaved()" + (formError)="logErrors($event)"> + </adf-cloud-form> + </div> + + <div class="adf-console" #console> + <h3>Error log:</h3> + <p *ngFor="let error of errorFields">Error {{ error.name }} {{error.validationSummary.message | + translate}}</p> + </div> + </mat-tab> + <mat-tab label="Editor"> + <ngx-monaco-editor + id="adf-form-config-editor" + class="adf-form-config-editor" + [options]="editorOptions" + [(ngModel)]="formConfig" + (onInit)="onInitFormEditor($event)"> + </ngx-monaco-editor> + <div class="adf-form-editor-buttons"> + <button mat-raised-button id="adf-form-config-save" (click)="onSaveFormConfig()" color="primary">Save + form config + </button> + <button mat-raised-button id="adf-form-config-clear" (click)="onClearFormConfig()" color="primary">Clear + form config + </button> + </div> + <div class="adf-upload-config-button"> + <a mat-raised-button color="primary" > + <mat-icon>file_upload</mat-icon> + <label for="upload-config-file">Upload JSON File</label> + <input + id="upload-config-file" + data-automation-id="upload-single-file" + type="file" + name="uploadConfig" + accept=".json" + (change)="onConfigAdded($event)"> + </a> + </div> + + </mat-tab> + + </mat-tab-group> +</div> + + + diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.scss b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.scss new file mode 100644 index 0000000000..8dcba59cf8 --- /dev/null +++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.scss @@ -0,0 +1,57 @@ +.adf-form-container { + padding: 10px; +} + +.adf-main-content { + padding: 0 15px; +} + +.adf-card-view { + width: 30%; + display: inline-block; +} + +.adf-console { + width: 60%; + display: inline-block; + vertical-align: top; + margin-left: 10px; + height: 500px; + overflow: scroll; + padding-bottom: 30px; + + h3 { + margin-top: 0; + } + + p { + display: block; + font-family: monospace, monospace; + margin: 0; + } +} + +.adf-form-config-editor { + height: 500px !important; +} + +.adf-form-editor-buttons { + display: flex; + justify-content: space-evenly; +} + +.adf-upload-config-button { + display: flex; + justify-content: center; + + input { + cursor: pointer; + height: 100%; + right: 0; + opacity: 0; + position: absolute; + top: 0; + width: 300px; + z-index: 4; + } +} diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts new file mode 100644 index 0000000000..23e847942b --- /dev/null +++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts @@ -0,0 +1,109 @@ +/*! + * @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, OnDestroy, OnInit } from '@angular/core'; +import { FormFieldModel, NotificationService, FormRenderingService } from '@alfresco/adf-core'; +import { FormCloud, FormCloudService, UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; +import { Subscription } from 'rxjs'; +import { formDefinition } from './demo-form'; + +@Component({ + templateUrl: 'cloud-form-demo.component.html', + styleUrls: ['cloud-form-demo.component.scss'] +}) +export class FormCloudDemoComponent implements OnInit, OnDestroy { + + form: FormCloud; + errorFields: FormFieldModel[] = []; + formConfig: string; + editor: any; + private subscriptions: Subscription[] = []; + + editorOptions = { + theme: 'vs-dark', + language: 'json', + autoIndent: true, + formatOnPaste: true, + formatOnType: true, + automaticLayout: true + }; + + constructor( + private notificationService: NotificationService, + private formRenderingService: FormRenderingService, + private formService: FormCloudService) { + this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); + } + + logErrors(errorFields: FormFieldModel[]) { + this.errorFields = errorFields; + } + + ngOnInit() { + this.formConfig = formDefinition; + this.parseForm(); + } + + onFormSaved() { + this.notificationService.openSnackMessage('Task has been saved successfully'); + } + + ngOnDestroy() { + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); + this.subscriptions = []; + } + + onInitFormEditor(editor) { + this.editor = editor; + setTimeout(() => { + this.editor.getAction('editor.action.formatDocument').run(); + }, 1000); + } + + parseForm() { + this.form = this.formService.parseForm(JSON.parse(this.formConfig)); + } + + onSaveFormConfig() { + try { + this.parseForm(); + } catch (error) { + this.notificationService.openSnackMessage( + 'Wrong form configuration', + 4000 + ); + } + } + + onClearFormConfig() { + this.formConfig = ''; + } + + onConfigAdded($event: any): void { + const file = $event.currentTarget.files[0]; + + const fileReader = new FileReader(); + fileReader.onload = () => { + this.formConfig = <string> fileReader.result; + }; + fileReader.readAsText(file); + + this.onInitFormEditor(this.editor); + + $event.target.value = ''; + } +} diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/demo-form.ts b/demo-shell/src/app/components/app-layout/cloud/form-demo/demo-form.ts new file mode 100644 index 0000000000..0262f0bc7d --- /dev/null +++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/demo-form.ts @@ -0,0 +1,96 @@ +/*! + * @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. + */ + +export const formDefinition = `{ + "formRepresentation": { + "id": "text-form", + "name": "test-start-form", + "version": 0, + "description": "", + "formDefinition": { + "tabs": [], + "fields": [ + { + "id": "1511517333638", + "type": "container", + "fieldType": "ContainerRepresentation", + "name": "Label", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "texttest", + "name": "texttest", + "type": "text", + "value": null, + "required": false, + "placeholder": "text", + "params": { + "existingColspan": 2, + "maxColspan": 6, + "inputMaskReversed": true, + "inputMask": "0#", + "inputMaskPlaceholder": "(0-9)" + } + } + ], + "2": [{ + "fieldType": "AttachFileFieldRepresentation", + "id": "attachfiletest", + "name": "attachfiletest", + "type": "upload", + "required": true, + "colspan": 2, + "placeholder": "attachfile", + "params": { + "existingColspan": 2, + "maxColspan": 2, + "fileSource": { + "serviceId": "local-file", + "name": "Local File" + }, + "multiple": true, + "link": false + }, + "visibilityCondition": { + } + }] + } + } + ], + "outcomes": [], + "metadata": { + "property1": "value1", + "property2": "value2" + }, + "variables": [ + { + "name": "variable1", + "type": "string", + "value": "value1" + }, + { + "name": "variable2", + "type": "string", + "value": "value2" + } + ] + } + }} + `; diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html index 23a9dbcb61..b155b15ecf 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html @@ -1,19 +1,30 @@ <h4 data-automation-id="task-details-header">Simple page to show the taskId: {{ taskId }} of the app: {{ appName }}</h4> -<div class="adf-task-detail-container"> - <div class="adf-task-control"> - <button mat-button (click)="goBack()">Cancel</button> - <button mat-button color="primary" *ngIf="canCompleteTask()" adf-cloud-complete-task [appName]="appName" [taskId]="taskId" - (success)="onCompletedTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button> - - <button mat-button color="primary" *ngIf="canClaimTask()" adf-cloud-claim-task [appName]="appName" [taskId]="taskId" - (success)="onClaimTask()">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.CLAIM' | translate }}</button> - - <button mat-button color="primary" *ngIf="canUnClaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId" - (success)="onUnclaimTask()">{{ 'ADF_CLOUD_TASK_HEADER.BUTTON.RELEASE' | translate }}</button> +<div fxLayout="column" fxFill fxLayoutGap="2px"> + <div fxLayout="row" fxFill> + <div fxLayout="column" fxFlex="80%"> + <div class="adf-task-control"> + <button mat-button (click)="goBack()">Cancel</button> + <button mat-button color="primary" *ngIf="canCompleteTask()" adf-cloud-complete-task + (success)="onCompletedTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button> + + <button mat-button color="primary" *ngIf="canClaimTask()" adf-cloud-claim-task + (success)="onClaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.CLAIM' | translate }}</button> + + <button mat-button color="primary" *ngIf="canUnClaimTask()" adf-cloud-unclaim-task + (success)="onUnclaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.UNCLAIM' | translate }}</button> + </div> + <adf-cloud-form *ngIf="hasTaskForm()" fxFlex="100%" + [appName]="appName" + [taskId]="taskId" + (formCompleted)="onTaskCompleted()" + (formSaved)="onFormSaved()"> + </adf-cloud-form> + </div> + <adf-cloud-task-header fxFlex + [appName]="appName" + [taskId]="taskId" + [readOnly]="readOnly"> + </adf-cloud-task-header> </div> - - <adf-cloud-task-header class="adf-demop-card-container" [appName]="appName" [taskId]="taskId" [readOnly]="readOnly"> - </adf-cloud-task-header> - -</div> \ No newline at end of file +</div> diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts index 25f72933b2..95518ed986 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts @@ -17,7 +17,8 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { TaskDetailsCloudModel, TaskCloudService } from '@alfresco/adf-process-services-cloud'; +import { TaskDetailsCloudModel, TaskCloudService, UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; +import { NotificationService, FormRenderingService } from '@alfresco/adf-core'; @Component({ templateUrl: './task-details-cloud-demo.component.html', @@ -33,7 +34,9 @@ export class TaskDetailsCloudDemoComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, - private taskCloudService: TaskCloudService + private formRenderingService: FormRenderingService, + private taskCloudService: TaskCloudService, + private notificationService: NotificationService ) { this.route.params.subscribe((params) => { this.taskId = params.taskId; @@ -41,6 +44,8 @@ export class TaskDetailsCloudDemoComponent implements OnInit { this.route.parent.params.subscribe((params) => { this.appName = params.appName; }); + this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); + } ngOnInit() { @@ -59,7 +64,7 @@ export class TaskDetailsCloudDemoComponent implements OnInit { } canCompleteTask(): boolean { - return this.taskDetails && this.taskCloudService.canCompleteTask(this.taskDetails); + return this.taskDetails && !this.taskDetails.formKey && this.taskCloudService.canCompleteTask(this.taskDetails); } canClaimTask(): boolean { @@ -70,6 +75,10 @@ export class TaskDetailsCloudDemoComponent implements OnInit { return this.taskDetails && this.taskCloudService.canUnclaimTask(this.taskDetails); } + hasTaskForm(): boolean { + return this.taskDetails && this.taskDetails.formKey; + } + goBack() { this.router.navigate([`/cloud/${this.appName}/`]); } @@ -85,4 +94,12 @@ export class TaskDetailsCloudDemoComponent implements OnInit { onClaimTask() { this.goBack(); } + + onTaskCompleted() { + this.goBack(); + } + + onFormSaved() { + this.notificationService.openSnackMessage('Task has been saved successfully'); + } } diff --git a/demo-shell/src/app/components/form/form-list.component.ts b/demo-shell/src/app/components/form/form-list.component.ts index 5bc660b9e8..4ad54895e7 100644 --- a/demo-shell/src/app/components/form/form-list.component.ts +++ b/demo-shell/src/app/components/form/form-list.component.ts @@ -16,7 +16,8 @@ */ import { Component, ViewChild } from '@angular/core'; -import { FormComponent, FormModel, FormService, LogService, FormOutcomeEvent } from '@alfresco/adf-core'; +import { FormModel, FormService, LogService, FormOutcomeEvent } from '@alfresco/adf-core'; +import { FormComponent } from '@alfresco/adf-process-services'; @Component({ selector: 'app-form-list', diff --git a/demo-shell/src/app/services/in-memory-form.service.ts b/demo-shell/src/app/services/in-memory-form.service.ts index 892b1e8d39..fe015bd834 100644 --- a/demo-shell/src/app/services/in-memory-form.service.ts +++ b/demo-shell/src/app/services/in-memory-form.service.ts @@ -74,7 +74,7 @@ export class InMemoryFormService extends FormService { if (!json.fields) { form.outcomes = [ new FormOutcomeModel(form, { - id: '$custom', + id: '$save', name: FormOutcomeModel.SAVE_ACTION, isSystem: true }) diff --git a/docs/docassets/demo-cloud.form.json b/docs/docassets/demo-cloud.form.json new file mode 100644 index 0000000000..0c3c494c15 --- /dev/null +++ b/docs/docassets/demo-cloud.form.json @@ -0,0 +1,665 @@ +{ + "formRepresentation": { + "id": "form-with-all-fields", + "name": "Form with all fields", + "description": "", + "version": 0, + "formDefinition": { + "tabs": [], + "fields": [ + { + "fieldType": "ContainerRepresentation", + "id": "26b10e64-0403-4686-a75b-0d45279ce3a8", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "text1", + "name": "Text1", + "type": "text", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "minLength": 0, + "maxLength": 0, + "minValue": null, + "maxValue": null, + "regexPattern": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "text2", + "name": "Text2", + "type": "text", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "minLength": 0, + "maxLength": 0, + "minValue": null, + "maxValue": null, + "regexPattern": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "69c1390a-8d8d-423c-8efb-8e43401efa42", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "multilinetext1", + "name": "Multiline text1", + "type": "multi-line-text", + "overrideId": false, + "colspan": 1, + "placeholder": null, + "minLength": 0, + "maxLength": 0, + "regexPattern": null, + "required": false, + "readOnly": false, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "multilinetext2", + "name": "Multiline text2", + "type": "multi-line-text", + "overrideId": false, + "colspan": 1, + "placeholder": null, + "minLength": 0, + "maxLength": 0, + "regexPattern": null, + "required": false, + "readOnly": false, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "df046463-2d65-4388-9ee1-0e1517985215", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "number1", + "overrideId": false, + "name": "Number1", + "type": "integer", + "colspan": 1, + "placeholder": null, + "readOnly": false, + "minValue": null, + "maxValue": null, + "required": false, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "number2", + "overrideId": false, + "name": "Number2", + "type": "integer", + "colspan": 1, + "placeholder": null, + "readOnly": false, + "minValue": null, + "maxValue": null, + "required": false, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "9672cc7b-1959-49c9-96be-3816e57bdfc1", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "checkbox1", + "name": "Checkbox1", + "type": "boolean", + "required": false, + "readOnly": false, + "colspan": 1, + "overrideId": false, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "checkbox2", + "name": "Checkbox2", + "type": "boolean", + "required": false, + "readOnly": false, + "colspan": 1, + "overrideId": false, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "054d193e-a899-4494-9a3e-b489315b7d57", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "dropdown1", + "name": "Dropdown1", + "type": "dropdown", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "optionType": "manual", + "options": [], + "endpoint": null, + "requestHeaders": null, + "restUrl": null, + "restResponsePath": null, + "restIdProperty": null, + "restLabelProperty": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "dropdown2", + "name": "Dropdown2", + "type": "dropdown", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "optionType": "manual", + "options": [], + "endpoint": null, + "requestHeaders": null, + "restUrl": null, + "restResponsePath": null, + "restIdProperty": null, + "restLabelProperty": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "1f8f0b66-e022-4667-91b4-bbbf2ddc36fb", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "amount1", + "name": "Amount1", + "type": "amount", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": "123", + "minValue": null, + "maxValue": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + }, + "enableFractions": false, + "currency": "$" + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "amount2", + "name": "Amount2", + "type": "amount", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": "123", + "minValue": null, + "maxValue": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + }, + "enableFractions": false, + "currency": "$" + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "541a368b-67ee-4a7c-ae7e-232c050b9e24", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "date1", + "name": "Date1", + "type": "date", + "overrideId": false, + "required": false, + "readOnly": false, + "colspan": 1, + "placeholder": null, + "minValue": null, + "maxValue": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + }, + "dateDisplayFormat": "D-M-YYYY" + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "date2", + "name": "Date2", + "type": "date", + "overrideId": false, + "required": false, + "readOnly": false, + "colspan": 1, + "placeholder": null, + "minValue": null, + "maxValue": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + }, + "dateDisplayFormat": "D-M-YYYY" + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "e79cb7e2-3dc1-4c79-8158-28662c28a9f3", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "radiobuttons1", + "name": "Radio buttons1", + "type": "radio-buttons", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "optionType": "manual", + "options": [ + { + "id": "option_1", + "name": "Option 1" + }, + { + "id": "option_2", + "name": "Option 2" + } + ], + "endpoint": null, + "requestHeaders": null, + "restUrl": null, + "restResponsePath": null, + "restIdProperty": null, + "restLabelProperty": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "radiobuttons2", + "name": "Radio buttons2", + "type": "radio-buttons", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "optionType": "manual", + "options": [ + { + "id": "option_1", + "name": "Option 1" + }, + { + "id": "option_2", + "name": "Option 2" + } + ], + "endpoint": null, + "requestHeaders": null, + "restUrl": null, + "restResponsePath": null, + "restIdProperty": null, + "restLabelProperty": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "7c01ed35-be86-4be7-9c28-ed640a5a2ae1", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "AttachFileFieldRepresentation", + "id": "attachfile1", + "name": "Attach file1", + "type": "upload", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2, + "fileSource": { + "serviceId": "all-file-sources", + "name": "All file sources" + }, + "multiple": false, + "link": false + } + } + ], + "2": [ + { + "fieldType": "AttachFileFieldRepresentation", + "id": "attachfile2", + "name": "Attach file2", + "type": "upload", + "value": null, + "required": false, + "readOnly": false, + "overrideId": false, + "colspan": 1, + "placeholder": null, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2, + "fileSource": { + "serviceId": "all-file-sources", + "name": "All file sources" + }, + "multiple": false, + "link": false + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "07b13b96-d469-4a1e-8a9a-9bb957c68869", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "displayvalue1", + "name": "Display value1", + "type": "readonly", + "value": "No field selected", + "readOnly": false, + "overrideId": false, + "colspan": 1, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2, + "field": { + "id": "displayvalue", + "name": "Display value", + "type": "text" + } + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "displayvalue2", + "name": "Display value2", + "type": "readonly", + "value": "No field selected", + "readOnly": false, + "overrideId": false, + "colspan": 1, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2, + "field": { + "id": "displayvalue", + "name": "Display value", + "type": "text" + } + } + } + ] + } + }, + { + "fieldType": "ContainerRepresentation", + "id": "1576ef25-c842-494c-ab84-265a1e3bf68d", + "name": "Label", + "type": "container", + "tab": null, + "numberOfColumns": 2, + "fields": { + "1": [ + { + "fieldType": "FormFieldRepresentation", + "id": "displaytext1", + "name": "Display text1", + "type": "readonly-text", + "value": "Display text as part of the form", + "readOnly": false, + "overrideId": false, + "colspan": 1, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ], + "2": [ + { + "fieldType": "FormFieldRepresentation", + "id": "displaytext2", + "name": "Display text2", + "type": "readonly-text", + "value": "Display text as part of the form", + "readOnly": false, + "overrideId": false, + "colspan": 1, + "visibilityCondition": null, + "params": { + "existingColspan": 1, + "maxColspan": 2 + } + } + ] + } + } + ], + "outcomes": [], + "javascriptEvents": [], + "className": "", + "style": "", + "customFieldTemplates": {}, + "metadata": {}, + "variables": [ + { + "name": "FormVarStr", + "type": "string", + "value": "" + }, + { + "name": "FormVarInt", + "type": "integer", + "value": "" + }, + { + "name": "FormVarBool", + "type": "boolean", + "value": "" + }, + { + "name": "FormVarDate", + "type": "date", + "value": "" + }, + { + "name": "NewVar", + "type": "string", + "value": "" + } + ], + "customFieldsValueInfo": {}, + "gridsterForm": false + } + }, + "processScopeIdentifiers": [] +} diff --git a/docs/process-services-cloud/components/form-cloud.component.md b/docs/process-services-cloud/components/form-cloud.component.md new file mode 100644 index 0000000000..820ce4e62a --- /dev/null +++ b/docs/process-services-cloud/components/form-cloud.component.md @@ -0,0 +1,262 @@ +--- +Title: Form component +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-01 +--- + +# [Form cloud component](../../../lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts "Defined in form-cloud.component.ts") + +Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) from Process Services + +## Contents + +- [Basic Usage](#basic-usage) + - [Empty form template](#empty-form-template) +- [Class members](#class-members) + - [Properties](#properties) + - [Events](#events) +- [Details](#details) + - [Displaying a form](#displaying-a-form) + - [Controlling outcome execution behaviour](#controlling-outcome-execution-behaviour) + - [Field Validators](#field-validators) + - [Common scenarios](#common-scenarios) +- [See also](#see-also) + +## Basic Usage + +```html +<adf-cloud-form + [appName]="appName" + [taskId]="taskId"> +</adf-cloud-form> +``` + +### Empty form template + +The template defined inside `empty-form` will be shown when no form definition is found: + +```html +<adf-cloud-form .... > + + <div empty-form > + <h2>Empty form</h2> + </div> + +</adf-cloud-form> +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| appName | `string` | | App id to fetch corresponding form and values. | +| taskId | `string` | | Task id to fetch corresponding form and values. | +| form | [`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) | | Underlying [form model](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) instance. | +| formId | `string` | | The id of the form definition to load and display with custom values. | +| data | [`TaskVariableCloud[]`](../../../lib/process-services-cloud/src/lib/form/models/task-variable.model.ts) | | Custom form values map to be used with the rendered form. | +| disableCompleteButton | `boolean` | false | If true then the `Complete` outcome button is shown but it will be disabled. | +| disableStartProcessButton | `boolean` | false | If true then the `Start Process` outcome button is shown but it will be disabled. | +| fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Contains a list of form field validator instances. | +| readOnly | `boolean` | false | Toggle readonly state of the form. Forces all form widgets to render as readonly if enabled. | +| showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | +| showDebugButton | `boolean` | false | Toggle debug options. | +| showRefreshButton | `boolean` | true | Toggle rendering of the `Refresh` button. | +| showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. | +| showTitle | `boolean` | true | Toggle rendering of the form title. | +| showValidationIcon | `boolean` | true | Toggle rendering of the validation icon next to the form title. | + + +### Events + +| Name | Type | Description | +| ---- | ---- | ----------- | +| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when any error occurs. | +| executeOutcome | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormOutcomeEvent`](../../../lib/core/form/components/widgets/core/form-outcome-event.model.ts)`>` | Emitted when any outcome is executed. Default behaviour can be prevented via `event.preventDefault()`. | +| formCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Complete` outcome. | +| formDataRefreshed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when form values are refreshed due to a data property change. | +| formError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormFieldModel`](../../core/models/form-field.model.md)`[]>` | Emitted when the supplied form values have a validation error. | +| formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is loaded or reloaded. | +| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Save` or custom outcomes. | + +## Details + +All `formXXX` events receive a [`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) instance as their argument: + +**MyView.component.html** + +```html +<adf-cloud-form + [appName]="appName" + [taskId]="selectedTask?.id" + (formSaved)="onFormSaved($event)"> +</adf-cloud-form> +``` + +**MyView.component.ts** + +```ts +onFormSaved(form: FormCloudModel) { + console.log(form); +} +``` + +### Displaying a form + +There are various ways to display a form. The common scenarios are detailed below. + +#### Displaying a form instance by task id + +```html +<adf-cloud-form + [appName]="appName" + [taskId]="selectedTask?.id"> +</adf-cloud-form> +``` + +For an existing Task both the form and its values will be fetched and displayed. + +#### Displaying a form definition by form id + +```html +<adf-cloud-form + [appName]="appName" + [formId]="selectedFormDefinition?.id" + [data]="customData"> +</adf-cloud-form> +``` + +In this case, only the form definition will be fetched. + + +### Controlling outcome execution behaviour + +In unusual circumstances, you may need to take complete control of form outcome execution. +You can do this by implementing the `executeOutcome` event, which is emitted for both system +outcomes and custom ones. + +Note that by default, the code in your `executeOutcome` handler is executed _before_ the default +behavior but you can switch the default behavior off using `event.preventDefault()`. +You might want to do this, for example, to provide custom form validation or to show a summary +of the form validation before it is submitted. + +**MyView.component.html** + +```html +<adf-cloud-form + [appName]="appName" + [taskId]="selectedTask?.id" + executeOutcome="validateForm($event)"> +</adf-cloud-form> +``` + +**MyView.component.ts** + +```ts +import { FormOutcomeEvent } from '@alfresco/adf-core'; + +export class MyView { + + validateForm(event: FormOutcomeEvent) { + let outcome = event.outcome; + + // you can also get additional properties of outcomes + // if you defined them within outcome definition + + if (outcome) { + let form = outcome.form; + if (form) { + // check/update the form here + event.preventDefault(); + } + } + } + +} +``` + +There are two other functions that can be very useful when you need to control form outcomes: + +- `saveTaskForm()` - Saves the current form +- `completeTaskForm(outcome?: string)` Saves and completes the form with a given outcome name + +### Field Validators + +You can supply a set of validator objects to the form using the `fieldValidators` +property. Each validator implements a check for a particular type of data (eg, a +date validator might check that the date in the field falls between 1980 and 2017). +ADF supplies a standard set of validators that handle most common cases but you can +also implement your own custom validators to replace or extend the set. See the +[Form Field Validator](../../core/interfaces/form-field-validator.interface.md) interface for full details and examples. + +### Common scenarios + +#### Rendering a form using form definition JSON + +See the [demo-form](../../docassets/demo-cloud.form.json) file for an example of form definition JSON. + +The component below (with the JSON assigned to the `formDefinitionJSON` property), shows how a +form definition is rendered: + +```ts +@Component({ + selector: 'sample-form', + template: `<div class="form-container"> + <adf-cloud-form + [form]="form"> + </adf-cloud-form> + </div>` +}) +export class SampleFormComponent implements OnInit { + + form: FormCloudModel; + formDefinitionJSON: any; + + constructor(private formService: FormService) { + } + + ngOnInit() { + this.form = this.formService.parseForm(this.formDefinitionJSON); + } +} +``` + +#### Customizing the styles of form outcome buttons + +You can use normal CSS selectors to style the outcome buttons of your form. +Every outcome has an CSS id value following a simple pattern: + + adf-cloud-form-OUTCOME_NAME + +In the CSS, you can target any outcome ID and change the style as in this example: + +```css +#adf-cloud-form-complete { + background-color: blue !important; + color: white; +} + + +#adf-cloud-form-save { + background-color: green !important; + color: white; +} + +#adf-cloud-form-customoutcome { + background-color: yellow !important; + color: white; +} +``` + +![](../../docassets/images/form-style-sample.png) + + +## See also + +- [Form Field Validator interface](../../core/interfaces/form-field-validator.interface.md) +- [Extensibility](../../user-guide/extensibility.md) +- [Form rendering service](../../core/services/form-rendering.service.md) +- [Form field model](../../core/models/form-field.model.md) +- [Form service](../services/form-cloud.service.md) diff --git a/docs/process-services-cloud/services/form-cloud.service.md b/docs/process-services-cloud/services/form-cloud.service.md new file mode 100644 index 0000000000..d5777ba7d9 --- /dev/null +++ b/docs/process-services-cloud/services/form-cloud.service.md @@ -0,0 +1,67 @@ +--- +Title: Form service +Title: Form cloud service +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-02 +--- + +# [Form cloud service](../../../lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts "Defined in form-cloud.service.ts") + +Implements Process Services form methods + +## Basic Usage + +```ts +import { FormService } from '@alfresco/adf-core'; + +@Component(...) +class MyComponent { + + constructor(formService: FormService) { + +} +``` + +### Methods + +- `parseForm(json: any, data?:`[`TaskVariableCloud,`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`readOnly: boolean = false):`[`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts) + Parses JSON data to create a corresponding [`Form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) model. + - `json` - JSON to create the form + - `data` - (Optional) [`Values`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts) for the form fields + - `readOnly` - Should the form fields be read-only? + +- `saveTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` + Saves task [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts). + - `appName` - App Name + - `taskId` - Task Id + - `formId` - Form Id + - `formValues` - [`Form Values`](../../../lib/core/form/components/widgets/core/form-values.ts) + +- `completeTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues, outcome: string):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` + Completes task [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) + - `appName` - App Name + - `taskId` - Task Id + - `formId` - Form Id + - `formValues` - [`Form Values`](../../../lib/core/form/components/widgets/core/form-values.ts) + - `outcome` - (Optional) [`Form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) Outcome + +- `getTaskForm(appName: string, taskId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` + Get form defintion of a task + - `appName` - App Name + - `taskId` - Task Id + +- `getForm(appName: string, formId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` + Get a form definition + - `appName` - App Name + - `formId` - Form Id + +- `getTask(appName: string, taskId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)<[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)> + Gets details of a task. + - `appName` - App Name + - `taskId` - Task Id + +- `getTaskVariables(appName: string, taskId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)<[`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)[]> + Gets variables of a task. + - `appName` - App Name + - `taskId` - Task Id diff --git a/docs/core/components/form.component.md b/docs/process-services/components/form.component.md similarity index 94% rename from docs/core/components/form.component.md rename to docs/process-services/components/form.component.md index dc5aa913d9..351371144c 100644 --- a/docs/core/components/form.component.md +++ b/docs/process-services/components/form.component.md @@ -5,9 +5,9 @@ Status: Active Last reviewed: 2019-01-16 --- -# [Form component](../../../lib/core/form/components/form.component.ts "Defined in form.component.ts") +# [Form component](../../../lib/process-services/form/form.component.ts "Defined in form.component.ts") -Shows a [`Form`](../../../lib/process-services/task-list/models/form.model.ts) from APS +Shows a [`Form`](../../../lib/core/form/components/widgets/core/form.model.ts) from APS (See it live: [Form Quickstart](https://embed.plnkr.co/YSLXTqb3DtMhVJSqXKkE/)) @@ -279,7 +279,7 @@ could use this, say, to provide two alternative ways of entering the same inform up default values that can be edited. You can implement this in ADF using the `formFieldValueChanged` event of the -[Form service](../services/form.service.md). For example, if you had a form with a dropdown widget (id: `type`) +[Form service](../../core/services/form.service.md). For example, if you had a form with a dropdown widget (id: `type`) and a multiline text (id:`description`), you could synchronize their values as follows: ```ts @@ -305,7 +305,7 @@ The result should look like the following: #### Responding to all form events -Subscribe to the `formEvents` event of the [Form service](../services/form.service.md) to get notification +Subscribe to the `formEvents` event of the [Form service](../../core/services/form.service.md) to get notification of all form events: ```ts @@ -361,8 +361,8 @@ Also, don't forget to set the `providers` property to `ALL` in the `app.config.j ## See also -- [Form Field Validator interface](../interfaces/form-field-validator.interface.md) +- [Form Field Validator interface](../../core/interfaces/form-field-validator.interface.md) - [Extensibility](../../user-guide/extensibility.md) -- [Form rendering service](../services/form-rendering.service.md) -- [Form field model](../models/form-field.model.md) -- [Form service](../services/form.service.md) +- [Form rendering service](../../core/services/form-rendering.service.md) +- [Form field model](../../core/models/form-field.model.md) +- [Form service](../../core/services/form.service.md) diff --git a/lib/core/core.module.ts b/lib/core/core.module.ts index 742a3f3eb9..4fc25a86d9 100644 --- a/lib/core/core.module.ts +++ b/lib/core/core.module.ts @@ -35,7 +35,7 @@ import { HostSettingsModule } from './settings/host-settings.module'; import { ToolbarModule } from './toolbar/toolbar.module'; import { UserInfoModule } from './userinfo/userinfo.module'; import { ViewerModule } from './viewer/viewer.module'; -import { FormModule } from './form/form.module'; +import { FormBaseModule } from './form/form-base.module'; import { SidenavLayoutModule } from './layout/layout.module'; import { CommentsModule } from './comments/comments.module'; import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module'; @@ -75,7 +75,7 @@ import { ExtensionsModule } from '@alfresco/adf-extensions'; ToolbarModule, ContextMenuModule, CardViewModule, - FormModule, + FormBaseModule, CommentsModule, LoginModule, LanguageMenuModule, @@ -106,7 +106,7 @@ import { ExtensionsModule } from '@alfresco/adf-extensions'; ToolbarModule, ContextMenuModule, CardViewModule, - FormModule, + FormBaseModule, CommentsModule, LoginModule, LanguageMenuModule, diff --git a/lib/core/form/components/form-base.component.ts b/lib/core/form/components/form-base.component.ts new file mode 100644 index 0000000000..88d355932c --- /dev/null +++ b/lib/core/form/components/form-base.component.ts @@ -0,0 +1,213 @@ +/*! + * @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 { FormBaseModel } from './form-base.model'; +import { FormOutcomeModel, FormFieldValidator, FormFieldModel, FormOutcomeEvent } from './widgets'; +import { EventEmitter, Input, Output } from '@angular/core'; + +export abstract class FormBaseComponent { + + static SAVE_OUTCOME_ID: string = '$save'; + static COMPLETE_OUTCOME_ID: string = '$complete'; + static START_PROCESS_OUTCOME_ID: string = '$startProcess'; + static CUSTOM_OUTCOME_ID: string = '$custom'; + static COMPLETE_BUTTON_COLOR: string = 'primary'; + static COMPLETE_OUTCOME_NAME: string = 'COMPLETE'; + + /** Path of the folder where the metadata will be stored. */ + @Input() + path: string; + + /** Name to assign to the new node where the metadata are stored. */ + @Input() + nameNode: string; + + /** Toggle rendering of the form title. */ + @Input() + showTitle: boolean = true; + + /** Toggle rendering of the `Complete` outcome button. */ + @Input() + showCompleteButton: boolean = true; + + /** If true then the `Complete` outcome button is shown but it will be disabled. */ + @Input() + disableCompleteButton: boolean = false; + + /** If true then the `Start Process` outcome button is shown but it will be disabled. */ + @Input() + disableStartProcessButton: boolean = false; + + /** Toggle rendering of the `Save` outcome button. */ + @Input() + showSaveButton: boolean = true; + + /** Toggle readonly state of the form. Forces all form widgets to render as readonly if enabled. */ + @Input() + readOnly: boolean = false; + + /** Toggle rendering of the `Refresh` button. */ + @Input() + showRefreshButton: boolean = true; + + /** Toggle rendering of the validation icon next to the form title. */ + @Input() + showValidationIcon: boolean = true; + + /** Contains a list of form field validator instances. */ + @Input() + fieldValidators: FormFieldValidator[] = []; + + /** Emitted when the supplied form values have a validation error. */ + @Output() + formError: EventEmitter<FormFieldModel[]> = new EventEmitter<FormFieldModel[]>(); + + /** Emitted when any outcome is executed. Default behaviour can be prevented + * via `event.preventDefault()`. + */ + @Output() + executeOutcome: EventEmitter<FormOutcomeEvent> = new EventEmitter<FormOutcomeEvent>(); + + /** + * Emitted when any error occurs. + */ + @Output() + error: EventEmitter<any> = new EventEmitter<any>(); + + form: FormBaseModel; + + getParsedFormDefinition(): FormBaseComponent { + return this; + } + + hasForm(): boolean { + return this.form ? true : false; + } + + isTitleEnabled(): boolean { + let titleEnabled = false; + if (this.showTitle && this.form) { + titleEnabled = true; + } + return titleEnabled; + } + + getColorForOutcome(outcomeName: string): string { + return outcomeName === FormBaseComponent.COMPLETE_OUTCOME_NAME ? FormBaseComponent.COMPLETE_BUTTON_COLOR : ''; + } + + isOutcomeButtonEnabled(outcome: FormOutcomeModel): boolean { + if (this.form.readOnly) { + return false; + } + + if (outcome) { + // Make 'Save' button always available + if (outcome.name === FormOutcomeModel.SAVE_ACTION) { + return true; + } + if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) { + return this.disableCompleteButton ? false : this.form.isValid; + } + if (outcome.name === FormOutcomeModel.START_PROCESS_ACTION) { + return this.disableStartProcessButton ? false : this.form.isValid; + } + return this.form.isValid; + } + return false; + } + + isOutcomeButtonVisible(outcome: FormOutcomeModel, isFormReadOnly: boolean): boolean { + if (outcome && outcome.name) { + if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) { + return this.showCompleteButton; + } + if (isFormReadOnly) { + return outcome.isSelected; + } + if (outcome.name === FormOutcomeModel.SAVE_ACTION) { + return this.showSaveButton; + } + if (outcome.name === FormOutcomeModel.START_PROCESS_ACTION) { + return false; + } + return true; + } + return false; + } + + /** + * Invoked when user clicks outcome button. + * @param outcome Form outcome model + */ + onOutcomeClicked(outcome: FormOutcomeModel): boolean { + if (!this.readOnly && outcome && this.form) { + + if (!this.onExecuteOutcome(outcome)) { + return false; + } + + if (outcome.isSystem) { + if (outcome.id === FormBaseComponent.SAVE_OUTCOME_ID) { + this.saveTaskForm(); + return true; + } + + if (outcome.id === FormBaseComponent.COMPLETE_OUTCOME_ID) { + this.completeTaskForm(); + return true; + } + + if (outcome.id === FormBaseComponent.START_PROCESS_OUTCOME_ID) { + this.completeTaskForm(); + return true; + } + + if (outcome.id === FormBaseComponent.CUSTOM_OUTCOME_ID) { + this.onTaskSaved(this.form); + this.storeFormAsMetadata(); + return true; + } + } else { + // Note: Activiti is using NAME field rather than ID for outcomes + if (outcome.name) { + this.onTaskSaved(this.form); + this.completeTaskForm(outcome.name); + return true; + } + } + } + + return false; + } + + handleError(err: any): any { + this.error.emit(err); + } + + abstract onRefreshClicked(); + + abstract saveTaskForm(); + + abstract completeTaskForm(outcome?: string); + + protected abstract onTaskSaved(form: FormBaseModel); + + protected abstract storeFormAsMetadata(); + + protected abstract onExecuteOutcome(outcome: FormOutcomeModel); +} diff --git a/lib/core/form/components/form-base.model.ts b/lib/core/form/components/form-base.model.ts new file mode 100644 index 0000000000..73731d988d --- /dev/null +++ b/lib/core/form/components/form-base.model.ts @@ -0,0 +1,84 @@ +/*! + * @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 { FormValues } from './widgets/core/form-values'; +import { TabModel } from './widgets/core/tab.model'; +import { FormWidgetModel } from './widgets/core/form-widget.model'; +import { FormOutcomeModel } from './widgets/core/form-outcome.model'; +import { FormFieldModel } from './widgets/core/form-field.model'; +import { ContainerModel } from './widgets/core/container.model'; + +export abstract class FormBaseModel { + + static UNSET_TASK_NAME: string = 'Nameless task'; + static SAVE_OUTCOME: string = '$save'; + static COMPLETE_OUTCOME: string = '$complete'; + static START_PROCESS_OUTCOME: string = '$startProcess'; + + json: any; + isValid: boolean; + + values: FormValues = {}; + tabs: TabModel[] = []; + fields: FormWidgetModel[] = []; + outcomes: FormOutcomeModel[] = []; + + className: string; + readOnly: boolean = false; + taskName; + + hasTabs(): boolean { + return this.tabs && this.tabs.length > 0; + } + + hasFields(): boolean { + return this.fields && this.fields.length > 0; + } + + hasOutcomes(): boolean { + return this.outcomes && this.outcomes.length > 0; + } + + getFieldById(fieldId: string): FormFieldModel { + return this.getFormFields().find((field) => field.id === fieldId); + } + + // TODO: consider evaluating and caching once the form is loaded + getFormFields(): FormFieldModel[] { + const formFieldModel: FormFieldModel[] = []; + + for (let i = 0; i < this.fields.length; i++) { + const field = this.fields[i]; + + if (field instanceof ContainerModel) { + const container = <ContainerModel> field; + formFieldModel.push(container.field); + + container.field.columns.forEach((column) => { + formFieldModel.push(...column.fields); + }); + } + } + + return formFieldModel; + } + + abstract validateForm(); + abstract validateField(field: FormFieldModel); + abstract onFormFieldChanged(field: FormFieldModel); + abstract markAsInvalid(); +} diff --git a/lib/core/form/components/form-renderer.component.html b/lib/core/form/components/form-renderer.component.html new file mode 100644 index 0000000000..f142c328dd --- /dev/null +++ b/lib/core/form/components/form-renderer.component.html @@ -0,0 +1,25 @@ +<div class="{{formDefinition.className}}" [ngClass]="{'adf-readonly-form': formDefinition.readOnly }"> + <div *ngIf="formDefinition.hasTabs()"> + <tabs-widget [tabs]="formDefinition.tabs"></tabs-widget> + </div> + + <div *ngIf="!formDefinition.hasTabs() && formDefinition.hasFields()"> + <div *ngFor="let field of formDefinition.fields"> + <adf-form-field [field]="field.field"></adf-form-field> + </div> + </div> +</div> +<!-- +For debugging and data visualisation purposes, +will be removed during future revisions +--> +<div *ngIf="showDebugButton" class="adf-form-debug-container"> + <mat-slide-toggle [(ngModel)]="debugMode">Debug mode</mat-slide-toggle> + <div *ngIf="debugMode"> + <h4>Values</h4> + <pre>{{formDefinition.values | json}}</pre> + + <h4>Form</h4> + <pre>{{formDefinition.json | json}}</pre> + </div> +</div> diff --git a/lib/core/form/components/form.component.scss b/lib/core/form/components/form-renderer.component.scss similarity index 98% rename from lib/core/form/components/form.component.scss rename to lib/core/form/components/form-renderer.component.scss index de22f6fad3..b14652d8aa 100644 --- a/lib/core/form/components/form.component.scss +++ b/lib/core/form/components/form-renderer.component.scss @@ -1,4 +1,4 @@ -@mixin adf-form-component-theme($theme) { +@mixin adf-form-renderer-theme($theme) { $config: mat-typography-config(); $warn: map-get($theme, warn); diff --git a/lib/core/form/components/form-renderer.component.ts b/lib/core/form/components/form-renderer.component.ts new file mode 100644 index 0000000000..46c340e9f7 --- /dev/null +++ b/lib/core/form/components/form-renderer.component.ts @@ -0,0 +1,38 @@ +/*! + * @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, ViewEncapsulation, Input } from '@angular/core'; +import { FormBaseModel } from './form-base.model'; + +@Component({ + selector: 'adf-form-renderer', + templateUrl: './form-renderer.component.html', + styleUrls: ['./form-renderer.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class FormRendererComponent { + + /** Toggle debug options. */ + @Input() + showDebugButton: boolean = false; + + @Input() + formDefinition: FormBaseModel; + + debugMode: boolean; + +} diff --git a/lib/core/form/components/form.component.html b/lib/core/form/components/form.component.html deleted file mode 100644 index d897b4bc62..0000000000 --- a/lib/core/form/components/form.component.html +++ /dev/null @@ -1,64 +0,0 @@ -<div *ngIf="!hasForm()"> - <ng-content select="[empty-form]"> - </ng-content> -</div> - -<div *ngIf="hasForm()" class="{{form.className}} adf-form-container" [ngClass]="{'adf-readonly-form': readOnly }"> - <mat-card> - <mat-card-header> - <mat-card-title> - <h4> - <div *ngIf="showValidationIcon" class="adf-form-validation-button"> - <i id="adf-valid-form-icon" class="material-icons" *ngIf="form.isValid; else no_valid_form">check_circle</i> - <ng-template #no_valid_form> - <i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i> - </ng-template> - </div> - <div *ngIf="showRefreshButton" class="adf-form-reload-button"> - <button mat-icon-button (click)="onRefreshClicked()"> - <mat-icon>refresh</mat-icon> - </button> - </div> - <span *ngIf="isTitleEnabled()" class="adf-form-title">{{form.taskName}}</span> - - </h4> - </mat-card-title> - </mat-card-header> - <mat-card-content> - <div *ngIf="form.hasTabs()"> - <tabs-widget [tabs]="form.tabs"></tabs-widget> - </div> - - <div *ngIf="!form.hasTabs() && form.hasFields()"> - <div *ngFor="let field of form.fields"> - <adf-form-field [field]="field.field"></adf-form-field> - </div> - </div> - </mat-card-content> - <mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions"> - <!--[class.mdl-button--colored]="!outcome.isSystem"--> - <button [id]="'adf-form-'+ outcome.name | formatSpace" *ngFor="let outcome of form.outcomes" - [color]="getColorForOutcome(outcome.name)" - mat-button - [disabled]="!isOutcomeButtonEnabled(outcome)" - [class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)" - (click)="onOutcomeClicked(outcome)"> - {{outcome.name | translate | uppercase }} - </button> - </mat-card-actions> - </mat-card> -</div> -<!-- -For debugging and data visualisation purposes, -will be removed during future revisions ---> -<div *ngIf="showDebugButton" class="adf-form-debug-container"> - <mat-slide-toggle [(ngModel)]="debugMode">Debug mode</mat-slide-toggle> - <div *ngIf="debugMode && hasForm()"> - <h4>Values</h4> - <pre>{{form.values | json}}</pre> - - <h4>Form</h4> - <pre>{{form.json | json}}</pre> - </div> -</div> diff --git a/lib/core/form/components/widgets/core/form-widget.model.ts b/lib/core/form/components/widgets/core/form-widget.model.ts index 806a86b605..91144c3067 100644 --- a/lib/core/form/components/widgets/core/form-widget.model.ts +++ b/lib/core/form/components/widgets/core/form-widget.model.ts @@ -27,7 +27,7 @@ export abstract class FormWidgetModel { readonly type: string; readonly tab: string; - readonly form: FormModel; + readonly form: any; readonly json: any; constructor(form: FormModel, json: any) { diff --git a/lib/core/form/components/widgets/core/form.model.ts b/lib/core/form/components/widgets/core/form.model.ts index e845a66dc6..b2bd10ac23 100644 --- a/lib/core/form/components/widgets/core/form.model.ts +++ b/lib/core/form/components/widgets/core/form.model.ts @@ -34,13 +34,9 @@ import { FORM_FIELD_VALIDATORS, FormFieldValidator } from './form-field-validator'; +import { FormBaseModel } from '../../form-base.model'; -export class FormModel { - - static UNSET_TASK_NAME: string = 'Nameless task'; - static SAVE_OUTCOME: string = '$save'; - static COMPLETE_OUTCOME: string = '$complete'; - static START_PROCESS_OUTCOME: string = '$startProcess'; +export class FormModel extends FormBaseModel { readonly id: number; readonly name: string; @@ -53,34 +49,14 @@ export class FormModel { return this._isValid; } - className: string; - readOnly: boolean = false; - tabs: TabModel[] = []; - /** Stores root containers */ - fields: FormWidgetModel[] = []; - outcomes: FormOutcomeModel[] = []; customFieldTemplates: FormFieldTemplates = {}; fieldValidators: FormFieldValidator[] = [...FORM_FIELD_VALIDATORS]; readonly selectedOutcome: string; - values: FormValues = {}; processVariables: any; - readonly json: any; - - hasTabs(): boolean { - return this.tabs && this.tabs.length > 0; - } - - hasFields(): boolean { - return this.fields && this.fields.length > 0; - } - - hasOutcomes(): boolean { - return this.outcomes && this.outcomes.length > 0; - } - constructor(json?: any, formValues?: FormValues, readOnly: boolean = false, protected formService?: FormService) { + super(); this.readOnly = readOnly; if (json) { @@ -156,30 +132,6 @@ export class FormModel { } } - getFieldById(fieldId: string): FormFieldModel { - return this.getFormFields().find((field) => field.id === fieldId); - } - - // TODO: consider evaluating and caching once the form is loaded - getFormFields(): FormFieldModel[] { - const formFieldModel: FormFieldModel[] = []; - - for (let i = 0; i < this.fields.length; i++) { - const field = this.fields[i]; - - if (field instanceof ContainerModel) { - const container = <ContainerModel> field; - formFieldModel.push(container.field); - - container.field.columns.forEach((column) => { - formFieldModel.push(...column.fields); - }); - } - } - - return formFieldModel; - } - markAsInvalid() { this._isValid = false; } diff --git a/lib/core/form/form.module.ts b/lib/core/form/form-base.module.ts similarity index 90% rename from lib/core/form/form.module.ts rename to lib/core/form/form-base.module.ts index d27e909d3e..39c1827bd3 100644 --- a/lib/core/form/form.module.ts +++ b/lib/core/form/form-base.module.ts @@ -32,11 +32,10 @@ import { StartFormCustomButtonDirective } from './components/form-custom-button. import { FormFieldComponent } from './components/form-field/form-field.component'; import { FormListComponent } from './components/form-list.component'; -import { FormComponent } from './components/form.component'; -import { StartFormComponent } from './components/start-form.component'; import { ContentWidgetComponent } from './components/widgets/content/content.widget'; import { WidgetComponent } from './components/widgets/widget.component'; import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core'; +import { FormRendererComponent } from './components/form-renderer.component'; @NgModule({ imports: [ @@ -55,9 +54,8 @@ import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimep declarations: [ ContentWidgetComponent, FormFieldComponent, - FormComponent, FormListComponent, - StartFormComponent, + FormRendererComponent, StartFormCustomButtonDirective, ...WIDGET_DIRECTIVES, ...MASK_DIRECTIVE, @@ -69,12 +67,11 @@ import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimep exports: [ ContentWidgetComponent, FormFieldComponent, - FormComponent, FormListComponent, - StartFormComponent, + FormRendererComponent, StartFormCustomButtonDirective, ...WIDGET_DIRECTIVES ] }) -export class FormModule { +export class FormBaseModule { } diff --git a/lib/core/form/public-api.ts b/lib/core/form/public-api.ts index 389f6d00c5..c977566a48 100644 --- a/lib/core/form/public-api.ts +++ b/lib/core/form/public-api.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -export * from './components/form.component'; +export * from './components/form-base.component'; export * from './components/form-list.component'; export * from './components/widgets/content/content.widget'; -export * from './components/start-form.component'; +export * from './components/form-renderer.component'; export * from './components/widgets/index'; export * from './components/widgets/dynamic-table/dynamic-table-row.model'; @@ -32,4 +32,4 @@ export * from './services/widget-visibility.service'; export * from './events/index'; -export * from './form.module'; +export * from './form-base.module'; diff --git a/lib/core/form/services/form.service.ts b/lib/core/form/services/form.service.ts index 65f5a57d28..77e7205d90 100644 --- a/lib/core/form/services/form.service.ts +++ b/lib/core/form/services/form.service.ts @@ -106,7 +106,7 @@ export class FormService { if (!json.fields) { form.outcomes = [ new FormOutcomeModel(form, { - id: '$custom', + id: '$save', name: FormOutcomeModel.SAVE_ACTION, isSystem: true }) diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json index a8169edac3..16807a4fcc 100644 --- a/lib/core/i18n/en.json +++ b/lib/core/i18n/en.json @@ -26,6 +26,9 @@ "AT_LEAST_LONG": "Enter at least {{ minLength }} characters", "NO_LONGER_THAN": "Enter no more than {{ maxLength }} characters" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Nameless task" } }, "CORE": { diff --git a/lib/core/pagination/pagination.component.spec.ts b/lib/core/pagination/pagination.component.spec.ts index ef48716643..b9505e0e5b 100644 --- a/lib/core/pagination/pagination.component.spec.ts +++ b/lib/core/pagination/pagination.component.spec.ts @@ -19,7 +19,7 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Pagination } from '@alfresco/js-api'; import { PaginationComponent } from './pagination.component'; -import { PaginatedComponent } from './public-api'; +import { PaginatedComponent } from './paginated-component.interface'; import { BehaviorSubject } from 'rxjs'; import { setupTestBed } from '../testing/setupTestBed'; import { CoreTestingModule } from '../testing/core.testing.module'; diff --git a/lib/core/styles/_index.scss b/lib/core/styles/_index.scss index 6ac152b51c..4ead278054 100644 --- a/lib/core/styles/_index.scss +++ b/lib/core/styles/_index.scss @@ -20,7 +20,7 @@ @import '../viewer/components/pdfViewer-thumbnails.component'; @import '../viewer/components/txtViewer.component'; @import '../viewer/components/imgViewer.component'; -@import '../form/components/form.component'; +@import '../form/components/form-renderer.component'; @import '../layout/components/sidebar-action/sidebar-action-menu.component'; @import '../layout/components/header/header.component'; @import '../comments/comment-list.component'; @@ -54,7 +54,7 @@ @include adf-pdf-thumbnails-theme($theme); @include adf-image-viewer-theme($theme); @include adf-text-viewer-theme($theme); - @include adf-form-component-theme($theme); + @include adf-form-renderer-theme($theme); @include adf-sidebar-action-menu-theme($theme); @include adf-task-list-comment-list-theme($theme); @include adf-task-list-comment-theme($theme); diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html new file mode 100644 index 0000000000..116db6e634 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html @@ -0,0 +1,46 @@ +<div *ngIf="!hasForm()"> + <ng-content select="[empty-form]"> + </ng-content> +</div> + +<div *ngIf="hasForm()" class="adf-form-container"> + <mat-card> + <mat-card-header> + <mat-card-title> + <h4> + <div *ngIf="showValidationIcon" class="adf-form-validation-button"> + <i id="adf-valid-form-icon" class="material-icons" + *ngIf="form.isValid; else no_valid_form">check_circle</i> + <ng-template #no_valid_form> + <i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i> + </ng-template> + </div> + <div *ngIf="showRefreshButton" class="adf-form-reload-button"> + <button mat-icon-button (click)="onRefreshClicked()"> + <mat-icon>refresh</mat-icon> + </button> + </div> + <span *ngIf="isTitleEnabled()" class="adf-form-title"> + {{form.taskName}} + <ng-container *ngIf="!form.taskName"> + {{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}} + </ng-container> + </span> + + </h4> + </mat-card-title> + </mat-card-header> + <mat-card-content> + <adf-form-renderer [formDefinition]="form"> + </adf-form-renderer> + </mat-card-content> + <mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions"> + <button [id]="'adf-form-'+ outcome.name | formatSpace" *ngFor="let outcome of form.outcomes" + [color]="getColorForOutcome(outcome.name)" mat-button [disabled]="!isOutcomeButtonEnabled(outcome)" + [class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)" + (click)="onOutcomeClicked(outcome)"> + {{outcome.name | translate | uppercase }} + </button> + </mat-card-actions> + </mat-card> +</div> diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts new file mode 100644 index 0000000000..27ef2f9c17 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -0,0 +1,753 @@ +/*! + * @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 { SimpleChange } from '@angular/core'; +import { Observable, of, throwError } from 'rxjs'; +import { FormFieldModel, FormFieldTypes, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService } from '@alfresco/adf-core'; +import { FormCloudService } from '../services/form-cloud.service'; +import { FormCloudComponent } from './form-cloud.component'; +import { FormCloud } from '../models/form-cloud.model'; +import { cloudFormMock } from '../mocks/cloud-form.mock'; + +describe('FormCloudComponent', () => { + + let formService: FormCloudService; + let formComponent: FormCloudComponent; + let visibilityService: WidgetVisibilityService; + let logService: LogService; + + beforeEach(() => { + logService = new LogService(null); + visibilityService = new WidgetVisibilityService(null, logService); + spyOn(visibilityService, 'refreshVisibility').and.stub(); + formService = new FormCloudService(null, null, logService); + formComponent = new FormCloudComponent(formService, visibilityService); + }); + + it('should check form', () => { + expect(formComponent.hasForm()).toBeFalsy(); + formComponent.form = new FormCloud(); + expect(formComponent.hasForm()).toBeTruthy(); + }); + + it('should allow title if showTitle is true', () => { + const formModel = new FormCloud(); + formComponent.form = formModel; + + expect(formComponent.showTitle).toBeTruthy(); + expect(formComponent.isTitleEnabled()).toBeTruthy(); + + }); + + it('should not allow title if showTitle is false', () => { + const formModel = new FormCloud(); + + formComponent.form = formModel; + formComponent.showTitle = false; + + expect(formComponent.isTitleEnabled()).toBeFalsy(); + }); + + it('should return primary color for complete button', () => { + expect(formComponent.getColorForOutcome('COMPLETE')).toBe('primary'); + }); + + it('should not enable outcome button when model missing', () => { + expect(formComponent.isOutcomeButtonVisible(null, false)).toBeFalsy(); + }); + + it('should enable custom outcome buttons', () => { + const formModel = new FormCloud(); + formComponent.form = formModel; + const outcome = new FormOutcomeModel(<any> formModel, { id: 'action1', name: 'Action 1' }); + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); + }); + + it('should allow controlling [complete] button visibility', () => { + const formModel = new FormCloud(); + formComponent.form = formModel; + const outcome = new FormOutcomeModel(<any> formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); + + formComponent.showSaveButton = true; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); + + formComponent.showSaveButton = false; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy(); + }); + + it('should show only [complete] button with readOnly form ', () => { + const formModel = new FormCloud(); + formModel.readOnly = true; + formComponent.form = formModel; + const outcome = new FormOutcomeModel(<any> formModel, { id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION }); + + formComponent.showCompleteButton = true; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); + }); + + it('should not show [save] button with readOnly form ', () => { + const formModel = new FormCloud(); + formModel.readOnly = true; + formComponent.form = formModel; + const outcome = new FormOutcomeModel(<any> formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION }); + + formComponent.showSaveButton = true; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy(); + }); + + it('should show [custom-outcome] button with readOnly form and selected custom-outcome', () => { + const formModel = new FormCloud({formRepresentation: {formDefinition: {selectedOutcome: 'custom-outcome'}}}); + formModel.readOnly = true; + formComponent.form = formModel; + let outcome = new FormOutcomeModel(<any> formModel, { id: '$customoutome', name: 'custom-outcome' }); + + formComponent.showCompleteButton = true; + formComponent.showSaveButton = true; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); + + outcome = new FormOutcomeModel(<any> formModel, { id: '$customoutome2', name: 'custom-outcome2' }); + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy(); + }); + + it('should allow controlling [save] button visibility', () => { + const formModel = new FormCloud(); + formModel.readOnly = false; + formComponent.form = formModel; + const outcome = new FormOutcomeModel(<any> formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION }); + + formComponent.showCompleteButton = true; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy(); + + formComponent.showCompleteButton = false; + expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy(); + }); + + it('should load form on refresh', () => { + spyOn(formComponent, 'loadForm').and.stub(); + + formComponent.onRefreshClicked(); + expect(formComponent.loadForm).toHaveBeenCalled(); + }); + + it('should get task variables if a task form is rendered', () => { + spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => { + return new Observable((observer) => { + observer.next({ formRepresentation: { taskId: currentTaskId }}); + observer.complete(); + }); + }); + + spyOn(formService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formService, 'getTask').and.callFake((currentTaskId) => { + return new Observable((observer) => { + observer.next({ formRepresentation: { taskId: currentTaskId }}); + observer.complete(); + }); + }); + const taskId = '123'; + const appName = 'test-app'; + + formComponent.appName = appName; + formComponent.taskId = taskId; + formComponent.loadForm(); + + expect(formService.getTaskVariables).toHaveBeenCalledWith(appName, taskId); + }); + + it('should not get task variables and form if task id is not specified', () => { + spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => { + return new Observable((observer) => { + observer.next({ taskId: currentTaskId }); + observer.complete(); + }); + }); + + spyOn(formService, 'getTaskVariables').and.returnValue(of({})); + + formComponent.appName = 'test-app'; + formComponent.taskId = null; + formComponent.loadForm(); + + expect(formService.getTaskForm).not.toHaveBeenCalled(); + expect(formService.getTaskVariables).not.toHaveBeenCalled(); + }); + + it('should get form definition by form id on load', () => { + spyOn(formComponent, 'getFormById').and.stub(); + + const formId = '123'; + const appName = 'test-app'; + + formComponent.appName = appName; + formComponent.formId = formId; + formComponent.loadForm(); + + expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId); + }); + + it('should refresh visibility when the form is loaded', () => { + spyOn(formService, 'getForm').and.returnValue(of({formRepresentation: {formDefinition: {}}})); + const formId = '123'; + const appName = 'test-app'; + + formComponent.appName = appName; + formComponent.formId = formId; + formComponent.loadForm(); + + expect(formService.getForm).toHaveBeenCalledWith(appName, formId); + expect(visibilityService.refreshVisibility).toHaveBeenCalled(); + }); + + it('should reload form by task id on binding changes', () => { + spyOn(formComponent, 'getFormByTaskId').and.stub(); + const taskId = '<task id>'; + + const appName = 'test-app'; + formComponent.appName = appName; + const change = new SimpleChange(null, taskId, true); + formComponent.ngOnChanges({ 'taskId': change }); + + expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(appName, taskId); + }); + + it('should reload form definition by form id on binding changes', () => { + spyOn(formComponent, 'getFormById').and.stub(); + const formId = '123'; + const appName = 'test-app'; + + formComponent.appName = appName; + const change = new SimpleChange(null, formId, true); + formComponent.ngOnChanges({ 'formId': change }); + + expect(formComponent.getFormById).toHaveBeenCalledWith(appName, formId); + }); + + it('should not get form on load', () => { + spyOn(formComponent, 'getFormByTaskId').and.stub(); + spyOn(formComponent, 'getFormById').and.stub(); + + formComponent.taskId = null; + formComponent.formId = null; + formComponent.loadForm(); + + expect(formComponent.getFormByTaskId).not.toHaveBeenCalled(); + expect(formComponent.getFormById).not.toHaveBeenCalled(); + }); + + it('should not reload form on unrelated binding changes', () => { + spyOn(formComponent, 'getFormByTaskId').and.stub(); + spyOn(formComponent, 'getFormById').and.stub(); + + formComponent.ngOnChanges({ 'tag': new SimpleChange(null, 'hello world', false) }); + + expect(formComponent.getFormByTaskId).not.toHaveBeenCalled(); + expect(formComponent.getFormById).not.toHaveBeenCalled(); + }); + + it('should complete form on custom outcome click', () => { + const formModel = new FormCloud(); + const outcomeName = 'Custom Action'; + const outcome = new FormOutcomeModel(<any> formModel, { id: 'custom1', name: outcomeName }); + + let saved = false; + formComponent.form = formModel; + formComponent.formSaved.subscribe((v) => saved = true); + spyOn(formComponent, 'completeTaskForm').and.stub(); + + const result = formComponent.onOutcomeClicked(outcome); + expect(result).toBeTruthy(); + expect(saved).toBeTruthy(); + expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcomeName); + }); + + it('should save form on [save] outcome click', () => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { + id: FormCloudComponent.SAVE_OUTCOME_ID, + name: 'Save', + isSystem: true + }); + + formComponent.form = formModel; + spyOn(formComponent, 'saveTaskForm').and.stub(); + + const result = formComponent.onOutcomeClicked(outcome); + expect(result).toBeTruthy(); + expect(formComponent.saveTaskForm).toHaveBeenCalled(); + }); + + it('should complete form on [complete] outcome click', () => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { + id: FormCloudComponent.COMPLETE_OUTCOME_ID, + name: 'Complete', + isSystem: true + }); + + formComponent.form = formModel; + spyOn(formComponent, 'completeTaskForm').and.stub(); + + const result = formComponent.onOutcomeClicked(outcome); + expect(result).toBeTruthy(); + expect(formComponent.completeTaskForm).toHaveBeenCalled(); + }); + + it('should emit form saved event on custom outcome click', () => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { + id: FormCloudComponent.CUSTOM_OUTCOME_ID, + name: 'Custom', + isSystem: true + }); + + let saved = false; + formComponent.form = formModel; + formComponent.formSaved.subscribe((v) => saved = true); + + const result = formComponent.onOutcomeClicked(outcome); + expect(result).toBeTruthy(); + expect(saved).toBeTruthy(); + }); + + it('should do nothing when clicking outcome for readonly form', () => { + const formModel = new FormCloud(); + const outcomeName = 'Custom Action'; + const outcome = new FormOutcomeModel(<any> formModel, { id: 'custom1', name: outcomeName }); + + formComponent.form = formModel; + spyOn(formComponent, 'completeTaskForm').and.stub(); + + expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy(); + formComponent.readOnly = true; + expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); + }); + + it('should require outcome model when clicking outcome', () => { + formComponent.form = new FormCloud(); + formComponent.readOnly = false; + expect(formComponent.onOutcomeClicked(null)).toBeFalsy(); + }); + + it('should require loaded form when clicking outcome', () => { + const formModel = new FormCloud(); + const outcomeName = 'Custom Action'; + const outcome = new FormOutcomeModel(<any> formModel, { id: 'custom1', name: outcomeName }); + + formComponent.readOnly = false; + formComponent.form = null; + expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); + }); + + it('should not execute unknown system outcome', () => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { id: 'unknown', name: 'Unknown', isSystem: true }); + + formComponent.form = formModel; + expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); + }); + + it('should require custom action name to complete form', () => { + const formModel = new FormCloud(); + let outcome = new FormOutcomeModel(<any> formModel, { id: 'custom' }); + + formComponent.form = formModel; + expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy(); + + outcome = new FormOutcomeModel(<any> formModel, { id: 'custom', name: 'Custom' }); + spyOn(formComponent, 'completeTaskForm').and.stub(); + expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy(); + }); + + it('should fetch and parse form by task id', (done) => { + const appName = 'test-app'; + const taskId = '456'; + + spyOn(formService, 'getTask').and.returnValue(of({})); + spyOn(formService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formService, 'getTaskForm').and.returnValue(of({formRepresentation: {taskId: taskId, formDefinition: {selectedOutcome: 'custom-outcome'}}})); + + formComponent.formLoaded.subscribe(() => { + expect(formService.getTaskForm).toHaveBeenCalledWith(appName, taskId); + expect(formComponent.form).toBeDefined(); + expect(formComponent.form.taskId).toBe(taskId); + done(); + }); + + formComponent.appName = appName; + formComponent.taskId = taskId; + formComponent.loadForm(); + }); + + it('should handle error when getting form by task id', (done) => { + const error = 'Some error'; + + spyOn(formService, 'getTask').and.returnValue(of({})); + spyOn(formService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formComponent, 'handleError').and.stub(); + spyOn(formService, 'getTaskForm').and.callFake(() => { + return throwError(error); + }); + + formComponent.getFormByTaskId('test-app', '123').then((_) => { + expect(formComponent.handleError).toHaveBeenCalledWith(error); + done(); + }); + }); + + it('should fetch and parse form definition by id', (done) => { + spyOn(formService, 'getForm').and.callFake((currentAppName, currentFormId) => { + return new Observable((observer) => { + observer.next({ formRepresentation: {id: currentFormId, formDefinition: {}}}); + observer.complete(); + }); + }); + + const appName = 'test-app'; + const formId = '456'; + formComponent.formLoaded.subscribe(() => { + expect(formComponent.form).toBeDefined(); + expect(formComponent.form.id).toBe(formId); + done(); + }); + + formComponent.appName = appName; + formComponent.formId = formId; + formComponent.loadForm(); + }); + + it('should handle error when getting form by definition id', () => { + const error = 'Some error'; + + spyOn(formComponent, 'handleError').and.stub(); + spyOn(formService, 'getForm').and.callFake(() => throwError(error)); + + formComponent.getFormById('test-app', '123'); + expect(formComponent.handleError).toHaveBeenCalledWith(error); + }); + + it('should save task form and raise corresponding event', () => { + spyOn(formService, 'saveTaskForm').and.callFake(() => { + return new Observable((observer) => { + observer.next(); + observer.complete(); + }); + }); + + let saved = false; + let savedForm = null; + formComponent.formSaved.subscribe((form) => { + saved = true; + savedForm = form; + }); + + const taskId = '123-223'; + const appName = 'test-app'; + + const formModel = new FormCloud({ + formRepresentation: { + id: '23', + taskId: taskId, + formDefinition: { + fields: [ + { id: 'field1' }, + { id: 'field2' } + ] + } + } + }); + formComponent.form = formModel; + formComponent.taskId = taskId; + formComponent.appName = appName; + + formComponent.saveTaskForm(); + + expect(formService.saveTaskForm).toHaveBeenCalledWith(appName, formModel.taskId, formModel.id, formModel.values); + expect(saved).toBeTruthy(); + expect(savedForm).toEqual(formModel); + }); + + it('should handle error during form save', () => { + const error = 'Error'; + spyOn(formService, 'saveTaskForm').and.callFake(() => throwError(error)); + spyOn(formComponent, 'handleError').and.stub(); + + const taskId = '123-223'; + const appName = 'test-app'; + const formModel = new FormCloud({ + formRepresentation: { + id: '23', + taskId: taskId, + formDefinition: { + fields: [ + { id: 'field1' }, + { id: 'field2' } + ] + } + } + }); + formComponent.form = formModel; + formComponent.taskId = taskId; + formComponent.appName = appName; + + formComponent.saveTaskForm(); + + expect(formComponent.handleError).toHaveBeenCalledWith(error); + }); + + it('should require form with appName and taskId to save', () => { + spyOn(formService, 'saveTaskForm').and.stub(); + + formComponent.form = null; + formComponent.saveTaskForm(); + + formComponent.form = new FormCloud(); + + formComponent.appName = 'test-app'; + formComponent.saveTaskForm(); + + formComponent.appName = null; + formComponent.taskId = '123'; + formComponent.saveTaskForm(); + + expect(formService.saveTaskForm).not.toHaveBeenCalled(); + }); + + it('should require form with appName and taskId to complete', () => { + spyOn(formService, 'completeTaskForm').and.stub(); + + formComponent.form = null; + formComponent.completeTaskForm('save'); + + formComponent.form = new FormCloud(); + formComponent.appName = 'test-app'; + formComponent.completeTaskForm('complete'); + + formComponent.appName = null; + formComponent.taskId = '123'; + formComponent.completeTaskForm('complete'); + + expect(formService.completeTaskForm).not.toHaveBeenCalled(); + }); + + it('should complete form and raise corresponding event', () => { + spyOn(formService, 'completeTaskForm').and.callFake(() => { + return new Observable((observer) => { + observer.next(); + observer.complete(); + }); + }); + + const outcome = 'complete'; + let completed = false; + formComponent.formCompleted.subscribe(() => completed = true); + + const taskId = '123-223'; + const appName = 'test-app'; + const formModel = new FormCloud({ + formRepresentation: { + id: '23', + taskId: taskId, + formDefinition: { + fields: [ + { id: 'field1' }, + { id: 'field2' } + ] + } + } + }); + + formComponent.form = formModel; + formComponent.taskId = taskId; + formComponent.appName = appName; + formComponent.completeTaskForm(outcome); + + expect(formService.completeTaskForm).toHaveBeenCalledWith(appName, formModel.taskId, formModel.id, formModel.values, outcome); + expect(completed).toBeTruthy(); + }); + + it('should require json to parse form', () => { + expect(formComponent.parseForm(null)).toBeNull(); + }); + + it('should parse form from json', () => { + const form = formComponent.parseForm({ + formRepresentation: { + id: '1', + formDefinition: { + fields: [ + { id: 'field1', type: FormFieldTypes.CONTAINER } + ] + } + } + }); + + expect(form).toBeDefined(); + expect(form.id).toBe('1'); + expect(form.fields.length).toBe(1); + expect(form.fields[0].id).toBe('field1'); + }); + + it('should provide outcomes for form definition', () => { + spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough(); + + const form = formComponent.parseForm({ formRepresentation: { id: 1, formDefinition: {}}}); + expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form); + }); + + it('should prevent default outcome execution', () => { + + const outcome = new FormOutcomeModel(<any> new FormCloud(), { + id: FormCloudComponent.CUSTOM_OUTCOME_ID, + name: 'Custom' + }); + + formComponent.form = new FormCloud(); + formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => { + expect(event.outcome).toBe(outcome); + event.preventDefault(); + expect(event.defaultPrevented).toBeTruthy(); + }); + + const result = formComponent.onOutcomeClicked(outcome); + expect(result).toBeFalsy(); + }); + + it('should not prevent default outcome execution', () => { + const outcome = new FormOutcomeModel(<any> new FormCloud(), { + id: FormCloudComponent.CUSTOM_OUTCOME_ID, + name: 'Custom' + }); + + formComponent.form = new FormCloud(); + formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => { + expect(event.outcome).toBe(outcome); + expect(event.defaultPrevented).toBeFalsy(); + }); + + spyOn(formComponent, 'completeTaskForm').and.callThrough(); + + const result = formComponent.onOutcomeClicked(outcome); + expect(result).toBeTruthy(); + + expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcome.name); + }); + + it('should check visibility only if field with form provided', () => { + + formComponent.checkVisibility(null); + expect(visibilityService.refreshVisibility).not.toHaveBeenCalled(); + + let field = new FormFieldModel(null); + formComponent.checkVisibility(field); + expect(visibilityService.refreshVisibility).not.toHaveBeenCalled(); + + field = new FormFieldModel(<any> new FormCloud()); + formComponent.checkVisibility(field); + expect(visibilityService.refreshVisibility).toHaveBeenCalledWith(field.form); + }); + + it('should disable outcome buttons for readonly form', () => { + const formModel = new FormCloud(); + formModel.readOnly = true; + formComponent.form = formModel; + + const outcome = new FormOutcomeModel(<any> new FormCloud(), { + id: FormCloudComponent.CUSTOM_OUTCOME_ID, + name: 'Custom' + }); + + expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy(); + }); + + it('should require outcome to eval button state', () => { + formComponent.form = new FormCloud(); + expect(formComponent.isOutcomeButtonEnabled(null)).toBeFalsy(); + }); + + it('should disable complete outcome button when disableCompleteButton is true', () => { + const formModel = new FormCloud(); + formComponent.form = formModel; + formComponent.disableCompleteButton = true; + + expect(formModel.isValid).toBeTruthy(); + const completeOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.COMPLETE_ACTION); + + expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy(); + }); + + it('should disable start process outcome button when disableStartProcessButton is true', () => { + const formModel = new FormCloud(); + formComponent.form = formModel; + formComponent.disableStartProcessButton = true; + + expect(formModel.isValid).toBeTruthy(); + const startProcessOutcome = formComponent.form.outcomes.find((outcome) => outcome.name === FormOutcomeModel.START_PROCESS_ACTION); + + expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy(); + }); + + it('should raise [executeOutcome] event for formService', (done) => { + formComponent.executeOutcome.subscribe(() => { + done(); + }); + + const outcome = new FormOutcomeModel(<any> new FormCloud(), { + id: FormCloudComponent.CUSTOM_OUTCOME_ID, + name: 'Custom' + }); + + formComponent.form = new FormCloud(); + formComponent.onOutcomeClicked(outcome); + }); + + it('should refresh form values when data is changed', () => { + formComponent.form = new FormCloud(JSON.parse(JSON.stringify(cloudFormMock))); + let formFields = formComponent.form.getFormFields(); + + let labelField = formFields.find((field) => field.id === 'text1'); + let radioField = formFields.find((field) => field.id === 'number1'); + expect(labelField.value).toBeNull(); + expect(radioField.value).toBeUndefined(); + + const formValues: any[] = [{name: 'text1', value: 'test'}, {name: 'number1', value: 23}]; + + const change = new SimpleChange(null, formValues, false); + formComponent.data = formValues; + formComponent.ngOnChanges({ 'data': change }); + + formFields = formComponent.form.getFormFields(); + labelField = formFields.find((field) => field.id === 'text1'); + radioField = formFields.find((field) => field.id === 'number1'); + expect(labelField.value).toBe('test'); + expect(radioField.value).toBe(23); + }); + + it('should refresh radio buttons value when id is given to data', () => { + formComponent.form = new FormCloud(JSON.parse(JSON.stringify(cloudFormMock))); + let formFields = formComponent.form.getFormFields(); + let radioFieldById = formFields.find((field) => field.id === 'radiobuttons1'); + + const formValues: any[] = [{name: 'radiobuttons1', value: 'option_2'}]; + const change = new SimpleChange(null, formValues, false); + formComponent.data = formValues; + formComponent.ngOnChanges({ 'data': change }); + + formFields = formComponent.form.getFormFields(); + radioFieldById = formFields.find((field) => field.id === 'radiobuttons1'); + expect(radioFieldById.value).toBe('option_2'); + }); +}); diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts new file mode 100644 index 0000000000..368a522ae4 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts @@ -0,0 +1,296 @@ +/*! + * @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, EventEmitter, Input, OnChanges, + Output, SimpleChanges +} from '@angular/core'; +import { Observable, of, forkJoin } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; +import { Subscription } from 'rxjs'; +import { FormBaseComponent, FormFieldModel, FormOutcomeEvent, FormOutcomeModel, WidgetVisibilityService } from '@alfresco/adf-core'; +import { FormCloudService } from '../services/form-cloud.service'; +import { FormCloud } from '../models/form-cloud.model'; +import { TaskVariableCloud } from '../models/task-variable-cloud.model'; + +@Component({ + selector: 'adf-cloud-form', + templateUrl: './form-cloud.component.html' +}) +export class FormCloudComponent extends FormBaseComponent implements OnChanges { + + /** App id to fetch corresponding form and values. */ + @Input() + appName: string; + + /** Task id to fetch corresponding form and values. */ + @Input() + formId: string; + + /** Underlying form model instance. */ + @Input() + form: FormCloud; + + /** Task id to fetch corresponding form and values. */ + @Input() + taskId: string; + + /** Custom form values map to be used with the rendered form. */ + @Input() + data: TaskVariableCloud[]; + + /** Emitted when the form is submitted with the `Save` or custom outcomes. */ + @Output() + formSaved: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + + /** Emitted when the form is submitted with the `Complete` outcome. */ + @Output() + formCompleted: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + + /** Emitted when the form is loaded or reloaded. */ + @Output() + formLoaded: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + + /** Emitted when form values are refreshed due to a data property change. */ + @Output() + formDataRefreshed: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + + protected subscriptions: Subscription[] = []; + nodeId: string; + + constructor(protected formService: FormCloudService, + protected visibilityService: WidgetVisibilityService) { + super(); + } + + ngOnChanges(changes: SimpleChanges) { + const appName = changes['appName']; + if (appName && appName.currentValue) { + if (this.taskId) { + this.getFormDefinitionWithFolderTask(this.appName, this.taskId); + } else if (this.formId) { + this.getFormById(appName.currentValue, this.formId); + } + return; + } + + const formId = changes['formId']; + if (formId && formId.currentValue && this.appName) { + this.getFormById(this.appName, formId.currentValue); + return; + } + + const taskId = changes['taskId']; + if (taskId && taskId.currentValue && this.appName) { + this.getFormByTaskId(this.appName, taskId.currentValue); + return; + } + + const data = changes['data']; + if (data && data.currentValue) { + this.refreshFormData(); + return; + } + } + + /** + * Invoked when user clicks form refresh button. + */ + onRefreshClicked() { + this.loadForm(); + } + + loadForm() { + if (this.appName && this.taskId) { + this.getFormByTaskId(this.appName, this.taskId); + } else if (this.appName && this.formId) { + this.getFormById(this.appName, this.formId); + } + + } + + findProcessVariablesByTaskId(appName: string, taskId: string): Observable<any> { + return this.formService.getTask(appName, taskId).pipe( + switchMap((task: any) => { + if (this.isAProcessTask(task)) { + return this.formService.getTaskVariables(appName, taskId); + } else { + return of({}); + } + }) + ); + } + + isAProcessTask(taskRepresentation) { + return taskRepresentation.processDefinitionId && taskRepresentation.processDefinitionDeploymentId !== 'null'; + } + + getFormByTaskId(appName, taskId: string): Promise<FormCloud> { + return new Promise<FormCloud>((resolve, reject) => { + forkJoin(this.formService.getTaskForm(appName, taskId), + this.formService.getTaskVariables(appName, taskId)) + .subscribe( + (data) => { + this.data = data[1]; + const parsedForm = this.parseForm(data[0]); + this.visibilityService.refreshVisibility(<any> parsedForm); + parsedForm.validateForm(); + this.form = parsedForm; + this.form.nodeId = this.nodeId; + this.onFormLoaded(this.form); + resolve(this.form); + }, + (error) => { + this.handleError(error); + // reject(error); + resolve(null); + } + ); + }); + } + + async getFormDefinitionWithFolderTask(appName: string, taskId: string) { + await this.getFolderTask(appName, taskId); + await this.getFormByTaskId(appName, taskId); + } + + async getFolderTask(appName: string, taskId: string) { + this.nodeId = await this.formService.getProcessStorageFolderTask(appName, taskId).toPromise(); + } + + getFormById(appName: string, formId: string) { + this.formService + .getForm(appName, formId) + .subscribe( + (form) => { + const parsedForm = this.parseForm(form); + this.visibilityService.refreshVisibility(<any> parsedForm); + parsedForm.validateForm(); + this.form = parsedForm; + this.form.nodeId = this.nodeId; + this.onFormLoaded(this.form); + }, + (error) => { + this.handleError(error); + } + ); + } + + saveTaskForm() { + if (this.form && this.appName && this.taskId) { + this.formService + .saveTaskForm(this.appName, this.taskId, this.form.id, this.form.values) + .subscribe( + () => { + this.onTaskSaved(this.form); + }, + (error) => this.onTaskSavedError(this.form, error) + ); + } + } + + completeTaskForm(outcome?: string) { + if (this.form && this.appName && this.taskId) { + this.formService + .completeTaskForm(this.appName, this.taskId, this.form.id, this.form.values, outcome) + .subscribe( + () => { + this.onTaskCompleted(this.form); + }, + (error) => this.onTaskCompletedError(this.form, error) + ); + } + } + + parseForm(json: any): FormCloud { + if (json) { + const form = new FormCloud(json, this.data, this.readOnly, this.formService); + if (!json.formRepresentation.formDefinition || !json.formRepresentation.formDefinition.fields) { + form.outcomes = this.getFormDefinitionOutcomes(form); + } + if (this.fieldValidators && this.fieldValidators.length > 0) { + form.fieldValidators = this.fieldValidators; + } + return form; + } + return null; + } + + /** + * Get custom set of outcomes for a Form Definition. + * @param form Form definition model. + */ + getFormDefinitionOutcomes(form: FormCloud): FormOutcomeModel[] { + return [ + new FormOutcomeModel(<any> form, { id: '$save', name: FormOutcomeModel.SAVE_ACTION, isSystem: true }) + ]; + } + + checkVisibility(field: FormFieldModel) { + if (field && field.form) { + this.visibilityService.refreshVisibility(field.form); + } + } + + private refreshFormData() { + this.form = this.parseForm(this.form.json); + this.onFormLoaded(this.form); + this.onFormDataRefreshed(this.form); + } + + protected onFormLoaded(form: FormCloud) { + this.formLoaded.emit(form); + } + + protected onFormDataRefreshed(form: FormCloud) { + this.formDataRefreshed.emit(form); + } + + protected onTaskSaved(form: FormCloud) { + this.formSaved.emit(form); + } + + protected onTaskSavedError(form: FormCloud, error: any) { + this.handleError(error); + } + + protected onTaskCompleted(form: FormCloud) { + this.formCompleted.emit(form); + } + + protected onTaskCompletedError(form: FormCloud, error: any) { + this.handleError(error); + } + + protected onExecuteOutcome(outcome: FormOutcomeModel): boolean { + const args = new FormOutcomeEvent(outcome); + + if (args.defaultPrevented) { + return false; + } + + this.executeOutcome.emit(args); + if (args.defaultPrevented) { + return false; + } + + return true; + } + + protected storeFormAsMetadata() { + } +} diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html new file mode 100644 index 0000000000..1e8b6a207f --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html @@ -0,0 +1,40 @@ +<div class="adf-upload-widget {{field.className}}" + [class.adf-invalid]="!field.isValid" + [class.adf-readonly]="field.readOnly"> + <label class="adf-label" [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label> + <div class="adf-upload-widget-container"> + <div> + <mat-list *ngIf="hasFile"> + <mat-list-item class="adf-upload-files-row" *ngFor="let file of field.value"> + <img mat-list-icon class="adf-upload-widget__icon" + [id]="'file-'+file.id+'-icon'" + [src]="getIcon(file.mimeType)" + [alt]="mimeTypeIcon" + (click)="fileClicked(file)" + (keyup.enter)="fileClicked(file)" + role="button" + tabindex="0"/> + <span matLine id="{{'file-'+file.id}}" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)" + role="button" tabindex="0" class="adf-file">{{file.name}}</span> + <button *ngIf="!field.readOnly" mat-icon-button [id]="'file-'+file.id+'-remove'" + (click)="removeFile(file);" (keyup.enter)="removeFile(file);"> + <mat-icon class="mat-24">highlight_off</mat-icon> + </button> + </mat-list-item> + </mat-list> + </div> + + <div class="button-row" *ngIf="(!hasFile || multipleOption) && !field.readOnly"> + <a mat-raised-button color="primary"> + {{ 'FORM.FIELD.UPLOAD' | translate }}<mat-icon>file_upload</mat-icon> + <input #uploadFiles + [multiple]="multipleOption" + type="file" + [id]="field.id" + (change)="onFileChanged($event)"/> + </a> + </div> + </div> + <error-widget [error]="field.validationSummary"></error-widget> + <error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget> +</div> diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts new file mode 100644 index 0000000000..7a4f8b2beb --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts @@ -0,0 +1,135 @@ +/*! + * @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. + */ + +/* tslint:disable:component-selector */ + +import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { Observable, from } from 'rxjs'; +import { mergeMap, map } from 'rxjs/operators'; +import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService } from '@alfresco/adf-core'; +import { FormCloudService } from '../services/form-cloud.service'; + +@Component({ + selector: 'upload-cloud-widget', + templateUrl: './upload-cloud.widget.html', + styleUrls: ['./upload-cloud.widget.scss'], + host: baseHost, + encapsulation: ViewEncapsulation.None +}) +export class UploadCloudWidgetComponent extends WidgetComponent implements OnInit { + + hasFile: boolean; + displayText: string; + multipleOption: string = ''; + mimeTypeIcon: string; + + @ViewChild('uploadFiles') + fileInput: ElementRef; + + constructor(public formService: FormService, + private thumbnailService: ThumbnailService, + private formCloudService: FormCloudService, + private logService: LogService) { + super(formService); + } + + ngOnInit() { + if (this.field && + this.field.value && + this.field.value.length > 0) { + this.hasFile = true; + } + this.getMultipleFileParam(); + } + + removeFile(file: any) { + if (this.field) { + this.removeElementFromList(file); + } + } + + onFileChanged(event: any) { + const files = event.target.files; + let filesSaved = []; + + if (this.field.json.value) { + filesSaved = [...this.field.json.value]; + } + + if (files && files.length > 0) { + from(files) + .pipe(mergeMap((file) => this.uploadRawContent(file))) + .subscribe( + (res) => filesSaved.push(res), + (error) => this.logService.error(`Error uploading file. See console output for more details. ${error}` ), + () => { + this.field.form.values[this.field.id] = filesSaved; + this.hasFile = true; + } + ); + } + } + + getIcon(mimeType) { + return this.thumbnailService.getMimeTypeIcon(mimeType); + } + + private uploadRawContent(file): Observable<any> { + return this.formCloudService.createTemporaryRawRelatedContent(file, this.field.form.nodeId) + .pipe( + map((response: any) => { + this.logService.info(response); + return { nodeId : response.id}; + }) + ); + } + + getMultipleFileParam() { + if (this.field && + this.field.params && + this.field.params.multiple) { + this.multipleOption = this.field.params.multiple ? 'multiple' : ''; + } + } + + private removeElementFromList(file) { + const index = this.field.value.indexOf(file); + + // remove from content too + + if (index !== -1) { + this.field.value.splice(index, 1); + this.field.json.value = this.field.value; + this.field.updateForm(); + } + + this.hasFile = this.field.value.length > 0; + + this.resetFormValueWithNoFiles(); + } + + private resetFormValueWithNoFiles() { + if (this.field.value.length === 0) { + this.field.value = []; + this.field.json.value = []; + } + } + + fileClicked(contentLinkModel: any): void { + + } +} diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts new file mode 100644 index 0000000000..74f71a73c0 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -0,0 +1,47 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { TemplateModule, FormBaseModule, PipeModule, CoreModule } from '@alfresco/adf-core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { FormCloudComponent } from './components/form-cloud.component'; +import { UploadCloudWidgetComponent } from './components/upload-cloud.widget'; +import { MaterialModule } from '../material.module'; + +@NgModule({ + imports: [ + CommonModule, + PipeModule, + TemplateModule, + FlexLayoutModule, + MaterialModule, + FormsModule, + ReactiveFormsModule, + FormBaseModule, + CoreModule + ], + declarations: [FormCloudComponent, UploadCloudWidgetComponent], + entryComponents: [ + UploadCloudWidgetComponent + ], + exports: [ + FormCloudComponent, UploadCloudWidgetComponent + ] +}) +export class FormCloudModule { } diff --git a/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts b/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts new file mode 100644 index 0000000000..988c7954f4 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/mocks/cloud-form.mock.ts @@ -0,0 +1,686 @@ +/*! + * @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. + */ + +export const cloudFormMock = { + 'formRepresentation': { + 'id': 'form-b661635a-dc3e-4557-914a-3498ed47189c', + 'name': 'form-with-all-fields', + 'description': '', + 'version': 0, + 'formDefinition': { + 'tabs': [], + 'fields': [ + { + 'fieldType': 'ContainerRepresentation', + 'id': '26b10e64-0403-4686-a75b-0d45279ce3a8', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'text1', + 'name': 'Text1', + 'type': 'text', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'minValue': null, + 'maxValue': null, + 'regexPattern': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'text2', + 'name': 'Text2', + 'type': 'text', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'minValue': null, + 'maxValue': null, + 'regexPattern': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '69c1390a-8d8d-423c-8efb-8e43401efa42', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'multilinetext1', + 'name': 'Multiline text1', + 'type': 'multi-line-text', + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'regexPattern': null, + 'required': false, + 'readOnly': true, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'multilinetext2', + 'name': 'Multiline text2', + 'type': 'multi-line-text', + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'minLength': 0, + 'maxLength': 0, + 'regexPattern': null, + 'required': false, + 'readOnly': true, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': 'df046463-2d65-4388-9ee1-0e1517985215', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'number1', + 'overrideId': false, + 'name': 'Number1', + 'type': 'integer', + 'colspan': 1, + 'placeholder': null, + 'readOnly': true, + 'minValue': null, + 'maxValue': null, + 'required': false, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'number2', + 'overrideId': false, + 'name': 'Number2', + 'type': 'integer', + 'colspan': 1, + 'placeholder': null, + 'readOnly': true, + 'minValue': null, + 'maxValue': null, + 'required': false, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '9672cc7b-1959-49c9-96be-3816e57bdfc1', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'checkbox1', + 'name': 'Checkbox1', + 'type': 'boolean', + 'required': false, + 'readOnly': true, + 'colspan': 1, + 'overrideId': false, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'checkbox2', + 'name': 'Checkbox2', + 'type': 'boolean', + 'required': false, + 'readOnly': true, + 'colspan': 1, + 'overrideId': false, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '054d193e-a899-4494-9a3e-b489315b7d57', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'dropdown1', + 'name': 'Dropdown1', + 'type': 'dropdown', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'optionType': 'manual', + 'options': [], + 'endpoint': null, + 'requestHeaders': null, + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'dropdown2', + 'name': 'Dropdown2', + 'type': 'dropdown', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'optionType': 'manual', + 'options': [], + 'endpoint': null, + 'requestHeaders': null, + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '1f8f0b66-e022-4667-91b4-bbbf2ddc36fb', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'amount1', + 'name': 'Amount1', + 'type': 'amount', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': '123', + 'minValue': null, + 'maxValue': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + }, + 'enableFractions': false, + 'currency': '$' + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'amount2', + 'name': 'Amount2', + 'type': 'amount', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': '123', + 'minValue': null, + 'maxValue': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + }, + 'enableFractions': false, + 'currency': '$' + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '541a368b-67ee-4a7c-ae7e-232c050b9e24', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'date1', + 'name': 'Date1', + 'type': 'date', + 'overrideId': false, + 'required': false, + 'readOnly': true, + 'colspan': 1, + 'placeholder': null, + 'minValue': null, + 'maxValue': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + }, + 'dateDisplayFormat': 'D-M-YYYY' + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'date2', + 'name': 'Date2', + 'type': 'date', + 'overrideId': false, + 'required': false, + 'readOnly': true, + 'colspan': 1, + 'placeholder': null, + 'minValue': null, + 'maxValue': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + }, + 'dateDisplayFormat': 'D-M-YYYY' + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': 'e79cb7e2-3dc1-4c79-8158-28662c28a9f3', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'radiobuttons1', + 'name': 'Radio buttons1', + 'type': 'radio-buttons', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'optionType': 'manual', + 'options': [ + { + 'id': 'option_1', + 'name': 'Option 1' + }, + { + 'id': 'option_2', + 'name': 'Option 2' + } + ], + 'endpoint': null, + 'requestHeaders': null, + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'radiobuttons2', + 'name': 'Radio buttons2', + 'type': 'radio-buttons', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'optionType': 'manual', + 'options': [ + { + 'id': 'option_1', + 'name': 'Option 1' + }, + { + 'id': 'option_2', + 'name': 'Option 2' + } + ], + 'endpoint': null, + 'requestHeaders': null, + 'restUrl': null, + 'restResponsePath': null, + 'restIdProperty': null, + 'restLabelProperty': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '7c01ed35-be86-4be7-9c28-ed640a5a2ae1', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'AttachFileFieldRepresentation', + 'id': 'attachfile1', + 'name': 'Attach file1', + 'type': 'upload', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2, + 'fileSource': { + 'serviceId': 'all-file-sources', + 'name': 'All file sources' + }, + 'multiple': false, + 'link': false + } + } + ], + '2': [ + { + 'fieldType': 'AttachFileFieldRepresentation', + 'id': 'attachfile2', + 'name': 'Attach file2', + 'type': 'upload', + 'value': null, + 'required': false, + 'readOnly': true, + 'overrideId': false, + 'colspan': 1, + 'placeholder': null, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2, + 'fileSource': { + 'serviceId': 'all-file-sources', + 'name': 'All file sources' + }, + 'multiple': false, + 'link': false + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '07b13b96-d469-4a1e-8a9a-9bb957c68869', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'displayvalue1', + 'name': 'Display value1', + 'type': 'readonly', + 'value': 'No field selected', + 'readOnly': true, + 'required': false, + 'overrideId': false, + 'colspan': 1, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2, + 'field': { + 'id': 'displayvalue', + 'name': 'Display value', + 'type': 'text' + } + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'displayvalue2', + 'name': 'Display value2', + 'type': 'readonly', + 'value': 'No field selected', + 'readOnly': true, + 'required': false, + 'overrideId': false, + 'colspan': 1, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2, + 'field': { + 'id': 'displayvalue', + 'name': 'Display value', + 'type': 'text' + } + } + } + ] + } + }, + { + 'fieldType': 'ContainerRepresentation', + 'id': '1576ef25-c842-494c-ab84-265a1e3bf68d', + 'name': 'Label', + 'type': 'container', + 'tab': null, + 'numberOfColumns': 2, + 'fields': { + '1': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'displaytext1', + 'name': 'Display text1', + 'type': 'readonly-text', + 'value': 'Display text as part of the form', + 'readOnly': true, + 'required': false, + 'overrideId': false, + 'colspan': 1, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ], + '2': [ + { + 'fieldType': 'FormFieldRepresentation', + 'id': 'displaytext2', + 'name': 'Display text2', + 'type': 'readonly-text', + 'value': 'Display text as part of the form', + 'readOnly': true, + 'required': false, + 'overrideId': false, + 'colspan': 1, + 'visibilityCondition': null, + 'params': { + 'existingColspan': 1, + 'maxColspan': 2 + } + } + ] + } + } + ], + 'outcomes': [], + 'javascriptEvents': [], + 'className': '', + 'style': '', + 'customFieldTemplates': {}, + 'metadata': {}, + 'variables': [ + { + 'name': 'FormVarStr', + 'type': 'string', + 'value': '' + }, + { + 'name': 'FormVarInt', + 'type': 'integer', + 'value': '' + }, + { + 'name': 'FormVarBool', + 'type': 'boolean', + 'value': '' + }, + { + 'name': 'FormVarDate', + 'type': 'date', + 'value': '' + }, + { + 'name': 'NewVar', + 'type': 'string', + 'value': '' + } + ], + 'customFieldsValueInfo': {}, + 'gridsterForm': false + } + }, + 'processScopeIdentifiers': [] +}; diff --git a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts new file mode 100644 index 0000000000..7a9b1a5fdf --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts @@ -0,0 +1,233 @@ +/*! + * @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 { FormCloudService } from '../services/form-cloud.service'; +import { FormCloud } from './form-cloud.model'; +import { TabModel, FormFieldModel, ContainerModel, FormOutcomeModel, FormFieldTypes } from '@alfresco/adf-core'; + +describe('FormCloud', () => { + + let formCloudService: FormCloudService; + + beforeEach(() => { + formCloudService = new FormCloudService(null, null, null); + }); + + it('should store original json', () => { + const json = {formRepresentation: {formDefinition: {}}}; + const form = new FormCloud(json); + expect(form.json).toBe(json); + }); + + it('should setup properties with json', () => { + const json = {formRepresentation: { + id: '<id>', + name: '<name>', + taskId: '<task-id>', + taskName: '<task-name>' + }}; + const form = new FormCloud(json); + + Object.keys(json).forEach((key) => { + expect(form[key]).toEqual(form[key]); + }); + }); + + it('should take form name when task name is missing', () => { + const json = {formRepresentation: { + id: '<id>', + name: '<name>', + formDefinition: {} + }}; + const form = new FormCloud(json); + expect(form.taskName).toBe(json.formRepresentation.name); + }); + + it('should set readonly state from params', () => { + const form = new FormCloud({}, null, true); + expect(form.readOnly).toBeTruthy(); + }); + + it('should check tabs', () => { + const form = new FormCloud(); + + form.tabs = null; + expect(form.hasTabs()).toBeFalsy(); + + form.tabs = []; + expect(form.hasTabs()).toBeFalsy(); + + form.tabs = [new TabModel(null)]; + expect(form.hasTabs()).toBeTruthy(); + }); + + it('should check fields', () => { + const form = new FormCloud(); + + form.fields = null; + expect(form.hasFields()).toBeFalsy(); + + form.fields = []; + expect(form.hasFields()).toBeFalsy(); + + const field = new FormFieldModel(<any> form); + form.fields = [new ContainerModel(field)]; + expect(form.hasFields()).toBeTruthy(); + }); + + it('should check outcomes', () => { + const form = new FormCloud(); + + form.outcomes = null; + expect(form.hasOutcomes()).toBeFalsy(); + + form.outcomes = []; + expect(form.hasOutcomes()).toBeFalsy(); + + form.outcomes = [new FormOutcomeModel(null)]; + expect(form.hasOutcomes()).toBeTruthy(); + }); + + it('should parse tabs', () => { + const json = {formRepresentation: {formDefinition: { + tabs: [ + { id: 'tab1' }, + { id: 'tab2' } + ] + }}}; + + const form = new FormCloud(json); + expect(form.tabs.length).toBe(2); + expect(form.tabs[0].id).toBe('tab1'); + expect(form.tabs[1].id).toBe('tab2'); + }); + + it('should parse fields', () => { + const json = {formRepresentation: {formDefinition: { + fields: [ + { + id: 'field1', + type: FormFieldTypes.CONTAINER + }, + { + id: 'field2', + type: FormFieldTypes.CONTAINER + } + ] + }}}; + + const form = new FormCloud(json); + expect(form.fields.length).toBe(2); + expect(form.fields[0].id).toBe('field1'); + expect(form.fields[1].id).toBe('field2'); + }); + + it('should convert missing fields to empty collection', () => { + const json = {formRepresentation: {formDefinition: { + fields: null + }}}; + + const form = new FormCloud(json); + expect(form.fields).toBeDefined(); + expect(form.fields.length).toBe(0); + }); + + it('should put fields into corresponding tabs', () => { + const json = {formRepresentation: {formDefinition: { + tabs: [ + { id: 'tab1' }, + { id: 'tab2' } + ], + fields: [ + { id: 'field1', tab: 'tab1', type: FormFieldTypes.CONTAINER }, + { id: 'field2', tab: 'tab2', type: FormFieldTypes.CONTAINER }, + { id: 'field3', tab: 'tab1', type: FormFieldTypes.DYNAMIC_TABLE }, + { id: 'field4', tab: 'missing-tab', type: FormFieldTypes.DYNAMIC_TABLE } + ] + }}}; + + const form = new FormCloud(json); + expect(form.tabs.length).toBe(2); + expect(form.fields.length).toBe(4); + + const tab1 = form.tabs[0]; + expect(tab1.fields.length).toBe(2); + expect(tab1.fields[0].id).toBe('field1'); + expect(tab1.fields[1].id).toBe('field3'); + + const tab2 = form.tabs[1]; + expect(tab2.fields.length).toBe(1); + expect(tab2.fields[0].id).toBe('field2'); + }); + + it('should create standard form outcomes', () => { + const json = {formRepresentation: {formDefinition: { + fields: [ + { id: 'container1' } + ] + }}}; + + const form = new FormCloud(json); + expect(form.outcomes.length).toBe(3); + + expect(form.outcomes[0].id).toBe(FormCloud.SAVE_OUTCOME); + expect(form.outcomes[0].isSystem).toBeTruthy(); + + expect(form.outcomes[1].id).toBe(FormCloud.COMPLETE_OUTCOME); + expect(form.outcomes[1].isSystem).toBeTruthy(); + + expect(form.outcomes[2].id).toBe(FormCloud.START_PROCESS_OUTCOME); + expect(form.outcomes[2].isSystem).toBeTruthy(); + }); + + it('should create outcomes only when fields available', () => { + const json = {formRepresentation: {formDefinition: { + fields: null + }}}; + const form = new FormCloud(json); + expect(form.outcomes.length).toBe(0); + }); + + it('should use custom form outcomes', () => { + const json = {formRepresentation: {formDefinition: { + fields: [ + { id: 'container1' } + ]}, + outcomes: [ + { id: 'custom-1', name: 'custom 1' } + ] + }}; + + const form = new FormCloud(json); + expect(form.outcomes.length).toBe(2); + + expect(form.outcomes[0].id).toBe(FormCloud.SAVE_OUTCOME); + expect(form.outcomes[0].isSystem).toBeTruthy(); + + expect(form.outcomes[1].id).toBe('custom-1'); + expect(form.outcomes[1].isSystem).toBeFalsy(); + }); + + it('should get field by id', () => { + const form = new FormCloud({}, null, false, formCloudService); + const field: any = { id: 'field1' }; + spyOn(form, 'getFormFields').and.returnValue([field]); + + const result = form.getFieldById('field1'); + expect(result).toBe(field); + }); +}); diff --git a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts new file mode 100644 index 0000000000..f778b25c91 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts @@ -0,0 +1,247 @@ +/*! + * @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 { + TabModel, FormWidgetModel, FormOutcomeModel, FormValues, + FormWidgetModelCache, FormFieldModel, ContainerModel, FormFieldTypes, + ValidateFormFieldEvent, FormFieldValidator, FormFieldTemplates } from '@alfresco/adf-core'; +import { FormCloudService } from '../services/form-cloud.service'; +import { TaskVariableCloud } from './task-variable-cloud.model'; + +export class FormCloud { + + static SAVE_OUTCOME: string = '$save'; + static COMPLETE_OUTCOME: string = '$complete'; + static START_PROCESS_OUTCOME: string = '$startProcess'; + + readonly id: string; + nodeId: string; + readonly name: string; + readonly taskId: string; + readonly taskName: string; + private _isValid: boolean = true; + + get isValid(): boolean { + return this._isValid; + } + + readonly selectedOutcome: string; + readonly json: any; + + readOnly: boolean; + processDefinitionId: any; + className: string; + values: FormValues = {}; + + tabs: TabModel[] = []; + fields: FormWidgetModel[] = []; + outcomes: FormOutcomeModel[] = []; + customFieldTemplates: FormFieldTemplates = {}; + fieldValidators: FormFieldValidator[] = []; + + constructor(json?: any, formData?: TaskVariableCloud[], readOnly: boolean = false, protected formService?: FormCloudService) { + this.readOnly = readOnly; + + if (json && json.formRepresentation && json.formRepresentation.formDefinition) { + this.json = json; + this.id = json.formRepresentation.id; + this.name = json.formRepresentation.name; + this.taskId = json.formRepresentation.taskId; + this.taskName = json.formRepresentation.taskName || json.formRepresentation.name; + this.processDefinitionId = json.formRepresentation.processDefinitionId; + this.customFieldTemplates = json.formRepresentation.formDefinition.customFieldTemplates || {}; + this.selectedOutcome = json.formRepresentation.formDefinition.selectedOutcome || {}; + this.className = json.formRepresentation.formDefinition.className || ''; + + const tabCache: FormWidgetModelCache<TabModel> = {}; + + this.tabs = (json.formRepresentation.formDefinition.tabs || []).map((t) => { + const model = new TabModel(<any> this, t); + tabCache[model.id] = model; + return model; + }); + + this.fields = this.parseRootFields(json); + + if (formData) { + this.loadData(formData); + } + + for (let i = 0; i < this.fields.length; i++) { + const field = this.fields[i]; + if (field.tab) { + const tab = tabCache[field.tab]; + if (tab) { + tab.fields.push(field); + } + } + } + + if (json.formRepresentation.formDefinition.fields) { + const saveOutcome = new FormOutcomeModel(<any> this, { + id: FormCloud.SAVE_OUTCOME, + name: 'SAVE', + isSystem: true + }); + const completeOutcome = new FormOutcomeModel(<any> this, { + id: FormCloud.COMPLETE_OUTCOME, + name: 'COMPLETE', + isSystem: true + }); + const startProcessOutcome = new FormOutcomeModel(<any> this, { + id: FormCloud.START_PROCESS_OUTCOME, + name: 'START PROCESS', + isSystem: true + }); + + const customOutcomes = (json.formRepresentation.outcomes || []).map((obj) => new FormOutcomeModel(<any> this, obj)); + + this.outcomes = [saveOutcome].concat( + customOutcomes.length > 0 ? customOutcomes : [completeOutcome, startProcessOutcome] + ); + } + } + + this.validateForm(); + } + + hasTabs(): boolean { + return this.tabs && this.tabs.length > 0; + } + + hasFields(): boolean { + return this.fields && this.fields.length > 0; + } + + hasOutcomes(): boolean { + return this.outcomes && this.outcomes.length > 0; + } + + getFieldById(fieldId: string): FormFieldModel { + return this.getFormFields().find((field) => field.id === fieldId); + } + + onFormFieldChanged(field: FormFieldModel) { + this.validateField(field); + } + + getFormFields(): FormFieldModel[] { + const formFields: FormFieldModel[] = []; + + for (let i = 0; i < this.fields.length; i++) { + const field = this.fields[i]; + + if (field instanceof ContainerModel) { + const container = <ContainerModel> field; + formFields.push(container.field); + + container.field.columns.forEach((column) => { + formFields.push(...column.fields); + }); + } + } + + return formFields; + } + + markAsInvalid() { + this._isValid = false; + } + + validateForm() { + const errorsField: FormFieldModel[] = []; + + const fields = this.getFormFields(); + for (let i = 0; i < fields.length; i++) { + if (!fields[i].validate()) { + errorsField.push(fields[i]); + } + } + + this._isValid = errorsField.length > 0 ? false : true; + } + + /** + * Validates a specific form field, triggers form validation. + * + * @param field Form field to validate. + * @memberof FormCloud + */ + validateField(field: FormFieldModel) { + if (!field) { + return; + } + + const validateFieldEvent = new ValidateFormFieldEvent(<any> this, field); + + if (!validateFieldEvent.isValid) { + this._isValid = false; + return; + } + + if (validateFieldEvent.defaultPrevented) { + return; + } + + if (!field.validate()) { + this._isValid = false; + } + + this.validateForm(); + } + + // Activiti supports 3 types of root fields: container|group|dynamic-table + private parseRootFields(json: any): FormWidgetModel[] { + let fields = []; + + if (json.formRepresentation.fields) { + fields = json.formRepresentation.fields; + } else if (json.formRepresentation.formDefinition && json.formRepresentation.formDefinition.fields) { + fields = json.formRepresentation.formDefinition.fields; + } + + const formWidgetModel: FormWidgetModel[] = []; + + for (const field of fields) { + if (field.type === FormFieldTypes.DISPLAY_VALUE) { + // workaround for dynamic table on a completed/readonly form + if (field.params) { + const originalField = field.params['field']; + if (originalField.type === FormFieldTypes.DYNAMIC_TABLE) { + formWidgetModel.push(new ContainerModel(new FormFieldModel(<any> this, field))); + } + } + } else { + formWidgetModel.push(new ContainerModel(new FormFieldModel(<any> this, field))); + } + } + + return formWidgetModel; + } + + // Loads external data and overrides field values + // Typically used when form definition and form data coming from different sources + private loadData(formData: TaskVariableCloud[]) { + for (const field of this.getFormFields()) { + const fieldValue = formData.find((value) => { return value.name === field.id; }); + if (fieldValue) { + field.json.value = fieldValue.value; + field.value = field.parseValue(field.json); + } + } + } +} diff --git a/lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts new file mode 100644 index 0000000000..05ef43f792 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts @@ -0,0 +1,25 @@ +/*! + * @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. + */ + +export class TaskVariableCloud { + name: string; + value: any; + constructor(obj) { + this.name = obj.name || null; + this.value = obj.value || null; + } +} diff --git a/lib/process-services-cloud/src/lib/form/public-api.ts b/lib/process-services-cloud/src/lib/form/public-api.ts new file mode 100644 index 0000000000..d316dbb6a7 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/public-api.ts @@ -0,0 +1,22 @@ +/*! + * @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. + */ + +export * from './models/form-cloud.model'; +export * from './models/task-variable-cloud.model'; +export * from './components/form-cloud.component'; +export * from './components/upload-cloud.widget'; +export * from './services/form-cloud.service'; diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts new file mode 100644 index 0000000000..2714d0508b --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts @@ -0,0 +1,162 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { FormCloudService } from './form-cloud.service'; +import { AlfrescoApiService, CoreModule, setupTestBed, AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core'; +import { of } from 'rxjs'; + +declare let jasmine: any; + +const responseBody = { + entry: + { id: 'id', name: 'name', formKey: 'form-key' } +}; + +const alfrescoApiServiceStub = { + getInstance() { }, + load() { } +}; + +const oauth2Auth = jasmine.createSpyObj('oauth2Auth', ['callCustomApi']); + +describe('Form Cloud service', () => { + + let service: FormCloudService; + let apiService: AlfrescoApiService; + const appName = 'app-name'; + const taskId = 'task-id'; + + setupTestBed({ + imports: [ + NoopAnimationsModule, + CoreModule.forRoot() + ], + providers: [ + FormCloudService, + { provide: AlfrescoApiService, useValue: alfrescoApiServiceStub }, + { provide: AppConfigService, useClass: AppConfigServiceMock } + ] + }); + + beforeEach(() => { + service = TestBed.get(FormCloudService); + apiService = TestBed.get(AlfrescoApiService); + spyOn(apiService, 'getInstance').and.returnValue({ oauth2Auth: oauth2Auth }); + }); + + describe('Form tests', () => { + it('should fetch and parse form', (done) => { + const formId = 'form-id'; + oauth2Auth.callCustomApi.and.returnValue(Promise.resolve({ formRepresentation: { id: formId, name: 'task-form', taskId: 'task-id' } })); + + service.getForm(appName, formId).subscribe((result) => { + expect(result).toBeDefined(); + expect(result.formRepresentation.id).toBe(formId); + expect(result.formRepresentation.name).toBe('task-form'); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/form/v1/forms/${formId}`)).toBeTruthy(); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET'); + done(); + }); + }); + + it('should parse valid form json ', () => { + const formId = 'form-id'; + const json = { formRepresentation: { id: formId, name: 'task-form', taskId: 'task-id', formDefinition: {} } }; + + const result = service.parseForm(json); + expect(result).toBeDefined(); + expect(result.id).toBe(formId); + expect(result.name).toBe('task-form'); + }); + }); + + describe('Task tests', () => { + it('should fetch and parse task', (done) => { + oauth2Auth.callCustomApi.and.returnValue(Promise.resolve(responseBody)); + + service.getTask(appName, taskId).subscribe((result) => { + expect(result).toBeDefined(); + expect(result.id).toBe(responseBody.entry.id); + expect(result.name).toBe(responseBody.entry.name); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/rb/v1/tasks/${taskId}`)).toBeTruthy(); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET'); + done(); + }); + + }); + + it('should fetch task variables', (done) => { + oauth2Auth.callCustomApi.and.returnValue(Promise.resolve({ content: { name: 'abc' } })); + + service.getTaskVariables(appName, taskId).subscribe((result: any) => { + expect(result).toBeDefined(); + expect(result.name).toBe('abc'); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/rb/v1/tasks/${taskId}/variables`)).toBeTruthy(); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET'); + done(); + }); + + }); + + it('should fetch task form', (done) => { + spyOn(service, 'getTask').and.returnValue(of(responseBody.entry)); + spyOn(service, 'getForm').and.returnValue(of({ formRepresentation: { name: 'task-form' } })); + + service.getTaskForm(appName, taskId).subscribe((result) => { + expect(result).toBeDefined(); + expect(result.formRepresentation.name).toBe('task-form'); + expect(result.formRepresentation.taskId).toBe(responseBody.entry.id); + expect(result.formRepresentation.taskName).toBe(responseBody.entry.name); + done(); + }); + + }); + + it('should save task form', (done) => { + oauth2Auth.callCustomApi.and.returnValue(Promise.resolve(responseBody)); + const formId = 'form-id'; + + service.saveTaskForm(appName, taskId, formId, {}).subscribe((result: any) => { + expect(result).toBeDefined(); + expect(result.id).toBe('id'); + expect(result.name).toBe('name'); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/form/v1/forms/${formId}/save`)).toBeTruthy(); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('POST'); + done(); + }); + + }); + + it('should complete task form', (done) => { + oauth2Auth.callCustomApi.and.returnValue(Promise.resolve(responseBody)); + const formId = 'form-id'; + + service.completeTaskForm(appName, taskId, formId, {}, '').subscribe((result: any) => { + expect(result).toBeDefined(); + expect(result.id).toBe('id'); + expect(result.name).toBe('name'); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/form/v1/forms/${formId}/submit`)).toBeTruthy(); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('POST'); + done(); + }); + + }); + + }); +}); diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts new file mode 100644 index 0000000000..1c4a7ab0ae --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -0,0 +1,232 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { AlfrescoApiService, LogService, FormValues, AppConfigService, FormOutcomeModel } from '@alfresco/adf-core'; +import { throwError, Observable, from } from 'rxjs'; +import { catchError, map, switchMap } from 'rxjs/operators'; +import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model'; +import { SaveFormRepresentation, CompleteFormRepresentation } from '@alfresco/js-api'; +import { FormCloud } from '../models/form-cloud.model'; +import { TaskVariableCloud } from '../models/task-variable-cloud.model'; + +@Injectable({ + providedIn: 'root' +}) +export class FormCloudService { + + contentTypes = ['application/json']; accepts = ['application/json']; returnType = Object; + constructor( + private apiService: AlfrescoApiService, + private appConfigService: AppConfigService, + private logService: LogService + ) {} + + getTaskForm(appName: string, taskId: string): Observable<any> { + return this.getTask(appName, taskId).pipe( + switchMap((task: TaskDetailsCloudModel) => { + return this.getForm(appName, task.formKey).pipe( + map((form: any) => { + form.formRepresentation.taskId = task.id; + form.formRepresentation.taskName = task.name; + form.formRepresentation.processDefinitionId = task.processDefinitionId; + form.formRepresentation.processInstanceId = task.processInstanceId; + return form; + }) + ); + }) + ); + } + + saveTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues): Observable<TaskDetailsCloudModel> { + const apiUrl = this.buildSaveFormUrl(appName, formId); + const saveFormRepresentation = <SaveFormRepresentation> { values: formValues, taskId: taskId }; + return from(this.apiService + .getInstance() + .oauth2Auth.callCustomApi(apiUrl, 'POST', + null, null, null, + null, saveFormRepresentation, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } + + createTemporaryRawRelatedContent(file, nodeId): Observable<any> { + + const apiUrl = this.buildUploadUrl(nodeId); + + return from(this.apiService + .getInstance() + .oauth2Auth.callCustomApi(apiUrl, 'POST', + null, null, null, + { filedata: file, nodeType: 'cm:content' }, null, + ['multipart/form-data'], this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return (res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } + + completeTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues, outcome: string): Observable<TaskDetailsCloudModel> { + const apiUrl = this.buildSubmitFormUrl(appName, formId); + const completeFormRepresentation: any = <CompleteFormRepresentation> { values: formValues, taskId: taskId }; + if (outcome) { + completeFormRepresentation.outcome = outcome; + } + + return from(this.apiService + .getInstance() + .oauth2Auth.callCustomApi(apiUrl, 'POST', + null, null, null, + null, completeFormRepresentation, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } + + getTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { + const apiUrl = this.buildGetTaskUrl(appName, taskId); + return from(this.apiService + .getInstance() + .oauth2Auth.callCustomApi(apiUrl, 'GET', + null, null, null, + null, null, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return new TaskDetailsCloudModel(res.entry); + }), + catchError((err) => this.handleError(err)) + ); + } + + getProcessStorageFolderTask(appName: string, taskId: string): Observable<any> { + const apiUrl = this.buildFolderTask(appName, taskId); + return from(this.apiService + .getInstance() + .oauth2Auth.callCustomApi(apiUrl, 'GET', + null, null, null, + null, null, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return res.nodeId; + }), + catchError((err) => this.handleError(err)) + ); + } + + getTaskVariables(appName: string, taskId: string): Observable<TaskVariableCloud[]> { + const apiUrl = this.buildGetTaskVariablesUrl(appName, taskId); + return from(this.apiService + .getInstance() + .oauth2Auth.callCustomApi(apiUrl, 'GET', + null, null, null, + null, null, + this.contentTypes, this.accepts, + this.returnType, null, null) + ).pipe( + map((res: any) => { + return <TaskVariableCloud[]> res.content; + }), + catchError((err) => this.handleError(err)) + ); + } + + getForm(appName: string, taskId: string): Observable<any> { + const apiUrl = this.buildGetFormUrl(appName, taskId); + const bodyParam = {}, pathParams = {}, queryParams = {}, headerParams = {}, + formParams = {}; + + return from( + this.apiService + .getInstance() + .oauth2Auth.callCustomApi( + apiUrl, 'GET', pathParams, queryParams, + headerParams, formParams, bodyParam, + this.contentTypes, this.accepts, this.returnType, null, null) + ).pipe( + catchError((err) => this.handleError(err)) + ); + } + + parseForm(json: any, data?: TaskVariableCloud[], readOnly: boolean = false): FormCloud { + if (json) { + const form = new FormCloud(json, data, readOnly, this); + if (!json.fields) { + form.outcomes = [ + new FormOutcomeModel(<any> form, { + id: '$save', + name: FormOutcomeModel.SAVE_ACTION, + isSystem: true + }) + ]; + } + return form; + } + return null; + } + + private buildGetTaskUrl(appName: string, taskId: string): string { + return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks/${taskId}`; + } + + private buildGetFormUrl(appName: string, formId: string): string { + return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}`; + } + + private buildSaveFormUrl(appName: string, formId: string): string { + return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}/save`; + } + + private buildUploadUrl(nodeId: string): string { + return `${this.appConfigService.get('ecmHost')}/alfresco/api/-default-/public/alfresco/versions/1/nodes/${nodeId}/children`; + } + + private buildSubmitFormUrl(appName: string, formId: string): string { + return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}/submit`; + } + + private buildGetTaskVariablesUrl(appName: string, taskId: string): string { + return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks/${taskId}/variables`; + } + + private buildFolderTask(appName: string, taskId: string): string { + return `${this.appConfigService.get('bpmHost')}/${appName}/process-storage/v1/folders/tasks/${taskId}`; + } + + private handleError(error: any) { + this.logService.error(error); + return throwError(error || 'Server error'); + } + +} diff --git a/lib/process-services-cloud/src/lib/group/group-cloud.module.ts b/lib/process-services-cloud/src/lib/group/group-cloud.module.ts index 4c28ab8262..7148bce5fd 100644 --- a/lib/process-services-cloud/src/lib/group/group-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/group/group-cloud.module.ts @@ -20,7 +20,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; -import { TemplateModule, FormModule, PipeModule, CoreModule } from '@alfresco/adf-core'; +import { TemplateModule, PipeModule, CoreModule } from '@alfresco/adf-core'; import { MaterialModule } from '../material.module'; import { GroupCloudComponent } from './components/group-cloud.component'; import { InitialGroupNamePipe } from './pipe/group-initial.pipe'; @@ -34,7 +34,6 @@ import { InitialGroupNamePipe } from './pipe/group-initial.pipe'; MaterialModule, FormsModule, ReactiveFormsModule, - FormModule, CoreModule ], declarations: [GroupCloudComponent, InitialGroupNamePipe], diff --git a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts index 2d06817264..248bf6f02e 100644 --- a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts @@ -21,6 +21,7 @@ import { AppListCloudModule } from './app/app-list-cloud.module'; import { TaskCloudModule } from './task/task-cloud.module'; import { ProcessCloudModule } from './process/process-cloud.module'; import { GroupCloudModule } from './group/group-cloud.module'; +import { FormCloudModule } from './form/form-cloud.module'; @NgModule({ imports: [ @@ -28,7 +29,8 @@ import { GroupCloudModule } from './group/group-cloud.module'; AppListCloudModule, ProcessCloudModule, TaskCloudModule, - GroupCloudModule + GroupCloudModule, + FormCloudModule ], providers: [ { @@ -44,7 +46,8 @@ import { GroupCloudModule } from './group/group-cloud.module'; AppListCloudModule, ProcessCloudModule, TaskCloudModule, - GroupCloudModule + GroupCloudModule, + FormCloudModule ] }) export class ProcessServicesCloudModule { } diff --git a/lib/process-services-cloud/src/lib/process/process-cloud.module.ts b/lib/process-services-cloud/src/lib/process/process-cloud.module.ts index 757c16713b..ccecbc4a01 100644 --- a/lib/process-services-cloud/src/lib/process/process-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process/process-cloud.module.ts @@ -20,7 +20,7 @@ import { ProcessFiltersCloudModule } from './process-filters/process-filters-clo import { ProcessListCloudModule } from './process-list/process-list-cloud.module'; import { StartProcessCloudModule } from './start-process/start-process-cloud.module'; import { CoreModule } from '@alfresco/adf-core'; -import { ProcessHeaderCloudModule } from './process-header/public-api'; +import { ProcessHeaderCloudModule } from './process-header/process-header-cloud.module'; @NgModule({ imports: [ diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts index bc60f506f3..d6eddbe24d 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts @@ -17,7 +17,7 @@ import { Component, Input, OnChanges } from '@angular/core'; import { CardViewItem, CardViewTextItemModel, TranslationService, AppConfigService, CardViewDateItemModel, CardViewBaseItemModel } from '@alfresco/adf-core'; -import { ProcessInstanceCloud } from '../../start-process/public-api'; +import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model'; import { ProcessHeaderCloudService } from '../services/process-header-cloud.service'; @Component({ diff --git a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts index a78a257258..3eb4eedcd4 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts @@ -19,7 +19,7 @@ import { AlfrescoApiService, LogService, AppConfigService } from '@alfresco/adf- import { Injectable } from '@angular/core'; import { Observable, from, throwError } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; -import { ProcessInstanceCloud } from '../../start-process/public-api'; +import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model'; @Injectable({ providedIn: 'root' diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts index dc16962fa0..5244b43b67 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts @@ -31,7 +31,7 @@ import { UserPreferenceValues } from '@alfresco/adf-core'; import { PeopleCloudComponent } from './people-cloud/people-cloud.component'; -import { GroupCloudComponent } from '../../../../lib/group/public-api'; +import { GroupCloudComponent } from '../../../../lib/group/components/group-cloud.component'; @Component({ selector: 'adf-cloud-start-task', diff --git a/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts b/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts index 73138d8666..8535abf100 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts @@ -19,7 +19,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; import { MaterialModule } from '../../material.module'; -import { TemplateModule, FormModule, PipeModule, CoreModule } from '@alfresco/adf-core'; +import { TemplateModule, PipeModule, CoreModule } from '@alfresco/adf-core'; import { StartTaskCloudComponent } from './components/start-task-cloud.component'; import { StartTaskCloudService } from './services/start-task-cloud.service'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @@ -36,7 +36,6 @@ import { GroupCloudModule } from '../../group/group-cloud.module'; FormsModule, ReactiveFormsModule, GroupCloudModule, - FormModule, GroupCloudModule, CoreModule ], diff --git a/lib/process-services-cloud/src/lib/task/start-task/testing/start-task-cloud.testing.module.ts b/lib/process-services-cloud/src/lib/task/start-task/testing/start-task-cloud.testing.module.ts index 2c8281292d..07c142d892 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/testing/start-task-cloud.testing.module.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/testing/start-task-cloud.testing.module.ts @@ -21,7 +21,7 @@ import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; import { MaterialModule } from '../../../material.module'; import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; -import { TemplateModule, TranslateLoaderService, FormModule, PipeModule } from '@alfresco/adf-core'; +import { TemplateModule, TranslateLoaderService, PipeModule } from '@alfresco/adf-core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { StartTaskCloudModule } from '../start-task-cloud.module'; @@ -41,7 +41,6 @@ import { StartTaskCloudModule } from '../start-task-cloud.module'; MaterialModule, FormsModule, ReactiveFormsModule, - FormModule, PipeModule, StartTaskCloudModule ] diff --git a/lib/process-services-cloud/src/public-api.ts b/lib/process-services-cloud/src/public-api.ts index 37fd3dd798..5bbf0fc44a 100644 --- a/lib/process-services-cloud/src/public-api.ts +++ b/lib/process-services-cloud/src/public-api.ts @@ -22,3 +22,4 @@ export * from './lib/process/public-api'; export * from './lib/task/public-api'; export * from './lib/group/public-api'; export * from './lib/services/public-api'; +export * from './lib/form/public-api'; diff --git a/lib/process-services/form/form.component.html b/lib/process-services/form/form.component.html new file mode 100644 index 0000000000..116db6e634 --- /dev/null +++ b/lib/process-services/form/form.component.html @@ -0,0 +1,46 @@ +<div *ngIf="!hasForm()"> + <ng-content select="[empty-form]"> + </ng-content> +</div> + +<div *ngIf="hasForm()" class="adf-form-container"> + <mat-card> + <mat-card-header> + <mat-card-title> + <h4> + <div *ngIf="showValidationIcon" class="adf-form-validation-button"> + <i id="adf-valid-form-icon" class="material-icons" + *ngIf="form.isValid; else no_valid_form">check_circle</i> + <ng-template #no_valid_form> + <i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i> + </ng-template> + </div> + <div *ngIf="showRefreshButton" class="adf-form-reload-button"> + <button mat-icon-button (click)="onRefreshClicked()"> + <mat-icon>refresh</mat-icon> + </button> + </div> + <span *ngIf="isTitleEnabled()" class="adf-form-title"> + {{form.taskName}} + <ng-container *ngIf="!form.taskName"> + {{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}} + </ng-container> + </span> + + </h4> + </mat-card-title> + </mat-card-header> + <mat-card-content> + <adf-form-renderer [formDefinition]="form"> + </adf-form-renderer> + </mat-card-content> + <mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions"> + <button [id]="'adf-form-'+ outcome.name | formatSpace" *ngFor="let outcome of form.outcomes" + [color]="getColorForOutcome(outcome.name)" mat-button [disabled]="!isOutcomeButtonEnabled(outcome)" + [class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)" + (click)="onOutcomeClicked(outcome)"> + {{outcome.name | translate | uppercase }} + </button> + </mat-card-actions> + </mat-card> +</div> diff --git a/lib/core/form/components/form.component.spec.ts b/lib/process-services/form/form.component.spec.ts similarity index 97% rename from lib/core/form/components/form.component.spec.ts rename to lib/process-services/form/form.component.spec.ts index 5e01552d86..a9bdd4f0ff 100644 --- a/lib/core/form/components/form.component.spec.ts +++ b/lib/process-services/form/form.component.spec.ts @@ -16,15 +16,11 @@ */ import { SimpleChange } from '@angular/core'; -import { LogService } from '../../services/log.service'; import { Observable, of, throwError } from 'rxjs'; -import { fakeForm } from '../../mock'; -import { FormService } from './../services/form.service'; -import { NodeService } from './../services/node.service'; -import { WidgetVisibilityService } from './../services/widget-visibility.service'; +import { FormFieldModel, FormFieldTypes, FormModel, FormOutcomeEvent, FormOutcomeModel, + FormService, WidgetVisibilityService, NodeService, LogService, ContainerModel, fakeForm, FormRenderingService } from '@alfresco/adf-core'; + import { FormComponent } from './form.component'; -import { FormFieldModel, FormFieldTypes, FormModel, FormOutcomeEvent, FormOutcomeModel } from './widgets/index'; -import { ContainerModel } from './widgets/core/container.model'; describe('FormComponent', () => { @@ -33,6 +29,7 @@ describe('FormComponent', () => { let visibilityService: WidgetVisibilityService; let nodeService: NodeService; let logService: LogService; + let formRenderingService: FormRenderingService; beforeEach(() => { logService = new LogService(null); @@ -40,7 +37,8 @@ describe('FormComponent', () => { spyOn(visibilityService, 'refreshVisibility').and.stub(); formService = new FormService(null, null, logService); nodeService = new NodeService(null); - formComponent = new FormComponent(formService, visibilityService, null, nodeService); + formRenderingService = new FormRenderingService(); + formComponent = new FormComponent(formService, visibilityService, null, nodeService, formRenderingService); }); it('should check form', () => { @@ -57,13 +55,7 @@ describe('FormComponent', () => { expect(formModel.taskName).toBe(FormModel.UNSET_TASK_NAME); expect(formComponent.isTitleEnabled()).toBeTruthy(); - // override property as it's the readonly one - Object.defineProperty(formModel, 'taskName', { - enumerable: false, - configurable: false, - writable: false, - value: null - }); + formComponent.form = null; expect(formComponent.isTitleEnabled()).toBeFalsy(); }); diff --git a/lib/core/form/components/form.component.ts b/lib/process-services/form/form.component.ts similarity index 60% rename from lib/core/form/components/form.component.ts rename to lib/process-services/form/form.component.ts index 169a8a2dfd..d117f11e0c 100644 --- a/lib/core/form/components/form.component.ts +++ b/lib/process-services/form/form.component.ts @@ -15,40 +15,24 @@ * limitations under the License. */ -/* tslint:disable */ import { - Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, - Output, SimpleChanges, ViewEncapsulation + Component, EventEmitter, Input, Output, ViewEncapsulation, SimpleChanges, OnInit, OnDestroy, OnChanges } from '@angular/core'; -import { FormErrorEvent, FormEvent } from './../events/index'; -import { EcmModelService } from './../services/ecm-model.service'; -import { FormService } from './../services/form.service'; -import { NodeService } from './../services/node.service'; -import { ContentLinkModel } from './widgets/core/content-link.model'; -import { - FormFieldModel, FormModel, FormOutcomeEvent, FormOutcomeModel, - FormValues, FormFieldValidator -} from './widgets/core/index'; -import { Observable, of } from 'rxjs'; -import { WidgetVisibilityService } from './../services/widget-visibility.service'; +import { AttachFileWidgetComponent, AttachFolderWidgetComponent } from '../content-widget'; +import { EcmModelService, NodeService, WidgetVisibilityService, + FormService, FormRenderingService, FormBaseComponent, FormOutcomeModel, + ValidateFormEvent, FormEvent, FormErrorEvent, FormFieldModel, + FormModel, FormOutcomeEvent, FormValues, ContentLinkModel } from '@alfresco/adf-core'; + +import { Observable, of, Subscription } from 'rxjs'; import { switchMap } from 'rxjs/operators'; -import { ValidateFormEvent } from './../events/validate-form.event'; -import { Subscription } from 'rxjs'; @Component({ selector: 'adf-form', templateUrl: './form.component.html', - styleUrls: ['./form.component.scss'], encapsulation: ViewEncapsulation.None }) -export class FormComponent implements OnInit, OnChanges, OnDestroy { - - static SAVE_OUTCOME_ID: string = '$save'; - static COMPLETE_OUTCOME_ID: string = '$complete'; - static START_PROCESS_OUTCOME_ID: string = '$startProcess'; - static CUSTOM_OUTCOME_ID: string = '$custom'; - static COMPLETE_BUTTON_COLOR: string = 'primary'; - static COMPLETE_OUTCOME_NAME: string = 'COMPLETE'; +export class FormComponent extends FormBaseComponent implements OnInit, OnDestroy, OnChanges { /** Underlying form model instance. */ @Input() @@ -78,54 +62,6 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { @Input() data: FormValues; - /** Path of the folder where the metadata will be stored. */ - @Input() - path: string; - - /** Name to assign to the new node where the metadata are stored. */ - @Input() - nameNode: string; - - /** Toggle rendering of the form title. */ - @Input() - showTitle: boolean = true; - - /** Toggle rendering of the `Complete` outcome button. */ - @Input() - showCompleteButton: boolean = true; - - /** If true then the `Complete` outcome button is shown but it will be disabled. */ - @Input() - disableCompleteButton: boolean = false; - - /** If true then the `Start Process` outcome button is shown but it will be disabled. */ - @Input() - disableStartProcessButton: boolean = false; - - /** Toggle rendering of the `Save` outcome button. */ - @Input() - showSaveButton: boolean = true; - - /** Toggle debug options. */ - @Input() - showDebugButton: boolean = false; - - /** Toggle readonly state of the form. Forces all form widgets to render as readonly if enabled. */ - @Input() - readOnly: boolean = false; - - /** Toggle rendering of the `Refresh` button. */ - @Input() - showRefreshButton: boolean = true; - - /** Toggle rendering of the validation icon next to the form title. */ - @Input() - showValidationIcon: boolean = true; - - /** Contains a list of form field validator instances. */ - @Input() - fieldValidators: FormFieldValidator[] = []; - /** Emitted when the form is submitted with the `Save` or custom outcomes. */ @Output() formSaved: EventEmitter<FormModel> = new EventEmitter<FormModel>(); @@ -146,87 +82,18 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { @Output() formDataRefreshed: EventEmitter<FormModel> = new EventEmitter<FormModel>(); - /** Emitted when the supplied form values have a validation error.*/ - @Output() - formError: EventEmitter<FormFieldModel[]> = new EventEmitter<FormFieldModel[]>(); - - /** Emitted when any outcome is executed. Default behaviour can be prevented - * via `event.preventDefault()`. - */ - @Output() - executeOutcome: EventEmitter<FormOutcomeEvent> = new EventEmitter<FormOutcomeEvent>(); - - /** - * Emitted when any error occurs. - */ - @Output() - error: EventEmitter<any> = new EventEmitter<any>(); - debugMode: boolean = false; protected subscriptions: Subscription[] = []; constructor(protected formService: FormService, protected visibilityService: WidgetVisibilityService, - private ecmModelService: EcmModelService, - private nodeService: NodeService) { - } - - hasForm(): boolean { - return this.form ? true : false; - } - - isTitleEnabled(): boolean { - if (this.showTitle) { - if (this.form && this.form.taskName) { - return true; - } - } - return false; - } - - getColorForOutcome(outcomeName: string): string { - return outcomeName === FormComponent.COMPLETE_OUTCOME_NAME ? FormComponent.COMPLETE_BUTTON_COLOR : ''; - } - - isOutcomeButtonEnabled(outcome: FormOutcomeModel): boolean { - if (this.form.readOnly) { - return false; - } - - if (outcome) { - // Make 'Save' button always available - if (outcome.name === FormOutcomeModel.SAVE_ACTION) { - return true; - } - if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) { - return this.disableCompleteButton ? false : this.form.isValid; - } - if (outcome.name === FormOutcomeModel.START_PROCESS_ACTION) { - return this.disableStartProcessButton ? false : this.form.isValid; - } - return this.form.isValid; - } - return false; - } - - isOutcomeButtonVisible(outcome: FormOutcomeModel, isFormReadOnly: boolean): boolean { - if (outcome && outcome.name) { - if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) { - return this.showCompleteButton; - } - if (isFormReadOnly) { - return outcome.isSelected; - } - if (outcome.name === FormOutcomeModel.SAVE_ACTION) { - return this.showSaveButton; - } - if (outcome.name === FormOutcomeModel.START_PROCESS_ACTION) { - return false; - } - return true; - } - return false; + protected ecmModelService: EcmModelService, + protected nodeService: NodeService, + protected formRenderingService: FormRenderingService) { + super(); + this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileWidgetComponent, true); + this.formRenderingService.setComponentTypeResolver('select-folder', () => AttachFolderWidgetComponent, true); } ngOnInit() { @@ -243,87 +110,42 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { } ngOnDestroy() { - this.subscriptions.forEach(subscription => subscription.unsubscribe()); + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); this.subscriptions = []; } ngOnChanges(changes: SimpleChanges) { - let taskId = changes['taskId']; + const taskId = changes['taskId']; if (taskId && taskId.currentValue) { this.getFormByTaskId(taskId.currentValue); return; } - let formId = changes['formId']; + const formId = changes['formId']; if (formId && formId.currentValue) { this.getFormDefinitionByFormId(formId.currentValue); return; } - let formName = changes['formName']; + const formName = changes['formName']; if (formName && formName.currentValue) { this.getFormDefinitionByFormName(formName.currentValue); return; } - let nodeId = changes['nodeId']; + const nodeId = changes['nodeId']; if (nodeId && nodeId.currentValue) { this.loadFormForEcmNode(nodeId.currentValue); return; } - let data = changes['data']; + const data = changes['data']; if (data && data.currentValue) { this.refreshFormData(); return; } } - /** - * Invoked when user clicks outcome button. - * @param outcome Form outcome model - */ - onOutcomeClicked(outcome: FormOutcomeModel): boolean { - if (!this.readOnly && outcome && this.form) { - - if (!this.onExecuteOutcome(outcome)) { - return false; - } - - if (outcome.isSystem) { - if (outcome.id === FormComponent.SAVE_OUTCOME_ID) { - this.saveTaskForm(); - return true; - } - - if (outcome.id === FormComponent.COMPLETE_OUTCOME_ID) { - this.completeTaskForm(); - return true; - } - - if (outcome.id === FormComponent.START_PROCESS_OUTCOME_ID) { - this.completeTaskForm(); - return true; - } - - if (outcome.id === FormComponent.CUSTOM_OUTCOME_ID) { - this.onTaskSaved(this.form); - this.storeFormAsMetadata(); - return true; - } - } else { - // Note: Activiti is using NAME field rather than ID for outcomes - if (outcome.name) { - this.onTaskSaved(this.form); - this.completeTaskForm(outcome.name); - return true; - } - } - } - - return false; - } - /** * Invoked when user clicks form refresh button. */ @@ -370,7 +192,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.formService .getTaskForm(taskId) .subscribe( - form => { + (form) => { const parsedForm = this.parseForm(form); this.visibilityService.refreshVisibility(parsedForm); parsedForm.validateForm(); @@ -378,7 +200,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.onFormLoaded(this.form); resolve(this.form); }, - error => { + (error) => { this.handleError(error); // reject(error); resolve(null); @@ -392,7 +214,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.formService .getFormDefinitionById(formId) .subscribe( - form => { + (form) => { this.formName = form.name; this.form = this.parseForm(form); this.visibilityService.refreshVisibility(this.form); @@ -409,9 +231,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.formService .getFormDefinitionByName(formName) .subscribe( - id => { + (id) => { this.formService.getFormDefinitionById(id).subscribe( - form => { + (form) => { this.form = this.parseForm(form); this.visibilityService.refreshVisibility(this.form); this.form.validateForm(); @@ -437,7 +259,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.onTaskSaved(this.form); this.storeFormAsMetadata(); }, - error => this.onTaskSavedError(this.form, error) + (error) => this.onTaskSavedError(this.form, error) ); } } @@ -451,7 +273,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.onTaskCompleted(this.form); this.storeFormAsMetadata(); }, - error => this.onTaskCompletedError(this.form, error) + (error) => this.onTaskCompletedError(this.form, error) ); } } @@ -462,7 +284,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { parseForm(json: any): FormModel { if (json) { - let form = new FormModel(json, this.data, this.readOnly, this.formService); + const form = new FormModel(json, this.data, this.readOnly, this.formService); if (!json.fields) { form.outcomes = this.getFormDefinitionOutcomes(form); } @@ -480,7 +302,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { */ getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] { return [ - new FormOutcomeModel(form, { id: '$custom', name: FormOutcomeModel.SAVE_ACTION, isSystem: true }) + new FormOutcomeModel(form, { id: '$save', name: FormOutcomeModel.SAVE_ACTION, isSystem: true }) ]; } @@ -497,7 +319,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { } private loadFormForEcmNode(nodeId: string): void { - this.nodeService.getNodeMetadata(nodeId).subscribe(data => { + this.nodeService.getNodeMetadata(nodeId).subscribe((data) => { this.data = data.metadata; this.loadFormFromActiviti(data.nodeType); }, @@ -506,9 +328,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { loadFormFromActiviti(nodeType: string): any { this.formService.searchFrom(nodeType).subscribe( - form => { + (form) => { if (!form) { - this.formService.createFormFromANode(nodeType).subscribe(formMetadata => { + this.formService.createFormFromANode(nodeType).subscribe((formMetadata) => { this.loadFormFromFormId(formMetadata.id); }); } else { @@ -526,9 +348,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { this.loadForm(); } - private storeFormAsMetadata() { + protected storeFormAsMetadata() { if (this.saveMetadata) { - this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe(type => { + this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe((type) => { this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode); }, (error) => { @@ -569,7 +391,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { } protected onExecuteOutcome(outcome: FormOutcomeModel): boolean { - let args = new FormOutcomeEvent(outcome); + const args = new FormOutcomeEvent(outcome); this.formService.executeOutcome.next(args); if (args.defaultPrevented) { @@ -583,4 +405,5 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { return true; } + } diff --git a/lib/core/form/components/form.component.visibility.spec.ts b/lib/process-services/form/form.component.visibility.spec.ts similarity index 96% rename from lib/core/form/components/form.component.visibility.spec.ts rename to lib/process-services/form/form.component.visibility.spec.ts index 8d5b18f4d2..010f819341 100644 --- a/lib/core/form/components/form.component.visibility.spec.ts +++ b/lib/process-services/form/form.component.visibility.spec.ts @@ -22,13 +22,11 @@ import { of } from 'rxjs'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { formDefinitionDropdownField, formDefinitionTwoTextFields, formDefinitionRequiredField } from '../../mock'; -import { formReadonlyTwoTextFields } from '../../mock'; -import { formDefVisibilitiFieldDependsOnNextOne, formDefVisibilitiFieldDependsOnPreviousOne } from '../../mock'; -import { FormService } from './../services/form.service'; +import { formDefinitionDropdownField, formDefinitionTwoTextFields, + formDefinitionRequiredField, FormService, setupTestBed, CoreModule, + formDefVisibilitiFieldDependsOnNextOne, formDefVisibilitiFieldDependsOnPreviousOne, + formReadonlyTwoTextFields } from '@alfresco/adf-core'; import { FormComponent } from './form.component'; -import { setupTestBed } from '../../testing/setupTestBed'; -import { CoreModule } from '../../core.module'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; /** Duration of the select opening animation. */ @@ -54,6 +52,9 @@ describe('FormComponent UI and visibility', () => { NoopAnimationsModule, CoreModule.forRoot() ], + declarations: [ + FormComponent + ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); diff --git a/lib/process-services/form/form.module.ts b/lib/process-services/form/form.module.ts new file mode 100644 index 0000000000..62c1b8e7d8 --- /dev/null +++ b/lib/process-services/form/form.module.ts @@ -0,0 +1,38 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { MaterialModule } from '../material.module'; +import { CoreModule } from '@alfresco/adf-core'; +import { FormComponent } from './form.component'; +import { StartFormComponent } from './start-form.component'; + +@NgModule({ + imports: [ + CoreModule.forChild(), + MaterialModule + ], + declarations: [ + FormComponent, + StartFormComponent + ], + exports: [ + FormComponent, + StartFormComponent + ] +}) +export class FormModule {} diff --git a/lib/process-services/form/index.ts b/lib/process-services/form/index.ts new file mode 100644 index 0000000000..a7e30cc675 --- /dev/null +++ b/lib/process-services/form/index.ts @@ -0,0 +1,18 @@ +/*! + * @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. + */ + +export * from './public-api'; diff --git a/lib/process-services/form/public-api.ts b/lib/process-services/form/public-api.ts new file mode 100644 index 0000000000..c8d723ed8f --- /dev/null +++ b/lib/process-services/form/public-api.ts @@ -0,0 +1,20 @@ +/*! + * @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. + */ + +export * from './form.component'; +export * from './start-form.component'; +export * from './form.module'; diff --git a/lib/core/form/components/start-form.component.html b/lib/process-services/form/start-form.component.html similarity index 100% rename from lib/core/form/components/start-form.component.html rename to lib/process-services/form/start-form.component.html diff --git a/lib/process-services/form/start-form.component.scss b/lib/process-services/form/start-form.component.scss new file mode 100644 index 0000000000..3c747fcf66 --- /dev/null +++ b/lib/process-services/form/start-form.component.scss @@ -0,0 +1,125 @@ +@mixin adf-start-form-component-theme($theme) { + + $config: mat-typography-config(); + $warn: map-get($theme, warn); + $accent: map-get($theme, accent); + + .adf { + &-form-container { + max-width: 100% !important; + max-height: 100% !important; + + & .mat-card { + padding: 16px 24px; + overflow: hidden; + } + + & .mat-card-header-text { + margin: 0 !important; + } + + & .mat-tab-body-content { + overflow: hidden; + } + + & .mat-tab-label { + font-size: mat-font-size($config, subheading-2); + line-height: mat-line-height($config, headline); + letter-spacing: -0.4px; + text-align: left; + color: rgba(0, 0, 0, 0.54); + text-transform: uppercase; + } + + & .mat-ink-bar { + height: 4px; + } + + & .mat-form-field-wrapper { + margin: 0 12px 0 0; + } + } + + &-form-title { + font-size: mat-font-size($alfresco-typography, title); + } + + &-form-debug-container { + padding: 10px; + } + + &-form-debug-container .adf-debug-toggle-text { + padding-left: 15px; + cursor: pointer; + } + + &-form-debug-container .adf-debug-toggle-text:hover { + font-weight: bold; + } + + &-form-reload-button { + position: absolute; + right: 12px; + top: 30px; + } + + &-form-validation-button { + position: absolute; + right: 50px; + top: 39px; + color: mat-color($accent); + + & .adf-invalid-color { + color: mat-color($warn); + } + } + + &-form-hide-button { + display: none !important; + } + + &-task-title { + text-align: center; + } + + &-label { + width: 32px; + height: 16px; + font-size: mat-font-size($config, caption); + line-height: mat-line-height($config, headline); + text-align: left; + white-space: nowrap; + } + + &-form-mat-card-actions { + float: right; + padding-bottom: 25px !important; + padding-right: 25px !important; + + & .mat-button { + height: 36px; + border-radius: 5px; + + } + + & .mat-button-wrapper { + width: 58px; + height: 20px; + opacity: 0.54; + font-size: mat-font-size($config, body-2); + font-weight: bold; + } + } + } + + form-field { + width: 100%; + + .mat-input-element { + font-size: mat-font-size($config, body-2); + padding-top: 8px; + line-height: normal; + } + } + +} diff --git a/lib/core/form/components/start-form.component.spec.ts b/lib/process-services/form/start-form.component.spec.ts similarity index 98% rename from lib/core/form/components/start-form.component.spec.ts rename to lib/process-services/form/start-form.component.spec.ts index 851e8f8006..c994396fae 100644 --- a/lib/core/form/components/start-form.component.spec.ts +++ b/lib/process-services/form/start-form.component.spec.ts @@ -18,15 +18,11 @@ import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { of, throwError } from 'rxjs'; -import { startFormDateWidgetMock, startFormDropdownDefinitionMock, startFormTextDefinitionMock, startMockForm, startMockFormWithTab } from '../../mock'; -import { startFormAmountWidgetMock, startFormNumberWidgetMock, startFormRadioButtonWidgetMock } from '../../mock'; -import { FormService } from './../services/form.service'; -import { WidgetVisibilityService } from './../services/widget-visibility.service'; +import { startFormDateWidgetMock, startFormDropdownDefinitionMock, startFormTextDefinitionMock, startMockForm, startMockFormWithTab } from '../../core/mock'; +import { startFormAmountWidgetMock, startFormNumberWidgetMock, startFormRadioButtonWidgetMock } from '../../core/mock'; import { StartFormComponent } from './start-form.component'; -import { FormModel, FormOutcomeModel } from './widgets/index'; -import { setupTestBed } from '../../testing/setupTestBed'; -import { CoreModule } from '../../core.module'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { FormService, WidgetVisibilityService, setupTestBed, CoreModule, FormModel, FormOutcomeModel } from '@alfresco/adf-core'; describe('StartFormComponent', () => { @@ -44,6 +40,9 @@ describe('StartFormComponent', () => { NoopAnimationsModule, CoreModule.forRoot() ], + declarations: [ + StartFormComponent + ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); diff --git a/lib/core/form/components/start-form.component.ts b/lib/process-services/form/start-form.component.ts similarity index 92% rename from lib/core/form/components/start-form.component.ts rename to lib/process-services/form/start-form.component.ts index ed97a64fe4..71db078234 100644 --- a/lib/core/form/components/start-form.component.ts +++ b/lib/process-services/form/start-form.component.ts @@ -28,17 +28,13 @@ import { ViewEncapsulation, OnDestroy } from '@angular/core'; -import { FormService } from './../services/form.service'; -import { WidgetVisibilityService } from './../services/widget-visibility.service'; import { FormComponent } from './form.component'; -import { ContentLinkModel } from './widgets/core/content-link.model'; -import { FormOutcomeModel } from './widgets/core/index'; -import { ValidateFormEvent } from './../events/validate-form.event'; +import { ContentLinkModel, FormService, WidgetVisibilityService, FormRenderingService, ValidateFormEvent, FormOutcomeModel } from '@alfresco/adf-core'; @Component({ selector: 'adf-start-form', templateUrl: './start-form.component.html', - styleUrls: ['./form.component.scss'], + styleUrls: ['./start-form.component.scss'], encapsulation: ViewEncapsulation.None }) export class StartFormComponent extends FormComponent implements OnChanges, OnInit, OnDestroy { @@ -75,8 +71,9 @@ export class StartFormComponent extends FormComponent implements OnChanges, OnIn outcomesContainer: ElementRef = null; constructor(formService: FormService, - visibilityService: WidgetVisibilityService) { - super(formService, visibilityService, null, null); + visibilityService: WidgetVisibilityService, + formRenderingService: FormRenderingService) { + super(formService, visibilityService, null, null, formRenderingService); this.showTitle = false; } diff --git a/lib/process-services/index.ts b/lib/process-services/index.ts index bb1992f733..c392ed639f 100644 --- a/lib/process-services/index.ts +++ b/lib/process-services/index.ts @@ -22,5 +22,6 @@ export * from './attachment/index'; export * from './process-comments/index'; export * from './people/index'; export * from './content-widget/index'; +export * from './form/index'; export * from './process.module'; diff --git a/lib/process-services/process-list/components/process-instance-details.component.spec.ts b/lib/process-services/process-list/components/process-instance-details.component.spec.ts index ae23a9baae..31352bcde0 100644 --- a/lib/process-services/process-list/components/process-instance-details.component.spec.ts +++ b/lib/process-services/process-list/components/process-instance-details.component.spec.ts @@ -20,7 +20,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { of } from 'rxjs'; -import { FormModule, setupTestBed } from '@alfresco/adf-core'; +import { setupTestBed } from '@alfresco/adf-core'; import { TaskListModule } from '../../task-list/task-list.module'; import { ProcessInstance } from '../models/process-instance.model'; @@ -28,6 +28,7 @@ import { exampleProcess, exampleProcessNoName } from './../../mock'; import { ProcessService } from './../services/process.service'; import { ProcessInstanceDetailsComponent } from './process-instance-details.component'; import { ProcessTestingModule } from '../../testing/process.testing.module'; +import { FormModule } from '../../form'; describe('ProcessInstanceDetailsComponent', () => { diff --git a/lib/process-services/process-list/components/start-process.component.ts b/lib/process-services/process-list/components/start-process.component.ts index a4dc0e0ac8..d30431d0d5 100644 --- a/lib/process-services/process-list/components/start-process.component.ts +++ b/lib/process-services/process-list/components/start-process.component.ts @@ -21,17 +21,17 @@ import { } from '@angular/core'; import { ActivitiContentService, AppConfigService, AppConfigValues, - StartFormComponent, FormRenderingService, FormValues + FormValues } from '@alfresco/adf-core'; import { ProcessInstanceVariable } from '../models/process-instance-variable.model'; import { ProcessDefinitionRepresentation } from './../models/process-definition.model'; import { ProcessInstance } from './../models/process-instance.model'; import { ProcessService } from './../services/process.service'; -import { AttachFileWidgetComponent, AttachFolderWidgetComponent } from '../../content-widget'; import { FormControl, Validators, AbstractControl } from '@angular/forms'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { MatAutocompleteTrigger } from '@angular/material'; +import { StartFormComponent } from '../../form'; @Component({ selector: 'adf-start-process', @@ -102,12 +102,9 @@ export class StartProcessInstanceComponent implements OnChanges, OnInit { maxProcessNameLength: number = this.MAX_LENGTH; constructor(private activitiProcess: ProcessService, - private formRenderingService: FormRenderingService, private activitiContentService: ActivitiContentService, private appConfig: AppConfigService) { - this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileWidgetComponent, true); - this.formRenderingService.setComponentTypeResolver('select-folder', () => AttachFolderWidgetComponent, true); - } + } ngOnInit() { this.processNameInput = new FormControl(this.name, [Validators.required, Validators.maxLength(this.maxProcessNameLength)]); diff --git a/lib/process-services/process-list/process-list.module.ts b/lib/process-services/process-list/process-list.module.ts index 60a844896a..f4d6c1340c 100644 --- a/lib/process-services/process-list/process-list.module.ts +++ b/lib/process-services/process-list/process-list.module.ts @@ -33,6 +33,7 @@ import { ProcessInstanceHeaderComponent } from './components/process-instance-he import { ProcessInstanceTasksComponent } from './components/process-instance-tasks.component'; import { ProcessInstanceListComponent } from './components/process-list.component'; import { StartProcessInstanceComponent } from './components/start-process.component'; +import { FormModule } from '../form/form.module'; @NgModule({ imports: [ @@ -45,7 +46,8 @@ import { StartProcessInstanceComponent } from './components/start-process.compon TaskListModule, PeopleModule, ContentWidgetModule, - ProcessCommentsModule + ProcessCommentsModule, + FormModule ], declarations: [ ProcessInstanceListComponent, diff --git a/lib/process-services/process.module.ts b/lib/process-services/process.module.ts index 26f42dce78..58de03ae24 100644 --- a/lib/process-services/process.module.ts +++ b/lib/process-services/process.module.ts @@ -28,6 +28,7 @@ import { AppsListModule } from './app-list/apps-list.module'; import { ProcessCommentsModule } from './process-comments/process-comments.module'; import { AttachmentModule } from './attachment/attachment.module'; import { PeopleModule } from './people/people.module'; +import { FormModule } from './form/form.module'; @NgModule({ imports: [ @@ -41,7 +42,8 @@ import { PeopleModule } from './people/people.module'; TaskListModule, AppsListModule, AttachmentModule, - PeopleModule + PeopleModule, + FormModule ], providers: [ { @@ -62,7 +64,8 @@ import { PeopleModule } from './people/people.module'; TaskListModule, AppsListModule, AttachmentModule, - PeopleModule + PeopleModule, + FormModule ] }) export class ProcessModule { diff --git a/lib/process-services/styles/_index.scss b/lib/process-services/styles/_index.scss index a7d72ab228..40dc42af32 100644 --- a/lib/process-services/styles/_index.scss +++ b/lib/process-services/styles/_index.scss @@ -9,6 +9,7 @@ @import '../task-list/components/task-standalone.component'; @import '../app-list/apps-list.component'; @import '../content-widget/attach-file-widget-dialog.component'; +@import '../form/start-form.component'; @mixin adf-process-services-theme($theme) { @include adf-process-filters-theme($theme); @@ -22,4 +23,5 @@ @include adf-apps-theme($theme); @include adf-task-standalone-component-theme($theme); @include adf-attach-file-widget-dialog-component-theme($theme); -} + @include adf-start-form-component-theme($theme); + } diff --git a/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts b/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts index 61188986bf..4322e1b691 100644 --- a/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts +++ b/lib/process-services/task-list/components/no-task-detail-template.directive.spec.ts @@ -17,7 +17,7 @@ import { NoTaskDetailsTemplateDirective } from './no-task-detail-template.directive'; import { TaskDetailsComponent } from './task-details.component'; -import { FormRenderingService, AuthenticationService } from '@alfresco/adf-core'; +import { AuthenticationService } from '@alfresco/adf-core'; import { of } from 'rxjs'; describe('NoTaskDetailsTemplateDirective', () => { @@ -29,7 +29,7 @@ describe('NoTaskDetailsTemplateDirective', () => { beforeEach(() => { authService = new AuthenticationService(null, null, null, null); spyOn(authService, 'getBpmLoggedUser').and.returnValue(of({ email: 'fake-email'})); - detailsComponent = new TaskDetailsComponent(null, authService, null, new FormRenderingService(), null, null, null); + detailsComponent = new TaskDetailsComponent(null, authService, null, null, null, null); component = new NoTaskDetailsTemplateDirective(detailsComponent); }); diff --git a/lib/process-services/task-list/components/task-details.component.html b/lib/process-services/task-list/components/task-details.component.html index d5019be012..ac86217905 100644 --- a/lib/process-services/task-list/components/task-details.component.html +++ b/lib/process-services/task-list/components/task-details.component.html @@ -23,7 +23,6 @@ <div class="adf-task-details-core-form"> <div *ngIf="isAssigned()"> <adf-form *ngIf="isFormComponentVisible()" #activitiForm - [showDebugButton]="debugMode" [taskId]="taskDetails.id" [showTitle]="showFormTitle" [showRefreshButton]="showFormRefreshButton" diff --git a/lib/process-services/task-list/components/task-details.component.ts b/lib/process-services/task-list/components/task-details.component.ts index 5ea8c07922..55e19baa1a 100644 --- a/lib/process-services/task-list/components/task-details.component.ts +++ b/lib/process-services/task-list/components/task-details.component.ts @@ -22,7 +22,6 @@ import { ClickNotification, LogService, UpdateNotification, - FormRenderingService, CommentsComponent } from '@alfresco/adf-core'; import { @@ -42,7 +41,6 @@ import { ContentLinkModel, FormFieldValidator, FormModel, FormOutcomeEvent } fro import { TaskQueryRequestRepresentationModel } from '../models/filter.model'; import { TaskDetailsModel } from '../models/task-details.model'; import { TaskListService } from './../services/tasklist.service'; -import { AttachFileWidgetComponent, AttachFolderWidgetComponent } from '../../content-widget'; import { UserRepresentation } from '@alfresco/js-api'; import { share } from 'rxjs/operators'; @@ -188,13 +186,10 @@ export class TaskDetailsComponent implements OnInit, OnChanges { constructor(private taskListService: TaskListService, private authService: AuthenticationService, private peopleProcessService: PeopleProcessService, - private formRenderingService: FormRenderingService, private logService: LogService, private cardViewUpdateService: CardViewUpdateService, private dialog: MatDialog) { - this.formRenderingService.setComponentTypeResolver('select-folder', () => AttachFolderWidgetComponent, true); - this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileWidgetComponent, true); this.peopleSearch = new Observable<UserProcessModel[]>((observer) => this.peopleSearchObserver = observer) .pipe(share()); this.authService.getBpmLoggedUser().subscribe((user: UserRepresentation) => { diff --git a/lib/process-services/task-list/task-list.module.ts b/lib/process-services/task-list/task-list.module.ts index d31481ae15..bb9f62f472 100644 --- a/lib/process-services/task-list/task-list.module.ts +++ b/lib/process-services/task-list/task-list.module.ts @@ -36,6 +36,7 @@ import { TaskHeaderComponent } from './components/task-header.component'; import { TaskListComponent } from './components/task-list.component'; import { TaskStandaloneComponent } from './components/task-standalone.component'; import { AttachFormComponent } from './components/attach-form.component'; +import { FormModule } from '../form/form.module'; @NgModule({ imports: [ @@ -43,6 +44,7 @@ import { AttachFormComponent } from './components/attach-form.component'; FlexLayoutModule, MaterialModule, FormsModule, + FormModule, ReactiveFormsModule, CoreModule.forChild(), PeopleModule, diff --git a/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts b/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts index 230b6645bf..5eacc7e0fc 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/process-instances.service.ts @@ -58,6 +58,7 @@ export class ProcessInstancesService { async completeProcessInstance(processInstanceId, appName) { const path = '/' + appName + '/rb/v1/process-instances/' + processInstanceId + '/complete'; + const method = 'POST'; const queryParams = {}, postBody = {}; From 1bda3c914cbfc6549c66b4132ed2cd698bce79fa Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Wed, 10 Apr 2019 19:41:16 +0100 Subject: [PATCH 093/208] [ADF-4059] - Move Copy Folders with Load more- take2 (#4562) * C260132 automated * debbugging * in progress * done * review comments. * in progress * Update content-node-selector-dialog.page.ts * fix the locators * code review comments * removed the datatablecomponentPage call directly from hte test. --- .../document-list-actions.e2e.ts | 452 ++++++++++++------ .../breadcrumb/breadCrumbDropdownPage.ts | 42 ++ .../breadcrumb/breadCrumbPage.ts | 32 ++ e2e/pages/adf/contentServicesPage.ts | 20 +- e2e/search/search-filters.e2e.ts | 5 +- .../content-node-selector-dialog.page.ts | 100 ++++ .../example.page.ts => dialog/public-api.ts} | 4 +- .../pages/document-list.page.ts | 4 +- .../lib/content-services/pages/public-api.ts | 2 +- .../src/lib/content-services/public-api.ts | 1 + .../core/pages/data-table-component.page.ts | 24 + 11 files changed, 511 insertions(+), 175 deletions(-) create mode 100644 e2e/pages/adf/content-services/breadcrumb/breadCrumbDropdownPage.ts create mode 100644 e2e/pages/adf/content-services/breadcrumb/breadCrumbPage.ts create mode 100644 lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts rename lib/testing/src/lib/content-services/{pages/example.page.ts => dialog/public-api.ts} (92%) rename e2e/pages/adf/content-services/documentListPage.ts => lib/testing/src/lib/content-services/pages/document-list.page.ts (95%) diff --git a/e2e/content-services/document-list/document-list-actions.e2e.ts b/e2e/content-services/document-list/document-list-actions.e2e.ts index 17ea90eee8..fe1252430a 100644 --- a/e2e/content-services/document-list/document-list-actions.e2e.ts +++ b/e2e/content-services/document-list/document-list-actions.e2e.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { browser } from 'protractor'; -import { LoginPage } from '@alfresco/adf-testing'; +import { browser, by, element } from 'protractor'; +import { LoginPage, PaginationPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; @@ -27,6 +27,11 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; import { FileModel } from '../../models/ACS/fileModel'; import { StringUtil } from '@alfresco/adf-testing'; import { Util } from '../../util/util'; +import { ContentNodeSelectorDialogPage } from '@alfresco/adf-testing'; +import { BreadCrumbDropdownPage } from '../../pages/adf/content-services/breadcrumb/breadCrumbDropdownPage'; +import { FolderModel } from '../../models/ACS/folderModel'; +import { BreadCrumbPage } from '../../pages/adf/content-services/breadcrumb/breadCrumbPage'; +import { InfinitePaginationPage } from '../../pages/adf/core/infinitePaginationPage'; describe('Document List Component - Actions', () => { @@ -34,169 +39,324 @@ describe('Document List Component - Actions', () => { const contentServicesPage = new ContentServicesPage(); const navigationBarPage = new NavigationBarPage(); const contentListPage = contentServicesPage.getDocumentList(); - let uploadedFolder, secondUploadedFolder; + const contentNodeSelector = new ContentNodeSelectorDialogPage(); + const paginationPage = new PaginationPage(); + const breadCrumbDropdownPage = new BreadCrumbDropdownPage(); + const breadCrumbPage = new BreadCrumbPage(); const uploadActions = new UploadActions(); - let acsUser = null; - let pdfUploadedNode; - let folderName; - let fileNames = []; - const nrOfFiles = 5; + const infinitePaginationPage = new InfinitePaginationPage(element(by.css('adf-content-node-selector'))); - const pdfFileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, - 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location - }); - const testFileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, - 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location + const alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url }); - const files = { - base: 'newFile', - extension: '.txt' - }; + describe('Document List Component - Check Actions', () => { - beforeAll(async (done) => { - this.alfrescoJsApi = new AlfrescoApi({ - provider: 'ECM', - hostEcm: TestConfig.adf.url + let uploadedFolder, secondUploadedFolder; + let acsUser = null; + let pdfUploadedNode; + let folderName; + let fileNames = []; + const nrOfFiles = 5; + + const pdfFileModel = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PDF.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PDF.file_location + }); + const testFileModel = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, + 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location }); - acsUser = new AcsUserModel(); - folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - pdfUploadedNode = await uploadActions.uploadFile(this.alfrescoJsApi, pdfFileModel.location, pdfFileModel.name, '-my-'); - await uploadActions.uploadFile(this.alfrescoJsApi, testFileModel.location, testFileModel.name, '-my-'); - uploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); - secondUploadedFolder = await uploadActions.createFolder(this.alfrescoJsApi, 'secondFolder', '-my-'); + const files = { + base: 'newFile', + extension: '.txt' + }; - fileNames = Util.generateSequenceFiles(1, nrOfFiles, files.base, files.extension); - await uploadActions.createEmptyFiles(this.alfrescoJsApi, fileNames, uploadedFolder.entry.id); + beforeAll(async (done) => { - loginPage.loginToContentServicesUsingUserModel(acsUser); + acsUser = new AcsUserModel(); + folderName = `TATSUMAKY_${StringUtil.generateRandomString(5)}_SENPOUKYAKU`; + await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await alfrescoJsApi.core.peopleApi.addPerson(acsUser); + await alfrescoJsApi.login(acsUser.id, acsUser.password); + pdfUploadedNode = await uploadActions.uploadFile(alfrescoJsApi, pdfFileModel.location, pdfFileModel.name, '-my-'); + await uploadActions.uploadFile(alfrescoJsApi, testFileModel.location, testFileModel.name, '-my-'); + uploadedFolder = await uploadActions.createFolder(alfrescoJsApi, folderName, '-my-'); + secondUploadedFolder = await uploadActions.createFolder(alfrescoJsApi, 'secondFolder', '-my-'); - browser.driver.sleep(15000); - done(); - }); + fileNames = Util.generateSequenceFiles(1, nrOfFiles, files.base, files.extension); + await uploadActions.createEmptyFiles(alfrescoJsApi, fileNames, uploadedFolder.entry.id); - beforeEach(async (done) => { - navigationBarPage.clickAboutButton(); - navigationBarPage.clickContentServicesButton(); - done(); - }); + loginPage.loginToContentServicesUsingUserModel(acsUser); - describe('File Actions', () => { - - it('[C213257] Should be able to copy a file', () => { - contentServicesPage.checkContentIsDisplayed(pdfUploadedNode.entry.name); - - contentServicesPage.getDocumentList().rightClickOnRow(pdfFileModel.name); - contentServicesPage.pressContextMenuActionNamed('Copy'); - - contentServicesPage.typeIntoNodeSelectorSearchField(folderName); - contentServicesPage.clickContentNodeSelectorResult(folderName); - contentServicesPage.clickChooseButton(); - contentServicesPage.checkContentIsDisplayed(pdfFileModel.name); - contentServicesPage.doubleClickRow(uploadedFolder.entry.name); - contentServicesPage.checkContentIsDisplayed(pdfFileModel.name); + browser.driver.sleep(15000); + done(); }); - it('[C297491] Should be able to move a file', () => { - contentServicesPage.checkContentIsDisplayed(testFileModel.name); + beforeEach(async (done) => { + navigationBarPage.clickAboutButton(); + navigationBarPage.clickContentServicesButton(); + done(); + }); - contentServicesPage.getDocumentList().rightClickOnRow(testFileModel.name); + describe('File Actions', () => { + + it('[C213257] Should be able to copy a file', () => { + contentServicesPage.checkContentIsDisplayed(pdfUploadedNode.entry.name); + + contentServicesPage.getDocumentList().rightClickOnRow(pdfFileModel.name); + contentServicesPage.pressContextMenuActionNamed('Copy'); + + contentNodeSelector.checkDialogIsDisplayed(); + contentNodeSelector.typeIntoNodeSelectorSearchField(folderName); + contentNodeSelector.clickContentNodeSelectorResult(folderName); + contentNodeSelector.clickMoveCopyButton(); + contentServicesPage.checkContentIsDisplayed(pdfFileModel.name); + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + contentServicesPage.checkContentIsDisplayed(pdfFileModel.name); + }); + + it('[C297491] Should be able to move a file', () => { + contentServicesPage.checkContentIsDisplayed(testFileModel.name); + + contentServicesPage.getDocumentList().rightClickOnRow(testFileModel.name); + contentServicesPage.pressContextMenuActionNamed('Move'); + contentNodeSelector.checkDialogIsDisplayed(); + contentNodeSelector.typeIntoNodeSelectorSearchField(folderName); + contentNodeSelector.clickContentNodeSelectorResult(folderName); + contentNodeSelector.clickMoveCopyButton(); + contentServicesPage.checkContentIsNotDisplayed(testFileModel.name); + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + contentServicesPage.checkContentIsDisplayed(testFileModel.name); + }); + + it('[C280561] Should be able to delete a file via dropdown menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentServicesPage.checkContentIsDisplayed(fileNames[0]); + contentServicesPage.deleteContent(fileNames[0]); + contentServicesPage.checkContentIsNotDisplayed(fileNames[0]); + }); + + it('[C280562] Only one file is deleted when multiple files are selected using dropdown menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentListPage.selectRow(fileNames[1]); + contentListPage.selectRow(fileNames[2]); + contentServicesPage.deleteContent(fileNames[1]); + contentServicesPage.checkContentIsNotDisplayed(fileNames[1]); + contentServicesPage.checkContentIsDisplayed(fileNames[2]); + }); + + it('[C280565] Should be able to delete a file using context menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentListPage.rightClickOnRow(fileNames[2]); + contentServicesPage.pressContextMenuActionNamed('Delete'); + contentServicesPage.checkContentIsNotDisplayed(fileNames[2]); + }); + + it('[C280567] Only one file is deleted when multiple files are selected using context menu', () => { + contentServicesPage.doubleClickRow(uploadedFolder.entry.name); + + contentListPage.selectRow(fileNames[3]); + contentListPage.selectRow(fileNames[4]); + contentListPage.rightClickOnRow(fileNames[3]); + contentServicesPage.pressContextMenuActionNamed('Delete'); + contentServicesPage.checkContentIsNotDisplayed(fileNames[3]); + contentServicesPage.checkContentIsDisplayed(fileNames[4]); + }); + + it('[C280566] Should be able to open context menu with right click', () => { + contentServicesPage.getDocumentList().rightClickOnRow(pdfFileModel.name); + contentServicesPage.checkContextActionIsVisible('Download'); + contentServicesPage.checkContextActionIsVisible('Copy'); + contentServicesPage.checkContextActionIsVisible('Move'); + contentServicesPage.checkContextActionIsVisible('Delete'); + contentServicesPage.checkContextActionIsVisible('Info'); + contentServicesPage.checkContextActionIsVisible('Manage versions'); + contentServicesPage.checkContextActionIsVisible('Permission'); + contentServicesPage.checkContextActionIsVisible('Lock'); + contentServicesPage.closeActionContext(); + }); + + }); + + describe('Folder Actions', () => { + + it('[C260138] Should be able to copy a folder', () => { + contentServicesPage.copyContent(folderName); + contentNodeSelector.checkDialogIsDisplayed(); + contentNodeSelector.typeIntoNodeSelectorSearchField(secondUploadedFolder.entry.name); + contentNodeSelector.clickContentNodeSelectorResult(secondUploadedFolder.entry.name); + contentNodeSelector.clickMoveCopyButton(); + contentServicesPage.checkContentIsDisplayed(folderName); + contentServicesPage.doubleClickRow(secondUploadedFolder.entry.name); + contentServicesPage.checkContentIsDisplayed(folderName); + }); + + it('[C260123] Should be able to delete a folder using context menu', () => { + contentServicesPage.deleteContent(folderName); + contentServicesPage.checkContentIsNotDisplayed(folderName); + }); + + it('[C280568] Should be able to open context menu with right click', () => { + contentServicesPage.checkContentIsDisplayed(secondUploadedFolder.entry.name); + + contentListPage.rightClickOnRow(secondUploadedFolder.entry.name); + contentServicesPage.checkContextActionIsVisible('Download'); + contentServicesPage.checkContextActionIsVisible('Copy'); + contentServicesPage.checkContextActionIsVisible('Move'); + contentServicesPage.checkContextActionIsVisible('Delete'); + contentServicesPage.checkContextActionIsVisible('Info'); + contentServicesPage.checkContextActionIsVisible('Permission'); + }); + + }); + }); + + describe('Folder Actions - Copy and Move', () => { + + const folderModel1 = new FolderModel({'name': StringUtil.generateRandomString()}); + const folderModel2 = new FolderModel({'name': StringUtil.generateRandomString()}); + const folderModel3 = new FolderModel({'name': StringUtil.generateRandomString()}); + const folderModel4 = new FolderModel({'name': StringUtil.generateRandomString()}); + const folderModel5 = new FolderModel({'name': StringUtil.generateRandomString()}); + const folderModel6 = new FolderModel({'name': StringUtil.generateRandomString()}); + + let folder1, folder2, folder3, folder4, folder5, folder6; + + let folders; + const contentServicesUser = new AcsUserModel(); + + beforeAll(async (done) => { + + await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await alfrescoJsApi.core.peopleApi.addPerson(contentServicesUser); + await alfrescoJsApi.login(contentServicesUser.id, contentServicesUser.password); + folder1 = await uploadActions.createFolder(alfrescoJsApi, 'A' + folderModel1.name, '-my-'); + folder2 = await uploadActions.createFolder(alfrescoJsApi, 'B' + folderModel2.name, '-my-'); + folder3 = await uploadActions.createFolder(alfrescoJsApi, 'C' + folderModel3.name, '-my-'); + folder4 = await uploadActions.createFolder(alfrescoJsApi, 'D' + folderModel4.name, '-my-'); + folder5 = await uploadActions.createFolder(alfrescoJsApi, 'E' + folderModel5.name, '-my-'); + folder6 = await uploadActions.createFolder(alfrescoJsApi, 'F' + folderModel6.name, '-my-'); + folders = [folder1, folder2, folder3, folder4, folder5, folder6]; + done(); + }); + + beforeEach(async (done) => { + loginPage.loginToContentServicesUsingUserModel(contentServicesUser); + contentServicesPage.goToDocumentList(); + contentServicesPage.waitForTableBody(); + paginationPage.selectItemsPerPage('5'); + contentServicesPage.checkAcsContainer(); + contentListPage.waitForTableBody(); + done(); + }); + + afterAll(async (done) => { + await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await folders.forEach(function (folder) { + uploadActions.deleteFilesOrFolder(alfrescoJsApi, folder.entry.id); + }); + done(); + }); + + it('[C260132] Move action on folder with - Load more', () => { + + expect(paginationPage.getCurrentItemsPerPage()).toEqual('5'); + expect(paginationPage.getPaginationRange()).toEqual('Showing 1-' + 5 + ' of ' + 6); + contentListPage.rightClickOnRow('A' + folderModel1.name); + contentServicesPage.checkContextActionIsVisible('Move'); contentServicesPage.pressContextMenuActionNamed('Move'); - contentServicesPage.typeIntoNodeSelectorSearchField(folderName); - contentServicesPage.clickContentNodeSelectorResult(folderName); - contentServicesPage.clickChooseButton(); - contentServicesPage.checkContentIsNotDisplayed(testFileModel.name); - contentServicesPage.doubleClickRow(uploadedFolder.entry.name); - contentServicesPage.checkContentIsDisplayed(testFileModel.name); - }); + contentNodeSelector.checkDialogIsDisplayed(); + expect(contentNodeSelector.getDialogHeaderText()).toBe('Move \'' + 'A' + folderModel1.name + '\' to...'); + contentNodeSelector.checkSearchInputIsDisplayed(); + expect(contentNodeSelector.getSearchLabel()).toBe('Search'); + contentNodeSelector.checkSelectedSiteIsDisplayed('My files'); + contentNodeSelector.checkCancelButtonIsDisplayed(); + contentNodeSelector.checkMoveCopyButtonIsDisplayed(); + expect(contentNodeSelector.getMoveCopyButtonText()).toBe('MOVE'); + expect(contentNodeSelector.numberOfResultsDisplayed()).toBe(5); + infinitePaginationPage.clickLoadMoreButton(); + expect(contentNodeSelector.numberOfResultsDisplayed()).toBe(6); + infinitePaginationPage.checkLoadMoreButtonIsNotDisplayed(); + contentNodeSelector.contentListPage().dataTablePage().selectRowByContent('F' + folderModel6.name); + contentNodeSelector.contentListPage().dataTablePage().checkRowByContentIsSelected('F' + folderModel6.name); + contentNodeSelector.clickCancelButton(); + contentNodeSelector.checkDialogIsNotDisplayed(); + contentServicesPage.checkContentIsDisplayed('A' + folderModel1.name); - it('[C280561] Should be able to delete a file via dropdown menu', () => { - contentServicesPage.doubleClickRow(uploadedFolder.entry.name); - - contentServicesPage.checkContentIsDisplayed(fileNames[0]); - contentServicesPage.deleteContent(fileNames[0]); - contentServicesPage.checkContentIsNotDisplayed(fileNames[0]); - }); - - it('[C280562] Only one file is deleted when multiple files are selected using dropdown menu', () => { - contentServicesPage.doubleClickRow(uploadedFolder.entry.name); - - contentListPage.selectRow(fileNames[1]); - contentListPage.selectRow(fileNames[2]); - contentServicesPage.deleteContent(fileNames[1]); - contentServicesPage.checkContentIsNotDisplayed(fileNames[1]); - contentServicesPage.checkContentIsDisplayed(fileNames[2]); - }); - - it('[C280565] Should be able to delete a file using context menu', () => { - contentServicesPage.doubleClickRow(uploadedFolder.entry.name); - - contentListPage.rightClickOnRow(fileNames[2]); - contentServicesPage.pressContextMenuActionNamed('Delete'); - contentServicesPage.checkContentIsNotDisplayed(fileNames[2]); - }); - - it('[C280567] Only one file is deleted when multiple files are selected using context menu', () => { - contentServicesPage.doubleClickRow(uploadedFolder.entry.name); - - contentListPage.selectRow(fileNames[3]); - contentListPage.selectRow(fileNames[4]); - contentListPage.rightClickOnRow(fileNames[3]); - contentServicesPage.pressContextMenuActionNamed('Delete'); - contentServicesPage.checkContentIsNotDisplayed(fileNames[3]); - contentServicesPage.checkContentIsDisplayed(fileNames[4]); - }); - - it('[C280566] Should be able to open context menu with right click', () => { - contentServicesPage.getDocumentList().rightClickOnRow(pdfFileModel.name); - contentServicesPage.checkContextActionIsVisible('Download'); - contentServicesPage.checkContextActionIsVisible('Copy'); + contentListPage.rightClickOnRow('A' + folderModel1.name); contentServicesPage.checkContextActionIsVisible('Move'); - contentServicesPage.checkContextActionIsVisible('Delete'); - contentServicesPage.checkContextActionIsVisible('Info'); - contentServicesPage.checkContextActionIsVisible('Manage versions'); - contentServicesPage.checkContextActionIsVisible('Permission'); - contentServicesPage.checkContextActionIsVisible('Lock'); - contentServicesPage.closeActionContext(); + contentServicesPage.pressContextMenuActionNamed('Move'); + contentNodeSelector.checkDialogIsDisplayed(); + infinitePaginationPage.clickLoadMoreButton(); + contentNodeSelector.contentListPage().dataTablePage().selectRowByContent('F' + folderModel6.name); + contentNodeSelector.contentListPage().dataTablePage().checkRowByContentIsSelected('F' + folderModel6.name); + contentNodeSelector.clickMoveCopyButton(); + contentServicesPage.checkContentIsNotDisplayed('A' + folderModel1.name); + contentServicesPage.doubleClickRow('F' + folderModel6.name); + contentServicesPage.checkContentIsDisplayed('A' + folderModel1.name); + + contentListPage.rightClickOnRow('A' + folderModel1.name); + contentServicesPage.checkContextActionIsVisible('Move'); + contentServicesPage.pressContextMenuActionNamed('Move'); + contentNodeSelector.checkDialogIsDisplayed(); + breadCrumbDropdownPage.clickParentFolder(); + breadCrumbDropdownPage.checkBreadCrumbDropdownIsDisplayed(); + breadCrumbDropdownPage.choosePath(contentServicesUser.id); + contentNodeSelector.clickMoveCopyButton(); + contentServicesPage.checkContentIsNotDisplayed('A' + folderModel1.name); + + breadCrumbPage.chooseBreadCrumb(contentServicesUser.id); + contentServicesPage.waitForTableBody(); + contentServicesPage.checkContentIsDisplayed('A' + folderModel1.name); + + }); + + it('[C305051] Copy action on folder with - Load more', () => { + + expect(paginationPage.getCurrentItemsPerPage()).toEqual('5'); + expect(paginationPage.getPaginationRange()).toEqual('Showing 1-' + 5 + ' of ' + 6); + contentListPage.rightClickOnRow('A' + folderModel1.name); + contentServicesPage.checkContextActionIsVisible('Copy'); + contentServicesPage.pressContextMenuActionNamed('Copy'); + contentNodeSelector.checkDialogIsDisplayed(); + expect(contentNodeSelector.getDialogHeaderText()).toBe('Copy \'' + 'A' + folderModel1.name + '\' to...'); + contentNodeSelector.checkSearchInputIsDisplayed(); + expect(contentNodeSelector.getSearchLabel()).toBe('Search'); + contentNodeSelector.checkSelectedSiteIsDisplayed('My files'); + contentNodeSelector.checkCancelButtonIsDisplayed(); + contentNodeSelector.checkMoveCopyButtonIsDisplayed(); + expect(contentNodeSelector.getMoveCopyButtonText()).toBe('COPY'); + expect(contentNodeSelector.numberOfResultsDisplayed()).toBe(5); + infinitePaginationPage.clickLoadMoreButton(); + expect(contentNodeSelector.numberOfResultsDisplayed()).toBe(6); + infinitePaginationPage.checkLoadMoreButtonIsNotDisplayed(); + contentNodeSelector.contentListPage().dataTablePage().selectRowByContent('F' + folderModel6.name); + contentNodeSelector.contentListPage().dataTablePage().checkRowByContentIsSelected('F' + folderModel6.name); + contentNodeSelector.clickCancelButton(); + contentNodeSelector.checkDialogIsNotDisplayed(); + contentServicesPage.checkContentIsDisplayed('A' + folderModel1.name); + + contentListPage.rightClickOnRow('A' + folderModel1.name); + contentServicesPage.checkContextActionIsVisible('Copy'); + contentServicesPage.pressContextMenuActionNamed('Copy'); + contentNodeSelector.checkDialogIsDisplayed(); + infinitePaginationPage.clickLoadMoreButton(); + contentNodeSelector.contentListPage().dataTablePage().selectRowByContent('F' + folderModel6.name); + contentNodeSelector.contentListPage().dataTablePage().checkRowByContentIsSelected('F' + folderModel6.name); + contentNodeSelector.clickMoveCopyButton(); + contentServicesPage.checkContentIsDisplayed('A' + folderModel1.name); + paginationPage.clickOnNextPage(); + contentListPage.waitForTableBody(); + contentServicesPage.doubleClickRow('F' + folderModel6.name); + contentServicesPage.checkContentIsDisplayed('A' + folderModel1.name); + }); }); - - describe('Folder Actions', () => { - - it('[C260138] Should be able to copy a folder', () => { - contentServicesPage.copyContent(folderName); - contentServicesPage.typeIntoNodeSelectorSearchField(secondUploadedFolder.entry.name); - contentServicesPage.clickContentNodeSelectorResult(secondUploadedFolder.entry.name); - contentServicesPage.clickChooseButton(); - contentServicesPage.checkContentIsDisplayed(folderName); - contentServicesPage.doubleClickRow(secondUploadedFolder.entry.name); - contentServicesPage.checkContentIsDisplayed(folderName); - }); - - it('[C260123] Should be able to delete a folder using context menu', () => { - contentServicesPage.deleteContent(folderName); - contentServicesPage.checkContentIsNotDisplayed(folderName); - }); - - it('[C280568] Should be able to open context menu with right click', () => { - contentServicesPage.checkContentIsDisplayed(secondUploadedFolder.entry.name); - - contentListPage.rightClickOnRow(secondUploadedFolder.entry.name); - contentServicesPage.checkContextActionIsVisible('Download'); - contentServicesPage.checkContextActionIsVisible('Copy'); - contentServicesPage.checkContextActionIsVisible('Move'); - contentServicesPage.checkContextActionIsVisible('Delete'); - contentServicesPage.checkContextActionIsVisible('Info'); - contentServicesPage.checkContextActionIsVisible('Permission'); - }); - - }); - }); diff --git a/e2e/pages/adf/content-services/breadcrumb/breadCrumbDropdownPage.ts b/e2e/pages/adf/content-services/breadcrumb/breadCrumbDropdownPage.ts new file mode 100644 index 0000000000..ee19f8cf5a --- /dev/null +++ b/e2e/pages/adf/content-services/breadcrumb/breadCrumbDropdownPage.ts @@ -0,0 +1,42 @@ +/*! + * @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 { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; + +export class BreadCrumbDropdownPage { + + breadCrumb = element(by.css(`adf-dropdown-breadcrumb[data-automation-id='content-node-selector-content-breadcrumb']`)); + parentFolder = this.breadCrumb.element(by.css(`button[data-automation-id='dropdown-breadcrumb-trigger']`)); + breadCrumbDropdown = element(by.css(`div[class*='mat-select-panel']`)); + + choosePath(pathName) { + const path = this.breadCrumbDropdown.element(by.cssContainingText(`mat-option[data-automation-class='dropdown-breadcrumb-path-option'] span[class='mat-option-text']`, + pathName)); + BrowserVisibility.waitUntilElementIsVisible(path); + return path.click(); + } + + clickParentFolder() { + BrowserVisibility.waitUntilElementIsVisible(this.parentFolder); + return this.parentFolder.click(); + } + + checkBreadCrumbDropdownIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.breadCrumbDropdown); + } +} diff --git a/e2e/pages/adf/content-services/breadcrumb/breadCrumbPage.ts b/e2e/pages/adf/content-services/breadcrumb/breadCrumbPage.ts new file mode 100644 index 0000000000..cb9a1c585b --- /dev/null +++ b/e2e/pages/adf/content-services/breadcrumb/breadCrumbPage.ts @@ -0,0 +1,32 @@ +/*! + * @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 { element, by } from 'protractor'; +import { BrowserVisibility } from '@alfresco/adf-testing'; + +export class BreadCrumbPage { + + breadCrumb = element(by.css(`adf-breadcrumb nav[data-automation-id='breadcrumb']`)); + + chooseBreadCrumb(breadCrumbItem) { + const path = this.breadCrumb.element(by.css(`a[data-automation-id='breadcrumb_${breadCrumbItem}']`)); + BrowserVisibility.waitUntilElementIsVisible(path); + return path.click(); + + } + +} diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index 2cbcd74675..a098c382ef 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -16,7 +16,6 @@ */ import TestConfig = require('../../test.config'); -import { DocumentListPage } from './content-services/documentListPage'; import { CreateFolderDialog } from './dialog/createFolderDialog'; import { CreateLibraryDialog } from './dialog/createLibraryDialog'; import { DropActions } from '../../actions/drop.actions'; @@ -24,7 +23,7 @@ import { by, element, protractor, $$, browser } from 'protractor'; import path = require('path'); import { DateUtil } from '../../util/dateUtil'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { BrowserVisibility, DocumentListPage } from '@alfresco/adf-testing'; export class ContentServicesPage { @@ -658,23 +657,6 @@ export class ContentServicesPage { BrowserVisibility.waitUntilElementIsVisible(row); } - typeIntoNodeSelectorSearchField(text) { - BrowserVisibility.waitUntilElementIsVisible(this.searchInputElement); - this.searchInputElement.sendKeys(text); - } - - clickContentNodeSelectorResult(name) { - const resultElement = element.all(by.css(`div[data-automation-id="content-node-selector-content-list"] div[data-automation-id="${name}"`)).first(); - BrowserVisibility.waitUntilElementIsVisible(resultElement); - BrowserVisibility.waitUntilElementIsClickable(resultElement); - resultElement.click(); - } - - clickChooseButton() { - BrowserVisibility.waitUntilElementIsClickable(this.chooseButton); - this.chooseButton.click(); - } - clickShareButton() { BrowserVisibility.waitUntilElementIsClickable(this.shareNodeButton); this.shareNodeButton.click(); diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index f703fe10b9..47842d77e4 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -15,11 +15,8 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { SearchFiltersPage } from '../pages/adf/searchFiltersPage'; -import { PaginationPage } from '@alfresco/adf-testing'; -import { DocumentListPage } from '../pages/adf/content-services/documentListPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { SearchResultsPage } from '../pages/adf/searchResultsPage'; @@ -28,7 +25,7 @@ import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FileModel } from '../models/ACS/fileModel'; import TestConfig = require('../test.config'); -import { StringUtil } from '@alfresco/adf-testing'; +import { StringUtil, DocumentListPage, PaginationPage, LoginPage } from '@alfresco/adf-testing'; import resources = require('../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; diff --git a/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts b/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts new file mode 100644 index 0000000000..5cbf1aeaab --- /dev/null +++ b/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts @@ -0,0 +1,100 @@ +/*! + * @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 { by, element } from 'protractor'; +import { DocumentListPage } from '../pages/document-list.page'; +import { BrowserVisibility } from '../../core/browser-visibility'; + +export class ContentNodeSelectorDialogPage { + dialog = element(by.css(`adf-content-node-selector`)); + header = this.dialog.element(by.css(`header[data-automation-id='content-node-selector-title']`)); + searchInputElement = this.dialog.element(by.css(`input[data-automation-id='content-node-selector-search-input']`)); + searchLabel = this.searchInputElement.element(by.xpath("ancestor::div[@class='mat-form-field-infix']/span/label")); + siteListDropdown = this.dialog.element(by.css(`mat-select[data-automation-id='site-my-files-option']`)); + cancelButton = element(by.css(`button[data-automation-id='content-node-selector-actions-cancel']`)); + moveCopyButton = element(by.css(`button[data-automation-id='content-node-selector-actions-choose']`)); + contentList = new DocumentListPage(this.dialog); + + checkDialogIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.dialog); + return this; + } + + checkDialogIsNotDisplayed() { + BrowserVisibility.waitUntilElementIsNotOnPage(this.dialog); + return this; + } + + getDialogHeaderText() { + BrowserVisibility.waitUntilElementIsVisible(this.header); + return this.header.getText(); + } + + checkSearchInputIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.searchInputElement); + return this; + } + + getSearchLabel() { + BrowserVisibility.waitUntilElementIsVisible(this.searchLabel); + return this.searchLabel.getText(); + } + + checkSelectedSiteIsDisplayed(siteName) { + BrowserVisibility.waitUntilElementIsVisible(this.siteListDropdown.element(by.cssContainingText('.mat-select-value-text span', siteName))); + } + + checkCancelButtonIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); + } + + clickCancelButton() { + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); + return this.cancelButton.click(); + } + + checkMoveCopyButtonIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.moveCopyButton); + } + + getMoveCopyButtonText() { + BrowserVisibility.waitUntilElementIsVisible(this.moveCopyButton); + return this.moveCopyButton.getText(); + } + + clickMoveCopyButton() { + BrowserVisibility.waitUntilElementIsVisible(this.moveCopyButton); + return this.moveCopyButton.click(); + } + + numberOfResultsDisplayed() { + return this.contentList.dataTablePage().numberOfRows(); + } + + typeIntoNodeSelectorSearchField(text) { + BrowserVisibility.waitUntilElementIsVisible(this.searchInputElement); + this.searchInputElement.sendKeys(text); + } + + clickContentNodeSelectorResult(name) { + this.contentList.dataTablePage().clickRowByContent(name); + } + + contentListPage() { + return this.contentList; + } +} diff --git a/lib/testing/src/lib/content-services/pages/example.page.ts b/lib/testing/src/lib/content-services/dialog/public-api.ts similarity index 92% rename from lib/testing/src/lib/content-services/pages/example.page.ts rename to lib/testing/src/lib/content-services/dialog/public-api.ts index 9c83469852..f08c5daabc 100644 --- a/lib/testing/src/lib/content-services/pages/example.page.ts +++ b/lib/testing/src/lib/content-services/dialog/public-api.ts @@ -15,6 +15,4 @@ * limitations under the License. */ -export class ExamplePage { - -} +export * from './content-node-selector-dialog.page'; diff --git a/e2e/pages/adf/content-services/documentListPage.ts b/lib/testing/src/lib/content-services/pages/document-list.page.ts similarity index 95% rename from e2e/pages/adf/content-services/documentListPage.ts rename to lib/testing/src/lib/content-services/pages/document-list.page.ts index 47ec567c99..84e17a1ad3 100644 --- a/e2e/pages/adf/content-services/documentListPage.ts +++ b/lib/testing/src/lib/content-services/pages/document-list.page.ts @@ -16,8 +16,8 @@ */ import { by, element, ElementFinder, browser } from 'protractor'; -import { DataTableComponentPage } from '@alfresco/adf-testing'; -import { BrowserVisibility } from '@alfresco/adf-testing'; +import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; +import { BrowserVisibility } from '../../core/browser-visibility'; export class DocumentListPage { diff --git a/lib/testing/src/lib/content-services/pages/public-api.ts b/lib/testing/src/lib/content-services/pages/public-api.ts index 1233d842d2..a499c82064 100644 --- a/lib/testing/src/lib/content-services/pages/public-api.ts +++ b/lib/testing/src/lib/content-services/pages/public-api.ts @@ -15,4 +15,4 @@ * limitations under the License. */ -export * from './example.page'; +export * from './document-list.page'; diff --git a/lib/testing/src/lib/content-services/public-api.ts b/lib/testing/src/lib/content-services/public-api.ts index 357976c2aa..67b358990a 100644 --- a/lib/testing/src/lib/content-services/public-api.ts +++ b/lib/testing/src/lib/content-services/public-api.ts @@ -17,3 +17,4 @@ export * from './pages/public-api'; export * from './actions/public-api'; +export * from './dialog/public-api'; diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index 97b7851d25..0a67170f13 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -282,4 +282,28 @@ export class DataTableComponentPage { getCellByRowAndColumn(rowColumn, rowContent, columnName) { return this.getRow(rowColumn, rowContent).element(by.css(`div[title='${columnName}']`)); } + + selectRowByContent(content) { + const row = this.getCellByContent(content); + return row.click(); + } + + checkRowByContentIsSelected(folderName) { + const selectedRow = this.getCellByContent(folderName).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + BrowserVisibility.waitUntilElementIsVisible(selectedRow); + return this; + } + + getCellByContent(content) { + const cell = this.rootElement.element(by.cssContainingText(`div[class*='adf-datatable-row'] div[class*='adf-name-location-cell-name']`, content)); + BrowserVisibility.waitUntilElementIsVisible(cell); + return cell; + } + + clickRowByContent(name) { + const resultElement = this.rootElement.all(by.css(`div[data-automation-id='${name}']`)).first(); + BrowserVisibility.waitUntilElementIsVisible(resultElement); + BrowserVisibility.waitUntilElementIsClickable(resultElement); + resultElement.click(); + } } From 3f8ca56405bcb10d30ee729ba1c30125aefc971d Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Wed, 10 Apr 2019 21:45:41 +0300 Subject: [PATCH 094/208] [ADF-4921] TaskListCloud - fix lastModifiedTo date filter (#4577) * [ADF-4921] - fix lastModifiedTo date * [ADF-4291] - fix build * [ADF-4291] - fix build * [ADF-4291] - move lastModifiedTo function from task-list-cloud in edit-task-filter-cloud --- .../edit-task-filter-cloud.component.spec.ts | 25 +++++++++++++++++++ .../edit-task-filter-cloud.component.ts | 12 +++++++++ .../task-list-cloud.component.spec.ts | 1 + .../components/task-list-cloud.component.ts | 1 - 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts index bb5c1fb0c1..ecdfe1860b 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.spec.ts @@ -31,6 +31,8 @@ import { EditTaskFilterCloudComponent } from './edit-task-filter-cloud.component import { TaskFilterCloudService } from '../services/task-filter-cloud.service'; import { TaskFilterDialogCloudComponent } from './task-filter-dialog-cloud.component'; import { fakeFilter } from '../mock/task-filters-cloud.mock'; +import { AbstractControl } from '@angular/forms'; +import moment from 'moment-es6'; describe('EditTaskFilterCloudComponent', () => { let component: EditTaskFilterCloudComponent; @@ -392,6 +394,29 @@ describe('EditTaskFilterCloudComponent', () => { expect(deleteButton.disabled).toBe(false); }); })); + + it('should set the correct lastModifiedTo date', (done) => { + component.appName = 'fake'; + component.filterProperties = ['appName', 'processInstanceId', 'priority', 'lastModified']; + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange}); + fixture.detectChanges(); + + const lastModifiedToControl: AbstractControl = component.editTaskFilterForm.get('lastModifiedTo'); + lastModifiedToControl.setValue('Tue Apr 09 2019 00:00:00 GMT+0300 (Eastern European Summer Time)'); + const lastModifiedToFilter = moment(lastModifiedToControl.value); + lastModifiedToFilter.set({ + hour: 23, + minute: 59, + second: 59 + }); + + component.filterChange.subscribe( (res) => { + expect(component.changedTaskFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString()); + done(); + }); + component.onFilterChange(); + }); }); describe('edit filter actions', () => { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts index deaae0e70a..2771a3ecce 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts @@ -161,12 +161,24 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges { .pipe(debounceTime(500), filter(() => this.isFormValid())) .subscribe((formValues: TaskFilterCloudModel) => { + this.setLastModifiedToFilter(formValues); this.changedTaskFilter = new TaskFilterCloudModel(Object.assign({}, this.taskFilter, formValues)); this.formHasBeenChanged = !this.compareFilters(this.changedTaskFilter, this.taskFilter); this.filterChange.emit(this.changedTaskFilter); }); } + private setLastModifiedToFilter(formValues: TaskFilterCloudModel) { + if (formValues.lastModifiedTo && Date.parse(formValues.lastModifiedTo.toString())) { + const lastModifiedToFilterValue = moment(formValues.lastModifiedTo); + lastModifiedToFilterValue.set({ + hour: 23, + minute: 59, + second: 59 + }); + formValues.lastModifiedTo = lastModifiedToFilterValue.toDate(); + } + } createAndFilterProperties(): TaskFilterProperties[] { this.checkMandatoryFilterProperties(); diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts index 2fc3d318b6..909fbb9e94 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts @@ -26,6 +26,7 @@ import { fakeGlobalTask, fakeCustomSchema } from '../mock/fakeTaskResponseMock'; import { of } from 'rxjs'; import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { TaskListCloudModule } from '../task-list-cloud.module'; + @Component({ template: ` <adf-cloud-task-list #taskListCloud> diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts index 49d40c87b7..7355f7c4ea 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts @@ -271,5 +271,4 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges }; return new TaskQueryCloudRequestModel(requestNode); } - } From 7a2a8a1ed3f9d5bb8252e3efb37373b21dd3beae Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Wed, 10 Apr 2019 21:47:21 +0300 Subject: [PATCH 095/208] [ADF-4354]Fix cloud tests one by one (#4550) * Fix locator * Fix process-custom-filters.e2e.ts * Fix start-tasks-cloud, processList-cloud-component, start-task-custom-app-cloud tests * no message * no message * Fix process-header-cloud and task-header-cloud tests * Fix process-header-cloud tests * Fix processList-cloud-component --- .../process-custom-filters.e2e.ts | 10 +++------- e2e/process-services-cloud/process-header-cloud.e2e.ts | 10 +++++++--- .../processList-cloud-component.e2e.ts | 6 +++++- .../start-task-custom-app-cloud.e2e.ts | 1 + e2e/process-services-cloud/task-filters-cloud.e2e.ts | 9 ++++----- e2e/process-services-cloud/task-header-cloud.e2e.ts | 2 +- e2e/util/constants.js | 3 ++- .../pages/edit-process-filter-cloud-component.page.ts | 2 +- .../pages/start-tasks-cloud-component.page.ts | 1 + 9 files changed, 25 insertions(+), 19 deletions(-) diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index e0492af721..d4e3b69ccb 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -155,15 +155,13 @@ describe('Process list cloud', () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader() .setProcessInstanceId(completedProcess.entry.id); - processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); - - expect(processCloudDemoPage.processListCloudComponent().getDataTable().numberOfRows()).toBe(1); - processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(completedProcess.entry.id); - processCloudDemoPage.editProcessFilterCloudComponent().clickSaveAsButton(); processCloudDemoPage.editProcessFilterCloudComponent().editProcessFilterDialog().setFilterName('New').clickOnSaveButton(); expect(processCloudDemoPage.getActiveFilterName()).toBe('New'); + processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(completedProcess.entry.id); + expect(processCloudDemoPage.processListCloudComponent().getDataTable().numberOfRows()).toBe(1); + processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader(); expect(processCloudDemoPage.editProcessFilterCloudComponent().getProcessInstanceId()).toEqual(completedProcess.entry.id); }); @@ -176,7 +174,6 @@ describe('Process list cloud', () => { processCloudDemoPage.editProcessFilterCloudComponent().setStatusFilterDropDown('RUNNING') .setAppNameDropDown(simpleApp).setProcessInstanceId(runningProcessInstance.entry.id); - processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(runningProcessInstance.entry.id); expect(processCloudDemoPage.editProcessFilterCloudComponent().getNumberOfAppNameOptions()).toBe(noOfApps); expect(processCloudDemoPage.editProcessFilterCloudComponent().checkAppNamesAreUnique()).toBe(true); @@ -192,7 +189,6 @@ describe('Process list cloud', () => { processCloudDemoPage.editProcessFilterCloudComponent().setStatusFilterDropDown('RUNNING') .setAppNameDropDown(simpleApp).setProcessInstanceId(switchProcessInstance.entry.id); - processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(switchProcessInstance.entry.id); processCloudDemoPage.editProcessFilterCloudComponent().clickSaveAsButton(); processCloudDemoPage.editProcessFilterCloudComponent().editProcessFilterDialog().setFilterName('SwitchFilter').clickOnSaveButton(); diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index 0be178c55c..30a508265b 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -26,11 +26,13 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { ProcessHeaderCloudPage } from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; +import { browser } from 'protractor'; + describe('Process Header cloud component', () => { describe('Process Header cloud component', () => { - const simpleApp = 'simple-app', subProcessApp = 'projectsubprocess'; + const simpleApp = 'simple-app', subProcessApp = 'subprocess-app'; const formatDate = 'DD-MM-YYYY'; const processHeaderCloudPage = new ProcessHeaderCloudPage(); @@ -53,6 +55,8 @@ describe('Process Header cloud component', () => { silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); + browser.ignoreSynchronization = true; + loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -66,7 +70,7 @@ describe('Process Header cloud component', () => { simpleApp, { name: StringUtil.generateRandomString(), businessKey: 'test' }); runningCreatedDate = moment(runningProcess.entry.startDate).format(formatDate); parentCompleteProcess = await processInstancesService.createProcessInstance(childProcessDefinition.list.entries[0].entry.key, - subProcessApp, { name: 'cris' }); + subProcessApp); queryService = new QueryService(apiService); @@ -120,7 +124,7 @@ describe('Process Header cloud component', () => { processCloudDemoPage.processListCloudComponent().selectRowById(childCompleteProcess.entry.id); expect(processHeaderCloudPage.getId()).toEqual(childCompleteProcess.entry.id); - expect(processHeaderCloudPage.getName()).toEqual(childCompleteProcess.entry.name); + expect(processHeaderCloudPage.getName()).toEqual(CONSTANTS.PROCESS_DETAILS.NO_NAME); expect(processHeaderCloudPage.getStatus()).toEqual(childCompleteProcess.entry.status); expect(processHeaderCloudPage.getInitiator()).toEqual(childCompleteProcess.entry.initiator); expect(processHeaderCloudPage.getStartDate()).toEqual(completedCreatedDate); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index a9c4e2c2e6..14493237b4 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -24,6 +24,8 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { ProcessListCloudConfiguration } from './processListCloud.config'; +import { browser } from 'protractor'; + describe('Process list cloud', () => { describe('Process List', () => { @@ -46,6 +48,8 @@ describe('Process list cloud', () => { silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); + browser.ignoreSynchronization = true; + loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -80,7 +84,7 @@ describe('Process list cloud', () => { it('[C291997] Should be able to change the default columns', async () => { - expect(processCloudDemoPage.processListCloudComponent().getDataTable().getNumberOfColumns()).toBe(13); + expect(processCloudDemoPage.processListCloudComponent().getDataTable().getNumberOfColumns()).toBe(12); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('id'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('name'); processCloudDemoPage.processListCloudComponent().getDataTable().checkColumnIsDisplayed('status'); diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index be0709a98d..5c108df856 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -127,6 +127,7 @@ describe('Start Task', () => { it('[C291956] Should be able to create a new standalone task without assignee', () => { tasksCloudDemoPage.openNewTaskForm(); startTask.checkFormIsDisplayed(); + expect(peopleCloudComponent.getAssignee()).toContain('Admin', 'does not contain Admin'); startTask.clearField(peopleCloudComponent.peopleCloudSearch); startTask.addName(unassignedTaskName); startTask.clickStartButton(); diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index ddf77536a9..87655aace6 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -77,15 +77,14 @@ describe('Task filters cloud', () => { }); it('[C289955] Should display task in Complete Tasks List when task is completed', async () => { - const apiService = new ApiService('activiti', TestConfig.adf.url, TestConfig.adf.hostSso, 'BPM'); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); tasksService = new TasksService(apiService); - const task = await tasksService.createStandaloneTask(completedTask, simpleApp); - - await tasksService.claimTask(task.entry.id, simpleApp); - await tasksService.completeTask(task.entry.id, simpleApp); + const toBeCompletedTask = await tasksService.createStandaloneTask(completedTask, simpleApp); + await tasksService.claimTask(toBeCompletedTask.entry.id, simpleApp); + await tasksService.completeTask(toBeCompletedTask.entry.id, simpleApp); tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index 129b9dcfdd..e519ff0119 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -31,7 +31,7 @@ describe('Task Header cloud component', () => { const basicCreatedTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(); let basicCreatedTask, basicCreatedDate, completedTask, completedCreatedDate, subTask, subTaskCreatedDate; const simpleApp = 'simple-app'; - const priority = 30, description = 'descriptionTask', formatDate = 'MMM DD YYYY'; + const priority = 30, description = 'descriptionTask', formatDate = 'DD-MM-YYYY'; const taskHeaderCloudPage = new TaskHeaderCloudPage(); diff --git a/e2e/util/constants.js b/e2e/util/constants.js index e937d2d668..f7bf434583 100644 --- a/e2e/util/constants.js +++ b/e2e/util/constants.js @@ -131,7 +131,8 @@ exports.PROCESS_DETAILS = { NO_PARENT: "None", NO_DATE: "No date", NO_BUSINESS_KEY: 'None', - NO_DESCRIPTION: 'No description' + NO_DESCRIPTION: 'No description', + NO_NAME: 'No name' }; exports.PROCESS_STATUS = { diff --git a/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts index b683c0ddf2..423f6cd83b 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts @@ -178,7 +178,7 @@ export class EditProcessFilterCloudComponentPage { } clickSaveAsButton() { - const disabledButton = element(by.css(("button[id='adf-save-as-id'][disabled]"))); + const disabledButton = element(by.css(("button[data-automation-id='adf-filter-action-saveAs'][disabled]"))); BrowserVisibility.waitUntilElementIsClickable(this.saveAsButton); BrowserVisibility.waitUntilElementIsVisible(this.saveAsButton); BrowserVisibility.waitUntilElementIsNotVisible(disabledButton); diff --git a/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts index fc314e83e9..47ec6963ea 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts @@ -106,6 +106,7 @@ export class StartTasksCloudPage { clearField(locator) { BrowserVisibility.waitUntilElementIsVisible(locator); + BrowserVisibility.waitUntilElementIsClickable(locator); locator.getAttribute('value').then((result) => { for (let i = result.length; i >= 0; i--) { locator.sendKeys(protractor.Key.BACK_SPACE); From 1336fbee0e0604ee1e8090a7dd9012115c42fc2c Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Wed, 10 Apr 2019 19:48:20 +0100 Subject: [PATCH 096/208] [ADF-4278][ADF-4277] - Should fetch the preselect users (#4535) * C305033 Preselect Users automated. * fix the LastName issue failing. * C305041 automated * in progress * in progress * in progress * in progress * lint fix * moving the assignee filed to PeopleCloudComponent * moving the assignee filed to PeopleCloudComponent * split the tests into smaller chunks for easy understandability. * added the missing check and renamed the method appropriately. * fixes for flakiness --- .../people-groups-cloud-demo.component.html | 4 +- .../peopleGroupCloudComponentPage.ts | 62 ++++++ .../people-group-cloud-component.e2e.ts | 187 ++++++++++++++++-- .../identity/group-identity.service.ts | 34 ++++ .../core/actions/identity/identity.service.ts | 18 +- .../core/actions/identity/roles.service.ts | 15 ++ lib/testing/src/lib/core/models/user.model.ts | 3 +- .../pages/group-cloud-component.page.ts | 16 ++ .../pages/people-cloud-component.page.ts | 18 ++ 9 files changed, 335 insertions(+), 22 deletions(-) diff --git a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html index febd6f6414..dda47274ac 100644 --- a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html @@ -24,7 +24,7 @@ </mat-form-field> <mat-form-field *ngIf="isPeopleAppNameSelected()" class="adf-preselect-value"> <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.APP_NAME' | translate }}</mat-label> - <input matInput (input)="setPeopleAppName($event)" /> + <input matInput (input)="setPeopleAppName($event)" data-automation-id="adf-people-app-input" /> </mat-form-field> <mat-form-field class="adf-preselect-value-full"> <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.PRESELECTED_VALUE' | translate }}: {{ DEFAULT_PEOPLE_PLACEHOLDER }}</mat-label> @@ -81,7 +81,7 @@ </mat-form-field> <mat-form-field *ngIf="isGroupAppNameSelected()" class="adf-preselect-value"> <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.APP_NAME' | translate }}</mat-label> - <input matInput (input)="setGroupAppName($event)" /> + <input matInput (input)="setGroupAppName($event)" data-automation-id="adf-group-app-input"/> </mat-form-field> <mat-form-field class="adf-preselect-value-full"> <mat-label>Preselect: {{ DEFAULT_GROUP_PLACEHOLDER }}</mat-label> diff --git a/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts b/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts index a7ff4a75df..6b2b1b6aaf 100644 --- a/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage.ts @@ -21,17 +21,24 @@ import { BrowserVisibility } from '@alfresco/adf-testing'; export class PeopleGroupCloudComponentPage { peopleCloudSingleSelection = element(by.css('mat-radio-button[data-automation-id="adf-people-single-mode"]')); + peopleCloudSingleSelectionChecked = element(by.css('mat-radio-button[data-automation-id="adf-people-single-mode"][class*="mat-radio-checked"]')); peopleCloudMultipleSelection = element(by.css('mat-radio-button[data-automation-id="adf-people-multiple-mode"]')); peopleCloudFilterRole = element(by.css('mat-radio-button[data-automation-id="adf-people-filter-role"]')); groupCloudSingleSelection = element(by.css('mat-radio-button[data-automation-id="adf-group-single-mode"]')); groupCloudMultipleSelection = element(by.css('mat-radio-button[data-automation-id="adf-group-multiple-mode"]')); groupCloudFilterRole = element(by.css('mat-radio-button[data-automation-id="adf-group-filter-role"]')); peopleRoleInput = element(by.css('input[data-automation-id="adf-people-roles-input"]')); + peopleAppInput = element(by.css('input[data-automation-id="adf-people-app-input"]')); peoplePreselect = element(by.css('input[data-automation-id="adf-people-preselect-input"]')); groupRoleInput = element(by.css('input[data-automation-id="adf-group-roles-input"]')); + groupAppInput = element(by.css('input[data-automation-id="adf-group-app-input"]')); groupPreselect = element(by.css('input[data-automation-id="adf-group-preselect-input"]')); peopleCloudComponentTitle = element(by.cssContainingText('mat-card-title', 'People Cloud Component')); groupCloudComponentTitle = element(by.cssContainingText('mat-card-title', 'Groups Cloud Component')); + preselectValidation = element(by.css('mat-checkbox.adf-preselect-value')); + preselectValidationStatus = element(by.css('mat-checkbox.adf-preselect-value label input')); + peopleFilterByAppName = element(by.css('.people-control-options mat-radio-button[value="appName"]')); + groupFilterByAppName = element(by.css('.groups-control-options mat-radio-button[value="appName"]')); checkPeopleCloudComponentTitleIsDisplayed() { BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudComponentTitle); @@ -48,6 +55,15 @@ export class PeopleGroupCloudComponentPage { this.peopleCloudMultipleSelection.click(); } + clickPeopleCloudSingleSelection() { + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSingleSelection); + this.peopleCloudSingleSelection.click(); + } + + checkPeopleCloudSingleSelectionIsSelected() { + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSingleSelectionChecked); + } + clickPeopleCloudFilterRole() { BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudFilterRole); this.peopleCloudFilterRole.click(); @@ -65,6 +81,13 @@ export class PeopleGroupCloudComponentPage { return this; } + enterPeoplePreselect(preselect) { + BrowserVisibility.waitUntilElementIsVisible(this.peoplePreselect); + this.peoplePreselect.clear(); + this.peoplePreselect.sendKeys(preselect); + return this; + } + clearField(locator) { BrowserVisibility.waitUntilElementIsVisible(locator); locator.getAttribute('value').then((result) => { @@ -74,6 +97,11 @@ export class PeopleGroupCloudComponentPage { }); } + clickGroupCloudSingleSelection() { + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudSingleSelection); + this.groupCloudSingleSelection.click(); + } + clickGroupCloudMultipleSelection() { BrowserVisibility.waitUntilElementIsVisible(this.groupCloudMultipleSelection); this.groupCloudMultipleSelection.click(); @@ -86,4 +114,38 @@ export class PeopleGroupCloudComponentPage { return this; } + clickPreselectValidation() { + BrowserVisibility.waitUntilElementIsVisible(this.preselectValidation); + this.preselectValidation.click(); + } + + getPreselectValidationStatus() { + BrowserVisibility.waitUntilElementIsVisible(this.preselectValidationStatus); + return this.preselectValidationStatus.getAttribute('aria-checked'); + } + + clickPeopleFilerByApp() { + BrowserVisibility.waitUntilElementIsVisible(this.peopleFilterByAppName); + return this.peopleFilterByAppName.click(); + } + + clickGroupFilerByApp() { + BrowserVisibility.waitUntilElementIsVisible(this.groupFilterByAppName); + return this.groupFilterByAppName.click(); + } + + enterPeopleAppName(appName) { + BrowserVisibility.waitUntilElementIsVisible(this.peopleAppInput); + this.peopleAppInput.clear(); + this.peopleAppInput.sendKeys(appName); + return this; + } + + enterGroupAppName(appName) { + BrowserVisibility.waitUntilElementIsVisible(this.groupAppInput); + this.groupAppInput.clear(); + this.groupAppInput.sendKeys(appName); + return this; + } + } diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 1f93f7170f..888a223beb 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -49,8 +49,10 @@ describe('People Groups Cloud Component', () => { let activitiUserRoleId; let apsAdminRoleId; let activitiAdminRoleId; + let clientActivitiAdminRoleId, clientActivitiUserRoleId; let users = []; let groups = []; + let clientId; beforeAll(async () => { @@ -58,6 +60,11 @@ describe('People Groups Cloud Component', () => { await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); identityService = new IdentityService(apiService); rolesService = new RolesService(apiService); + groupIdentityService = new GroupIdentityService(apiService); + clientId = await groupIdentityService.getClientIdByApplicationName('simple-app'); + groupActiviti = await groupIdentityService.createIdentityGroup(); + clientActivitiAdminRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_ADMIN); + clientActivitiUserRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_USER); apsUser = await identityService.createIdentityUser(); apsUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_USER); @@ -66,14 +73,18 @@ describe('People Groups Cloud Component', () => { activitiUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_USER); await identityService.assignRole(activitiUser.idIdentityService, activitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); noRoleUser = await identityService.createIdentityUser(); - groupIdentityService = new GroupIdentityService(apiService); + await identityService.deleteClientRole(noRoleUser.idIdentityService, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN); + await identityService.deleteClientRole(noRoleUser.idIdentityService, clientId, clientActivitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); + groupAps = await groupIdentityService.createIdentityGroup(); apsAdminRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_ADMIN); await groupIdentityService.assignRole(groupAps.id, apsAdminRoleId, CONSTANTS.ROLES.APS_ADMIN); - groupActiviti = await groupIdentityService.createIdentityGroup(); activitiAdminRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_ADMIN); await groupIdentityService.assignRole(groupActiviti.id, activitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN); groupNoRole = await groupIdentityService.createIdentityGroup(); + + await groupIdentityService.addClientRole(groupAps.id, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN ); + await groupIdentityService.addClientRole(groupActiviti.id, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN ); users = [`${apsUser.idIdentityService}`, `${activitiUser.idIdentityService}`, `${noRoleUser.idIdentityService}`]; groups = [`${groupAps.id}`, `${groupActiviti.id}`, `${groupNoRole.id}`]; silentLogin = false; @@ -104,11 +115,11 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); peopleGroupCloudComponentPage.enterPeopleRoles(`["${CONSTANTS.ROLES.APS_USER}"]`); peopleCloudComponent.searchAssignee('LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); - peopleCloudComponent.checkUserIsNotDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); - peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); - peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); - peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); }); it('[C297674] Add more than one role filtering to PeopleCloudComponent', () => { @@ -116,22 +127,22 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); peopleGroupCloudComponentPage.enterPeopleRoles(`["${CONSTANTS.ROLES.APS_USER}", "${CONSTANTS.ROLES.ACTIVITI_USER}"]`); peopleCloudComponent.searchAssignee('LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); - peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); - peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); - peopleCloudComponent.checkSelectedPeople(`${activitiUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.lastName}`); }); it('[C297674] Add no role filters to PeopleCloudComponent', () => { peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); peopleCloudComponent.searchAssignee('LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}` + 'LastName'); - peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}` + 'LastName'); - peopleCloudComponent.selectAssigneeFromList(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); - peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}` + 'LastName'); + peopleCloudComponent.checkUserIsDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); }); it('[C297674] Add role filtering to GroupCloudComponent', () => { @@ -170,6 +181,148 @@ describe('People Groups Cloud Component', () => { groupCloudComponentPage.checkSelectedGroup(`${groupNoRole.name}`); }); + it('[C305033] Should fetch the preselect users based on the Validate flag set to True in Single mode selection', () => { + + peopleGroupCloudComponentPage.checkPeopleCloudSingleSelectionIsSelected(); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"id":"${noRoleUser.idIdentityService}"}]`); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('false'); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"email":"${apsUser.email}"}]`); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('false'); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"username":"${activitiUser.username}"}]`); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + + peopleGroupCloudComponentPage.enterPeoplePreselect('[{"id":"12345","username":"someUsername","email":"someEmail"}]'); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('false'); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(''); + }); + + it('[C305033] Should fetch the preselect users based on the Validate flag set to True in Multiple mode selection', () => { + + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"id":"${apsUser.idIdentityService}"},{"id":"${activitiUser.idIdentityService}"},` + + `{"id":"${noRoleUser.idIdentityService}"}]`); + peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"email":"${apsUser.email}"},{"email":"${activitiUser.email}"},{"email":"${noRoleUser.email}"}]`); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"username":"${apsUser.username}"},{"username":"${activitiUser.username}"},` + + `{"username":"${noRoleUser.username}"}]`); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + + peopleCloudComponent.searchAssigneeToExisting('LastName'); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + + }); + + it('[C305033] Should populate the Users without any validation when the Preselect flag is set to false', () => { + peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('false'); + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"firstName":"TestFirstName1","lastName":"TestLastName1"},` + + `{"firstName":"TestFirstName2","lastName":"TestLastName2"},{"firstName":"TestFirstName3","lastName":"TestLastName3"}]`); + peopleCloudComponent.checkSelectedPeople('TestFirstName1 TestLastName1'); + peopleCloudComponent.checkSelectedPeople('TestFirstName2 TestLastName2'); + peopleCloudComponent.checkSelectedPeople('TestFirstName3 TestLastName3'); + + }); + + it('[C305033] Should not fetch the preselect users when mandatory parameters Id, Email and username are missing', () => { + peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); + peopleGroupCloudComponentPage.clickPreselectValidation(); + expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); + peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"firstName":"${apsUser.firstName}","lastName":"${apsUser.lastName},"` + + `{"firstName":"${activitiUser.firstName}","lastName":"${activitiUser.lastName}",{"firstName":"${noRoleUser.firstName}","lastName":"${noRoleUser.lastName}"]`); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(''); + + }); + + it('[C305041] Should filter the People Single Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.checkPeopleCloudSingleSelectionIsSelected(); + peopleGroupCloudComponentPage.clickPeopleFilerByApp(); + peopleGroupCloudComponentPage.enterPeopleAppName('simple-app'); + peopleCloudComponent.searchAssignee(`${activitiUser.firstName}`); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + }); + + it('[C305041] Should filter the People Multiple Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); + peopleGroupCloudComponentPage.clickPeopleFilerByApp(); + peopleGroupCloudComponentPage.enterPeopleAppName('simple-app'); + peopleCloudComponent.searchAssignee(`${apsUser.firstName}`); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + + peopleCloudComponent.searchAssigneeToExisting(`${activitiUser.firstName}`); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + + peopleCloudComponent.searchAssigneeToExisting(`${noRoleUser.firstName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + }); + + it('[C305041] Should filter the Groups Single Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.clickGroupCloudSingleSelection(); + peopleGroupCloudComponentPage.clickGroupFilerByApp(); + peopleGroupCloudComponentPage.enterGroupAppName('simple-app'); + groupCloudComponentPage.searchGroups(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); + expect(groupCloudComponentPage.getGroupsFieldContent()).toBe(`${groupActiviti.name}`); + }); + + it('[C305041] Should filter the Groups Multiple Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); + peopleGroupCloudComponentPage.clickGroupFilerByApp(); + peopleGroupCloudComponentPage.enterGroupAppName('simple-app'); + groupCloudComponentPage.searchGroups(`${groupAps.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupAps.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupAps.name}`); + + groupCloudComponentPage.searchGroupsToExisting(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupActiviti.name}`); + + groupCloudComponentPage.searchGroupsToExisting(`${groupNoRole.name}`); + groupCloudComponentPage.checkGroupIsNotDisplayed(`${groupNoRole.name}`); + }); + }); }); diff --git a/lib/testing/src/lib/core/actions/identity/group-identity.service.ts b/lib/testing/src/lib/core/actions/identity/group-identity.service.ts index 9f7b9a346d..1cea809cf0 100644 --- a/lib/testing/src/lib/core/actions/identity/group-identity.service.ts +++ b/lib/testing/src/lib/core/actions/identity/group-identity.service.ts @@ -74,4 +74,38 @@ export class GroupIdentityService { return data; } + /** + * Add client roles. + * @param groupId ID of the target group + * @param clientId ID of the client + * @param roleId ID of the clientRole + * @param roleName of the clientRole + */ + async addClientRole(groupId: string, clientId: string, roleId: string, roleName: string) { + const path = `/groups/${groupId}/role-mappings/clients/${clientId}`; + const method = 'POST', queryParams = {}, + postBody = [{ + 'id': roleId, + 'name': roleName, + 'composite': false, + 'clientRole': true, + 'containerId': clientId + }]; + const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); + return data; + } + + /** + * Gets the client ID using the app name. + * @param applicationName Name of the app + * @returns client ID string + */ + async getClientIdByApplicationName(applicationName: string) { + const path = `/clients`; + const method = 'GET', queryParams = {clientId: applicationName}, postBody = {}; + + const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); + return data[0].id; + } + } diff --git a/lib/testing/src/lib/core/actions/identity/identity.service.ts b/lib/testing/src/lib/core/actions/identity/identity.service.ts index e42a46e4a7..0c1e3a08e7 100644 --- a/lib/testing/src/lib/core/actions/identity/identity.service.ts +++ b/lib/testing/src/lib/core/actions/identity/identity.service.ts @@ -29,7 +29,7 @@ export class IdentityService { async createIdentityUser(user: UserModel = new UserModel()) { await this.createUser(user); - const userIdentity = await this.getUserInfoByUsername(user.email); + const userIdentity = await this.getUserInfoByUsername(user.username); await this.resetPassword(userIdentity.id, user.password); user.idIdentityService = userIdentity.id; return user; @@ -63,7 +63,7 @@ export class IdentityService { const path = '/users'; const method = 'POST'; const queryParams = {}, postBody = { - 'username': user.email, + 'username': user.username, 'firstName': user.firstName, 'lastName': user.lastName, 'enabled': true, @@ -110,4 +110,18 @@ export class IdentityService { return data; } + async deleteClientRole(userId: string, clientId: string, roleId: string, roleName: string) { + const path = `/users/${userId}/role-mappings/clients/${clientId}`; + const method = 'DELETE', queryParams = {}, + postBody = [{ + 'id': roleId, + 'name': roleName, + 'composite': false, + 'clientRole': true, + 'containerId': clientId + }]; + const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); + return data; + } + } diff --git a/lib/testing/src/lib/core/actions/identity/roles.service.ts b/lib/testing/src/lib/core/actions/identity/roles.service.ts index acce862c4b..1b2c60da5c 100644 --- a/lib/testing/src/lib/core/actions/identity/roles.service.ts +++ b/lib/testing/src/lib/core/actions/identity/roles.service.ts @@ -40,4 +40,19 @@ export class RolesService { return roleId; } + async getClientRoleIdByRoleName(groupId, clientId, clientRoleName) { + const path = `/groups/${groupId}/role-mappings/clients/${clientId}/available`; + const method = 'GET'; + let clientRoleId; + const queryParams = {}, postBody = {}; + + const data = await this.api.performIdentityOperation(path, method, queryParams, postBody); + for (const key in data) { + if (data[key].name === clientRoleName) { + clientRoleId = data[key].id; + } + } + return clientRoleId; + } + } diff --git a/lib/testing/src/lib/core/models/user.model.ts b/lib/testing/src/lib/core/models/user.model.ts index b307c35a09..d3efd3db37 100644 --- a/lib/testing/src/lib/core/models/user.model.ts +++ b/lib/testing/src/lib/core/models/user.model.ts @@ -20,9 +20,10 @@ import { StringUtil } from '../string.util'; export class UserModel { firstName: string = StringUtil.generateRandomString(); - lastName: string = StringUtil.generateRandomString(); + lastName: string = StringUtil.generateRandomString() + 'LastName'; password: string = StringUtil.generateRandomString(); email: string = StringUtil.generateRandomEmail('@alfresco.com'); + username: string = StringUtil.generateRandomString().toLowerCase(); idIdentityService: string; constructor(details?: any) { diff --git a/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts index 67c0320e67..2ee1e1c1f5 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts @@ -34,6 +34,22 @@ export class GroupCloudComponentPage { return this; } + searchGroupsToExisting(name) { + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudSearch); + for (let i = 0; i < name.length; i++) { + this.groupCloudSearch.sendKeys(name[i]); + } + this.groupCloudSearch.sendKeys(protractor.Key.BACK_SPACE); + this.groupCloudSearch.sendKeys(name[name.length - 1]); + return this; + } + + getGroupsFieldContent() { + BrowserVisibility.waitUntilElementIsVisible(this.groupCloudSearch); + return this.groupCloudSearch.getAttribute('value'); + + } + selectGroupFromList(name) { const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); BrowserVisibility.waitUntilElementIsVisible(groupRow); diff --git a/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts index 428dfeceb0..13f38b45e4 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts @@ -21,6 +21,7 @@ import { BrowserVisibility } from '../../core/browser-visibility'; export class PeopleCloudComponentPage { peopleCloudSearch = element(by.css('input[data-automation-id="adf-people-cloud-search-input"]')); + assigneeField = element(by.css('input[data-automation-id="adf-people-cloud-search-input"]')); searchAssigneeAndSelect(name) { BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); @@ -32,6 +33,7 @@ export class PeopleCloudComponentPage { searchAssignee(name) { BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); + BrowserVisibility.waitUntilElementIsClickable(this.peopleCloudSearch); this.peopleCloudSearch.clear().then(() => { for (let i = 0; i < name.length; i++) { this.peopleCloudSearch.sendKeys(name[i]); @@ -42,6 +44,16 @@ export class PeopleCloudComponentPage { return this; } + searchAssigneeToExisting(name) { + BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); + for (let i = 0; i < name.length; i++) { + this.peopleCloudSearch.sendKeys(name[i]); + } + this.peopleCloudSearch.sendKeys(protractor.Key.BACK_SPACE); + this.peopleCloudSearch.sendKeys(name[name.length - 1]); + return this; + } + selectAssigneeFromList(name) { const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); BrowserVisibility.waitUntilElementIsVisible(assigneeRow); @@ -72,4 +84,10 @@ export class PeopleCloudComponentPage { return this; } + getAssigneeFieldContent() { + BrowserVisibility.waitUntilElementIsVisible(this.assigneeField); + return this.assigneeField.getAttribute('value'); + + } + } From 790beb2bb9c665125e496de94025704d8dabbdf1 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Wed, 10 Apr 2019 20:21:14 +0100 Subject: [PATCH 097/208] [ADF-4213] drop events for DataTable component (#4589) * stub for demo shell * drop events for datatable * fix docs * cleanup template * remove unused attribute * disable spellcheck for the demo file --- demo-shell/src/app/app.routes.ts | 4 + .../app-layout/app-layout.component.ts | 3 +- .../datatable-dnd.component.html | 6 ++ .../drag-and-drop/datatable-dnd.component.ts | 99 +++++++++++++++++++ .../drag-and-drop/datatable-dnd.module.ts | 41 ++++++++ docs/core/components/datatable.component.md | 24 ++++- .../datatable/datatable.component.html | 8 +- .../datatable/datatable.component.ts | 47 +++++++++ 8 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html create mode 100644 demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts create mode 100644 demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.module.ts diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index f2f14739e6..703c724073 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -254,6 +254,10 @@ export const appRoutes: Routes = [ path: 'datatable', loadChildren: 'app/components/datatable/datatable.module#AppDataTableModule' }, + { + path: 'datatable/dnd', + loadChildren: './components/datatable/drag-and-drop/datatable-dnd.module#AppDataTableDndModule' + }, { path: 'search', component: SearchResultComponent, diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index d58c63290c..f9fa4534f9 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -63,7 +63,8 @@ export class AppLayoutComponent implements OnInit { { href: '/dl-custom-sources', icon: 'extension', title: 'APP_LAYOUT.CUSTOM_SOURCES' }, { href: '/datatable', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE', children: [ { href: '/datatable', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE' }, - { href: '/datatable-lazy', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE_LAZY' } + { href: '/datatable-lazy', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE_LAZY' }, + { href: '/datatable/dnd', icon: 'view_module', title: 'Drag and Drop' } ]}, { href: '/template-list', icon: 'list_alt', title: 'APP_LAYOUT.TEMPLATE' }, { href: '/webscript', icon: 'extension', title: 'APP_LAYOUT.WEBSCRIPT' }, diff --git a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html new file mode 100644 index 0000000000..1a5cc482f3 --- /dev/null +++ b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html @@ -0,0 +1,6 @@ +<h1>DataTable Drag and Drop Demo</h1> +<div + (header-drop)="onDrop($event)" + (cell-drop)="onDrop($event)"> + <adf-datatable [data]="data"></adf-datatable> +</div> diff --git a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts new file mode 100644 index 0000000000..5b4f90e3e5 --- /dev/null +++ b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts @@ -0,0 +1,99 @@ +/*! + * @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. + */ + +/* cspell:disable */ + +import { Component, OnInit } from '@angular/core'; +import { ObjectDataTableAdapter, DataSorting, NotificationService, DataTableDropEvent } from '@alfresco/adf-core'; + +const createdBy = { + name: 'Administrator', + email: 'admin@alfresco.com' +}; + +@Component({ + selector: 'app-datatable-dnd', + templateUrl: './datatable-dnd.component.html' +}) +export class DataTableDnDComponent implements OnInit { + + data: ObjectDataTableAdapter; + + constructor(private notificationService: NotificationService) { + } + + ngOnInit() { + this.data = new ObjectDataTableAdapter( + [ + { + id: 1, + name: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum.`, + createdOn: new Date(2016, 6, 2, 15, 8, 1), + createdBy, + icon: 'material-icons://folder_open', + json: null + }, + { + id: 2, + name: 'Name 2', + createdOn: new Date(2016, 6, 2, 15, 8, 2), + createdBy, + icon: 'material-icons://accessibility', + json: null + }, + { + id: 3, + name: 'Name 3', + createdOn: new Date(2016, 6, 2, 15, 8, 3), + createdBy, + icon: 'material-icons://alarm', + json: null + }, + { + id: 4, + name: 'Image 8', + createdOn: new Date(2016, 6, 2, 15, 8, 4), + createdBy, + icon: 'material-icons://alarm' + } + ], + [ + { type: 'image', key: 'icon', title: '', srTitle: 'Thumbnail' }, + { type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '' }, + { type: 'text', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-2' }, + { type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true }, + { type: 'text', key: 'createdBy.name', title: 'Created By', sortable: true, cssClass: ''} + ] + ); + + this.data.setSorting(new DataSorting('id', 'asc')); + } + + onDrop(event: DataTableDropEvent) { + event.preventDefault(); + + const { column, target } = event.detail; + const message = `Dropped data on [ ${column.key} ] ${target}`; + + this.notificationService.openSnackMessage(message); + } +} diff --git a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.module.ts b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.module.ts new file mode 100644 index 0000000000..82b0352525 --- /dev/null +++ b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.module.ts @@ -0,0 +1,41 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { CoreModule } from '@alfresco/adf-core'; +import { ContentModule } from '@alfresco/adf-content-services'; +import { DataTableDnDComponent } from './datatable-dnd.component'; + +const routes: Routes = [ + { + path: '', + component: DataTableDnDComponent + } +]; + +@NgModule({ + imports: [ + CommonModule, + RouterModule.forChild(routes), + CoreModule.forChild(), + ContentModule.forChild() + ], + declarations: [DataTableDnDComponent] +}) +export class AppDataTableDndModule {} diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 5d922f2a84..1eff7b0e2c 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -367,8 +367,30 @@ These events bubble up the component tree and can be handled by any parent compo | row-unselect | Raised after user unselects a row | | row-keyup | Raised on the 'keyup' event for the focused row. | | sorting-changed | Raised after user clicks the sortable column header. | +| header-drop | Raised when data is dropped on the column header. | +| cell-drop | Raised when data is dropped on the column cell. | -For example: +#### Drop Events + +All custom DOM events related to `drop` handling expose the following interface: + +```ts +export interface DataTableDropEvent { + detail: { + target: 'cell' | 'header'; + event: Event; + column: DataColumn; + row?: DataRow + }; + + preventDefault(): void; +} +``` + +Note that `event` is the original `drop` event, +and `row` is not available for Header events. + +#### Example ```html <root-component (row-click)="onRowClick($event)"> diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 7a660d51fe..a1acc46132 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -25,7 +25,9 @@ (keyup.enter)="onColumnHeaderClick(col)" role="columnheader" tabindex="0" - title="{{ col.title | translate }}"> + title="{{ col.title | translate }}" + (dragover)="onDragOver($event)" + (drop)="onHeaderDrop($event, col)"> <span *ngIf="col.srTitle" class="adf-sr-only">{{ col.srTitle | translate }}</span> <span *ngIf="col.title" class="adf-datatable-cell-value">{{ col.title | translate}}</span> </div> @@ -95,7 +97,9 @@ (click)="onRowClick(row, $event)" (keydown.enter)="onEnterKeyPressed(row, $event)" [adf-context-menu]="getContextMenuActions(row, col)" - [adf-context-menu-enabled]="contextMenu"> + [adf-context-menu-enabled]="contextMenu" + (dragover)="onDragOver($event)" + (drop)="onCellDrop($event, col, row)"> <div *ngIf="!col.template" class="adf-datatable-cell-container"> <ng-container [ngSwitch]="col.type"> <div *ngSwitchCase="'image'" class="adf-cell-value"> diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 524984017b..8dd36c03c0 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -701,4 +701,51 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, const name = this.getNameColumnValue(); return name ? row.getValue(name.key) : ''; } + + onDragOver(event: Event) { + event.preventDefault(); + } + + onHeaderDrop(event: Event, column: DataColumn) { + event.preventDefault(); + + this.elementRef.nativeElement.dispatchEvent( + new CustomEvent('header-drop', { + detail: { + target: 'header', + event, + column + }, + bubbles: true + }) + ); + } + + onCellDrop(event: Event, column: DataColumn, row: DataRow) { + event.preventDefault(); + + this.elementRef.nativeElement.dispatchEvent( + new CustomEvent('cell-drop', { + detail: { + target: 'cell', + event, + column, + row + }, + bubbles: true + }) + ); + } + +} + +export interface DataTableDropEvent { + detail: { + target: 'cell' | 'header'; + event: Event; + column: DataColumn; + row?: DataRow + }; + + preventDefault(): void; } From 4f76c4e45c5c512ab3ad05b0c302984e89ab3c47 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 11 Apr 2019 12:07:18 +0100 Subject: [PATCH 098/208] [build-issue] Run always all when is not a PR (#4593) * run always all when is not a PR * run always all when is not a PR * run always all when is not a PR * run always all when is not a PR * run always all when is not a PR --- .travis.yml | 27 +++++++++++++-------------- demo-shell/proxy.conf.js | 2 +- tslint.json | 2 -- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0cfefd25d9..66e0d36397 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,10 +21,7 @@ branches: # TRAVIS_PULL_REQUEST == false means is running on dev branch and is not a PR stages: - - name: Warm Up Cache - if: branch = master - name: Warm Up Cache & Lint & Build Dist - if: branch != master - name: Unit test - name: e2e Test - name: Create Docker PR @@ -44,19 +41,21 @@ before_install: jobs: include: - - stage: Warm Up Cache - script: - - ./scripts/npm-build-all.sh || exit 1 - stage: Warm Up Cache & Lint & Build Dist script: - - ./scripts/update-version.sh -gnu -alpha || exit 1 - - npm install - - ./scripts/lint.sh || exit 1 - - rm -rf tmp && mkdir tmp - - git merge-base origin/$TRAVIS_BRANCH HEAD > ./tmp/devhead.txt - - (./scripts/smart-build.sh -b $TRAVIS_BRANCH -gnu || exit 1;); - - npm run build:dist || exit 1 - - ./scripts/license-list-generator.sh + if [[ $TRAVIS_PULL_REQUEST == "false" ]]; + then + (./scripts/npm-build-all.sh || exit 1); + else + (./scripts/update-version.sh -gnu -alpha || exit 1); + npm install; + (./scripts/lint.sh || exit 1); + (rm -rf tmp && mkdir tmp); + (git merge-base origin/$TRAVIS_BRANCH HEAD > ./tmp/devhead.txt); + (./scripts/smart-build.sh -b $TRAVIS_BRANCH -gnu || exit 1); + fi; + (npm run build:dist || exit 1); + (./scripts/license-list-generator.sh || exit 1); - stage: Unit test name: core and extensions script: diff --git a/demo-shell/proxy.conf.js b/demo-shell/proxy.conf.js index eaa6a59bb1..7da0babb2f 100644 --- a/demo-shell/proxy.conf.js +++ b/demo-shell/proxy.conf.js @@ -1,6 +1,6 @@ module.exports = { "/alfresco": { - "target": "http://aps2staging.envalfresco.com", + "target": "http://localhost:8080", "secure": false, "pathRewrite": { "^/alfresco/alfresco": "" diff --git a/tslint.json b/tslint.json index cefc89ebcf..85f3072268 100644 --- a/tslint.json +++ b/tslint.json @@ -180,9 +180,7 @@ true, 2 ], - "contextual-life-cycle": true, "use-host-property-decorator": false, - "use-life-cycle-interface": true, "use-pipe-transform-interface": true, "component-class-suffix": true, "directive-class-suffix": true, From f258c79f7adbe8e49cbfd80ade1b46052487a586 Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Thu, 11 Apr 2019 14:06:52 +0100 Subject: [PATCH 099/208] [ADF-4391] Removed duplicate title in Form Cloud service docs (#4594) --- docs/process-services-cloud/services/form-cloud.service.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/process-services-cloud/services/form-cloud.service.md b/docs/process-services-cloud/services/form-cloud.service.md index d5777ba7d9..fcb2dab5bd 100644 --- a/docs/process-services-cloud/services/form-cloud.service.md +++ b/docs/process-services-cloud/services/form-cloud.service.md @@ -1,5 +1,4 @@ --- -Title: Form service Title: Form cloud service Added: v3.2.0 Status: Active From 0fe0ee9db7546fbb54bca26dcbfd86b406795716 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Fri, 12 Apr 2019 09:25:29 +0100 Subject: [PATCH 100/208] [ADF-4274] Should be able to reassign the removed user when starting a new task. (#4591) * C305050 automated * added the api call to delete the tasks created in afterAll() method and also creating a new user and using that in the Tests and deleting the user in the end rather than using 'Super Admin' and reduce the dependency on env configuration. * linting fixes --- .../start-task-custom-app-cloud.e2e.ts | 53 +++++++++++++++++-- .../core/actions/identity/tasks.service.ts | 10 ++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 5c108df856..22c85059f0 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -18,8 +18,10 @@ import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { LoginSSOPage, SettingsPage, AppListCloudPage, StringUtil, TaskHeaderCloudPage, - StartTasksCloudPage, PeopleCloudComponentPage } from '@alfresco/adf-testing'; +import { + LoginSSOPage, SettingsPage, AppListCloudPage, StringUtil, TaskHeaderCloudPage, + StartTasksCloudPage, PeopleCloudComponentPage, TasksService, ApiService, IdentityService +} from '@alfresco/adf-testing'; import { browser } from 'protractor'; describe('Start Task', () => { @@ -33,6 +35,7 @@ describe('Start Task', () => { const startTask = new StartTasksCloudPage(); const peopleCloudComponent = new PeopleCloudComponentPage(); const standaloneTaskName = StringUtil.generateRandomString(5); + const reassignTaskName = StringUtil.generateRandomString(5); const unassignedTaskName = StringUtil.generateRandomString(5); const taskName255Characters = StringUtil.generateRandomString(255); const taskNameBiggerThen255Characters = StringUtil.generateRandomString(256); @@ -41,14 +44,36 @@ describe('Start Task', () => { const dateValidationError = 'Date format DD/MM/YYYY'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const appName = 'simple-app'; - let silentLogin; + let silentLogin, activitiUser; + let tasksService: TasksService; + let identityService: IdentityService; + + beforeAll(async(done) => { + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + identityService = new IdentityService(apiService); + tasksService = new TasksService(apiService); + activitiUser = await identityService.createIdentityUser(); - beforeAll((done) => { silentLogin = false; settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); loginSSOPage.clickOnSSOButton(); browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); + done(); + }); + + afterAll(async (done) => { + const tasks = [ standaloneTaskName, unassignedTaskName, reassignTaskName ]; + for (let i = 0; i < tasks.length; i++) { + const taskId = await tasksService.getTaskId(tasks[i], appName); + await tasksService.deleteTask(taskId, appName); + } + await identityService.deleteIdentityUser(activitiUser.idIdentityService); + done(); + }); + + beforeEach((done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); appListCloudComponent.checkAppIsDisplayed(appName); @@ -109,7 +134,7 @@ describe('Start Task', () => { tasksCloudDemoPage.openNewTaskForm(); startTask.checkFormIsDisplayed(); startTask.addName(standaloneTaskName); - peopleCloudComponent.searchAssigneeAndSelect('Super Admin'); + peopleCloudComponent.searchAssigneeAndSelect(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); startTask.checkStartButtonIsEnabled(); startTask.clickStartButton(); tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); @@ -139,6 +164,24 @@ describe('Start Task', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(unassignedTaskName); }); + it('[C305050] Should be able to reassign the removed user when starting a new task', () => { + + tasksCloudDemoPage.openNewTaskForm(); + startTask.checkFormIsDisplayed(); + startTask.addName(reassignTaskName); + expect(peopleCloudComponent.getAssignee()).toBe('Administrator ADF'); + startTask.clearField(peopleCloudComponent.peopleCloudSearch); + peopleCloudComponent.searchAssignee(user); + peopleCloudComponent.checkUserIsDisplayed('Administrator ADF'); + peopleCloudComponent.selectAssigneeFromList('Administrator ADF'); + startTask.clickStartButton(); + tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(reassignTaskName); + tasksCloudDemoPage.taskListCloudComponent().selectRow(reassignTaskName); + expect(taskHeaderCloudPage.getAssignee()).toBe('admin.adf'); + }); + it('[C297675] Should create a task unassigned when assignee field is empty in Start Task form', () => { tasksCloudDemoPage.openNewTaskForm(); diff --git a/lib/testing/src/lib/core/actions/identity/tasks.service.ts b/lib/testing/src/lib/core/actions/identity/tasks.service.ts index d0d726da5c..e399f92f9a 100644 --- a/lib/testing/src/lib/core/actions/identity/tasks.service.ts +++ b/lib/testing/src/lib/core/actions/identity/tasks.service.ts @@ -86,6 +86,16 @@ export class TasksService { return data; } + async getTaskId(taskName, appName) { + const path = '/' + appName + '/query/v1/tasks'; + const method = 'GET'; + + const queryParams = {name: taskName}, postBody = {}; + + const data = await this.api.performBpmOperation(path, method, queryParams, postBody); + return data.list.entries[0].entry.id; + } + async createStandaloneSubtask(parentTaskId, appName, name) { const path = '/' + appName + '/rb/v1/tasks'; const method = 'POST'; From 0915343222cbc8cc48acc0459f5da3e084deed39 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Fri, 12 Apr 2019 09:28:32 +0100 Subject: [PATCH 101/208] [ADF-4311] - ProcessCloud - Incorrect label loaded for unclaim option -> "Resqueue" should be "Release" (#4588) * C307032 automated * defined a new TaskDetailsCloudDemoPage under Demo-Shell, as it's not part of a component. --- .../taskDetailsCloudDemoPage.ts | 35 +++++++++++++++++++ .../start-task-custom-app-cloud.e2e.ts | 4 ++- .../task-header-cloud.e2e.ts | 8 +++++ .../pages/task-header-cloud-component.page.ts | 6 ---- 4 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts diff --git a/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts new file mode 100644 index 0000000000..0fa41b9f3e --- /dev/null +++ b/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts @@ -0,0 +1,35 @@ +/*! + * @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 { BrowserVisibility } from '@alfresco/adf-testing'; +import { element, by } from 'protractor'; + +export class TaskDetailsCloudDemoPage { + + taskDetailsHeader = element(by.css(`h4[data-automation-id='task-details-header']`)); + releaseButton = element(by.css('button[adf-cloud-unclaim-task]')); + + getTaskDetailsHeader() { + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsHeader); + return this.taskDetailsHeader.getText(); + } + + getReleaseButtonText() { + BrowserVisibility.waitUntilElementIsVisible(this.releaseButton); + return this.releaseButton.getText(); + } +} diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 22c85059f0..4ec50ac6dc 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -23,6 +23,7 @@ import { StartTasksCloudPage, PeopleCloudComponentPage, TasksService, ApiService, IdentityService } from '@alfresco/adf-testing'; import { browser } from 'protractor'; +import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; describe('Start Task', () => { @@ -34,6 +35,7 @@ describe('Start Task', () => { const tasksCloudDemoPage = new TasksCloudDemoPage(); const startTask = new StartTasksCloudPage(); const peopleCloudComponent = new PeopleCloudComponentPage(); + const taskDetailsCloudDemoPage = new TaskDetailsCloudDemoPage(); const standaloneTaskName = StringUtil.generateRandomString(5); const reassignTaskName = StringUtil.generateRandomString(5); const unassignedTaskName = StringUtil.generateRandomString(5); @@ -197,7 +199,7 @@ describe('Start Task', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(unassignedTaskName); const taskId = tasksCloudDemoPage.taskListCloudComponent().getIdCellValue(unassignedTaskName); tasksCloudDemoPage.taskListCloudComponent().selectRow(unassignedTaskName); - expect(taskHeaderCloudPage.getTaskDetailsHeader()).toContain(taskId); + expect(taskDetailsCloudDemoPage.getTaskDetailsHeader()).toContain(taskId); expect(taskHeaderCloudPage.getAssignee()).toBe('No assignee'); }); diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index e519ff0119..996ca06e90 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -24,6 +24,7 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { LoginSSOPage, SettingsPage, AppListCloudPage, TaskHeaderCloudPage, TasksService } from '@alfresco/adf-testing'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { browser } from 'protractor'; +import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; describe('Task Header cloud component', () => { @@ -40,6 +41,7 @@ describe('Task Header cloud component', () => { const navigationBarPage = new NavigationBarPage(); const appListCloudComponent = new AppListCloudPage(); const tasksCloudDemoPage = new TasksCloudDemoPage(); + const taskDetailsCloudDemoPage = new TaskDetailsCloudDemoPage(); let tasksService: TasksService; let silentLogin; @@ -143,4 +145,10 @@ describe('Task Header cloud component', () => { .toEqual(subTask.entry.parentTaskId === null ? '' : subTask.entry.parentTaskId); }); + it('[C307032] Should display the appropriate title for the unclaim option of a Task', async () => { + tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(basicCreatedTaskName); + tasksCloudDemoPage.taskListCloudComponent().selectRow(basicCreatedTaskName); + expect(taskDetailsCloudDemoPage.getReleaseButtonText()).toBe('Release'); + }); }); diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts index de3a940e0d..34b935ed6e 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts @@ -31,7 +31,6 @@ export class TaskHeaderCloudPage { endDateField = element.all(by.css('span[data-automation-id*="endDate"] span')).first(); idField = element.all(by.css('span[data-automation-id*="id"] span')).first(); descriptionField = element(by.css('span[data-automation-id*="description"] span')); - taskDetailsHeader = element(by.css(`h4[data-automation-id='task-details-header']`)); taskPropertyList = element(by.css('adf-cloud-task-header adf-card-view div[class="adf-property-list"]')); getAssignee() { @@ -89,9 +88,4 @@ export class TaskHeaderCloudPage { return this.dueDateField.getText(); } - getTaskDetailsHeader() { - BrowserVisibility.waitUntilElementIsVisible(this.taskPropertyList); - return this.taskDetailsHeader.getText(); - } - } From 5c345c56bcf3ba7d0e4a19fefcb371f3041c9a52 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 12 Apr 2019 10:16:28 +0100 Subject: [PATCH 102/208] [no-issue] ban env (#4595) * ban env * ban env * Update protractor.conf.js * Update test-e2e-lib.sh --- e2e/core/settings-component.e2e.ts | 8 ++++---- scripts/lint.sh | 14 ++++++++++++++ scripts/next_version.sh | 1 - 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/e2e/core/settings-component.e2e.ts b/e2e/core/settings-component.e2e.ts index ce8c5e5b91..7f0f781371 100644 --- a/e2e/core/settings-component.e2e.ts +++ b/e2e/core/settings-component.e2e.ts @@ -51,23 +51,23 @@ describe('Settings component', () => { it('[C291946] Should not save BPM Settings changes when User clicks Back button', () => { settingsPage.setProvider(settingsPage.getBpmOption(), 'BPM'); - settingsPage.setProcessServicesURL('http://adfdev.envalfresco1.com'); + settingsPage.setProcessServicesURL('http://myenvUrl.co.uk'); settingsPage.clickBackButton(); loginPage.waitForElements(); settingsPage.goToSettingsPage(); expect(settingsPage.getSelectedOptionText()).not.toEqual('BPM', 'The Settings changes are saved'); - expect(settingsPage.getBpmHostUrl()).not.toEqual('http://adfdev.envalfresco1.com', 'The Settings changes are saved'); + expect(settingsPage.getBpmHostUrl()).not.toEqual('http://myenvUrl.co.uk', 'The Settings changes are saved'); }); it('[C291947] Should not save ECM Settings changes when User clicks Back button', () => { settingsPage.setProvider(settingsPage.getEcmOption(), 'ECM'); - settingsPage.setContentServicesURL('http://adfdev.envalfresco1.com'); + settingsPage.setContentServicesURL('http://myenvUrl.co.uk'); settingsPage.clickBackButton(); loginPage.waitForElements(); settingsPage.goToSettingsPage(); expect(settingsPage.getSelectedOptionText()).not.toEqual('ECM', 'The Settings changes are saved'); - expect(settingsPage.getBpmHostUrl()).not.toEqual('http://adfdev.envalfresco1.com', 'The Settings changes are saved'); + expect(settingsPage.getBpmHostUrl()).not.toEqual('http://myenvUrl.co.uk', 'The Settings changes are saved'); }); diff --git a/scripts/lint.sh b/scripts/lint.sh index 4dcb840706..33cdbc92bf 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -1,5 +1,12 @@ #!/usr/bin/env bash + +show_help() { + echo "Usage: ./scripts/lint.sh -ban word_to_ban" + echo "" + echo "-ban (optional)" +} + DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$DIR/../" @@ -22,3 +29,10 @@ npm run spellcheck || exit 1 echo "====== styleLint =====" npm run stylelint || exit 1 + +echo "====== exclude-word =====" + +if grep "envalfresco" . -R --exclude-dir={node_modules,.history,.idea,scripts}; then + echo not permitted word + exit 1 +fi diff --git a/scripts/next_version.sh b/scripts/next_version.sh index d84ae9f89c..64ad3957c4 100755 --- a/scripts/next_version.sh +++ b/scripts/next_version.sh @@ -111,7 +111,6 @@ then do :; done NEXT_VERSION=${NEXT_VERSION}-beta${NEXT_BETA_VERSION[1]} - fi echo $NEXT_VERSION From 6ad63055b35b43eb305359b6f47851facd672476 Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Fri, 12 Apr 2019 12:03:45 +0100 Subject: [PATCH 103/208] [ADF-4260] Re-adding upgrade guide 3.0 -> 3.1 (#4597) --- docs/upgrade-guide/upgrade30-31.md | 76 ++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/upgrade-guide/upgrade30-31.md diff --git a/docs/upgrade-guide/upgrade30-31.md b/docs/upgrade-guide/upgrade30-31.md new file mode 100644 index 0000000000..debe341cf3 --- /dev/null +++ b/docs/upgrade-guide/upgrade30-31.md @@ -0,0 +1,76 @@ +--- +Title: Upgrading from ADF v3.0 to v3.1 +--- + +# Upgrading from ADF v3.0 to v3.1 + +This guide explains how to upgrade your ADF v3.0 project to work with v3.1. + +**Note:** the steps described below might involve making changes +to your code. If you are working with a versioning system then you should +commit any changes you are currently working on. If you aren't using versioning +then be sure to make a backup copy of your project before going ahead with the +upgrade. + +## Library updates + +### Automatic update using the Yeoman Generator + +If your application has few changes from the original app created by the +[Yeoman generator](https://github.com/Alfresco/generator-ng2-alfresco-app) +then you may be able to update your project with the following steps: + +1. Update the Yeoman generator to the latest version (3.1.0). Note that + you might need to run these commands with `sudo` on Linux or MacOS: + + ```sh + npm uninstall -g generator-alfresco-adf-app + npm install -g generator-alfresco-adf-app + ``` + +2. Run the new yeoman app generator: + + ```sh + yo alfresco-adf-app + ``` + +3. Clean your old distribution and dependencies by deleting the `node_modules` folder + and the `package-lock.json` file. + +4. Install the dependencies: + ```sh + npm install + ``` + +At this point, the generator might have overwritten some of your code where it differs from +the original generated app. Be sure to check for any differences from your project code +(using a versioning system might make this easier) and if there are any differences, +retrofit your changes. When you have done this, you should be able to start the application +as usual: + +```sh +npm run start +``` + +After starting the app, if everything is working fine, that's all and you don't need to do anything else. However, if things don't work as they should then recover the original version of the project and try the manual approach. + +### Manual update + +1. Update the `package.json` file with the latest library versions: + ```json + "dependencies": { + ... + "@alfresco/adf-core": "3.1.0", + "@alfresco/adf-content-services": "3.1.0", + "@alfresco/adf-process-services-cloud": "3.1.0", + "@alfresco/adf-insights": "3.1.0", + "@alfresco/js-api": "3.1.0", + ... + ``` + +2. Clean your old distribution and dependencies by deleting `node_modules` and `package-lock.json`. + +3. Reinstall your dependencies + ```sh + npm install + ``` \ No newline at end of file From dac3bed09f5e8235868555c24102f91dcae9c6e1 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 12 Apr 2019 12:47:14 +0100 Subject: [PATCH 104/208] protractor option disable controlflow (#4598) --- e2e/proxy.ts | 3 ++- protractor.conf.js | 7 +++++-- scripts/test-e2e-lib.sh | 9 +++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/e2e/proxy.ts b/e2e/proxy.ts index ec533eda52..6f2a2b71b1 100644 --- a/e2e/proxy.ts +++ b/e2e/proxy.ts @@ -18,7 +18,8 @@ import { browser } from 'protractor'; export async function setConfigField(field: string, value: string) { + return browser.executeScript( - `window.adf.setConfigField('${field}', '${value}');` + "window.adf.setConfigField(`"+field + "`, `" + value + "`);" ); } diff --git a/protractor.conf.js b/protractor.conf.js index 7ddc2d8454..f241692646 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -22,6 +22,7 @@ let BROWSER_RUN = process.env.BROWSER_RUN; let FOLDER = process.env.FOLDER || ''; let SELENIUM_SERVER = process.env.SELENIUM_SERVER || ''; let DIRECT_CONNECCT = SELENIUM_SERVER ? false : true; +let SELENIUM_PROMISE_MANAGER = parseInt(process.env.SELENIUM_PROMISE_MANAGER); let MAXINSTANCES = process.env.MAXINSTANCES || 1; let TIMEOUT = parseInt(process.env.TIMEOUT, 10); let SAVE_SCREENSHOT = (process.env.SAVE_SCREENSHOT == 'true'); @@ -199,6 +200,8 @@ exports.config = { */ seleniumAddress: SELENIUM_SERVER, + SELENIUM_PROMISE_MANAGER: SELENIUM_PROMISE_MANAGER, + plugins: [{ package: 'jasmine2-protractor-utils', disableScreenshot: false, @@ -213,6 +216,7 @@ exports.config = { }, onPrepare() { + retry.onPrepare(); global.TestConfig = TestConfig; @@ -269,12 +273,11 @@ exports.config = { fs.exists(reportsFolder, function (exists, error) { if (exists) { rimraf(reportsFolder, function (err) { - console.log('[ERROR] rimraf: ', err); }); } if (error) { - console.log('[ERROR] fs', error); + console.error('[ERROR] fs', error); } }); }, diff --git a/scripts/test-e2e-lib.sh b/scripts/test-e2e-lib.sh index e8b5af9195..88f4c6c9ae 100755 --- a/scripts/test-e2e-lib.sh +++ b/scripts/test-e2e-lib.sh @@ -8,6 +8,7 @@ EXECLINT=true LITESERVER=false EXEC_VERSION_JSAPI=false TIMEOUT=7000 +SELENIUM_PROMISE_MANAGER=1 show_help() { echo "Usage: ./scripts/test-e2e-lib.sh -host adf.domain.com -u admin -p admin -e admin" @@ -29,6 +30,7 @@ show_help() { echo "-timeout or --timeout override the timeout foe the wait utils" echo "-sl --skip-lint skip lint" echo "-m --maxInstances max instances parallel for tests" + echo "-disable-control-flow disable control flow" echo "-vjsapi install different version from npm of JS-API defined in the package.json" echo "-h or --help" } @@ -104,6 +106,11 @@ max_instances(){ MAXINSTANCES=$1 } +disable_control_flow(){ + echo "====== disable control flow =====" + SELENIUM_PROMISE_MANAGER=0 +} + version_js_api() { JSAPI_VERSION=$1 @@ -138,6 +145,7 @@ while [[ $1 == -* ]]; do -sl|--skip-lint) skip_lint; shift;; -m|--maxInstances) max_instances $2; shift 2;; -vjsapi) version_js_api $2; shift 2;; + -disable-control-flow|--disable-control-flow) disable_control_flow; shift;; -*) echo "invalid option: $1" 1>&2; show_help; exit 1;; esac done @@ -160,6 +168,7 @@ export FOLDER=$FOLDER'/' export SELENIUM_SERVER=$SELENIUM_SERVER export NAME_TEST=$NAME_TEST export MAXINSTANCES=$MAXINSTANCES +export SELENIUM_PROMISE_MANAGER=$SELENIUM_PROMISE_MANAGER if $EXEC_VERSION_JSAPI == true; then From 338b208a731f6094b086545ec3b6464e6d4da914 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Fri, 12 Apr 2019 12:49:00 +0100 Subject: [PATCH 105/208] fix dearch test --- e2e/pages/adf/searchResultsPage.ts | 10 ---- .../components/search-sorting-picker.e2e.ts | 58 +++++++++++++------ 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/e2e/pages/adf/searchResultsPage.ts b/e2e/pages/adf/searchResultsPage.ts index 93c01bef87..846876a027 100644 --- a/e2e/pages/adf/searchResultsPage.ts +++ b/e2e/pages/adf/searchResultsPage.ts @@ -119,14 +119,4 @@ export class SearchResultsPage { return this.contentServices.checkElementsSortedDesc(authorList); } - async checkListIsOrderedBySizeAsc() { - const list = await this.contentServices.getElementsDisplayedSize(); - return this.contentServices.checkElementsSortedAsc(list); - } - - async checkListIsOrderedBySizeDesc() { - const list = await this.contentServices.getElementsDisplayedSize(); - return this.contentServices.checkElementsSortedDesc(list); - } - } diff --git a/e2e/search/components/search-sorting-picker.e2e.ts b/e2e/search/components/search-sorting-picker.e2e.ts index 42b21caedb..0d2bcf9332 100644 --- a/e2e/search/components/search-sorting-picker.e2e.ts +++ b/e2e/search/components/search-sorting-picker.e2e.ts @@ -118,7 +118,13 @@ describe('Search Sorting Picker', () => { navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); configEditor.clickClearButton(); - jsonFile.sorting.options.push({ 'key': 'Modifier', 'label': 'Modifier', 'type': 'FIELD', 'field': 'cm:modifier', 'ascending': true }); + jsonFile.sorting.options.push({ + 'key': 'Modifier', + 'label': 'Modifier', + 'type': 'FIELD', + 'field': 'cm:modifier', + 'ascending': true + }); configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); configEditor.clickSaveButton(); @@ -159,7 +165,13 @@ describe('Search Sorting Picker', () => { configEditor.clickSearchConfiguration(); configEditor.clickClearButton(); jsonFile.sorting.options[0].ascending = false; - jsonFile.sorting.defaults[0] = { 'key': 'Size', 'label': 'Size', 'type': 'FIELD', 'field': 'content.size', 'ascending': true }; + jsonFile.sorting.defaults[0] = { + 'key': 'Size', + 'label': 'Size', + 'type': 'FIELD', + 'field': 'content.size', + 'ascending': true + }; configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); configEditor.clickSaveButton(); @@ -201,7 +213,7 @@ describe('Search Sorting Picker', () => { it('[C277286] Should be able to sort the search results by "Created Date" ASC', () => { searchResults.sortByCreated(true); browser.controlFlow().execute(async () => { - const results = await searchResults. dataTable.geCellElementDetail('Created'); + const results = await searchResults.dataTable.geCellElementDetail('Created'); expect(contentServices.checkElementsDateSortedAsc(results)).toBe(true); }); }); @@ -209,7 +221,7 @@ describe('Search Sorting Picker', () => { it('[C277287] Should be able to sort the search results by "Created Date" DESC', () => { searchResults.sortByCreated(false); browser.controlFlow().execute(async () => { - const results = await searchResults. dataTable.geCellElementDetail('Created'); + const results = await searchResults.dataTable.geCellElementDetail('Created'); expect(contentServices.checkElementsDateSortedDesc(results)).toBe(true); }); }); @@ -220,7 +232,13 @@ describe('Search Sorting Picker', () => { navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); configEditor.clickClearButton(); - jsonFile.sorting.options.push({ 'key': 'Modified Date', 'label': 'Modified Date', 'type': 'FIELD', 'field': 'cm:modified', 'ascending': true }); + jsonFile.sorting.options.push({ + 'key': 'Modified Date', + 'label': 'Modified Date', + 'type': 'FIELD', + 'field': 'cm:modified', + 'ascending': true + }); configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); configEditor.clickSaveButton(); @@ -244,23 +262,19 @@ describe('Search Sorting Picker', () => { }); }); - it('[C277290] Should be able to sort the search results by "Size" ASC', () => { - searchResults.sortBySize(true); - expect(searchResults.checkListIsOrderedBySizeAsc()).toBe(true); - }); - - it('[C277291] Should be able to sort the search results by "Size" DESC', () => { - searchResults.sortBySize(false); - expect(searchResults.checkListIsOrderedBySizeDesc()).toBe(true); - }); - it('[C277301] Should be able to change default sorting option for the search results', () => { const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); navigationBar.clickConfigEditorButton(); configEditor.clickSearchConfiguration(); configEditor.clickClearButton(); - jsonFile.sorting.defaults[0] = { 'key': 'Size', 'label': 'Size', 'type': 'FIELD', 'field': 'content.size', 'ascending': true }; + jsonFile.sorting.options.push({ + 'key': 'Modified Date', + 'label': 'Modified Date', + 'type': 'FIELD', + 'field': 'cm:modified', + 'ascending': true + }); configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); configEditor.clickSaveButton(); @@ -269,6 +283,16 @@ describe('Search Sorting Picker', () => { .enterTextAndPressEnter(search); searchSortingPicker.checkSortingSelectorIsDisplayed(); - expect(searchResults.checkListIsOrderedBySizeAsc()).toBe(true); + browser.controlFlow().execute(async () => { + const idList = await contentServices.getElementsDisplayedId(); + const numberOfElements = await contentServices.numberOfResultsDisplayed(); + + const nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements); + const modifiedDateList = []; + for (let i = 0; i < nodeList.length; i++) { + modifiedDateList.push(new Date(nodeList[i].entry.modifiedAt)); + } + expect(contentServices.checkElementsDateSortedAsc(modifiedDateList)).toBe(true); + }); }); }); From 16aaa0f0b37ff4d70872a4bc70985c8b9932db5a Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Fri, 12 Apr 2019 15:59:14 +0300 Subject: [PATCH 106/208] [ADF-4393] TaskHeaderCloud - remove readOnly property (#4599) --- .../cloud/task-details-cloud-demo.component.html | 7 +++---- .../cloud/task-details-cloud-demo.component.ts | 1 - .../components/task-header-cloud.component.md | 1 - .../components/task-header-cloud.component.ts | 14 +++----------- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html index b155b15ecf..c8faa507d2 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html @@ -7,10 +7,10 @@ <button mat-button (click)="goBack()">Cancel</button> <button mat-button color="primary" *ngIf="canCompleteTask()" adf-cloud-complete-task (success)="onCompletedTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button> - + <button mat-button color="primary" *ngIf="canClaimTask()" adf-cloud-claim-task (success)="onClaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.CLAIM' | translate }}</button> - + <button mat-button color="primary" *ngIf="canUnClaimTask()" adf-cloud-unclaim-task (success)="onUnclaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.UNCLAIM' | translate }}</button> </div> @@ -23,8 +23,7 @@ </div> <adf-cloud-task-header fxFlex [appName]="appName" - [taskId]="taskId" - [readOnly]="readOnly"> + [taskId]="taskId"> </adf-cloud-task-header> </div> </div> diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts index 95518ed986..37a78e7798 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts @@ -29,7 +29,6 @@ export class TaskDetailsCloudDemoComponent implements OnInit { taskDetails: TaskDetailsCloudModel; taskId: string; appName: string; - readOnly = false; constructor( private route: ActivatedRoute, diff --git a/docs/process-services-cloud/components/task-header-cloud.component.md b/docs/process-services-cloud/components/task-header-cloud.component.md index fa3ae215c9..22566c42b3 100644 --- a/docs/process-services-cloud/components/task-header-cloud.component.md +++ b/docs/process-services-cloud/components/task-header-cloud.component.md @@ -27,7 +27,6 @@ Shows all the information related to a task. | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | | appName | `string` | | (Required) The name of the application. | -| readOnly | `boolean` | false | Toggles Read Only Mode. This disables click selection and editing for all cells. | | taskId | `string` | | (Required) The id of the task. | ### Events diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index af9c24e2bf..04e050a555 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -45,10 +45,6 @@ export class TaskHeaderCloudComponent implements OnInit { @Input() taskId: string; - /** Toggles Read Only Mode. This disables click selection and editing for all cells. */ - @Input() - readOnly: boolean = false; - /** Emitted when the task is claimed. */ @Output() claim: EventEmitter<any> = new EventEmitter<any>(); @@ -113,7 +109,7 @@ export class TaskHeaderCloudComponent implements OnInit { label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.PRIORITY', value: this.taskDetails.priority, key: 'priority', - editable: this.isReadOnlyMode() + editable: true } ), new CardViewDateItemModel( @@ -123,7 +119,7 @@ export class TaskHeaderCloudComponent implements OnInit { key: 'dueDate', format: 'DD-MM-YYYY', default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DUE_DATE_DEFAULT'), - editable: this.isReadOnlyMode() + editable: true } ), new CardViewTextItemModel( @@ -179,7 +175,7 @@ export class TaskHeaderCloudComponent implements OnInit { key: 'description', default: this.translationService.instant('ADF_CLOUD_TASK_HEADER.PROPERTIES.DESCRIPTION_DEFAULT'), multiline: true, - editable: this.isReadOnlyMode() + editable: true } ) ]; @@ -237,10 +233,6 @@ export class TaskHeaderCloudComponent implements OnInit { return this.taskDetails.assignee !== undefined; } - isReadOnlyMode() { - return !this.readOnly; - } - private isValidSelection(filteredProperties: string[], cardItem: CardViewBaseItemModel): boolean { return filteredProperties ? filteredProperties.indexOf(cardItem.key) >= 0 : true; } From 921fdc00df39b1953e263d4e4511e8b1d2b0bdda Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Fri, 12 Apr 2019 16:18:43 +0100 Subject: [PATCH 107/208] [ADF-4391] Doc review for 3.2 (#4601) * [ADF-4391] Reviewed new clipboard class docs * [ADF-4391] Reviewed new proc cloud class docs * [ADF-4391] Reviewed new datatable doc additions --- docs/README.md | 9 +- docs/core/components/data-column.component.md | 34 ++++++- docs/core/components/datatable.component.md | 30 +----- docs/core/components/json-cell.component.md | 23 +++-- docs/core/directives/clipboard.directive.md | 23 +++-- docs/core/services/clipboard.service.md | 38 ++++++++ .../claim-task.directive.md | 26 ------ .../components/form-cloud.component.md | 30 +++--- .../services/form-cloud.service.md | 93 +++++++++++-------- .../unclaim-tas.directie.md | 26 ------ lib/core/clipboard/clipboard.directive.ts | 3 + lib/core/clipboard/clipboard.service.ts | 15 +++ lib/core/data-column/data-column.component.ts | 4 +- .../datatable/datatable-cell.component.ts | 5 + .../lib/form/services/form-cloud.service.ts | 48 ++++++++++ tools/doc/doctool.config.json | 2 + 16 files changed, 256 insertions(+), 153 deletions(-) create mode 100644 docs/core/services/clipboard.service.md delete mode 100644 docs/process-services-cloud/claim-task.directive.md delete mode 100644 docs/process-services-cloud/unclaim-tas.directie.md diff --git a/docs/README.md b/docs/README.md index a772af2d7d..70328cf129 100644 --- a/docs/README.md +++ b/docs/README.md @@ -91,7 +91,6 @@ for more information about installing and using the source code. | [Error Content Component](core/components/error-content.component.md) | Displays info about a specific error. | [Source](../lib/core/templates/error-content/error-content.component.ts) | | [Form field component](core/components/form-field.component.md) | Represents a UI field in a form. | [Source](../lib/core/form/components/form-field/form-field.component.ts) | | [Form List Component](core/components/form-list.component.md) | Shows forms as a list. | [Source](../lib/core/form/components/form-list.component.ts) | -| [Form component](core/components/form.component.md) | Shows a Form from APS | [Source](../lib/core/form/components/form.component.ts) | | [Header component](core/components/header.component.md) | Reusable header for Alfresco applications. | [Source](../lib/core/layout/components/header/header.component.ts) | | [Host settings component](core/components/host-settings.component.md) ![Internal](docassets/images/InternalIcon.png) | Validates the URLs for ACS and APS and saves them in the user's local storage | [Source](../lib/core/settings/host-settings.component.ts) | | [Icon Component](core/components/icon.component.md) | Provides a universal way of rendering registered and named icons. | [Source](../lib/core/icon/icon.component.ts) | @@ -99,6 +98,7 @@ for more information about installing and using the source code. | [Info drawer layout component](core/components/info-drawer-layout.component.md) | Displays a sidebar-style information panel. | [Source](../lib/core/info-drawer/info-drawer-layout.component.ts) | | [Info Drawer Tab component](core/components/info-drawer-tab.component.md) | Renders tabs in a Info drawer component. | [Source](../lib/core/info-drawer/info-drawer.component.ts) | | [Info Drawer component](core/components/info-drawer.component.md) | Displays a sidebar-style information panel with tabs. | [Source](../lib/core/info-drawer/info-drawer.component.ts) | +| [JsonCell component](core/components/json-cell.component.md) | Show Json formated value inside datatable component. | [Source](../lib/core/datatable/components/datatable/json-cell.component.ts) | | [Language Menu component](core/components/language-menu.component.md) | Displays all the languages that are present in "app.config.json" and the default (EN). | [Source](../lib/core/language-menu/language-menu.component.ts) | | [Login Dialog Panel component](core/components/login-dialog-panel.component.md) | Shows and manages a login dialog. | [Source](../lib/core/login/components/login-dialog-panel.component.ts) | | [Login Dialog component](core/components/login-dialog.component.md) | Allows a user to perform a login via a dialog. | [Source](../lib/core/login/components/login-dialog.component.ts) | @@ -107,7 +107,7 @@ for more information about installing and using the source code. | [Sidebar action menu component](core/components/sidebar-action-menu.component.md) | Displays a sidebar-action menu information panel. | [Source](../lib/core/layout/components/sidebar-action/sidebar-action-menu.component.ts) | | [Sidenav Layout component](core/components/sidenav-layout.component.md) | Displays the standard three-region ADF application layout. | [Source](../lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts) | | [Sorting Picker Component](core/components/sorting-picker.component.md) | Selects from a set of predefined sorting definitions and directions. | [Source](../lib/core/sorting-picker/sorting-picker.component.ts) | -| [Start Form component](core/components/start-form.component.md) | Displays the Start Form for a process. | [Source](../lib/core/form/components/start-form.component.ts) | +| [Start Form component](core/components/start-form.component.md) | Displays the Start Form for a process. | [Source](../lib/process-services/form/start-form.component.ts) | | [Text Mask directive](core/components/text-mask.component.md) | Implements text field input masks. | [Source](../lib/core/form/components/widgets/text/text-mask.component.ts) | | [Toolbar Divider Component](core/components/toolbar-divider.component.md) | Divides groups of elements in a Toolbar with a visual separator. | [Source](../lib/core/toolbar/toolbar-divider.component.ts) | | [Toolbar Title Component](core/components/toolbar-title.component.md) | Supplies custom HTML to be included in a Toolbar component title. | [Source](../lib/core/toolbar/toolbar-title.component.ts) | @@ -120,6 +120,7 @@ for more information about installing and using the source code. | Name | Description | Source link | | ---- | ----------- | ----------- | | [Check Allowable Operation directive](core/directives/check-allowable-operation.directive.md) | Selectively disables an HTML element or Angular component. | [Source](../lib/core/directives/check-allowable-operation.directive.ts) | +| [Clipboard directive](core/directives/clipboard.directive.md) | Copies text to the clipboard. | [Source](../lib/core/clipboard/clipboard.directive.ts) | | [Context Menu directive](core/directives/context-menu.directive.md) | Adds a context menu to a component. | [Source](../lib/core/context-menu/context-menu.directive.ts) | | [Highlight directive](core/directives/highlight.directive.md) | Adds highlighting to selected sections of an HTML element's content. | [Source](../lib/core/directives/highlight.directive.ts) | | [Logout directive](core/directives/logout.directive.md) | Logs the user out when the decorated element is clicked. | [Source](../lib/core/directives/logout.directive.ts) | @@ -178,6 +179,7 @@ for more information about installing and using the source code. | [Bpm User service](core/services/bpm-user.service.md) | Gets information about the current Process Services user. | [Source](../lib/core/userinfo/services/bpm-user.service.ts) | | [Card Item Type service](core/services/card-item-types.service.md) | Maps type names to field component types for the Card View component. | [Source](../lib/core/card-view/services/card-item-types.service.ts) | | [Card View Update service](core/services/card-view-update.service.md) | Reports edits and clicks within fields of a Card View component. | [Source](../lib/core/card-view/services/card-view-update.service.ts) | +| [Clipboard service](core/services/clipboard.service.md) | Copies text to the clipboard. | [Source](../lib/core/clipboard/clipboard.service.ts) | | [Comment Content service](core/services/comment-content.service.md) | Adds and retrieves comments for nodes in Content Services. | [Source](../lib/core/services/comment-content.service.ts) | | [Comment Process service](core/services/comment-process.service.md) | Adds and retrieves comments for task and process instances in Process Services. | [Source](../lib/core/services/comment-process.service.ts) | | [Content service](core/services/content.service.md) | Accesses app-generated data objects via URLs and file downloads. | [Source](../lib/core/services/content.service.ts) | @@ -348,6 +350,7 @@ for more information about installing and using the source code. | [Checklist Component](process-services/components/checklist.component.md) | Shows the checklist task functionality. | [Source](../lib/process-services/task-list/components/checklist.component.ts) | | [Create Process Attachment component](process-services/components/create-process-attachment.component.md) | Displays an Upload Component (Drag and Click) to upload the attachment to a specified process instance. | [Source](../lib/process-services/attachment/create-process-attachment.component.ts) | | [Create Task Attachment Component](process-services/components/create-task-attachment.component.md) | Displays an Upload Component (Drag and Click) to upload the attachment to a specified task. | [Source](../lib/process-services/attachment/create-task-attachment.component.ts) | +| [Form component](process-services/components/form.component.md) | Shows a Form from APS | [Source](../lib/process-services/form/form.component.ts) | | [People list component](process-services/components/people-list.component.md) | Shows a list of users (people). | [Source](../lib/process-services/people/components/people-list/people-list.component.ts) | | [People Search component](process-services/components/people-search.component.md) | Searches users/people. | [Source](../lib/process-services/people/components/people-search/people-search.component.ts) | | [People Component](process-services/components/people.component.md) | Displays users involved with a specified task | [Source](../lib/process-services/people/components/people/people.component.ts) | @@ -404,6 +407,7 @@ for more information about installing and using the source code. | [App List Cloud Component](process-services-cloud/components/app-list-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Shows all deployed cloud application instances. | [Source](../lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts) | | [Edit Process Filter Cloud component](process-services-cloud/components/edit-process-filter-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Shows/edits process filter details. | [Source](../lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts) | | [Edit Task Filter Cloud component](process-services-cloud/components/edit-task-filter-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Edits task filter details. | [Source](../lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts) | +| [Form cloud component](process-services-cloud/components/form-cloud.component.md) | Shows a form from Process Services. | [Source](../lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts) | | [Group Cloud component](process-services-cloud/components/group-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Searches Groups. | [Source](../lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts) | | [People Cloud Component](process-services-cloud/components/people-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Allows one or more users to be selected (with auto-suggestion) based on the input parameters. | [Source](../lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts) | | [Process Filters Cloud Component](process-services-cloud/components/process-filters-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Lists all available process filters and allows to select a filter. | [Source](../lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.ts) | @@ -434,6 +438,7 @@ for more information about installing and using the source code. | Name | Description | Source link | | ---- | ----------- | ----------- | | [Apps Process Cloud Service](process-services-cloud/services/apps-process-cloud.service.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Gets details of deployed apps for the current user. | [Source](../lib/process-services-cloud/src/lib/app/services/apps-process-cloud.service.ts) | +| [Form cloud service](process-services-cloud/services/form-cloud.service.md) | Implements Process Services form methods | [Source](../lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts) | | [Group Cloud Service](process-services-cloud/services/group-cloud.service.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Searches and gets information for groups. | [Source](../lib/process-services-cloud/src/lib/group/services/group-cloud.service.ts) | | [Process Filter Cloud Service](process-services-cloud/services/process-filter-cloud.service.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Manage Process Filters, which are pre-configured Process Instance queries. | [Source](../lib/process-services-cloud/src/lib/process/process-filters/services/process-filter-cloud.service.ts) | | [Process Header Cloud Service](process-services-cloud/services/process-header-cloud.service.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Manages cloud process instances. | [Source](../lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts) | diff --git a/docs/core/components/data-column.component.md b/docs/core/components/data-column.component.md index e097e5cdc6..e8c197b8dc 100644 --- a/docs/core/components/data-column.component.md +++ b/docs/core/components/data-column.component.md @@ -2,7 +2,7 @@ Title: Data Column Component Added: v2.0.0 Status: Active -Last reviewed: 2018-11-12 +Last reviewed: 2019-04-12 --- # [Data Column Component](../../../lib/core/data-column/data-column.component.ts "Defined in data-column.component.ts") @@ -20,6 +20,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo - [Custom tooltips](#custom-tooltips) - [Column Template](#column-template) - [Styling Techniques](#styling-techniques) + - [Using the `copyContent` option](#using-the-copycontent-option) - [See also](#see-also) ## Basic Usage @@ -42,6 +43,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | +| copyContent | `boolean` | | Enables/disables a [Clipboard directive](../../core/directives/clipboard.directive.md) to allow copying of cell contents. | | cssClass | `string` | | Additional CSS class to be applied to column (header and cells). | | format | `string` | | Value format (if supported by the parent component), for example format of the date. | | formatTooltip | `Function` | | Custom tooltip formatter function. | @@ -49,7 +51,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo | sortable | `boolean` | true | Toggles ability to sort by this column, for example by clicking the column header. | | srTitle | `string` | | Title to be used for screen readers. | | title | `string` | "" | Display title of the column, typically used for column headers. You can use the i18n resource key to get it translated automatically. | -| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'image', 'date', 'fileSize', 'location' and 'json'. | +| type | `string` | "text" | Value type for the column. Possible settings are 'text', 'image', 'date', 'fileSize', 'location', and 'json'. | ## Details @@ -298,6 +300,34 @@ Now you can declare columns and assign the `desktop-only` class where needed: ![Responsive Mobile](../../docassets/images/responsive-mobile.png) +### Using the `copyContent` option + +When the `copyContent` property is true, a +Clipboard directive +is added to each cell in the column. This lets the user copy the cell content +to the clipboard with a mouse click. + +See the [Clipboard Directive](../directives/clipboard.directive.md) page for full details of the directive. + +Example of using `copyContent` from a JSON config file: + +```json +[ + {"type": "text", "key": "id", "title": "Id", "copyContent": "true"}, + {"type": "text", "key": "name", "title": "name"}, +] +``` + +HTML `<data-column>` element example: + +```html +<adf-tasklist ...> + <data-columns> + <data-column [copyContent]="true" key="id" title="Id"></data-column> + ... + </data-columns> +</adf-tasklist> +``` ## See also - [Document list component](../../content-services/components/document-list.component.md) diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 1eff7b0e2c..96d8caacba 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -2,7 +2,7 @@ Title: DataTable component Added: v2.0.0 Status: Active -Last reviewed: 2019-03-20 +Last reviewed: 2019-04-12 --- # [DataTable component](../../../lib/core/datatable/components/datatable/datatable.component.ts "Defined in datatable.component.ts") @@ -311,7 +311,7 @@ together in the same datatable. | ---- | ---- | ------------- | ----------- | | actions | `boolean` | false | Toggles the data actions column. | | actionsPosition | `string` | "right" | Position of the actions dropdown menu. Can be "left" or "right". | -| allowDropFiles | `boolean` | false | Toggles file drop support for rows (see [Upload directive](../directives/upload.directive.md) for further details). | +| allowDropFiles | `boolean` | false | Toggles file drop support for rows (see [Upload directive](upload.directive.md) for further details). | | columns | `any[]` | \[] | The columns that the datatable will show. | | contextMenu | `boolean` | false | Toggles custom context menu for the component. | | data | [`DataTableAdapter`](../../../lib/core/datatable/data/datatable-adapter.ts) | | Data source for the table | @@ -625,7 +625,8 @@ widths according to your needs: #### No-growing cells -As mentioned before, in the beginning, all cells have the same width. You can prevent cells from growing by using the `adf-no-grow-cell` class. +As mentioned before, all cells initially have the same width. You can prevent cells from +growing by using the `adf-no-grow-cell` class. ```js { @@ -636,7 +637,7 @@ As mentioned before, in the beginning, all cells have the same width. You can pr } ``` -Notice that this class is compatible with `adf-ellipsis-cell` and for that reason it has a `min-width` of `100px`. You can override this property in your custom class to better suit your needs. +Note that this class is compatible with `adf-ellipsis-cell` and for that reason it has a `min-width` of `100px`. You can override this property in your custom class to better suit your needs. ![](../../docassets/images/datatable-no-grow-cell.png) @@ -680,27 +681,6 @@ the total height of all rows exceeds the fixed height of the parent element. </div> ``` -### CopyClipboardDirective example - -See the [Copy Content Directive ](../directives/clipboard.directive.md) page for full details of the directive - -Json config file: -```json -[ - {"type": "text", "key": "id", "title": "Id", "copyContent": "true"}, - {"type": "text", "key": "name", "title": "name"}, -] -``` -HTML data-columns -```html -<adf-tasklist ...> - <data-columns> - <data-column [copyContent]="true" key="id" title="Id"></data-column> - <data-column key="created" title="Created" class="hidden"></data-column> - </data-columns> -</adf-tasklist> -``` - Once set up, the sticky header behaves as shown in the image below: ![](../../docassets/images/datatable-sticky-header.png) diff --git a/docs/core/components/json-cell.component.md b/docs/core/components/json-cell.component.md index 6862af1a19..803685a6c7 100644 --- a/docs/core/components/json-cell.component.md +++ b/docs/core/components/json-cell.component.md @@ -1,12 +1,13 @@ --- -Title: JsonCell component -Added: v2.0.0 +Title: Json Cell component +Added: v3.2.0 Status: Active +Last reviewed: 2019-04-12 --- -# [JsonCellComponent](../../../lib/core/datatable/components/datatable/json-cell.component.ts "Defined in empty-list.component.ts") +# [Json Cell Component](../../../lib/core/datatable/components/datatable/json-cell.component.ts "Defined in json-cell.component.ts") -Show Json formated value inside datatable component. +Shows a JSON-formatted value inside a datatable component. ## Basic Usage @@ -18,7 +19,7 @@ Show Json formated value inside datatable component. </adf-datatable> ``` -You can specify the cell inside configuration file +You can specify the cell inside the `app.config.json` file: ```javascript "adf-cloud-process-list": { @@ -40,14 +41,16 @@ You can specify the cell inside configuration file | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| data | [`DataTableAdapter`](../../../lib/core/datatable/data/datatable-adapter.ts) | `null` | Data adapter instance. | -| column | [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts) | `null` | Data that defines the column | -| row | [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts) | | Data that defines the row | - +| column | [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts) | | Data that defines the column. | +| copyContent | `boolean` | | Enables/disables a [Clipboard directive](../../core/directives/clipboard.directive.md) to allow copying of the cell's content. | +| data | [`DataTableAdapter`](../../../lib/core/datatable/data/datatable-adapter.ts) | | Data table adapter instance. | +| row | [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts) | | Data that defines the row. | +| tooltip | `string` | | Text for the cell's tooltip. | ## Details -This component provides a custom display to show a [Datatable component](datatable.component.md) cell +This component provides a custom display to show JSON data in a +[Datatable component](datatable.component.md) cell ## See also diff --git a/docs/core/directives/clipboard.directive.md b/docs/core/directives/clipboard.directive.md index f96560d451..7d586277af 100644 --- a/docs/core/directives/clipboard.directive.md +++ b/docs/core/directives/clipboard.directive.md @@ -1,13 +1,13 @@ --- -Title: Copy Clipboard directive +Title: Clipboard directive Added: v3.2.0 Status: Active -Last reviewed: 2019-04-01 +Last reviewed: 2019-04-12 --- # [Clipboard directive](../../../lib/core/clipboard/clipboard.directive.ts "Defined in clipboard.directive.ts") -Copy text to clipboard +Copies text to the clipboard. ## Basic Usage @@ -21,16 +21,25 @@ Copy text to clipboard </button> ``` - ## Class members ### Properties | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| target | `HTMLElement ref` | false | HTMLElement reference | -| clipboard-notification | `string` | | Translation key message for toast notification | +| adf-clipboard | `string` | | Translation key or message for the tooltip. | +| clipboard-notification | `string` | | Translation key or message for snackbar notification. | +| target | [`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)` \| `[`HTMLTextAreaElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement) | | Reference to the HTML element containing the text to copy. | ## Details -When the user hover the directive element a tooltip will will show up to inform that, when you click on the current element, the content or the reference content will be copied into the clipboard. +Clicking on the decorated element will copy the text content of that element (or the +element specified in the `target` property) to the clipboard. + +Use the parameter to `adf-clipboard` to specify a tooltip message that will be shown when +the user hovers the mouse over the element. You can also provide a snackbar message in the +`clipboard-notification` property, which will appear when the copying is complete. + +## See also + +- [Clipboard service](../../core/services/clipboard.service.md) diff --git a/docs/core/services/clipboard.service.md b/docs/core/services/clipboard.service.md new file mode 100644 index 0000000000..cdea589991 --- /dev/null +++ b/docs/core/services/clipboard.service.md @@ -0,0 +1,38 @@ +--- +Title: Clipboard service +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-12 +--- + +# [Clipboard service](../../../lib/core/clipboard/clipboard.service.ts "Defined in clipboard.service.ts") + +Copies text to the clipboard. + +## Class members + +### Methods + +- **copyContentToClipboard**(content: `string`, message: `string`)<br/> + Copies a text string to the clipboard. + - _content:_ `string` - Text to copy + - _message:_ `string` - Snackbar message to alert when copying happens +- **copyToClipboard**(target: [`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)`|`[`HTMLTextAreaElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement), message?: `string`)<br/> + Copies text from an HTML element to the clipboard. + - _target:_ [`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)`|`[`HTMLTextAreaElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement) - HTML element to be copied + - _message:_ `string` - (Optional) Snackbar message to alert when copying happens +- **isTargetValid**(target: [`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)`|`[`HTMLTextAreaElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement)): `boolean`<br/> + Checks if the target element can have its text copied. + - _target:_ [`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)`|`[`HTMLTextAreaElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement) - Target HTML element + - **Returns** `boolean` - True if the text can be copied, false otherwise + +## Details + +Use `copyContentToClipboard` to copy a text string or `isTargetValid` and +`copyToClipboard` to copy the content of an HTML element in the page. The +`message` parameter specifies a snackbar message to alert the user when the +copying operation takes place. + +## See also + +- [Clipboard directive](../../core/directives/clipboard.directive.md) diff --git a/docs/process-services-cloud/claim-task.directive.md b/docs/process-services-cloud/claim-task.directive.md deleted file mode 100644 index 97ccdd8e80..0000000000 --- a/docs/process-services-cloud/claim-task.directive.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -Title: Claim Task Directive -Added: v3.1.0 -Status: Experimental -Last reviewed: 2019-03-05 ---- - -# [Claim task directive](../../lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts "Defined in claim-task.directive.ts") - -Claim a task - -## Basic Usage - -```html -<button adf-claim-task [appName]="appName" [taskId]="taskId" (success)="onTaskClaimed()">Complete</button> -``` -## Class members - -### Properties - -| Name | Type | Default value | Description | -| ---- | ---- | ------------- | ----------- | -| taskId | `string` | empty |(Required) The id of the task. | -| appName | `string` | empty | (Required) The name of the application. | -| success | `EventEmitter<any>` | empty | Emitted when the task is completed. | -| error | `EventEmitter<any>` | empty | Emitted when the task cannot be completed. | \ No newline at end of file diff --git a/docs/process-services-cloud/components/form-cloud.component.md b/docs/process-services-cloud/components/form-cloud.component.md index 820ce4e62a..039cb58ac9 100644 --- a/docs/process-services-cloud/components/form-cloud.component.md +++ b/docs/process-services-cloud/components/form-cloud.component.md @@ -1,13 +1,13 @@ --- -Title: Form component +Title: Form cloud component Added: v3.2.0 Status: Active -Last reviewed: 2019-04-01 +Last reviewed: 2019-04-12 --- # [Form cloud component](../../../lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts "Defined in form-cloud.component.ts") -Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) from Process Services +Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) from Process Services. ## Contents @@ -53,21 +53,21 @@ The template defined inside `empty-form` will be shown when no form definition i | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | | appName | `string` | | App id to fetch corresponding form and values. | -| taskId | `string` | | Task id to fetch corresponding form and values. | -| form | [`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) | | Underlying [form model](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) instance. | -| formId | `string` | | The id of the form definition to load and display with custom values. | -| data | [`TaskVariableCloud[]`](../../../lib/process-services-cloud/src/lib/form/models/task-variable.model.ts) | | Custom form values map to be used with the rendered form. | +| data | [`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]` | | Custom form values map to be used with the rendered form. | | disableCompleteButton | `boolean` | false | If true then the `Complete` outcome button is shown but it will be disabled. | | disableStartProcessButton | `boolean` | false | If true then the `Start Process` outcome button is shown but it will be disabled. | | fieldValidators | [`FormFieldValidator`](../../../lib/core/form/components/widgets/core/form-field-validator.ts)`[]` | \[] | Contains a list of form field validator instances. | +| form | [`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) | | Underlying [form model](../../../lib/core/form/components/widgets/core/form.model.ts) instance. | +| formId | `string` | | Task id to fetch corresponding form and values. | +| nameNode | `string` | | Name to assign to the new node where the metadata are stored. | +| path | `string` | | Path of the folder where the metadata will be stored. | | readOnly | `boolean` | false | Toggle readonly state of the form. Forces all form widgets to render as readonly if enabled. | | showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | -| showDebugButton | `boolean` | false | Toggle debug options. | | showRefreshButton | `boolean` | true | Toggle rendering of the `Refresh` button. | | showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. | | showTitle | `boolean` | true | Toggle rendering of the form title. | | showValidationIcon | `boolean` | true | Toggle rendering of the validation icon next to the form title. | - +| taskId | `string` | | Task id to fetch corresponding form and values. | ### Events @@ -75,11 +75,11 @@ The template defined inside `empty-form` will be shown when no form definition i | ---- | ---- | ----------- | | error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when any error occurs. | | executeOutcome | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormOutcomeEvent`](../../../lib/core/form/components/widgets/core/form-outcome-event.model.ts)`>` | Emitted when any outcome is executed. Default behaviour can be prevented via `event.preventDefault()`. | -| formCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Complete` outcome. | -| formDataRefreshed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when form values are refreshed due to a data property change. | +| formCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Complete` outcome. | +| formDataRefreshed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when form values are refreshed due to a data property change. | | formError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormFieldModel`](../../core/models/form-field.model.md)`[]>` | Emitted when the supplied form values have a validation error. | -| formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is loaded or reloaded. | -| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloudModel`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Save` or custom outcomes. | +| formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is loaded or reloaded. | +| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Save` or custom outcomes. | ## Details @@ -130,7 +130,6 @@ For an existing Task both the form and its values will be fetched and displayed. In this case, only the form definition will be fetched. - ### Controlling outcome execution behaviour In unusual circumstances, you may need to take complete control of form outcome execution. @@ -252,11 +251,10 @@ In the CSS, you can target any outcome ID and change the style as in this exampl ![](../../docassets/images/form-style-sample.png) - ## See also - [Form Field Validator interface](../../core/interfaces/form-field-validator.interface.md) - [Extensibility](../../user-guide/extensibility.md) - [Form rendering service](../../core/services/form-rendering.service.md) - [Form field model](../../core/models/form-field.model.md) -- [Form service](../services/form-cloud.service.md) +- [Form cloud service](../services/form-cloud.service.md) diff --git a/docs/process-services-cloud/services/form-cloud.service.md b/docs/process-services-cloud/services/form-cloud.service.md index fcb2dab5bd..aeca24c579 100644 --- a/docs/process-services-cloud/services/form-cloud.service.md +++ b/docs/process-services-cloud/services/form-cloud.service.md @@ -2,7 +2,7 @@ Title: Form cloud service Added: v3.2.0 Status: Active -Last reviewed: 2019-04-02 +Last reviewed: 2019-04-12 --- # [Form cloud service](../../../lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts "Defined in form-cloud.service.ts") @@ -12,55 +12,74 @@ Implements Process Services form methods ## Basic Usage ```ts -import { FormService } from '@alfresco/adf-core'; +import { FormCloudService } from '@alfresco/adf-process-services-cloud'; @Component(...) class MyComponent { - constructor(formService: FormService) { + constructor(formCloudService: FormCloudService) {} } ``` +## Class members + ### Methods -- `parseForm(json: any, data?:`[`TaskVariableCloud,`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`readOnly: boolean = false):`[`FormModel`](../../../lib/core/form/components/widgets/core/form.model.ts) - Parses JSON data to create a corresponding [`Form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) model. - - `json` - JSON to create the form - - `data` - (Optional) [`Values`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts) for the form fields - - `readOnly` - Should the form fields be read-only? +- **completeTaskForm**(appName: `string`, taskId: `string`, formId: `string`, formValues: [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts), outcome: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>`<br/> + Completes a task form. + - _appName:_ `string` - Name of the app + - _taskId:_ `string` - ID of the target task + - _formId:_ `string` - ID of the form to complete + - _formValues:_ [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts) - [Form](../../../lib/process-services/task-list/models/form.model.ts) values object + - _outcome:_ `string` - (Optional) [Form](../../../lib/process-services/task-list/models/form.model.ts) outcome + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>` - Updated task details +- **createTemporaryRawRelatedContent**(file: `any`, nodeId: `any`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> -- `saveTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Saves task [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts). - - `appName` - App Name - - `taskId` - Task Id - - `formId` - Form Id - - `formValues` - [`Form Values`](../../../lib/core/form/components/widgets/core/form-values.ts) + - _file:_ `any` - + - _nodeId:_ `any` - + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - -- `completeTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues, outcome: string):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Completes task [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) - - `appName` - App Name - - `taskId` - Task Id - - `formId` - Form Id - - `formValues` - [`Form Values`](../../../lib/core/form/components/widgets/core/form-values.ts) - - `outcome` - (Optional) [`Form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) Outcome +- **getForm**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> + Gets a form definition. + - _appName:_ `string` - Name of the app + - _taskId:_ `string` - ID of the target task + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Form definition +- **getProcessStorageFolderTask**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> -- `getTaskForm(appName: string, taskId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Get form defintion of a task - - `appName` - App Name - - `taskId` - Task Id + - _appName:_ `string` - + - _taskId:_ `string` - + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - -- `getForm(appName: string, formId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Get a form definition - - `appName` - App Name - - `formId` - Form Id +- **getTask**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>`<br/> + Gets details of a task + - _appName:_ `string` - Name of the app + - _taskId:_ `string` - ID of the target task + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>` - Details of the task +- **getTaskForm**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> + Gets the form definition of a task. + - _appName:_ `string` - Name of the app + - _taskId:_ `string` - ID of the target task + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Form definition +- **getTaskVariables**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]>`<br/> + Gets the variables of a task. + - _appName:_ `string` - Name of the app + - _taskId:_ `string` - ID of the target task + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]>` - Task variables +- **parseForm**(json: `any`, data?: [`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]`, readOnly: `boolean` = `false`): [`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)<br/> + Parses JSON data to create a corresponding form. + - _json:_ `any` - JSON data to create the form + - _data:_ [`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)`[]` - (Optional) (Optional) Values for the form's fields + - _readOnly:_ `boolean` - Toggles whether or not the form should be read-only + - **Returns** [`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) - [Form](../../../lib/process-services/task-list/models/form.model.ts) created from the JSON specification +- **saveTaskForm**(appName: `string`, taskId: `string`, formId: `string`, formValues: [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>`<br/> + Saves a task form. + - _appName:_ `string` - Name of the app + - _taskId:_ `string` - ID of the target task + - _formId:_ `string` - ID of the form to save + - _formValues:_ [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts) - [Form](../../../lib/process-services/task-list/models/form.model.ts) values object + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>` - Updated task details -- `getTask(appName: string, taskId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)<[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)> - Gets details of a task. - - `appName` - App Name - - `taskId` - Task Id +## See also -- `getTaskVariables(appName: string, taskId: string):`[`Observable`](http://reactivex.io/documentation/observable.html)<[`TaskVariableCloud`](../../../lib/process-services-cloud/src/lib/form/models/task-variable-cloud.model.ts)[]> - Gets variables of a task. - - `appName` - App Name - - `taskId` - Task Id +- [Form cloud component](../components/form-cloud.component.md) diff --git a/docs/process-services-cloud/unclaim-tas.directie.md b/docs/process-services-cloud/unclaim-tas.directie.md deleted file mode 100644 index 1bdebdf9b0..0000000000 --- a/docs/process-services-cloud/unclaim-tas.directie.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -Title: Unclaim Task Directive -Added: v3.1.0 -Status: Experimental -Last reviewed: 2019-03-05 ---- - -# [Unclaim task directive](../../lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts "Defined in unclaim-task.directive.ts") - -Unclaim a task - -## Basic Usage - -```html -<button adf-unclaim-task [appName]="appName" [taskId]="taskId" (success)="onTaskUnclaimed()">Complete</button> -``` -## Class members - -### Properties - -| Name | Type | Default value | Description | -| ---- | ---- | ------------- | ----------- | -| taskId | `string` | empty |(Required) The id of the task. | -| appName | `string` | empty | (Required) The name of the application. | -| success | `EventEmitter<any>` | empty | Emitted when the task is completed. | -| error | `EventEmitter<any>` | empty | Emitted when the task cannot be completed. | \ No newline at end of file diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index 8ca6d16f6e..167fc08ac3 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -23,13 +23,16 @@ import { ClipboardService } from './clipboard.service'; exportAs: 'adfClipboard' }) export class ClipboardDirective { + /** Translation key or message for the tooltip. */ // tslint:disable-next-line:no-input-rename @Input('adf-clipboard') placeholder: string; + /** Reference to the HTML element containing the text to copy. */ @Input() target: HTMLInputElement | HTMLTextAreaElement; + /** Translation key or message for snackbar notification. */ // tslint:disable-next-line:no-input-rename @Input('clipboard-notification') message: string; diff --git a/lib/core/clipboard/clipboard.service.ts b/lib/core/clipboard/clipboard.service.ts index 53064a3beb..a265340e70 100644 --- a/lib/core/clipboard/clipboard.service.ts +++ b/lib/core/clipboard/clipboard.service.ts @@ -28,6 +28,11 @@ export class ClipboardService { private logService: LogService, private notificationService: NotificationService) {} + /** + * Checks if the target element can have its text copied. + * @param target Target HTML element + * @returns True if the text can be copied, false otherwise + */ isTargetValid(target: HTMLInputElement | HTMLTextAreaElement) { if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { return !target.hasAttribute('disabled'); @@ -35,6 +40,11 @@ export class ClipboardService { return false; } + /** + * Copies text from an HTML element to the clipboard. + * @param target HTML element to be copied + * @param message Snackbar message to alert when copying happens + */ copyToClipboard(target: HTMLInputElement | HTMLTextAreaElement, message?: string) { if (this.isTargetValid(target)) { try { @@ -48,6 +58,11 @@ export class ClipboardService { } } + /** + * Copies a text string to the clipboard. + * @param content Text to copy + * @param message Snackbar message to alert when copying happens + */ copyContentToClipboard(content: string, message: string) { try { document.addEventListener('copy', (e: ClipboardEvent) => { diff --git a/lib/core/data-column/data-column.component.ts b/lib/core/data-column/data-column.component.ts index 345dace375..554e48e835 100644 --- a/lib/core/data-column/data-column.component.ts +++ b/lib/core/data-column/data-column.component.ts @@ -32,7 +32,7 @@ export class DataColumnComponent implements OnInit { key: string; /** Value type for the column. Possible settings are 'text', 'image', - * 'date', 'fileSize' and 'location'. + * 'date', 'fileSize', 'location', and 'json'. */ @Input() type: string = 'text'; @@ -66,7 +66,7 @@ export class DataColumnComponent implements OnInit { @Input('class') cssClass: string; - /** flag to show the copy content directive */ + /** Enables/disables a Clipboard directive to allow copying of cell contents. */ @Input() copyContent: boolean; diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index 01b6f5cb45..256f3bf2b2 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -55,20 +55,25 @@ import { Node } from '@alfresco/js-api'; host: { class: 'adf-datatable-cell' } }) export class DataTableCellComponent implements OnInit, OnDestroy { + /** Data table adapter instance. */ @Input() data: DataTableAdapter; + /** Data that defines the column. */ @Input() column: DataColumn; + /** Data that defines the row. */ @Input() row: DataRow; value$ = new BehaviorSubject<any>(''); + /** Enables/disables a Clipboard directive to allow copying of the cell's content. */ @Input() copyContent: boolean; + /** Text for the cell's tooltip. */ @Input() tooltip: string; diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts index 1c4a7ab0ae..eeced9d7f1 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -36,6 +36,12 @@ export class FormCloudService { private logService: LogService ) {} + /** + * Gets the form definition of a task. + * @param appName Name of the app + * @param taskId ID of the target task + * @returns Form definition + */ getTaskForm(appName: string, taskId: string): Observable<any> { return this.getTask(appName, taskId).pipe( switchMap((task: TaskDetailsCloudModel) => { @@ -52,6 +58,14 @@ export class FormCloudService { ); } + /** + * Saves a task form. + * @param appName Name of the app + * @param taskId ID of the target task + * @param formId ID of the form to save + * @param formValues Form values object + * @returns Updated task details + */ saveTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues): Observable<TaskDetailsCloudModel> { const apiUrl = this.buildSaveFormUrl(appName, formId); const saveFormRepresentation = <SaveFormRepresentation> { values: formValues, taskId: taskId }; @@ -89,6 +103,15 @@ export class FormCloudService { ); } + /** + * Completes a task form. + * @param appName Name of the app + * @param taskId ID of the target task + * @param formId ID of the form to complete + * @param formValues Form values object + * @param outcome (Optional) Form outcome + * @returns Updated task details + */ completeTaskForm(appName: string, taskId: string, formId: string, formValues: FormValues, outcome: string): Observable<TaskDetailsCloudModel> { const apiUrl = this.buildSubmitFormUrl(appName, formId); const completeFormRepresentation: any = <CompleteFormRepresentation> { values: formValues, taskId: taskId }; @@ -111,6 +134,12 @@ export class FormCloudService { ); } + /** + * Gets details of a task + * @param appName Name of the app + * @param taskId ID of the target task + * @returns Details of the task + */ getTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { const apiUrl = this.buildGetTaskUrl(appName, taskId); return from(this.apiService @@ -145,6 +174,12 @@ export class FormCloudService { ); } + /** + * Gets the variables of a task. + * @param appName Name of the app + * @param taskId ID of the target task + * @returns Task variables + */ getTaskVariables(appName: string, taskId: string): Observable<TaskVariableCloud[]> { const apiUrl = this.buildGetTaskVariablesUrl(appName, taskId); return from(this.apiService @@ -162,6 +197,12 @@ export class FormCloudService { ); } + /** + * Gets a form definition. + * @param appName Name of the app + * @param taskId ID of the target task + * @returns Form definition + */ getForm(appName: string, taskId: string): Observable<any> { const apiUrl = this.buildGetFormUrl(appName, taskId); const bodyParam = {}, pathParams = {}, queryParams = {}, headerParams = {}, @@ -179,6 +220,13 @@ export class FormCloudService { ); } + /** + * Parses JSON data to create a corresponding form. + * @param json JSON data to create the form + * @param data (Optional) Values for the form's fields + * @param readOnly Toggles whether or not the form should be read-only + * @returns Form created from the JSON specification + */ parseForm(json: any, data?: TaskVariableCloud[], readOnly: boolean = false): FormCloud { if (json) { const form = new FormCloud(json, data, readOnly, this); diff --git a/tools/doc/doctool.config.json b/tools/doc/doctool.config.json index 78d5fac00f..51e365e500 100644 --- a/tools/doc/doctool.config.json +++ b/tools/doc/doctool.config.json @@ -36,6 +36,8 @@ "Blob": "https://developer.mozilla.org/en-US/docs/Web/API/Blob", "Promise": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises", "EventEmitter": "https://angular.io/api/core/EventEmitter", + "HTMLInputElement": "https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement", + "HTMLTextAreaElement": "https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement", "MatDialog": "https://material.angular.io/components/dialog/overview", "MatIconRegistry": "https://material.angular.io/components/icon/api", "MatSnackBarRef": "https://material.angular.io/components/snack-bar/overview", From 68f674c0fdfc0fd26eb0949622c51296bc0ba142 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Fri, 12 Apr 2019 16:25:58 +0100 Subject: [PATCH 108/208] [ADF-3983] Add permission template to app list cloud (#4592) * [ADF-3983] Add permission template to app list cloud * [ADF-3983] Fix and add unit tests --- .../components/app-list-cloud.component.html | 18 ++- .../components/app-list-cloud.component.scss | 2 +- .../app-list-cloud.component.spec.ts | 27 +++- .../components/app-list-cloud.component.ts | 153 +++++++++--------- .../src/lib/i18n/en.json | 10 +- 5 files changed, 124 insertions(+), 86 deletions(-) diff --git a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.html b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.html index 3c05799595..bff0c2bd52 100644 --- a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.html +++ b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.html @@ -1,8 +1,8 @@ -<div class="menu-container" *ngIf="apps$ | async as appsList; else loading"> +<div class="menu-container" *ngIf="apps$ | async as appsList; else loadingOrError"> <ng-container *ngIf="appsList.length > 0; else noApps"> <div *ngIf="isGrid(); else appList" fxLayout="row wrap"> - <adf-cloud-app-details fxFlex="33.33333%" fxFlex.lt-md="50%" fxFlex.lt-sm="100%" *ngFor="let app of appsList" - [applicationInstance]="app" (selectedApp)="onSelectApp($event)"> + <adf-cloud-app-details fxFlex="33.33333%" fxFlex.lt-md="50%" fxFlex.lt-sm="100%" + *ngFor="let app of appsList" [applicationInstance]="app" (selectedApp)="onSelectApp($event)"> </adf-cloud-app-details> </div> @@ -24,15 +24,23 @@ </ng-content> <ng-template #defaultEmptyTemplate> - <adf-empty-content icon="apps" [title]="'ADF_CLOUD_TASK_LIST.APPS.TITLE' | translate" [subtitle]="'ADF_CLOUD_TASK_LIST.APPS.SUBTITLE' | translate"> + <adf-empty-content icon="apps" [title]="'ADF_CLOUD_TASK_LIST.APPS.NO_APPS.TITLE' | translate" + [subtitle]="'ADF_CLOUD_TASK_LIST.APPS.NO_APPS.SUBTITLE' | translate"> </adf-empty-content> </ng-template> </div> </ng-template> -<ng-template #loading> +<ng-template #loadingOrError> + <div *ngIf="loadingError$ | async; else loading" class="adf-app-list-error"> + <adf-empty-content icon="error_outline" [title]="'ADF_CLOUD_TASK_LIST.APPS.ERROR.TITLE' | translate" + [subtitle]="'ADF_CLOUD_TASK_LIST.APPS.ERROR.SUBTITLE' | translate"> + </adf-empty-content> + </div> + <ng-template #loading> <ng-container> <div class="adf-app-list-spinner"> <mat-spinner></mat-spinner> </div> </ng-container> </ng-template> +</ng-template> diff --git a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.scss b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.scss index 0c80dc2f08..88e1d3b6a6 100644 --- a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.scss @@ -8,7 +8,7 @@ cursor: pointer; } - .adf-app-list-spinner, .adf-app-list-empty { + .adf-app-list-spinner, .adf-app-list-empty, .adf-app-list-error { display: flex; align-items: center; justify-content: center; diff --git a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.spec.ts index 55ea187214..eb89b3832b 100644 --- a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.spec.ts @@ -18,7 +18,7 @@ import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { setupTestBed, CoreModule, AlfrescoApiServiceMock, AlfrescoApiService } from '@alfresco/adf-core'; -import { of } from 'rxjs'; +import { of, throwError } from 'rxjs'; import { fakeApplicationInstance } from '../mock/app-model.mock'; import { AppListCloudComponent } from './app-list-cloud.component'; @@ -40,7 +40,7 @@ describe('AppListCloudComponent', () => { } }; - beforeEach( async(() => { + beforeEach(async(() => { TestBed.configureTestingModule({ imports: [CoreModule.forRoot(), ProcessServiceCloudTestingModule, AppListCloudModule], providers: [ @@ -56,7 +56,7 @@ describe('AppListCloudComponent', () => { }).compileComponents(); })); - beforeEach( () => { + beforeEach(() => { fixture = TestBed.createComponent(AppListCloudComponent); component = fixture.componentInstance; alfrescoApiService = TestBed.get(AlfrescoApiService); @@ -105,11 +105,28 @@ describe('AppListCloudComponent', () => { expect(defaultEmptyTemplate).toBeDefined(); expect(defaultEmptyTemplate).not.toBeNull(); expect(emptyContent).not.toBeNull(); - expect(emptyTitle.innerText).toBe('ADF_CLOUD_TASK_LIST.APPS.TITLE'); - expect(emptySubtitle.innerText).toBe('ADF_CLOUD_TASK_LIST.APPS.SUBTITLE'); + expect(emptyTitle.innerText).toBe('ADF_CLOUD_TASK_LIST.APPS.NO_APPS.TITLE'); + expect(emptySubtitle.innerText).toBe('ADF_CLOUD_TASK_LIST.APPS.NO_APPS.SUBTITLE'); expect(getAppsSpy).toHaveBeenCalled(); }); + it('should display default no permissions template when response returns exception', () => { + getAppsSpy.and.returnValue(throwError({})); + fixture.detectChanges(); + fixture.whenStable().then(() => { + component.loadingError$.next(true); + fixture.detectChanges(); + const errorTemplate = fixture.nativeElement.querySelector('.adf-app-list-error'); + const errorTitle = fixture.debugElement.nativeElement.querySelector('.adf-empty-content__title'); + const errorSubtitle = fixture.debugElement.nativeElement.querySelector('.adf-empty-content__subtitle'); + expect(errorTemplate).not.toBeNull(); + expect(errorTitle.innerText).toBe('ADF_CLOUD_TASK_LIST.APPS.ERROR.TITLE'); + expect(errorSubtitle.innerText).toBe('ADF_CLOUD_TASK_LIST.APPS.ERROR.SUBTITLE'); + expect(getAppsSpy).toHaveBeenCalled(); + }); + + }); + describe('Grid Layout ', () => { it('should display a grid by default', () => { diff --git a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts index 79302daf4c..3984e0c105 100644 --- a/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts @@ -15,93 +15,100 @@ * limitations under the License. */ - import { CustomEmptyContentTemplateDirective } from '@alfresco/adf-core'; - import { AfterContentInit, Component, EventEmitter, Input, OnInit, Output, ContentChild } from '@angular/core'; - import { Observable } from 'rxjs'; - import { AppsProcessCloudService } from '../services/apps-process-cloud.service'; - import { ApplicationInstanceModel } from '../models/application-instance.model'; - import { ApplicationDeploymentCloudService } from '../services/app-deployment-cloud.service'; +import { CustomEmptyContentTemplateDirective } from '@alfresco/adf-core'; +import { AfterContentInit, Component, EventEmitter, Input, OnInit, Output, ContentChild } from '@angular/core'; +import { Observable, of, Subject } from 'rxjs'; +import { AppsProcessCloudService } from '../services/apps-process-cloud.service'; +import { ApplicationInstanceModel } from '../models/application-instance.model'; +import { ApplicationDeploymentCloudService } from '../services/app-deployment-cloud.service'; +import { catchError } from 'rxjs/operators'; - @Component({ - selector: 'adf-cloud-app-list', - templateUrl: './app-list-cloud.component.html', - styleUrls: ['./app-list-cloud.component.scss'], - providers: [ +@Component({ + selector: 'adf-cloud-app-list', + templateUrl: './app-list-cloud.component.html', + styleUrls: ['./app-list-cloud.component.scss'], + providers: [ { provide: AppsProcessCloudService, useClass: ApplicationDeploymentCloudService } - ] - }) - export class AppListCloudComponent implements OnInit, AfterContentInit { + ] +}) +export class AppListCloudComponent implements OnInit, AfterContentInit { - public static LAYOUT_LIST: string = 'LIST'; - public static LAYOUT_GRID: string = 'GRID'; - public static RUNNING_STATUS: string = 'RUNNING'; + public static LAYOUT_LIST: string = 'LIST'; + public static LAYOUT_GRID: string = 'GRID'; + public static RUNNING_STATUS: string = 'RUNNING'; - @ContentChild(CustomEmptyContentTemplateDirective) - emptyCustomContent: CustomEmptyContentTemplateDirective; + @ContentChild(CustomEmptyContentTemplateDirective) + emptyCustomContent: CustomEmptyContentTemplateDirective; - /** (**required**) Defines the layout of the apps. There are two possible - * values, "GRID" and "LIST". - */ - @Input() - layoutType: string = AppListCloudComponent.LAYOUT_GRID; + /** (**required**) Defines the layout of the apps. There are two possible + * values, "GRID" and "LIST". + */ + @Input() + layoutType: string = AppListCloudComponent.LAYOUT_GRID; - /** Emitted when an app entry is clicked. */ - @Output() - appClick: EventEmitter<ApplicationInstanceModel> = new EventEmitter<ApplicationInstanceModel>(); + /** Emitted when an app entry is clicked. */ + @Output() + appClick: EventEmitter<ApplicationInstanceModel> = new EventEmitter<ApplicationInstanceModel>(); - apps$: Observable<any>; + apps$: Observable<any>; + loadingError$ = new Subject<boolean>(); + hasEmptyCustomContentTemplate: boolean = false; - hasEmptyCustomContentTemplate: boolean = false; + constructor(private appsProcessCloudService: AppsProcessCloudService) { } - constructor(private appsProcessCloudService: AppsProcessCloudService) { } + ngOnInit() { + if (!this.isValidType()) { + this.setDefaultLayoutType(); + } - ngOnInit() { - if (!this.isValidType()) { - this.setDefaultLayoutType(); - } + this.apps$ = this.appsProcessCloudService.getDeployedApplicationsByStatus(AppListCloudComponent.RUNNING_STATUS) + .pipe( + catchError((error) => { + this.loadingError$.next(true); + return of(); + }) + ); + } - this.apps$ = this.appsProcessCloudService.getDeployedApplicationsByStatus(AppListCloudComponent.RUNNING_STATUS); - } + ngAfterContentInit() { + if (this.emptyCustomContent) { + this.hasEmptyCustomContentTemplate = true; + } + } - ngAfterContentInit() { - if (this.emptyCustomContent) { - this.hasEmptyCustomContentTemplate = true; - } - } + onSelectApp(app: ApplicationInstanceModel): void { + this.appClick.emit(app); + } - onSelectApp(app: ApplicationInstanceModel): void { - this.appClick.emit(app); - } + /** + * Check if the value of the layoutType property is an allowed value + */ + isValidType(): boolean { + if (this.layoutType && (this.layoutType === AppListCloudComponent.LAYOUT_LIST || this.layoutType === AppListCloudComponent.LAYOUT_GRID)) { + return true; + } + return false; + } - /** - * Check if the value of the layoutType property is an allowed value - */ - isValidType(): boolean { - if (this.layoutType && (this.layoutType === AppListCloudComponent.LAYOUT_LIST || this.layoutType === AppListCloudComponent.LAYOUT_GRID)) { - return true; - } - return false; - } + /** + * Assign the default value to LayoutType + */ + setDefaultLayoutType(): void { + this.layoutType = AppListCloudComponent.LAYOUT_GRID; + } - /** - * Assign the default value to LayoutType - */ - setDefaultLayoutType(): void { - this.layoutType = AppListCloudComponent.LAYOUT_GRID; - } + /** + * Return true if the layout type is LIST + */ + isList(): boolean { + return this.layoutType === AppListCloudComponent.LAYOUT_LIST; + } - /** - * Return true if the layout type is LIST - */ - isList(): boolean { - return this.layoutType === AppListCloudComponent.LAYOUT_LIST; - } + /** + * Return true if the layout type is GRID + */ + isGrid(): boolean { - /** - * Return true if the layout type is GRID - */ - isGrid(): boolean { - - return this.layoutType === AppListCloudComponent.LAYOUT_GRID; - } - } + return this.layoutType === AppListCloudComponent.LAYOUT_GRID; + } +} diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 796e9d4232..71173431f6 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "No Applications Found", - "SUBTITLE": "Create a new application that you want to easily find later" + "NO_APPS": { + "TITLE": "No Applications Found", + "SUBTITLE": "Create a new application that you want to easily find later" + }, + "ERROR": { + "TITLE": "There was an error", + "SUBTITLE": "Check you have permission to access the apps" + } }, "START_TASK": { "FORM": { From 578f00d270ca3c44244c42e1d6a11a744c8b9acc Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Fri, 12 Apr 2019 16:45:04 +0100 Subject: [PATCH 109/208] extend ProfileState interface with optional groups --- lib/extensions/src/lib/store/states/profile.state.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/extensions/src/lib/store/states/profile.state.ts b/lib/extensions/src/lib/store/states/profile.state.ts index e41706107c..4b6443c8e8 100644 --- a/lib/extensions/src/lib/store/states/profile.state.ts +++ b/lib/extensions/src/lib/store/states/profile.state.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +import { Group } from '@alfresco/js-api'; + export interface ProfileState { id: string; isAdmin: boolean; @@ -22,4 +24,5 @@ export interface ProfileState { lastName: string; userName?: string; initials?: string; + groups?: Group[]; } From 4215666a96b8138547056a0f0181cf2982e7b95f Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Fri, 12 Apr 2019 16:54:27 +0100 Subject: [PATCH 110/208] allow setting custom data for ProfileState --- lib/extensions/src/lib/store/states/profile.state.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/extensions/src/lib/store/states/profile.state.ts b/lib/extensions/src/lib/store/states/profile.state.ts index 4b6443c8e8..6097978374 100644 --- a/lib/extensions/src/lib/store/states/profile.state.ts +++ b/lib/extensions/src/lib/store/states/profile.state.ts @@ -18,6 +18,8 @@ import { Group } from '@alfresco/js-api'; export interface ProfileState { + [key: string]: any; + id: string; isAdmin: boolean; firstName: string; From 4cc449dfbb4d075016d04a3b341bea4c39969f1f Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Fri, 12 Apr 2019 17:27:51 +0100 Subject: [PATCH 111/208] [ADF-4376] Fix Sticky Header in Datatable Component (#4582) * [ADF-4376] Fix Sticky Header in Datatable Component * [ADF-4374] Rebase branch * remove search from permissions test * remove search from permissions test --- .../datatable/datatable.component.html | 2 +- .../datatable/datatable.component.ts | 2 +- .../permissions/permissions-component.e2e.ts | 183 +------------- .../permissions/site-permissions.e2e.ts | 226 +----------------- e2e/pages/adf/contentServicesPage.ts | 2 - e2e/proxy.ts | 4 +- ...content-node-selector-panel.component.scss | 1 + .../datatable/datatable.component.scss | 18 +- 8 files changed, 28 insertions(+), 410 deletions(-) diff --git a/demo-shell/src/app/components/datatable/datatable.component.html b/demo-shell/src/app/components/datatable/datatable.component.html index 4b95fd54ba..b6faba51b2 100644 --- a/demo-shell/src/app/components/datatable/datatable.component.html +++ b/demo-shell/src/app/components/datatable/datatable.component.html @@ -56,4 +56,4 @@ <button mat-raised-button (click)="addRow()">{{ 'DATATABLE.ADD_ROW'| translate }}</button> <button mat-raised-button (click)="replaceRows()">{{ 'DATATABLE.REPLACE_ROWS'| translate }}</button> <button mat-raised-button (click)="replaceColumns()">{{ 'DATATABLE.REPLACE_COLUMNS'| translate }}</button> -</div> \ No newline at end of file +</div> diff --git a/demo-shell/src/app/components/datatable/datatable.component.ts b/demo-shell/src/app/components/datatable/datatable.component.ts index 39e7a7b62d..79e5d7eec6 100644 --- a/demo-shell/src/app/components/datatable/datatable.component.ts +++ b/demo-shell/src/app/components/datatable/datatable.component.ts @@ -129,7 +129,7 @@ export class DataTableComponent { [ { type: 'image', key: 'icon', title: '', srTitle: 'Thumbnail' }, { type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '' }, - { type: 'text', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-2' }, + { type: 'date', key: 'createdOn', title: 'Created On', sortable: true, cssClass: 'adf-ellipsis-cell adf-expand-cell-2' }, { type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true }, { type: 'text', key: 'createdBy.name', title: 'Created By', sortable: true, cssClass: ''}, { type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2'} diff --git a/e2e/content-services/permissions/permissions-component.e2e.ts b/e2e/content-services/permissions/permissions-component.e2e.ts index bf32ca226e..c9eccf6577 100644 --- a/e2e/content-services/permissions/permissions-component.e2e.ts +++ b/e2e/content-services/permissions/permissions-component.e2e.ts @@ -27,10 +27,10 @@ import { UploadActions } from '../../actions/ACS/upload.actions'; import { StringUtil } from '@alfresco/adf-testing'; import { browser, protractor } from 'protractor'; import { FolderModel } from '../../models/ACS/folderModel'; -import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { NotificationPage } from '../../pages/adf/notificationPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; describe('Permissions Component', function () { @@ -38,11 +38,11 @@ describe('Permissions Component', function () { const loginPage = new LoginPage(); const contentServicesPage = new ContentServicesPage(); const permissionsPage = new PermissionsPage(); + const navigationBarPage = new NavigationBarPage(); const uploadActions = new UploadActions(); const contentList = contentServicesPage.getDocumentList(); - const searchDialog = new SearchDialog(); const viewerPage = new ViewerPage(); const metadataViewPage = new MetadataViewPage(); const notificationPage = new NotificationPage(); @@ -92,21 +92,15 @@ describe('Permissions Component', function () { await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await alfrescoJsApi.core.peopleApi.addPerson(fileOwnerUser); - await alfrescoJsApi.core.peopleApi.addPerson(filePermissionUser); - await alfrescoJsApi.core.groupsApi.createGroup(groupBody); await alfrescoJsApi.login(fileOwnerUser.id, fileOwnerUser.password); roleConsumerFolder = await uploadActions.createFolder(alfrescoJsApi, roleConsumerFolderModel.name, '-my-'); - roleCoordinatorFolder = await uploadActions.createFolder(alfrescoJsApi, roleCoordinatorFolderModel.name, '-my-'); - roleContributorFolder = await uploadActions.createFolder(alfrescoJsApi, roleContributorFolderModel.name, '-my-'); - roleCollaboratorFolder = await uploadActions.createFolder(alfrescoJsApi, roleCollaboratorFolderModel.name, '-my-'); - roleEditorFolder = await uploadActions.createFolder(alfrescoJsApi, roleEditorFolderModel.name, '-my-'); folders = [roleConsumerFolder, roleContributorFolder, roleCoordinatorFolder, roleCollaboratorFolder, roleEditorFolder]; @@ -114,131 +108,78 @@ describe('Permissions Component', function () { await alfrescoJsApi.core.nodesApi.updateNode(roleConsumerFolder.entry.id, { - permissions: { - locallySet: [{ - authorityId: filePermissionUser.getId(), - name: 'Consumer', - accessStatus: 'ALLOWED' - }] - } - }); await alfrescoJsApi.core.nodesApi.updateNode(roleCollaboratorFolder.entry.id, - { - permissions: { - locallySet: [{ - authorityId: filePermissionUser.getId(), - name: 'Collaborator', - accessStatus: 'ALLOWED' - }] - } - }); await alfrescoJsApi.core.nodesApi.updateNode(roleCoordinatorFolder.entry.id, - { - permissions: { - locallySet: [{ - authorityId: filePermissionUser.getId(), - name: 'Coordinator', - accessStatus: 'ALLOWED' - }] - } - }); await alfrescoJsApi.core.nodesApi.updateNode(roleContributorFolder.entry.id, { - permissions: { - locallySet: [{ - authorityId: filePermissionUser.getId(), - name: 'Contributor', - accessStatus: 'ALLOWED' - }] - } - }); await alfrescoJsApi.core.nodesApi.updateNode(roleEditorFolder.entry.id, { - permissions: { - locallySet: [{ - authorityId: filePermissionUser.getId(), - name: 'Editor', - accessStatus: 'ALLOWED' - }] - } - }); await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'RoleConsumer' + fileModel.name, roleConsumerFolder.entry.id); - await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'RoleContributor' + fileModel.name, roleContributorFolder.entry.id); - await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'RoleCoordinator' + fileModel.name, roleCoordinatorFolder.entry.id); - await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'RoleCollaborator' + fileModel.name, roleCollaboratorFolder.entry.id); - await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'RoleEditor' + fileModel.name, roleEditorFolder.entry.id); - browser.driver.sleep(15000); // wait search get the groups, files and folders - done(); - }); afterAll(async (done) => { - await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await folders.forEach(function (folder) { - uploadActions.deleteFilesOrFolder(alfrescoJsApi, folder.entry.id); }); done(); - }); describe('Inherit and assigning permissions', function () { @@ -252,11 +193,8 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(fileOwnerUser); contentServicesPage.goToDocumentList(); - contentServicesPage.checkContentIsDisplayed(fileModel.name); - contentServicesPage.checkSelectedSiteIsDisplayed('My files'); - contentList.rightClickOnRow(fileModel.name); contentServicesPage.pressContextMenuActionNamed('Permission'); @@ -481,28 +419,13 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(filePermissionUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(roleConsumerFolderModel.name) - - .resultTableContainsRow(roleConsumerFolderModel.name) - - .clickOnSpecificRow(roleConsumerFolderModel.name); + navigationBarPage.openContentServicesFolder(roleConsumerFolder.entry.id); contentServicesPage.checkContentIsDisplayed('RoleConsumer' + fileModel.name); contentList.doubleClickRow('RoleConsumer' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -527,28 +450,13 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(filePermissionUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(roleContributorFolderModel.name) - - .resultTableContainsRow(roleContributorFolderModel.name) - - .clickOnSpecificRow(roleContributorFolderModel.name); + navigationBarPage.openContentServicesFolder(roleContributorFolder.entry.id); contentServicesPage.checkContentIsDisplayed('RoleContributor' + fileModel.name); contentList.doubleClickRow('RoleContributor' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -566,7 +474,6 @@ describe('Permissions Component', function () { contentServicesPage.uploadFile(testFileModel.location).checkContentIsDisplayed(testFileModel.name); uploadDialog.fileIsUploaded(testFileModel.name); - uploadDialog.clickOnCloseButton().dialogIsNotDisplayed(); }); @@ -575,28 +482,13 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(filePermissionUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(roleEditorFolderModel.name) - - .resultTableContainsRow(roleEditorFolderModel.name) - - .clickOnSpecificRow(roleEditorFolderModel.name); + navigationBarPage.openContentServicesFolder(roleEditorFolder.entry.id); contentServicesPage.checkContentIsDisplayed('RoleEditor' + fileModel.name); contentList.doubleClickRow('RoleEditor' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -616,9 +508,7 @@ describe('Permissions Component', function () { await metadataViewPage.editIconClick(); metadataViewPage.editPropertyIconIsDisplayed('properties.cm:title'); - metadataViewPage.clickEditPropertyIcons('properties.cm:title'); - metadataViewPage.enterPropertyText('properties.cm:title', 'newTitle1'); await metadataViewPage.clickUpdatePropertyIcon('properties.cm:title'); @@ -639,28 +529,13 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(filePermissionUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(roleCollaboratorFolderModel.name) - - .resultTableContainsRow(roleCollaboratorFolderModel.name) - - .clickOnSpecificRow(roleCollaboratorFolderModel.name); + navigationBarPage.openContentServicesFolder(roleCollaboratorFolder.entry.id); contentServicesPage.checkContentIsDisplayed('RoleCollaborator' + fileModel.name); contentList.doubleClickRow('RoleCollaborator' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -680,9 +555,7 @@ describe('Permissions Component', function () { await metadataViewPage.editIconClick(); metadataViewPage.editPropertyIconIsDisplayed('properties.cm:title'); - metadataViewPage.clickEditPropertyIcons('properties.cm:title'); - metadataViewPage.enterPropertyText('properties.cm:title', 'newTitle2'); await metadataViewPage.clickUpdatePropertyIcon('properties.cm:title'); @@ -694,7 +567,6 @@ describe('Permissions Component', function () { contentServicesPage.uploadFile(testFileModel.location).checkContentIsDisplayed(testFileModel.name); uploadDialog.fileIsUploaded(testFileModel.name); - uploadDialog.clickOnCloseButton().dialogIsNotDisplayed(); }); @@ -705,28 +577,13 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(filePermissionUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(roleCoordinatorFolderModel.name) - - .resultTableContainsRow(roleCoordinatorFolderModel.name) - - .clickOnSpecificRow(roleCoordinatorFolderModel.name); + navigationBarPage.openContentServicesFolder(roleCoordinatorFolder.entry.id); contentServicesPage.checkContentIsDisplayed('RoleCoordinator' + fileModel.name); contentList.doubleClickRow('RoleCoordinator' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -740,9 +597,7 @@ describe('Permissions Component', function () { await metadataViewPage.editIconClick(); metadataViewPage.editPropertyIconIsDisplayed('properties.cm:title'); - metadataViewPage.clickEditPropertyIcons('properties.cm:title'); - metadataViewPage.enterPropertyText('properties.cm:title', 'newTitle3'); await metadataViewPage.clickUpdatePropertyIcon('properties.cm:title'); @@ -750,17 +605,13 @@ describe('Permissions Component', function () { expect(metadataViewPage.getPropertyText('properties.cm:title')).toEqual('newTitle3'); metadataViewPage.clickCloseButton(); - contentServicesPage.uploadFile(pngFileModel.location).checkContentIsDisplayed(pngFileModel.name); uploadDialog.fileIsUploaded(pngFileModel.name); - uploadDialog.clickOnCloseButton().dialogIsNotDisplayed(); contentServicesPage.checkContentIsDisplayed('RoleCoordinator' + fileModel.name); - contentServicesPage.deleteContent('RoleCoordinator' + fileModel.name); - contentServicesPage.checkContentIsNotDisplayed('RoleCoordinator' + fileModel.name); }); @@ -771,24 +622,9 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(filePermissionUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(roleConsumerFolderModel.name) - - .resultTableContainsRow(roleConsumerFolderModel.name) - - .clickOnSpecificRow(roleConsumerFolderModel.name); + navigationBarPage.openContentServicesFolder(roleConsumerFolder.entry.id); contentServicesPage.checkContentIsDisplayed('RoleConsumer' + fileModel.name); - contentServicesPage.checkSelectedSiteIsDisplayed('My files'); contentList.rightClickOnRow('RoleConsumer' + fileModel.name); @@ -796,13 +632,10 @@ describe('Permissions Component', function () { contentServicesPage.pressContextMenuActionNamed('Permission'); permissionsPage.checkPermissionInheritedButtonIsDisplayed(); - permissionsPage.checkAddPermissionButtonIsDisplayed(); - permissionsPage.clickPermissionInheritedButton(); notificationPage.checkNotifyContains('You are not allowed to change permissions'); - notificationPage.checkNotificationSnackBarIsNotDisplayed(); permissionsPage.clickAddPermissionButton(); diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index cb2838f6db..b32946c7e9 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -16,63 +16,36 @@ */ import { PermissionsPage } from '../../pages/adf/permissionsPage'; - import { LoginPage } from '@alfresco/adf-testing'; - import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; - import { AcsUserModel } from '../../models/ACS/acsUserModel'; - import TestConfig = require('../../test.config'); - import resources = require('../../util/resources'); - import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; - import { FileModel } from '../../models/ACS/fileModel'; - import { UploadActions } from '../../actions/ACS/upload.actions'; - import { StringUtil } from '@alfresco/adf-testing'; - import { browser, protractor } from 'protractor'; - -import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; - import { ViewerPage } from '../../pages/adf/viewerPage'; - import { NotificationPage } from '../../pages/adf/notificationPage'; - import CONSTANTS = require('../../util/constants'); - import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; - import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; - -import { VersionManagePage } from '../../pages/adf/versionManagerPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; describe('Permissions Component', function () { const loginPage = new LoginPage(); - const contentServicesPage = new ContentServicesPage(); - const permissionsPage = new PermissionsPage(); - const uploadActions = new UploadActions(); const contentList = contentServicesPage.getDocumentList(); - const searchDialog = new SearchDialog(); - const viewerPage = new ViewerPage(); - + const navigationBarPage = new NavigationBarPage(); const metadataViewPage = new MetadataViewPage(); - const notificationPage = new NotificationPage(); - - const versionManagePage = new VersionManagePage(); - const uploadDialog = new UploadDialog(); let folderOwnerUser, consumerUser, siteConsumerUser, contributorUser, managerUser, collaboratorUser; @@ -80,49 +53,32 @@ describe('Permissions Component', function () { let publicSite, privateSite, folderName; const fileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.TXT_0B.file_name, - 'location': resources.Files.ADF_DOCUMENTS.TXT_0B.file_location - }); const testFileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.TEST.file_name, - 'location': resources.Files.ADF_DOCUMENTS.TEST.file_location - }); const pngFileModel = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, - 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location - }); const alfrescoJsApi = new AlfrescoApi({ - provider: 'ECM', - hostEcm: TestConfig.adf.url - }); let siteFolder, privateSiteFile; folderOwnerUser = new AcsUserModel(); - consumerUser = new AcsUserModel(); - siteConsumerUser = new AcsUserModel(); - collaboratorUser = new AcsUserModel(); - contributorUser = new AcsUserModel(); - managerUser = new AcsUserModel(); beforeAll(async (done) => { @@ -130,17 +86,11 @@ describe('Permissions Component', function () { await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await alfrescoJsApi.core.peopleApi.addPerson(folderOwnerUser); - await alfrescoJsApi.core.peopleApi.addPerson(siteConsumerUser); - await alfrescoJsApi.core.peopleApi.addPerson(consumerUser); - await alfrescoJsApi.core.peopleApi.addPerson(contributorUser); - await alfrescoJsApi.core.peopleApi.addPerson(collaboratorUser); - await alfrescoJsApi.core.peopleApi.addPerson(managerUser); - await alfrescoJsApi.login(folderOwnerUser.id, folderOwnerUser.password); const publicSiteName = `PUBLIC_TEST_SITE_${StringUtil.generateRandomString(5)}`; @@ -154,47 +104,31 @@ describe('Permissions Component', function () { const privateSiteBody = {visibility: 'PRIVATE', title: privateSiteName}; publicSite = await alfrescoJsApi.core.sitesApi.createSite(publicSiteBody); - privateSite = await alfrescoJsApi.core.sitesApi.createSite(privateSiteBody); await alfrescoJsApi.core.sitesApi.addSiteMember(publicSite.entry.id, { - id: siteConsumerUser.id, - role: CONSTANTS.CS_USER_ROLES.CONSUMER - }); await alfrescoJsApi.core.sitesApi.addSiteMember(publicSite.entry.id, { - id: collaboratorUser.id, - role: CONSTANTS.CS_USER_ROLES.COLLABORATOR - }); await alfrescoJsApi.core.sitesApi.addSiteMember(publicSite.entry.id, { - id: contributorUser.id, - role: CONSTANTS.CS_USER_ROLES.CONTRIBUTOR - }); await alfrescoJsApi.core.sitesApi.addSiteMember(publicSite.entry.id, { - id: managerUser.id, - role: CONSTANTS.CS_USER_ROLES.MANAGER - }); await alfrescoJsApi.core.sitesApi.addSiteMember(privateSite.entry.id, { - id: managerUser.id, - role: CONSTANTS.CS_USER_ROLES.MANAGER - }); siteFolder = await uploadActions.createFolder(alfrescoJsApi, folderName, publicSite.entry.guid); @@ -204,27 +138,17 @@ describe('Permissions Component', function () { await alfrescoJsApi.core.nodesApi.updateNode(privateSiteFile.entry.id, { - permissions: { - locallySet: [{ - authorityId: managerUser.getId(), - name: 'SiteConsumer', - accessStatus: 'ALLOWED' - }] - } - }); await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'Site' + fileModel.name, siteFolder.entry.id); - browser.driver.sleep(15000); // wait search get the groups, files and folders - done(); }); @@ -232,13 +156,10 @@ describe('Permissions Component', function () { afterAll(async (done) => { await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await alfrescoJsApi.core.sitesApi.deleteSite(publicSite.entry.id); - await alfrescoJsApi.core.sitesApi.deleteSite(privateSite.entry.id); done(); - }); describe('Role Site Dropdown', function () { @@ -258,23 +179,14 @@ describe('Permissions Component', function () { contentServicesPage.pressContextMenuActionNamed('Permission'); permissionsPage.checkPermissionInheritedButtonIsDisplayed(); - permissionsPage.checkAddPermissionButtonIsDisplayed(); - permissionsPage.clickAddPermissionButton(); - permissionsPage.checkAddPermissionDialogIsDisplayed(); - permissionsPage.checkSearchUserInputIsDisplayed(); - permissionsPage.searchUserOrGroup(consumerUser.getId()); - permissionsPage.clickUserOrGroup(consumerUser.getFirstName()); - permissionsPage.checkUserOrGroupIsAdded(consumerUser.getId()); - done(); - }); it('[C277002] Should display the Role Site dropdown', () => { @@ -303,21 +215,7 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(siteConsumerUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(folderName) - - .resultTableContainsRow(folderName) - - .clickOnSpecificRow(folderName); + navigationBarPage.openContentServicesFolder(siteFolder.entry.id); contentServicesPage.checkContentIsDisplayed('Site' + fileModel.name); @@ -349,21 +247,7 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(contributorUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(folderName) - - .resultTableContainsRow(folderName) - - .clickOnSpecificRow(folderName); + navigationBarPage.openContentServicesFolder(siteFolder.entry.id); contentServicesPage.checkContentIsDisplayed('Site' + fileModel.name); @@ -397,21 +281,7 @@ describe('Permissions Component', function () { loginPage.loginToContentServicesUsingUserModel(collaboratorUser); - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(folderName) - - .resultTableContainsRow(folderName) - - .clickOnSpecificRow(folderName); + navigationBarPage.openContentServicesFolder(siteFolder.entry.id); contentServicesPage.checkContentIsDisplayed('Site' + fileModel.name); @@ -460,35 +330,16 @@ describe('Permissions Component', function () { }); it('[C277006] Role SiteManager', () => { - loginPage.loginToContentServicesUsingUserModel(managerUser); - - contentServicesPage.goToDocumentList(); - - searchDialog - - .checkSearchIconIsVisible() - - .clickOnSearchIcon() - - .checkSearchBarIsVisible() - - .enterText(folderName) - - .resultTableContainsRow(folderName) - - .clickOnSpecificRow(folderName); - + navigationBarPage.openContentServicesFolder(siteFolder.entry.id); contentServicesPage.checkContentIsDisplayed('Site' + fileModel.name); contentList.doubleClickRow('Site' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); - contentServicesPage.metadataContent('Site' + fileModel.name); metadataViewPage.editIconIsDisplayed(); @@ -498,9 +349,7 @@ describe('Permissions Component', function () { await metadataViewPage.editIconClick(); metadataViewPage.editPropertyIconIsDisplayed('properties.cm:description'); - metadataViewPage.clickEditPropertyIcons('properties.cm:description'); - metadataViewPage.enterDescriptionText('newDescription'); await metadataViewPage.clickUpdatePropertyIcon('properties.cm:description'); @@ -508,81 +357,18 @@ describe('Permissions Component', function () { expect(metadataViewPage.getPropertyText('properties.cm:description')).toEqual('newDescription'); metadataViewPage.clickCloseButton(); - contentServicesPage.uploadFile(testFileModel.location).checkContentIsDisplayed(testFileModel.name); uploadDialog.fileIsUploaded(testFileModel.name); - uploadDialog.clickOnCloseButton().dialogIsNotDisplayed(); contentServicesPage.checkContentIsDisplayed('Site' + fileModel.name); - contentServicesPage.deleteContent('Site' + fileModel.name); - contentServicesPage.checkContentIsNotDisplayed('Site' + fileModel.name); - }); }); }); - describe('Site Consumer - Add new version', function () { - - it('[C277118] Should be able to add new version with Site Consumer permission on file', () => { - - loginPage.loginToContentServicesUsingUserModel(managerUser); - - browser.get(TestConfig.adf.url + '/files/' + privateSite.entry.guid); - - contentServicesPage.checkContentIsDisplayed('privateSite' + fileModel.name); - - contentList.doubleClickRow('privateSite' + fileModel.name); - - viewerPage.checkFileIsLoaded(); - - viewerPage.checkInfoButtonIsDisplayed(); - - viewerPage.clickInfoButton(); - - viewerPage.checkInfoSideBarIsDisplayed(); - - viewerPage.clickMoveRightChevron(); - - viewerPage.clickMoveRightChevron(); - - viewerPage.clickOnTab('Versions'); - - viewerPage.checkTabIsActive('Versions'); - - versionManagePage - - .checkUploadNewVersionsButtonIsDisplayed() - - .clickAddNewVersionsButton() - - .checkMajorChangeIsDisplayed() - - .checkMinorChangeIsDisplayed() - - .checkCommentTextIsDisplayed() - - .checkCancelButtonIsDisplayed(); - - versionManagePage.uploadNewVersionFile(pngFileModel.location); - - versionManagePage.checkFileVersionExist('1.0'); - - expect(versionManagePage.getFileVersionName('1.0')).toEqual('privateSite' + fileModel.name); - - versionManagePage.checkFileVersionExist('1.1'); - - expect(versionManagePage.getFileVersionName('1.1')).toEqual(pngFileModel.name); - - viewerPage.checkFileNameIsDisplayed(pngFileModel.name); - - }); - - }); - }); diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index a098c382ef..a8310c56cf 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -58,8 +58,6 @@ export class ContentServicesPage { emptyRecent = element(by.css('.adf-container-recent .adf-empty-list__title')); gridViewButton = element(by.css('button[data-automation-id="document-list-grid-view"]')); cardViewContainer = element(by.css('div.adf-document-list-container div.adf-datatable-card')); - chooseButton = element(by.css('button[data-automation-id="content-node-selector-actions-choose"]')); - searchInputElement = element(by.css('input[data-automation-id="content-node-selector-search-input"]')); shareNodeButton = element(by.cssContainingText('mat-icon', ' share ')); nameColumnHeader = 'name'; createdByColumnHeader = 'createdByUser.displayName'; diff --git a/e2e/proxy.ts b/e2e/proxy.ts index 6f2a2b71b1..09d1864eb0 100644 --- a/e2e/proxy.ts +++ b/e2e/proxy.ts @@ -15,11 +15,13 @@ * limitations under the License. */ +/* tslint:disable */ + import { browser } from 'protractor'; export async function setConfigField(field: string, value: string) { return browser.executeScript( - "window.adf.setConfigField(`"+field + "`, `" + value + "`);" + "window.adf.setConfigField(`" + field + "`, `" + value + "`);" ); } diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.scss b/lib/content-services/content-node-selector/content-node-selector-panel.component.scss index af8fc13291..8b5a8a9f83 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.scss +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.scss @@ -142,6 +142,7 @@ .adf-datatable-cell { & .adf-name-location-cell-location { + padding: 0; display: block; } diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index 7df1810b4e..ce7d172b55 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -334,9 +334,7 @@ } .adf-datatable-cell-value { - overflow: hidden; - text-overflow: ellipsis; - word-break: break-all; + word-break: break-word; padding: 0 10px; } @@ -504,20 +502,20 @@ .adf-sticky-header { border-top: 0; - max-width: calc(100% - 0.2em); + height: 100%; .adf-datatable-header { - position: absolute; - background-color: mat-color($background, card); - display: flex; - z-index: 10; + display: block; + margin-right: 0; border-top: $data-table-dividers; border-bottom: $data-table-dividers; - width: calc(100% - 17.4em); } .adf-datatable-body { - margin-top: 57px; + display: block; + flex: 1; + overflow-y: scroll; + margin-top: -1px; } } From 9accfcfb6ec982f6083b9582e131ce78036ce73d Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Sun, 14 Apr 2019 23:03:16 +0200 Subject: [PATCH 112/208] Update ADF packages version 3.2.0-beta6 (#4602) --- demo-shell/package.json | 2 +- lib/content-services/package.json | 6 +++--- lib/core/package.json | 4 ++-- lib/extensions/package.json | 4 ++-- lib/insights/package.json | 8 ++++---- lib/process-services-cloud/package.json | 6 +++--- lib/process-services/package.json | 8 ++++---- lib/testing/package.json | 4 ++-- package.json | 18 +++++++++--------- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/demo-shell/package.json b/demo-shell/package.json index 5fa80ae451..5d02f1bdb3 100644 --- a/demo-shell/package.json +++ b/demo-shell/package.json @@ -1,7 +1,7 @@ { "name": "Alfresco-ADF-Angular-Demo", "description": "Demo shell for Alfresco Angular components", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "repository": { "type": "git", diff --git a/lib/content-services/package.json b/lib/content-services/package.json index d2a28513fc..71e865ec22 100644 --- a/lib/content-services/package.json +++ b/lib/content-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-content-services", "description": "Alfresco ADF content services", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-content-services.js", "repository": { @@ -25,9 +25,9 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.1.0", + "@alfresco/js-api": "3.2.0-beta6", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta3", + "@alfresco/adf-core": "3.2.0-beta6", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/core/package.json b/lib/core/package.json index ab199e933f..5f3557ba12 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-core", "description": "Alfresco ADF core", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-core.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@mat-datetimepicker/core": ">=2.0.1", "@mat-datetimepicker/moment": ">=2.0.1", - "@alfresco/js-api": "3.1.0", + "@alfresco/js-api": "3.2.0-beta6", "rxjs": ">=6.2.2", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", diff --git a/lib/extensions/package.json b/lib/extensions/package.json index c56ec13db0..f56a2efe6a 100644 --- a/lib/extensions/package.json +++ b/lib/extensions/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-extensions", "description": "Provides extensibility support for ADF applications.", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "license": "Apache-2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-extensions.js", @@ -16,7 +16,7 @@ "@angular/common": ">=7.0.3", "@angular/core": ">=7.0.3", "@angular/http": ">=7.0.3", - "@alfresco/js-api": "3.1.0" + "@alfresco/js-api": "3.2.0-beta6" }, "keywords": [ "extensions", diff --git a/lib/insights/package.json b/lib/insights/package.json index e3f7eb2ba1..379cd10b76 100644 --- a/lib/insights/package.json +++ b/lib/insights/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-insights", "description": "Alfresco ADF insights", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-insights.js", "repository": { @@ -25,10 +25,10 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.1.0", + "@alfresco/js-api": "3.2.0-beta6", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta3", - "@alfresco/adf-content-services": "3.2.0-beta3", + "@alfresco/adf-core": "3.2.0-beta6", + "@alfresco/adf-content-services": "3.2.0-beta6", "@ngx-translate/core": ">=11.0.0", "chart.js": ">=2.5.0", "core-js": ">=2.5.4", diff --git a/lib/process-services-cloud/package.json b/lib/process-services-cloud/package.json index 41d73bf4d6..0d25e5dbe9 100644 --- a/lib/process-services-cloud/package.json +++ b/lib/process-services-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services-cloud", "description": "Alfresco ADF process services cloud", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services-cloud.js", "repository": { @@ -25,9 +25,9 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.1.0", + "@alfresco/js-api": "3.2.0-beta6", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta3", + "@alfresco/adf-core": "3.2.0-beta6", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/process-services/package.json b/lib/process-services/package.json index beba6d7228..8b0073757d 100644 --- a/lib/process-services/package.json +++ b/lib/process-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services", "description": "Alfresco ADF process services", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services.js", "repository": { @@ -25,10 +25,10 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.1.0", + "@alfresco/js-api": "3.2.0-beta6", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta3", - "@alfresco/adf-content-services": "3.2.0-beta3", + "@alfresco/adf-core": "3.2.0-beta6", + "@alfresco/adf-content-services": "3.2.0-beta6", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", "hammerjs": ">=2.0.8", diff --git a/lib/testing/package.json b/lib/testing/package.json index e1f1ad5132..3e31054c0d 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,9 +1,9 @@ { "name": "@alfresco/adf-testing", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0", - "@alfresco/js-api": "3.1.0" + "@alfresco/js-api": "3.2.0-beta6" } } diff --git a/package.json b/package.json index 7c10a71e68..025c2a0b9f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alfresco-components", "description": "Alfresco Angular components", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "author": "Alfresco Software, Ltd.", "main": "./index.js", "scripts": { @@ -55,14 +55,14 @@ "process services-cloud" ], "dependencies": { - "@alfresco/adf-content-services": "3.2.0-beta3", - "@alfresco/adf-core": "3.2.0-beta3", - "@alfresco/adf-extensions": "3.2.0-beta3", - "@alfresco/adf-insights": "3.2.0-beta3", - "@alfresco/adf-process-services": "3.2.0-beta3", - "@alfresco/adf-process-services-cloud": "3.2.0-beta3", - "@alfresco/adf-testing": "3.2.0-beta3", - "@alfresco/js-api": "3.1.0", + "@alfresco/adf-content-services": "3.2.0-beta6", + "@alfresco/adf-core": "3.2.0-beta6", + "@alfresco/adf-extensions": "3.2.0-beta6", + "@alfresco/adf-insights": "3.2.0-beta6", + "@alfresco/adf-process-services": "3.2.0-beta6", + "@alfresco/adf-process-services-cloud": "3.2.0-beta6", + "@alfresco/adf-testing": "3.2.0-beta6", + "@alfresco/js-api": "3.2.0-beta6", "@angular/animations": "7.0.3", "@angular/cdk": "7.0.3", "@angular/common": "7.0.3", From b80655645380655bb6f031599a5cfaa3fa7a1a1e Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Mon, 15 Apr 2019 01:01:47 +0200 Subject: [PATCH 113/208] [no-issue] improve e2e timeout and names apps (#4604) * fix sso, change timeout, parallel * cange travis * split viewer test * timeot fix * move name apps in resources file * resources fix * resources fix * fix search default * fix sso test * fix test --- .travis.yml | 6 +- .../permissions/site-permissions.e2e.ts | 23 +- .../sso-download-directive-component.e2e.ts | 17 +- .../viewer-arcive.component.e2e.ts | 106 +++++ .../file-extensions/viewer-component.e2e.ts | 132 ++++++ .../viewer-excel.component.e2e.ts | 107 +++++ .../viewer-image.component.e2e.ts | 127 ++++++ .../viewer-powerpoint.component.e2e.ts | 108 +++++ .../viewer-text.component.e2e.ts | 109 +++++ .../viewer-word.component.e2e.ts | 108 +++++ e2e/core/viewer/viewer-component.e2e.ts | 389 ------------------ .../apps-section-cloud.e2e.ts | 7 +- .../edit-process-filters-component.e2e.ts | 3 +- .../edit-task-filters-component.e2e.ts | 3 +- .../people-group-cloud-component.e2e.ts | 11 +- .../process-custom-filters.e2e.ts | 25 +- .../process-filters-cloud.e2e.ts | 3 +- .../process-header-cloud.e2e.ts | 4 +- .../processList-cloud-component.e2e.ts | 9 +- .../start-process-cloud.e2e.ts | 17 +- .../start-task-custom-app-cloud.e2e.ts | 12 +- .../task-filters-cloud.e2e.ts | 3 +- .../task-header-cloud.e2e.ts | 3 +- .../task-list-properties.e2e.ts | 6 +- .../task-list-selection.e2e.ts | 3 +- .../tasks-custom-filters.e2e.ts | 3 +- .../process-attachmentList-actionMenu.e2e.ts | 4 +- .../components/search-sorting-picker.e2e.ts | 19 +- e2e/search/search-filters.e2e.ts | 2 +- e2e/search/search-multiselect.e2e.ts | 6 +- e2e/util/resources.js | 6 + .../bundle-process-services-cloud-scss.js | 1 - .../core/actions/identity/identity.service.ts | 10 +- package-lock.json | 23 ++ protractor.conf.js | 4 +- 35 files changed, 931 insertions(+), 488 deletions(-) create mode 100644 e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts create mode 100644 e2e/core/viewer/file-extensions/viewer-component.e2e.ts create mode 100644 e2e/core/viewer/file-extensions/viewer-excel.component.e2e.ts create mode 100644 e2e/core/viewer/file-extensions/viewer-image.component.e2e.ts create mode 100644 e2e/core/viewer/file-extensions/viewer-powerpoint.component.e2e.ts create mode 100644 e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts create mode 100644 e2e/core/viewer/file-extensions/viewer-word.component.e2e.ts delete mode 100644 e2e/core/viewer/viewer-component.e2e.ts diff --git a/.travis.yml b/.travis.yml index 66e0d36397..453161a096 100644 --- a/.travis.yml +++ b/.travis.yml @@ -141,7 +141,7 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "process-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder process-services --skip-lint --use-dist || exit 1;); + (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder process-services --skip-lint --use-dist || exit 1;); fi; - stage: e2e Test # Test content-services name: content-services @@ -150,14 +150,14 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "content-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder content-services --skip-lint --use-dist || exit 1;); + (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder content-services --skip-lint --use-dist || exit 1;); fi; - stage: e2e Test # Test search name: search script: AFFECTED_E2E="$(./scripts/affected-folder.sh -b $TRAVIS_BRANCH -f "e2e")"; AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; - if [[ $AFFECTED_LIBS =~ "content-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; + if [[ $AFFECTED_LIBS =~ "content-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder search --skip-lint --use-dist || exit 1;); fi; diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index b32946c7e9..57559bdb67 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -154,7 +154,6 @@ describe('Permissions Component', function () { }); afterAll(async (done) => { - await alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); await alfrescoJsApi.core.sitesApi.deleteSite(publicSite.entry.id); await alfrescoJsApi.core.sitesApi.deleteSite(privateSite.entry.id); @@ -164,7 +163,7 @@ describe('Permissions Component', function () { describe('Role Site Dropdown', function () { - beforeEach(async (done) => { + it('[C277002] Should display the Role Site dropdown', () => { loginPage.loginToContentServicesUsingUserModel(folderOwnerUser); @@ -186,25 +185,16 @@ describe('Permissions Component', function () { permissionsPage.searchUserOrGroup(consumerUser.getId()); permissionsPage.clickUserOrGroup(consumerUser.getFirstName()); permissionsPage.checkUserOrGroupIsAdded(consumerUser.getId()); - done(); - }); - - it('[C277002] Should display the Role Site dropdown', () => { expect(permissionsPage.getRoleCellValue(consumerUser.getId())).toEqual('SiteCollaborator'); permissionsPage.clickRoleDropdown(); expect(permissionsPage.getRoleDropdownOptions().count()).toBe(4); - expect(permissionsPage.getRoleDropdownOptions().get(0).getText()).toBe('SiteCollaborator'); - expect(permissionsPage.getRoleDropdownOptions().get(1).getText()).toBe('SiteConsumer'); - expect(permissionsPage.getRoleDropdownOptions().get(2).getText()).toBe('SiteContributor'); - expect(permissionsPage.getRoleDropdownOptions().get(3).getText()).toBe('SiteManager'); - }); }); @@ -222,7 +212,6 @@ describe('Permissions Component', function () { contentList.doubleClickRow('Site' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -244,7 +233,6 @@ describe('Permissions Component', function () { }); it('[C276997] Role SiteContributor', () => { - loginPage.loginToContentServicesUsingUserModel(contributorUser); navigationBarPage.openContentServicesFolder(siteFolder.entry.id); @@ -254,7 +242,6 @@ describe('Permissions Component', function () { contentList.doubleClickRow('Site' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -272,7 +259,6 @@ describe('Permissions Component', function () { contentServicesPage.uploadFile(testFileModel.location).checkContentIsDisplayed(testFileModel.name); uploadDialog.fileIsUploaded(testFileModel.name); - uploadDialog.clickOnCloseButton().dialogIsNotDisplayed(); }); @@ -288,7 +274,6 @@ describe('Permissions Component', function () { contentList.doubleClickRow('Site' + fileModel.name); viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); contentList.waitForTableBody(); @@ -296,7 +281,6 @@ describe('Permissions Component', function () { contentServicesPage.checkDeleteIsDisabled('Site' + fileModel.name); browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); - browser.controlFlow().execute(async () => { contentList.checkActionMenuIsNotDisplayed(); @@ -304,25 +288,20 @@ describe('Permissions Component', function () { contentServicesPage.metadataContent('Site' + fileModel.name); metadataViewPage.editIconIsDisplayed(); - await metadataViewPage.editIconClick(); metadataViewPage.editPropertyIconIsDisplayed('properties.cm:title'); - metadataViewPage.clickEditPropertyIcons('properties.cm:title'); metadataViewPage.enterPropertyText('properties.cm:title', 'newTitle'); - await metadataViewPage.clickUpdatePropertyIcon('properties.cm:title'); expect(metadataViewPage.getPropertyText('properties.cm:title')).toEqual('newTitle'); - metadataViewPage.clickCloseButton(); contentServicesPage.uploadFile(pngFileModel.location).checkContentIsDisplayed(pngFileModel.name); uploadDialog.fileIsUploaded(pngFileModel.name); - uploadDialog.clickOnCloseButton().dialogIsNotDisplayed(); }); diff --git a/e2e/content-services/sso/sso-download-directive-component.e2e.ts b/e2e/content-services/sso/sso-download-directive-component.e2e.ts index 61e781042e..44d81e4e9a 100644 --- a/e2e/content-services/sso/sso-download-directive-component.e2e.ts +++ b/e2e/content-services/sso/sso-download-directive-component.e2e.ts @@ -54,8 +54,20 @@ describe('SSO in ADF using ACS and AIS, Download Directive, Viewer, DocumentList this.alfrescoJsApi = new AlfrescoApi({ provider: 'ECM', - hostEcm: TestConfig.adf.url + hostEcm: TestConfig.adf.url, + authType: 'OAUTH', + oauth2: { + host: TestConfig.adf.hostSso, + clientId: 'alfresco', + scope: 'openid', + secret: '', + implicitFlow: false, + silentLogin: false, + redirectUri: '/', + redirectUriLogout: '/logout' + } }); + const downloadedPngFile = path.join(__dirname, 'downloads', pngFileModel.name); const downloadedMultipleFiles = path.join(__dirname, 'downloads', 'archive.zip'); const folderName = StringUtil.generateRandomString(5); @@ -65,8 +77,6 @@ describe('SSO in ADF using ACS and AIS, Download Directive, Viewer, DocumentList describe('SSO in ADF using ACS and AIS, implicit flow set', () => { beforeAll(async (done) => { - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - const apiService = new ApiService('alfresco', TestConfig.adf.url, TestConfig.adf.hostSso, 'ECM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -79,7 +89,6 @@ describe('SSO in ADF using ACS and AIS, Download Directive, Viewer, DocumentList folder = await uploadActions.createFolder(this.alfrescoJsApi, folderName, '-my-'); pdfUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, firstPdfFileModel.location, firstPdfFileModel.name, folder.entry.id); - pngUploadedFile = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileModel.location, pngFileModel.name, folder.entry.id); silentLogin = false; diff --git a/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts new file mode 100644 index 0000000000..744bce338a --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts @@ -0,0 +1,106 @@ +/*! + * @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 TestConfig = require('../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../util/constants'); +import resources = require('../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FolderModel } from '../../models/ACS/folderModel'; +import { AcsUserModel } from '../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + + const archiveFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.ARCHIVE_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.ARCHIVE_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + done(); + }); + + describe('Archive Folder Uploaded', () => { + let uploadedArchives; + let archiveFolderUploaded; + + beforeAll(async (done) => { + archiveFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, archiveFolderInfo.name, '-my-'); + + uploadedArchives = await uploadActions.uploadFolder(this.alfrescoJsApi, archiveFolderInfo.location, archiveFolderUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, archiveFolderUploaded.entry.id); + done(); + }); + + it('[C260517] Should be possible to open any Archive file', () => { + contentServicesPage.doubleClickRow('archive'); + + uploadedArchives.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); +}); diff --git a/e2e/core/viewer/file-extensions/viewer-component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-component.e2e.ts new file mode 100644 index 0000000000..59a140906c --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-component.e2e.ts @@ -0,0 +1,132 @@ +/*! + * @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 TestConfig = require('../../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; +import { FileModel } from '../../..//models/ACS/fileModel'; + +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; +import { NavigationBarPage } from '../../..//pages/adf/navigationBarPage'; + + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const navigationBarPage = new NavigationBarPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + let pngFileUploaded; + + const pngFileInfo = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + const otherFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.OTHER_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.OTHER_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + pngFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileInfo.location, pngFileInfo.name, site.entry.guid); + done(); + }); + + it('[C272813] Should be redirected to site when opening and closing a file in a site', () => { + loginPage.loginToContentServicesUsingUserModel(acsUser); + + navigationBarPage.goToSite(site); + contentServicesPage.checkAcsContainer(); + + viewerPage.viewFile(pngFileUploaded.entry.name); + + viewerPage.checkImgViewerIsDisplayed(); + + viewerPage.clickCloseButton(); + }); + + describe('Other Folder Uploaded', () => { + + let uploadedOthers; + let otherFolderUploaded; + + beforeAll(async (done) => { + otherFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, otherFolderInfo.name, '-my-'); + + uploadedOthers = await uploadActions.uploadFolder(this.alfrescoJsApi, otherFolderInfo.location, otherFolderUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, otherFolderUploaded.entry.id); + done(); + }); + + it('[C280012] Should be possible to open any other Document supported extension', () => { + contentServicesPage.doubleClickRow('other'); + + uploadedOthers.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); + +}); diff --git a/e2e/core/viewer/file-extensions/viewer-excel.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-excel.component.e2e.ts new file mode 100644 index 0000000000..00a1ee95cd --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-excel.component.e2e.ts @@ -0,0 +1,107 @@ +/*! + * @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 TestConfig = require('../../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + + const excelFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.EXCEL_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.EXCEL_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + done(); + }); + describe('Excel Folder Uploaded', () => { + + let uploadedExcels; + let excelFolderUploaded; + + beforeAll(async (done) => { + excelFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, excelFolderInfo.name, '-my-'); + + uploadedExcels = await uploadActions.uploadFolder(this.alfrescoJsApi, excelFolderInfo.location, excelFolderUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, excelFolderUploaded.entry.id); + done(); + }); + + it('[C280008] Should be possible to open any Excel file', () => { + contentServicesPage.doubleClickRow('excel'); + + uploadedExcels.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); + +}); diff --git a/e2e/core/viewer/file-extensions/viewer-image.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-image.component.e2e.ts new file mode 100644 index 0000000000..d0bd51e737 --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-image.component.e2e.ts @@ -0,0 +1,127 @@ +/*! + * @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 TestConfig = require('../../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + + const imgFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.IMG_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.IMG_FOLDER.folder_location + }); + + const imgRenditionFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.IMG_RENDITION_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.IMG_RENDITION_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + done(); + }); + + describe('Image Folder Uploaded', () => { + + let uploadedImages, uploadedImgRenditionFolderInfo; + let imgFolderUploaded, imgFolderRenditionUploaded; + + beforeAll(async (done) => { + imgFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, imgFolderInfo.name, '-my-'); + + uploadedImages = await uploadActions.uploadFolder(this.alfrescoJsApi, imgFolderInfo.location, imgFolderUploaded.entry.id); + + imgFolderRenditionUploaded = await uploadActions.createFolder(this.alfrescoJsApi, imgRenditionFolderInfo.name, imgFolderUploaded.entry.id); + + uploadedImgRenditionFolderInfo = await uploadActions.uploadFolder(this.alfrescoJsApi, imgRenditionFolderInfo.location, imgFolderRenditionUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, imgFolderUploaded.entry.id); + done(); + }); + + it('[C279966] Should be possible to open any Image supported extension', () => { + contentServicesPage.doubleClickRow('images'); + + uploadedImages.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkImgViewerIsDisplayed(); + viewerPage.clickCloseButton(); + } + }); + + contentServicesPage.doubleClickRow('images-rendition'); + + uploadedImgRenditionFolderInfo.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); + +}); diff --git a/e2e/core/viewer/file-extensions/viewer-powerpoint.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-powerpoint.component.e2e.ts new file mode 100644 index 0000000000..897985610d --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-powerpoint.component.e2e.ts @@ -0,0 +1,108 @@ +/*! + * @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 TestConfig = require('../../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + + const pptFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.PPT_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.PPT_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + done(); + }); + + describe('PowerPoint Folder Uploaded', () => { + + let uploadedPpt; + let pptFolderUploaded; + + beforeAll(async (done) => { + pptFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, pptFolderInfo.name, '-my-'); + + uploadedPpt = await uploadActions.uploadFolder(this.alfrescoJsApi, pptFolderInfo.location, pptFolderUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, pptFolderUploaded.entry.id); + done(); + }); + + it('[C280009] Should be possible to open any PowerPoint file', () => { + contentServicesPage.doubleClickRow('ppt'); + + uploadedPpt.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); + +}); diff --git a/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts new file mode 100644 index 0000000000..9db136c4f3 --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts @@ -0,0 +1,109 @@ +/*! + * @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 TestConfig = require('../../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + + const textFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.TEXT_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.TEXT_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + done(); + }); + + describe('Text Folder Uploaded', () => { + + let uploadedTexts; + let textFolderUploaded; + + beforeAll(async (done) => { + textFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, textFolderInfo.name, '-my-'); + + uploadedTexts = await uploadActions.uploadFolder(this.alfrescoJsApi, textFolderInfo.location, textFolderUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, textFolderUploaded.entry.id); + done(); + }); + + it('[C280010] Should be possible to open any Text file', () => { + contentServicesPage.doubleClickRow('text'); + + uploadedTexts.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); + + +}); diff --git a/e2e/core/viewer/file-extensions/viewer-word.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-word.component.e2e.ts new file mode 100644 index 0000000000..e322900bdd --- /dev/null +++ b/e2e/core/viewer/file-extensions/viewer-word.component.e2e.ts @@ -0,0 +1,108 @@ +/*! + * @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 TestConfig = require('../../../test.config'); + +import { LoginPage } from '@alfresco/adf-testing'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; + +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); +import { StringUtil } from '@alfresco/adf-testing'; + +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; + +describe('Viewer', () => { + + const viewerPage = new ViewerPage(); + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const uploadActions = new UploadActions(); + let site; + const acsUser = new AcsUserModel(); + + const wordFolderInfo = new FolderModel({ + 'name': resources.Files.ADF_DOCUMENTS.WORD_FOLDER.folder_name, + 'location': resources.Files.ADF_DOCUMENTS.WORD_FOLDER.folder_location + }); + + beforeAll(async (done) => { + + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + site = await this.alfrescoJsApi.core.sitesApi.createSite({ + title: StringUtil.generateRandomString(8), + visibility: 'PUBLIC' + }); + + await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { + id: acsUser.id, + role: CONSTANTS.CS_USER_ROLES.MANAGER + }); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + done(); + }); + + describe('Word Folder Uploaded', () => { + + let uploadedWords; + let wordFolderUploaded; + + beforeAll(async (done) => { + wordFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, wordFolderInfo.name, '-my-'); + + uploadedWords = await uploadActions.uploadFolder(this.alfrescoJsApi, wordFolderInfo.location, wordFolderUploaded.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + contentServicesPage.goToDocumentList(); + + done(); + }); + + afterAll(async (done) => { + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, wordFolderUploaded.entry.id); + done(); + }); + + it('[C280011] Should be possible to open any Word file', () => { + contentServicesPage.doubleClickRow('word'); + + uploadedWords.forEach((currentFile) => { + if (currentFile.entry.name !== '.DS_Store') { + contentServicesPage.doubleClickRow(currentFile.entry.name); + viewerPage.checkFileIsLoaded(); + viewerPage.clickCloseButton(); + } + }); + }); + + }); + +}); diff --git a/e2e/core/viewer/viewer-component.e2e.ts b/e2e/core/viewer/viewer-component.e2e.ts deleted file mode 100644 index 5aaf79da2a..0000000000 --- a/e2e/core/viewer/viewer-component.e2e.ts +++ /dev/null @@ -1,389 +0,0 @@ -/*! - * @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 TestConfig = require('../../test.config'); - -import { LoginPage } from '@alfresco/adf-testing'; -import { ViewerPage } from '../../pages/adf/viewerPage'; -import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; - -import CONSTANTS = require('../../util/constants'); -import resources = require('../../util/resources'); -import { StringUtil } from '@alfresco/adf-testing'; - -import { FileModel } from '../../models/ACS/fileModel'; -import { FolderModel } from '../../models/ACS/folderModel'; -import { AcsUserModel } from '../../models/ACS/acsUserModel'; - -import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { UploadActions } from '../../actions/ACS/upload.actions'; - -describe('Viewer', () => { - - const viewerPage = new ViewerPage(); - const navigationBarPage = new NavigationBarPage(); - const loginPage = new LoginPage(); - const contentServicesPage = new ContentServicesPage(); - const uploadActions = new UploadActions(); - let site; - const acsUser = new AcsUserModel(); - let pngFileUploaded; - - const pngFileInfo = new FileModel({ - 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, - 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location - }); - - const archiveFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.ARCHIVE_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.ARCHIVE_FOLDER.folder_location - }); - - const excelFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.EXCEL_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.EXCEL_FOLDER.folder_location - }); - - const otherFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.OTHER_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.OTHER_FOLDER.folder_location - }); - - const pptFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.PPT_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.PPT_FOLDER.folder_location - }); - - const textFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.TEXT_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.TEXT_FOLDER.folder_location - }); - - const wordFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.WORD_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.WORD_FOLDER.folder_location - }); - - const imgFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.IMG_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.IMG_FOLDER.folder_location - }); - - const imgRenditionFolderInfo = new FolderModel({ - 'name': resources.Files.ADF_DOCUMENTS.IMG_RENDITION_FOLDER.folder_name, - 'location': resources.Files.ADF_DOCUMENTS.IMG_RENDITION_FOLDER.folder_location - }); - - beforeAll(async (done) => { - - this.alfrescoJsApi = new AlfrescoApi({ - provider: 'ECM', - hostEcm: TestConfig.adf.url - }); - - await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); - - site = await this.alfrescoJsApi.core.sitesApi.createSite({ - title: StringUtil.generateRandomString(8), - visibility: 'PUBLIC' - }); - - await this.alfrescoJsApi.core.sitesApi.addSiteMember(site.entry.id, { - id: acsUser.id, - role: CONSTANTS.CS_USER_ROLES.MANAGER - }); - - await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - - pngFileUploaded = await uploadActions.uploadFile(this.alfrescoJsApi, pngFileInfo.location, pngFileInfo.name, site.entry.guid); - done(); - }); - - it('[C272813] Should be redirected to site when opening and closing a file in a site', () => { - loginPage.loginToContentServicesUsingUserModel(acsUser); - - navigationBarPage.goToSite(site); - contentServicesPage.checkAcsContainer(); - - viewerPage.viewFile(pngFileUploaded.entry.name); - - viewerPage.checkImgViewerIsDisplayed(); - - viewerPage.clickCloseButton(); - }); - - describe('Archive Folder Uploaded', () => { - let uploadedArchives; - let archiveFolderUploaded; - - beforeAll(async (done) => { - archiveFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, archiveFolderInfo.name, '-my-'); - - uploadedArchives = await uploadActions.uploadFolder(this.alfrescoJsApi, archiveFolderInfo.location, archiveFolderUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, archiveFolderUploaded.entry.id); - done(); - }); - - it('[C260517] Should be possible to open any Archive file', () => { - contentServicesPage.doubleClickRow('archive'); - - uploadedArchives.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - - describe('Excel Folder Uploaded', () => { - - let uploadedExcels; - let excelFolderUploaded; - - beforeAll(async (done) => { - excelFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, excelFolderInfo.name, '-my-'); - - uploadedExcels = await uploadActions.uploadFolder(this.alfrescoJsApi, excelFolderInfo.location, excelFolderUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, excelFolderUploaded.entry.id); - done(); - }); - - it('[C280008] Should be possible to open any Excel file', () => { - contentServicesPage.doubleClickRow('excel'); - - uploadedExcels.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - - describe('PowerPoint Folder Uploaded', () => { - - let uploadedPpt; - let pptFolderUploaded; - - beforeAll(async (done) => { - pptFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, pptFolderInfo.name, '-my-'); - - uploadedPpt = await uploadActions.uploadFolder(this.alfrescoJsApi, pptFolderInfo.location, pptFolderUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, pptFolderUploaded.entry.id); - done(); - }); - - it('[C280009] Should be possible to open any PowerPoint file', () => { - contentServicesPage.doubleClickRow('ppt'); - - uploadedPpt.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - - describe('Text Folder Uploaded', () => { - - let uploadedTexts; - let textFolderUploaded; - - beforeAll(async (done) => { - textFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, textFolderInfo.name, '-my-'); - - uploadedTexts = await uploadActions.uploadFolder(this.alfrescoJsApi, textFolderInfo.location, textFolderUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, textFolderUploaded.entry.id); - done(); - }); - - it('[C280010] Should be possible to open any Text file', () => { - contentServicesPage.doubleClickRow('text'); - - uploadedTexts.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - - describe('Word Folder Uploaded', () => { - - let uploadedWords; - let wordFolderUploaded; - - beforeAll(async (done) => { - wordFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, wordFolderInfo.name, '-my-'); - - uploadedWords = await uploadActions.uploadFolder(this.alfrescoJsApi, wordFolderInfo.location, wordFolderUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, wordFolderUploaded.entry.id); - done(); - }); - - it('[C280011] Should be possible to open any Word file', () => { - contentServicesPage.doubleClickRow('word'); - - uploadedWords.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - - describe('Other Folder Uploaded', () => { - - let uploadedOthers; - let otherFolderUploaded; - - beforeAll(async (done) => { - otherFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, otherFolderInfo.name, '-my-'); - - uploadedOthers = await uploadActions.uploadFolder(this.alfrescoJsApi, otherFolderInfo.location, otherFolderUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, otherFolderUploaded.entry.id); - done(); - }); - - it('[C280012] Should be possible to open any other Document supported extension', () => { - contentServicesPage.doubleClickRow('other'); - - uploadedOthers.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - - describe('Image Folder Uploaded', () => { - - let uploadedImages, uploadedImgRenditionFolderInfo; - let imgFolderUploaded, imgFolderRenditionUploaded; - - beforeAll(async (done) => { - imgFolderUploaded = await uploadActions.createFolder(this.alfrescoJsApi, imgFolderInfo.name, '-my-'); - - uploadedImages = await uploadActions.uploadFolder(this.alfrescoJsApi, imgFolderInfo.location, imgFolderUploaded.entry.id); - - imgFolderRenditionUploaded = await uploadActions.createFolder(this.alfrescoJsApi, imgRenditionFolderInfo.name, imgFolderUploaded.entry.id); - - uploadedImgRenditionFolderInfo = await uploadActions.uploadFolder(this.alfrescoJsApi, imgRenditionFolderInfo.location, imgFolderRenditionUploaded.entry.id); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - - done(); - }); - - afterAll(async (done) => { - await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, imgFolderUploaded.entry.id); - done(); - }); - - it('[C279966] Should be possible to open any Image supported extension', () => { - contentServicesPage.doubleClickRow('images'); - - uploadedImages.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkImgViewerIsDisplayed(); - viewerPage.clickCloseButton(); - } - }); - - contentServicesPage.doubleClickRow('images-rendition'); - - uploadedImgRenditionFolderInfo.forEach((currentFile) => { - if (currentFile.entry.name !== '.DS_Store') { - contentServicesPage.doubleClickRow(currentFile.entry.name); - viewerPage.checkFileIsLoaded(); - viewerPage.clickCloseButton(); - } - }); - }); - - }); - -}); diff --git a/e2e/process-services-cloud/apps-section-cloud.e2e.ts b/e2e/process-services-cloud/apps-section-cloud.e2e.ts index b1442d00b5..6d0db57d14 100644 --- a/e2e/process-services-cloud/apps-section-cloud.e2e.ts +++ b/e2e/process-services-cloud/apps-section-cloud.e2e.ts @@ -20,6 +20,7 @@ import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Applications list', () => { @@ -27,7 +28,7 @@ describe('Applications list', () => { const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); const appListCloudPage = new AppListCloudPage(); - const appName = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; it('[C289910] Should the app be displayed on dashboard when is deployed on APS', () => { settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity); @@ -35,8 +36,8 @@ describe('Applications list', () => { loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudPage.checkApsContainer(); - appListCloudPage.checkAppIsDisplayed(appName); - appListCloudPage.goToApp(appName); + appListCloudPage.checkAppIsDisplayed(simpleApp); + appListCloudPage.goToApp(simpleApp); }); diff --git a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts index 9e7d3728fe..97cf7bd761 100644 --- a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts @@ -23,6 +23,7 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Edit process filters cloud', () => { @@ -35,7 +36,7 @@ describe('Edit process filters cloud', () => { const processCloudDemoPage = new ProcessCloudDemoPage(); let silentLogin; - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; beforeAll(async () => { silentLogin = false; diff --git a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts index a014dfd285..60ec7ceb9e 100644 --- a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts @@ -22,6 +22,7 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Edit task filters cloud', () => { @@ -34,7 +35,7 @@ describe('Edit task filters cloud', () => { let tasksService: TasksService; let silentLogin; - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; const completedTaskName = StringUtil.generateRandomString(), assignedTaskName = StringUtil.generateRandomString(); let assignedTask; diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index 888a223beb..ab2a36a925 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -24,6 +24,7 @@ import { GroupCloudComponentPage, PeopleCloudComponentPage } from '@alfresco/adf import { browser } from 'protractor'; import { LoginSSOPage, IdentityService, GroupIdentityService, RolesService, ApiService } from '@alfresco/adf-testing'; import CONSTANTS = require('../util/constants'); +import resources = require('../util/resources'); describe('People Groups Cloud Component', () => { @@ -61,7 +62,7 @@ describe('People Groups Cloud Component', () => { identityService = new IdentityService(apiService); rolesService = new RolesService(apiService); groupIdentityService = new GroupIdentityService(apiService); - clientId = await groupIdentityService.getClientIdByApplicationName('simple-app'); + clientId = await groupIdentityService.getClientIdByApplicationName(resources.ACTIVITI7_APPS.SIMPLE_APP); groupActiviti = await groupIdentityService.createIdentityGroup(); clientActivitiAdminRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_ADMIN); clientActivitiUserRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_USER); @@ -269,7 +270,7 @@ describe('People Groups Cloud Component', () => { it('[C305041] Should filter the People Single Selection with the Application name filter', () => { peopleGroupCloudComponentPage.checkPeopleCloudSingleSelectionIsSelected(); peopleGroupCloudComponentPage.clickPeopleFilerByApp(); - peopleGroupCloudComponentPage.enterPeopleAppName('simple-app'); + peopleGroupCloudComponentPage.enterPeopleAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); peopleCloudComponent.searchAssignee(`${activitiUser.firstName}`); peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); @@ -280,7 +281,7 @@ describe('People Groups Cloud Component', () => { it('[C305041] Should filter the People Multiple Selection with the Application name filter', () => { peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); peopleGroupCloudComponentPage.clickPeopleFilerByApp(); - peopleGroupCloudComponentPage.enterPeopleAppName('simple-app'); + peopleGroupCloudComponentPage.enterPeopleAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); peopleCloudComponent.searchAssignee(`${apsUser.firstName}`); peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); @@ -298,7 +299,7 @@ describe('People Groups Cloud Component', () => { it('[C305041] Should filter the Groups Single Selection with the Application name filter', () => { peopleGroupCloudComponentPage.clickGroupCloudSingleSelection(); peopleGroupCloudComponentPage.clickGroupFilerByApp(); - peopleGroupCloudComponentPage.enterGroupAppName('simple-app'); + peopleGroupCloudComponentPage.enterGroupAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); groupCloudComponentPage.searchGroups(`${groupActiviti.name}`); groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); @@ -308,7 +309,7 @@ describe('People Groups Cloud Component', () => { it('[C305041] Should filter the Groups Multiple Selection with the Application name filter', () => { peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); peopleGroupCloudComponentPage.clickGroupFilerByApp(); - peopleGroupCloudComponentPage.enterGroupAppName('simple-app'); + peopleGroupCloudComponentPage.enterGroupAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); groupCloudComponentPage.searchGroups(`${groupAps.name}`); groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); groupCloudComponentPage.selectGroupFromList(`${groupAps.name}`); diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index d4e3b69ccb..59e81da33e 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -24,6 +24,7 @@ import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/p import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; +import resources = require('../util/resources'); import { browser, protractor } from 'protractor'; @@ -45,7 +46,7 @@ describe('Process list cloud', () => { let silentLogin; let completedProcess, runningProcessInstance, switchProcessInstance, noOfApps; - const simpleApp = 'candidateuserapp'; + const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; beforeAll(async () => { silentLogin = false; @@ -85,25 +86,25 @@ describe('Process list cloud', () => { await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); processDefinitionService = new ProcessDefinitionsService(apiService); - const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(candidateuserapp); processInstancesService = new ProcessInstancesService(apiService); - await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - runningProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - switchProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); + runningProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); + switchProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); - completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); queryService = new QueryService(apiService); - const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, simpleApp); + const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, candidateuserapp); tasksService = new TasksService(apiService); - const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); - await tasksService.completeTask(claimedTask.entry.id, simpleApp); + const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, candidateuserapp); + await tasksService.completeTask(claimedTask.entry.id, candidateuserapp); }); beforeEach((done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); - appListCloudComponent.goToApp(simpleApp); + appListCloudComponent.goToApp(candidateuserapp); tasksCloudDemoPage.taskListCloudComponent().checkTaskListIsLoaded(); processCloudDemoPage.clickOnProcessFilters(); done(); @@ -172,7 +173,7 @@ describe('Process list cloud', () => { expect(processCloudDemoPage.editProcessFilterCloudComponent().checkAppNamesAreUnique()).toBe(true); browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); processCloudDemoPage.editProcessFilterCloudComponent().setStatusFilterDropDown('RUNNING') - .setAppNameDropDown(simpleApp).setProcessInstanceId(runningProcessInstance.entry.id); + .setAppNameDropDown(candidateuserapp).setProcessInstanceId(runningProcessInstance.entry.id); processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(runningProcessInstance.entry.id); expect(processCloudDemoPage.editProcessFilterCloudComponent().getNumberOfAppNameOptions()).toBe(noOfApps); @@ -187,7 +188,7 @@ describe('Process list cloud', () => { expect(processCloudDemoPage.editProcessFilterCloudComponent().getProcessInstanceId()).toEqual(runningProcessInstance.entry.id); processCloudDemoPage.editProcessFilterCloudComponent().setStatusFilterDropDown('RUNNING') - .setAppNameDropDown(simpleApp).setProcessInstanceId(switchProcessInstance.entry.id); + .setAppNameDropDown(candidateuserapp).setProcessInstanceId(switchProcessInstance.entry.id); processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedById(switchProcessInstance.entry.id); processCloudDemoPage.editProcessFilterCloudComponent().clickSaveAsButton(); diff --git a/e2e/process-services-cloud/process-filters-cloud.e2e.ts b/e2e/process-services-cloud/process-filters-cloud.e2e.ts index fe1707ec95..d345e942d7 100644 --- a/e2e/process-services-cloud/process-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-filters-cloud.e2e.ts @@ -24,6 +24,7 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { AppListCloudPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Process filters cloud', () => { @@ -42,7 +43,7 @@ describe('Process filters cloud', () => { let silentLogin; let runningProcess, completedProcess; - const simpleApp = 'candidateuserapp'; + const simpleApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; beforeAll(async () => { diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index 30a508265b..ba178a3b51 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -27,12 +27,14 @@ import { ProcessHeaderCloudPage } from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Process Header cloud component', () => { describe('Process Header cloud component', () => { - const simpleApp = 'simple-app', subProcessApp = 'subprocess-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const subProcessApp = resources.ACTIVITI7_APPS.SUB_PROCESS_APP; const formatDate = 'DD-MM-YYYY'; const processHeaderCloudPage = new ProcessHeaderCloudPage(); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index 14493237b4..635d306e09 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -25,6 +25,7 @@ import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { ProcessListCloudConfiguration } from './processListCloud.config'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Process list cloud', () => { @@ -40,7 +41,7 @@ describe('Process list cloud', () => { let processInstancesService: ProcessInstancesService; let silentLogin; - const simpleApp = 'candidateuserapp'; + const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; let jsonFile; let runningProcess; @@ -55,9 +56,9 @@ describe('Process list cloud', () => { await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); processDefinitionService = new ProcessDefinitionsService(apiService); - const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + const processDefinition = await processDefinitionService.getProcessDefinitions(candidateuserapp); processInstancesService = new ProcessInstancesService(apiService); - runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); }); @@ -72,7 +73,7 @@ describe('Process list cloud', () => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); - appListCloudComponent.goToApp(simpleApp); + appListCloudComponent.goToApp(candidateuserapp); processCloudDemoPage.clickOnProcessFilters(); processCloudDemoPage.runningProcessesFilter().checkProcessFilterIsDisplayed(); processCloudDemoPage.runningProcessesFilter().clickProcessFilter(); diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index b4f164f925..e64d1d5476 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -22,6 +22,7 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Start Process', () => { @@ -38,7 +39,7 @@ describe('Start Process', () => { const requiredError = 'Process Name is required', requiredProcessError = 'Process Definition is required'; const processDefinition = 'processwithvariables'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - const appName = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; let silentLogin; beforeAll((done) => { @@ -58,8 +59,8 @@ describe('Start Process', () => { }); it('[C291857] Should be possible to cancel a process', () => { - appListCloudComponent.checkAppIsDisplayed(appName); - appListCloudComponent.goToApp(appName); + appListCloudComponent.checkAppIsDisplayed(simpleApp); + appListCloudComponent.goToApp(simpleApp); processCloudDemoPage.openNewProcessForm(); startProcessPage.clearField(startProcessPage.processNameInput); startProcessPage.blur(startProcessPage.processNameInput); @@ -69,7 +70,7 @@ describe('Start Process', () => { }); it('[C291842] Should be displayed an error message if process name exceed 255 characters', () => { - appListCloudComponent.goToApp(appName); + appListCloudComponent.goToApp(simpleApp); processCloudDemoPage.openNewProcessForm(); startProcessPage.enterProcessName(processName255Characters); startProcessPage.checkStartProcessButtonIsEnabled(); @@ -81,8 +82,8 @@ describe('Start Process', () => { }); it('[C291860] Should be able to start a process', () => { - appListCloudComponent.checkAppIsDisplayed(appName); - appListCloudComponent.goToApp(appName); + appListCloudComponent.checkAppIsDisplayed(simpleApp); + appListCloudComponent.goToApp(simpleApp); processCloudDemoPage.openNewProcessForm(); startProcessPage.clearField(startProcessPage.processNameInput); @@ -98,8 +99,8 @@ describe('Start Process', () => { }); it('[C291860] Should be able to start a process with variables', () => { - appListCloudComponent.checkAppIsDisplayed(appName); - appListCloudComponent.goToApp(appName); + appListCloudComponent.checkAppIsDisplayed(simpleApp); + appListCloudComponent.goToApp(simpleApp); processCloudDemoPage.openNewProcessForm(); startProcessPage.clearField(startProcessPage.processNameInput); diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 4ec50ac6dc..8f90db8838 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -24,6 +24,7 @@ import { } from '@alfresco/adf-testing'; import { browser } from 'protractor'; import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; +import resources = require('../util/resources'); describe('Start Task', () => { @@ -45,7 +46,8 @@ describe('Start Task', () => { const requiredError = 'Field required'; const dateValidationError = 'Date format DD/MM/YYYY'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - const appName = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + let silentLogin, activitiUser; let tasksService: TasksService; let identityService: IdentityService; @@ -68,8 +70,8 @@ describe('Start Task', () => { afterAll(async (done) => { const tasks = [ standaloneTaskName, unassignedTaskName, reassignTaskName ]; for (let i = 0; i < tasks.length; i++) { - const taskId = await tasksService.getTaskId(tasks[i], appName); - await tasksService.deleteTask(taskId, appName); + const taskId = await tasksService.getTaskId(tasks[i], simpleApp); + await tasksService.deleteTask(taskId, simpleApp); } await identityService.deleteIdentityUser(activitiUser.idIdentityService); done(); @@ -78,8 +80,8 @@ describe('Start Task', () => { beforeEach((done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); - appListCloudComponent.checkAppIsDisplayed(appName); - appListCloudComponent.goToApp(appName); + appListCloudComponent.checkAppIsDisplayed(simpleApp); + appListCloudComponent.goToApp(simpleApp); tasksCloudDemoPage.taskListCloudComponent().getDataTable().waitForTableBody(); done(); }); diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index 87655aace6..2faf69a557 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -21,6 +21,7 @@ import { LoginSSOPage, TasksService, ApiService, SettingsPage, AppListCloudPage, import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Task filters cloud', () => { @@ -35,7 +36,7 @@ describe('Task filters cloud', () => { let silentLogin; const newTask = StringUtil.generateRandomString(5), completedTask = StringUtil.generateRandomString(5); - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; beforeAll(() => { silentLogin = false; diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index 996ca06e90..793931c7f1 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -25,13 +25,14 @@ import { LoginSSOPage, SettingsPage, AppListCloudPage, TaskHeaderCloudPage, Task import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { browser } from 'protractor'; import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; +import resources = require('../util/resources'); describe('Task Header cloud component', () => { const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const basicCreatedTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(); let basicCreatedTask, basicCreatedDate, completedTask, completedCreatedDate, subTask, subTaskCreatedDate; - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; const priority = 30, description = 'descriptionTask', formatDate = 'DD-MM-YYYY'; const taskHeaderCloudPage = new TaskHeaderCloudPage(); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index 29f896f039..0643f96da9 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -31,6 +31,7 @@ import { DateUtil } from '../util/dateUtil'; import { NotificationPage } from '../pages/adf/notificationPage'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Edit task filters and task list properties', () => { @@ -49,8 +50,9 @@ describe('Edit task filters and task list properties', () => { const notificationPage = new NotificationPage(); let silentLogin; - const simpleApp = 'simple-app'; - const candidateUserApp = 'candidateuserapp'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const candidateUserApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; + const noTasksFoundMessage = 'No Tasks Found'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let createdTask, notAssigned, notDisplayedTask, processDefinition, processInstance, priorityTask, subTask; diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index bf3a95239c..0d5ab39efa 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -23,6 +23,7 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { AppListCloudPage } from '@alfresco/adf-testing'; import { StringUtil } from '@alfresco/adf-testing'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Task list cloud - selection', () => { @@ -36,7 +37,7 @@ describe('Task list cloud - selection', () => { let tasksService: TasksService; let silentLogin; - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const noOfTasks = 3; let response; diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index 09990a189e..34d90047e5 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -23,6 +23,7 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { AppListCloudPage } from '@alfresco/adf-testing'; import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Task filters cloud', () => { @@ -40,7 +41,7 @@ describe('Task filters cloud', () => { let silentLogin; const createdTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(), assignedTaskName = StringUtil.generateRandomString(), deletedTaskName = StringUtil.generateRandomString(); - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let assignedTask, deletedTask, suspendedTasks; const orderByNameAndPriority = ['cCreatedTask', 'dCreatedTask', 'eCreatedTask']; diff --git a/e2e/process-services/process-attachmentList-actionMenu.e2e.ts b/e2e/process-services/process-attachmentList-actionMenu.e2e.ts index 36d237c871..cc7ffb3e07 100644 --- a/e2e/process-services/process-attachmentList-actionMenu.e2e.ts +++ b/e2e/process-services/process-attachmentList-actionMenu.e2e.ts @@ -116,7 +116,7 @@ describe('Attachment list action menu for processes', () => { viewerPage.checkFileNameIsDisplayed(pngFile.name); viewerPage.clickCloseButton(); - browser.sleep(20000); + browser.sleep(10000); processFiltersPage.clickRunningFilterButton(); processFiltersPage.selectFromProcessList(processName.active); @@ -141,7 +141,7 @@ describe('Attachment list action menu for processes', () => { attachmentListPage.clickAttachFileButton(pngFile.location); processDetailsPage.clickCancelProcessButton(); - browser.sleep(20000); + browser.sleep(10000); processFiltersPage.clickCompletedFilterButton(); processDetailsPage.checkProcessTitleIsDisplayed(); diff --git a/e2e/search/components/search-sorting-picker.e2e.ts b/e2e/search/components/search-sorting-picker.e2e.ts index 0d2bcf9332..0daf3601f9 100644 --- a/e2e/search/components/search-sorting-picker.e2e.ts +++ b/e2e/search/components/search-sorting-picker.e2e.ts @@ -269,12 +269,13 @@ describe('Search Sorting Picker', () => { configEditor.clickSearchConfiguration(); configEditor.clickClearButton(); jsonFile.sorting.options.push({ - 'key': 'Modified Date', - 'label': 'Modified Date', + 'key': 'createdByUser', + 'label': 'Author', 'type': 'FIELD', - 'field': 'cm:modified', + 'field': 'cm:creator', 'ascending': true }); + configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); configEditor.clickSaveButton(); @@ -283,16 +284,6 @@ describe('Search Sorting Picker', () => { .enterTextAndPressEnter(search); searchSortingPicker.checkSortingSelectorIsDisplayed(); - browser.controlFlow().execute(async () => { - const idList = await contentServices.getElementsDisplayedId(); - const numberOfElements = await contentServices.numberOfResultsDisplayed(); - - const nodeList = await nodeActions.getNodesDisplayed(this.alfrescoJsApi, idList, numberOfElements); - const modifiedDateList = []; - for (let i = 0; i < nodeList.length; i++) { - modifiedDateList.push(new Date(nodeList[i].entry.modifiedAt)); - } - expect(contentServices.checkElementsDateSortedAsc(modifiedDateList)).toBe(true); - }); + expect(searchResults.checkListIsOrderedByAuthorAsc()).toBe(true); }); }); diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index 47842d77e4..2a62c3291a 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -108,7 +108,7 @@ describe('Search Filters', () => { loginPage.loginToContentServicesUsingUserModel(acsUser); - await browser.driver.sleep(30000); // wait search index previous file/folder uploaded + await browser.driver.sleep(15000); // wait search index previous file/folder uploaded searchDialog.checkSearchIconIsVisible(); searchDialog.clickOnSearchIcon(); diff --git a/e2e/search/search-multiselect.e2e.ts b/e2e/search/search-multiselect.e2e.ts index f76105c9de..29bbc24abe 100644 --- a/e2e/search/search-multiselect.e2e.ts +++ b/e2e/search/search-multiselect.e2e.ts @@ -81,7 +81,7 @@ describe('Search Component - Multi-Select Facet', () => { txtFileSite = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, site.entry.guid); - await browser.driver.sleep(30000); + await browser.driver.sleep(15000); loginPage.loginToContentServicesUsingUserModel(acsUser); @@ -166,7 +166,7 @@ describe('Search Component - Multi-Select Facet', () => { jpgFile = await uploadActions.uploadFile(this.alfrescoJsApi, jpgFileInfo.location, jpgFileInfo.name, site.entry.guid); - await browser.driver.sleep(30000); + await browser.driver.sleep(15000); loginPage.loginToContentServicesUsingUserModel(userUploadingImg); @@ -220,7 +220,7 @@ describe('Search Component - Multi-Select Facet', () => { }); txtFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, '-my-'); - await browser.driver.sleep(30000); + await browser.driver.sleep(15000); loginPage.loginToContentServicesUsingUserModel(acsUser); diff --git a/e2e/util/resources.js b/e2e/util/resources.js index c1ec69a40d..6f33c63c1f 100644 --- a/e2e/util/resources.js +++ b/e2e/util/resources.js @@ -512,3 +512,9 @@ exports.Files = { } }; + +exports.ACTIVITI7_APPS = { + CANDIDATE_USER_APP : "candidateuserapp", + SIMPLE_APP : "simple-app", + SUB_PROCESS_APP : "subprocess-app" +}; diff --git a/lib/config/bundle-process-services-cloud-scss.js b/lib/config/bundle-process-services-cloud-scss.js index 043329a60a..28b65bd882 100644 --- a/lib/config/bundle-process-services-cloud-scss.js +++ b/lib/config/bundle-process-services-cloud-scss.js @@ -1,6 +1,5 @@ var Bundler = require('scss-bundle').Bundler; var writeFileSync = require('fs-extra').writeFileSync; -var mkdirpSync = require('fs-extra').mkdirpSync; new Bundler().Bundle('./lib/process-services-cloud/src/lib/styles/_index.scss', '**/*.scss').then(result => { writeFileSync('./lib/dist/process-services-cloud/_theming.scss', result.bundledContent); diff --git a/lib/testing/src/lib/core/actions/identity/identity.service.ts b/lib/testing/src/lib/core/actions/identity/identity.service.ts index 0c1e3a08e7..7aeae95dba 100644 --- a/lib/testing/src/lib/core/actions/identity/identity.service.ts +++ b/lib/testing/src/lib/core/actions/identity/identity.service.ts @@ -17,6 +17,7 @@ import { ApiService } from '../api.service'; import { UserModel } from '../../models/user.model'; +import { PersonBodyCreate } from '@alfresco/js-api'; export class IdentityService { @@ -37,7 +38,14 @@ export class IdentityService { async createIdentityUserAndSyncECMBPM(user: UserModel) { if (this.api.config.provider === 'ECM' || this.api.config.provider === 'ALL') { - await this.api.apiService.core.peopleApi.addPerson(user); + const createUser: PersonBodyCreate = <PersonBodyCreate> { + firstName: user.firstName, + lastName: user.lastName, + password: user.password, + email: user.email, + id: user.email + }; + await this.api.apiService.core.peopleApi.addPerson(createUser); } if (this.api.config.provider === 'BPM' || this.api.config.provider === 'ALL') { diff --git a/package-lock.json b/package-lock.json index 339e9db346..06149ed9bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9534,6 +9534,21 @@ "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", "dev": true }, + "jasmine-fail-fast": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jasmine-fail-fast/-/jasmine-fail-fast-2.0.0.tgz", + "integrity": "sha1-5dguaimiX2YsZA5MMnDC+acTh+c=", + "requires": { + "lodash": "3.10.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz", + "integrity": "sha1-k9UcZygopEFqEq9XIguoqHN+L7s=" + } + } + }, "jasmine-reporters": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.3.2.tgz", @@ -13943,6 +13958,14 @@ } } }, + "protractor-fail-fast": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/protractor-fail-fast/-/protractor-fail-fast-3.1.0.tgz", + "integrity": "sha512-OjuIFmY7hm5R/Msmioyg3aBevySpmpIgtm2TGUvMEqTzviPk/Fqd1HYmMjIQ+NzFMzrK+93LJa4civDvw1+hEg==", + "requires": { + "jasmine-fail-fast": "~2.0.0" + } + }, "protractor-html-reporter-2": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/protractor-html-reporter-2/-/protractor-html-reporter-2-1.0.4.tgz", diff --git a/protractor.conf.js b/protractor.conf.js index f241692646..9d7c062451 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -187,9 +187,11 @@ exports.config = { framework: 'jasmine2', + getPageTimeout: 60000, + jasmineNodeOpts: { showColors: true, - defaultTimeoutInterval: 90000, + defaultTimeoutInterval: 60000, print: function () { } }, From 5e9cbe5690bc6adcb52f672c26f5adf082cd374c Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Mon, 15 Apr 2019 09:12:13 +0100 Subject: [PATCH 114/208] fix clean script --- scripts/clean-env.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scripts/clean-env.js b/scripts/clean-env.js index 56f0f3b5d5..6e74f7a1c3 100644 --- a/scripts/clean-env.js +++ b/scripts/clean-env.js @@ -25,23 +25,24 @@ async function main() { async function cleanRoot(alfrescoJsApi) { console.log('====== Clean Root ======'); - let rootNodes = await alfrescoJsApi.core.nodesApi.getNodeChildren('-root-'); + let rootNodes = await alfrescoJsApi.core.nodesApi.getNodeChildren('-root-', { + include: ['properties'] + }); for (let i = 0; i < rootNodes.list.entries.length; i++) { sleep(200); - console.log(rootNodes.list.entries[i].entry.id); + if(rootNodes.list.entries[i].entry.createdByUser.id !== 'System') { - try { - await alfrescoJsApi.core.nodesApi.deleteNode(rootNodes.list.entries[i].entry.id); - } catch (error) { - console.log('error' + JSON.stringify(error)); + try { + await alfrescoJsApi.core.nodesApi.deleteNode(rootNodes.list.entries[i].entry.id); + } catch (error) { + console.log('error' + JSON.stringify(error)); + } } } - - cleanRoot(alfrescoJsApi); } async function emptyTrashCan(alfrescoJsApi) { From 74e918d916ad87f58b091cb26dc3196ffb90c17b Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Tue, 16 Apr 2019 02:59:21 +0100 Subject: [PATCH 115/208] [ADF-4043] Demo Shell- Fix roles display (#4606) --- .../components/cloud/people-groups-cloud-demo.component.html | 4 ++-- .../components/cloud/people-groups-cloud-demo.component.scss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html index dda47274ac..60b41df399 100644 --- a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.html @@ -19,7 +19,7 @@ 'PEOPLE_GROUPS_CLOUD.ROLE_FILTER_MODE' | translate }}</mat-radio-button> </mat-radio-group> <mat-form-field *ngIf="!isPeopleAppNameSelected()" class="adf-preselect-value"> - <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.ROLE' | translate }} ['ACTIVITI_ADMIN', "ACTIVITI_USER"]</mat-label> + <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.ROLE' | translate }} ["ACTIVITI_ADMIN", "ACTIVITI_USER"]</mat-label> <input matInput (input)="setPeopleRoles($event)" data-automation-id="adf-people-roles-input" /> </mat-form-field> <mat-form-field *ngIf="isPeopleAppNameSelected()" class="adf-preselect-value"> @@ -76,7 +76,7 @@ 'PEOPLE_GROUPS_CLOUD.ROLE_FILTER_MODE' | translate }}</mat-radio-button> </mat-radio-group> <mat-form-field *ngIf="!isGroupAppNameSelected()" class="adf-preselect-value"> - <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.ROLE' | translate }} ['ACTIVITI_ADMIN', "ACTIVITI_USER"]</mat-label> + <mat-label>{{ 'PEOPLE_GROUPS_CLOUD.ROLE' | translate }} ["ACTIVITI_ADMIN", "ACTIVITI_USER"]</mat-label> <input matInput (input)="setGroupRoles($event)" data-automation-id="adf-group-roles-input"/> </mat-form-field> <mat-form-field *ngIf="isGroupAppNameSelected()" class="adf-preselect-value"> diff --git a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.scss index 3603ae7b91..99098e7061 100644 --- a/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.scss +++ b/demo-shell/src/app/components/cloud/people-groups-cloud-demo.component.scss @@ -16,7 +16,7 @@ .adf-preselect-value { margin-right: 15px; - min-width: 330px; + min-width: 25%; &-big { width:60%; From 36ce9bce0d2824a132710baa4dd48fc37093994a Mon Sep 17 00:00:00 2001 From: Cilibiu Bogdan <pionnegru@users.noreply.github.com> Date: Tue, 16 Apr 2019 12:59:37 +0300 Subject: [PATCH 116/208] [ADF-4400] Versioning - restore does not update the document list (#4605) * emit NodeInfo data on restore * update row data and cache on node update event * tests * fix metadatat e2e --- .../card-view/metadata-smoke-tests.e2e.ts | 2 +- .../version-list.component.spec.ts | 50 ++++++++++-- .../version-manager/version-list.component.ts | 8 +- .../datatable-cell.component.spec.ts | 76 +++++++++++++++++++ .../datatable/datatable-cell.component.ts | 7 +- 5 files changed, 130 insertions(+), 13 deletions(-) diff --git a/e2e/core/card-view/metadata-smoke-tests.e2e.ts b/e2e/core/card-view/metadata-smoke-tests.e2e.ts index 6282516d47..c98c2972ad 100644 --- a/e2e/core/card-view/metadata-smoke-tests.e2e.ts +++ b/e2e/core/card-view/metadata-smoke-tests.e2e.ts @@ -208,7 +208,7 @@ describe('Metadata component', () => { await viewerPage.clickCloseButton(); contentServicesPage.waitForTableBody(); - viewerPage.viewFile(resources.Files.ADF_DOCUMENTS.PNG.file_name); + viewerPage.viewFile('exampleText.png'); viewerPage.clickInfoButton(); viewerPage.checkInfoSideBarIsDisplayed(); metadataViewPage.clickOnPropertiesTab(); diff --git a/lib/content-services/version-manager/version-list.component.spec.ts b/lib/content-services/version-manager/version-list.component.spec.ts index 08350edfa4..2066ec17e2 100644 --- a/lib/content-services/version-manager/version-list.component.spec.ts +++ b/lib/content-services/version-manager/version-list.component.spec.ts @@ -16,7 +16,7 @@ */ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { VersionListComponent } from './version-list.component'; import { AlfrescoApiService, setupTestBed, CoreModule, AlfrescoApiServiceMock } from '@alfresco/adf-core'; @@ -71,6 +71,7 @@ describe('VersionListComponent', () => { component.node = <Node> { id: nodeId, allowableOperations: ['update'] }; spyOn(component, 'downloadContent').and.stub(); + spyOn(alfrescoApiService.nodesApi, 'getNodeInfo').and.returnValue(Promise.resolve(<Node> { id: 'nodeInfoId' })); }); it('should raise confirmation dialog on delete', () => { @@ -285,7 +286,43 @@ describe('VersionListComponent', () => { expect(spyOnRevertVersion).toHaveBeenCalledWith(nodeId, versionId, { majorVersion: true, comment: '' }); }); - it('should reload the version list after a version restore', (done) => { + it('should get node info after restoring the node', fakeAsync(() => { + fixture.detectChanges(); + component.versions = versionTest; + spyOn(alfrescoApiService.versionsApi, 'listVersionHistory') + .and.callFake(() => Promise.resolve({ list: { entries: versionTest } })); + + spyOn(alfrescoApiService.versionsApi, 'revertVersion') + .and.callFake(() => Promise.resolve(new VersionEntry( + { entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } }))); + + component.restore(versionId); + fixture.detectChanges(); + tick(); + + expect(alfrescoApiService.nodesApi.getNodeInfo).toHaveBeenCalled(); + })); + + it('should emit with node info data', fakeAsync(() => { + fixture.detectChanges(); + component.versions = versionTest; + spyOn(alfrescoApiService.versionsApi, 'listVersionHistory') + .and.callFake(() => Promise.resolve({ list: { entries: versionTest } })); + + spyOn(alfrescoApiService.versionsApi, 'revertVersion') + .and.callFake(() => Promise.resolve(new VersionEntry( + { entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } }))); + + spyOn(component.restored, 'emit'); + + component.restore(versionId); + fixture.detectChanges(); + tick(); + + expect(component.restored.emit).toHaveBeenCalledWith(<Node> { id: 'nodeInfoId' }); + })); + + it('should reload the version list after a version restore', fakeAsync(() => { fixture.detectChanges(); component.versions = versionTest; @@ -294,12 +331,11 @@ describe('VersionListComponent', () => { spyOn(alfrescoApiService.versionsApi, 'revertVersion').and.callFake(() => Promise.resolve()); component.restore(versionId); + fixture.detectChanges(); + tick(); - fixture.whenStable().then(() => { - expect(spyOnListVersionHistory).toHaveBeenCalledTimes(1); - done(); - }); - }); + expect(spyOnListVersionHistory).toHaveBeenCalledTimes(1); + })); }); describe('Actions buttons', () => { diff --git a/lib/content-services/version-manager/version-list.component.ts b/lib/content-services/version-manager/version-list.component.ts index 569a5fc40a..dfb1a902da 100644 --- a/lib/content-services/version-manager/version-list.component.ts +++ b/lib/content-services/version-manager/version-list.component.ts @@ -82,7 +82,13 @@ export class VersionListComponent implements OnChanges { if (this.canUpdate()) { this.versionsApi .revertVersion(this.node.id, versionId, { majorVersion: true, comment: '' }) - .then(() => this.onVersionRestored(this.node)); + .then(() => + this.alfrescoApi.nodesApi.getNodeInfo( + this.node.id, + { include: ['permissions', 'path', 'isFavorite', 'allowableOperations'] } + ) + ) + .then((node) => this.onVersionRestored(node)); } } diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts b/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts index 603f76c2ae..31a00170a6 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.spec.ts @@ -17,8 +17,16 @@ import { DateCellComponent } from './date-cell.component'; import { Subject } from 'rxjs'; +import { AlfrescoApiServiceMock, AppConfigService } from '@alfresco/adf-core'; +import { Node } from '@alfresco/js-api'; describe('DataTableCellComponent', () => { + let alfrescoApiService: AlfrescoApiServiceMock; + + beforeEach(() => { + alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null)); + }); + it('should use medium format by default', () => { const component = new DateCellComponent(null, null); expect(component.format).toBe('medium'); @@ -37,4 +45,72 @@ describe('DataTableCellComponent', () => { component.ngOnInit(); expect(component.format).toBe('longTime'); }); + + it('should update cell data on alfrescoApiService.nodeUpdated event', () => { + const component = new DateCellComponent( + null, + alfrescoApiService + ); + + component.column = { + key: 'name', + type: 'text' + }; + + component.row = <any> { + cache: { + name: 'some-name' + }, + node: { + entry: { + id: 'id', + name: 'test-name' + } + } + }; + + component.ngOnInit(); + + alfrescoApiService.nodeUpdated.next(<Node> { + id: 'id', + name: 'updated-name' + }); + + expect(component.row['node'].entry.name).toBe('updated-name'); + expect(component.row['cache'].name).toBe('updated-name'); + }); + + it('not should update cell data if ids don`t match', () => { + const component = new DateCellComponent( + null, + alfrescoApiService + ); + + component.column = { + key: 'name', + type: 'text' + }; + + component.row = <any> { + cache: { + name: 'some-name' + }, + node: { + entry: { + id: 'some-id', + name: 'test-name' + } + } + }; + + component.ngOnInit(); + + alfrescoApiService.nodeUpdated.next(<Node> { + id: 'id', + name: 'updated-name' + }); + + expect(component.row['node'].entry.name).not.toBe('updated-name'); + expect(component.row['cache'].name).not.toBe('updated-name'); + }); }); diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index 256f3bf2b2..fd39b6f8a4 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -85,10 +85,9 @@ export class DataTableCellComponent implements OnInit, OnDestroy { this.updateValue(); this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => { if (this.row) { - const { entry } = this.row['node']; - - if (entry === node) { - this.row['node'] = { entry }; + if (this.row['node'].entry.id === node.id) { + this.row['node'].entry = node; + this.row['cache'][this.column.key] = this.column.key.split('.').reduce((source, key) => source[key], node); this.updateValue(); } } From e1a0475dfc094b8ce3af27bdb4b6e34af54a4f2b Mon Sep 17 00:00:00 2001 From: Marouan Bentaleb <38426175+marouanbentaleb@users.noreply.github.com> Date: Tue, 16 Apr 2019 12:19:08 +0100 Subject: [PATCH 117/208] [ADF-4396] Automation test for cancelling new version upload (#4607) --- .../version/version-actions.e2e.ts | 25 ++++++++++++++++++- e2e/pages/adf/trashcanPage.ts | 5 ++++ .../core/pages/data-table-component.page.ts | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/e2e/content-services/version/version-actions.e2e.ts b/e2e/content-services/version/version-actions.e2e.ts index b41ee4b305..63bc6b18fe 100644 --- a/e2e/content-services/version/version-actions.e2e.ts +++ b/e2e/content-services/version/version-actions.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { by, element } from 'protractor'; +import { browser, by, element } from 'protractor'; import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; @@ -33,6 +33,8 @@ import { Util } from '../../util/util'; import path = require('path'); import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { BrowserVisibility } from '@alfresco/adf-testing'; +import { UploadDialog } from '../../pages/adf/dialog/uploadDialog'; +import { TrashcanPage } from '../../pages/adf/trashcanPage'; describe('Version component actions', () => { @@ -40,6 +42,7 @@ describe('Version component actions', () => { const contentServicesPage = new ContentServicesPage(); const versionManagePage = new VersionManagePage(); const navigationBarPage = new NavigationBarPage(); + const trashcanPage = new TrashcanPage(); const acsUser = new AcsUserModel(); @@ -147,4 +150,24 @@ describe('Version component actions', () => { versionManagePage.checkFileVersionExist('2.0'); }); + it('[C307033] Should be possible to cancel the upload of a new version', async () => { + await browser.refresh(); + contentServicesPage.versionManagerContent(txtFileModel.name); + browser.executeScript(' setTimeout(() => {document.querySelector(\'mat-icon[class*="adf-file-uploading-row__action"]\').click();}, 1000)'); + + versionManagePage.showNewVersionButton.click(); + versionManagePage.uploadNewVersionFile(fileModelVersionTwo.location); + versionManagePage.closeVersionDialog(); + + await expect(new UploadDialog().getTitleText()).toEqual('Upload canceled'); + + navigationBarPage.clickTrashcanButton(); + await trashcanPage.waitForTableBody(); + trashcanPage.checkTrashcanIsEmpty(); + + navigationBarPage.clickContentServicesButton(); + await contentServicesPage.waitForTableBody(); + contentServicesPage.checkContentIsDisplayed(txtFileModel.name); + }); + }); diff --git a/e2e/pages/adf/trashcanPage.ts b/e2e/pages/adf/trashcanPage.ts index 2f624ceeb2..d2c4deb860 100644 --- a/e2e/pages/adf/trashcanPage.ts +++ b/e2e/pages/adf/trashcanPage.ts @@ -24,6 +24,7 @@ export class TrashcanPage { rows = by.css('adf-document-list div[class*="adf-datatable-body"] div[class*="adf-datatable-row"]'); tableBody = element.all(by.css('adf-document-list div[class="adf-datatable-body"]')).first(); pagination = element(by.css('adf-pagination')); + emptyTrashcan = element(by.css('adf-empty-content')); numberOfResultsDisplayed() { return element.all(this.rows).count(); @@ -37,4 +38,8 @@ export class TrashcanPage { BrowserVisibility.waitUntilElementIsVisible(this.pagination); } + checkTrashcanIsEmpty() { + BrowserVisibility.waitUntilElementIsVisible(this.emptyTrashcan); + } + } diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index 0a67170f13..6f84a10efa 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -224,7 +224,7 @@ export class DataTableComponentPage { } checkContentIsDisplayed(columnName, columnValue) { - const row = this.getRow(columnName, columnValue); + const row = this.getRowElement(columnName, columnValue); BrowserVisibility.waitUntilElementIsVisible(row); return this; } From 550c0006c9590073b07dec291d86088a1b85f831 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Wed, 17 Apr 2019 12:23:36 +0300 Subject: [PATCH 118/208] [ADF-4394] - add suport for copy clipboard on JSON cell type (#4611) * [ADF-4394] - add suport for copy clipboard on JSON cell type * [ADF-4394] - lint * [ADF-4394] - change translation keys --- demo-shell/resources/i18n/en.json | 4 +--- .../datatable/datatable-cell.component.ts | 4 ++-- .../datatable/datatable.component.html | 1 + .../datatable/json-cell.component.scss | 4 ++++ .../datatable/json-cell.component.ts | 18 ++++++++++++++++-- lib/core/i18n/en.json | 5 ++++- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 5eb8d9adf4..17e745dcd7 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -179,9 +179,7 @@ "REPLACE_COLUMNS": "Replace columns", "LOAD_NODE": "Load Node", "MULTISELECT": "Multiselect", - "MULTISELECT_DESCRIPTION": "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items", - "CLICK_TO_COPY": "Click to copy", - "SUCCESS_COPY": "Text copied to clipboard" + "MULTISELECT_DESCRIPTION": "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items" }, "ANALYTICS_REPORT": { "NO_REPORT_MESSAGE": "No report selected. Choose a report from the list" diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index fd39b6f8a4..d1caf3c6dc 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -36,8 +36,8 @@ import { Node } from '@alfresco/js-api'; template: ` <ng-container> <span *ngIf="copyContent; else defaultCell" - adf-clipboard="DATATABLE.CLICK_TO_COPY" - [clipboard-notification]="'DATATABLE.SUCCESS_COPY'" + adf-clipboard="CLIPBOARD.CLICK_TO_COPY" + [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'" [attr.aria-label]="value$ | async" [title]="tooltip" class="adf-datatable-cell-value" diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index a1acc46132..f1d25f0b22 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -162,6 +162,7 @@ <div *ngSwitchCase="'json'" class="adf-cell-value" [attr.data-automation-id]="'text_' + data.getValue(row, col)"> <adf-json-cell + [copyContent]="col.copyContent" [data]="data" [column]="col" [row]="row"> diff --git a/lib/core/datatable/components/datatable/json-cell.component.scss b/lib/core/datatable/components/datatable/json-cell.component.scss index 69b91154fe..6ee7d6d74c 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.scss +++ b/lib/core/datatable/components/datatable/json-cell.component.scss @@ -2,3 +2,7 @@ white-space: pre-wrap; word-wrap: break-word; } + +.adf-datatable-cell-value { + position: relative; +} diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts index b0c2cacce2..5f459c05a0 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.ts +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation, Input } from '@angular/core'; import { DataTableCellComponent } from './datatable-cell.component'; @Component({ @@ -23,10 +23,20 @@ import { DataTableCellComponent } from './datatable-cell.component'; changeDetection: ChangeDetectionStrategy.OnPush, template: ` <ng-container> + <span *ngIf="copyContent; else defaultJsonTemplate" class="adf-datatable-cell-value"> + <pre + class="adf-datatable-json-cell" + [adf-clipboard]="'CLIPBOARD.CLICK_TO_COPY'" + [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"> + {{ value$ | async | json }} + </pre> + </span> + </ng-container> + <ng-template #defaultJsonTemplate> <span class="adf-datatable-cell-value"> <pre class="adf-datatable-json-cell">{{ value$ | async | json }}</pre> </span> - </ng-container> + </ng-template> `, styleUrls: ['./json-cell.component.scss'], encapsulation: ViewEncapsulation.None, @@ -34,6 +44,10 @@ import { DataTableCellComponent } from './datatable-cell.component'; }) export class JsonCellComponent extends DataTableCellComponent implements OnInit { + /** Enables/disables a Clipboard directive to allow copying of the cell's content. */ + @Input() + copyContent: boolean; + ngOnInit() { if (this.column && this.column.key && this.row && this.data) { this.value$.next(this.data.getValue(this.row, this.column)); diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json index 16807a4fcc..992c958be8 100644 --- a/lib/core/i18n/en.json +++ b/lib/core/i18n/en.json @@ -422,6 +422,9 @@ "CRYPTODOC_ENABLED": "Is Cryptodoc Enabled" } } - + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Click to copy", + "SUCCESS_COPY": "Text copied to clipboard" } } From bcdfcee39750ffcee85a78c6f099a5a8b6ece0c2 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Wed, 17 Apr 2019 13:10:36 +0300 Subject: [PATCH 119/208] [ADF-4390]Added copyContent datatable cell tests (#4614) * Modified data-table page on demo-shell to make copyClipboard possible to test * Add a new page in demo-shell. Add copyContent automated tests. --- demo-shell/src/app/app.routes.ts | 4 + .../app-layout/app-layout.component.ts | 3 +- .../copy-content/datatable.component.html | 23 +++ .../copy-content/datatable.component.ts | 125 ++++++++++++++++ .../copy-content/datatable.module.ts | 41 +++++ .../datatable/datatable.component.html | 2 +- .../datatable/data-table-component.e2e.ts | 140 +++++++++++++++--- e2e/pages/adf/demo-shell/dataTablePage.ts | 75 +++++++++- e2e/pages/adf/navigationBarPage.ts | 8 + .../src/lib/core/browser-visibility.ts | 4 + .../core/pages/data-table-component.page.ts | 27 ++++ 11 files changed, 421 insertions(+), 31 deletions(-) create mode 100644 demo-shell/src/app/components/datatable/copy-content/datatable.component.html create mode 100644 demo-shell/src/app/components/datatable/copy-content/datatable.component.ts create mode 100644 demo-shell/src/app/components/datatable/copy-content/datatable.module.ts diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 703c724073..e3d521ac41 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -377,6 +377,10 @@ export const appRoutes: Routes = [ path: 'datatable-lazy', loadChildren: 'app/components/lazy-loading/lazy-loading.module#LazyLoadingModule' }, + { + path: 'copy-content', + loadChildren: 'app/components/datatable/copy-content/datatable.module#AppDataTableCopyModule' + }, { path: 'template-list', component: TemplateDemoComponent diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index f9fa4534f9..7518587bc6 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -64,7 +64,8 @@ export class AppLayoutComponent implements OnInit { { href: '/datatable', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE', children: [ { href: '/datatable', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE' }, { href: '/datatable-lazy', icon: 'view_module', title: 'APP_LAYOUT.DATATABLE_LAZY' }, - { href: '/datatable/dnd', icon: 'view_module', title: 'Drag and Drop' } + { href: '/datatable/dnd', icon: 'view_module', title: 'Drag and Drop' }, + { href: '/copy-content', icon: 'view_module', title: 'Copy Content' } ]}, { href: '/template-list', icon: 'list_alt', title: 'APP_LAYOUT.TEMPLATE' }, { href: '/webscript', icon: 'extension', title: 'APP_LAYOUT.WEBSCRIPT' }, diff --git a/demo-shell/src/app/components/datatable/copy-content/datatable.component.html b/demo-shell/src/app/components/datatable/copy-content/datatable.component.html new file mode 100644 index 0000000000..e4005850ee --- /dev/null +++ b/demo-shell/src/app/components/datatable/copy-content/datatable.component.html @@ -0,0 +1,23 @@ + +<div style="height: 310px; overflow-y: auto;" data-automation-id="datatable"> + <adf-datatable + #dataTable + [data]="data"> + </adf-datatable> +</div> + +<div> + Paste clipboard: + <input data-automation-id="paste clipboard input"> +</div> + +<div style="height: 310px; overflow-y: auto;" data-automation-id="copyClipboard-datatable"> + <adf-datatable + [data]="dataForCopy"> + <data-columns> + <data-column key="id" title="Id" [copyContent]="true"></data-column> + <data-column key="name" title="Name" class="adf-full-width name-column" [copyContent]="false"></data-column> + <data-column key="createdBy" title="Created By"></data-column> + </data-columns> + </adf-datatable> +</div> diff --git a/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts b/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts new file mode 100644 index 0000000000..585ed77935 --- /dev/null +++ b/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts @@ -0,0 +1,125 @@ +/*! + * @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 } from '@angular/core'; +import { DataColumn, DataRow } from '@alfresco/adf-core'; +import { ObjectDataTableAdapter } from '@alfresco/adf-core'; + +export class FilteredDataAdapter extends ObjectDataTableAdapter { + + filterValue = ''; + filterKey = 'name'; + + getRows(): Array<DataRow> { + let rows = super.getRows(); + const filter = (this.filterValue || '').trim().toLowerCase(); + + if (this.filterKey && filter) { + rows = rows.filter((row) => { + const value = row.getValue(this.filterKey); + if (value !== undefined && value !== null) { + const stringValue: string = value.toString().trim().toLowerCase(); + return stringValue.startsWith(filter); + } + return false; + }); + } + return rows; + } + + constructor(data?: any[], schema?: DataColumn[]) { + super(data, schema); + } +} + +@Component({ + selector: 'app-datatable', + templateUrl: './datatable.component.html' +}) +export class DataTableComponent { + + @Input() + selectionMode = 'single'; + + dataForCopy = new FilteredDataAdapter( + [ + { + id: 1, + name: 'First', + createdBy: 'Created one' + }, + { + id: 2, + name: 'Second', + createdBy: 'Created two' + }, + { + id: 3, + name: 'Third', + createdBy: 'Created three' + } + ] +); + data = new FilteredDataAdapter( + [ + { + id: 1, + name: 'Name 1', + createdBy: 'Created One', + icon: 'material-icons://folder_open', + json: null + }, + { + id: 2, + name: 'Name 2', + createdBy: 'Created Two', + icon: 'material-icons://accessibility', + json: null + }, + { + id: 3, + name: 'Name 3', + createdBy: 'Created Three', + icon: 'material-icons://alarm', + json: null + }, + { + id: 4, + name: 'Image 8', + createdBy: 'Created Four', + icon: 'material-icons://alarm', + json: { + id: 4, + name: 'Image 8', + createdOn: new Date(2016, 6, 2, 15, 8, 4), + createdBy: { + name: 'Felipe', + lastname: 'Melo' + }, + icon: 'material-icons://alarm' + } + } + ], + [ + { type: 'image', key: 'icon', title: '', srTitle: 'Thumbnail' }, + { type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '', copyContent: true }, + { type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true, copyContent: false }, + { type: 'text', key: 'createdBy', title: 'Created By', sortable: true, cssClass: ''}, + { type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2'} + ] +); +} diff --git a/demo-shell/src/app/components/datatable/copy-content/datatable.module.ts b/demo-shell/src/app/components/datatable/copy-content/datatable.module.ts new file mode 100644 index 0000000000..a757a4ef33 --- /dev/null +++ b/demo-shell/src/app/components/datatable/copy-content/datatable.module.ts @@ -0,0 +1,41 @@ +/*! + * @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 { NgModule } from '@angular/core'; +import { DataTableComponent } from './datatable.component'; +import { Routes, RouterModule } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { CoreModule } from '@alfresco/adf-core'; +import { ContentModule } from '@alfresco/adf-content-services'; + +const routes: Routes = [ + { + path: '', + component: DataTableComponent + } +]; + +@NgModule({ + imports: [ + CommonModule, + CoreModule.forChild(), + RouterModule.forChild(routes), + ContentModule.forChild() + ], + declarations: [DataTableComponent] +}) +export class AppDataTableCopyModule {} diff --git a/demo-shell/src/app/components/datatable/datatable.component.html b/demo-shell/src/app/components/datatable/datatable.component.html index b6faba51b2..2c0d852471 100644 --- a/demo-shell/src/app/components/datatable/datatable.component.html +++ b/demo-shell/src/app/components/datatable/datatable.component.html @@ -10,7 +10,7 @@ Sticky header </mat-slide-toggle> -<div style="height: 310px; overflow-y: auto;"> +<div style="height: 310px; overflow-y: auto;" data-automation-id="datatable"> <adf-datatable #dataTable [data]="data" diff --git a/e2e/core/datatable/data-table-component.e2e.ts b/e2e/core/datatable/data-table-component.e2e.ts index cb75e747ed..cf14f36f8a 100644 --- a/e2e/core/datatable/data-table-component.e2e.ts +++ b/e2e/core/datatable/data-table-component.e2e.ts @@ -23,14 +23,17 @@ import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; +import { NotificationPage } from '../../pages/adf/notificationPage'; describe('Datatable component', () => { - const dataTablePage = new DataTablePage(); + const dataTablePage = new DataTablePage('defaultTable'); + const copyContentDataTablePage = new DataTablePage('copyClipboardDataTable'); const loginPage = new LoginPage(); const acsUser = new AcsUserModel(); const navigationBarPage = new NavigationBarPage(); const dataTableComponent = new DataTableComponentPage(); + const notificationPage = new NotificationPage(); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -44,34 +47,127 @@ describe('Datatable component', () => { loginPage.loginToContentServicesUsingUserModel(acsUser); - navigationBarPage.navigateToDatatable(); - done(); }); - it('[C91314] Should be possible add new row to the table', () => { - dataTableComponent.numberOfRows().then((result) => { - dataTablePage.addRow(); - expect(dataTableComponent.numberOfRows()).toEqual(result + 1); - dataTablePage.addRow(); - expect(dataTableComponent.numberOfRows()).toEqual(result + 2); + describe('Datatable component', () => { + + beforeAll(async (done) => { + navigationBarPage.navigateToDatatable(); + + done(); + }); + + beforeEach(async (done) => { + dataTablePage.clickReset(); + done(); + }); + + it('[C91314] Should be possible add new row to the table', () => { + dataTableComponent.numberOfRows().then((result) => { + dataTablePage.addRow(); + expect(dataTableComponent.numberOfRows()).toEqual(result + 1); + dataTablePage.addRow(); + expect(dataTableComponent.numberOfRows()).toEqual(result + 2); + }); + }); + + it('[C260039] Should be possible replace rows', () => { + dataTablePage.replaceRows(1); + }); + + it('[C260041] Should be possible replace columns', () => { + dataTablePage.replaceColumns(); + }); + + it('[C277314] Should filter the table rows when the input filter is passed', () => { + dataTablePage.replaceRows(1); + dataTablePage.replaceColumns(); + expect(dataTableComponent.numberOfRows()).toEqual(4); + dataTablePage.insertFilter('Name'); + expect(dataTableComponent.numberOfRows()).toEqual(3); + dataTablePage.insertFilter('I'); + expect(dataTableComponent.numberOfRows()).toEqual(1); }); }); - it('[C260039] Should be possible replace rows', () => { - dataTablePage.replaceRows(1); - }); + describe('Datatable component - copyContent', () => { - it('[C260041] Should be possible replace columns', () => { - dataTablePage.replaceColumns(); - }); + beforeAll(async (done) => { + navigationBarPage.navigateToCopyContentDatatable(); + done(); + }); - it('[C277314] Should filter the table rows when the input filter is passed', () => { - expect(dataTableComponent.numberOfRows()).toEqual(4); - dataTablePage.insertFilter('Name'); - expect(dataTableComponent.numberOfRows()).toEqual(3); - dataTablePage.insertFilter('I'); - expect(dataTableComponent.numberOfRows()).toEqual(1); - }); + it('[C307037] A tooltip is displayed when mouseOver a column with copyContent set to true', () => { + dataTablePage.mouseOverIdColumn('1'); + expect(dataTablePage.getCopyContentTooltip()).toEqual('Click to copy'); + dataTablePage.mouseOverNameColumn('Name 2'); + dataTablePage.dataTable.copyContentTooltipIsNotDisplayed(); + }); + it('[C307045] No tooltip is displayed when hover over a column with copyContent set to false', () => { + dataTablePage.mouseOverNameColumn('Name 2'); + dataTablePage.dataTable.copyContentTooltipIsNotDisplayed(); + dataTablePage.clickOnNameColumn('Name 2'); + notificationPage.checkNotificationSnackBarIsNotDisplayed(); + }); + + it('[C307046] No tooltip is displayed when hover over a column that has default value for copyContent property', () => { + dataTablePage.mouseOverCreatedByColumn('Created One'); + dataTablePage.dataTable.copyContentTooltipIsNotDisplayed(); + dataTablePage.clickOnCreatedByColumn('Created One'); + notificationPage.checkNotificationSnackBarIsNotDisplayed(); + }); + + it('[C307040] A column value with copyContent set to true is copied when clicking on it', () => { + dataTablePage.mouseOverIdColumn('1'); + expect(dataTablePage.getCopyContentTooltip()).toEqual('Click to copy'); + dataTablePage.clickOnIdColumn('1'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + dataTablePage.pasteClipboard(); + expect(dataTablePage.getClipboardInputText()).toEqual('1'); + dataTablePage.clickOnIdColumn('2'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + dataTablePage.clickOnIdColumn('3'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + dataTablePage.pasteClipboard(); + expect(dataTablePage.getClipboardInputText()).toEqual('3'); + }); + + it('[C307072] A tooltip is displayed when mouseOver a column with copyContent set to true', () => { + copyContentDataTablePage.mouseOverIdColumn('1'); + expect(copyContentDataTablePage.getCopyContentTooltip()).toEqual('Click to copy'); + copyContentDataTablePage.mouseOverNameColumn('First'); + copyContentDataTablePage.dataTable.copyContentTooltipIsNotDisplayed(); + }); + + it('[C307074] No tooltip is displayed when hover over a column with copyContent set to false', () => { + copyContentDataTablePage.mouseOverNameColumn('Second'); + copyContentDataTablePage.dataTable.copyContentTooltipIsNotDisplayed(); + copyContentDataTablePage.clickOnNameColumn('Second'); + notificationPage.checkNotificationSnackBarIsNotDisplayed(); + }); + + it('[C307075] No tooltip is displayed when hover over a column that has default value for copyContent property', () => { + copyContentDataTablePage.mouseOverCreatedByColumn('Created one'); + copyContentDataTablePage.dataTable.copyContentTooltipIsNotDisplayed(); + copyContentDataTablePage.clickOnCreatedByColumn('Created one'); + notificationPage.checkNotificationSnackBarIsNotDisplayed(); + }); + + it('[C307073] A column value with copyContent set to true is copied when clicking on it', () => { + copyContentDataTablePage.mouseOverIdColumn('1'); + expect(copyContentDataTablePage.getCopyContentTooltip()).toEqual('Click to copy'); + copyContentDataTablePage.clickOnIdColumn('1'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + copyContentDataTablePage.pasteClipboard(); + expect(copyContentDataTablePage.getClipboardInputText()).toEqual('1'); + copyContentDataTablePage.clickOnIdColumn('2'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + copyContentDataTablePage.clickOnIdColumn('3'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + copyContentDataTablePage.pasteClipboard(); + expect(copyContentDataTablePage.getClipboardInputText()).toEqual('3'); + }); + }); }); diff --git a/e2e/pages/adf/demo-shell/dataTablePage.ts b/e2e/pages/adf/demo-shell/dataTablePage.ts index 63328fc3ca..bfe30ac248 100644 --- a/e2e/pages/adf/demo-shell/dataTablePage.ts +++ b/e2e/pages/adf/demo-shell/dataTablePage.ts @@ -21,7 +21,18 @@ import { BrowserVisibility } from '@alfresco/adf-testing'; export class DataTablePage { - dataTable = new DataTableComponentPage(); + columns = { + id: 'Id', + name: 'Name', + createdBy: 'Created By' + }; + + data = { + copyClipboardDataTable: 'copyClipboard-datatable', + defaultTable: 'datatable' + }; + + dataTable; multiSelect = element(by.css(`div[data-automation-id='multiselect'] label > div[class='mat-checkbox-inner-container']`)); reset = element(by.xpath(`//span[contains(text(),'Reset to default')]/..`)); selectionButton = element(by.css(`div[class='mat-select-arrow']`)); @@ -33,6 +44,15 @@ export class DataTablePage { replaceRowsElement = element(by.xpath(`//span[contains(text(),'Replace rows')]/..`)); replaceColumnsElement = element(by.xpath(`//span[contains(text(),'Replace columns')]/..`)); createdOnColumn = element(by.css(`div[data-automation-id='auto_id_createdOn']`)); + pasteClipboardInput = element(by.css(`input[data-automation-id='paste clipboard input']`)); + + constructor(data?) { + if (this.data[data]) { + this.dataTable = new DataTableComponentPage(element(by.css(`div[data-automation-id='` + this.data[data] + `']`))); + } else { + this.dataTable = new DataTableComponentPage(element(by.css(`div[data-automation-id='` + this.data.defaultTable + `']`))); + } + } insertFilter(filterText) { const inputFilter = element(by.css(`#adf-datatable-filter-input`)); @@ -46,7 +66,7 @@ export class DataTablePage { } replaceRows(id) { - const rowID = this.dataTable.getRowElement('Id', id); + const rowID = this.dataTable.getRowElement(this.columns.id, id); BrowserVisibility.waitUntilElementIsVisible(rowID); this.replaceRowsElement.click(); BrowserVisibility.waitUntilElementIsNotVisible(rowID); @@ -69,7 +89,7 @@ export class DataTablePage { } checkRowIsNotSelected(rowNumber) { - const isRowSelected = this.dataTable.getRowElement('Id', rowNumber) + const isRowSelected = this.dataTable.getRowElement(this.columns.id, rowNumber) .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row custom-row-style ng-star-inserted is-selected')]`)); BrowserVisibility.waitUntilElementIsNotOnPage(isRowSelected); } @@ -96,13 +116,13 @@ export class DataTablePage { } clickCheckbox(rowNumber) { - const checkbox = this.dataTable.getRowElement('Id', rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); + const checkbox = this.dataTable.getRowElement(this.columns.id, rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); BrowserVisibility.waitUntilElementIsVisible(checkbox); checkbox.click(); } selectRow(rowNumber) { - const locator = this.dataTable.getRowElement('Id', rowNumber); + const locator = this.dataTable.getRowElement(this.columns.id, rowNumber); BrowserVisibility.waitUntilElementIsVisible(locator); BrowserVisibility.waitUntilElementIsClickable(locator); locator.click(); @@ -110,7 +130,7 @@ export class DataTablePage { } selectRowWithKeyboard(rowNumber) { - const row = this.dataTable.getRowElement('Id', rowNumber); + const row = this.dataTable.getRowElement(this.columns.id, rowNumber); browser.actions().sendKeys(protractor.Key.COMMAND).click(row).perform(); } @@ -122,6 +142,47 @@ export class DataTablePage { } getRowCheckbox(rowNumber) { - return this.dataTable.getRowElement('Id', rowNumber).element(by.xpath(`ancestor::div/div/mat-checkbox[contains(@class, 'mat-checkbox-checked')]`)); + return this.dataTable.getRowElement(this.columns.id, rowNumber).element(by.xpath(`ancestor::div/div/mat-checkbox[contains(@class, 'mat-checkbox-checked')]`)); + } + + getCopyContentTooltip() { + return this.dataTable.getCopyContentTooltip(); + } + + mouseOverNameColumn(name) { + return this.dataTable.mouseOverColumn(this.columns.name, name); + } + + mouseOverCreatedByColumn(name) { + return this.dataTable.mouseOverColumn(this.columns.createdBy, name); + } + + mouseOverIdColumn(name) { + return this.dataTable.mouseOverColumn(this.columns.id, name); + } + + clickOnIdColumn(name) { + return this.dataTable.clickColumn(this.columns.id, name); + } + + clickOnNameColumn(name) { + return this.dataTable.clickColumn(this.columns.name, name); + } + + clickOnCreatedByColumn(name) { + return this.dataTable.clickColumn(this.columns.createdBy, name); + } + + pasteClipboard() { + this.pasteClipboardInput.clear(); + BrowserVisibility.waitUntilElementIsVisible(this.pasteClipboardInput); + this.pasteClipboardInput.click(); + this.pasteClipboardInput.sendKeys(protractor.Key.chord(protractor.Key.SHIFT, protractor.Key.INSERT)); + return this; + } + + getClipboardInputText() { + BrowserVisibility.waitUntilElementIsVisible(this.pasteClipboardInput); + return this.pasteClipboardInput.getAttribute('value'); } } diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index 12f92ef000..076d41866c 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -27,6 +27,7 @@ export class NavigationBarPage { contentServicesButton = element(by.css('a[data-automation-id="Content Services"]')); dataTableButton = element(by.css('a[data-automation-id="Datatable"]')); dataTableNestedButton = element(by.css('button[data-automation-id="Datatable"]')); + dataTableCopyContentButton = element(by.css('button[data-automation-id="Copy Content"]')); taskListButton = element(by.css("a[data-automation-id='Task List']")); configEditorButton = element(by.css('a[data-automation-id="Configuration Editor"]')); processServicesButton = element(by.css('a[data-automation-id="Process Services"]')); @@ -59,6 +60,13 @@ export class NavigationBarPage { this.dataTableNestedButton.click(); } + navigateToCopyContentDatatable() { + BrowserVisibility.waitUntilElementIsVisible(this.dataTableButton); + this.dataTableButton.click(); + BrowserVisibility.waitUntilElementIsVisible(this.dataTableCopyContentButton); + this.dataTableCopyContentButton.click(); + } + clickContentServicesButton() { BrowserVisibility.waitUntilElementIsVisible(this.contentServicesButton); this.contentServicesButton.click(); diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/browser-visibility.ts index 024bdce410..c767940392 100644 --- a/lib/testing/src/lib/core/browser-visibility.ts +++ b/lib/testing/src/lib/core/browser-visibility.ts @@ -112,4 +112,8 @@ export class BrowserVisibility { return browser.wait(until.presenceOf(elementToCheck), waitTimeout, 'Element is not present ' + elementToCheck.locator()); } + static waitUntilElementIsNotPresent(elementToCheck, waitTimeout: number = DEFAULT_TIMEOUT) { + return browser.wait(until.not(until.presenceOf(elementToCheck)), waitTimeout, 'Element is not in the page ' + elementToCheck.locator()); + } + } diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index 6f84a10efa..0f7d4861e4 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -31,6 +31,7 @@ export class DataTableComponentPage { selectedRowNumber; allSelectedRows; selectAll; + copyColumnTooltip; constructor(rootElement: ElementFinder = element.all(by.css('adf-datatable')).first()) { this.rootElement = rootElement; @@ -42,6 +43,7 @@ export class DataTableComponentPage { this.selectedRowNumber = this.rootElement.element(by.css(`div[class*='is-selected'] div[data-automation-id*='text_']`)); this.allSelectedRows = this.rootElement.all(by.css(`div[class*='is-selected']`)); this.selectAll = this.rootElement.element(by.css(`div[class*='adf-datatable-header'] mat-checkbox`)); + this.copyColumnTooltip = this.rootElement.element(by.css(`adf-datatable-copy-content-tooltip span`)); } checkAllRowsButtonIsDisplayed() { @@ -306,4 +308,29 @@ export class DataTableComponentPage { BrowserVisibility.waitUntilElementIsClickable(resultElement); resultElement.click(); } + + getCopyContentTooltip() { + BrowserVisibility.waitUntilElementIsVisible(this.copyColumnTooltip); + return this.copyColumnTooltip.getText(); + } + + copyContentTooltipIsNotDisplayed() { + BrowserVisibility.waitUntilElementIsNotPresent(this.copyColumnTooltip); + return this; + } + + mouseOverColumn(columnName, columnValue) { + const column = this.getRowElement(columnName, columnValue); + BrowserVisibility.waitUntilElementIsVisible(column); + browser.actions().mouseMove(column).perform(); + return this; + } + + clickColumn(columnName, columnValue) { + const column = this.getRowElement(columnName, columnValue); + BrowserVisibility.waitUntilElementIsVisible(column); + BrowserVisibility.waitUntilElementIsClickable(column); + column.click(); + return this; + } } From 21fd0299bd64051f0163f82aa5f422a1dfc0b887 Mon Sep 17 00:00:00 2001 From: Deepak Paul <deepak.paul@muraai.com> Date: Wed, 17 Apr 2019 20:34:59 +0530 Subject: [PATCH 120/208] [ADF-4349] Cloud - task-form-component - Create a new component (#4620) * [ADF-4349] Created task form cloud * [ADF-4349] Used task-form in demo shell * [ADF-4349] Used task directives * [ADF-4349] Added tests * [ADF-4349] Added documentation * [ADF-4349] Added translation for buttons --- .../task-details-cloud-demo.component.html | 20 +- .../task-details-cloud-demo.component.ts | 35 +- .../components/task-form-cloud.component.md | 63 ++++ lib/core/i18n/en.json | 3 + .../components/form-cloud.component.spec.ts | 48 +++ .../form/components/form-cloud.component.ts | 49 +++ .../components/task-form-cloud.component.html | 56 +++ .../components/task-form-cloud.component.scss | 32 ++ .../task-form-cloud.component.spec.ts | 345 ++++++++++++++++++ .../components/task-form-cloud.component.ts | 191 ++++++++++ .../src/lib/form/form-cloud.module.ts | 9 +- .../src/lib/form/models/form-cloud.model.ts | 4 + .../src/lib/form/public-api.ts | 1 + .../src/lib/i18n/en.json | 13 + .../src/lib/styles/_index.scss | 2 + .../lib/task/services/task-cloud.service.ts | 4 +- .../models/task-details-cloud.model.ts | 6 +- 17 files changed, 827 insertions(+), 54 deletions(-) create mode 100644 docs/process-services-cloud/components/task-form-cloud.component.md create mode 100644 lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.html create mode 100644 lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.scss create mode 100644 lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts create mode 100644 lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html index c8faa507d2..bd9b9593fb 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html @@ -3,23 +3,15 @@ <div fxLayout="column" fxFill fxLayoutGap="2px"> <div fxLayout="row" fxFill> <div fxLayout="column" fxFlex="80%"> - <div class="adf-task-control"> - <button mat-button (click)="goBack()">Cancel</button> - <button mat-button color="primary" *ngIf="canCompleteTask()" adf-cloud-complete-task - (success)="onCompletedTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button> - - <button mat-button color="primary" *ngIf="canClaimTask()" adf-cloud-claim-task - (success)="onClaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.CLAIM' | translate }}</button> - - <button mat-button color="primary" *ngIf="canUnClaimTask()" adf-cloud-unclaim-task - (success)="onUnclaimTask()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.UNCLAIM' | translate }}</button> - </div> - <adf-cloud-form *ngIf="hasTaskForm()" fxFlex="100%" + <adf-task-form-cloud [appName]="appName" [taskId]="taskId" - (formCompleted)="onTaskCompleted()" + (cancelClick)="goBack()" + (taskClaimed)="onClaimTask()" + (taskCompleted)="onTaskCompleted()" + (taskUnclaimed)="onUnclaimTask()" (formSaved)="onFormSaved()"> - </adf-cloud-form> + </adf-task-form-cloud> </div> <adf-cloud-task-header fxFlex [appName]="appName" diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts index 37a78e7798..3f590ba456 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts @@ -15,18 +15,17 @@ * limitations under the License. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { TaskDetailsCloudModel, TaskCloudService, UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; +import { UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; import { NotificationService, FormRenderingService } from '@alfresco/adf-core'; @Component({ templateUrl: './task-details-cloud-demo.component.html', styleUrls: ['./task-details-cloud-demo.component.scss'] }) -export class TaskDetailsCloudDemoComponent implements OnInit { +export class TaskDetailsCloudDemoComponent { - taskDetails: TaskDetailsCloudModel; taskId: string; appName: string; @@ -34,7 +33,6 @@ export class TaskDetailsCloudDemoComponent implements OnInit { private route: ActivatedRoute, private router: Router, private formRenderingService: FormRenderingService, - private taskCloudService: TaskCloudService, private notificationService: NotificationService ) { this.route.params.subscribe((params) => { @@ -47,37 +45,10 @@ export class TaskDetailsCloudDemoComponent implements OnInit { } - ngOnInit() { - this.loadTaskDetailsById(this.appName, this.taskId); - } - - loadTaskDetailsById(appName: string, taskId: string) { - this.taskCloudService.getTaskById(appName, taskId).subscribe( - (taskDetails: TaskDetailsCloudModel ) => { - this.taskDetails = taskDetails; - }); - } - isTaskValid(): boolean { return this.appName !== undefined && this.taskId !== undefined; } - canCompleteTask(): boolean { - return this.taskDetails && !this.taskDetails.formKey && this.taskCloudService.canCompleteTask(this.taskDetails); - } - - canClaimTask(): boolean { - return this.taskDetails && this.taskCloudService.canClaimTask(this.taskDetails); - } - - canUnClaimTask(): boolean { - return this.taskDetails && this.taskCloudService.canUnclaimTask(this.taskDetails); - } - - hasTaskForm(): boolean { - return this.taskDetails && this.taskDetails.formKey; - } - goBack() { this.router.navigate([`/cloud/${this.appName}/`]); } diff --git a/docs/process-services-cloud/components/task-form-cloud.component.md b/docs/process-services-cloud/components/task-form-cloud.component.md new file mode 100644 index 0000000000..457c972cc9 --- /dev/null +++ b/docs/process-services-cloud/components/task-form-cloud.component.md @@ -0,0 +1,63 @@ +--- +Title: Form cloud component +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-17 +--- + +# [Task form cloud component](../../../lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts "Defined in task-form-cloud.component.ts") + +Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts) for a task. + +## Contents + +- [Basic Usage](#basic-usage) +- [Class members](#class-members) + - [Properties](#properties) + - [Events](#events) +- [See also](#see-also) + +## Basic Usage + +```html +<adf-task-form-cloud + [appName]="appName" + [taskId]="taskId"> +</adf-task-form-cloud> +``` + + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| appName | `string` | | App id to fetch corresponding form and values. | +| taskId | `string` | | Task id to fetch corresponding form and values. | +| showRefreshButton | `boolean` | false | Toggle rendering of the `Refresh` button. | +| showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. | +| showCancelButton | `boolean` | true | Toggle rendering of the `Cancel` outcome button. | +| showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | +| showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. | +| readOnly | `boolean` | false | Toggle readonly state of the task. | + + +### Events + +| Name | Type | Description | +| ---- | ---- | ----------- | +| formSaved | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is saved. | +| formCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Complete` outcome. | +| taskCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`string`>` | Emitted when the task is completed. | +| taskClaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`string`>` | Emitted when the task is claimed. | +| taskUnclaimed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`string`>` | Emitted when the task is unclaimed. | +| cancelClick | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`string`>` | Emitted when the cancel button is clicked. | +| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when any error occurs. | + + +## See also + +- [Form component](./form-cloud.component.md) +- [Form field model](../../core/models/form-field.model.md) +- [Form cloud service](../services/form-cloud.service.md) diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json index 992c958be8..fa01565df3 100644 --- a/lib/core/i18n/en.json +++ b/lib/core/i18n/en.json @@ -1,6 +1,9 @@ { "SAVE": "SAVE", "COMPLETE": "COMPLETE", + "CANCEL": "CANCEL", + "CLAIM": "CLAIM", + "UNCLAIM": "UNCLAIM", "START PROCESS": "START PROCESS", "FORM": { "START_FORM": { diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts index 27ef2f9c17..342f5a7c97 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -750,4 +750,52 @@ describe('FormCloudComponent', () => { radioFieldById = formFields.find((field) => field.id === 'radiobuttons1'); expect(radioFieldById.value).toBe('option_2'); }); + + it('should emit executeOutcome on [claim] outcome click', (done) => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { + id: FormCloud.CLAIM_OUTCOME, + name: 'CLAIM', + isSystem: true + }); + + formComponent.form = formModel; + formComponent.executeOutcome.subscribe(() => { + done(); + }); + + formComponent.onOutcomeClicked(outcome); + }); + + it('should emit executeOutcome on [unclaim] outcome click', (done) => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { + id: FormCloud.UNCLAIM_OUTCOME, + name: 'UNCLAIM', + isSystem: true + }); + + formComponent.form = formModel; + formComponent.executeOutcome.subscribe(() => { + done(); + }); + + formComponent.onOutcomeClicked(outcome); + }); + + it('should emit executeOutcome on [cancel] outcome click', (done) => { + const formModel = new FormCloud(); + const outcome = new FormOutcomeModel(<any> formModel, { + id: FormCloud.CANCEL_OUTCOME, + name: 'CANCEL', + isSystem: true + }); + + formComponent.form = formModel; + formComponent.executeOutcome.subscribe(() => { + done(); + }); + + formComponent.onOutcomeClicked(outcome); + }); }); diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts index 368a522ae4..f0a832a0a0 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts @@ -53,6 +53,18 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { @Input() data: TaskVariableCloud[]; + /** Toggle rendering of the `Cancel` outcome button. */ + @Input() + showCancelButton = false; + + /** Toggle rendering of the `Claim` outcome button. */ + @Input() + showClaimButton = false; + + /** Toggle rendering of the `Unclaim` outcome button. */ + @Input() + showUnclaimButton = false; + /** Emitted when the form is submitted with the `Save` or custom outcomes. */ @Output() formSaved: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); @@ -147,6 +159,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { (data) => { this.data = data[1]; const parsedForm = this.parseForm(data[0]); + this.appendCustomOutcomes(parsedForm); this.visibilityService.refreshVisibility(<any> parsedForm); parsedForm.validateForm(); this.form = parsedForm; @@ -178,6 +191,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { .subscribe( (form) => { const parsedForm = this.parseForm(form); + this.appendCustomOutcomes(parsedForm); this.visibilityService.refreshVisibility(<any> parsedForm); parsedForm.validateForm(); this.form = parsedForm; @@ -293,4 +307,39 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { protected storeFormAsMetadata() { } + + private appendCustomOutcomes(form: FormCloud): FormCloud { + + if (this.showClaimButton) { + const claimOutcome = new FormOutcomeModel(<any> form, { + id: FormCloud.CLAIM_OUTCOME, + name: 'CLAIM', + isSystem: true + }); + + form.outcomes.unshift(claimOutcome); + } + + if (this.showUnclaimButton) { + const unclaimOutcome = new FormOutcomeModel(<any> form, { + id: FormCloud.UNCLAIM_OUTCOME, + name: 'UNCLAIM', + isSystem: true + }); + + form.outcomes.unshift(unclaimOutcome); + } + + if (this.showCancelButton) { + const cancelOutcome = new FormOutcomeModel(<any> form, { + id: FormCloud.CANCEL_OUTCOME, + name: 'CANCEL', + isSystem: true + }); + + form.outcomes.unshift(cancelOutcome); + } + + return form; + } } diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.html b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.html new file mode 100644 index 0000000000..910ed18fd1 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.html @@ -0,0 +1,56 @@ +<div *ngIf="taskDetails"> + <adf-cloud-form *ngIf="hasForm(); else withoutForm" + [appName]="appName" + [taskId]="taskId" + [readOnly]="isReadOnly()" + [showRefreshButton]="showRefreshButton" + [showValidationIcon]="showValidationIcon" + [showCompleteButton]="canCompleteTask()" + [showSaveButton]="canCompleteTask()" + [showCancelButton]="showCancelButton" + [showClaimButton]="canClaimTask()" + [showUnclaimButton]="canUnclaimTask()" + (executeOutcome)="onExecuteOutcome($event.outcome)" + (formSaved)="onFormSaved($event)" + (formCompleted)="onFormCompleted($event)" + (formError)="onError($event)"> + </adf-cloud-form> + + <ng-template #withoutForm> + <mat-card class="adf-task-form-container"> + <mat-card-header> + <mat-card-title> + <h4> + <span class="adf-form-title"> + {{taskDetails.name}} + <ng-container *ngIf="!taskDetails.name"> + {{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}} + </ng-container> + </span> + </h4> + </mat-card-title> + </mat-card-header> + <mat-card-content> + <adf-empty-content + [icon]="'description'" + [title]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.TITLE'" + [subtitle]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.SUBTITLE'"> + </adf-empty-content> + </mat-card-content> + <mat-card-actions class="adf-task-form-actions"> + <button mat-button *ngIf="showCancelButton" id="adf-cloud-cancel-task" (click)="onCancelClick()"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL' | translate}} + </button> + <button mat-button *ngIf="canClaimTask()" adf-cloud-claim-task [appName]="appName" [taskId]="taskId" (success)="onClaimTask()"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM' | translate}} + </button> + <button mat-button *ngIf="canUnclaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId" (success)="onUnclaimTask()"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM' | translate}} + </button> + <button mat-button *ngIf="canCompleteTask()" adf-cloud-complete-task [appName]="appName" [taskId]="taskId" (success)="onCompleteTask()" color="primary"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.COMPLETE' | translate}} + </button> + </mat-card-actions> + </mat-card> + </ng-template> +</div> diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.scss b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.scss new file mode 100644 index 0000000000..11e52617b9 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.scss @@ -0,0 +1,32 @@ +@mixin adf-task-form-cloud-theme($theme) { + + $config: mat-typography-config(); + + .adf-task-form { + &-container { + overflow: hidden; + } + + &-actions { + float: right; + padding-bottom: 25px !important; + padding-right: 25px !important; + + & .mat-button { + height: 36px; + border-radius: 5px; + + } + + & .mat-button-wrapper { + width: 58px; + height: 20px; + opacity: 0.54; + font-size: mat-font-size($config, body-2); + font-weight: bold; + } + } + } + + +} diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts new file mode 100644 index 0000000000..4de95293ca --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts @@ -0,0 +1,345 @@ +/*! + * @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 { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; +import { FormCloudModule } from '../form-cloud.module'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { TaskFormCloudComponent } from './task-form-cloud.component'; +import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; +import { TaskCloudService, TaskDetailsCloudModel } from '../../task/public-api'; +import { of } from 'rxjs'; +import { DebugElement, CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; +import { By } from '@angular/platform-browser'; + +const taskDetails = { + appName: 'simple-app', + assignee: 'admin.adf', + completedDate: null, + createdDate: 1555419255340, + description: null, + formKey: null, + id: 'bd6b1741-6046-11e9-80f0-0a586460040d', + name: 'Task1', + owner: 'admin.adf', + standAlone: true, + status: 'ASSIGNED' +}; + +describe('TaskFormCloudComponent', () => { + + let taskCloudService: TaskCloudService; + let identityUserService: IdentityUserService; + + let getTaskSpy: jasmine.Spy; + let getCurrentUserSpy: jasmine.Spy; + let debugElement: DebugElement; + + let component: TaskFormCloudComponent; + let fixture: ComponentFixture<TaskFormCloudComponent>; + + setupTestBed({ + imports: [ProcessServiceCloudTestingModule, FormCloudModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + beforeEach(() => { + taskDetails.status = 'ASSIGNED'; + identityUserService = TestBed.get(IdentityUserService); + getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({username: 'admin.adf'}); + taskCloudService = TestBed.get(TaskCloudService); + getTaskSpy = spyOn(taskCloudService, 'getTaskById').and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + + fixture = TestBed.createComponent(TaskFormCloudComponent); + debugElement = fixture.debugElement; + component = fixture.componentInstance; + + }); + + it('should create TaskFormCloudComponent ', () => { + expect(component instanceof TaskFormCloudComponent).toBe(true); + }); + + describe('Complete button', () => { + it('should show complete button when status is ASSIGNED', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); + expect(completeBtn.nativeElement).toBeDefined(); + }); + })); + + it('should not show complete button when status is ASSIGNED but assigned to a different person', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + + getCurrentUserSpy.and.returnValue({}); + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); + expect(completeBtn).toBeNull(); + }); + })); + + it('should not show complete button when showCompleteButton=false', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + component.showCompleteButton = false; + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); + expect(completeBtn).toBeNull(); + }); + })); + }); + + describe('Claim/Unclaim buttons', () => { + it('should show unclaim button when status is ASSIGNED', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); + expect(unclaimBtn.nativeElement).toBeDefined(); + }); + })); + + it('should not show unclaim button when status is ASSIGNED but assigned to different person', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + + getCurrentUserSpy.and.returnValue({}); + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); + expect(unclaimBtn).toBeNull(); + }); + })); + + it('should not show unclaim button when status is not ASSIGNED', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + taskDetails.status = ''; + getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); + expect(unclaimBtn).toBeNull(); + }); + })); + + it('should show claim button when status is CREATED', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + taskDetails.status = 'CREATED'; + getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); + expect(claimBtn.nativeElement).toBeDefined(); + }); + })); + + it('should not show claim button when status is not CREATED', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + taskDetails.status = ''; + getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); + expect(claimBtn).toBeNull(); + }); + })); + }); + + describe('Cancel button', () => { + it('should show cancel button by default', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); + expect(cancelBtn.nativeElement).toBeDefined(); + }); + })); + + it('should not show cancel button when showCancelButton=false', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + component.showCancelButton = false; + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); + expect(cancelBtn).toBeNull(); + }); + })); + }); + + describe('Inputs', () => { + it('should not show complete/claim/unclaim buttons when readOnly=true', async(() => { + component.appName = 'app1'; + component.taskId = 'task1'; + component.readOnly = true; + + component.loadTask(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); + expect(completeBtn).toBeNull(); + + const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); + expect(claimBtn).toBeNull(); + + const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); + expect(unclaimBtn).toBeNull(); + + const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); + expect(cancelBtn.nativeElement).toBeDefined(); + }); + })); + + it('should load data when appName changes', () => { + component.taskId = 'task1'; + component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) }); + expect(getTaskSpy).toHaveBeenCalled(); + }); + + it('should load data when taskId changes', () => { + component.appName = 'app1'; + component.ngOnChanges({ taskId: new SimpleChange(null, 'task1', false) }); + expect(getTaskSpy).toHaveBeenCalled(); + }); + + it('should not load data when appName changes and taskId is not defined', () => { + component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) }); + expect(getTaskSpy).not.toHaveBeenCalled(); + }); + + it('should not load data when taskId changes and appName is not defined', () => { + component.ngOnChanges({ taskId: new SimpleChange(null, 'task1', false) }); + expect(getTaskSpy).not.toHaveBeenCalled(); + }); + }); + + describe('Events', () => { + it('should emit cancelClick when cancel button is clicked', (done) => { + component.appName = 'app1'; + component.taskId = 'task1'; + + component.cancelClick.subscribe(() => { + done(); + }); + + component.loadTask(); + fixture.detectChanges(); + const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); + + cancelBtn.nativeElement.click(); + }); + + it('should emit taskCompleted when task is completed', (done) => { + + spyOn(taskCloudService, 'completeTask').and.returnValue(of({})); + + component.appName = 'app1'; + component.taskId = 'task1'; + + component.taskCompleted.subscribe(() => { + done(); + }); + + component.loadTask(); + fixture.detectChanges(); + const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); + + completeBtn.nativeElement.click(); + }); + + it('should emit taskClaimed when task is claimed', (done) => { + spyOn(taskCloudService, 'claimTask').and.returnValue(of({})); + taskDetails.status = 'CREATED'; + getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + + component.appName = 'app1'; + component.taskId = 'task1'; + + component.taskClaimed.subscribe(() => { + done(); + }); + + component.loadTask(); + fixture.detectChanges(); + const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); + + claimBtn.nativeElement.click(); + }); + + it('should emit taskUnclaimed when task is unclaimed', (done) => { + spyOn(taskCloudService, 'unclaimTask').and.returnValue(of({})); + taskDetails.status = 'ASSIGNED'; + getTaskSpy.and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); + + component.appName = 'app1'; + component.taskId = 'task1'; + + component.taskUnclaimed.subscribe(() => { + done(); + }); + + component.loadTask(); + fixture.detectChanges(); + const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); + + unclaimBtn.nativeElement.click(); + }); + + it('should emit error when error occurs', (done) => { + component.appName = 'app1'; + component.taskId = 'task1'; + + component.error.subscribe(() => { + done(); + }); + + component.onError({}); + }); + + }); + +}); diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts new file mode 100644 index 0000000000..eabf87a18c --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts @@ -0,0 +1,191 @@ +/*! + * @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, EventEmitter, Input, OnChanges, + Output, SimpleChanges +} from '@angular/core'; +import { FormCloud } from '../models/form-cloud.model'; +import { TaskDetailsCloudModel, TaskCloudService } from '../../task/public-api'; +import { IdentityUserService, FormOutcomeModel } from '@alfresco/adf-core'; + +@Component({ + selector: 'adf-task-form-cloud', + templateUrl: './task-form-cloud.component.html', + styleUrls: ['./task-form-cloud.component.scss'] +}) +export class TaskFormCloudComponent implements OnChanges { + + /** App id to fetch corresponding form and values. */ + @Input() + appName: string; + + /** Task id to fetch corresponding form and values. */ + @Input() + taskId: string; + + /** Toggle rendering of the `Refresh` button. */ + @Input() + showRefreshButton = false; + + /** Toggle rendering of the `Validation` icon. */ + @Input() + showValidationIcon = true; + + /** Toggle rendering of the `Cancel` button. */ + @Input() + showCancelButton = true; + + /** Toggle rendering of the `Complete` button. */ + @Input() + showCompleteButton = true; + + /** Toggle readonly state of the task. */ + @Input() + readOnly = false; + + /** Emitted when the form is saved. */ + @Output() + formSaved: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + + /** Emitted when the form is submitted with the `Complete` outcome. */ + @Output() + formCompleted: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + + /** Emitted when the task is completed. */ + @Output() + taskCompleted: EventEmitter<string> = new EventEmitter<string>(); + + /** Emitted when the task is claimed. */ + @Output() + taskClaimed: EventEmitter<string> = new EventEmitter<string>(); + + /** Emitted when the task is unclaimed. */ + @Output() + taskUnclaimed: EventEmitter<string> = new EventEmitter<string>(); + + /** Emitted when the cancel button is clicked. */ + @Output() + cancelClick: EventEmitter<string> = new EventEmitter<string>(); + + /** Emitted when any error occurs. */ + @Output() + error: EventEmitter<any> = new EventEmitter<any>(); + + taskDetails: TaskDetailsCloudModel; + + constructor( + private taskCloudService: TaskCloudService, + private identityUserService: IdentityUserService) { + + } + + ngOnChanges(changes: SimpleChanges) { + const appName = changes['appName']; + if (appName && appName.currentValue && this.taskId) { + this.loadTask(); + return; + } + + const taskId = changes['taskId']; + if (taskId && taskId.currentValue && this.appName) { + this.loadTask(); + return; + } + + } + + loadTask() { + this.taskCloudService.getTaskById(this.appName, this.taskId).subscribe((details: TaskDetailsCloudModel) => { + this.taskDetails = details; + }); + } + + hasForm(): boolean { + return this.taskDetails && !!this.taskDetails.formKey; + } + + canCompleteTask(): boolean { + return this.showCompleteButton && !this.readOnly && this.taskCloudService.canCompleteTask(this.taskDetails); + } + + canClaimTask(): boolean { + return !this.readOnly && this.taskCloudService.canClaimTask(this.taskDetails); + } + + canUnclaimTask(): boolean { + return !this.readOnly && this.taskCloudService.canUnclaimTask(this.taskDetails); + } + + isReadOnly(): boolean { + return this.readOnly || this.taskDetails.isCompleted(); + } + + onCompleteTask() { + this.taskCompleted.emit(this.taskId); + } + + onClaimTask() { + this.taskClaimed.emit(this.taskId); + } + + onUnclaimTask() { + this.taskUnclaimed.emit(this.taskId); + } + + onCancelClick() { + this.cancelClick.emit(this.taskId); + } + + claimTask() { + const currentUser = this.identityUserService.getCurrentUserInfo().username; + this.taskCloudService.claimTask(this.appName, this.taskId, currentUser).subscribe( + () => { + this.taskClaimed.emit(this.taskId); + }); + } + + unclaimTask() { + this.taskCloudService.unclaimTask(this.appName, this.taskId).subscribe( + () => { + this.taskUnclaimed.emit(this.taskId); + }); + } + + onExecuteOutcome(outcome: FormOutcomeModel) { + if (outcome.id === FormCloud.CANCEL_OUTCOME) { + this.onCancelClick(); + } else if (outcome.id === FormCloud.CLAIM_OUTCOME) { + this.claimTask(); + } else if (outcome.id === FormCloud.UNCLAIM_OUTCOME) { + this.unclaimTask(); + } + } + + onFormSaved(form: FormCloud) { + this.formSaved.emit(form); + } + + onFormCompleted(form: FormCloud) { + this.formCompleted.emit(form); + this.taskCompleted.emit(this.taskId); + } + + onError(data: any) { + this.error.emit(data); + } +} diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts index 74f71a73c0..e64a6dc8f7 100644 --- a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -23,6 +23,8 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormCloudComponent } from './components/form-cloud.component'; import { UploadCloudWidgetComponent } from './components/upload-cloud.widget'; import { MaterialModule } from '../material.module'; +import { TaskFormCloudComponent } from './components/task-form-cloud.component'; +import { TaskModule } from '../task/task.module'; @NgModule({ imports: [ @@ -34,14 +36,15 @@ import { MaterialModule } from '../material.module'; FormsModule, ReactiveFormsModule, FormBaseModule, - CoreModule + CoreModule, + TaskModule ], - declarations: [FormCloudComponent, UploadCloudWidgetComponent], + declarations: [FormCloudComponent, UploadCloudWidgetComponent, TaskFormCloudComponent], entryComponents: [ UploadCloudWidgetComponent ], exports: [ - FormCloudComponent, UploadCloudWidgetComponent + FormCloudComponent, UploadCloudWidgetComponent, TaskFormCloudComponent ] }) export class FormCloudModule { } diff --git a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts index f778b25c91..1f557675bd 100644 --- a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts @@ -28,6 +28,10 @@ export class FormCloud { static COMPLETE_OUTCOME: string = '$complete'; static START_PROCESS_OUTCOME: string = '$startProcess'; + static CANCEL_OUTCOME: string = '$cancel'; + static CLAIM_OUTCOME: string = '$claim'; + static UNCLAIM_OUTCOME: string = '$unclaim'; + readonly id: string; nodeId: string; readonly name: string; diff --git a/lib/process-services-cloud/src/lib/form/public-api.ts b/lib/process-services-cloud/src/lib/form/public-api.ts index d316dbb6a7..36df829477 100644 --- a/lib/process-services-cloud/src/lib/form/public-api.ts +++ b/lib/process-services-cloud/src/lib/form/public-api.ts @@ -19,4 +19,5 @@ export * from './models/form-cloud.model'; export * from './models/task-variable-cloud.model'; export * from './components/form-cloud.component'; export * from './components/upload-cloud.widget'; +export * from './components/task-form-cloud.component'; export * from './services/form-cloud.service'; diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 71173431f6..4943ac30d6 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -228,5 +228,18 @@ "PARENT_ID": "Parent Id", "NONE": "None" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "No form available", + "SUBTITLE": "Attach a form that can be viewed later", + "BUTTONS": { + "COMPLETE": "COMPLETE", + "CANCEL": "CANCEL", + "CLAIM": "CLAIM", + "UNCLAIM": "UNCLAIM" + } + } } + } diff --git a/lib/process-services-cloud/src/lib/styles/_index.scss b/lib/process-services-cloud/src/lib/styles/_index.scss index 1558379abe..33cdc296d2 100644 --- a/lib/process-services-cloud/src/lib/styles/_index.scss +++ b/lib/process-services-cloud/src/lib/styles/_index.scss @@ -7,6 +7,7 @@ @import './../process/process-filters/components/edit-process-filter-cloud.component.scss'; @import './../task/start-task/components/people-cloud/people-cloud.component.scss'; @import './../group/components/group-cloud.component'; +@import './../form/components/task-form-cloud.component'; @mixin adf-process-services-cloud-theme($theme) { @@ -19,4 +20,5 @@ @include adf-start-task-cloud-theme($theme); @include adf-cloud-people-theme($theme); @include adf-cloud-group-theme($theme); + @include adf-task-form-cloud-theme($theme); } diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index fe207c46ab..706839aecd 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -71,7 +71,7 @@ export class TaskCloudService { */ canCompleteTask(taskDetails: TaskDetailsCloudModel): boolean { const currentUser = this.identityUserService.getCurrentUserInfo().username; - return taskDetails.assignee && taskDetails.assignee === currentUser && taskDetails.isAssigned(); + return taskDetails && taskDetails.assignee && taskDetails.assignee === currentUser && taskDetails.isAssigned(); } /** @@ -90,7 +90,7 @@ export class TaskCloudService { */ canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean { const currentUser = this.identityUserService.getCurrentUserInfo().username; - return taskDetails.canUnclaimTask(currentUser); + return taskDetails && taskDetails.canUnclaimTask(currentUser); } /** diff --git a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts index 06747c4b0c..6942194311 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts @@ -75,11 +75,11 @@ export class TaskDetailsCloudModel { } isCompleted(): boolean { - return this.status && this.status === TaskStatusEnum.COMPLETED; + return this.status === TaskStatusEnum.COMPLETED; } isAssigned(): boolean { - return this.status && this.status === TaskStatusEnum.ASSIGNED; + return this.status === TaskStatusEnum.ASSIGNED; } canClaimTask(): boolean { @@ -87,7 +87,7 @@ export class TaskDetailsCloudModel { } canUnclaimTask(user: string): boolean { - return this.status !== TaskStatusEnum.COMPLETED && this.assignee === user; + return this.isAssigned() && this.assignee === user; } } From 8395b0baa50db7b727c055bc5fe0ff36a774e028 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Wed, 17 Apr 2019 17:04:27 +0100 Subject: [PATCH 121/208] [ADF-4219] Multivalue Metadata Card View (#4600) * [ADF-4219] Multivalue Metadata Card View * [ADF-4219] Add documentation * [ADF-4219] Improve code, docs and tests * [ADF-4219] Fix e2e tests --- demo-shell/src/app.config.json | 5 +- docs/README.md | 1 + .../content-metadata-card.component.md | 18 +++++ docs/core/pipes/multi-value.pipe.md | 39 +++++++++++ .../images/multi-value-default.pipe.png | Bin 0 -> 10388 bytes docs/docassets/images/multi-value.pipe.png | Bin 0 -> 11126 bytes .../viewer-arcive.component.e2e.ts | 16 ++--- .../file-extensions/viewer-component.e2e.ts | 1 - .../viewer-text.component.e2e.ts | 2 - .../property-groups-translator.service.ts | 15 +++- lib/core/app-config/schema.json | 4 ++ .../card-view-textitem.component.ts | 26 +++++-- ...card-view-textitem-properties.interface.ts | 1 + .../models/card-view-textitem.model.ts | 2 + lib/core/pipes/multi-value.pipe.spec.ts | 66 ++++++++++++++++++ lib/core/pipes/multi-value.pipe.ts | 34 +++++++++ lib/core/pipes/pipe.module.ts | 10 ++- lib/core/pipes/public-api.ts | 1 + 18 files changed, 217 insertions(+), 24 deletions(-) create mode 100644 docs/core/pipes/multi-value.pipe.md create mode 100644 docs/docassets/images/multi-value-default.pipe.png create mode 100644 docs/docassets/images/multi-value.pipe.png create mode 100644 lib/core/pipes/multi-value.pipe.spec.ts create mode 100644 lib/core/pipes/multi-value.pipe.ts diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 75d013078a..96bfb02028 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -601,9 +601,10 @@ "content-metadata": { "presets": { "default": { - "exif:exif": "*" + "exif:exif": "*" } - } + }, + "multi-value-pipe-separator" : ", " }, "sideNav": { "expandedSidenav": true, diff --git a/docs/README.md b/docs/README.md index 70328cf129..007acbe6fa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -162,6 +162,7 @@ for more information about installing and using the source code. | [Text Highlight pipe](core/pipes/text-highlight.pipe.md) | Adds highlighting to words or sections of text that match a search string. | [Source](../lib/core/pipes/text-highlight.pipe.ts) | | [Time Ago pipe](core/pipes/time-ago.pipe.md) | Converts a recent past date into a number of days ago. | [Source](../lib/core/pipes/time-ago.pipe.ts) | | [User Initial pipe](core/pipes/user-initial.pipe.md) | Takes the name fields of a UserProcessModel object and extracts and formats the initials. | [Source](../lib/core/pipes/user-initial.pipe.ts) | +| [Multi value pipe](core/pipes/multi-value.pipe.md) | Takes a list of values to stringify them with a custom separator. | [Source](../lib/core/pipes/multi-value.pipe.ts) | ### Services diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index 2b73654d7c..773ed6b807 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -274,3 +274,21 @@ example below shows this with an aspect-oriented config: Nothing - since this aspect is not related to the node, it will simply be ignored and not displayed. The aspects to be displayed are calculated as an intersection of the preset's aspects and the aspects related to the node. + +## Multi value card properties +Multi value properties are displayed one after another separated by a comma. This card makes use of the [Multi Value Pipe](../../core/pipes/multi-value.pipe.ts). + +To customize the separator used by this card you can set it in your `app.config.json` inside your content-metadata configuration: + +```json +"content-metadata": { + "presets": { + "default": { + "includeAll": true, + "exclude": "exif:exif", + "exif:exif": [ "exif:pixelXDimension", "exif:pixelYDimension"] + } + }, + "multi-value-pipe-separator" : " - " +}, +``` diff --git a/docs/core/pipes/multi-value.pipe.md b/docs/core/pipes/multi-value.pipe.md new file mode 100644 index 0000000000..a0f948a9b6 --- /dev/null +++ b/docs/core/pipes/multi-value.pipe.md @@ -0,0 +1,39 @@ +# [Multi Value Pipe](../../../lib/core/pipes/multi-value.pipe.ts "Defined in multi-value.pipe.ts") + +Takes an array of strings and turns it into one string where items are separated by a separator. The default separator applied to the list is `', '`, however, you can set your own separator in the params of the pipe. + +## Basic Usage + +<!-- {% raw %} --> + +### Default separator + +```HTML +<div> + List {{ values | multiValue }} +</div> +``` + +#### Result + +![multi-value-pipe](../../docassets/images/multi-value-default.pipe.png) + +### Custom separator + +```HTML +<div> + List {{ values | multiValue: ' :) ' }} +</div> +``` + +<!-- {% endraw %} --> + +#### Result + +![multi-value-pipe](../../docassets/images/multi-value.pipe.png) + +## Details + +The pipe gets every one of the items passed to the pipe and stringifies it adding the separator set in the configuration. + +You will need to specify the separator you want to use for it to work. diff --git a/docs/docassets/images/multi-value-default.pipe.png b/docs/docassets/images/multi-value-default.pipe.png new file mode 100644 index 0000000000000000000000000000000000000000..bd57f0221bcfebfc2a81debba252506310125cee GIT binary patch literal 10388 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 literal 0 HcmV?d00001 diff --git a/docs/docassets/images/multi-value.pipe.png b/docs/docassets/images/multi-value.pipe.png new file mode 100644 index 0000000000000000000000000000000000000000..3a72938e66e8776bb2d84c4821255df4d4d5c836 GIT binary patch literal 11126 zcmeIYWmJ{T7dH$D(k&o;=<e=@LrXVEgOrqXH%O<n(jd~^NT+mzgdp8r&xLZ||9h?X z{qlT&uC)%=oS8klX74>SzeCs?1u0|%JOl^`2xMunxH1F;6c}hb!Mz0jdh-mwfq*~) zTZ)OjkropJy>YNJv$QsafB=UjYQSo$^kZl0C`()T!GYmh!jyAm;Xg~D#n8^eNrOIj zrJ#xL^;IH#(-UtG{uWN%*a%grK3T&U-Xio$Nol&<A32eWCVSWWu;no0FwNsJoo7pk z!tpQzQn(<PDsl5mBgBUEiRm#q$yfLyOL}E0VPEWQh?lRs*9Y_V>gz2aOphL1+&l=i z#TwSWY}{<!`Ctk7y%~Xp2n*mA18r@I+|fa}!W+;I!utMxaX!s<k|)CtZ}b9J4$Y_t z!@S5o48y$8K5u}MCG*8GBSarNkzx{z?+3QYDugSo7^z#zu5TEAnozzdxNE|#p;W%y z7;ETmZW9Tw=OIHr+PPLf^n7CJ>R&fSHgsm7B?$@tHLkln^jJmssB_|g6~MChGds*A z_IM!GaK(00E<)J|uS+2AV~S?zIf*wDcHth0WD%)^N!&aU$FD)2a&uq!iV|NOJeUfa zuGP536pKhfG8KZ6px58fs^6rK%1>S~Vhnu8U{B|$v^=f|;8y7|wDQDvWmVJ7yO)+w zz|i^bqe8xca?(bFL6KkR*i#6zw(&Z&hQw^Z5#!4wXNr7mC?=Z)nMxPkX`SD!B6S#? z(y6futLf@7o`+VZXSu$0EO;n#>}Rp3l2LB3IZjr=zzW=&+2_Cv_CB%%#ZaQJ5+EdG zm6<3#44F9gb0fm>yBOEVLpn>_^d6!D1V^$2ce+sdUoh}^2K>y#j9?BSBC_FVS=FsD zbCc7ao}$wZL=pC%zHi#05V%>}*<+BqYy{*5j*{Ie366Y`Odv_#k6FAFP*!EbaFvIU z_^B8gC@i>v^CcC_AFA+?KUd8_PdNWwt?;kd7er#|uwR53?@HgeNe6$S2#|V1_8{dX zIK+X2@@rAZ*}5=n+Tv9}Gku1LtkG+hgxAtYRJ?1HuAqZxsqa?I1PAq~2Ye~}8Xld- zqI|0)t9YLS-dh#dYhLIH&@-brwZpBZrn0q`;?@Ox&2)t$g19E(8tIbvMHIx7G+Gy7 zuBDoEVE;r{@|byR$Kg5Q97))n=&u~C<WGaL;_;5p(gUS}+T+G1WU|2w={%8*{nX2I zgewEP-DC1HX_nMl=mQ>KR7N+7p}cPpVRvc;;;bPBk+wv%YKaB2b~9}jK_6fYe<o#q zWxT_T`;6_3;!cC7;pdZkIPQsDHq$kFCBX>fl{-;vjZR`7|6d0?n~1(Ad|$lfTg-}E zQQ=M(HI_tWA)w4qkdO#&iX$4K+aJC|ys`6{nse!x>EMAF`TC2_1m+##w`Md5tl#Za z1FutFSp9_9wTIPjCx#ASX2$OF7mq>6Z)c47>7L|=`<7D^LPmr~6J^?$wjA9WlCRyi z9F^Tq>?ijXVLEJbJI8z2Z<&lo1ZVzr*~B7f7@|_ILs^XcW=Tgv`PKrUNe#j57}2?; z+hA-`kym}zCM3#HU&V`KhQWj<hz@8xQRx!%u{wP(a`D}QJjGcOg7LD=3JG};&PC=d zUZsXANLKyWwm{eRXOy5D({{p{4<(Ws&6)Xua>g?s0x5@RY?PFOxEWwyu1SwP*kv-S z`xU9A{awY&uP_gz8s#WoVQ+mg?O%>`>itBB>WY6aC`gzU!PHT5MCeN9jnU>W)b4T2 z1kKx#@Kf%H>^(dtoK_%ipt2~8A^s}F>MPIGMmW1Lang7T#j{{VV_KFp?uh!p`po(e z*N?Lbd*m0fU~=O)HX7eovTLy?(s{Ygxq7)dxr4ck;~tgRbN+h@C{zWp6dOhkFm6=W zaM!HY@C{jCWGnKnl#FPg2IK}<2h?Q{f05=zj4Mv%%&WX844bsxfqF+#<L4gko_wP% zD?2DNsA1Kdq-oWvo;R&u%BGE4E%@WiQh^=C218y%M`l5RPqInEL%v{Q|98h3yStzl zO-q!wzjxMye%faN<+KupADIPurAvigTDL(c620mnrEC%f-~v(ewh@U8BE9f$8H`fN z1$-KH+Lze}$V-9(!I^3LU-dJWF<LU*&CfG;;?MTazMsL|P~7O8DgJh0We(;D`2Ld( zo3)lzfu#{C^yS4%-2m$Vhk&J*HZNO(Z-R4><B<`OOOR3VKQOc86UGk?nKBw580(vR z6PR&+6p-V#J}wV7Ob%&b!?S&5P0misHgD`S{5ywbkb8)`*EPsK{#XEWv8&&txgRMW znX*96Js2P9l6ZtzpVM>YXd%C_DBiMpn|^{JA4l$XXlR&pDA#OvNFn7sg>5)sxN2A< zjhN-I_N^wgb|{0o4nd7;535OqR>N1BX=(Mcydu-wyiSKI(=^kz#1^$UwTdaC5|3$B zE8<<b-Kpu)=@w3G&UI_Eg~^4*+PvAD*>LNb`OI1`b91|7qstt<_$3t&GLLUwv0g3r zda#XRG2fj+v_ndw#HEOP33|_?lGEQ%DN@C%)J#a2PtFZ$?KLkqctINm9>Vp9&ZBeb zS}<BCLnXT>!;*a>%aOv4w#K_QN*FGzR-%*4AUf}!n&6mmF4-mI@~W$_?Y3pGEnCc3 zygryZ&=B}dv`Tc!pDLgq^?`_ipvCY^UNLx!dz4r}M?lEK&7;2=ueq_srg@^ps@d-9 z^;Oq3{V~tF>=E*D#+FClWk6Q4LF<ZOTic!9o#UO$jS!)+kR-R+ZpsKm350(8rf-z6 z`djy(`R!4lL6H6%n;+lb?!FZ{s{Ki2E%kxZ1LsyE)GCyIL%5GGir5@wOOqNK4_zC3 z9y^~n>6JRx2cbn;e!6DCX0A>)BlWHdu&9aZMtC2-E*oQ(PVYY9uE2+p*?6Vu!ob4f z!jLhAvC7{`_P^^Z*3~1M@Qv}w!YspKDi&weDlXUd*7JMsIWxHhZ9UJgdXH_7tJW2% zm@)Dx_vBpDUdPqbA1lO(#gP_qXi>Q-JLsJ>CHzQ8q#?wVluuz>^(>Yy=C0w1Oh`(v zWhk{Xn(gAiY@&2ipv`dds=VLm>^Cn+k?YTJa4jBDU7oz(4m?XZ%h=9xt!UQPH+adF zLz$C2x?1*22nQNb9kDS8vNN%h>J#KAI<_n`7?aY09c-8|T5$oRsCt<@Rz6k_<BO*B z+4Oy$7Y#HG9w&Wn+itKFH*p00{g#^(2n98=8F_i*QQO`VGjfNC68*LP=+`E0j;)Z3 z<pyuKslDIuQ^V00GP(+px%E7Vwunlv27OXs!x{Bdex-kQO7Ds7qrPiBIEQE^l=3~Z z%8ikg%h-08f7gxTv~g2vXr;op5oF#$-2JVaE@FjVPHR@#NS(DU_cSDwct^HI)-;dH z`|QzvozyedRcXN}x_cMfhXyktgU*GajQX)Uux(>e(N;+9fxVpF(Q<*c%oINfGg&st zzyQ74s8^;XQG$+7BT{FoKDDON`aF$8WhTA!wO)ligLA2ojg+aA=_zlT^WcnEF@~C6 z2};qjim`T8{pON;$IT$VKNq_-`+{cc@jB&kep(tCC)f1+l)5#EEzRtStJTT$gwXAs zZr!kn&UNkR0>uK~hpt0ztt~x`x(TPPO807grIi+|@o%zCVlG@<_3YNm-xpO{arV^q zye?#Km}V{|_N|r<tJ+pI77VOVm{AfqNF&+sJ<`PG35Sb@_hEa9tZk0%c#anOR%(eW z`BlAUkB%zICdnwIUPfUP?(<O!Ogr-Lx|;7!PV-Swrq{bW-1XP0C>4y{5k1_7P3%ob zjY6mMI87h!bvO!crH*)H*fsxjTWu%K^dYb~eP`AD+pFR_?l3Ruf@NQd5mryoo8oNX zP@_R()F7f^+FM}zW*9%-)@kw8qNh9E<@DeJOx^9_P@8PM&IiRy{cf*`+nPs*yO~Us zvZ(K<qQttcDMv>NRBfl%WY;;0dKA&y(R7)b{6!u+4`**&Trcy?F|(Wnk_8VBY3@}H zM^kZ7n7r@luF4QwFx{K<2lP>zwNK`+&M&xfR;n+$&zF4CE^8n4<~-If`2?>#x$jwi zt;av$W`VP4h4{Q}uQASl9SASC`zBDW7u7<&Ca^H0gea?hA*=}F3wen)8Mfn?DT8)C zryA7m)45ZXEz=BP;mh^wLxv-gZ_E4H;gH3nZ;QoLFJDZ4H@2`4&)i=9w)v$46Ls~z zz1@lp0?Yv6nS_jVR!02#su_#Y1JT!bVrok^4{desZF~uaUhOPuYqHOam3H4+qLyfD z;A#Q?9<1dE0f9~N^nsLCCO?9JfXuK|)pXL7m*X|Ivtcweu`@DdbhUX8P(wiQyYd1} z8&fAkkgJWgts}3i0O=nJUZDNd%|r_NL*is5K&mPK1|(+ZU<%@3WM^b16+{4mK>Q9S zX1vPclF!qDZvvziPEPN6nV4K$To_&080{R)nOJyuc$k=3nOIpF015_2H(Mt|R|Z>0 zvcF9J;UjM9XzXD5-pSI=7WBl|(8$i&Nr05}NzlK~Up-A-E&nIU*74aaz(A&_5hfN! zW~P6615^2*dU@Yix|&*Rid)*4+ByO<1Ub0b`Tx-We@6Z%@jo-Q{x_3_h4a5N|1<JD zlb`9yfd3fu*IR#j0e1-^@H74EdO?Kpfn0H5H3%%l6;**Z)YH-c4=?bcetrY(ml^d9 zhAY6^Qd(R@)fIAYN!DsgjsW(jk4}ZYuu?I&g`ruwi;tmRNw*%&o}_W2G)smWjN`m2 z*`=6GN=p01zcBlagc3B?;e6{MQu>elngRivo6I9Y$TT_Duy`u1JMg9)Z_h(Ur?@W! zBos6p8t4t26C5}w2<FchVP9cvw3tP>rvYJK2){UAUsWh2a-jJ{3<o~=I|m?>78a)U zqsDlm0{WoIFQ3^7XOn|KiNdeo|1f}rf{OF_R}uzVj0`CJnKvY4zrZtJG-`M_Fa?^# zvkJbx8${21;S!*sb1_0mpT!CbJD@)Eg_ePWQid0geHIG>HNgJW84`*D60!*T3;0<q zV9tyGTXQxEV)R=*aeW@{!p?VRq<}D28M{1O>0PL^b8KPIsqKoRkWD?vfqGW!EeXu# zs~AZssrAkv#D<mvg^cjb%*=cnpR?aei}m(oGkjh*PG9v~8n*=})UNJtU7VbqC8VT! zou;hGo?S4c`L^T5_<C>j`px-ngP$WjxXt^1px5o@%rc$Ng)xayk9R#@{U2+YGur)O zb0<^IHfZECGBVtj2eQfx+IoKcc(be~{7&MB;9rB=SD+u_eb4H8hRj-g+3^{i|1OH( z92~u?uuNHxev5nJEt1W0vzxMxkmnT|z$0ojOK7WAqC~wkyvAy#XCRTzaf!*GwX4bH zkaQT|>k|sGpso{|L4{Fw`Ynh2y9BIfNsls5`loT(tpQVTukWr;G0W|i8nIA`_*2Ti zDb2QcxDar^2W9fRVQ|?kTYt@DUukl&JG;D8)V729$Bp?=HkdJzl9FrlHC7EvO&|8d zop+~y{bHwYzrVdab-2mXO&w>36!N|c<#RdMa6nLqT!otcsuiEb{R{cwpSaLQvq<wz z$fV6HkOh`2noKH6jyv&;cmMiyD>jpqgVHMo4`cILYfr>#Jz*KeXcR);$uoYK+<bA` zXEqE7)$)Lg#%xzwGZc*%YHcbUw?@EagV+q(?7xcO!77!S(tiVNC_s1tI`^z0&g1f+ zd#TBVDt)>q65n{G)k`8Pw?`7Ph{RCgnX>MQvM0>z_JZM2nc;p?$a&FLE{)SB+_*Oi zD?k<jjEw8}HwWIf!pt**B857#gnW9c%tyl&;|T=Z*=uc=QcFIfg3U)WBTWaBB3GtZ zpM95Y>Q@U7-p;A=*|l>z-<jff-FUdaUH{n;aBb4&^GJllq(3xhK9U~Bo}C-^oHNYC zP&Vi>Jv}{Z<9V`U3kzwm0lKZ8ZuYiWf?naPtE;*SWM+r66*;q<+}y7%O%7UHTlu*+ z*197iY_R{ywNiv39pQJ=zR38TUB~Oar<zi~Vyji)8a=NaQ24gFw;f5g4Q>|udZUR? zKTovBQYoZU-+=NGw>9h{MaWfnU`hl$F2wO@+y5y?7HV%hpp+4~sT4EQSwVR{1sY~F zd(E!Lq{?scg!0<s1xb_-%oFqn^J319R=<C_X>S)sk?ux7{3pY;5Qb<#!zYia_UB_` zV+1L@e0&j#p>lPO#aWUI2L}fzWpnxQm63lvkP;@W^D_4nyDs5B#ZL_=Dr%KcvVRwB zQe9ZMct3CA{omniTA;AdYV}h5&DnQ!AkfssxFz@BC3uqv)XK!K>(3>z1`93boyRtN z`d?9nG5{-?Y5V64oJW8I*R(j{Jx7Kr1qh@@v0MMw3Sk=<=-hdIUSt5fdzxJg)Xm~J zXWeHlY5^T>m@<Mf|JFz~pmwVD^D;hbp#$hxo2>BtSx_-hKZ{KWlb^LH1$11HEm(aP zqz3f}>^+Z<?wTfRz;Pn#Y17%yfGH=CzzO1m^adn?V}7D#`(~49g8V=*<igZ&Z|a+x zpp!cZ5#SE=fhO=&J>EAK7r1W?4;}0s1SHpOskhYeO?bQ4-VU|YHF>DYrHjMCL6U%= z1AWoZphQ6;*&%Ss{z0w(>1!tg`RBrl{D+JNT0BPC_qXzYx=6w9FaNR-e(H@86^5pP z31tlW!}U)Wz{LD-<FBm0Ox|D5Ta`6r`8>>>Z%_1|?=NtXN$%?~wcS<fxGXt)b*)DW zEti&eBGh2gNLoVA=B<4)&ph7VOfg2`nlp({9LbUM4<YuRwP`t@7VM`;)?M2Kc(L|3 z=`Irc+>Nyy_u#kcBQjLS?2hF~C70yTl0ON*VnRa`84$jY5ks*z?)i8ezj8ifkcFOe zQHo>WIaXTHgD1FFRFJu&u4S4yANDGT1UeWQe{<RMRK9MQbD>_~Vm9Y9|Bk%VR)$Ms zY3=-gRNKu?31P00brMtSRVOk5_YbbsyVFsZLB^)N*+qgWy(gFaU<JI!n*FhV_*b&Q z0k)2H#YfHVx;1|BnDB~soM+9aBaR`2A5zj>*TR;_qWRY-Gn~fFs)poOmf$dumy9A9 z7MEOB_QS^WlJ!#;F23O%?UuDQdK|XQEWQ7Zd=N?&^<G7uLrtT!c!vTyuw66I7fxBh z9Hz7@hD2<UXDdA(lkTw=PFaw%6eX+%bbHv=w%{}&ucId(XW&8(u3PbLnrR*D!?$Z5 z8|GT^l=kQiX0m8S5jcBeFeOFoH7U=xUu`T_qb3D}N+UNEDVT@Q>0-{jDJP0|AVl!E z3)6O|s9+@Qla~%O4Sw=SBO*=XVe2h{H(2f}gJLNbbpLRB_|50>fr#~eph=WGsXsgC zdD0FobPo~W6^9!Hs@*Ado#7B7#~~Km{hFEoaPsJY!KnvU?{@F7VT*|CbcoGGMhV~u z`N~_Z8u@e*h>!#Ki@iCTD`&}kQgDV}@yRPF(QH%buqkmxf%62Ph{vn-XhOR@$6=1- zG{+I1B@9{mRrm9q#4yfHbWhm#m8KHIzK}1PM^WE-zqIUpc(}DIyU6l5Xo%+*ygyUv z4JS3}3PpdwR6hM7hT34B<uwf)JIXfGn4Ryo3$i@t?R#*0<ypF4J@7qJI|9m{mCPmS z*z&j>G;C2Co_k7T<|b<B&$T?<?0N%$h@#Lw&|>0Ru&!zl33%BcfvuHmmc-O@7T2`< zt!WXK*z>1-s`t(I694JYdPW=7CzH6LvuJ^fl-u7q(ajfDM?X70*|**v@MSUiMKCrN z_A(G2w_Gke)-Ai2cs$-;F3lMD?63bQ<E9=JyxrUWtu|AAUAtg=YI%(H8P$!ESucuf z*;UQnO7Dlp87^xFG^T4-PE2rONC&!i+x>-OnoX@19PK^)^yiUDblu-%^D@Mf>$yu{ zpP=xQJ%OY47Z2B)b?m<qRNNmyNBJw)rTmX~r-DHEmmNG@wmk;r24$^y-<IBPW%+m# z+*PkR0U1@n2h8(&jfjb-mof93yS>W(beO9NN8h#McwrM)%k#MV-nISo{$~Jc<EYT% zV%lhuzPsh+f?ZpKj%`DC-4+l!mzG8R^JT6S>oRnu8z<hxtra&^Pnp~&l1%{}7G@PM z&uK4rr{#Z2Z+H1U1hvea%@kw)!-7p!+?C()*@WWdMmQX>qUM#&sk<fL8V7(7)Aw|~ zBHU{_Y+Y8GSSj~uh8Mcth+kzrjfebjyI*%{D7UEFEBgAfP$;nAV=g>~?3g{}NE}cn zRtP<hI#A-0uqg*KT$Xu0L5#2J8rXMZd1EMs_;F#PVDj5nZcJ$yI0JHuQF*s><1tEc zxv241q7a#yndyq!LZpLl@~B8CjVS5T7pnr{Q%*pY=LneGm^@IB{%|m#n_;ju+cCB0 z9S3L%0<#;1J}nlVnkMTdeKHF`=6o;9P@{T6U{-2mmET64kPMv(3#XoR#Aig~4Prxs z1*-@^Ne90rONj|VAxtF?=o4K-Cs>w>#7hjEy3HH2hkz1v*Z?cGPM97qtW#Ld=((Ja zp0EzmuWO|A;4M3)Ug1^k%CQZ<S{ZkF+7pEJ;MnD3TyxATjn2_nmz*Ztl-Y*aCtM@p zU#P}dm9<P;nbvP2b6a@Vn-#HW=Nz^@F1Imw19jnnAqk#H8k3wIZ^5Q61JyX1WatG_ zzD4#C&RXQzN4AlpRkz1?=;U%%=9zB!iYTijkM0zd;1~{erd$K>>t9O%$#22y4NM$6 zlJ}kPROAa#fvhRzB#?e4zWZ^qjNAPybY;zJHKtt@PYu>%GWhK@3h*Qi8uGwfcy94H zY3#PI%yS3T6ADpnno)u`7B16T=GQtgB$O**l&O6!w+Bt${$#%VV^{Kk82j<XLkZ|G zaSIg?b^?xZTACrP?^N)f78bPBy_VUh?mA2c7!TtySpGC{Du`pjV0#5)6gd#0z_?oS zE4$cH)f%29mWY3f2y?7ttt@z^W!WC06nkCRHOT@$l}sPob@hu-f5eTS4+z{PbkaxW z<u#^zdMo;)uczeoTxE{S;j*CI<Dbnl53O9J#jv98BHSibqe8mtac;o{*e$$^21X~> zusm){W}&r61dTA|y5+D1BV)gWGmM>IeitI+!kR##xQ=U!%|P1|8irQFYF!P+SGSJ& z8m_Y2sd^(#v}rd<a+AVh9C!3oC&XOGkjXwsYwsxDx07O%DM=HMDcHw6+TtaV6Cm06 z7ls>ee1Y=bK+TkFEbg=+rX;Q%;oVhTie~y~L18+JkWc;_$Wyr!O5z)GY&LXtxvGuz z6kH~h;*@;){t2*pP<_R0PoQ*t><{k3qgzN=f|y)3sA-Y|pek;E@5uf7dR5_MQ;XTr zNDbR;rx=?5`>8Fat6I9*EuHt~w%tUZ>MuK!&qm}NMO5ctV}nGHGkO7sP^qc~MgL5n zZAkeS{K%*m{5ZR%b^6NREI-oa`<2iRum?+X?=M;8L>6~8gl2K|V23>&XR@*2>djc) zfJz+KQDT9S|1pL86Fix;d4ARqEwigAUZ+U{C0I^@<Rko;rzPttO`~*1%GK4N3^68k z9~d_b9^-tF%uX)wGojDjv6M2j3H746k!<`&v@y9z>1IqtewM|HEJIPIoiu)blU76N zR^TY&s@8fOWQnpi7=9g0-Zen5;J9les3-jpQ{moKjV$fcJ*oos_#pyI;bs;T;;NO! zGR76JsQyYZRW$1e7c<xFHsS%<?R0VLyv|ZK&b90D=sPOgZmKip30meQJ35K?RZD5Z zW~x@d;~@txN(wf;<<lV}E=`C@9}*uuS2yL=Q`$zLTZDs-FNj|<>Rc<kOaTc=oP|;< zC5JGMn=(h;FC-sh1ZCvSx}D3=5Jg3{qb#{onsx0@Zo^(Bq8!Ncg6cA2AXpdLW-*-Z zTT1ShEE_aUX8CY`YrsWGarSR0o42l%-vA}3b8qPI8qk=cV^j+Yy@FnnZd_k1*v%-Q zb;G?D)r<%X<4-_;vS`rLH_mgIUsE**A&_hGGm;4H&?MBDLmZQ4Labyj<UH=Y$n9xh zE7Gxe%*mT^FQD*fM+&Pz_j_W+`O(=t&=gZ+^1R68xx$txNy$=<^FbF8C7Z(S>>_-* zS^Xhj-Hk=0aw*I)M~qYy_n6#pa60~WLydeBl+}f7Cbz~V76Y~$X_RiA93xnzb6K>P z`o{T@J!MJM<I1FR_y#dwWG!K8L`fm3Yo7fyY%n~|4Ru(ikZm)Sv_f7izMe(oU2WT1 zW7@i>5*BSUTHsA>9B7V(LAup4{+&_~9wF@72NTO`(NBRv7vUfn)iWBv`{ranUWtfe zjkc@xY`wsgd%br=LxZ7nkk-XO3Qp<d6=RMFYBXx4A!8AtEzaWkMrGOsy<NW^C3`S) zQW7eUCUkcsraWv0j}f2CqfJFw<qMN_wJjX{dsK6%pQnhc3vOSfR0ym=*ToqsH^2#d z*H~4(Pr9QJlBM2GLJ1zez-iScS<$}tnzt;Vu-B1}G3t!FNT!3TinaH>^QT0@bYOsg zP$31^#3<JTIZ`T`P2+De7#r`$JFWXlEvl{~TVU4faw+1Ax)Ixuk4TIWF+61+>o~p0 zmlng$>O_MeiFH-{wVnt5bF|!9CH@cNQHX&~bMIPBL=jDo!%kaD`Q^U!wo3fGw3FFe zFw^0m)N@)Ktu-oVCS3h||HqxSjobO;E82M9XSG@qp=rFMPCT<K+bvB9Kv~&t#l5*W zJxJ)eUx|JQ0Fl7^!Y>~V1DZ+>yJp#aeE`+~Hr+LXT)*hT0F8Wz{j(RagXt-$@da|o z#u&xRGB_$N<9pVlDh*(=GklJ8gQii4=z)`$cfF-5CG3wAH*{9*W3tLq#i+n+?JDUT zKns~&DV{EF)Kq!(6sUBZTa^xUimvE>2`@hmR<kjUz85;9!E0k3|ILjSKR{Y=GYhE? zT_iV3{SENkFbG)Y&N@n@$rPiVMAtZJrh=%`P%qL4ME_TOvGd<1?Wf*(+a-azql&H` zHsG&<1j{2CO1{hqDhYn=gT}KW+aUpehDhIaJ1y8t@%_9%P@)K4(8}t#&N_)mf2<ln z9UQh)aW~ZuMU6$sCmINaSFXB;IfmE9*ooPiz)3?d5~G91=nCcU`0|mR7p03ySb_;u zk)@9<5?;4Xy_;^3pAk+6M56}@pk}z2)9b}kb+S1Yw8U8_^s*~Mj8WyS-hASh`y(JQ z{l57pJ|C?YR?VGXL;FkxScfslPmm~C=M@PjplmC&$V)4VY8v~ZOr-mefM5-4Rs=Rp zgu(k$Xk^g#4~s4g_P{_ap112BU4aH=<)bRUneHaWG18}YS>|#l)&dp1t_Rr)dZK2# zBH%Huf&J5-@W(@U310uohfGDVYM~Xbe;^IZPn<M~e!dTZo87rj_IRF8X~1uyjoP(d z=ZjS=Mo3!%hFzA^o?Pz6G}!*Ro+6+DRW8=fTG{YN4}ZJxP<9wGc<-v;H}t5MpyZd* z{(?P8B5;!&$4oqvp+4D1@_%*cn2@<qWUhNz&BnSaF^=Hh1&v$H{`UQt1ddx9{rl>S zukogHfu=U;7QJcYm}u9+lFUJsO2%>z;86p)7$f<heP%twGJHxpITC9hUoD2*7X_L| zHVF2hcRxD>C9e`$#$em9s<E}8c}AE#qigiOmdna&684{}s=o)LQcCX(<wv4{=aICc zvx0scus@ZSE4{8X31yT~3Qd@OluIM!#ov;#wWpp~;w=3gs#@xJxUke@obo3hML$?z zn!JW0tV^pkN6&R#S32?S8#m`(*|K~wSgUvp+_No&pi>3k1==+6(Dh%0&@6VOkwIIB zIXN)KeG*>m!MEGve#4<?ovjd64kqR>dhynQ9ac&_FhJ(?WT4Stw-9}&_w(oT^xdS9 zw&j~omL2=Rr9qI#e8L{inx6Bjsb*SxkhltMCAtlt<fxbNy`+YAUmEL4V9x8#2K}El zB@>>i3!{DeKp6}Ag%RucjoTq$UC*eZf4FW?PU3hUWo5h0I9gy@o_jTruydR%JPMCx z%gLvm#<D$ve=r<f(MLBdwr?nxANH*g9iEr#O(D81=Ym0g|8eh*$vLi6Rf_uPTtwgk zaNqSJ)OMbPgXIsvHwv8o^x=mO(`ngLY2#TAT6v$jSN<I(Do6jL36)f2?z#g}Hu~L} zjgK#9$i2+p6BfD!7L`drJ8&|voAosMAbc8|N73FDv`KcQkCt`#)s{qv&xdAAIrp-_ zuq@?`!i`P+GG}-3^=x$T+3^SH8cx(9+Op-F?vms+(+B&^6zX+k1hFO-0bg0{S`q=n zt}qUzw?h>KDQ#<|uiDA5k9zko`CvjS`$tDC2N(VLH~iH78Q_dC;kTumt~b*(2CNxn zGCyS7jc-|+@3^WcR%1jW<WJ6CM&5ks7On~~OW0z4>zhO>o4Q>VL%jKJXq^7Bw>Q{W zQdFpyZhOEYrc+^Va%BXJBym0J8ZUp>hlh1U!-w*AS<EWkTcIzcHb)C_Q#Lb=zQdfZ z#SUkGh;_j<Z|1441`6Z(C0WE6sRx^da@pfg>H@GLt72jF`e{aeE(=?TP+tvzV{TJF z-qgr1kEE-4H4tc8ZKnCOplm~pF=h)eSNW}%atkJ~5pwOO2KYu+*L&aJOieM_6P=-( z=Af?~saE5fcEJ@0W#cf&wS-J0^=FAW^XTHNf|jZ!OXT#sV651s2~r0Piz2~Q_lX*m z+T>*41XI52@<7*X;c~o7nA!ZY&2jp!YOX=D2NK~It|@(rVKD9@aFsV`BzkL`yHZf% zaz~>Vitz-kV8d0XgPd_Dna5IA;_VblC_f+g%WGKo0w`n)yxGrozY%pc=Wg2CuL`x= zV}?YwU1w=(@Zf&n*6)dy?;xj*@y8=g0MM0i41I(>ARbZMJ$W}m;KXLMt*#;R6S(Nv zi-n+^PleqVHp<)&OnxWWZDCT&3?3PB32R#dAeLqWgHLx=Yx7z@$k*(qzw$gp0j$gK zz#l+iBo*g(aLi?=yh3fHf0|`DPk+>GoKiz;UksdsS9z^)z8=MAt5KxA?T$pm&rPzK z;(U9tzw3T^us^I&J3cWd)7oWERA6#SMW-jp+tC+GmQmX0NGAF5eXW!hujb4jIkn;d z+?KPTMbf2nUT*jugH1=0eQAdj4hfIF?-ntVNPw55RxkHmUa=qQG5|E`XyB<&R5+Aq zu~6Byv3~TlUO=1yaA>nCRrf!Rs1tr-hi@<5gPxkVbxtod+9z7~AOUU7k?V5SdyQYP zQ=xSPTS>UsLY!Edy8GjmXOOkIbKOxVq6?hW#>-8U0h5SO;P(rTxS;VrmAa7vK#Z0u zb*2gre1$b(dUr(B8H_{;7U18y{KlyPphdq6KxC1?jaDgu-8`d&G9Zw@Dipm0*1tXT zFCfu#FMgZX{117g_5(Z&U;aw%Uo6rB6+o2cbF!vno^1JpKW0M%;wjpdRsYu`03d+x zqP^AW{zWMLFyKN#i4d|%|LggGN>|6fnt5zmX5B-x=dX+i)G@b8-9-$dW~{~shL B1#tiX literal 0 HcmV?d00001 diff --git a/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts index 744bce338a..2b23a1e19f 100644 --- a/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts +++ b/e2e/core/viewer/file-extensions/viewer-arcive.component.e2e.ts @@ -15,21 +15,21 @@ * limitations under the License. */ -import TestConfig = require('../../test.config'); +import TestConfig = require('../../../test.config'); import { LoginPage } from '@alfresco/adf-testing'; -import { ViewerPage } from '../../pages/adf/viewerPage'; -import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import { ViewerPage } from '../../../pages/adf/viewerPage'; +import { ContentServicesPage } from '../../../pages/adf/contentServicesPage'; -import CONSTANTS = require('../../util/constants'); -import resources = require('../../util/resources'); +import CONSTANTS = require('../../../util/constants'); +import resources = require('../../../util/resources'); import { StringUtil } from '@alfresco/adf-testing'; -import { FolderModel } from '../../models/ACS/folderModel'; -import { AcsUserModel } from '../../models/ACS/acsUserModel'; +import { FolderModel } from '../../../models/ACS/folderModel'; +import { AcsUserModel } from '../../../models/ACS/acsUserModel'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { UploadActions } from '../../actions/ACS/upload.actions'; +import { UploadActions } from '../../../actions/ACS/upload.actions'; describe('Viewer', () => { diff --git a/e2e/core/viewer/file-extensions/viewer-component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-component.e2e.ts index 59a140906c..49f0c71a67 100644 --- a/e2e/core/viewer/file-extensions/viewer-component.e2e.ts +++ b/e2e/core/viewer/file-extensions/viewer-component.e2e.ts @@ -33,7 +33,6 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../../actions/ACS/upload.actions'; import { NavigationBarPage } from '../../..//pages/adf/navigationBarPage'; - describe('Viewer', () => { const viewerPage = new ViewerPage(); diff --git a/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts b/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts index 9db136c4f3..a98518b53e 100644 --- a/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts +++ b/e2e/core/viewer/file-extensions/viewer-text.component.e2e.ts @@ -104,6 +104,4 @@ describe('Viewer', () => { }); }); - - }); diff --git a/lib/content-services/content-metadata/services/property-groups-translator.service.ts b/lib/content-services/content-metadata/services/property-groups-translator.service.ts index 2833552aba..5ec97325fe 100644 --- a/lib/content-services/content-metadata/services/property-groups-translator.service.ts +++ b/lib/content-services/content-metadata/services/property-groups-translator.service.ts @@ -25,7 +25,9 @@ import { CardViewDatetimeItemModel, CardViewIntItemModel, CardViewFloatItemModel, - LogService + LogService, + MultiValuePipe, + AppConfigService } from '@alfresco/adf-core'; import { Property, CardViewGroup, OrganisedPropertyGroup } from '../interfaces/content-metadata.interfaces'; @@ -46,7 +48,12 @@ export class PropertyGroupTranslatorService { static readonly RECOGNISED_ECM_TYPES = [D_TEXT, D_MLTEXT, D_DATE, D_DATETIME, D_INT, D_LONG, D_FLOAT, D_DOUBLE, D_BOOLEAN]; - constructor(private logService: LogService) { + valueSeparator: string; + + constructor(private logService: LogService, + private multiValuePipe: MultiValuePipe, + private appConfig: AppConfigService) { + this.valueSeparator = this.appConfig.get<string>('content-metadata.multi-value-pipe-separator'); } public translateToCardViewGroups(propertyGroups: OrganisedPropertyGroup[], propertyValues): CardViewGroup[] { @@ -115,7 +122,9 @@ export class PropertyGroupTranslatorService { case D_TEXT: default: cardViewItemProperty = new CardViewTextItemModel(Object.assign(propertyDefinition, { - multiline: false + multivalued: property.multiValued, + multiline: property.multiValued, + pipes: [{ pipe: this.multiValuePipe, params: [this.valueSeparator]}] })); } diff --git a/lib/core/app-config/schema.json b/lib/core/app-config/schema.json index ecfe2b9969..bf6809bf16 100644 --- a/lib/core/app-config/schema.json +++ b/lib/core/app-config/schema.json @@ -859,6 +859,10 @@ ] } } + }, + "multi-value-pipe-separator": { + "description": "Content metadata's separator for multi value properties", + "type": "string" } } }, diff --git a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts index 6a44787326..deeabaf1b7 100644 --- a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts +++ b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts @@ -18,6 +18,7 @@ import { Component, Input, OnChanges, ViewChild } from '@angular/core'; import { CardViewTextItemModel } from '../../models/card-view-textitem.model'; import { CardViewUpdateService } from '../../services/card-view-update.service'; +import { AppConfigService } from '../../../app-config/app-config.service'; @Component({ selector: 'adf-card-view-textitem', @@ -25,6 +26,9 @@ import { CardViewUpdateService } from '../../services/card-view-update.service'; styleUrls: ['./card-view-textitem.component.scss'] }) export class CardViewTextItemComponent implements OnChanges { + + static DEFAULT_SEPARATOR = ', '; + @Input() property: CardViewTextItemModel; @@ -40,12 +44,15 @@ export class CardViewTextItemComponent implements OnChanges { inEdit: boolean = false; editedValue: string; errorMessages: string[]; + valueSeparator: string; - constructor(private cardViewUpdateService: CardViewUpdateService) { + constructor(private cardViewUpdateService: CardViewUpdateService, + private appConfig: AppConfigService) { + this.valueSeparator = this.appConfig.get<string>('content-metadata.multi-value-pipe-separator') || CardViewTextItemComponent.DEFAULT_SEPARATOR; } ngOnChanges(): void { - this.editedValue = this.property.value; + this.editedValue = this.property.multiline ? this.property.displayValue : this.property.value; } showProperty(): boolean { @@ -78,20 +85,29 @@ export class CardViewTextItemComponent implements OnChanges { } reset(): void { - this.editedValue = this.property.value; + this.editedValue = this.property.multiline ? this.property.displayValue : this.property.value; this.setEditMode(false); } update(): void { if (this.property.isValid(this.editedValue)) { - this.cardViewUpdateService.update(this.property, this.editedValue); - this.property.value = this.editedValue; + const updatedValue = this.prepareValueForUpload(this.property, this.editedValue); + this.cardViewUpdateService.update(this.property, updatedValue); + this.property.value = updatedValue; this.setEditMode(false); } else { this.errorMessages = this.property.getValidationErrors(this.editedValue); } } + prepareValueForUpload(property: CardViewTextItemModel, value: string): string | string [] { + const listOfValues = value; + if (property.multivalued) { + return listOfValues.split(this.valueSeparator); + } + return listOfValues; + } + onTextAreaInputChange() { this.errorMessages = this.property.getValidationErrors(this.editedValue); } diff --git a/lib/core/card-view/interfaces/card-view-textitem-properties.interface.ts b/lib/core/card-view/interfaces/card-view-textitem-properties.interface.ts index d80fa18d1e..511271e8d3 100644 --- a/lib/core/card-view/interfaces/card-view-textitem-properties.interface.ts +++ b/lib/core/card-view/interfaces/card-view-textitem-properties.interface.ts @@ -20,6 +20,7 @@ import { CardViewTextItemPipeProperty } from './card-view-textitem-pipe-property export interface CardViewTextItemProperties extends CardViewItemProperties { multiline?: boolean; + multivalued?: boolean; pipes?: CardViewTextItemPipeProperty[]; clickCallBack?: any; } diff --git a/lib/core/card-view/models/card-view-textitem.model.ts b/lib/core/card-view/models/card-view-textitem.model.ts index 32a6acabb0..22de7d0b23 100644 --- a/lib/core/card-view/models/card-view-textitem.model.ts +++ b/lib/core/card-view/models/card-view-textitem.model.ts @@ -23,12 +23,14 @@ import { CardViewTextItemPipeProperty, CardViewTextItemProperties } from '../int export class CardViewTextItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel { type: string = 'text'; multiline?: boolean; + multivalued?: boolean; pipes?: CardViewTextItemPipeProperty[]; clickCallBack?: any; constructor(cardViewTextItemProperties: CardViewTextItemProperties) { super(cardViewTextItemProperties); this.multiline = !!cardViewTextItemProperties.multiline; + this.multivalued = !!cardViewTextItemProperties.multivalued; this.pipes = cardViewTextItemProperties.pipes || []; this.clickCallBack = cardViewTextItemProperties.clickCallBack ? cardViewTextItemProperties.clickCallBack : null; } diff --git a/lib/core/pipes/multi-value.pipe.spec.ts b/lib/core/pipes/multi-value.pipe.spec.ts new file mode 100644 index 0000000000..acc3ce103c --- /dev/null +++ b/lib/core/pipes/multi-value.pipe.spec.ts @@ -0,0 +1,66 @@ +/*! + * @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 { MultiValuePipe } from './multi-value.pipe'; +import { TestBed } from '@angular/core/testing'; +import { setupTestBed } from 'core'; +import { CoreTestingModule } from 'core/testing/core.testing.module'; + +describe('FullNamePipe', () => { + + let pipe: MultiValuePipe; + + setupTestBed({ + imports: [CoreTestingModule] + }); + + beforeEach(() => { + pipe = TestBed.get(MultiValuePipe); + + }); + + it('should add the separator when a list is provided', () => { + const values = ['cat', 'house', 'dog']; + expect(pipe.transform(values)).toBe('cat, house, dog'); + }); + + it('should add custom separator when set', () => { + const values = ['cat', 'house', 'dog']; + const customSeparator = ' - '; + expect(pipe.transform(values, customSeparator)).toBe('cat - house - dog'); + }); + + it('should not add separator when the list has only one item', () => { + const values = ['cat']; + expect(pipe.transform(values)).toBe('cat'); + }); + + it('should return empty string when an empty list is passed', () => { + const values = []; + expect(pipe.transform(values)).toBe(''); + }); + + it('should return empty string when an empty string is passed', () => { + const values = ''; + expect(pipe.transform(values)).toBe(''); + }); + + it('should return same string when the value passed is a string', () => { + const values = 'cat'; + expect(pipe.transform(values)).toBe('cat'); + }); +}); diff --git a/lib/core/pipes/multi-value.pipe.ts b/lib/core/pipes/multi-value.pipe.ts new file mode 100644 index 0000000000..a75a2959f0 --- /dev/null +++ b/lib/core/pipes/multi-value.pipe.ts @@ -0,0 +1,34 @@ +/*! + * @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 { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ name: 'multiValue' }) +export class MultiValuePipe implements PipeTransform { + + static DEFAULT_SEPARATOR = ', '; + + transform(values: string | string [], valueSeparator: string = MultiValuePipe.DEFAULT_SEPARATOR): string { + + if (values && values instanceof Array) { + values.map((value) => value.trim()); + return values.join(valueSeparator); + } + + return <string> values; + } +} diff --git a/lib/core/pipes/pipe.module.ts b/lib/core/pipes/pipe.module.ts index 2bd70806eb..8d1311671f 100644 --- a/lib/core/pipes/pipe.module.ts +++ b/lib/core/pipes/pipe.module.ts @@ -27,6 +27,7 @@ import { InitialUsernamePipe } from './user-initial.pipe'; import { FullNamePipe } from './full-name.pipe'; import { FormatSpacePipe } from './format-space.pipe'; import { FileTypePipe } from './file-type.pipe'; +import { MultiValuePipe } from './multi-value.pipe'; @NgModule({ imports: [ @@ -41,7 +42,8 @@ import { FileTypePipe } from './file-type.pipe'; FullNamePipe, NodeNameTooltipPipe, FormatSpacePipe, - FileTypePipe + FileTypePipe, + MultiValuePipe ], providers: [ FileSizePipe, @@ -51,7 +53,8 @@ import { FileTypePipe } from './file-type.pipe'; InitialUsernamePipe, NodeNameTooltipPipe, FormatSpacePipe, - FileTypePipe + FileTypePipe, + MultiValuePipe ], exports: [ FileSizePipe, @@ -62,7 +65,8 @@ import { FileTypePipe } from './file-type.pipe'; FullNamePipe, NodeNameTooltipPipe, FormatSpacePipe, - FileTypePipe + FileTypePipe, + MultiValuePipe ] }) export class PipeModule { diff --git a/lib/core/pipes/public-api.ts b/lib/core/pipes/public-api.ts index a40350bacf..9746057417 100644 --- a/lib/core/pipes/public-api.ts +++ b/lib/core/pipes/public-api.ts @@ -22,5 +22,6 @@ export * from './text-highlight.pipe'; export * from './time-ago.pipe'; export * from './user-initial.pipe'; export * from './full-name.pipe'; +export * from './multi-value.pipe'; export * from './pipe.module'; From 181cee72d67825756b323d78ab56378f285d1a87 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Thu, 18 Apr 2019 11:34:16 +0200 Subject: [PATCH 122/208] [ADF-4364] Fix Back button action on Viewer Component (#4613) * [ADF-3364] Fix Back button action on Viewer Component * [ADF-4364] Fix Module providers * [ADF-4364] Add unit tests * [ADF-4364] Fix unit tests * [ADF-4364] Fix lazy loading module of Viewer component --- .../services/previous-route.service.spec.ts | 61 +++++++++++++++++ lib/core/services/previous-route.service.ts | 42 ++++++++++++ lib/core/services/public-api.ts | 1 + .../components/pdfViewer.component.spec.ts | 6 +- .../components/viewer.component.spec.ts | 66 ++++++++++++++++++- .../viewer/components/viewer.component.ts | 16 ++++- .../viewer-extension.directive.spec.ts | 4 +- 7 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 lib/core/services/previous-route.service.spec.ts create mode 100644 lib/core/services/previous-route.service.ts diff --git a/lib/core/services/previous-route.service.spec.ts b/lib/core/services/previous-route.service.spec.ts new file mode 100644 index 0000000000..5972b95d1e --- /dev/null +++ b/lib/core/services/previous-route.service.spec.ts @@ -0,0 +1,61 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { setupTestBed } from '../testing/setupTestBed'; +import { PreviousRouteService } from './previous-route.service'; +import { Router, NavigationEnd } from '@angular/router'; +import { Observable } from 'rxjs'; +import { CoreTestingModule } from 'core/testing/core.testing.module'; + +class MockRouter { + firstUrl = new NavigationEnd(0, '/files', '/files'); + secondUrl = new NavigationEnd(0, '/home', '/home'); + events = new Observable((observer) => { + observer.next(this.firstUrl); + observer.next(this.secondUrl); + observer.complete(); + }); +} + +describe('Previous route service ', () => { + + let previousRouteService: PreviousRouteService; + + setupTestBed({ + imports: [ + CoreTestingModule + ], + providers: [ + { provide: Router, useClass: MockRouter }, + PreviousRouteService + ] + }); + + beforeEach(() => { + previousRouteService = TestBed.get(PreviousRouteService); + }); + + it('should be able to create the service', () => { + expect(previousRouteService).not.toBeNull(); + expect(previousRouteService).toBeDefined(); + }); + + it('should set curent url when new page loads', () => { + expect(previousRouteService.getPreviousUrl()).toBe('/files'); + }); +}); diff --git a/lib/core/services/previous-route.service.ts b/lib/core/services/previous-route.service.ts new file mode 100644 index 0000000000..d545943723 --- /dev/null +++ b/lib/core/services/previous-route.service.ts @@ -0,0 +1,42 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; + +@Injectable({ + providedIn: 'root' +}) +export class PreviousRouteService { + + private previousUrl: string; + private currentUrl: string; + + constructor(private router: Router) { + this.currentUrl = this.router.url; + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + this.previousUrl = this.currentUrl; + this.currentUrl = event.url; + } + }); + } + + public getPreviousUrl(): string { + return this.previousUrl; + } +} diff --git a/lib/core/services/public-api.ts b/lib/core/services/public-api.ts index 3af0268852..f9bf816079 100644 --- a/lib/core/services/public-api.ts +++ b/lib/core/services/public-api.ts @@ -55,3 +55,4 @@ export * from './jwt-helper.service'; export * from './download-zip.service'; export * from './lock.service'; export * from './automation.service'; +export * from './previous-route.service'; diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index ae84a6424c..bf27dac71a 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -276,23 +276,21 @@ describe('Test PdfViewer component', () => { document.body.removeChild(elementBlobTestComponent); }); - it('should Canvas be present', (done) => { + it('should Canvas be present', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { expect(elementBlobTestComponent.querySelector('.adf-pdfViewer')).not.toBeNull(); expect(elementBlobTestComponent.querySelector('.adf-viewer-pdf-viewer')).not.toBeNull(); - done(); }); }); - it('should Next an Previous Buttons be present', (done) => { + it('should Next an Previous Buttons be present', () => { fixtureBlobTestComponent.detectChanges(); fixtureBlobTestComponent.whenStable().then(() => { expect(elementBlobTestComponent.querySelector('#viewer-previous-page-button')).not.toBeNull(); expect(elementBlobTestComponent.querySelector('#viewer-next-page-button')).not.toBeNull(); - done(); }); }); diff --git a/lib/core/viewer/components/viewer.component.spec.ts b/lib/core/viewer/components/viewer.component.spec.ts index a9865e1b30..c915d8713f 100644 --- a/lib/core/viewer/components/viewer.component.spec.ts +++ b/lib/core/viewer/components/viewer.component.spec.ts @@ -18,18 +18,21 @@ import { Location } from '@angular/common'; import { SpyLocation } from '@angular/common/testing'; import { Component } from '@angular/core'; -import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; +import { ComponentFixture, TestBed, fakeAsync, tick, async } from '@angular/core/testing'; import { AlfrescoApiService, RenditionsService } from '../../services'; import { CoreModule } from '../../core.module'; -import { throwError } from 'rxjs'; +import { throwError, Observable } from 'rxjs'; import { EventMock } from '../../mock/event.mock'; import { RenderingQueueServices } from '../services/rendering-queue.services'; import { ViewerComponent } from './viewer.component'; import { setupTestBed } from '../../testing/setupTestBed'; import { AlfrescoApiServiceMock } from '../../mock/alfresco-api.service.mock'; import { NodeEntry } from '@alfresco/js-api'; +import { PreviousRouteService } from 'core/services/previous-route.service'; +import { RouterTestingModule } from '@angular/router/testing'; +import { Router, NavigationEnd } from '@angular/router'; @Component({ selector: 'adf-viewer-container-toolbar', @@ -120,16 +123,28 @@ class ViewerWithCustomOpenWithComponent { class ViewerWithCustomMoreActionsComponent { } +class MockRouter { + navigate = jasmine.createSpy('navigate'); + firstUrl = new NavigationEnd(0, '/files', '/files'); + events = new Observable((observer) => { + observer.next(this.firstUrl); + observer.complete(); + }); +} + describe('ViewerComponent', () => { let component: ViewerComponent; let fixture: ComponentFixture<ViewerComponent>; let alfrescoApiService: AlfrescoApiService; + let previousRouteService: PreviousRouteService; + let router: Router; let element: HTMLElement; setupTestBed({ imports: [ - CoreModule.forRoot() + CoreModule.forRoot(), + RouterTestingModule ], declarations: [ ViewerWithCustomToolbarComponent, @@ -147,7 +162,9 @@ describe('ViewerComponent', () => { } } }, + { provide: Router, useClass: MockRouter }, RenderingQueueServices, + PreviousRouteService, { provide: Location, useClass: SpyLocation } ] }); @@ -158,6 +175,8 @@ describe('ViewerComponent', () => { component = fixture.componentInstance; alfrescoApiService = TestBed.get(AlfrescoApiService); + previousRouteService = TestBed.get(PreviousRouteService); + router = TestBed.get(Router); }); describe('Extension Type Test', () => { @@ -623,6 +642,47 @@ describe('ViewerComponent', () => { }); }); + it('should render close viewer button if it is not a shared link', (done) => { + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(element.querySelector('[data-automation-id="adf-toolbar-back"]')).toBeDefined(); + expect(element.querySelector('[data-automation-id="adf-toolbar-back"]')).not.toBeNull(); + done(); + }); + }); + + it('should go back when back button is clicked', async(() => { + + spyOn(previousRouteService, 'getPreviousUrl').and.returnValue('home'); + + const button: HTMLButtonElement = element.querySelector('[data-automation-id="adf-toolbar-back"]') as HTMLButtonElement; + button.click(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(router.navigate).toHaveBeenCalled(); + }); + })); + + it('should render close viewer button if it is a shared link', (done) => { + spyOn(alfrescoApiService.getInstance().core.sharedlinksApi, 'getSharedLink') + .and.returnValue(Promise.reject({})); + + component.sharedLinkId = 'the-Shared-Link-id'; + component.urlFile = null; + component.mimeType = null; + + component.ngOnChanges(null); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(element.querySelector('[data-automation-id="adf-toolbar-back"]')).toBeNull(); + done(); + }); + }); + }); describe('View', () => { diff --git a/lib/core/viewer/components/viewer.component.ts b/lib/core/viewer/components/viewer.component.ts index 30787a25a4..1b95a7c66d 100644 --- a/lib/core/viewer/components/viewer.component.ts +++ b/lib/core/viewer/components/viewer.component.ts @@ -25,6 +25,7 @@ import { RenditionPaging, SharedLinkEntry, Node, RenditionEntry, NodeEntry } fro import { BaseEvent } from '../../events'; import { AlfrescoApiService } from '../../services/alfresco-api.service'; import { LogService } from '../../services/log.service'; +import { PreviousRouteService } from '../../services/previous-route.service'; import { ViewerMoreActionsComponent } from './viewer-more-actions.component'; import { ViewerOpenWithComponent } from './viewer-open-with.component'; import { ViewerSidebarComponent } from './viewer-sidebar.component'; @@ -32,6 +33,7 @@ import { ViewerToolbarComponent } from './viewer-toolbar.component'; import { Subscription } from 'rxjs'; import { ViewUtilService } from '../services/view-util.service'; import { AppExtensionService, ViewerExtensionRef } from '@alfresco/adf-extensions'; +import { Router } from '@angular/router'; @Component({ selector: 'adf-viewer', @@ -239,7 +241,9 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { private logService: LogService, private location: Location, private extensionService: AppExtensionService, - private el: ElementRef) { + private el: ElementRef, + private router: Router, + private previousRouteService: PreviousRouteService) { } isSourceDefined(): boolean { @@ -304,6 +308,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { } ); } else if (this.sharedLinkId) { + this.allowGoBack = false; this.apiService.sharedLinksApi.getSharedLink(this.sharedLinkId).then( (sharedLinkEntry: SharedLinkEntry) => { @@ -479,7 +484,14 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy { this.goBack.next(event); if (!event.defaultPrevented) { - this.location.back(); + + const previousUrl = this.previousRouteService.getPreviousUrl(); + + if (previousUrl && previousUrl.includes('login') || window.history.length <= 2) { + this.router.navigate([{outlets: {overlay: null, primary: ['home']}}]); + } else { + this.location.back(); + } } } } diff --git a/lib/core/viewer/directives/viewer-extension.directive.spec.ts b/lib/core/viewer/directives/viewer-extension.directive.spec.ts index b6217502cf..4970b21fbe 100644 --- a/lib/core/viewer/directives/viewer-extension.directive.spec.ts +++ b/lib/core/viewer/directives/viewer-extension.directive.spec.ts @@ -23,6 +23,7 @@ import { ViewerComponent } from '../components/viewer.component'; import { ViewerExtensionDirective } from './viewer-extension.directive'; import { setupTestBed } from '../../testing/setupTestBed'; import { CoreModule } from '../../core.module'; +import { RouterTestingModule } from '@angular/router/testing'; describe('ExtensionViewerDirective', () => { let extensionViewerDirective: ViewerExtensionDirective; @@ -35,7 +36,8 @@ describe('ExtensionViewerDirective', () => { setupTestBed({ imports: [ - CoreModule.forRoot() + CoreModule.forRoot(), + RouterTestingModule ], providers: [ { provide: Location, useClass: SpyLocation }, From 64be9e3624821be5db9b75ce0b83dbe94cce65ac Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 18 Apr 2019 13:31:42 +0200 Subject: [PATCH 123/208] [NO-ISSUE] Fix e2e test (#4621) * fix sso, change timeout, parallel * cange travis * move name apps in resources file * resources fix * resources fix * add sleep before search group * add possibility to extend duration of snack-bar message from configuration * fix unit test * fix unit test * remove timeout * change timeout * decrease message time * add lint main branch travis * reduce timeout * add new check application presence * change permission script fix search selector * fix travis conf * check app environment and upload the app if abbsent * fix cloud test * remove duplicate * restore ps test * restore resources file * fix e2e test * process with variables missing * test new conf travis * fix lint * fix spellcheck * remove duplicate module * fix ps module * fix travis conf * change check activiti env * add concept of processes in resources --- .travis.yml | 40 ++-- cspell.json | 3 +- demo-shell/src/app.config.json | 1 + .../form-demo/cloud-form-demo.component.ts | 5 +- .../start-process-cloud-demo.component.ts | 5 +- .../cloud/start-task-cloud-demo.component.ts | 10 +- .../config-editor/config-editor.component.ts | 21 +- .../app/components/files/files.component.ts | 10 +- .../src/app/components/form/form.component.ts | 7 +- .../permissions/demo-permissions.component.ts | 5 +- docs/core/services/notification.service.md | 8 + .../document-list-actions.e2e.ts | 3 +- .../permissions/site-permissions.e2e.ts | 10 +- .../search/components/search-checkList.ts | 2 +- e2e/pages/adf/notificationPage.ts | 3 - e2e/pages/adf/viewerPage.ts | 2 +- .../apps-section-cloud.e2e.ts | 4 +- .../edit-process-filters-component.e2e.ts | 11 +- .../edit-task-filters-component.e2e.ts | 11 +- .../people-group-cloud-component.e2e.ts | 78 +------- ...people-group-cloud-filter-component.e2e.ts | 174 ++++++++++++++++ .../process-custom-filters.e2e.ts | 16 +- .../process-filters-cloud.e2e.ts | 11 +- .../process-header-cloud.e2e.ts | 10 +- .../processList-cloud-component.e2e.ts | 20 +- .../start-process-cloud.e2e.ts | 13 +- .../start-task-custom-app-cloud.e2e.ts | 9 +- .../task-filters-cloud.e2e.ts | 8 +- .../task-header-cloud.e2e.ts | 9 +- .../task-list-properties.e2e.ts | 16 +- .../task-list-selection.e2e.ts | 7 +- .../tasks-custom-filters.e2e.ts | 11 +- .../candidateuserapp.zip} | Bin e2e/resources/activiti7/simpleApp.zip | Bin 0 -> 3184 bytes e2e/resources/activiti7/subProcessApp.zip | Bin 0 -> 2815 bytes e2e/resources/aps2/simple_app.zip | Bin 3019 -> 0 bytes e2e/search/components/search-checkList.e2e.ts | 75 ++----- e2e/search/components/search-text.e2e.ts | 2 +- e2e/search/search-page-component.e2e.ts | 2 +- e2e/util/resources.js | 39 ++-- lib/core/app-config/app-config.service.ts | 3 +- lib/core/clipboard/clipboard.service.spec.ts | 22 +- .../services/notification.service.spec.ts | 4 +- lib/core/services/notification.service.ts | 18 +- .../src/lib/form/form-cloud.module.ts | 4 +- .../src/lib/task/task-cloud.module.ts | 7 +- .../actions/process-definitions.service.ts | 14 +- ...dit-process-filter-cloud-component.page.ts | 2 +- .../pages/group-cloud-component.page.ts | 4 +- .../pages/people-cloud-component.page.ts | 5 +- .../process-header-cloud-component.page.ts | 4 +- .../start-process-cloud-component.page.ts | 1 + .../pages/start-tasks-cloud-component.page.ts | 2 +- .../pages/task-header-cloud-component.page.ts | 2 +- package-lock.json | 73 +++---- scripts/check-activiti-env.js | 188 ++++++++++++++++++ scripts/test-e2e-lib.sh | 2 +- scripts/update-project.sh | 2 +- 58 files changed, 627 insertions(+), 391 deletions(-) create mode 100644 e2e/process-services-cloud/people-group-cloud-filter-component.e2e.ts rename e2e/resources/{aps2/candidateuserapp .zip => activiti7/candidateuserapp.zip} (100%) create mode 100644 e2e/resources/activiti7/simpleApp.zip create mode 100644 e2e/resources/activiti7/subProcessApp.zip delete mode 100644 e2e/resources/aps2/simple_app.zip create mode 100755 scripts/check-activiti-env.js diff --git a/.travis.yml b/.travis.yml index 453161a096..05bb0fd9bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,19 +43,20 @@ jobs: include: - stage: Warm Up Cache & Lint & Build Dist script: - if [[ $TRAVIS_PULL_REQUEST == "false" ]]; + - if [[ $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/npm-build-all.sh || exit 1); + ./scripts/lint.sh || exit 1; + ./scripts/npm-build-all.sh || exit 1; else - (./scripts/update-version.sh -gnu -alpha || exit 1); + ./scripts/update-version.sh -gnu -alpha || exit 1; npm install; - (./scripts/lint.sh || exit 1); - (rm -rf tmp && mkdir tmp); - (git merge-base origin/$TRAVIS_BRANCH HEAD > ./tmp/devhead.txt); - (./scripts/smart-build.sh -b $TRAVIS_BRANCH -gnu || exit 1); + ./scripts/lint.sh || exit 1; + rm -rf tmp && mkdir tmp; + git merge-base origin/$TRAVIS_BRANCH HEAD > ./tmp/devhead.txt; + ./scripts/smart-build.sh -b $TRAVIS_BRANCH -gnu || exit 1; fi; - (npm run build:dist || exit 1); - (./scripts/license-list-generator.sh || exit 1); + npm run build:dist || exit 1; + ./scripts/license-list-generator.sh || exit 1; - stage: Unit test name: core and extensions script: @@ -108,23 +109,31 @@ jobs: - stage: Update children projects dependency #Update generator-ng2-alfresco-app name: Update Generator if: tag =~ .*beta.* - script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n generator-ng2-alfresco-app + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/generator-ng2-alfresco-app' - stage: Update children projects dependency # Test Update alfresco-content-app name: Update ACA if: tag =~ .*beta.* - script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n alfresco-content-app + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/alfresco-content-app' - stage: Update children projects dependency # Test Update adf-app-manager-ui name: Update adf-app-manager-ui if: tag =~ .*beta.* - script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n adf-app-manager-ui + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/adf-app-manager-ui' - stage: Update children projects dependency # Test Update alfresco-ng2-components name: Update alfresco-ng2-components if: tag =~ .*beta.* - script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n alfresco-ng2-components + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/alfresco-ng2-components' - stage: Update children projects dependency # Test Update alfresco-modeler-app name: Update alfresco modeler app if: tag =~ .*beta.* - script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n alfresco-modeler-app + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/alfresco-modeler-app' + - stage: Update children projects dependency # Test Update activiti-modeling-app + name: Update alfresco modeler activiti app + if: tag =~ .*beta.* + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n Activiti/activiti-modeling-app' + - stage: Update children projects dependency # Test alfresco-admin-app + name: Update alfresco modeler activiti app + if: tag =~ .*beta.* + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/alfresco-admin-app' - stage: e2e Test # Test core name: core script: @@ -168,7 +177,8 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "process-services-cloud$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST_BPM" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder process-services-cloud --skip-lint --use-dist || exit 1;); + node ./scripts/check-activiti-env.js --host "$E2E_HOST_BPM" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" --client 'activiti' || exit 1; + ./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST_BPM" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder process-services-cloud --skip-lint --use-dist -timeout 8000 || exit 1; fi; - stage: e2e Test # Test insights name: insights diff --git a/cspell.json b/cspell.json index dcde13fef3..62f2f884db 100644 --- a/cspell.json +++ b/cspell.json @@ -125,7 +125,8 @@ "filedata", "uncheck", "subfolders", - "ECMBPM" + "ECMBPM", + "candidateuserapp" ], "dictionaries": [ "html", diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 96bfb02028..5d1cc26da5 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -8,6 +8,7 @@ "contextRootBpm": "activiti-app", "authType" : "BASIC", "locale" : "en", + "notificationDefaultDuration" : 6000, "auth": { "withCredentials": false }, diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts index 23e847942b..162ca97369 100644 --- a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts +++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.ts @@ -82,10 +82,7 @@ export class FormCloudDemoComponent implements OnInit, OnDestroy { try { this.parseForm(); } catch (error) { - this.notificationService.openSnackMessage( - 'Wrong form configuration', - 4000 - ); + this.notificationService.openSnackMessage('Wrong form configuration'); } } diff --git a/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.ts index 9fff604ef6..47def2087a 100644 --- a/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/start-process-cloud-demo.component.ts @@ -55,9 +55,6 @@ export class StartProcessCloudDemoComponent implements OnInit { } openSnackMessage(event: any) { - this.notificationService.openSnackMessage( - event.response.body.message, - 4000 - ); + this.notificationService.openSnackMessage(event.response.body.message); } } diff --git a/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.ts index 516bd9bda2..25abc786ff 100644 --- a/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/start-task-cloud-demo.component.ts @@ -19,6 +19,7 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { NotificationService } from '@alfresco/adf-core'; import { CloudLayoutService } from './services/cloud-layout.service'; + @Component({ templateUrl: './start-task-cloud-demo.component.html', styleUrls: ['./start-task-cloud-demo.component.scss'] @@ -41,19 +42,16 @@ export class StartTaskCloudDemoComponent implements OnInit { } onStartTaskSuccess() { - this.cloudLayoutService.setCurrentTaskFilterParam({key: 'my-tasks'}); + this.cloudLayoutService.setCurrentTaskFilterParam({ key: 'my-tasks' }); this.router.navigate([`/cloud/${this.appName}/tasks`]); } onCancelStartTask() { - this.cloudLayoutService.setCurrentTaskFilterParam({key: 'my-tasks'}); + this.cloudLayoutService.setCurrentTaskFilterParam({ key: 'my-tasks' }); this.router.navigate([`/cloud/${this.appName}/tasks`]); } openSnackMessage(event: any) { - this.notificationService.openSnackMessage( - event.response.body.message, - 4000 - ); + this.notificationService.openSnackMessage(event.response.body.message); } } diff --git a/demo-shell/src/app/components/config-editor/config-editor.component.ts b/demo-shell/src/app/components/config-editor/config-editor.component.ts index 0c5de2da75..e83410d3c6 100644 --- a/demo-shell/src/app/components/config-editor/config-editor.component.ts +++ b/demo-shell/src/app/components/config-editor/config-editor.component.ts @@ -16,7 +16,12 @@ */ import { Component } from '@angular/core'; -import { AppConfigService, NotificationService, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core'; +import { + AppConfigService, + NotificationService, + UserPreferencesService, + UserPreferenceValues +} from '@alfresco/adf-core'; @Component({ selector: 'app-config-editor', @@ -60,16 +65,10 @@ export class ConfigEditorComponent { } } catch (error) { this.invalidJson = true; - this.notificationService.openSnackMessage( - 'Wrong Code configuration ' + error, - 1000 - ); + this.notificationService.openSnackMessage('Wrong Code configuration ' + error); } finally { if (!this.invalidJson) { - this.notificationService.openSnackMessage( - 'Saved', - 1000 - ); + this.notificationService.openSnackMessage('Saved'); } } } @@ -89,7 +88,7 @@ export class ConfigEditorComponent { this.isUserPreference = true; this.userPreferenceProperty = 'textOrientation'; - this.userPreferencesService.select( this.userPreferenceProperty).subscribe((textOrientation: number) => { + this.userPreferencesService.select(this.userPreferenceProperty).subscribe((textOrientation: number) => { this.code = JSON.stringify(textOrientation); this.field = 'textOrientation'; this.indentCode(); @@ -147,7 +146,7 @@ export class ConfigEditorComponent { this.indentCode(); } - editTaskFilterConfClick() { + editTaskFilterConfClick() { this.isUserPreference = false; this.code = JSON.stringify(this.appConfig.config['adf-edit-task-filter']); this.field = 'adf-edit-task-filter'; diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index ca3caef9b2..ef9fcc77d4 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -349,10 +349,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { } openSnackMessage(event: any) { - this.notificationService.openSnackMessage( - event, - 4000 - ); + this.notificationService.openSnackMessage(event); } emitReadyEvent(event: NodePaging) { @@ -579,10 +576,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { }); dialogInstance.componentInstance.error.subscribe((message) => { - this.notificationService.openSnackMessage( - message, - 6000 - ); + this.notificationService.openSnackMessage(message); }); } diff --git a/demo-shell/src/app/components/form/form.component.ts b/demo-shell/src/app/components/form/form.component.ts index f56a72baec..91335db20b 100644 --- a/demo-shell/src/app/components/form/form.component.ts +++ b/demo-shell/src/app/components/form/form.component.ts @@ -26,7 +26,7 @@ import { Subscription } from 'rxjs'; templateUrl: 'form.component.html', styleUrls: ['form.component.scss'], providers: [ - {provide: FormService, useClass: InMemoryFormService} + { provide: FormService, useClass: InMemoryFormService } ], encapsulation: ViewEncapsulation.None }) @@ -87,10 +87,7 @@ export class FormComponent implements OnInit, OnDestroy { try { this.parseForm(); } catch (error) { - this.notificationService.openSnackMessage( - 'Wrong form configuration', - 4000 - ); + this.notificationService.openSnackMessage('Wrong form configuration'); } } diff --git a/demo-shell/src/app/components/permissions/demo-permissions.component.ts b/demo-shell/src/app/components/permissions/demo-permissions.component.ts index c0bf66d7e2..d40bc426e0 100644 --- a/demo-shell/src/app/components/permissions/demo-permissions.component.ts +++ b/demo-shell/src/app/components/permissions/demo-permissions.component.ts @@ -70,10 +70,7 @@ export class DemoPermissionComponent implements OnInit { showErrorMessage(error) { const message = error.message ? error.message : error; - this.notificationService.openSnackMessage( - message, - 4000 - ); + this.notificationService.openSnackMessage(message); } } diff --git a/docs/core/services/notification.service.md b/docs/core/services/notification.service.md index e72c2070e6..676af8ef51 100644 --- a/docs/core/services/notification.service.md +++ b/docs/core/services/notification.service.md @@ -93,3 +93,11 @@ export class MyComponent implements OnInit { } } ``` +The default message duration is 5000 ms that is used only if you don't pass a custom duration in the parameters of openSnackMessageAction/openSnackMessage methods. +You can also change the default 5000 ms adding the following configuration in the app.config.json: + +```json + + "notificationDefaultDuration" : "7000" + +``` diff --git a/e2e/content-services/document-list/document-list-actions.e2e.ts b/e2e/content-services/document-list/document-list-actions.e2e.ts index fe1252430a..6cf7c63857 100644 --- a/e2e/content-services/document-list/document-list-actions.e2e.ts +++ b/e2e/content-services/document-list/document-list-actions.e2e.ts @@ -91,12 +91,11 @@ describe('Document List Component - Actions', () => { loginPage.loginToContentServicesUsingUserModel(acsUser); - browser.driver.sleep(15000); + browser.driver.sleep(10000); done(); }); beforeEach(async (done) => { - navigationBarPage.clickAboutButton(); navigationBarPage.clickContentServicesButton(); done(); }); diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index 57559bdb67..62ee1d85b1 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -99,9 +99,9 @@ describe('Permissions Component', function () { folderName = `MEESEEKS_${StringUtil.generateRandomString(5)}`; - const publicSiteBody = {visibility: 'PUBLIC', title: publicSiteName}; + const publicSiteBody = { visibility: 'PUBLIC', title: publicSiteName }; - const privateSiteBody = {visibility: 'PRIVATE', title: privateSiteName}; + const privateSiteBody = { visibility: 'PRIVATE', title: privateSiteName }; publicSite = await alfrescoJsApi.core.sitesApi.createSite(publicSiteBody); privateSite = await alfrescoJsApi.core.sitesApi.createSite(privateSiteBody); @@ -136,7 +136,6 @@ describe('Permissions Component', function () { privateSiteFile = await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'privateSite' + fileModel.name, privateSite.entry.guid); await alfrescoJsApi.core.nodesApi.updateNode(privateSiteFile.entry.id, - { permissions: { locallySet: [{ @@ -148,9 +147,7 @@ describe('Permissions Component', function () { }); await uploadActions.uploadFile(alfrescoJsApi, fileModel.location, 'Site' + fileModel.name, siteFolder.entry.id); - done(); - }); afterAll(async (done) => { @@ -182,6 +179,9 @@ describe('Permissions Component', function () { permissionsPage.clickAddPermissionButton(); permissionsPage.checkAddPermissionDialogIsDisplayed(); permissionsPage.checkSearchUserInputIsDisplayed(); + + browser.sleep(7000); + permissionsPage.searchUserOrGroup(consumerUser.getId()); permissionsPage.clickUserOrGroup(consumerUser.getFirstName()); permissionsPage.checkUserOrGroupIsAdded(consumerUser.getId()); diff --git a/e2e/pages/adf/content-services/search/components/search-checkList.ts b/e2e/pages/adf/content-services/search/components/search-checkList.ts index 57c51e5660..635ec46dae 100644 --- a/e2e/pages/adf/content-services/search/components/search-checkList.ts +++ b/e2e/pages/adf/content-services/search/components/search-checkList.ts @@ -32,7 +32,7 @@ export class SearchCheckListPage { clickCheckListOption(option) { BrowserVisibility.waitUntilElementIsVisible(this.filter); - const result = this.filter.all(by.css(`mat-checkbox[data-automation-id*='-${option}'] .mat-checkbox-inner-container`)).first(); + const result = this.filter.all(by.css(`mat-checkbox[data-automation-id*='${option}'] .mat-checkbox-inner-container`)).first(); BrowserVisibility.waitUntilElementIsVisible(result); BrowserVisibility.waitUntilElementIsClickable(result); result.click(); diff --git a/e2e/pages/adf/notificationPage.ts b/e2e/pages/adf/notificationPage.ts index c52902a363..6a1dd33d29 100644 --- a/e2e/pages/adf/notificationPage.ts +++ b/e2e/pages/adf/notificationPage.ts @@ -28,7 +28,6 @@ export class NotificationPage { actionToggle = element(by.css('mat-slide-toggle[data-automation-id="notification-action-toggle"]')); notificationSnackBar = element.all(by.css('simple-snack-bar')).first(); actionOutput = element(by.css('div[data-automation-id="notification-action-output"]')); - customNotificationButton = element(by.css('button[data-automation-id="notification-custom-config-button"]')); selectionDropDown = element.all(by.css('.mat-select-panel')).first(); notificationsPage = element(by.css('a[data-automation-id="Notifications"]')); notificationConfig = element(by.css('p[data-automation-id="notification-custom-object"]')); @@ -98,8 +97,6 @@ export class NotificationPage { } clickNotificationButton() { - // BrowserVisibility.waitUntilElementIsVisible(this.customNotificationButton); - // this.customNotificationButton.click(); const button = browser.wait(until.elementLocated(by.css('button[data-automation-id="notification-custom-config-button"]'))); button.click(); } diff --git a/e2e/pages/adf/viewerPage.ts b/e2e/pages/adf/viewerPage.ts index 38b37971fc..74c511a6c5 100644 --- a/e2e/pages/adf/viewerPage.ts +++ b/e2e/pages/adf/viewerPage.ts @@ -132,7 +132,7 @@ export class ViewerPage { } checkFileIsLoaded() { - BrowserVisibility.waitUntilElementIsOnPage(this.pdfPageLoaded, 15000); + BrowserVisibility.waitUntilElementIsOnPage(this.pdfPageLoaded, 10000); } checkImgViewerIsDisplayed() { diff --git a/e2e/process-services-cloud/apps-section-cloud.e2e.ts b/e2e/process-services-cloud/apps-section-cloud.e2e.ts index 6d0db57d14..cac06b0c86 100644 --- a/e2e/process-services-cloud/apps-section-cloud.e2e.ts +++ b/e2e/process-services-cloud/apps-section-cloud.e2e.ts @@ -19,7 +19,6 @@ import { LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Applications list', () => { @@ -28,11 +27,10 @@ describe('Applications list', () => { const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); const appListCloudPage = new AppListCloudPage(); - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; it('[C289910] Should the app be displayed on dashboard when is deployed on APS', () => { settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudPage.checkApsContainer(); diff --git a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts index 97cf7bd761..faa07087ec 100644 --- a/e2e/process-services-cloud/edit-process-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-process-filters-component.e2e.ts @@ -22,7 +22,6 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Edit process filters cloud', () => { @@ -35,15 +34,13 @@ describe('Edit process filters cloud', () => { const tasksCloudDemoPage = new TasksCloudDemoPage(); const processCloudDemoPage = new ProcessCloudDemoPage(); - let silentLogin; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; - beforeAll(async () => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + done(); }); beforeEach((done) => { diff --git a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts index 60ec7ceb9e..e0d1194971 100644 --- a/e2e/process-services-cloud/edit-task-filters-component.e2e.ts +++ b/e2e/process-services-cloud/edit-task-filters-component.e2e.ts @@ -21,7 +21,6 @@ import { AppListCloudPage, StringUtil, ApiService, LoginSSOPage, TasksService, S import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Edit task filters cloud', () => { @@ -34,16 +33,13 @@ describe('Edit task filters cloud', () => { const tasksCloudDemoPage = new TasksCloudDemoPage(); let tasksService: TasksService; - let silentLogin; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; const completedTaskName = StringUtil.generateRandomString(), assignedTaskName = StringUtil.generateRandomString(); let assignedTask; - beforeAll(async () => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); @@ -53,6 +49,7 @@ describe('Edit task filters cloud', () => { assignedTask = await tasksService.createStandaloneTask(assignedTaskName, simpleApp); await tasksService.claimTask(assignedTask.entry.id, simpleApp); await tasksService.createAndCompleteTask(completedTaskName, simpleApp); + done(); }); beforeEach((done) => { diff --git a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts index ab2a36a925..6c523cded3 100644 --- a/e2e/process-services-cloud/people-group-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/people-group-cloud-component.e2e.ts @@ -39,7 +39,6 @@ describe('People Groups Cloud Component', () => { let groupIdentityService: GroupIdentityService; let rolesService: RolesService; - let silentLogin; let apsUser; let activitiUser; let noRoleUser; @@ -55,14 +54,14 @@ describe('People Groups Cloud Component', () => { let groups = []; let clientId; - beforeAll(async () => { + beforeAll(async (done) => { const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); identityService = new IdentityService(apiService); rolesService = new RolesService(apiService); groupIdentityService = new GroupIdentityService(apiService); - clientId = await groupIdentityService.getClientIdByApplicationName(resources.ACTIVITI7_APPS.SIMPLE_APP); + clientId = await groupIdentityService.getClientIdByApplicationName(resources.ACTIVITI7_APPS.SIMPLE_APP.name); groupActiviti = await groupIdentityService.createIdentityGroup(); clientActivitiAdminRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_ADMIN); clientActivitiUserRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_USER); @@ -88,12 +87,11 @@ describe('People Groups Cloud Component', () => { await groupIdentityService.addClientRole(groupActiviti.id, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN ); users = [`${apsUser.idIdentityService}`, `${activitiUser.idIdentityService}`, `${noRoleUser.idIdentityService}`]; groups = [`${groupAps.id}`, `${groupActiviti.id}`, `${groupNoRole.id}`]; - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); navigationBarPage.navigateToPeopleGroupCloudPage(); + done(); }); afterAll(async () => { @@ -106,11 +104,14 @@ describe('People Groups Cloud Component', () => { }); beforeEach(() => { - browser.refresh(); peopleGroupCloudComponentPage.checkGroupsCloudComponentTitleIsDisplayed(); peopleGroupCloudComponentPage.checkPeopleCloudComponentTitleIsDisplayed(); }); + afterEach(() => { + browser.refresh(); + }); + it('[C297674] Add role filtering to PeopleCloudComponent', () => { peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); peopleGroupCloudComponentPage.clickPeopleCloudFilterRole(); @@ -188,7 +189,6 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPreselectValidation(); expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"id":"${noRoleUser.idIdentityService}"}]`); - browser.sleep(100); expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); peopleGroupCloudComponentPage.clickPreselectValidation(); @@ -196,7 +196,6 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPreselectValidation(); expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"email":"${apsUser.email}"}]`); - browser.sleep(100); expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); peopleGroupCloudComponentPage.clickPreselectValidation(); @@ -204,7 +203,6 @@ describe('People Groups Cloud Component', () => { peopleGroupCloudComponentPage.clickPreselectValidation(); expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"username":"${activitiUser.username}"}]`); - browser.sleep(100); expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); peopleGroupCloudComponentPage.enterPeoplePreselect('[{"id":"12345","username":"someUsername","email":"someEmail"}]'); @@ -212,7 +210,6 @@ describe('People Groups Cloud Component', () => { expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('false'); peopleGroupCloudComponentPage.clickPreselectValidation(); expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); - browser.sleep(100); expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(''); }); @@ -262,68 +259,11 @@ describe('People Groups Cloud Component', () => { expect(peopleGroupCloudComponentPage.getPreselectValidationStatus()).toBe('true'); peopleGroupCloudComponentPage.enterPeoplePreselect(`[{"firstName":"${apsUser.firstName}","lastName":"${apsUser.lastName},"` + `{"firstName":"${activitiUser.firstName}","lastName":"${activitiUser.lastName}",{"firstName":"${noRoleUser.firstName}","lastName":"${noRoleUser.lastName}"]`); - browser.sleep(100); + browser.sleep(200); expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(''); }); - it('[C305041] Should filter the People Single Selection with the Application name filter', () => { - peopleGroupCloudComponentPage.checkPeopleCloudSingleSelectionIsSelected(); - peopleGroupCloudComponentPage.clickPeopleFilerByApp(); - peopleGroupCloudComponentPage.enterPeopleAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); - peopleCloudComponent.searchAssignee(`${activitiUser.firstName}`); - peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - browser.sleep(100); - expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - }); - - it('[C305041] Should filter the People Multiple Selection with the Application name filter', () => { - peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); - peopleGroupCloudComponentPage.clickPeopleFilerByApp(); - peopleGroupCloudComponentPage.enterPeopleAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); - peopleCloudComponent.searchAssignee(`${apsUser.firstName}`); - peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); - - peopleCloudComponent.searchAssigneeToExisting(`${activitiUser.firstName}`); - peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - peopleCloudComponent.checkSelectedPeople(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); - - peopleCloudComponent.searchAssigneeToExisting(`${noRoleUser.firstName}`); - peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); - }); - - it('[C305041] Should filter the Groups Single Selection with the Application name filter', () => { - peopleGroupCloudComponentPage.clickGroupCloudSingleSelection(); - peopleGroupCloudComponentPage.clickGroupFilerByApp(); - peopleGroupCloudComponentPage.enterGroupAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); - groupCloudComponentPage.searchGroups(`${groupActiviti.name}`); - groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); - groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); - expect(groupCloudComponentPage.getGroupsFieldContent()).toBe(`${groupActiviti.name}`); - }); - - it('[C305041] Should filter the Groups Multiple Selection with the Application name filter', () => { - peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); - peopleGroupCloudComponentPage.clickGroupFilerByApp(); - peopleGroupCloudComponentPage.enterGroupAppName(resources.ACTIVITI7_APPS.SIMPLE_APP); - groupCloudComponentPage.searchGroups(`${groupAps.name}`); - groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); - groupCloudComponentPage.selectGroupFromList(`${groupAps.name}`); - groupCloudComponentPage.checkSelectedGroup(`${groupAps.name}`); - - groupCloudComponentPage.searchGroupsToExisting(`${groupActiviti.name}`); - groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); - groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); - groupCloudComponentPage.checkSelectedGroup(`${groupActiviti.name}`); - - groupCloudComponentPage.searchGroupsToExisting(`${groupNoRole.name}`); - groupCloudComponentPage.checkGroupIsNotDisplayed(`${groupNoRole.name}`); - }); - }); }); diff --git a/e2e/process-services-cloud/people-group-cloud-filter-component.e2e.ts b/e2e/process-services-cloud/people-group-cloud-filter-component.e2e.ts new file mode 100644 index 0000000000..58f2b5a6a0 --- /dev/null +++ b/e2e/process-services-cloud/people-group-cloud-filter-component.e2e.ts @@ -0,0 +1,174 @@ +/*! + * @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 TestConfig = require('../test.config'); + +import { SettingsPage } from '@alfresco/adf-testing'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; +import { PeopleGroupCloudComponentPage } from '../pages/adf/demo-shell/process-services/peopleGroupCloudComponentPage'; +import { GroupCloudComponentPage, PeopleCloudComponentPage } from '@alfresco/adf-testing'; +import { browser } from 'protractor'; +import { LoginSSOPage, IdentityService, GroupIdentityService, RolesService, ApiService } from '@alfresco/adf-testing'; +import CONSTANTS = require('../util/constants'); +import resources = require('../util/resources'); + +describe('People Groups Cloud Component', () => { + + describe('People Groups Cloud Component', () => { + const settingsPage = new SettingsPage(); + const loginSSOPage = new LoginSSOPage(); + const navigationBarPage = new NavigationBarPage(); + const peopleGroupCloudComponentPage = new PeopleGroupCloudComponentPage(); + const peopleCloudComponent = new PeopleCloudComponentPage(); + const groupCloudComponentPage = new GroupCloudComponentPage(); + let identityService: IdentityService; + let groupIdentityService: GroupIdentityService; + let rolesService: RolesService; + + let apsUser; + let activitiUser; + let noRoleUser; + let groupAps; + let groupActiviti; + let groupNoRole; + let apsUserRoleId; + let activitiUserRoleId; + let apsAdminRoleId; + let activitiAdminRoleId; + let clientActivitiAdminRoleId, clientActivitiUserRoleId; + let users = []; + let groups = []; + let clientId; + + beforeAll(async (done) => { + + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + identityService = new IdentityService(apiService); + rolesService = new RolesService(apiService); + groupIdentityService = new GroupIdentityService(apiService); + clientId = await groupIdentityService.getClientIdByApplicationName(resources.ACTIVITI7_APPS.SIMPLE_APP.name); + groupActiviti = await groupIdentityService.createIdentityGroup(); + clientActivitiAdminRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_ADMIN); + clientActivitiUserRoleId = await rolesService.getClientRoleIdByRoleName(groupActiviti.id, clientId, CONSTANTS.ROLES.ACTIVITI_USER); + + apsUser = await identityService.createIdentityUser(); + apsUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_USER); + await identityService.assignRole(apsUser.idIdentityService, apsUserRoleId, CONSTANTS.ROLES.APS_USER); + activitiUser = await identityService.createIdentityUser(); + activitiUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_USER); + await identityService.assignRole(activitiUser.idIdentityService, activitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); + noRoleUser = await identityService.createIdentityUser(); + await identityService.deleteClientRole(noRoleUser.idIdentityService, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN); + await identityService.deleteClientRole(noRoleUser.idIdentityService, clientId, clientActivitiUserRoleId, CONSTANTS.ROLES.ACTIVITI_USER); + + groupAps = await groupIdentityService.createIdentityGroup(); + apsAdminRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_ADMIN); + await groupIdentityService.assignRole(groupAps.id, apsAdminRoleId, CONSTANTS.ROLES.APS_ADMIN); + activitiAdminRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.ACTIVITI_ADMIN); + await groupIdentityService.assignRole(groupActiviti.id, activitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN); + groupNoRole = await groupIdentityService.createIdentityGroup(); + + await groupIdentityService.addClientRole(groupAps.id, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN ); + await groupIdentityService.addClientRole(groupActiviti.id, clientId, clientActivitiAdminRoleId, CONSTANTS.ROLES.ACTIVITI_ADMIN ); + users = [`${apsUser.idIdentityService}`, `${activitiUser.idIdentityService}`, `${noRoleUser.idIdentityService}`]; + groups = [`${groupAps.id}`, `${groupActiviti.id}`, `${groupNoRole.id}`]; + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); + loginSSOPage.clickOnSSOButton(); + loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + navigationBarPage.navigateToPeopleGroupCloudPage(); + done(); + }); + + afterAll(async () => { + for (let i = 0; i < users.length; i++) { + await identityService.deleteIdentityUser(users[i]); + } + for (let i = 0; i < groups.length; i++) { + await groupIdentityService.deleteIdentityGroup(groups[i]); + } + }); + + beforeEach(() => { + peopleGroupCloudComponentPage.checkGroupsCloudComponentTitleIsDisplayed(); + peopleGroupCloudComponentPage.checkPeopleCloudComponentTitleIsDisplayed(); + }); + + afterEach(() => { + browser.refresh(); + }); + + it('[C305041] Should filter the People Single Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.checkPeopleCloudSingleSelectionIsSelected(); + peopleGroupCloudComponentPage.clickPeopleFilerByApp(); + peopleGroupCloudComponentPage.enterPeopleAppName(resources.ACTIVITI7_APPS.SIMPLE_APP.name); + peopleCloudComponent.searchAssignee(`${activitiUser.firstName}`); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + browser.sleep(100); + expect(peopleCloudComponent.getAssigneeFieldContent()).toBe(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + }); + + it('[C305041] Should filter the People Multiple Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.clickPeopleCloudMultipleSelection(); + peopleGroupCloudComponentPage.clickPeopleFilerByApp(); + peopleGroupCloudComponentPage.enterPeopleAppName(resources.ACTIVITI7_APPS.SIMPLE_APP.name); + peopleCloudComponent.searchAssignee(`${apsUser.firstName}`); + peopleCloudComponent.checkUserIsDisplayed(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${apsUser.firstName}` + ' ' + `${apsUser.lastName}`); + + peopleCloudComponent.searchAssigneeToExisting(`${activitiUser.firstName}`); + peopleCloudComponent.checkUserIsDisplayed(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.selectAssigneeFromList(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + peopleCloudComponent.checkSelectedPeople(`${activitiUser.firstName}` + ' ' + `${activitiUser.lastName}`); + + peopleCloudComponent.searchAssigneeToExisting(`${noRoleUser.firstName}`); + peopleCloudComponent.checkUserIsNotDisplayed(`${noRoleUser.firstName}` + ' ' + `${noRoleUser.lastName}`); + }); + + it('[C305041] Should filter the Groups Single Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.clickGroupCloudSingleSelection(); + peopleGroupCloudComponentPage.clickGroupFilerByApp(); + peopleGroupCloudComponentPage.enterGroupAppName(resources.ACTIVITI7_APPS.SIMPLE_APP.name); + groupCloudComponentPage.searchGroups(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); + expect(groupCloudComponentPage.getGroupsFieldContent()).toBe(`${groupActiviti.name}`); + }); + + it('[C305041] Should filter the Groups Multiple Selection with the Application name filter', () => { + peopleGroupCloudComponentPage.clickGroupCloudMultipleSelection(); + peopleGroupCloudComponentPage.clickGroupFilerByApp(); + peopleGroupCloudComponentPage.enterGroupAppName(resources.ACTIVITI7_APPS.SIMPLE_APP.name); + groupCloudComponentPage.searchGroups(`${groupAps.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupAps.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupAps.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupAps.name}`); + + groupCloudComponentPage.searchGroupsToExisting(`${groupActiviti.name}`); + groupCloudComponentPage.checkGroupIsDisplayed(`${groupActiviti.name}`); + groupCloudComponentPage.selectGroupFromList(`${groupActiviti.name}`); + groupCloudComponentPage.checkSelectedGroup(`${groupActiviti.name}`); + + groupCloudComponentPage.searchGroupsToExisting(`${groupNoRole.name}`); + groupCloudComponentPage.checkGroupIsNotDisplayed(`${groupNoRole.name}`); + }); + + }); + +}); diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index 59e81da33e..f8f47655e8 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -44,15 +44,12 @@ describe('Process list cloud', () => { let processInstancesService: ProcessInstancesService; let queryService: QueryService; - let silentLogin; let completedProcess, runningProcessInstance, switchProcessInstance, noOfApps; - const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; + const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; - beforeAll(async () => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); navigationBarPage.clickConfigEditorButton(); @@ -87,8 +84,10 @@ describe('Process list cloud', () => { processDefinitionService = new ProcessDefinitionsService(apiService); const processDefinition = await processDefinitionService.getProcessDefinitions(candidateuserapp); + processInstancesService = new ProcessInstancesService(apiService); await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); + runningProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); switchProcessInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); @@ -99,9 +98,10 @@ describe('Process list cloud', () => { tasksService = new TasksService(apiService); const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, candidateuserapp); await tasksService.completeTask(claimedTask.entry.id, candidateuserapp); + done(); }); - beforeEach((done) => { + beforeEach(async(done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); appListCloudComponent.goToApp(candidateuserapp); @@ -128,7 +128,7 @@ describe('Process list cloud', () => { }); }); - it('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async () => { + xit('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('RUNNING') .setSortFilterDropDown('Id').setOrderFilterDropDown('ASC'); processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); diff --git a/e2e/process-services-cloud/process-filters-cloud.e2e.ts b/e2e/process-services-cloud/process-filters-cloud.e2e.ts index d345e942d7..c6625021c7 100644 --- a/e2e/process-services-cloud/process-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-filters-cloud.e2e.ts @@ -23,7 +23,6 @@ import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/p import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Process filters cloud', () => { @@ -41,16 +40,13 @@ describe('Process filters cloud', () => { let processInstancesService: ProcessInstancesService; let queryService: QueryService; - let silentLogin; let runningProcess, completedProcess; - const simpleApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; + const simpleApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - beforeAll(async () => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); @@ -67,6 +63,7 @@ describe('Process filters cloud', () => { tasksService = new TasksService(apiService); const claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, simpleApp); await tasksService.completeTask(claimedTask.entry.id, simpleApp); + done(); }); beforeEach((done) => { diff --git a/e2e/process-services-cloud/process-header-cloud.e2e.ts b/e2e/process-services-cloud/process-header-cloud.e2e.ts index ba178a3b51..a28a9c25e7 100644 --- a/e2e/process-services-cloud/process-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-header-cloud.e2e.ts @@ -26,15 +26,14 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { ProcessHeaderCloudPage } from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Process Header cloud component', () => { describe('Process Header cloud component', () => { - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; - const subProcessApp = resources.ACTIVITI7_APPS.SUB_PROCESS_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; + const subProcessApp = resources.ACTIVITI7_APPS.SUB_PROCESS_APP.name; const formatDate = 'DD-MM-YYYY'; const processHeaderCloudPage = new ProcessHeaderCloudPage(); @@ -50,14 +49,11 @@ describe('Process Header cloud component', () => { let processInstancesService: ProcessInstancesService; let queryService: QueryService; - let silentLogin; let runningProcess, runningCreatedDate, parentCompleteProcess, childCompleteProcess, completedCreatedDate; beforeAll(async (done) => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index 635d306e09..79521a5c27 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -16,7 +16,13 @@ */ import TestConfig = require('../test.config'); -import { ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService, SettingsPage } from '@alfresco/adf-testing'; +import { + ProcessDefinitionsService, + ProcessInstancesService, + LoginSSOPage, + ApiService, + SettingsPage +} from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; @@ -24,7 +30,6 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { ProcessListCloudConfiguration } from './processListCloud.config'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Process list cloud', () => { @@ -40,16 +45,13 @@ describe('Process list cloud', () => { let processDefinitionService: ProcessDefinitionsService; let processInstancesService: ProcessInstancesService; - let silentLogin; - const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; + const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; let jsonFile; let runningProcess; - beforeAll(async () => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); @@ -59,7 +61,7 @@ describe('Process list cloud', () => { const processDefinition = await processDefinitionService.getProcessDefinitions(candidateuserapp); processInstancesService = new ProcessInstancesService(apiService); runningProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); - + done(); }); beforeEach(async (done) => { diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index e64d1d5476..b85c4ead48 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -21,7 +21,6 @@ import TestConfig = require('../test.config'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { StringUtil } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Start Process', () => { @@ -37,16 +36,13 @@ describe('Start Process', () => { const processNameBiggerThen255Characters = StringUtil.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; const requiredError = 'Process Name is required', requiredProcessError = 'Process Definition is required'; - const processDefinition = 'processwithvariables'; + const processWithVariables = resources.ACTIVITI7_APPS.SIMPLE_APP.processes.processwithvariables; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; - let silentLogin; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; beforeAll((done) => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); @@ -70,6 +66,7 @@ describe('Start Process', () => { }); it('[C291842] Should be displayed an error message if process name exceed 255 characters', () => { + appListCloudComponent.checkAppIsDisplayed(simpleApp); appListCloudComponent.goToApp(simpleApp); processCloudDemoPage.openNewProcessForm(); startProcessPage.enterProcessName(processName255Characters); @@ -110,7 +107,7 @@ describe('Start Process', () => { startProcessPage.blur(startProcessPage.processDefinition); startProcessPage.checkValidationErrorIsDisplayed(requiredProcessError); - startProcessPage.selectFromProcessDropdown(processDefinition); + startProcessPage.selectFromProcessDropdown(processWithVariables); startProcessPage.checkStartProcessButtonIsEnabled(); startProcessPage.clickStartProcessButton(); processCloudDemoPage.clickOnProcessFilters(); diff --git a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts index 8f90db8838..d83a059f21 100644 --- a/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-task-custom-app-cloud.e2e.ts @@ -22,7 +22,6 @@ import { LoginSSOPage, SettingsPage, AppListCloudPage, StringUtil, TaskHeaderCloudPage, StartTasksCloudPage, PeopleCloudComponentPage, TasksService, ApiService, IdentityService } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; import resources = require('../util/resources'); @@ -46,9 +45,9 @@ describe('Start Task', () => { const requiredError = 'Field required'; const dateValidationError = 'Date format DD/MM/YYYY'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; - let silentLogin, activitiUser; + let activitiUser; let tasksService: TasksService; let identityService: IdentityService; @@ -59,10 +58,8 @@ describe('Start Task', () => { tasksService = new TasksService(apiService); activitiUser = await identityService.createIdentityUser(); - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); done(); }); diff --git a/e2e/process-services-cloud/task-filters-cloud.e2e.ts b/e2e/process-services-cloud/task-filters-cloud.e2e.ts index 2faf69a557..7265805446 100644 --- a/e2e/process-services-cloud/task-filters-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-filters-cloud.e2e.ts @@ -20,7 +20,6 @@ import TestConfig = require('../test.config'); import { LoginSSOPage, TasksService, ApiService, SettingsPage, AppListCloudPage, StringUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Task filters cloud', () => { @@ -34,15 +33,12 @@ describe('Task filters cloud', () => { let tasksService: TasksService; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - let silentLogin; const newTask = StringUtil.generateRandomString(5), completedTask = StringUtil.generateRandomString(5); - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; beforeAll(() => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); }); diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index 793931c7f1..3f80507399 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -23,7 +23,6 @@ import moment = require('moment'); import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { LoginSSOPage, SettingsPage, AppListCloudPage, TaskHeaderCloudPage, TasksService } from '@alfresco/adf-testing'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { browser } from 'protractor'; import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; import resources = require('../util/resources'); @@ -32,7 +31,7 @@ describe('Task Header cloud component', () => { const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const basicCreatedTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(); let basicCreatedTask, basicCreatedDate, completedTask, completedCreatedDate, subTask, subTaskCreatedDate; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; const priority = 30, description = 'descriptionTask', formatDate = 'DD-MM-YYYY'; const taskHeaderCloudPage = new TaskHeaderCloudPage(); @@ -45,13 +44,9 @@ describe('Task Header cloud component', () => { const taskDetailsCloudDemoPage = new TaskDetailsCloudDemoPage(); let tasksService: TasksService; - let silentLogin; - beforeAll(async (done) => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index 0643f96da9..cb2b86ff25 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -30,7 +30,6 @@ import moment = require('moment'); import { DateUtil } from '../util/dateUtil'; import { NotificationPage } from '../pages/adf/notificationPage'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Edit task filters and task list properties', () => { @@ -49,9 +48,8 @@ describe('Edit task filters and task list properties', () => { let processInstancesService: ProcessInstancesService; const notificationPage = new NotificationPage(); - let silentLogin; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; - const candidateUserApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; + const candidateUserApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; const noTasksFoundMessage = 'No Tasks Found'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; @@ -63,11 +61,9 @@ describe('Edit task filters and task list properties', () => { const afterDate = moment().add(1, 'days').format('DD/MM/YYYY'); beforeAll(async (done) => { - silentLogin = false; const jsonFile = new TaskListCloudConfiguration().getConfiguration(); - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); navigationBarPage.clickConfigEditorButton(); @@ -80,7 +76,7 @@ describe('Edit task filters and task list properties', () => { configEditorPage.clickEditTaskConfiguration(); configEditorPage.clickClearButton(); - browser.driver.sleep(5000); + configEditorPage.enterBigConfigurationText(`{ "filterProperties": [ "appName", @@ -305,7 +301,7 @@ describe('Edit task filters and task list properties', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(createdTask.entry.name); }); - it('[C297691] Task is not displayed when typing into lastModifiedFrom field a date before the task due date ' + + xit('[C297691] Task is not displayed when typing into lastModifiedFrom field a date before the task due date ' + 'and into lastModifiedTo a date before task due date', function () { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); @@ -316,7 +312,7 @@ describe('Edit task filters and task list properties', () => { expect(tasksCloudDemoPage.taskListCloudComponent().getNoTasksFoundMessage()).toEqual(noTasksFoundMessage); }); - it('[C297692] Task is displayed when typing into lastModifiedFrom field a date before the tasks due date ' + + xit('[C297692] Task is displayed when typing into lastModifiedFrom field a date before the tasks due date ' + 'and into lastModifiedTo a date after', function () { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index 0d5ab39efa..f928f85367 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -36,18 +36,15 @@ describe('Task list cloud - selection', () => { let tasksService: TasksService; - let silentLogin; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const noOfTasks = 3; let response; const tasks = []; beforeAll(async (done) => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index 34d90047e5..e0b999725b 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -22,7 +22,6 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Task filters cloud', () => { @@ -38,21 +37,18 @@ describe('Task filters cloud', () => { let processInstancesService: ProcessInstancesService; let queryService: QueryService; - let silentLogin; const createdTaskName = StringUtil.generateRandomString(), completedTaskName = StringUtil.generateRandomString(), assignedTaskName = StringUtil.generateRandomString(), deletedTaskName = StringUtil.generateRandomString(); - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; let assignedTask, deletedTask, suspendedTasks; const orderByNameAndPriority = ['cCreatedTask', 'dCreatedTask', 'eCreatedTask']; let priority = 30; const nrOfTasks = 3; - beforeAll(async () => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(user, password); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); @@ -83,6 +79,7 @@ describe('Task filters cloud', () => { await processInstancesService.suspendProcessInstance(processInstance.entry.id, simpleApp); await processInstancesService.deleteProcessInstance(secondProcessInstance.entry.id, simpleApp); await queryService.getProcessInstanceTasks(processInstance.entry.id, simpleApp); + done(); }); beforeEach(async (done) => { diff --git a/e2e/resources/aps2/candidateuserapp .zip b/e2e/resources/activiti7/candidateuserapp.zip similarity index 100% rename from e2e/resources/aps2/candidateuserapp .zip rename to e2e/resources/activiti7/candidateuserapp.zip diff --git a/e2e/resources/activiti7/simpleApp.zip b/e2e/resources/activiti7/simpleApp.zip new file mode 100644 index 0000000000000000000000000000000000000000..d27baa2f4e0f583e4e9bd11c23774656b304d3c3 GIT binary patch literal 3184 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 TGYegfh4z%uN|sDh1b}}5vU>uL literal 0 HcmV?d00001 diff --git a/e2e/resources/activiti7/subProcessApp.zip b/e2e/resources/activiti7/subProcessApp.zip new file mode 100644 index 0000000000000000000000000000000000000000..6bf3c95510f26e636584d1fab5e2af858dae28e9 GIT binary patch literal 2815 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 literal 0 HcmV?d00001 diff --git a/e2e/resources/aps2/simple_app.zip b/e2e/resources/aps2/simple_app.zip deleted file mode 100644 index 5648e87c209652341e97afbdd200d45f3f7c7d0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3019 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 diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index ed7e381289..993ea719e0 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -18,8 +18,6 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; -import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; @@ -32,13 +30,12 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { browser } from 'protractor'; import { StringUtil } from '@alfresco/adf-testing'; +import { setConfigField } from '../../proxy'; describe('Search Checklist Component', () => { const loginPage = new LoginPage(); const searchFiltersPage = new SearchFiltersPage(); - const configEditorPage = new ConfigEditorPage(); - const navigationBarPage = new NavigationBarPage(); const searchDialog = new SearchDialog(); const searchResults = new SearchResultsPage(); @@ -139,18 +136,13 @@ describe('Search Checklist Component', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C277143] Should be able to click show more/less button with pageSize set as default', () => { - navigationBarPage.clickConfigEditorButton(); - + fit('[C277143] Should be able to click show more/less button with pageSize set as default', async() => { for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', 'value': "TYPE:'cm:folder'" }); } - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); - + await setConfigField('search', JSON.stringify(jsonFile)); +browser.sleep(2000); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -176,19 +168,14 @@ describe('Search Checklist Component', () => { browser.refresh(); }); - it('[C277144] Should be able to click show more/less button with pageSize set with a custom value', () => { - navigationBarPage.clickConfigEditorButton(); - + it('[C277144] Should be able to click show more/less button with pageSize set with a custom value', async() => { jsonFile.categories[1].component.settings.pageSize = 10; for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', 'value': "TYPE:'cm:folder'" }); } - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -197,16 +184,9 @@ describe('Search Checklist Component', () => { searchFiltersPage.checkListFiltersPage().checkShowMoreButtonIsNotDisplayed(); - browser.refresh(); - - navigationBarPage.clickConfigEditorButton(); - jsonFile.categories[1].component.settings.pageSize = 11; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -217,14 +197,9 @@ describe('Search Checklist Component', () => { browser.refresh(); - navigationBarPage.clickConfigEditorButton(); - jsonFile.categories[1].component.settings.pageSize = 9; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -236,19 +211,14 @@ describe('Search Checklist Component', () => { browser.refresh(); }); - it('[C277145] Should be able to click show more/less button with pageSize set to zero', () => { - navigationBarPage.clickConfigEditorButton(); - + it('[C277145] Should be able to click show more/less button with pageSize set to zero', async() => { jsonFile.categories[1].component.settings.pageSize = 0; for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', 'value': "TYPE:'cm:folder'" }); } - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -267,14 +237,9 @@ describe('Search Checklist Component', () => { browser.refresh(); - navigationBarPage.clickConfigEditorButton(); - delete jsonFile.categories[1].component.settings.pageSize; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -309,15 +274,10 @@ describe('Search Checklist Component', () => { done(); }); - it('[C277018] Should be able to change the operator', () => { - navigationBarPage.clickConfigEditorButton(); - + it('[C277018] Should be able to change the operator', async() => { jsonFile.categories[1].component.settings.operator = 'AND'; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -336,15 +296,10 @@ describe('Search Checklist Component', () => { browser.refresh(); }); - it('[C277019] Should be able to add new properties with different types', () => { - navigationBarPage.clickConfigEditorButton(); - + it('[C277019] Should be able to add new properties with different types', async() => { jsonFile.categories[1].component.settings.options.push({ 'name': filterType.custom, 'value': "TYPE:'cm:auditable'" }); - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); diff --git a/e2e/search/components/search-text.e2e.ts b/e2e/search/components/search-text.e2e.ts index 062e366c50..4be3776a00 100644 --- a/e2e/search/components/search-text.e2e.ts +++ b/e2e/search/components/search-text.e2e.ts @@ -68,7 +68,7 @@ describe('Search component - Text widget', () => { } }, {}, {}); - await browser.driver.sleep(10000); + await browser.driver.sleep(15000); loginPage.loginToContentServicesUsingUserModel(acsUser); diff --git a/e2e/search/search-page-component.e2e.ts b/e2e/search/search-page-component.e2e.ts index a684c9bc45..7b5114ab45 100644 --- a/e2e/search/search-page-component.e2e.ts +++ b/e2e/search/search-page-component.e2e.ts @@ -98,7 +98,7 @@ describe('Search component - Search Page', () => { await uploadActions.createEmptyFiles(this.alfrescoJsApi, adminFileNames, newFolderModelUploaded.entry.id); - browser.driver.sleep(15000); + browser.driver.sleep(10000); loginPage.loginToContentServicesUsingUserModel(acsUser); diff --git a/e2e/util/resources.js b/e2e/util/resources.js index 6f33c63c1f..de5bb79f6f 100644 --- a/e2e/util/resources.js +++ b/e2e/util/resources.js @@ -36,8 +36,8 @@ exports.Files = { } }, - APP_WITH_PROCESSES:{ - file_location:"/resources/apps/App_with_processes.zip", + APP_WITH_PROCESSES: { + file_location: "/resources/apps/App_with_processes.zip", title: "App_with_processes", description: "Description for app", process_se_name: "process_with_se", @@ -45,15 +45,15 @@ exports.Files = { task_name: "Task Test 2" }, - APP_DYNAMIC_TABLE_DROPDOWN:{ - file_location:"/resources/apps/AppDynamicTableDropdown.zip", + APP_DYNAMIC_TABLE_DROPDOWN: { + file_location: "/resources/apps/AppDynamicTableDropdown.zip", title: "App3576", description: "Description for app", processName: "Process3576" }, - APP_WITH_USER_WIDGET:{ - file_location:"/resources/apps/appWithUser.zip", + APP_WITH_USER_WIDGET: { + file_location: "/resources/apps/appWithUser.zip", title: "appWithUser", description: "Description for app", processName: "ProcessWithUser", @@ -361,7 +361,7 @@ exports.Files = { last_page_number: "8", password: "1q2w3e4r" }, - LARGE_FILE:{ + LARGE_FILE: { file_location: "/resources/adf/BigFile.zip", file_name: "BigFile.zip" }, @@ -454,15 +454,15 @@ exports.Files = { file_location: "/resources/adf/allFileTypes/a_zip_file.mp4.zip", file_name: "a_zip_file.mp4.zip" }, - PAGES:{ + PAGES: { file_location: "/resources/adf/allFileTypes/file_unsupported.pages", file_name: "file_unsupported.pages" }, - UNSUPPORTED:{ + UNSUPPORTED: { file_location: "/resources/adf/allFileTypes/file_unsupported.3DS", file_name: "file_unsupported.3DS" }, - INI:{ + INI: { file_location: "/resources/adf/allFileTypes/desktop.ini", file_name: "desktop.ini" }, @@ -514,7 +514,20 @@ exports.Files = { }; exports.ACTIVITI7_APPS = { - CANDIDATE_USER_APP : "candidateuserapp", - SIMPLE_APP : "simple-app", - SUB_PROCESS_APP : "subprocess-app" + CANDIDATE_USER_APP: { + name: "candidateuserapp", + file_location: "/resources/activiti7/candidateuserapp.zip" + }, + SIMPLE_APP: { + name: "simpleapp", + file_location: "/resources/activiti7/simpleApp.zip", + processes: { + processwithvariables: "processwithvariables", + simpleProcess: "simpleProcess" + } + }, + SUB_PROCESS_APP: { + name: "subprocess-app", + file_location: "/resources/activiti7/subProcessApp.zip", + } }; diff --git a/lib/core/app-config/app-config.service.ts b/lib/core/app-config/app-config.service.ts index e7e08cf4c4..d9f7247701 100644 --- a/lib/core/app-config/app-config.service.ts +++ b/lib/core/app-config/app-config.service.ts @@ -38,7 +38,8 @@ export enum AppConfigValues { LOGIN_ROUTE = 'loginRoute', DISABLECSRF = 'disableCSRF', AUTH_WITH_CREDENTIALS = 'auth.withCredentials', - APPLICATION = 'application' + APPLICATION = 'application', + NOTIFY_DURATION = 'notificationDefaultDuration' } export enum Status { diff --git a/lib/core/clipboard/clipboard.service.spec.ts b/lib/core/clipboard/clipboard.service.spec.ts index dcea0aedae..8c97214ddf 100644 --- a/lib/core/clipboard/clipboard.service.spec.ts +++ b/lib/core/clipboard/clipboard.service.spec.ts @@ -21,6 +21,11 @@ import { AppConfigService } from '../app-config/app-config.service'; import { TestBed } from '@angular/core/testing'; import { ClipboardModule } from './clipboard.module'; import { ClipboardService } from './clipboard.service'; +import { TranslationService } from '../services/translation.service'; +import { AppConfigServiceMock } from '../mock/app-config.service.mock'; +import { HttpClientModule } from '@angular/common/http'; +import { MatSnackBarModule } from '@angular/material'; +import { TranslationMock } from '@alfresco/adf-core'; describe('ClipboardService', () => { let clipboardService: ClipboardService; @@ -30,20 +35,15 @@ describe('ClipboardService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ - ClipboardModule + ClipboardModule, + HttpClientModule, + MatSnackBarModule ], providers: [ LogService, - NotificationService, - { - provide: AppConfigService, - useValue: new AppConfigService(null) - - }, - { - provide: NotificationService, - useValue: new NotificationService(null, null) - } + { provide: TranslationService, useClass: TranslationMock }, + { provide: AppConfigService, useClass: AppConfigServiceMock }, + NotificationService ] }); }); diff --git a/lib/core/services/notification.service.spec.ts b/lib/core/services/notification.service.spec.ts index 7d2eb3f3b3..fba92dbce9 100644 --- a/lib/core/services/notification.service.spec.ts +++ b/lib/core/services/notification.service.spec.ts @@ -25,6 +25,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NotificationService } from './notification.service'; import { TranslationMock } from '../mock/translation.service.mock'; import { TranslationService } from './translation.service'; +import { HttpClientModule } from '@angular/common/http'; @Component({ template: '', @@ -76,7 +77,8 @@ describe('NotificationService', () => { imports: [ NoopAnimationsModule, OverlayModule, - MatSnackBarModule + MatSnackBarModule, + HttpClientModule ], declarations: [ProvidesNotificationServiceComponent], providers: [ diff --git a/lib/core/services/notification.service.ts b/lib/core/services/notification.service.ts index bbc7b9d0f4..f71527e4aa 100644 --- a/lib/core/services/notification.service.ts +++ b/lib/core/services/notification.service.ts @@ -18,16 +18,20 @@ import { Injectable } from '@angular/core'; import { MatSnackBar, MatSnackBarRef, MatSnackBarConfig } from '@angular/material'; import { TranslationService } from './translation.service'; +import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; @Injectable({ providedIn: 'root' }) export class NotificationService { - static DEFAULT_DURATION_MESSAGE: number = 5000; + DEFAULT_DURATION_MESSAGE: number = 5000; constructor(private snackBar: MatSnackBar, - private translationService: TranslationService) { + private translationService: TranslationService, + private appConfigService: AppConfigService) { + this.DEFAULT_DURATION_MESSAGE = this.appConfigService.get<number>(AppConfigValues.NOTIFY_DURATION) || this.DEFAULT_DURATION_MESSAGE; + } /** @@ -36,7 +40,10 @@ export class NotificationService { * @param config Time before notification disappears after being shown or MatSnackBarConfig object * @returns Information/control object for the SnackBar */ - openSnackMessage(message: string, config: number | MatSnackBarConfig = NotificationService.DEFAULT_DURATION_MESSAGE): MatSnackBarRef<any> { + openSnackMessage(message: string, config?: number | MatSnackBarConfig): MatSnackBarRef<any> { + if (!config) { + config = this.DEFAULT_DURATION_MESSAGE; + } const translatedMessage = this.translationService.instant(message); @@ -56,7 +63,10 @@ export class NotificationService { * @param config Time before notification disappears after being shown or MatSnackBarConfig object * @returns Information/control object for the SnackBar */ - openSnackMessageAction(message: string, action: string, config: number | MatSnackBarConfig = NotificationService.DEFAULT_DURATION_MESSAGE): MatSnackBarRef<any> { + openSnackMessageAction(message: string, action: string, config?: number | MatSnackBarConfig): MatSnackBarRef<any> { + if (!config) { + config = this.DEFAULT_DURATION_MESSAGE; + } const translatedMessage = this.translationService.instant(message); diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts index e64a6dc8f7..b26be954e2 100644 --- a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -24,7 +24,7 @@ import { FormCloudComponent } from './components/form-cloud.component'; import { UploadCloudWidgetComponent } from './components/upload-cloud.widget'; import { MaterialModule } from '../material.module'; import { TaskFormCloudComponent } from './components/task-form-cloud.component'; -import { TaskModule } from '../task/task.module'; +import { TaskCloudModule } from '../task/task-cloud.module'; @NgModule({ imports: [ @@ -37,7 +37,7 @@ import { TaskModule } from '../task/task.module'; ReactiveFormsModule, FormBaseModule, CoreModule, - TaskModule + TaskCloudModule ], declarations: [FormCloudComponent, UploadCloudWidgetComponent, TaskFormCloudComponent], entryComponents: [ diff --git a/lib/process-services-cloud/src/lib/task/task-cloud.module.ts b/lib/process-services-cloud/src/lib/task/task-cloud.module.ts index 9f7e2882fb..ce53b22747 100644 --- a/lib/process-services-cloud/src/lib/task/task-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/task/task-cloud.module.ts @@ -20,19 +20,22 @@ import { TaskListCloudModule } from './task-list/task-list-cloud.module'; import { TaskFiltersCloudModule } from './task-filters/task-filters-cloud.module'; import { StartTaskCloudModule } from './start-task/start-task-cloud.module'; import { TaskHeaderCloudModule } from './task-header/task-header-cloud.module'; +import { TaskDirectiveModule } from './directives/task-directive.module'; @NgModule({ imports: [ TaskListCloudModule, TaskFiltersCloudModule, StartTaskCloudModule, - TaskHeaderCloudModule + TaskHeaderCloudModule, + TaskDirectiveModule ], exports: [ TaskListCloudModule, TaskFiltersCloudModule, StartTaskCloudModule, - TaskHeaderCloudModule + TaskHeaderCloudModule, + TaskDirectiveModule ] }) export class TaskCloudModule { } diff --git a/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts b/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts index 6a7f83d819..8176bc9c85 100644 --- a/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts +++ b/lib/testing/src/lib/process-services-cloud/actions/process-definitions.service.ts @@ -31,7 +31,17 @@ export class ProcessDefinitionsService { const queryParams = {}; - const data = await this.api.performBpmOperation(path, method, queryParams, {}); - return data; + try { + const data = await this.api.performBpmOperation(path, method, queryParams, {}); + return data; + } catch (error) { + if (error.status === 404) { + // tslint:disable-next-line:no-console + console.log(`${appName} not present`); + } else if (error.status === 403) { + // tslint:disable-next-line:no-console + console.log(`Access to the requested resource has been denied ${appName}`); + } + } } } diff --git a/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts index 423f6cd83b..5c56734899 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts @@ -41,7 +41,7 @@ export class EditProcessFilterCloudComponentPage { checkCustomiseFilterHeaderIsExpanded() { const expansionPanelExtended = element.all(by.css('mat-expansion-panel-header[class*="mat-expanded"]')).first(); BrowserVisibility.waitUntilElementIsVisible(expansionPanelExtended); - const content = element(by.css('div[class*="mat-expansion-panel-content "][style*="visible"]')); + const content = element.all(by.css('div[class*="mat-expansion-panel-content "][style*="visible"]')).first(); BrowserVisibility.waitUntilElementIsVisible(content); return this; } diff --git a/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts index 2ee1e1c1f5..2616d7a9d2 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { by, element, protractor } from 'protractor'; +import { browser, by, element, protractor } from 'protractor'; import { BrowserVisibility } from '../../core/browser-visibility'; export class GroupCloudComponentPage { @@ -24,6 +24,7 @@ export class GroupCloudComponentPage { searchGroups(name) { BrowserVisibility.waitUntilElementIsVisible(this.groupCloudSearch); + browser.sleep(1000); this.groupCloudSearch.clear().then(() => { for (let i = 0; i < name.length; i++) { this.groupCloudSearch.sendKeys(name[i]); @@ -53,6 +54,7 @@ export class GroupCloudComponentPage { selectGroupFromList(name) { const groupRow = element.all(by.cssContainingText('mat-option span', name)).first(); BrowserVisibility.waitUntilElementIsVisible(groupRow); + browser.sleep(1000); groupRow.click(); BrowserVisibility.waitUntilElementIsNotVisible(groupRow); return this; diff --git a/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts index 13f38b45e4..b43495f0aa 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { by, element, protractor } from 'protractor'; +import { browser, by, element, protractor } from 'protractor'; import { BrowserVisibility } from '../../core/browser-visibility'; export class PeopleCloudComponentPage { @@ -34,6 +34,7 @@ export class PeopleCloudComponentPage { searchAssignee(name) { BrowserVisibility.waitUntilElementIsVisible(this.peopleCloudSearch); BrowserVisibility.waitUntilElementIsClickable(this.peopleCloudSearch); + browser.sleep(1000); this.peopleCloudSearch.clear().then(() => { for (let i = 0; i < name.length; i++) { this.peopleCloudSearch.sendKeys(name[i]); @@ -57,6 +58,7 @@ export class PeopleCloudComponentPage { selectAssigneeFromList(name) { const assigneeRow = element(by.cssContainingText('mat-option span.adf-people-label-name', name)); BrowserVisibility.waitUntilElementIsVisible(assigneeRow); + browser.sleep(1000); assigneeRow.click(); BrowserVisibility.waitUntilElementIsNotVisible(assigneeRow); return this; @@ -86,6 +88,7 @@ export class PeopleCloudComponentPage { getAssigneeFieldContent() { BrowserVisibility.waitUntilElementIsVisible(this.assigneeField); + browser.sleep(1000); return this.assigneeField.getAttribute('value'); } diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts index 83579432b9..e741e51973 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts @@ -24,8 +24,8 @@ export class ProcessHeaderCloudPage { nameField = element.all(by.css('span[data-automation-id*="name"] span')).first(); statusField = element(by.css('span[data-automation-id*="status"] span')); initiatorField = element(by.css('span[data-automation-id*="initiator"] span')); - startDateField = element(by.css('span[data-automation-id*="startDate"] span')); - lastModifiedField = element(by.css('span[data-automation-id*="lastModified"] span')); + startDateField = element.all(by.css('span[data-automation-id*="startDate"] span')).first(); + lastModifiedField = element.all(by.css('span[data-automation-id*="lastModified"] span')).first(); parentIdField = element(by.css('span[data-automation-id*="parentId"] span')); businessKeyField = element.all(by.css('span[data-automation-id*="businessKey"] span')).first(); diff --git a/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts index a3ab574fa3..5a48996e8d 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts @@ -86,6 +86,7 @@ export class StartProcessCloudPage { } checkStartProcessButtonIsEnabled() { + BrowserVisibility.waitUntilElementIsClickable(this.startProcessButton); expect(this.startProcessButton.isEnabled()).toBe(true); } diff --git a/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts index 47ec6963ea..0d483a62f0 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts @@ -27,7 +27,7 @@ export class StartTasksCloudPage { startButton = element(by.css('button[id="button-start"]')); startButtonEnabled = element(by.css('button[id="button-start"]:not(disabled)')); cancelButton = element(by.css('button[id="button-cancel"]')); - form = element(by.css('adf-cloud-start-task form')); + form = element.all(by.css('adf-cloud-start-task form')).first(); checkFormIsDisplayed() { BrowserVisibility.waitUntilElementIsVisible(this.form); diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts index 34b935ed6e..192361ef68 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts @@ -23,7 +23,7 @@ export class TaskHeaderCloudPage { assigneeField = element(by.css('span[data-automation-id*="assignee"] span')); statusField = element(by.css('span[data-automation-id*="status"] span')); priorityField = element(by.css('span[data-automation-id*="priority"] span')); - dueDateField = element(by.css('span[data-automation-id*="dueDate"] span')); + dueDateField = element.all(by.css('span[data-automation-id*="dueDate"] span')).first(); categoryField = element(by.css('span[data-automation-id*="category"] span')); createdField = element(by.css('span[data-automation-id="card-dateitem-created"] span')); parentNameField = element(by.css('span[data-automation-id*="parentName"] span')); diff --git a/package-lock.json b/package-lock.json index 06149ed9bc..8544d55b76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,69 +1,69 @@ { "name": "alfresco-components", - "version": "3.2.0-beta3", + "version": "3.2.0-beta6", "lockfileVersion": 1, "requires": true, "dependencies": { "@alfresco/adf-content-services": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta3.tgz", - "integrity": "sha512-OVPpclIBbJjFmRPXD8fGGBk0t7i6Avz3Xuk/DjgxFZfJdJDEb+it2KSPR4wT38NZS95vJHtB6TCfh76rMQJzHQ==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.2.0-beta6.tgz", + "integrity": "sha512-ENQKbCZ8p6mOHFijS5gDIoUZHdX7nSQw87I9U1qxZA85/5Y7tOz58ZmRhA6tathN2S/D6nsXgAqql+y6HGCdTw==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-core": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta3.tgz", - "integrity": "sha512-lT7c9QYatJS4x3oAupgiASCGvzQyowZWBoYu32YctS/F6876QAPPaegjkRxqitWjfvs7aXRaCYydb5BoDeLkRg==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.2.0-beta6.tgz", + "integrity": "sha512-DCe2FLGL3UnRCQ7cnxHKZhmK3inWaERhguTl2WIwEWl2wmyJoDd2tDQrc2cfIdjNrqpz3D6yJQdFtExv4XseKw==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-extensions": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta3.tgz", - "integrity": "sha512-TEguuRhzbj6cAeawLJqcK0o8lNzeRO7Pmw9Paxeu9m5RtQEPfvwGydDrlDGWnJ3H5Xx8byxhERIgdOfuK2SWTg==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.2.0-beta6.tgz", + "integrity": "sha512-fPN2kf7NyWU9FvmE9KHayKG87RZEUIzhXRAHGgCuXMzjXsJdddPoNF8c9cvb03MfEFuGHU6cHR75x2Td+GL94w==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-insights": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta3.tgz", - "integrity": "sha512-19zsI39GREZ6fzvs+4fw0FktMSLz6qSq8P2+QTRUThvtL1KZFLeW76BEZPX19YG/K0OuQvuLTXKt2tsf1CChRw==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-insights/-/adf-insights-3.2.0-beta6.tgz", + "integrity": "sha512-i3ak+KZFVaNaikoa0hrF+U/v5y/YUuPFJTFGg32wsRtfeJuCC4IhcyRx6VHRO4QIwnhVKSDh1QPx86DjKpW44Q==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta3.tgz", - "integrity": "sha512-rwJLBrrRI+ndHa7H+RMMlLtbs44yR4Y1pMOCnfchqtGD1m7G/D2g/n5WHo7fp832rU8RP3yw/ZEz4WzMZuxcfA==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services/-/adf-process-services-3.2.0-beta6.tgz", + "integrity": "sha512-QfwhCR6Ykk4ny5NAMwtDAs+UkaGopvmyAwcFglim/RwQJKF3MnFG/gX0K/p6eJDzDRZhoumfzh+I/mBU5DVk9Q==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-process-services-cloud": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta3.tgz", - "integrity": "sha512-j0QWbMBvGN/zRfI0L7V+uXQvY8pSBnOsvBpUEh889WPlf/XWacfKC+a08/UHH5l0YRuWdn4H7cenYrMewdzgiA==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-process-services-cloud/-/adf-process-services-cloud-3.2.0-beta6.tgz", + "integrity": "sha512-lhqU/n1AptJm3ALYImdCj1VpvVbllT8qyBCO/yQN9W+GrRNGnapZh8H7sS1JwTgRkfJMqRAUWQpnlWc1sEK/JA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-testing": { - "version": "3.2.0-beta3", - "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta3.tgz", - "integrity": "sha512-aB4duKaP4CUms90FrvNyL6xunjTHguwYlTlF+/ImqmEZbS0gIvFajyzEbSv0xbtFJRbuYWVQTh41ad6n2vml9A==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/adf-testing/-/adf-testing-3.2.0-beta6.tgz", + "integrity": "sha512-xweqGzrgK2lvzQONc3ZC4cXWsLXTmesr1oybEu06FbK9MkXf+aUlGvCG3hLueYkU3GwnLRFu9ZsDnRCH8ZIwfA==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/js-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.1.0.tgz", - "integrity": "sha512-kjh2vmbZ2LImNVUOfmYz6kZPcv/8IoMFLtOOcL5IrBg6PdYxYlmjAw5Gs/5wlNHuqSnZe6nNfZCPlmYDxsL6aQ==", + "version": "3.2.0-beta6", + "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.2.0-beta6.tgz", + "integrity": "sha512-XWsA5lTcrJ5WOeXvej/TAh9NEyExue4SO07RvLNNU+NKB8lW/3V0N29V8I15daquh4eJWi783SJz+24Pbp6Edw==", "requires": { "event-emitter": "0.3.4", "superagent": "3.8.2" @@ -9534,21 +9534,6 @@ "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", "dev": true }, - "jasmine-fail-fast": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jasmine-fail-fast/-/jasmine-fail-fast-2.0.0.tgz", - "integrity": "sha1-5dguaimiX2YsZA5MMnDC+acTh+c=", - "requires": { - "lodash": "3.10.0" - }, - "dependencies": { - "lodash": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz", - "integrity": "sha1-k9UcZygopEFqEq9XIguoqHN+L7s=" - } - } - }, "jasmine-reporters": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.3.2.tgz", @@ -13958,14 +13943,6 @@ } } }, - "protractor-fail-fast": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/protractor-fail-fast/-/protractor-fail-fast-3.1.0.tgz", - "integrity": "sha512-OjuIFmY7hm5R/Msmioyg3aBevySpmpIgtm2TGUvMEqTzviPk/Fqd1HYmMjIQ+NzFMzrK+93LJa4civDvw1+hEg==", - "requires": { - "jasmine-fail-fast": "~2.0.0" - } - }, "protractor-html-reporter-2": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/protractor-html-reporter-2/-/protractor-html-reporter-2-1.0.4.tgz", diff --git a/scripts/check-activiti-env.js b/scripts/check-activiti-env.js new file mode 100755 index 0000000000..f87a0078a4 --- /dev/null +++ b/scripts/check-activiti-env.js @@ -0,0 +1,188 @@ +let path = require('path'); +let fs = require('fs'); +let alfrescoApi = require('@alfresco/js-api'); +let program = require('commander'); +let ACTIVITI7_APPS = require('../e2e/util/resources').ACTIVITI7_APPS; + +let config = {}; +let absentApps = []; +let host; + +async function main() { + + program + .version('0.1.0') + .option('--host [type]', 'Remote environment host adf.lab.com ') + .option('--client [type]', 'clientId ') + .option('-p, --password [type]', 'password ') + .option('-u, --username [type]', 'username ') + .parse(process.argv); + + config = { + provider: 'BPM', + hostBpm: `http://${program.host}`, + authType: 'OAUTH', + oauth2: { + host: `http://${program.host}/auth/realms/alfresco`, + clientId: program.client, + scope: 'openid', + secret: '', + implicitFlow: false, + silentLogin: false, + redirectUri: '/', + redirectUriLogout: '/logout' + } + }; + + host = program.host; + + try { + this.alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility(config); + await this.alfrescoJsApi.login(program.username, program.password); + } catch (e) { + console.log('Login error' + e); + } + + let appsDeployed = await getDeployedApplicationsByStatus(this.alfrescoJsApi, 'RUNNING'); + + Object.keys(ACTIVITI7_APPS).forEach((key) => { + let isPresent = appsDeployed.find((currentApp) => { + return ACTIVITI7_APPS[key].name === currentApp.entry.name; + }); + + if (!isPresent) { + absentApps.push(ACTIVITI7_APPS[key]); + } + }); + + if (absentApps.length > 0) { + console.log(`The following apps are missing in the target env ${JSON.stringify(absentApps)}`) + + await checkIfAppIsReleased(this.alfrescoJsApi, absentApps); + + process.exit(1); + } +} + +async function checkIfAppIsReleased(apiService, absentApps) { + let listAppsInModeler = await getAppProjects(apiService); + + for (let i = 0; i < absentApps.length; i++) { + let currentAbsentApp = absentApps[i]; + let isPresent = listAppsInModeler.find((currentApp) => { + return currentAbsentApp.name === currentApp.entry.name; + }); + + if (!isPresent) { + console.log(`uplodare ` + currentAbsentApp.name); + let uploadedApp = await importApp(apiService, currentAbsentApp); + if (uploadedApp) { + await releaseApp(apiService, uploadedApp); + await deployApp(apiService, uploadedApp); + } + } + } +} + +async function deployApp(apiService, app) { + const url = `${config.hostBpm}/alfresco-deployment-service/v1/applications`; + + const pathParams = {}, + queryParams = { + "name": "re", + "releaseId": app.entry.id, + "security": [{"role": "APS_ADMIN", "groups": [], "users": ["admin.adf"]}, { + "role": "APS_USER", + "groups": [], + "users": ["admin.adf"] + }] + }; + + const headerParams = {}, formParams = {}, bodyParam = {}, + contentTypes = ['multipart/form-data'], accepts = ['application/json']; + + try { + return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + } catch (error) { + console.log(`Not possible to deploy the project ${app.entry.name} ` + error); + process.exit(1); + } +} + +async function importApp(apiService, app) { + const pathFile = path.join('./e2e/' + app.file_location); + const file = fs.createReadStream(pathFile); + + const url = `${config.hostBpm}/alfresco-modeling-service/v1/projects/import`; + + const pathParams = {}, queryParams = {}, + headerParams = {}, formParams = {'file': file}, bodyParam = {}, + contentTypes = ['multipart/form-data'], accepts = ['application/json']; + + try { + return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + } catch (error) { + console.log(`Not possible to upload the project ${app.name} ` + error); + process.exit(1); + } + +} + +async function releaseApp(apiService, app) { + const url = `${config.hostBpm}alfresco-modeling-service/v1/projects/${app.entry.id}/releases`; + console.log(url); + + const pathParams = {}, queryParams = {}, + headerParams = {}, formParams = {}, bodyParam = {}, + contentTypes = ['application/json'], accepts = ['application/json']; + + try { + return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + } catch (error) { + console.log(`Not possible to release the project ${app.entry.name} ` + error); + process.exit(1); + } + +} + +async function getDeployedApplicationsByStatus(apiService, status) { + const url = `${config.hostBpm}/alfresco-deployment-service/v1/applications`; + + const pathParams = {}, queryParams = {status: status}, + headerParams = {}, formParams = {}, bodyParam = {}, + contentTypes = ['application/json'], accepts = ['application/json']; + + let data; + try { + data = await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + return data.list.entries; + } catch (error) { + console.log(`Not possible get the application from alfresco-deployment-service` + error); + process.exit(1); + } + +} + +async function getAppProjects(apiService, status) { + const url = `${config.hostBpm}/alfresco-modeling-service/v1/projects`; + + const pathParams = {}, queryParams = {status: status}, + headerParams = {}, formParams = {}, bodyParam = {}, + contentTypes = ['application/json'], accepts = ['application/json']; + + let data; + try { + data = await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + return data.list.entries; + } catch (error) { + console.log(`Not possible get the application from alfresco-modeling-service` + error); + process.exit(1); + } +} + +main(); diff --git a/scripts/test-e2e-lib.sh b/scripts/test-e2e-lib.sh index 88f4c6c9ae..78c677c9cd 100755 --- a/scripts/test-e2e-lib.sh +++ b/scripts/test-e2e-lib.sh @@ -7,7 +7,7 @@ DEVELOPMENT=false EXECLINT=true LITESERVER=false EXEC_VERSION_JSAPI=false -TIMEOUT=7000 +TIMEOUT=20000 SELENIUM_PROMISE_MANAGER=1 show_help() { diff --git a/scripts/update-project.sh b/scripts/update-project.sh index 126f8e0521..9ed0490cd4 100755 --- a/scripts/update-project.sh +++ b/scripts/update-project.sh @@ -56,6 +56,6 @@ git add . git commit -m "Update ADF packages version $VERSION" git push -u origin $BRANCH -curl -H "Authorization: token $TOKEN" -X POST -d '{"body":"Update ADF packages version '$VERSION'","head":"'$BRANCH'","base":"development","title":"Update ADF packages version '$VERSION'"}' https://api.github.com/repos/alfresco/$NAME_REPO/pulls +curl -H "Authorization: token $TOKEN" -X POST -d '{"body":"Update ADF packages version '$VERSION'","head":"'$BRANCH'","base":"development","title":"Update ADF packages version '$VERSION'"}' https://api.github.com/repos/$NAME_REPO/pulls rm -rf $TEMP_GENERATOR_DIR; From 159e6a5c705895a949ab7381b1c73e6c5e5100bc Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Thu, 18 Apr 2019 14:17:52 +0100 Subject: [PATCH 124/208] fix lint --- e2e/search/components/search-checkList.e2e.ts | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index 993ea719e0..54f7181a63 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -69,8 +69,14 @@ describe('Search Checklist Component', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - createdFolder = await this.alfrescoJsApi.nodes.addNode('-my-', {name: nodeNames.folder, nodeType: 'cm:folder'}); - createdFile = await this.alfrescoJsApi.nodes.addNode('-my-', {name: nodeNames.document, nodeType: 'cm:content'}); + createdFolder = await this.alfrescoJsApi.nodes.addNode('-my-', { + name: nodeNames.folder, + nodeType: 'cm:folder' + }); + createdFile = await this.alfrescoJsApi.nodes.addNode('-my-', { + name: nodeNames.document, + nodeType: 'cm:content' + }); await browser.driver.sleep(15000); @@ -136,13 +142,16 @@ describe('Search Checklist Component', () => { jsonFile = searchConfiguration.getConfiguration(); }); - fit('[C277143] Should be able to click show more/less button with pageSize set as default', async() => { + it('[C277143] Should be able to click show more/less button with pageSize set as default', async () => { for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { - jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', 'value': "TYPE:'cm:folder'" }); + jsonFile.categories[1].component.settings.options.push({ + 'name': 'Folder', + 'value': "TYPE:'cm:folder'" + }); } await setConfigField('search', JSON.stringify(jsonFile)); -browser.sleep(2000); + browser.sleep(2000); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -168,11 +177,14 @@ browser.sleep(2000); browser.refresh(); }); - it('[C277144] Should be able to click show more/less button with pageSize set with a custom value', async() => { + it('[C277144] Should be able to click show more/less button with pageSize set with a custom value', async () => { jsonFile.categories[1].component.settings.pageSize = 10; for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { - jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', 'value': "TYPE:'cm:folder'" }); + jsonFile.categories[1].component.settings.options.push({ + 'name': 'Folder', + 'value': "TYPE:'cm:folder'" + }); } await setConfigField('search', JSON.stringify(jsonFile)); @@ -211,11 +223,14 @@ browser.sleep(2000); browser.refresh(); }); - it('[C277145] Should be able to click show more/less button with pageSize set to zero', async() => { + it('[C277145] Should be able to click show more/less button with pageSize set to zero', async () => { jsonFile.categories[1].component.settings.pageSize = 0; for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { - jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', 'value': "TYPE:'cm:folder'" }); + jsonFile.categories[1].component.settings.options.push({ + 'name': 'Folder', + 'value': "TYPE:'cm:folder'" + }); } await setConfigField('search', JSON.stringify(jsonFile)); @@ -274,7 +289,7 @@ browser.sleep(2000); done(); }); - it('[C277018] Should be able to change the operator', async() => { + it('[C277018] Should be able to change the operator', async () => { jsonFile.categories[1].component.settings.operator = 'AND'; await setConfigField('search', JSON.stringify(jsonFile)); @@ -296,8 +311,11 @@ browser.sleep(2000); browser.refresh(); }); - it('[C277019] Should be able to add new properties with different types', async() => { - jsonFile.categories[1].component.settings.options.push({ 'name': filterType.custom, 'value': "TYPE:'cm:auditable'" }); + it('[C277019] Should be able to add new properties with different types', async () => { + jsonFile.categories[1].component.settings.options.push({ + 'name': filterType.custom, + 'value': "TYPE:'cm:auditable'" + }); await setConfigField('search', JSON.stringify(jsonFile)); From 7826eea9461b56bd6419efdd2980a2b6c612c6ac Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Thu, 18 Apr 2019 14:30:17 +0100 Subject: [PATCH 125/208] fix spell --- cspell.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index 62f2f884db..fc8475a2ba 100644 --- a/cspell.json +++ b/cspell.json @@ -126,7 +126,8 @@ "uncheck", "subfolders", "ECMBPM", - "candidateuserapp" + "candidateuserapp", + "processwithvariables" ], "dictionaries": [ "html", From cc53d96698221a228416586e742cf140b4e01009 Mon Sep 17 00:00:00 2001 From: Cilibiu Bogdan <pionnegru@users.noreply.github.com> Date: Thu, 18 Apr 2019 16:36:37 +0300 Subject: [PATCH 126/208] [ADF-4410] Upload dialog - remove delete action of version upload (#4618) * undo remove node version implementation * clean up style * version upload row style * upload version row cells * update tests * fix aria label --- .../upload/remove-upload.e2e.ts | 10 ++--- lib/content-services/i18n/en.json | 3 ++ .../file-uploading-dialog.component.scss | 4 -- .../file-uploading-list-row.component.html | 14 +++++- .../file-uploading-list-row.component.scss | 2 +- .../file-uploading-list-row.component.spec.ts | 16 ++++++- .../file-uploading-list.component.spec.ts | 28 +----------- .../file-uploading-list.component.ts | 45 ++++--------------- 8 files changed, 43 insertions(+), 79 deletions(-) diff --git a/e2e/content-services/upload/remove-upload.e2e.ts b/e2e/content-services/upload/remove-upload.e2e.ts index 60100b4fb4..10bc747755 100644 --- a/e2e/content-services/upload/remove-upload.e2e.ts +++ b/e2e/content-services/upload/remove-upload.e2e.ts @@ -27,7 +27,6 @@ import TestConfig = require('../../test.config'); import resources = require('../../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { browser } from 'protractor'; describe('Upload component', () => { const contentServicesPage = new ContentServicesPage(); @@ -81,7 +80,7 @@ describe('Upload component', () => { .clickOnCloseButton(); }); - it('should revert to last version when remove uploaded version file', () => { + it('should not have remove action if uploaded file is a file version', () => { contentServicesPage.uploadFile(docxFileModel.location); uploadDialog.fileIsUploaded(docxFileModel.name); contentServicesPage.checkContentIsDisplayed(docxFileModel.name); @@ -92,10 +91,7 @@ describe('Upload component', () => { fileModelVersion.location ); versionManagePage.closeVersionDialog(); - uploadDialog - .removeUploadedFile(fileModelVersion.name) - .fileIsCancelled(fileModelVersion.name); - browser.refresh(); - contentServicesPage.checkContentIsDisplayed(docxFileModel.name); + uploadDialog.removeUploadedFile(fileModelVersion.name); + contentServicesPage.checkContentIsDisplayed(fileModelVersion.name); }); }); diff --git a/lib/content-services/i18n/en.json b/lib/content-services/i18n/en.json index bfbfd692ae..9034f6f2ee 100644 --- a/lib/content-services/i18n/en.json +++ b/lib/content-services/i18n/en.json @@ -128,6 +128,9 @@ "TITLE": "Cancel Upload", "TEXT": "Stop uploading and remove files already uploaded." } + }, + "ARIA-LABEL": { + "VERSION": "File version" } }, "FILE_UPLOAD": { diff --git a/lib/content-services/upload/components/file-uploading-dialog.component.scss b/lib/content-services/upload/components/file-uploading-dialog.component.scss index caf12dbfd1..500f28f13e 100644 --- a/lib/content-services/upload/components/file-uploading-dialog.component.scss +++ b/lib/content-services/upload/components/file-uploading-dialog.component.scss @@ -87,9 +87,5 @@ text-transform: uppercase; } } - - & mat-icon { - cursor: pointer; - } } } diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.html b/lib/content-services/upload/components/file-uploading-list-row.component.html index 1a50d171d2..729b18c1ee 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.html +++ b/lib/content-services/upload/components/file-uploading-list-row.component.html @@ -12,7 +12,7 @@ </span> <span *ngIf="isUploadVersion()" class="adf-file-uploading-row__version"> - <mat-chip aria-label="file version" color="primary" disabled>{{ + <mat-chip color="primary" [attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.VERSION' | translate" [title]="'version' + versionNumber" disabled>{{ versionNumber }}</mat-chip> </span> @@ -34,7 +34,7 @@ </div> <div - *ngIf="file.status === FileUploadStatus.Complete" + *ngIf="file.status === FileUploadStatus.Complete && !isUploadVersion()" (click)="onRemove(file)" class="adf-file-uploading-row__group adf-file-uploading-row__group--toggle" title="{{ 'ADF_FILE_UPLOAD.BUTTON.REMOVE_FILE' | translate }}"> @@ -51,6 +51,16 @@ </mat-icon> </div> + <div + *ngIf="file.status === FileUploadStatus.Complete && isUploadVersion()" + class="adf-file-uploading-row__file-version"> + <mat-icon + mat-list-icon + class="adf-file-uploading-row__status--done"> + check_circle + </mat-icon> + </div> + <div *ngIf="file.status === FileUploadStatus.Pending" (click)="onCancel(file)" diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.scss b/lib/content-services/upload/components/file-uploading-list-row.component.scss index 7710fb0fe1..a3eb07584b 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.scss +++ b/lib/content-services/upload/components/file-uploading-list-row.component.scss @@ -30,7 +30,7 @@ padding: 0 1em 0 0.5em; } - &__group, &__block { + &__group, &__block, &__file-version { min-width: 100px; display: flex; justify-content: flex-end; diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts b/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts index 71182fd38d..fe6a28043e 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts +++ b/lib/content-services/upload/components/file-uploading-list-row.component.spec.ts @@ -16,7 +16,7 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FileModel, CoreModule, FileUploadOptions } from '@alfresco/adf-core'; +import { FileModel, CoreModule, FileUploadOptions, FileUploadStatus } from '@alfresco/adf-core'; import { UploadModule } from '../upload.module'; import { FileUploadingListRowComponent } from './file-uploading-list-row.component'; @@ -70,4 +70,18 @@ describe('FileUploadingListRowComponent', () => { '.adf-file-uploading-row__version' ).textContent).toContain('1'); }); + + it('should not emit remove event on a version file', () => { + spyOn(component.remove, 'emit'); + component.file = new FileModel(<File> { name: 'fake-name' }); + component.file.options = <FileUploadOptions> { newVersion: true }; + component.file.data = { entry: { properties: { 'cm:versionLabel': '1' } } }; + component.file.status = FileUploadStatus.Complete; + + fixture.detectChanges(); + const uploadCompleteIcon = document.querySelector('.adf-file-uploading-row__file-version .adf-file-uploading-row__status--done'); + uploadCompleteIcon.dispatchEvent(new MouseEvent('click')); + + expect(component.remove.emit).not.toHaveBeenCalled(); + }); }); diff --git a/lib/content-services/upload/components/file-uploading-list.component.spec.ts b/lib/content-services/upload/components/file-uploading-list.component.spec.ts index c2e5789511..4afa46c18e 100644 --- a/lib/content-services/upload/components/file-uploading-list.component.spec.ts +++ b/lib/content-services/upload/components/file-uploading-list.component.spec.ts @@ -17,7 +17,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TranslationService, FileUploadStatus, NodesApiService, UploadService, - setupTestBed, CoreModule, AlfrescoApiService, AlfrescoApiServiceMock, FileModel, FileUploadOptions + setupTestBed, CoreModule, AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core'; import { of, throwError } from 'rxjs'; import { UploadModule } from '../upload.module'; @@ -30,7 +30,6 @@ describe('FileUploadingListComponent', () => { let uploadService: UploadService; let nodesApiService: NodesApiService; let translateService: TranslationService; - let alfrescoApiService: AlfrescoApiService; let file: any; beforeEach(() => { @@ -56,7 +55,6 @@ describe('FileUploadingListComponent', () => { translateService = TestBed.get(TranslationService); fixture = TestBed.createComponent(FileUploadingListComponent); - alfrescoApiService = TestBed.get(AlfrescoApiService); component = fixture.componentInstance; spyOn(translateService, 'get').and.returnValue(of('some error message')); @@ -108,30 +106,6 @@ describe('FileUploadingListComponent', () => { expect(uploadService.cancelUpload).toHaveBeenCalled(); }); - it('should delete node version', () => { - spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(of(file)); - file = new FileModel(<File> { name: 'fake-name' }); - file.options = <FileUploadOptions> { newVersion: true }; - file.data = { entry: { id: 'nodeId', properties: { 'cm:versionLabel': '1' } } }; - - component.removeFile(file); - - expect(alfrescoApiService.versionsApi.deleteVersion).toHaveBeenCalled(); - }); - - it('should throw error when delete node version fails', (done) => { - spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(throwError(file)); - file = new FileModel(<File> { name: 'fake-name' }); - file.options = <FileUploadOptions> { newVersion: true }; - file.data = { entry: { id: 'nodeId', properties: { 'cm:versionLabel': '1' } } }; - - component.error.subscribe(() => { - done(); - }); - - component.removeFile(file); - }); - describe('Events', () => { it('should throw an error event if delete file goes wrong', (done) => { diff --git a/lib/content-services/upload/components/file-uploading-list.component.ts b/lib/content-services/upload/components/file-uploading-list.component.ts index c1954a11c8..bd31019ec8 100644 --- a/lib/content-services/upload/components/file-uploading-list.component.ts +++ b/lib/content-services/upload/components/file-uploading-list.component.ts @@ -19,7 +19,6 @@ import { FileModel, FileUploadStatus, NodesApiService, - AlfrescoApiService, TranslationService, UploadService } from '@alfresco/adf-core'; @@ -31,7 +30,7 @@ import { TemplateRef, EventEmitter } from '@angular/core'; -import { Observable, forkJoin, of, from } from 'rxjs'; +import { Observable, forkJoin, of } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; @Component({ @@ -53,7 +52,6 @@ export class FileUploadingListComponent { error: EventEmitter<any> = new EventEmitter(); constructor( - private alfrescoApiService: AlfrescoApiService, private uploadService: UploadService, private nodesApi: NodesApiService, private translateService: TranslationService @@ -78,23 +76,14 @@ export class FileUploadingListComponent { * @memberOf FileUploadingListComponent */ removeFile(file: FileModel): void { - if (file.options && file.options.newVersion) { - this.deleteNodeVersion(file).subscribe(() => { - if (file.status === FileUploadStatus.Error) { - this.notifyError(file); - } - this.uploadService.cancelUpload(file); - }); - } else { - this.deleteNode(file).subscribe(() => { - if (file.status === FileUploadStatus.Error) { - this.notifyError(file); - } + this.deleteNode(file).subscribe(() => { + if (file.status === FileUploadStatus.Error) { + this.notifyError(file); + } - this.cancelNodeVersionInstances(file); - this.uploadService.cancelUpload(file); - }); - } + this.cancelNodeVersionInstances(file); + this.uploadService.cancelUpload(file); + }); } /** @@ -168,24 +157,6 @@ export class FileUploadingListComponent { ); } - private deleteNodeVersion(file: FileModel): Observable<FileModel> { - return from( - this.alfrescoApiService.versionsApi.deleteVersion( - file.data.entry.id, - file.data.entry.properties['cm:versionLabel'] - ) - ).pipe( - map(() => { - file.status = FileUploadStatus.Deleted; - return file; - }), - catchError(() => { - file.status = FileUploadStatus.Error; - return of(file); - }) - ); - } - private cancelNodeVersionInstances(file) { this.files .filter( From 59eee6ebaf7ae3c10c0fcb02adfcdff2eae6c557 Mon Sep 17 00:00:00 2001 From: Suzana Dirla <dirla.silvia.suzana@gmail.com> Date: Thu, 18 Apr 2019 18:07:31 +0300 Subject: [PATCH 127/208] [ADF-4401] Fix DL issues because of nested 'adf-datatable-cell' items (#4615) * [ADF-4401] remove classname from nested items - use 'adf-content-cell' instead * [ADF-4401] some DL display fixes - align header cells with content cells - columns aligned on Trashcan DL - ellipsis on long folder names inside the content node selector - more width on highlight cell from search-results * [ADF-4401] use 'adf-content-cell' - to allow ellipsis to display when a parent has 'adf-ellipsis-cell' class * [ADF-4401] remove not used styles * [ADF-4401] rename scss classname to have 'adf-datatable' prefix * [ADF-4401] Add documentation for datatable --- .../name-column/name-column.component.ts | 2 +- .../app/components/files/files.component.html | 2 +- .../trashcan/trashcan.component.html | 3 +- docs/core/components/datatable.component.md | 38 ++++++++++++++++- .../name-location-cell.component.ts | 2 +- .../library-name-column.component.ts | 2 +- .../library-role-column.component.ts | 2 +- .../library-status-column.component.ts | 2 +- .../name-column/name-column.component.ts | 2 +- .../trashcan-name-column.component.ts | 2 +- .../datatable/datatable-cell.component.ts | 2 +- .../datatable/datatable.component.scss | 41 ++++++++++--------- .../datatable/date-cell.component.ts | 2 +- .../datatable/json-cell.component.ts | 2 +- .../datatable/location-cell.component.ts | 2 +- 15 files changed, 72 insertions(+), 34 deletions(-) diff --git a/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts b/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts index 938c53d450..54c43bce43 100644 --- a/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts +++ b/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts @@ -38,7 +38,7 @@ import { Node } from '@alfresco/js-api'; `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell adf-datatable-link adf-name-column' } + host: { class: 'adf-datatable-content-cell adf-datatable-link adf-name-column' } }) export class NameColumnComponent implements OnInit, OnDestroy { @Input() diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html index 06eec65dd6..0be21ed52d 100644 --- a/demo-shell/src/app/components/files/files.component.html +++ b/demo-shell/src/app/components/files/files.component.html @@ -288,7 +288,7 @@ *ngIf="searchTerm" key="search" title="Search" - class="adf-desktop-only"> + class="adf-desktop-only adf-expand-cell-3"> <ng-template let-entry="$implicit"> <div [innerHTML]="searchResultsHighlight(entry.row.node.entry.search) | highlight:searchTerm"> </div> diff --git a/demo-shell/src/app/components/trashcan/trashcan.component.html b/demo-shell/src/app/components/trashcan/trashcan.component.html index 66229fb45f..0b3317a182 100644 --- a/demo-shell/src/app/components/trashcan/trashcan.component.html +++ b/demo-shell/src/app/components/trashcan/trashcan.component.html @@ -61,7 +61,8 @@ key="name" title="DOCUMENT_LIST.COLUMNS.DISPLAY_NAME"> <ng-template let-value="value" let-context> - <span class="adf-datatable-cell" title="{{ context?.row?.obj | adfNodeNameTooltip }}">{{ value }}</span> + <span title="{{ context?.row?.obj | adfNodeNameTooltip }}" + class="adf-datatable-cell-value">{{ value }}</span> </ng-template> </data-column> diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 96d8caacba..7a463c3ba3 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -248,8 +248,19 @@ export class DataTableDemo { ### [Transclusions](../../user-guide/transclusion.md) -You can add [Data column component](data-column.component.md) instances to define columns for the -table as described in the usage examples and the [Customizing columns](#customizing-columns) section. +You can add [Data column component](data-column.component.md) instances to define columns for thetable as described in the usage examples and the [Customizing columns](#customizing-columns) section. + +```html +<adf-datatable ...> + <data-column> + <!--Add your custom empty template here--> + <ng-template> + <div></div> + <span> My custom value </spam> + </ng-template> + </data-column> +</adf-datatable> +``` You can also supply a `<adf-no-content-template>` or an [Empty list component](empty-list.component.md) sub-component to show when the table is empty: @@ -300,9 +311,32 @@ while the data for the table is loading: } ``` +###Styling transcluded content + +When adding your custom templates you can style them as you like. However, for an out of the box experience, if you want to apply datatable styles to your column you will need to follow this structure: + +```html +<adf-datatable ...> + <data-column> + <!--Add your custom empty template here--> + <ng-template> + <div class="adf-datatable-content-cell"> + <span class="adf-datatable-cell-value"> My custom value </span> + </div> + </ng-template> + </data-column> +</adf-datatable> +``` + +Notice above those two classes. Apply `adf-datatable-content-cell` for the container of the value that you are going to place in that column and `adf-datatable-cell-value` for the value itself. + +If you follow these structure you will be able to apply classes like `.adf-ellipsis-cell` and much more. + Note that you can use both the `<adf-no-content-template>` and the `<adf-loading-content-template>` together in the same datatable. +Learm more about styling your datatable: [Customizing the component's styles](#customizing-the-components-styles) + ## Class members ### Properties diff --git a/lib/content-services/content-node-selector/name-location-cell/name-location-cell.component.ts b/lib/content-services/content-node-selector/name-location-cell/name-location-cell.component.ts index efccd124fe..fcb5692736 100644 --- a/lib/content-services/content-node-selector/name-location-cell/name-location-cell.component.ts +++ b/lib/content-services/content-node-selector/name-location-cell/name-location-cell.component.ts @@ -27,7 +27,7 @@ import { DataRow } from '@alfresco/adf-core'; styleUrls: ['./name-location-cell.component.scss'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, - host: { class: 'adf-name-location-cell' } + host: { class: 'adf-name-location-cell adf-datatable-content-cell' } }) export class NameLocationCellComponent implements OnInit { diff --git a/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts b/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts index 712fe08e7a..1ff690aa88 100644 --- a/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts +++ b/lib/content-services/document-list/components/library-name-column/library-name-column.component.ts @@ -39,7 +39,7 @@ import { BehaviorSubject, Subscription } from 'rxjs'; changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { - class: 'adf-datatable-cell adf-datatable-link adf-library-name-column' + class: 'adf-datatable-content-cell adf-datatable-link adf-library-name-column' } }) export class LibraryNameColumnComponent implements OnInit, OnDestroy { diff --git a/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts b/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts index 90a431efcb..a7087dc218 100644 --- a/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts +++ b/lib/content-services/document-list/components/library-role-column/library-role-column.component.ts @@ -37,7 +37,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-library-role-column' } + host: { class: 'adf-library-role-column adf-datatable-content-cell' } }) export class LibraryRoleColumnComponent implements OnInit, OnDestroy { @Input() diff --git a/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts b/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts index 5b009ebe42..b645884b29 100644 --- a/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts +++ b/lib/content-services/document-list/components/library-status-column/library-status-column.component.ts @@ -28,7 +28,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; {{ (displayText$ | async) | translate }} </span> `, - host: { class: 'adf-library-status-column' } + host: { class: 'adf-library-status-column adf-datatable-content-cell' } }) export class LibraryStatusColumnComponent implements OnInit, OnDestroy { @Input() diff --git a/lib/content-services/document-list/components/name-column/name-column.component.ts b/lib/content-services/document-list/components/name-column/name-column.component.ts index ad093d99cf..144543afa5 100644 --- a/lib/content-services/document-list/components/name-column/name-column.component.ts +++ b/lib/content-services/document-list/components/name-column/name-column.component.ts @@ -39,7 +39,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell adf-datatable-link adf-name-column' } + host: { class: 'adf-datatable-content-cell adf-datatable-link adf-name-column' } }) export class NameColumnComponent implements OnInit, OnDestroy { @Input() diff --git a/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts b/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts index d2dae7a225..34446dbbf3 100644 --- a/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts +++ b/lib/content-services/document-list/components/trashcan-name-column/trashcan-name-column.component.ts @@ -37,7 +37,7 @@ import { ShareDataRow } from '../../data/share-data-row.model'; `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell adf-trashcan-name-column' } + host: { class: 'adf-datatable-content-cell adf-trashcan-name-column' } }) export class TrashcanNameColumnComponent implements OnInit { @Input() diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index d1caf3c6dc..bac6b1c12d 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -52,7 +52,7 @@ import { Node } from '@alfresco/js-api'; </ng-template> `, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell' } + host: { class: 'adf-datatable-content-cell' } }) export class DataTableCellComponent implements OnInit, OnDestroy { /** Data table adapter instance. */ diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index ce7d172b55..025e973631 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -19,6 +19,7 @@ $data-table-card-padding: 24px !default; $data-table-cell-top: $data-table-card-padding / 2; $data-table-drag-border: 1px dashed rgb(68, 138, 255); + $data-table-thumbnail-width: 50px !default; .adf-datatable-card { @@ -207,12 +208,14 @@ padding-right: 20px; .adf-datatable-checkbox { - max-width: 50px; + max-width: $data-table-thumbnail-width; + width: $data-table-thumbnail-width; } } - .adf-datatable-cell { + .adf-datatable-cell, .adf-datatable-cell-header { text-align: left; + box-sizing: border-box; &--text { text-align: left; @@ -230,7 +233,8 @@ &--image { padding-left: 24px; padding-right: 24px; - width: 10px; + width: $data-table-thumbnail-width; + min-width: $data-table-thumbnail-width; text-align: left; } @@ -249,12 +253,11 @@ font-weight: bold; line-height: 24px; letter-spacing: 0; - height: $data-table-row-height; + min-height: $data-table-row-height !important; font-size: $data-table-header-font-size; color: $data-table-header-color; padding-bottom: 8px; box-sizing: border-box; - white-space: nowrap; &:focus { outline-offset: -1px; @@ -280,7 +283,8 @@ @include typo-icon; font-size: $data-table-header-sort-icon-size; content: '\e5d8'; - margin-right: 5px; + left: 5px; + position: relative; vertical-align: sub; } } @@ -335,7 +339,8 @@ .adf-datatable-cell-value { word-break: break-word; - padding: 0 10px; + padding: 10px; + display: block; } &:focus { @@ -348,15 +353,16 @@ display: flex; min-height: inherit; align-items: center; + word-break: break-all; } .adf-datatable__actions-cell, .adf-datatable-cell--image { - max-width: 50px; + max-width: $data-table-thumbnail-width; display: flex; } .adf-datatable-cell--image { - max-width: 50px; + max-width: $data-table-thumbnail-width; } .adf-location-cell { @@ -402,23 +408,20 @@ text-overflow: ellipsis; white-space: nowrap; - .adf-datatable-cell, .adf-datatable-cell-header { + &.adf-datatable-cell-header, + .adf-datatable-content-cell { + max-width: calc(100% - 0.1px); overflow: hidden; - - .adf-datatable-cell-container { - overflow: hidden; - } + text-overflow: ellipsis; .adf-datatable-cell-value { overflow: hidden; text-overflow: ellipsis; - white-space: nowrap; - display: block; - width: calc(100% - 2em); - position: absolute; - // margin-top: -10px; } } + .adf-datatable-content-cell { + position: absolute; + } /* query for Microsoft IE 11*/ @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) { diff --git a/lib/core/datatable/components/datatable/date-cell.component.ts b/lib/core/datatable/components/datatable/date-cell.component.ts index 51112a3db6..a1643818b3 100644 --- a/lib/core/datatable/components/datatable/date-cell.component.ts +++ b/lib/core/datatable/components/datatable/date-cell.component.ts @@ -48,7 +48,7 @@ import { AlfrescoApiService } from '../../../services/alfresco-api.service'; </ng-template> `, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-date-cell adf-datatable-cell' } + host: { class: 'adf-date-cell adf-datatable-content-cell' } }) export class DateCellComponent extends DataTableCellComponent { currentLocale: string; diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts index 5f459c05a0..500a867e16 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.ts +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -40,7 +40,7 @@ import { DataTableCellComponent } from './datatable-cell.component'; `, styleUrls: ['./json-cell.component.scss'], encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell' } + host: { class: 'adf-datatable-content-cell' } }) export class JsonCellComponent extends DataTableCellComponent implements OnInit { diff --git a/lib/core/datatable/components/datatable/location-cell.component.ts b/lib/core/datatable/components/datatable/location-cell.component.ts index 1a62782a1e..bd37d216ee 100644 --- a/lib/core/datatable/components/datatable/location-cell.component.ts +++ b/lib/core/datatable/components/datatable/location-cell.component.ts @@ -37,7 +37,7 @@ import { AlfrescoApiService } from '../../../services/alfresco-api.service'; </ng-container> `, encapsulation: ViewEncapsulation.None, - host: { class: 'adf-location-cell' } + host: { class: 'adf-location-cell adf-datatable-content-cell' } }) export class LocationCellComponent extends DataTableCellComponent implements OnInit { @Input() From 0b09af3ac6470e836b82cf7dc052393772750049 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Thu, 18 Apr 2019 17:17:10 +0200 Subject: [PATCH 128/208] [ADF-4291] Fix lastModifiedTo filter on processes (#4624) --- ...dit-process-filter-cloud.component.spec.ts | 25 +++++++++++++++++++ .../edit-process-filter-cloud.component.ts | 13 ++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts index 92893f28b9..ccb5372b6b 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts @@ -30,6 +30,8 @@ import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model'; import { ProcessFilterCloudService } from '../services/process-filter-cloud.service'; import { AppsProcessCloudService } from '../../../app/services/apps-process-cloud.service'; import { fakeApplicationInstance } from './../../../app/mock/app-model.mock'; +import moment from 'moment-es6'; +import { AbstractControl } from '@angular/forms'; describe('EditProcessFilterCloudComponent', () => { let component: EditProcessFilterCloudComponent; @@ -496,5 +498,28 @@ describe('EditProcessFilterCloudComponent', () => { expect(deleteButton.disabled).toEqual(false); }); })); + + it('should set the correct lastModifiedTo date', (done) => { + component.appName = 'fake'; + component.filterProperties = ['appName', 'processInstanceId', 'priority', 'lastModified']; + const taskFilterIDchange = new SimpleChange(undefined, 'mock-task-filter-id', true); + component.ngOnChanges({ 'id': taskFilterIDchange }); + fixture.detectChanges(); + + const lastModifiedToControl: AbstractControl = component.editProcessFilterForm.get('lastModifiedTo'); + lastModifiedToControl.setValue('Tue Apr 09 2019 00:00:00 GMT+0300 (Eastern European Summer Time)'); + const lastModifiedToFilter = moment(lastModifiedToControl.value); + lastModifiedToFilter.set({ + hour: 23, + minute: 59, + second: 59 + }); + + component.filterChange.subscribe((res) => { + expect(component.changedProcessFilter.lastModifiedTo.toISOString()).toEqual(lastModifiedToFilter.toISOString()); + done(); + }); + component.onFilterChange(); + }); }); }); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts index 3bfb964261..d13275505a 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts @@ -161,6 +161,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges { this.editProcessFilterForm.valueChanges .pipe(debounceTime(500), filter(() => this.isFormValid())) .subscribe((formValues: ProcessFilterCloudModel) => { + this.setLastModifiedToFilter(formValues); this.changedProcessFilter = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues)); this.formHasBeenChanged = !this.compareFilters(this.changedProcessFilter, this.processFilter); this.filterChange.emit(this.changedProcessFilter); @@ -404,6 +405,18 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges { } } + private setLastModifiedToFilter(formValues: ProcessFilterCloudModel) { + if (formValues.lastModifiedTo && Date.parse(formValues.lastModifiedTo.toString())) { + const lastModifiedToFilterValue = moment(formValues.lastModifiedTo); + lastModifiedToFilterValue.set({ + hour: 23, + minute: 59, + second: 59 + }); + formValues.lastModifiedTo = lastModifiedToFilterValue.toDate(); + } + } + createFilterActions(): ProcessFilterAction[] { return [ new ProcessFilterAction({ From 01e4cf2871c41e70465d10a78e12e7b03e06af97 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 18 Apr 2019 18:12:49 +0200 Subject: [PATCH 129/208] speed up search test (#4626) --- e2e/proxy.ts | 3 +- e2e/search/components/search-checkList.e2e.ts | 23 +++++--- .../components/search-date-range.e2e.ts | 13 ++-- .../components/search-number-range.e2e.ts | 30 ++++------ e2e/search/components/search-radio.e2e.ts | 59 +++++-------------- e2e/search/components/search-slider.e2e.ts | 39 ++++++------ .../components/search-sorting-picker.e2e.ts | 52 +++++++--------- e2e/search/components/search-text.e2e.ts | 12 ++-- e2e/search/search-component.e2e.ts | 10 +--- e2e/search/search-filters.e2e.ts | 40 +++++-------- e2e/search/search-multiselect.e2e.ts | 3 - 11 files changed, 109 insertions(+), 175 deletions(-) diff --git a/e2e/proxy.ts b/e2e/proxy.ts index 09d1864eb0..4cec020e5f 100644 --- a/e2e/proxy.ts +++ b/e2e/proxy.ts @@ -21,7 +21,8 @@ import { browser } from 'protractor'; export async function setConfigField(field: string, value: string) { - return browser.executeScript( + await browser.executeScript( "window.adf.setConfigField(`" + field + "`, `" + value + "`);" ); + } diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index 54f7181a63..ad822f26e3 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -19,6 +19,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; @@ -38,6 +39,7 @@ describe('Search Checklist Component', () => { const searchFiltersPage = new SearchFiltersPage(); const searchDialog = new SearchDialog(); const searchResults = new SearchResultsPage(); + const navigationBarPage = new NavigationBarPage(); const acsUser = new AcsUserModel(); const uploadActions = new UploadActions(); @@ -143,6 +145,8 @@ describe('Search Checklist Component', () => { }); it('[C277143] Should be able to click show more/less button with pageSize set as default', async () => { + navigationBarPage.clickContentServicesButton(); + for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { jsonFile.categories[1].component.settings.options.push({ 'name': 'Folder', @@ -173,11 +177,11 @@ describe('Search Checklist Component', () => { searchFiltersPage.checkListFiltersPage().checkShowMoreButtonIsDisplayed(); searchFiltersPage.checkListFiltersPage().checkShowLessButtonIsNotDisplayed(); - - browser.refresh(); }); it('[C277144] Should be able to click show more/less button with pageSize set with a custom value', async () => { + navigationBarPage.clickContentServicesButton(); + jsonFile.categories[1].component.settings.pageSize = 10; for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { @@ -196,6 +200,7 @@ describe('Search Checklist Component', () => { searchFiltersPage.checkListFiltersPage().checkShowMoreButtonIsNotDisplayed(); + navigationBarPage.clickContentServicesButton(); jsonFile.categories[1].component.settings.pageSize = 11; await setConfigField('search', JSON.stringify(jsonFile)); @@ -207,7 +212,7 @@ describe('Search Checklist Component', () => { searchFiltersPage.checkListFiltersPage().checkShowMoreButtonIsNotDisplayed(); - browser.refresh(); + navigationBarPage.clickContentServicesButton(); jsonFile.categories[1].component.settings.pageSize = 9; @@ -219,11 +224,11 @@ describe('Search Checklist Component', () => { expect(searchFiltersPage.checkListFiltersPage().getCheckListOptionsNumberOnPage()).toBe(9); searchFiltersPage.checkListFiltersPage().checkShowMoreButtonIsDisplayed(); - - browser.refresh(); }); it('[C277145] Should be able to click show more/less button with pageSize set to zero', async () => { + navigationBarPage.clickContentServicesButton(); + jsonFile.categories[1].component.settings.pageSize = 0; for (let numberOfOptions = 0; numberOfOptions < 8; numberOfOptions++) { @@ -250,7 +255,7 @@ describe('Search Checklist Component', () => { searchFiltersPage.checkListFiltersPage().checkShowMoreButtonIsNotDisplayed(); searchFiltersPage.checkListFiltersPage().checkShowLessButtonIsDisplayed(); - browser.refresh(); + navigationBarPage.clickContentServicesButton(); delete jsonFile.categories[1].component.settings.pageSize; @@ -290,6 +295,8 @@ describe('Search Checklist Component', () => { }); it('[C277018] Should be able to change the operator', async () => { + navigationBarPage.clickContentServicesButton(); + jsonFile.categories[1].component.settings.operator = 'AND'; await setConfigField('search', JSON.stringify(jsonFile)); @@ -307,11 +314,11 @@ describe('Search Checklist Component', () => { searchResults.checkContentIsNotDisplayed(nodeNames.folder); searchResults.checkContentIsNotDisplayed(nodeNames.document); - - browser.refresh(); }); it('[C277019] Should be able to add new properties with different types', async () => { + navigationBarPage.clickContentServicesButton(); + jsonFile.categories[1].component.settings.options.push({ 'name': filterType.custom, 'value': "TYPE:'cm:auditable'" diff --git a/e2e/search/components/search-date-range.e2e.ts b/e2e/search/components/search-date-range.e2e.ts index 0bcabdc1ef..a9d8da8cd8 100644 --- a/e2e/search/components/search-date-range.e2e.ts +++ b/e2e/search/components/search-date-range.e2e.ts @@ -21,7 +21,6 @@ import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { DatePickerPage } from '../../pages/adf/material/datePickerPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { SearchConfiguration } from '../search.config'; @@ -30,6 +29,7 @@ import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { browser } from 'protractor'; import { DateUtil } from '../../util/dateUtil'; +import { setConfigField } from '../../proxy'; describe('Search Date Range Filter', () => { @@ -40,7 +40,6 @@ describe('Search Date Range Filter', () => { const searchResults = new SearchResultsPage(); const datePicker = new DatePickerPage(); const navigationBar = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const dataTable = new DataTableComponentPage(); beforeAll(async (done) => { @@ -197,14 +196,12 @@ describe('Search Date Range Filter', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C277117] Should be able to change date format', () => { + it('[C277117] Should be able to change date format', async () => { + navigationBar.clickContentServicesButton(); + jsonFile.categories[4].component.settings.dateFormat = 'MM-DD-YY'; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().enterTextAndPressEnter('*'); searchFilters.checkCreatedRangeFilterIsDisplayed() diff --git a/e2e/search/components/search-number-range.e2e.ts b/e2e/search/components/search-number-range.e2e.ts index db621b8f69..7f785a8877 100644 --- a/e2e/search/components/search-number-range.e2e.ts +++ b/e2e/search/components/search-number-range.e2e.ts @@ -20,7 +20,6 @@ import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import TestConfig = require('../../test.config'); @@ -33,6 +32,7 @@ import { browser } from 'protractor'; import resources = require('../../util/resources'); import { SearchConfiguration } from '../search.config'; import { DateUtil } from '../../util/dateUtil'; +import { setConfigField } from '../../proxy'; describe('Search Number Range Filter', () => { @@ -42,7 +42,6 @@ describe('Search Number Range Filter', () => { const sizeRangeFilter = searchFilters.sizeRangeFilterPage(); const searchResults = new SearchResultsPage(); const navigationBar = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const dataTable = new DataTableComponentPage(); const acsUser = new AcsUserModel(); @@ -398,13 +397,12 @@ describe('Search Number Range Filter', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C276928] Should be able to change the field property for number range', () => { + it('[C276928] Should be able to change the field property for number range', async() => { + navigationBar.clickContentServicesButton(); + jsonFile.categories[3].component.settings.field = 'cm:created'; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -441,13 +439,12 @@ describe('Search Number Range Filter', () => { }); - it('[C277139] Should be able to set To field to be exclusive', () => { + it('[C277139] Should be able to set To field to be exclusive', async() => { + navigationBar.clickContentServicesButton(); + jsonFile.categories[3].component.settings.format = '[{FROM} TO {TO}>'; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -478,13 +475,12 @@ describe('Search Number Range Filter', () => { searchResults.checkContentIsDisplayed(file2BytesModel.name); }); - it('[C277140] Should be able to set From field to be exclusive', () => { + it('[C277140] Should be able to set From field to be exclusive', async() => { + navigationBar.clickContentServicesButton(); + jsonFile.categories[3].component.settings.format = '<{FROM} TO {TO}]'; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() diff --git a/e2e/search/components/search-radio.e2e.ts b/e2e/search/components/search-radio.e2e.ts index 871c33c19c..31a6f1dd72 100644 --- a/e2e/search/components/search-radio.e2e.ts +++ b/e2e/search/components/search-radio.e2e.ts @@ -18,7 +18,6 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; @@ -32,12 +31,12 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { browser } from 'protractor'; import { StringUtil } from '@alfresco/adf-testing'; +import { setConfigField } from '../../proxy'; describe('Search Radio Component', () => { const loginPage = new LoginPage(); const searchFiltersPage = new SearchFiltersPage(); - const configEditorPage = new ConfigEditorPage(); const navigationBarPage = new NavigationBarPage(); const searchDialog = new SearchDialog(); const searchResults = new SearchResultsPage(); @@ -141,8 +140,8 @@ describe('Search Radio Component', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C277147] Should be able to customise the pageSize value', () => { - navigationBarPage.clickConfigEditorButton(); + it('[C277147] Should be able to customise the pageSize value', async() => { + navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 10; @@ -153,42 +152,28 @@ describe('Search Radio Component', () => { }); } - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); expect(searchFiltersPage.typeFiltersPage().getRadioButtonsNumberOnPage()).toBe(10); - browser.refresh(); - - navigationBarPage.clickConfigEditorButton(); + navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 11; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); expect(searchFiltersPage.typeFiltersPage().getRadioButtonsNumberOnPage()).toBe(10); - browser.refresh(); - - navigationBarPage.clickConfigEditorButton(); - + navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 9; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -201,8 +186,8 @@ describe('Search Radio Component', () => { browser.refresh(); }); - it('[C277148] Should be able to click show more/less button', () => { - navigationBarPage.clickConfigEditorButton(); + it('[C277148] Should be able to click show more/less button', async() => { + navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 0; @@ -213,10 +198,7 @@ describe('Search Radio Component', () => { }); } - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -240,16 +222,10 @@ describe('Search Radio Component', () => { searchFiltersPage.typeFiltersPage().checkShowMoreButtonIsDisplayed(); searchFiltersPage.typeFiltersPage().checkShowLessButtonIsNotDisplayed(); - browser.refresh(); - - navigationBarPage.clickConfigEditorButton(); - + navigationBarPage.clickContentServicesButton(); delete jsonFile.categories[5].component.settings.pageSize; - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -291,18 +267,15 @@ describe('Search Radio Component', () => { done(); }); - it('[C277033] Should be able to add a new option', () => { - navigationBarPage.clickConfigEditorButton(); + it('[C277033] Should be able to add a new option', async() => { + navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.options.push({ 'name': filterType.custom, 'value': "TYPE:'cm:content'" }); - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); diff --git a/e2e/search/components/search-slider.e2e.ts b/e2e/search/components/search-slider.e2e.ts index 8a992351fc..eec37cc475 100644 --- a/e2e/search/components/search-slider.e2e.ts +++ b/e2e/search/components/search-slider.e2e.ts @@ -20,7 +20,6 @@ import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import TestConfig = require('../../test.config'); @@ -32,6 +31,7 @@ import { FileModel } from '../../models/ACS/fileModel'; import { browser } from 'protractor'; import resources = require('../../util/resources'); import { SearchConfiguration } from '../search.config'; +import { setConfigField } from '../../proxy'; describe('Search Number Range Filter', () => { @@ -41,7 +41,6 @@ describe('Search Number Range Filter', () => { const sizeSliderFilter = searchFilters.sizeSliderFilterPage(); const searchResults = new SearchResultsPage(); const navigationBar = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const dataTable = new DataTableComponentPage(); const acsUser = new AcsUserModel(); @@ -164,13 +163,12 @@ describe('Search Number Range Filter', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C276983] Should be able to disable thumb label in Search Size Slider', () => { + it('[C276983] Should be able to disable thumb label in Search Size Slider', async() => { + navigationBar.clickContentServicesButton(); + jsonFile.categories[2].component.settings.thumbLabel = false; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -183,14 +181,13 @@ describe('Search Number Range Filter', () => { sizeSliderFilter.checkSliderWithThumbLabelIsNotDisplayed(); }); - it('[C276985] Should be able to set min value for Search Size Slider', () => { + it('[C276985] Should be able to set min value for Search Size Slider', async() => { + navigationBar.clickContentServicesButton(); + const minSize = 3; jsonFile.categories[2].component.settings.min = minSize; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -205,14 +202,13 @@ describe('Search Number Range Filter', () => { expect(sizeSliderFilter.getMinValue()).toEqual(`${minSize}`); }); - it('[C276986] Should be able to set max value for Search Size Slider', () => { + it('[C276986] Should be able to set max value for Search Size Slider', async() => { + navigationBar.clickContentServicesButton(); + const maxSize = 50; jsonFile.categories[2].component.settings.max = maxSize; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -227,14 +223,13 @@ describe('Search Number Range Filter', () => { expect(sizeSliderFilter.getMaxValue()).toEqual(`${maxSize}`); }); - it('[C276987] Should be able to set steps for Search Size Slider', () => { + it('[C276987] Should be able to set steps for Search Size Slider', async() => { + navigationBar.clickContentServicesButton(); + const step = 10; jsonFile.categories[2].component.settings.step = step; - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() diff --git a/e2e/search/components/search-sorting-picker.e2e.ts b/e2e/search/components/search-sorting-picker.e2e.ts index 0daf3601f9..3306b0b419 100644 --- a/e2e/search/components/search-sorting-picker.e2e.ts +++ b/e2e/search/components/search-sorting-picker.e2e.ts @@ -19,7 +19,6 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { NodeActions } from '../../actions/ACS/node.actions'; @@ -33,6 +32,7 @@ import { browser } from 'protractor'; import resources = require('../../util/resources'); import { SearchConfiguration } from '../search.config'; import { SearchSortingPickerPage } from '../../pages/adf/content-services/search/components/search-sortingPicker.page'; +import { setConfigField } from '../../proxy'; describe('Search Sorting Picker', () => { @@ -41,7 +41,6 @@ describe('Search Sorting Picker', () => { const searchFilters = new SearchFiltersPage(); const searchResults = new SearchResultsPage(); const navigationBar = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const searchSortingPicker = new SearchSortingPickerPage(); const contentServices = new ContentServicesPage(); const nodeActions = new NodeActions(); @@ -112,12 +111,10 @@ describe('Search Sorting Picker', () => { searchSortingPicker.checkOrderArrowIsDisplayed(); }); - it('[C277271] Should be able to add a custom search sorter in the "sort by" option', () => { + it('[C277271] Should be able to add a custom search sorter in the "sort by" option', async() => { + navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); jsonFile.sorting.options.push({ 'key': 'Modifier', 'label': 'Modifier', @@ -125,8 +122,7 @@ describe('Search Sorting Picker', () => { 'field': 'cm:modifier', 'ascending': true }); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -138,15 +134,12 @@ describe('Search Sorting Picker', () => { .checkOptionIsDisplayed('Modifier'); }); - it('[C277272] Should be able to exclude a standard search sorter from the sorting option', () => { + it('[C277272] Should be able to exclude a standard search sorter from the sorting option', async() => { + navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); const removedOption = jsonFile.sorting.options.splice(0, 1); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -158,12 +151,11 @@ describe('Search Sorting Picker', () => { .checkOptionIsNotDisplayed(removedOption[0].label); }); - it('[C277273] Should be able to set a default order for a search sorting option', () => { + it('[C277273] Should be able to set a default order for a search sorting option', async() => { + navigationBar.clickContentServicesButton(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); jsonFile.sorting.options[0].ascending = false; jsonFile.sorting.defaults[0] = { 'key': 'Size', @@ -172,8 +164,8 @@ describe('Search Sorting Picker', () => { 'field': 'content.size', 'ascending': true }; - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -226,12 +218,11 @@ describe('Search Sorting Picker', () => { }); }); - it('[C277288] Should be able to sort the search results by "Modified Date" ASC', () => { + it('[C277288] Should be able to sort the search results by "Modified Date" ASC', async() => { + navigationBar.clickContentServicesButton(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); jsonFile.sorting.options.push({ 'key': 'Modified Date', 'label': 'Modified Date', @@ -239,8 +230,7 @@ describe('Search Sorting Picker', () => { 'field': 'cm:modified', 'ascending': true }); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -262,12 +252,11 @@ describe('Search Sorting Picker', () => { }); }); - it('[C277301] Should be able to change default sorting option for the search results', () => { + it('[C277301] Should be able to change default sorting option for the search results', async() => { + navigationBar.clickContentServicesButton(); + const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); jsonFile.sorting.options.push({ 'key': 'createdByUser', 'label': 'Author', @@ -276,8 +265,7 @@ describe('Search Sorting Picker', () => { 'ascending': true }); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() diff --git a/e2e/search/components/search-text.e2e.ts b/e2e/search/components/search-text.e2e.ts index 4be3776a00..1179dd3bd4 100644 --- a/e2e/search/components/search-text.e2e.ts +++ b/e2e/search/components/search-text.e2e.ts @@ -28,14 +28,13 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; -import { ConfigEditorPage } from '../../pages/adf/configEditorPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { SearchConfiguration } from '../search.config'; +import { setConfigField } from '../../proxy'; describe('Search component - Text widget', () => { - const configEditorPage = new ConfigEditorPage(); const navigationBarPage = new NavigationBarPage(); const searchFiltersPage = new SearchFiltersPage(); @@ -92,7 +91,7 @@ describe('Search component - Text widget', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C289330] Should be able to change the Field setting', () => { + it('[C289330] Should be able to change the Field setting', async() => { browser.get(TestConfig.adf.url + '/search;q=*'); searchResultPage.tableIsLoaded(); @@ -109,11 +108,8 @@ describe('Search component - Text widget', () => { jsonFile.categories[0].component.settings.field = 'cm:description'; - navigationBarPage.clickConfigEditorButton(); - configEditorPage.clickSearchConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditorPage.clickSaveButton(); + navigationBarPage.clickContentServicesButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().enterTextAndPressEnter('*'); searchResultPage.tableIsLoaded(); diff --git a/e2e/search/search-component.e2e.ts b/e2e/search/search-component.e2e.ts index dfd514809e..1f0fed29c8 100644 --- a/e2e/search/search-component.e2e.ts +++ b/e2e/search/search-component.e2e.ts @@ -34,8 +34,8 @@ import { StringUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { SearchConfiguration } from './search.config'; +import { setConfigField } from '../proxy'; describe('Search component - Search Bar', () => { @@ -305,17 +305,13 @@ describe('Search component - Search Bar', () => { describe('Highlight', () => { const navigationBar = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const searchConfiguration = new SearchConfiguration().getConfiguration(); beforeAll(async () => { + navigationBar.clickContentServicesButton(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(searchConfiguration)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(searchConfiguration)); searchDialog .checkSearchIconIsVisible() diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index 2a62c3291a..6b64b48d32 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -17,12 +17,11 @@ import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { SearchFiltersPage } from '../pages/adf/searchFiltersPage'; -import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { SearchResultsPage } from '../pages/adf/searchResultsPage'; import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FileModel } from '../models/ACS/fileModel'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import TestConfig = require('../test.config'); import { StringUtil, DocumentListPage, PaginationPage, LoginPage } from '@alfresco/adf-testing'; @@ -32,6 +31,7 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; import { browser } from 'protractor'; import { SearchConfiguration } from './search.config'; +import { setConfigField } from '../proxy'; describe('Search Filters', () => { @@ -41,9 +41,8 @@ describe('Search Filters', () => { const uploadActions = new UploadActions(); const paginationPage = new PaginationPage(); const contentList = new DocumentListPage(); - const navigationBar = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const searchResults = new SearchResultsPage(); + const navigationBarPage = new NavigationBarPage(); const acsUser = new AcsUserModel(); @@ -173,11 +172,9 @@ describe('Search Filters', () => { searchFiltersPage.fileTypeCheckListFiltersPage().clickCheckListOption('PNG Image'); const bucketNumberForFilter = searchFiltersPage.fileTypeCheckListFiltersPage().getBucketNumberOfFilterType(filter.type); - const resultFileNames = contentList.getAllRowsColumnValues('Display name'); expect(bucketNumberForFilter).not.toEqual('0'); - expect(paginationPage.getTotalNumberOfFiles()).toEqual(bucketNumberForFilter); resultFileNames.then((fileNames) => { @@ -187,13 +184,11 @@ describe('Search Filters', () => { }); }); - it('[C291802] Should be able to filter facet fields with "Contains"', () => { - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); + it('[C291802] Should be able to filter facet fields with "Contains"', async() => { + navigationBarPage.clickContentServicesButton(); + jsonFile['filterWithContains'] = true; - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon() .enterTextAndPressEnter('*'); @@ -213,15 +208,10 @@ describe('Search Filters', () => { .checkSizeFacetQueryGroupIsDisplayed(); }); - it('[C291981] Should group search facets under the default label, by default', () => { - browser.refresh(); + it('[C291981] Should group search facets under the default label, by default', async() => { + navigationBarPage.clickContentServicesButton(); - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); - jsonFile['filterWithContains'] = true; - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon() .enterTextAndPressEnter('*'); @@ -270,14 +260,12 @@ describe('Search Filters', () => { }); - it('[C299124] Should be able to parse escaped empty spaced labels inside facetFields', () => { - navigationBar.clickConfigEditorButton(); - configEditor.clickSearchConfiguration(); - configEditor.clickClearButton(); + it('[C299124] Should be able to parse escaped empty spaced labels inside facetFields', async() => { + navigationBarPage.clickContentServicesButton(); + jsonFile.facetFields.fields[0].label = 'My File Types'; jsonFile.facetFields.fields[1].label = 'My File Sizes'; - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)); - configEditor.clickSaveButton(); + await setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon() .enterTextAndPressEnter('*'); diff --git a/e2e/search/search-multiselect.e2e.ts b/e2e/search/search-multiselect.e2e.ts index 29bbc24abe..f895a70f64 100644 --- a/e2e/search/search-multiselect.e2e.ts +++ b/e2e/search/search-multiselect.e2e.ts @@ -74,11 +74,8 @@ describe('Search Component - Multi-Select Facet', () => { }); jpgFile = await uploadActions.uploadFile(this.alfrescoJsApi, jpgFileInfo.location, jpgFileInfo.name, '-my-'); - jpgFileSite = await uploadActions.uploadFile(this.alfrescoJsApi, jpgFileInfo.location, jpgFileInfo.name, site.entry.guid); - txtFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, '-my-'); - txtFileSite = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, site.entry.guid); await browser.driver.sleep(15000); From 97ad54a4f8c7418acafe6c4d4c0f9b2bad6cfb25 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 19 Apr 2019 19:53:45 +0200 Subject: [PATCH 130/208] [no-issue] fix test plus fix update script (#4629) * fix test plus * fix test lint * increase timeout * increase timeout --- .travis.yml | 2 +- .../permissions/site-permissions.e2e.ts | 2 +- .../version/version-actions.e2e.ts | 7 ++- .../task-header-cloud.e2e.ts | 2 +- e2e/search/search-multiselect.e2e.ts | 53 +++++++++---------- e2e/search/search-page-component.e2e.ts | 17 +----- scripts/update-project.sh | 2 +- 7 files changed, 35 insertions(+), 50 deletions(-) diff --git a/.travis.yml b/.travis.yml index 05bb0fd9bd..5f6faa47bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -131,7 +131,7 @@ jobs: if: tag =~ .*beta.* script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n Activiti/activiti-modeling-app' - stage: Update children projects dependency # Test alfresco-admin-app - name: Update alfresco modeler activiti app + name: Update alfresco admin app if: tag =~ .*beta.* script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Alfresco/alfresco-admin-app' - stage: e2e Test # Test core diff --git a/e2e/content-services/permissions/site-permissions.e2e.ts b/e2e/content-services/permissions/site-permissions.e2e.ts index 62ee1d85b1..1215ac8e74 100644 --- a/e2e/content-services/permissions/site-permissions.e2e.ts +++ b/e2e/content-services/permissions/site-permissions.e2e.ts @@ -180,7 +180,7 @@ describe('Permissions Component', function () { permissionsPage.checkAddPermissionDialogIsDisplayed(); permissionsPage.checkSearchUserInputIsDisplayed(); - browser.sleep(7000); + browser.sleep(10000); permissionsPage.searchUserOrGroup(consumerUser.getId()); permissionsPage.clickUserOrGroup(consumerUser.getFirstName()); diff --git a/e2e/content-services/version/version-actions.e2e.ts b/e2e/content-services/version/version-actions.e2e.ts index 63bc6b18fe..bb073232df 100644 --- a/e2e/content-services/version/version-actions.e2e.ts +++ b/e2e/content-services/version/version-actions.e2e.ts @@ -56,6 +56,11 @@ describe('Version component actions', () => { 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location }); + const bigFileToCancel = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.LARGE_FILE.file_name, + 'location': resources.Files.ADF_DOCUMENTS.LARGE_FILE.file_location + }); + beforeAll(async (done) => { const uploadActions = new UploadActions(); @@ -156,7 +161,7 @@ describe('Version component actions', () => { browser.executeScript(' setTimeout(() => {document.querySelector(\'mat-icon[class*="adf-file-uploading-row__action"]\').click();}, 1000)'); versionManagePage.showNewVersionButton.click(); - versionManagePage.uploadNewVersionFile(fileModelVersionTwo.location); + versionManagePage.uploadNewVersionFile(bigFileToCancel.location); versionManagePage.closeVersionDialog(); await expect(new UploadDialog().getTitleText()).toEqual('Upload canceled'); diff --git a/e2e/process-services-cloud/task-header-cloud.e2e.ts b/e2e/process-services-cloud/task-header-cloud.e2e.ts index 3f80507399..f007a6166e 100644 --- a/e2e/process-services-cloud/task-header-cloud.e2e.ts +++ b/e2e/process-services-cloud/task-header-cloud.e2e.ts @@ -145,6 +145,6 @@ describe('Task Header cloud component', () => { tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(basicCreatedTaskName); tasksCloudDemoPage.taskListCloudComponent().selectRow(basicCreatedTaskName); - expect(taskDetailsCloudDemoPage.getReleaseButtonText()).toBe('Release'); + expect(taskDetailsCloudDemoPage.getReleaseButtonText()).toBe('UNCLAIM'); }); }); diff --git a/e2e/search/search-multiselect.e2e.ts b/e2e/search/search-multiselect.e2e.ts index f895a70f64..1aaafa32d1 100644 --- a/e2e/search/search-multiselect.e2e.ts +++ b/e2e/search/search-multiselect.e2e.ts @@ -78,18 +78,7 @@ describe('Search Component - Multi-Select Facet', () => { txtFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, '-my-'); txtFileSite = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, site.entry.guid); - await browser.driver.sleep(15000); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - - searchDialog.checkSearchIconIsVisible(); - searchDialog.clickOnSearchIcon(); - searchDialog.enterTextAndPressEnter(`${randomName}`); - - userOption = `${acsUser.firstName} ${acsUser.lastName}`; - - searchFiltersPage.checkSearchFiltersIsDisplayed(); - searchFiltersPage.creatorCheckListFiltersPage().filterBy(userOption); + await browser.driver.sleep(20000); done(); }); @@ -108,6 +97,16 @@ describe('Search Component - Multi-Select Facet', () => { }); it('[C280054] Should be able to select multiple items from a search facet filter', () => { + loginPage.loginToContentServicesUsingUserModel(acsUser); + + searchDialog.checkSearchIconIsVisible(); + searchDialog.clickOnSearchIcon(); + searchDialog.enterTextAndPressEnter(`${randomName}`); + + userOption = `${acsUser.firstName} ${acsUser.lastName}`; + + searchFiltersPage.checkSearchFiltersIsDisplayed(); + searchFiltersPage.creatorCheckListFiltersPage().filterBy(userOption); searchFiltersPage.fileTypeCheckListFiltersPage().filterBy('Plain Text'); expect(searchResultsPage.numberOfResultsDisplayed()).toBe(2); @@ -163,23 +162,20 @@ describe('Search Component - Multi-Select Facet', () => { jpgFile = await uploadActions.uploadFile(this.alfrescoJsApi, jpgFileInfo.location, jpgFileInfo.name, site.entry.guid); - await browser.driver.sleep(15000); + await browser.driver.sleep(20000); + done(); + }); + + it('[C280056] Should be able to select multiple items from multiple search facet filters', () => { loginPage.loginToContentServicesUsingUserModel(userUploadingImg); searchDialog.checkSearchIconIsVisible(); searchDialog.clickOnSearchIcon(); searchDialog.enterTextAndPressEnter(`*${randomName}*`); - done(); - }); - - it('[C280056] Should be able to select multiple items from multiple search facet filters', () => { - searchFiltersPage.checkSearchFiltersIsDisplayed(); - searchFiltersPage.creatorCheckListFiltersPage().filterBy(`${userUploadingTxt.firstName} ${userUploadingTxt.lastName}`); - searchFiltersPage.creatorCheckListFiltersPage().filterBy(`${userUploadingImg.firstName} ${userUploadingImg.lastName}`); searchResultsPage.checkContentIsDisplayed(txtFile.entry.name); @@ -217,15 +213,7 @@ describe('Search Component - Multi-Select Facet', () => { }); txtFile = await uploadActions.uploadFile(this.alfrescoJsApi, txtFileInfo.location, txtFileInfo.name, '-my-'); - await browser.driver.sleep(15000); - - loginPage.loginToContentServicesUsingUserModel(acsUser); - - searchDialog.checkSearchIconIsVisible(); - searchDialog.clickOnSearchIcon(); - searchDialog.enterTextAndPressEnter(`*${randomName}*`); - - searchFiltersPage.checkSearchFiltersIsDisplayed(); + await browser.driver.sleep(20000); done(); }); @@ -237,6 +225,13 @@ describe('Search Component - Multi-Select Facet', () => { }); it('[C280058] Should update filter facets items number when another filter facet item is selected', () => { + loginPage.loginToContentServicesUsingUserModel(acsUser); + + searchDialog.checkSearchIconIsVisible(); + searchDialog.clickOnSearchIcon(); + searchDialog.enterTextAndPressEnter(`*${randomName}*`); + + searchFiltersPage.checkSearchFiltersIsDisplayed(); searchFiltersPage.fileTypeCheckListFiltersPage().filterBy('Plain Text'); searchFiltersPage.creatorCheckListFiltersPage().filterBy(`${acsUser.firstName} ${acsUser.lastName}`); diff --git a/e2e/search/search-page-component.e2e.ts b/e2e/search/search-page-component.e2e.ts index 7b5114ab45..9ae2bccb50 100644 --- a/e2e/search/search-page-component.e2e.ts +++ b/e2e/search/search-page-component.e2e.ts @@ -22,7 +22,6 @@ import { LoginPage } from '@alfresco/adf-testing'; import { SearchDialog } from '../pages/adf/dialog/searchDialog'; import { ContentServicesPage } from '../pages/adf/contentServicesPage'; import { SearchResultsPage } from '../pages/adf/searchResultsPage'; -import { FilePreviewPage } from '../pages/adf/filePreviewPage'; import { AcsUserModel } from '../models/ACS/acsUserModel'; import { FolderModel } from '../models/ACS/folderModel'; @@ -54,7 +53,6 @@ describe('Search component - Search Page', () => { const contentServicesPage = new ContentServicesPage(); const searchDialog = new SearchDialog(); const searchResultPage = new SearchResultsPage(); - const filePreviewPage = new FilePreviewPage(); const acsUser = new AcsUserModel(); const emptyFolderModel = new FolderModel({ 'name': 'search' + StringUtil.generateRandomString() }); @@ -98,7 +96,7 @@ describe('Search component - Search Page', () => { await uploadActions.createEmptyFiles(this.alfrescoJsApi, adminFileNames, newFolderModelUploaded.entry.id); - browser.driver.sleep(10000); + browser.driver.sleep(15000); loginPage.loginToContentServicesUsingUserModel(acsUser); @@ -112,19 +110,6 @@ describe('Search component - Search Page', () => { searchResultPage.checkNoResultMessageIsDisplayed(); }); - it('[C260265] Should display file previewer when opening a file from search results', () => { - searchDialog - .clickOnSearchIcon() - .enterTextAndPressEnter(firstFileModel.name); - - searchResultPage.checkContentIsDisplayed(firstFileModel.name); - searchResultPage.navigateToFolder(firstFileModel.name); - - browser.driver.sleep(200); - - filePreviewPage.closePreviewWithButton(); - }); - it('[C272810] Should display only files corresponding to search', () => { searchDialog .clickOnSearchIcon() diff --git a/scripts/update-project.sh b/scripts/update-project.sh index 9ed0490cd4..ed3ff9af09 100755 --- a/scripts/update-project.sh +++ b/scripts/update-project.sh @@ -39,7 +39,7 @@ done rm -rf $TEMP_GENERATOR_DIR; -git clone https://$TOKEN@github.com/Alfresco/$NAME_REPO.git $TEMP_GENERATOR_DIR +git clone https://$TOKEN@github.com/$NAME_REPO.git $TEMP_GENERATOR_DIR cd $TEMP_GENERATOR_DIR git checkout development From e85b57876e0a6a25f4ccd1f6bdfe74cbbf4a193b Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Sun, 21 Apr 2019 23:42:59 +0100 Subject: [PATCH 131/208] Added a new LocalStorageUtil and using the setConfigMethod to set the local storage variables (#4575) * added a new LocalStorageUtil and using the setConfigMethod to set the localstorage variables, instead of using hte settings ui page. * linting fix * fixing import paths * update new path LocalStorageUtil * fix problems after rebase * fix async loadin and clear * local storage fix * fix lint * fix cs tests * fix tag navigation and rename file appNavigation to processTabNavigation * fix lint * fix process test * fix lint Signed-off-by: Eugenio Romano <eugenio.romano@alfresco.com> * fix start process cloud * inc timeout --- .../document-list-pagination.e2e.ts | 42 ++++------ e2e/content-services/tag-component.e2e.ts | 10 +-- .../card-view/aspect-oriented-config.e2e.ts | 19 +++-- .../card-view/metadata-permissions.e2e.ts | 14 ++-- .../card-view/metadata-smoke-tests.e2e.ts | 5 +- e2e/insights/analytics-component.e2e.ts | 6 +- e2e/pages/adf/navigationBarPage.ts | 6 ++ ...BarPage.ts => processServiceTabBarPage.ts} | 13 +--- .../process-services/processServicesPage.ts | 6 +- .../process-custom-filters.e2e.ts | 53 ++++++------- .../processList-cloud-component.e2e.ts | 12 +-- .../start-process-cloud.e2e.ts | 1 + .../task-list-properties.e2e.ts | 78 ++++++++----------- .../custom-process-filters.e2e.ts | 16 ++-- .../dynamic-table-date-picker.e2e.ts | 8 +- .../empty-process-list-component.e2e.ts | 2 +- .../form-people-widget.e2e.ts | 4 +- .../process-filters-component.e2e.ts | 8 +- .../process-instance-details.e2e.ts | 6 +- .../start-process-component.e2e.ts | 48 ++++++------ .../start-task-custom-app.e2e.ts | 12 +-- .../start-task-task-app.e2e.ts | 12 +-- .../task-filters-component.e2e.ts | 16 ++-- e2e/search/components/search-checkList.e2e.ts | 19 +++-- .../components/search-date-range.e2e.ts | 5 +- .../components/search-number-range.e2e.ts | 15 ++-- e2e/search/components/search-radio.e2e.ts | 26 ++++--- e2e/search/components/search-slider.e2e.ts | 19 +++-- .../components/search-sorting-picker.e2e.ts | 23 +++--- e2e/search/components/search-text.e2e.ts | 9 +-- e2e/search/search-component.e2e.ts | 5 +- e2e/search/search-filters.e2e.ts | 15 ++-- lib/core/services/automation.service.ts | 18 ++++- .../content-node-selector-dialog.page.ts | 2 +- .../pages/document-list.page.ts | 2 +- .../identity/group-identity.service.ts | 2 +- lib/testing/src/lib/core/models/user.model.ts | 2 +- .../core/pages/data-table-component.page.ts | 2 +- lib/testing/src/lib/core/pages/error.page.ts | 2 +- .../lib/core/pages/form-controller.page.ts | 2 +- lib/testing/src/lib/core/pages/header.page.ts | 2 +- .../src/lib/core/pages/login-sso.page.ts | 2 +- lib/testing/src/lib/core/pages/login.page.ts | 45 ++++++----- .../src/lib/core/pages/pagination.page.ts | 2 +- .../src/lib/core/pages/settings.page.ts | 2 +- .../src/lib/core/pages/user-info.page.ts | 2 +- lib/testing/src/lib/core/public-api.ts | 5 +- .../core/{ => utils}/browser-visibility.ts | 0 .../src/lib/core/utils/local-storage.util.ts | 45 +++++++++++ .../lib/core/{ => utils}/protractor.util.ts | 0 .../testing/src/lib/core/utils/public-api.ts | 15 +--- .../src/lib/core/{ => utils}/string.util.ts | 0 .../src/lib/material/pages/tabs.page.ts | 2 +- .../app/app-list-cloud.page.ts | 2 +- .../dialog/edit-process-filter-dialog.page.ts | 2 +- .../dialog/edit-task-filter-dialog.page.ts | 2 +- ...dit-process-filter-cloud-component.page.ts | 2 +- .../edit-task-filter-cloud-component.page.ts | 2 +- .../pages/group-cloud-component.page.ts | 2 +- .../pages/people-cloud-component.page.ts | 2 +- .../process-filters-cloud-component.page.ts | 2 +- .../process-header-cloud-component.page.ts | 2 +- .../process-list-cloud-component.page.ts | 2 +- .../start-process-cloud-component.page.ts | 3 +- .../pages/start-tasks-cloud-component.page.ts | 2 +- .../task-filters-cloud-component.page.ts | 2 +- .../pages/task-header-cloud-component.page.ts | 2 +- .../pages/task-list-cloud-component.page.ts | 2 +- .../pages/form-fields.page.ts | 2 +- 69 files changed, 369 insertions(+), 351 deletions(-) rename e2e/pages/adf/process-services/{appNavigationBarPage.ts => processServiceTabBarPage.ts} (87%) rename lib/testing/src/lib/core/{ => utils}/browser-visibility.ts (100%) create mode 100644 lib/testing/src/lib/core/utils/local-storage.util.ts rename lib/testing/src/lib/core/{ => utils}/protractor.util.ts (100%) rename e2e/proxy.ts => lib/testing/src/lib/core/utils/public-api.ts (71%) rename lib/testing/src/lib/core/{ => utils}/string.util.ts (100%) diff --git a/e2e/content-services/document-list/document-list-pagination.e2e.ts b/e2e/content-services/document-list/document-list-pagination.e2e.ts index 078982330e..120e38ef43 100644 --- a/e2e/content-services/document-list/document-list-pagination.e2e.ts +++ b/e2e/content-services/document-list/document-list-pagination.e2e.ts @@ -18,7 +18,6 @@ import { LoginPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { PaginationPage } from '@alfresco/adf-testing'; -import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { AcsUserModel } from '../../models/ACS/acsUserModel'; import { FolderModel } from '../../models/ACS/folderModel'; @@ -28,6 +27,7 @@ import { Util } from '../../util/util'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; +import { browser } from 'protractor'; describe('Document List - Pagination', function () { const pagination = { @@ -51,17 +51,16 @@ describe('Document List - Pagination', function () { const loginPage = new LoginPage(); const contentServicesPage = new ContentServicesPage(); const paginationPage = new PaginationPage(); - const navigationBarPage = new NavigationBarPage(); const acsUser = new AcsUserModel(); - const newFolderModel = new FolderModel({'name': 'newFolder'}); + const newFolderModel = new FolderModel({ 'name': 'newFolder' }); let fileNames = []; const nrOfFiles = 20; let currentPage = 1; let secondSetOfFiles = []; const secondSetNumber = 25; - const folderTwoModel = new FolderModel({'name': 'folderTwo'}); - const folderThreeModel = new FolderModel({'name': 'folderThree'}); + const folderTwoModel = new FolderModel({ 'name': 'folderTwo' }); + const folderThreeModel = new FolderModel({ 'name': 'folderThree' }); beforeAll(async (done) => { const uploadActions = new UploadActions(); @@ -87,7 +86,11 @@ describe('Document List - Pagination', function () { await uploadActions.createEmptyFiles(this.alfrescoJsApi, secondSetOfFiles, folderThreeUploadedModel.entry.id); - loginPage.loginToContentServicesUsingUserModel(acsUser); + done(); + }); + + beforeEach(async (done) => { + await loginPage.loginToContentServicesUsingUserModel(acsUser); done(); }); @@ -124,14 +127,9 @@ describe('Document List - Pagination', function () { paginationPage.checkNextPageButtonIsDisabled(); paginationPage.checkPreviousPageButtonIsDisabled(); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - contentServicesPage.checkAcsContainer(); + browser.refresh(); contentServicesPage.waitForTableBody(); expect(paginationPage.getCurrentItemsPerPage()).toEqual(itemsPerPage.twenty); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); }); it('[C260069] Should be able to set Items per page to 5', function () { @@ -179,14 +177,10 @@ describe('Document List - Pagination', function () { expect(Util.arrayContainsArray(list, fileNames.slice(15, 20))).toEqual(true); }); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); + browser.refresh(); contentServicesPage.checkAcsContainer(); contentServicesPage.waitForTableBody(); expect(paginationPage.getCurrentItemsPerPage()).toEqual(itemsPerPage.five); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); }); it('[C260067] Should be able to set Items per page to 10', function () { @@ -215,15 +209,9 @@ describe('Document List - Pagination', function () { expect(Util.arrayContainsArray(list, fileNames.slice(10, 20))).toEqual(true); }); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - contentServicesPage.checkAcsContainer(); + browser.refresh(); contentServicesPage.waitForTableBody(); expect(paginationPage.getCurrentItemsPerPage()).toEqual(itemsPerPage.ten); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); - currentPage = 1; }); it('[C260065] Should be able to set Items per page to 15', function () { @@ -253,10 +241,8 @@ describe('Document List - Pagination', function () { expect(Util.arrayContainsArray(list, fileNames.slice(15, 20))).toEqual(true); }); - navigationBarPage.clickLogoutButton(); - loginPage.loginToContentServicesUsingUserModel(acsUser); - contentServicesPage.goToDocumentList(); - contentServicesPage.checkAcsContainer(); + browser.refresh(); + contentServicesPage.waitForTableBody(); expect(paginationPage.getCurrentItemsPerPage()).toEqual(itemsPerPage.fifteen); }); diff --git a/e2e/content-services/tag-component.e2e.ts b/e2e/content-services/tag-component.e2e.ts index ae5fc73875..59abca84b2 100644 --- a/e2e/content-services/tag-component.e2e.ts +++ b/e2e/content-services/tag-component.e2e.ts @@ -20,7 +20,7 @@ import { FileModel } from '../models/ACS/fileModel'; import { LoginPage } from '@alfresco/adf-testing'; import { TagPage } from '../pages/adf/tagPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import TestConfig = require('../test.config'); import resources = require('../util/resources'); @@ -35,7 +35,7 @@ describe('Tag component', () => { const loginPage = new LoginPage(); const tagPage = new TagPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const navigationBarPage = new NavigationBarPage(); const acsUser = new AcsUserModel(); const uploadActions = new UploadActions(); @@ -86,9 +86,7 @@ describe('Tag component', () => { await this.alfrescoJsApi.core.tagsApi.addTag(nodeId, tags); - loginPage.loginToContentServicesUsingUserModel(acsUser); - - appNavigationBarPage.clickTagButton(); + await loginPage.loginToContentServicesUsingUserModel(acsUser); done(); }); @@ -100,6 +98,8 @@ describe('Tag component', () => { }); it('[C260374] Should NOT be possible to add a new tag without Node ID', () => { + navigationBarPage.clickTagButton(); + expect(tagPage.getNodeId()).toEqual(''); expect(tagPage.getNewTagPlaceholder()).toEqual('New Tag'); expect(tagPage.addTagButtonIsEnabled()).toEqual(false); diff --git a/e2e/core/card-view/aspect-oriented-config.e2e.ts b/e2e/core/card-view/aspect-oriented-config.e2e.ts index 5dee4142f7..65b704a121 100644 --- a/e2e/core/card-view/aspect-oriented-config.e2e.ts +++ b/e2e/core/card-view/aspect-oriented-config.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; @@ -30,7 +30,6 @@ import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { check } from '../../util/material'; -import { setConfigField } from '../../proxy'; describe('Aspect oriented config', () => { @@ -96,7 +95,7 @@ describe('Aspect oriented config', () => { it('[C261117] Should be possible restrict the display properties of one an aspect', async () => { - await setConfigField('content-metadata', JSON.stringify({ + await LocalStorageUtil.setConfigField('content-metadata', JSON.stringify({ presets: { default: [ { @@ -137,7 +136,7 @@ describe('Aspect oriented config', () => { it('[C260185] Should ignore not existing aspect when present in the configuration', async () => { - await setConfigField('content-metadata', JSON.stringify({ + await LocalStorageUtil.setConfigField('content-metadata', JSON.stringify({ presets: { default: { 'exif:exif': '*', @@ -164,7 +163,7 @@ describe('Aspect oriented config', () => { it('[C260183] Should show all the aspect if the content-metadata configuration is NOT provided', async () => { - await setConfigField('content-metadata', '{}'); + await LocalStorageUtil.setConfigField('content-metadata', '{}'); navigationBarPage.clickContentServicesButton(); @@ -182,7 +181,7 @@ describe('Aspect oriented config', () => { it('[C260182] Should show all the aspects if the default configuration contains the star symbol', async () => { - await setConfigField('content-metadata', JSON.stringify({ + await LocalStorageUtil.setConfigField('content-metadata', JSON.stringify({ presets: { default: '*' } @@ -205,7 +204,7 @@ describe('Aspect oriented config', () => { it('[C268899] Should be possible use a Translation key as Title of a metadata group', async () => { - await setConfigField('content-metadata', '{' + + await LocalStorageUtil.setConfigField('content-metadata', '{' + ' "presets": {' + ' "default": [' + ' {' + @@ -250,7 +249,7 @@ describe('Aspect oriented config', () => { it('[C279968] Should be possible use a custom preset', async () => { - await setConfigField('content-metadata', '{' + + await LocalStorageUtil.setConfigField('content-metadata', '{' + ' "presets": {' + ' "custom-preset": {' + ' "exif:exif": "*",' + @@ -280,7 +279,7 @@ describe('Aspect oriented config', () => { it('[C299186] The aspect without properties is not displayed', async () => { - await setConfigField('content-metadata', '{' + + await LocalStorageUtil.setConfigField('content-metadata', '{' + ' "presets": { "' + modelOneName + ' ": { "' + modelOneName + ':' + emptyAspectName + ' ":"*"' + @@ -303,7 +302,7 @@ describe('Aspect oriented config', () => { it('[C299187] The aspect with empty properties is displayed when edit', async () => { - await setConfigField('content-metadata', '{' + + await LocalStorageUtil.setConfigField('content-metadata', '{' + ' "presets": { "' + defaultModel + ' ": { "' + defaultModel + ':' + defaultEmptyPropertiesAspect + ' ":"*"' + diff --git a/e2e/core/card-view/metadata-permissions.e2e.ts b/e2e/core/card-view/metadata-permissions.e2e.ts index 8c0197641e..1406432807 100644 --- a/e2e/core/card-view/metadata-permissions.e2e.ts +++ b/e2e/core/card-view/metadata-permissions.e2e.ts @@ -102,13 +102,13 @@ describe('permissions', () => { done(); }); - afterAll(async(done) => { + afterAll(async (done) => { await this.alfrescoJsApi.core.sitesApi.deleteSite(site.entry.id); done(); }); - it('[C274692] Should not be possible edit metadata properties when the user is a consumer user', () => { - loginPage.loginToContentServicesUsingUserModel(consumerUser); + it('[C274692] Should not be possible edit metadata properties when the user is a consumer user', async () => { + await loginPage.loginToContentServicesUsingUserModel(consumerUser); navigationBarPage.openContentServicesFolder(site.entry.guid); @@ -119,8 +119,8 @@ describe('permissions', () => { metadataViewPage.editIconIsNotDisplayed(); }); - it('[C279971] Should be possible edit metadata properties when the user is a collaborator user', () => { - loginPage.loginToContentServicesUsingUserModel(collaboratorUser); + it('[C279971] Should be possible edit metadata properties when the user is a collaborator user', async () => { + await loginPage.loginToContentServicesUsingUserModel(collaboratorUser); navigationBarPage.openContentServicesFolder(site.entry.guid); @@ -139,8 +139,8 @@ describe('permissions', () => { metadataViewPage.editIconIsDisplayed(); }); - it('[C279972] Should be possible edit metadata properties when the user is a contributor user', () => { - loginPage.loginToContentServicesUsingUserModel(collaboratorUser); + it('[C279972] Should be possible edit metadata properties when the user is a contributor user', async () => { + await loginPage.loginToContentServicesUsingUserModel(collaboratorUser); navigationBarPage.openContentServicesFolder(site.entry.guid); diff --git a/e2e/core/card-view/metadata-smoke-tests.e2e.ts b/e2e/core/card-view/metadata-smoke-tests.e2e.ts index c98c2972ad..52cd26c798 100644 --- a/e2e/core/card-view/metadata-smoke-tests.e2e.ts +++ b/e2e/core/card-view/metadata-smoke-tests.e2e.ts @@ -17,7 +17,7 @@ import { browser } from 'protractor'; -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; import { ViewerPage } from '../../pages/adf/viewerPage'; import { MetadataViewPage } from '../../pages/adf/metadataViewPage'; @@ -32,7 +32,6 @@ import dateFormat = require('dateformat'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; -import { setConfigField } from '../../proxy'; describe('Metadata component', () => { @@ -97,7 +96,7 @@ describe('Metadata component', () => { describe('Viewer Metadata', () => { beforeAll(async() => { - await setConfigField('content-metadata', JSON.stringify({ + await LocalStorageUtil.setConfigField('content-metadata', JSON.stringify({ presets: { default: { 'exif:exif': '*' diff --git a/e2e/insights/analytics-component.e2e.ts b/e2e/insights/analytics-component.e2e.ts index 3cd53312ea..003c363736 100644 --- a/e2e/insights/analytics-component.e2e.ts +++ b/e2e/insights/analytics-component.e2e.ts @@ -19,7 +19,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { AnalyticsPage } from '../pages/adf/process-services/analyticsPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import TestConfig = require('../test.config'); import { Tenant } from '../models/APS/tenant'; import { User } from '../models/APS/user'; @@ -30,7 +30,7 @@ describe('Analytics Smoke Test', () => { const loginPage = new LoginPage(); const navigationBarPage = new NavigationBarPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const analyticsPage = new AnalyticsPage(); const processServicesPage = new ProcessServicesPage(); let tenantId; @@ -65,7 +65,7 @@ describe('Analytics Smoke Test', () => { navigationBarPage.navigateToProcessServicesPage(); processServicesPage.checkApsContainer(); processServicesPage.goToApp('Task App'); - appNavigationBarPage.clickReportsButton(); + processServiceTabBarPage.clickReportsButton(); analyticsPage.checkNoReportMessage(); analyticsPage.getReport('Process definition heat map'); analyticsPage.changeReportTitle(reportTitle); diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index 076d41866c..31d72c2c0c 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -52,6 +52,12 @@ export class NavigationBarPage { settingsButton = element(by.css('a[data-automation-id="Settings"]')); peopleGroupCloudButton = element(by.css('button[data-automation-id="People/Group Cloud"]')); aboutButton = element(by.css('a[data-automation-id="About"]')); + tagButton = element.all(by.css('a[data-automation-id="Tag"]')); + + clickTagButton() { + BrowserVisibility.waitUntilElementIsVisible(this.tagButton); + this.tagButton.click(); + } navigateToDatatable() { BrowserVisibility.waitUntilElementIsVisible(this.dataTableButton); diff --git a/e2e/pages/adf/process-services/appNavigationBarPage.ts b/e2e/pages/adf/process-services/processServiceTabBarPage.ts similarity index 87% rename from e2e/pages/adf/process-services/appNavigationBarPage.ts rename to e2e/pages/adf/process-services/processServiceTabBarPage.ts index 24be431a9e..0e53921692 100644 --- a/e2e/pages/adf/process-services/appNavigationBarPage.ts +++ b/e2e/pages/adf/process-services/processServiceTabBarPage.ts @@ -18,10 +18,9 @@ import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by, browser } from 'protractor'; -export class AppNavigationBarPage { +export class ProcessServiceTabBarPage { tasksButton = element.all(by.cssContainingText('div[class*="mat-tab-label"] .mat-tab-labels div', 'Tasks')).first(); - tagButton = element.all(by.css('[data-automation-id="Tag"]')); processButton = element.all(by.cssContainingText('div[class*="mat-tab-label"] .mat-tab-labels div', 'Process')).first(); reportsButton = element.all(by.cssContainingText('div[class*="mat-tab-label"] .mat-tab-labels div', 'Reports')).first(); settingsButton = element.all(by.cssContainingText('div[class*="mat-tab-label"] .mat-tab-labels div', 'Settings')).first(); @@ -30,21 +29,17 @@ export class AppNavigationBarPage { clickTasksButton() { BrowserVisibility.waitUntilElementIsVisible(this.tasksButton); this.tasksButton.click(); - return browser.sleep(400); + return browser.sleep(600); } clickProcessButton() { this.processButton.click(); - return browser.sleep(400); - } - - clickTagButton() { - return this.tagButton.click(); + return browser.sleep(600); } clickSettingsButton() { this.settingsButton.click(); - return browser.sleep(400); + return browser.sleep(600); } clickReportsButton() { diff --git a/e2e/pages/adf/process-services/processServicesPage.ts b/e2e/pages/adf/process-services/processServicesPage.ts index f1a33944bb..7eb0d0e137 100644 --- a/e2e/pages/adf/process-services/processServicesPage.ts +++ b/e2e/pages/adf/process-services/processServicesPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { AppNavigationBarPage } from './appNavigationBarPage'; +import { ProcessServiceTabBarPage } from './processServiceTabBarPage'; import { element, by } from 'protractor'; import { BrowserVisibility } from '@alfresco/adf-testing'; @@ -35,13 +35,13 @@ export class ProcessServicesPage { const app = element(by.css('mat-card[title="' + applicationName + '"]')); BrowserVisibility.waitUntilElementIsVisible(app); app.click(); - return new AppNavigationBarPage(); + return new ProcessServiceTabBarPage(); } goToTaskApp() { BrowserVisibility.waitUntilElementIsVisible(this.taskApp); this.taskApp.click(); - return new AppNavigationBarPage(); + return new ProcessServiceTabBarPage(); } getAppIconType(applicationName) { diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index f8f47655e8..9dc7dda83a 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -17,13 +17,14 @@ import TestConfig = require('../test.config'); -import { TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, - LoginSSOPage, ApiService, SettingsPage } from '@alfresco/adf-testing'; +import { + TasksService, QueryService, ProcessDefinitionsService, ProcessInstancesService, + LoginSSOPage, ApiService, SettingsPage +} from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { AppListCloudPage } from '@alfresco/adf-testing'; -import { ConfigEditorPage } from '../pages/adf/configEditorPage'; +import { AppListCloudPage, LocalStorageUtil } from '@alfresco/adf-testing'; import resources = require('../util/resources'); import { browser, protractor } from 'protractor'; @@ -31,7 +32,6 @@ import { browser, protractor } from 'protractor'; describe('Process list cloud', () => { describe('Process List', () => { - const configEditorPage = new ConfigEditorPage(); const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); @@ -52,32 +52,27 @@ describe('Process list cloud', () => { loginSSOPage.clickOnSSOButton(); loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - navigationBarPage.clickConfigEditorButton(); - configEditorPage.clickEditProcessCloudConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(`{ - "filterProperties": [ - "appName", - "status", - "processInstanceId", - "order", - "sort", - "order" + await LocalStorageUtil.setConfigField('adf-edit-process-filter', JSON.stringify({ + 'filterProperties': [ + 'appName', + 'status', + 'processInstanceId', + 'order', + 'sort', + 'order' ], - "sortProperties": [ - "id", - "name", - "status", - "startDate" + 'sortProperties': [ + 'id', + 'name', + 'status', + 'startDate' ], - "actions": [ - "save", - "saveAs", - "delete" + 'actions': [ + 'save', + 'saveAs', + 'delete' ] - }`); - - configEditorPage.clickSaveButton(); + })); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); @@ -101,7 +96,7 @@ describe('Process list cloud', () => { done(); }); - beforeEach(async(done) => { + beforeEach(async (done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); appListCloudComponent.goToApp(candidateuserapp); diff --git a/e2e/process-services-cloud/processList-cloud-component.e2e.ts b/e2e/process-services-cloud/processList-cloud-component.e2e.ts index 79521a5c27..01abfe5c09 100644 --- a/e2e/process-services-cloud/processList-cloud-component.e2e.ts +++ b/e2e/process-services-cloud/processList-cloud-component.e2e.ts @@ -21,13 +21,13 @@ import { ProcessInstancesService, LoginSSOPage, ApiService, - SettingsPage + SettingsPage, + LocalStorageUtil } from '@alfresco/adf-testing'; import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { ProcessListCloudConfiguration } from './processListCloud.config'; import resources = require('../util/resources'); @@ -38,7 +38,6 @@ describe('Process list cloud', () => { const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); - const configEditor = new ConfigEditorPage(); const appListCloudComponent = new AppListCloudPage(); const processCloudDemoPage = new ProcessCloudDemoPage(); @@ -67,11 +66,8 @@ describe('Process list cloud', () => { beforeEach(async (done) => { const processListCloudConfiguration = new ProcessListCloudConfiguration(); jsonFile = processListCloudConfiguration.getConfiguration(); - done(); - navigationBarPage.clickConfigEditorButton(); - configEditor.clickProcessListCloudConfiguration(); - configEditor.clickClearButton(); - configEditor.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); + + await LocalStorageUtil.setConfigField('adf-cloud-process-list', JSON.stringify(jsonFile)); navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index b85c4ead48..35aa47f907 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -51,6 +51,7 @@ describe('Start Process', () => { afterEach((done) => { navigationBarPage.navigateToProcessServicesCloudPage(); + appListCloudComponent.checkApsContainer(); done(); }); diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index cb2b86ff25..c5663f6efc 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -20,22 +20,19 @@ import TestConfig = require('../test.config'); import { StringUtil, TasksService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService, - SettingsPage, AppListCloudPage } from '@alfresco/adf-testing'; + SettingsPage, AppListCloudPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; -import { ConfigEditorPage } from '../pages/adf/configEditorPage'; import { TaskListCloudConfiguration } from './taskListCloud.config'; import moment = require('moment'); import { DateUtil } from '../util/dateUtil'; -import { NotificationPage } from '../pages/adf/notificationPage'; import resources = require('../util/resources'); describe('Edit task filters and task list properties', () => { describe('Edit task filters and task list properties', () => { - const configEditorPage = new ConfigEditorPage(); const settingsPage = new SettingsPage(); const loginSSOPage = new LoginSSOPage(); const navigationBarPage = new NavigationBarPage(); @@ -46,7 +43,6 @@ describe('Edit task filters and task list properties', () => { let tasksService: TasksService; let processDefinitionService: ProcessDefinitionsService; let processInstancesService: ProcessInstancesService; - const notificationPage = new NotificationPage(); const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; const candidateUserApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; @@ -66,48 +62,36 @@ describe('Edit task filters and task list properties', () => { loginSSOPage.clickOnSSOButton(); loginSSOPage.loginSSOIdentityService(user, password); - navigationBarPage.clickConfigEditorButton(); - - configEditorPage.clickTaskListCloudConfiguration(); - configEditorPage.clickClearButton(); - configEditorPage.enterBigConfigurationText(JSON.stringify(jsonFile)).clickSaveButton(); - notificationPage.checkNotificationSnackBarIsDisplayedWithMessage('Save'); - notificationPage.checkNotificationSnackBarIsNotDisplayed(); - - configEditorPage.clickEditTaskConfiguration(); - configEditorPage.clickClearButton(); - - configEditorPage.enterBigConfigurationText(`{ - "filterProperties": [ - "appName", - "status", - "assignee", - "taskName", - "parentTaskId", - "priority", - "standAlone", - "owner", - "processDefinitionId", - "processInstanceId", - "lastModified", - "sort", - "order" - ], - "sortProperties": [ - "id", - "name", - "createdDate", - "priority", - "processDefinitionId" - ], - "actions": [ - "save", - "saveAs", - "delete" - ] - }`); - - configEditorPage.clickSaveButton(); + await LocalStorageUtil.setConfigField('adf-cloud-task-list', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('adf-edit-task-filter', JSON.stringify({ + 'filterProperties': [ + 'appName', + 'status', + 'assignee', + 'taskName', + 'parentTaskId', + 'priority', + 'standAlone', + 'owner', + 'processDefinitionId', + 'processInstanceId', + 'lastModified', + 'sort', + 'order' + ], + 'sortProperties': [ + 'id', + 'name', + 'createdDate', + 'priority', + 'processDefinitionId' + ], + 'actions': [ + 'save', + 'saveAs', + 'delete' + ] + })); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); diff --git a/e2e/process-services/custom-process-filters.e2e.ts b/e2e/process-services/custom-process-filters.e2e.ts index 8ed646eca8..ea5c4b5bc2 100644 --- a/e2e/process-services/custom-process-filters.e2e.ts +++ b/e2e/process-services/custom-process-filters.e2e.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { AppSettingsToggles } from '../pages/adf/process-services/dialog/appSettingsToggles'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; @@ -32,7 +32,7 @@ describe('New Process Filters', () => { const loginPage = new LoginPage(); const processFiltersPage = new ProcessFiltersPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const appSettingsToggles = new AppSettingsToggles(); const navigationBarPage = new NavigationBarPage(); @@ -128,9 +128,9 @@ describe('New Process Filters', () => { processFiltersPage.checkFilterIsDisplayed(processFilter.new_icon); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); appSettingsToggles.enableProcessFiltersIcon(); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.checkFilterIsDisplayed(processFilter.new_icon); expect(processFiltersPage.getFilterIcon(processFilter.new_icon)).toEqual('cloud'); @@ -189,9 +189,9 @@ describe('New Process Filters', () => { processFiltersPage.checkFilterIsDisplayed(processFilter.edit_icon); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); appSettingsToggles.enableProcessFiltersIcon(); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.checkFilterIsDisplayed(processFilter.edit_icon); expect(processFiltersPage.getFilterIcon(processFilter.edit_icon)).toEqual('cloud'); @@ -202,9 +202,9 @@ describe('New Process Filters', () => { navigationBarPage.navigateToProcessServicesPage().goToTaskApp().clickProcessButton(); processFiltersPage.checkFilterHasNoIcon(processFilter.all); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); appSettingsToggles.enableProcessFiltersIcon(); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.checkFilterIsDisplayed(processFilter.all); expect(processFiltersPage.getFilterIcon(processFilter.all)).toEqual('dashboard'); diff --git a/e2e/process-services/dynamic-table-date-picker.e2e.ts b/e2e/process-services/dynamic-table-date-picker.e2e.ts index c803c4c7d1..411eccf274 100644 --- a/e2e/process-services/dynamic-table-date-picker.e2e.ts +++ b/e2e/process-services/dynamic-table-date-picker.e2e.ts @@ -17,7 +17,7 @@ import { LoginPage } from '@alfresco/adf-testing'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { DynamicTableWidget } from '../pages/adf/process-services/widgets/dynamicTableWidget'; import { DropdownWidget } from '../pages/adf/process-services/widgets/dropdownWidget'; import { DatePickerPage } from '../pages/adf/material/datePickerPage'; @@ -34,7 +34,7 @@ describe('Dynamic Table', () => { const loginPage = new LoginPage(); const processFiltersPage = new ProcessFiltersPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const dynamicTable = new DynamicTableWidget(); const datePicker = new DatePickerPage(); const navigationBarPage = new NavigationBarPage(); @@ -99,7 +99,7 @@ describe('Dynamic Table', () => { beforeEach(() => { navigationBarPage.navigateToProcessServicesPage().goToTaskApp().clickProcessButton(); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); @@ -154,7 +154,7 @@ describe('Dynamic Table', () => { beforeEach(() => { navigationBarPage.navigateToProcessServicesPage().goToApp(app.title).clickProcessButton(); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); diff --git a/e2e/process-services/empty-process-list-component.e2e.ts b/e2e/process-services/empty-process-list-component.e2e.ts index 7bb62245e7..0d2f3b42ea 100644 --- a/e2e/process-services/empty-process-list-component.e2e.ts +++ b/e2e/process-services/empty-process-list-component.e2e.ts @@ -62,11 +62,11 @@ describe('Empty Process List Test', () => { await apps.importPublishDeployApp(this.alfrescoJsApi, appA.file_location); await apps.importPublishDeployApp(this.alfrescoJsApi, appB.file_location); + await loginPage.loginToProcessServicesUsingUserModel(user); done(); }); it('[C260494] Should add process to list when a process is created', () => { - loginPage.loginToProcessServicesUsingUserModel(user); navigationBarPage.navigateToProcessServicesPage(); processServicesPage.checkApsContainer(); processServicesPage.goToApp(appA.title).clickProcessButton(); diff --git a/e2e/process-services/form-people-widget.e2e.ts b/e2e/process-services/form-people-widget.e2e.ts index e06d925993..ee715ba1b9 100644 --- a/e2e/process-services/form-people-widget.e2e.ts +++ b/e2e/process-services/form-people-widget.e2e.ts @@ -21,7 +21,7 @@ import { Widget } from '../pages/adf/process-services/widgets/widget'; import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; import { TaskDetailsPage } from '../pages/adf/process-services/taskDetailsPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import TestConfig = require('../test.config'); @@ -44,7 +44,7 @@ describe('Form widgets - People', () => { const startProcess = new StartProcessPage(); const processDetailsPage = new ProcessDetailsPage(); const taskDetails = new TaskDetailsPage(); - const appNavigationBar = new AppNavigationBarPage(); + const appNavigationBar = new ProcessServiceTabBarPage(); beforeAll(async (done) => { const users = new UsersActions(); diff --git a/e2e/process-services/process-filters-component.e2e.ts b/e2e/process-services/process-filters-component.e2e.ts index 4df15b8ef0..78e4330dea 100644 --- a/e2e/process-services/process-filters-component.e2e.ts +++ b/e2e/process-services/process-filters-component.e2e.ts @@ -23,7 +23,7 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; import { ProcessListPage } from '../pages/adf/process-services/processListPage'; @@ -41,7 +41,7 @@ describe('Process Filters Test', () => { const processServicesPage = new ProcessServicesPage(); const startProcessPage = new StartProcessPage(); const processFiltersPage = new ProcessFiltersPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const processDetailsPage = new ProcessDetailsPage(); let appModel; @@ -83,7 +83,7 @@ describe('Process Filters Test', () => { navigationBarPage.navigateToProcessServicesPage(); processServicesPage.checkApsContainer(); processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processListPage.checkProcessListIsDisplayed(); }); @@ -100,7 +100,7 @@ describe('Process Filters Test', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); diff --git a/e2e/process-services/process-instance-details.e2e.ts b/e2e/process-services/process-instance-details.e2e.ts index e2ed34b074..708bef6fe4 100644 --- a/e2e/process-services/process-instance-details.e2e.ts +++ b/e2e/process-services/process-instance-details.e2e.ts @@ -24,7 +24,7 @@ import resources = require('../util/resources'); import { AppsActions } from '../actions/APS/apps.actions'; import { LoginPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { ProcessListPage } from '../pages/adf/process-services/processListPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; import dateFormat = require('dateformat'); @@ -34,7 +34,7 @@ describe('Process Instance Details', () => { const loginPage = new LoginPage(); const navigationBarPage = new NavigationBarPage(); const processServicesPage = new ProcessServicesPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const processListPage = new ProcessListPage(); const processDetailsPage = new ProcessDetailsPage(); @@ -65,7 +65,7 @@ describe('Process Instance Details', () => { navigationBarPage.navigateToProcessServicesPage(); processServicesPage.checkApsContainer(); processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processListPage.checkProcessListIsDisplayed(); process = await this.alfrescoJsApi.activiti.processApi.getProcessInstance(processModel.id); diff --git a/e2e/process-services/start-process-component.e2e.ts b/e2e/process-services/start-process-component.e2e.ts index f1e719297c..f330dd99af 100644 --- a/e2e/process-services/start-process-component.e2e.ts +++ b/e2e/process-services/start-process-component.e2e.ts @@ -24,7 +24,7 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { ProcessServicesPage } from '../pages/adf/process-services/processServicesPage'; import { StartProcessPage } from '../pages/adf/process-services/startProcessPage'; import { ProcessFiltersPage } from '../pages/adf/process-services/processFiltersPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { ProcessDetailsPage } from '../pages/adf/process-services/processDetailsPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; import { AppsActions } from '../actions/APS/apps.actions'; @@ -47,7 +47,7 @@ describe('Start Process Component', () => { const processServicesPage = new ProcessServicesPage(); const startProcessPage = new StartProcessPage(); const processFiltersPage = new ProcessFiltersPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const processDetailsPage = new ProcessDetailsPage(); const attachmentListPage = new AttachmentListPage(); const apps = new AppsActions(); @@ -120,7 +120,7 @@ describe('Start Process Component', () => { it('[C260458] Should NOT be able to start a process without process model', () => { processServicesPage.goToApp('Task App'); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.checkNoProcessMessage(); @@ -137,7 +137,7 @@ describe('Start Process Component', () => { it('[C260441] Should display start process form and default name when creating a new process', () => { processServicesPage.goToApp('Task App'); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); expect(startProcessPage.getDefaultName()).toEqual('My Default Name'); @@ -145,7 +145,7 @@ describe('Start Process Component', () => { it('[C260445] Should require process definition and be possible to click cancel button', () => { processServicesPage.goToApp('Task App'); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName(''); @@ -158,7 +158,7 @@ describe('Start Process Component', () => { it('[C260444] Should require process name', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); @@ -174,7 +174,7 @@ describe('Start Process Component', () => { it('[C260443] Should be possible to start a process without start event', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); @@ -190,7 +190,7 @@ describe('Start Process Component', () => { it('[C260449] Should be possible to start a process with start event', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Test'); @@ -215,7 +215,7 @@ describe('Start Process Component', () => { it('[C286503] Should NOT display any process definition when typing a non-existent one', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.typeProcessDefinition('nonexistent'); @@ -225,7 +225,7 @@ describe('Start Process Component', () => { it('[C286504] Should display proper options when typing a part of existent process definitions', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.typeProcessDefinition('process'); @@ -237,7 +237,7 @@ describe('Start Process Component', () => { it('[C286508] Should display only one option when typing an existent process definition', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.typeProcessDefinition(processModelWithoutSe); @@ -249,7 +249,7 @@ describe('Start Process Component', () => { it('[C286509] Should select automatically the processDefinition when the app contains only one', () => { processServicesPage.goToApp(simpleApp.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); expect(startProcessPage.getProcessDefinitionValue()).toBe(simpleApp.title); @@ -258,7 +258,7 @@ describe('Start Process Component', () => { it('[C286511] Should be able to type the process definition and start a process', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Type'); @@ -273,7 +273,7 @@ describe('Start Process Component', () => { it('[C286513] Should be able to use down arrow key when navigating throw suggestions', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.typeProcessDefinition('process'); @@ -284,7 +284,7 @@ describe('Start Process Component', () => { it('[C286514] Should the process definition input be cleared when clicking on options drop down ', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.typeProcessDefinition('process'); @@ -297,7 +297,7 @@ describe('Start Process Component', () => { it('[C260453] Should be possible to add a comment on an active process', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Comment Process'); @@ -311,7 +311,7 @@ describe('Start Process Component', () => { it('[C260454] Should be possible to download audit log file', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Audit Log'); @@ -327,7 +327,7 @@ describe('Start Process Component', () => { it('Should be able to attach a file using the button', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); @@ -346,7 +346,7 @@ describe('Start Process Component', () => { it('[C260451] Should be possible to display process diagram', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); @@ -363,7 +363,7 @@ describe('Start Process Component', () => { it('[C260452] Should redirect user when clicking on active/completed task', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Active Task'); @@ -380,7 +380,7 @@ describe('Start Process Component', () => { navigationBarPage.navigateToProcessServicesPage(); processServicesPage.checkApsContainer(); processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Cancel Process'); @@ -396,7 +396,7 @@ describe('Start Process Component', () => { it('[C260461] Should be possible to add a comment on a completed/canceled process', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('Comment Process 2'); @@ -413,7 +413,7 @@ describe('Start Process Component', () => { it('[C260467] Should NOT be possible to attach a file on a completed process', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); startProcessPage.enterProcessName('File'); @@ -430,7 +430,7 @@ describe('Start Process Component', () => { it('[C291781] Should be displayed an error message if process name exceed 255 characters', () => { processServicesPage.goToApp(app.title); - appNavigationBarPage.clickProcessButton(); + processServiceTabBarPage.clickProcessButton(); processFiltersPage.clickCreateProcessButton(); processFiltersPage.clickNewProcessDropdown(); diff --git a/e2e/process-services/start-task-custom-app.e2e.ts b/e2e/process-services/start-task-custom-app.e2e.ts index cfb88a8ff5..51c238f50c 100644 --- a/e2e/process-services/start-task-custom-app.e2e.ts +++ b/e2e/process-services/start-task-custom-app.e2e.ts @@ -20,7 +20,7 @@ import { by } from 'protractor'; import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { Tenant } from '../models/APS/tenant'; @@ -41,7 +41,7 @@ describe('Start Task - Custom App', () => { const loginPage = new LoginPage(); const navigationBarPage = new NavigationBarPage(); const attachmentListPage = new AttachmentListPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); let processUserModel, assigneeUserModel; const app = resources.Files.SIMPLE_APP_WITH_USER_FORM; @@ -270,15 +270,15 @@ describe('Start Task - Custom App', () => { taskPage.createNewTask().addName(showHeaderTask).clickStartButton(); taskPage.tasksListPage().checkContentIsDisplayed(showHeaderTask); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); taskPage.taskDetails().appSettingsToggles().disableShowHeader(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskPage.taskDetails().taskInfoDrawerIsNotDisplayed(); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); taskPage.taskDetails().appSettingsToggles().enableShowHeader(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskPage.taskDetails().taskInfoDrawerIsDisplayed(); }); diff --git a/e2e/process-services/start-task-task-app.e2e.ts b/e2e/process-services/start-task-task-app.e2e.ts index c58f988910..537679b386 100644 --- a/e2e/process-services/start-task-task-app.e2e.ts +++ b/e2e/process-services/start-task-task-app.e2e.ts @@ -20,7 +20,7 @@ import { by } from 'protractor'; import { LoginPage } from '@alfresco/adf-testing'; import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { AttachmentListPage } from '../pages/adf/process-services/attachmentListPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import CONSTANTS = require('../util/constants'); @@ -41,7 +41,7 @@ describe('Start Task - Task App', () => { const loginPage = new LoginPage(); const attachmentListPage = new AttachmentListPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const navigationBarPage = new NavigationBarPage(); let processUserModel, assigneeUserModel; @@ -171,15 +171,15 @@ describe('Start Task - Task App', () => { taskPage.filtersPage().goToFilter(CONSTANTS.TASK_FILTERS.MY_TASKS); taskPage.tasksListPage().checkContentIsDisplayed(showHeaderTask); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); taskPage.taskDetails().appSettingsToggles().disableShowHeader(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskPage.taskDetails().taskInfoDrawerIsNotDisplayed(); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); taskPage.taskDetails().appSettingsToggles().enableShowHeader(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskPage.taskDetails().taskInfoDrawerIsDisplayed(); }); diff --git a/e2e/process-services/task-filters-component.e2e.ts b/e2e/process-services/task-filters-component.e2e.ts index 4cd281a933..b792eb5da1 100644 --- a/e2e/process-services/task-filters-component.e2e.ts +++ b/e2e/process-services/task-filters-component.e2e.ts @@ -24,7 +24,7 @@ import { ProcessServicesPage } from '../pages/adf/process-services/processServic import { TasksPage } from '../pages/adf/process-services/tasksPage'; import { TasksListPage } from '../pages/adf/process-services/tasksListPage'; import { TaskDetailsPage } from '../pages/adf/process-services/taskDetailsPage'; -import { AppNavigationBarPage } from '../pages/adf/process-services/appNavigationBarPage'; +import { ProcessServiceTabBarPage } from '../pages/adf/process-services/processServiceTabBarPage'; import { AppSettingsToggles } from '../pages/adf/process-services/dialog/appSettingsToggles'; import { TaskFiltersDemoPage } from '../pages/adf/demo-shell/process-services/taskFiltersDemoPage'; @@ -204,7 +204,7 @@ describe('Task', () => { const loginPage = new LoginPage(); const navigationBarPage = new NavigationBarPage(); const processServicesPage = new ProcessServicesPage(); - const appNavigationBarPage = new AppNavigationBarPage(); + const processServiceTabBarPage = new ProcessServiceTabBarPage(); const appSettingsToggles = new AppSettingsToggles(); const taskFiltersDemoPage = new TaskFiltersDemoPage(); @@ -290,10 +290,10 @@ describe('Task', () => { }); browser.refresh(); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); browser.sleep(500); appSettingsToggles.enableTaskFiltersIcon(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskFiltersDemoPage.customTaskFilter('New Task Filter with icon').checkTaskFilterIsDisplayed(); expect(taskFiltersDemoPage.customTaskFilter('New Task Filter with icon').getTaskFilterIcon()).toEqual('cloud'); @@ -307,9 +307,9 @@ describe('Task', () => { it('[C286449] Should display task filter icons only when showIcon property is set on true', () => { taskFiltersDemoPage.myTasksFilter().checkTaskFilterHasNoIcon(); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); appSettingsToggles.enableTaskFiltersIcon(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskFiltersDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(taskFiltersDemoPage.myTasksFilter().getTaskFilterIcon()).toEqual('inbox'); @@ -384,12 +384,12 @@ describe('Task', () => { }); browser.refresh(); - appNavigationBarPage.clickSettingsButton(); + processServiceTabBarPage.clickSettingsButton(); browser.sleep(500); appSettingsToggles.enableTaskFiltersIcon(); - appNavigationBarPage.clickTasksButton(); + processServiceTabBarPage.clickTasksButton(); taskFiltersDemoPage.customTaskFilter('Task Filter Edited icon').checkTaskFilterIsDisplayed(); expect(taskFiltersDemoPage.customTaskFilter('Task Filter Edited icon').getTaskFilterIcon()).toEqual('cloud'); diff --git a/e2e/search/components/search-checkList.e2e.ts b/e2e/search/components/search-checkList.e2e.ts index ad822f26e3..871b65cd27 100644 --- a/e2e/search/components/search-checkList.e2e.ts +++ b/e2e/search/components/search-checkList.e2e.ts @@ -30,8 +30,7 @@ import { SearchConfiguration } from '../search.config'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { browser } from 'protractor'; -import { StringUtil } from '@alfresco/adf-testing'; -import { setConfigField } from '../../proxy'; +import { StringUtil, LocalStorageUtil } from '@alfresco/adf-testing'; describe('Search Checklist Component', () => { @@ -154,7 +153,7 @@ describe('Search Checklist Component', () => { }); } - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); browser.sleep(2000); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -191,7 +190,7 @@ describe('Search Checklist Component', () => { }); } - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -203,7 +202,7 @@ describe('Search Checklist Component', () => { navigationBarPage.clickContentServicesButton(); jsonFile.categories[1].component.settings.pageSize = 11; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -216,7 +215,7 @@ describe('Search Checklist Component', () => { jsonFile.categories[1].component.settings.pageSize = 9; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -238,7 +237,7 @@ describe('Search Checklist Component', () => { }); } - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -259,7 +258,7 @@ describe('Search Checklist Component', () => { delete jsonFile.categories[1].component.settings.pageSize; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -299,7 +298,7 @@ describe('Search Checklist Component', () => { jsonFile.categories[1].component.settings.operator = 'AND'; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); @@ -324,7 +323,7 @@ describe('Search Checklist Component', () => { 'value': "TYPE:'cm:auditable'" }); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickCheckListFilter(); diff --git a/e2e/search/components/search-date-range.e2e.ts b/e2e/search/components/search-date-range.e2e.ts index a9d8da8cd8..085f889c48 100644 --- a/e2e/search/components/search-date-range.e2e.ts +++ b/e2e/search/components/search-date-range.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; @@ -29,7 +29,6 @@ import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { browser } from 'protractor'; import { DateUtil } from '../../util/dateUtil'; -import { setConfigField } from '../../proxy'; describe('Search Date Range Filter', () => { @@ -201,7 +200,7 @@ describe('Search Date Range Filter', () => { jsonFile.categories[4].component.settings.dateFormat = 'MM-DD-YY'; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().enterTextAndPressEnter('*'); searchFilters.checkCreatedRangeFilterIsDisplayed() diff --git a/e2e/search/components/search-number-range.e2e.ts b/e2e/search/components/search-number-range.e2e.ts index 7f785a8877..e9fcd2df2e 100644 --- a/e2e/search/components/search-number-range.e2e.ts +++ b/e2e/search/components/search-number-range.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; @@ -32,7 +32,6 @@ import { browser } from 'protractor'; import resources = require('../../util/resources'); import { SearchConfiguration } from '../search.config'; import { DateUtil } from '../../util/dateUtil'; -import { setConfigField } from '../../proxy'; describe('Search Number Range Filter', () => { @@ -397,12 +396,12 @@ describe('Search Number Range Filter', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C276928] Should be able to change the field property for number range', async() => { + it('[C276928] Should be able to change the field property for number range', async () => { navigationBar.clickContentServicesButton(); jsonFile.categories[3].component.settings.field = 'cm:created'; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -439,12 +438,12 @@ describe('Search Number Range Filter', () => { }); - it('[C277139] Should be able to set To field to be exclusive', async() => { + it('[C277139] Should be able to set To field to be exclusive', async () => { navigationBar.clickContentServicesButton(); jsonFile.categories[3].component.settings.format = '[{FROM} TO {TO}>'; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -475,12 +474,12 @@ describe('Search Number Range Filter', () => { searchResults.checkContentIsDisplayed(file2BytesModel.name); }); - it('[C277140] Should be able to set From field to be exclusive', async() => { + it('[C277140] Should be able to set From field to be exclusive', async () => { navigationBar.clickContentServicesButton(); jsonFile.categories[3].component.settings.format = '<{FROM} TO {TO}]'; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() diff --git a/e2e/search/components/search-radio.e2e.ts b/e2e/search/components/search-radio.e2e.ts index 31a6f1dd72..1e60dbaacc 100644 --- a/e2e/search/components/search-radio.e2e.ts +++ b/e2e/search/components/search-radio.e2e.ts @@ -30,8 +30,7 @@ import { SearchConfiguration } from '../search.config'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../../actions/ACS/upload.actions'; import { browser } from 'protractor'; -import { StringUtil } from '@alfresco/adf-testing'; -import { setConfigField } from '../../proxy'; +import { StringUtil, LocalStorageUtil } from '@alfresco/adf-testing'; describe('Search Radio Component', () => { @@ -73,7 +72,10 @@ describe('Search Radio Component', () => { await this.alfrescoJsApi.login(acsUser.id, acsUser.password); - createdFolder = await this.alfrescoJsApi.nodes.addNode('-my-', {name: nodeNames.folder, nodeType: 'cm:folder'}); + createdFolder = await this.alfrescoJsApi.nodes.addNode('-my-', { + name: nodeNames.folder, + nodeType: 'cm:folder' + }); createdFile = await this.alfrescoJsApi.nodes.addNode('-my-', { name: nodeNames.document, nodeType: 'cm:content' @@ -140,7 +142,7 @@ describe('Search Radio Component', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C277147] Should be able to customise the pageSize value', async() => { + it('[C277147] Should be able to customise the pageSize value', async () => { navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 10; @@ -152,7 +154,7 @@ describe('Search Radio Component', () => { }); } - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -163,7 +165,7 @@ describe('Search Radio Component', () => { jsonFile.categories[5].component.settings.pageSize = 11; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -173,7 +175,7 @@ describe('Search Radio Component', () => { navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 9; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -186,7 +188,7 @@ describe('Search Radio Component', () => { browser.refresh(); }); - it('[C277148] Should be able to click show more/less button', async() => { + it('[C277148] Should be able to click show more/less button', async () => { navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.pageSize = 0; @@ -198,7 +200,7 @@ describe('Search Radio Component', () => { }); } - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -225,7 +227,7 @@ describe('Search Radio Component', () => { navigationBarPage.clickContentServicesButton(); delete jsonFile.categories[5].component.settings.pageSize; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); @@ -267,7 +269,7 @@ describe('Search Radio Component', () => { done(); }); - it('[C277033] Should be able to add a new option', async() => { + it('[C277033] Should be able to add a new option', async () => { navigationBarPage.clickContentServicesButton(); jsonFile.categories[5].component.settings.options.push({ @@ -275,7 +277,7 @@ describe('Search Radio Component', () => { 'value': "TYPE:'cm:content'" }); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().checkSearchBarIsVisible().enterTextAndPressEnter(randomName); searchFiltersPage.clickTypeFilterHeader(); diff --git a/e2e/search/components/search-slider.e2e.ts b/e2e/search/components/search-slider.e2e.ts index eec37cc475..e76817dbaf 100644 --- a/e2e/search/components/search-slider.e2e.ts +++ b/e2e/search/components/search-slider.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { DataTableComponentPage } from '@alfresco/adf-testing'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; @@ -31,7 +31,6 @@ import { FileModel } from '../../models/ACS/fileModel'; import { browser } from 'protractor'; import resources = require('../../util/resources'); import { SearchConfiguration } from '../search.config'; -import { setConfigField } from '../../proxy'; describe('Search Number Range Filter', () => { @@ -163,12 +162,12 @@ describe('Search Number Range Filter', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C276983] Should be able to disable thumb label in Search Size Slider', async() => { + it('[C276983] Should be able to disable thumb label in Search Size Slider', async () => { navigationBar.clickContentServicesButton(); jsonFile.categories[2].component.settings.thumbLabel = false; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -181,13 +180,13 @@ describe('Search Number Range Filter', () => { sizeSliderFilter.checkSliderWithThumbLabelIsNotDisplayed(); }); - it('[C276985] Should be able to set min value for Search Size Slider', async() => { + it('[C276985] Should be able to set min value for Search Size Slider', async () => { navigationBar.clickContentServicesButton(); const minSize = 3; jsonFile.categories[2].component.settings.min = minSize; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -202,13 +201,13 @@ describe('Search Number Range Filter', () => { expect(sizeSliderFilter.getMinValue()).toEqual(`${minSize}`); }); - it('[C276986] Should be able to set max value for Search Size Slider', async() => { + it('[C276986] Should be able to set max value for Search Size Slider', async () => { navigationBar.clickContentServicesButton(); const maxSize = 50; jsonFile.categories[2].component.settings.max = maxSize; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -223,13 +222,13 @@ describe('Search Number Range Filter', () => { expect(sizeSliderFilter.getMaxValue()).toEqual(`${maxSize}`); }); - it('[C276987] Should be able to set steps for Search Size Slider', async() => { + it('[C276987] Should be able to set steps for Search Size Slider', async () => { navigationBar.clickContentServicesButton(); const step = 10; jsonFile.categories[2].component.settings.step = step; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() diff --git a/e2e/search/components/search-sorting-picker.e2e.ts b/e2e/search/components/search-sorting-picker.e2e.ts index 3306b0b419..7058cb6141 100644 --- a/e2e/search/components/search-sorting-picker.e2e.ts +++ b/e2e/search/components/search-sorting-picker.e2e.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; @@ -32,7 +32,6 @@ import { browser } from 'protractor'; import resources = require('../../util/resources'); import { SearchConfiguration } from '../search.config'; import { SearchSortingPickerPage } from '../../pages/adf/content-services/search/components/search-sortingPicker.page'; -import { setConfigField } from '../../proxy'; describe('Search Sorting Picker', () => { @@ -111,7 +110,7 @@ describe('Search Sorting Picker', () => { searchSortingPicker.checkOrderArrowIsDisplayed(); }); - it('[C277271] Should be able to add a custom search sorter in the "sort by" option', async() => { + it('[C277271] Should be able to add a custom search sorter in the "sort by" option', async () => { navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); @@ -122,7 +121,7 @@ describe('Search Sorting Picker', () => { 'field': 'cm:modifier', 'ascending': true }); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -134,12 +133,12 @@ describe('Search Sorting Picker', () => { .checkOptionIsDisplayed('Modifier'); }); - it('[C277272] Should be able to exclude a standard search sorter from the sorting option', async() => { + it('[C277272] Should be able to exclude a standard search sorter from the sorting option', async () => { navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); jsonFile = searchConfiguration.getConfiguration(); const removedOption = jsonFile.sorting.options.splice(0, 1); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -151,7 +150,7 @@ describe('Search Sorting Picker', () => { .checkOptionIsNotDisplayed(removedOption[0].label); }); - it('[C277273] Should be able to set a default order for a search sorting option', async() => { + it('[C277273] Should be able to set a default order for a search sorting option', async () => { navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); @@ -165,7 +164,7 @@ describe('Search Sorting Picker', () => { 'ascending': true }; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -218,7 +217,7 @@ describe('Search Sorting Picker', () => { }); }); - it('[C277288] Should be able to sort the search results by "Modified Date" ASC', async() => { + it('[C277288] Should be able to sort the search results by "Modified Date" ASC', async () => { navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); @@ -230,7 +229,7 @@ describe('Search Sorting Picker', () => { 'field': 'cm:modified', 'ascending': true }); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() @@ -252,7 +251,7 @@ describe('Search Sorting Picker', () => { }); }); - it('[C277301] Should be able to change default sorting option for the search results', async() => { + it('[C277301] Should be able to change default sorting option for the search results', async () => { navigationBar.clickContentServicesButton(); const searchConfiguration = new SearchConfiguration(); @@ -265,7 +264,7 @@ describe('Search Sorting Picker', () => { 'ascending': true }); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.checkSearchIconIsVisible() .clickOnSearchIcon() diff --git a/e2e/search/components/search-text.e2e.ts b/e2e/search/components/search-text.e2e.ts index 1179dd3bd4..4fdc5423e7 100644 --- a/e2e/search/components/search-text.e2e.ts +++ b/e2e/search/components/search-text.e2e.ts @@ -24,14 +24,13 @@ import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; -import { LoginPage } from '@alfresco/adf-testing'; +import { LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import { SearchDialog } from '../../pages/adf/dialog/searchDialog'; import { SearchResultsPage } from '../../pages/adf/searchResultsPage'; import { SearchFiltersPage } from '../../pages/adf/searchFiltersPage'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { SearchConfiguration } from '../search.config'; -import { setConfigField } from '../../proxy'; describe('Search component - Text widget', () => { @@ -43,7 +42,7 @@ describe('Search component - Text widget', () => { const searchResultPage = new SearchResultsPage(); const acsUser = new AcsUserModel(); - const newFolderModel = new FolderModel({'name': 'newFolder', 'description': 'newDescription'}); + const newFolderModel = new FolderModel({ 'name': 'newFolder', 'description': 'newDescription' }); beforeAll(async (done) => { @@ -91,7 +90,7 @@ describe('Search component - Text widget', () => { jsonFile = searchConfiguration.getConfiguration(); }); - it('[C289330] Should be able to change the Field setting', async() => { + it('[C289330] Should be able to change the Field setting', async () => { browser.get(TestConfig.adf.url + '/search;q=*'); searchResultPage.tableIsLoaded(); @@ -109,7 +108,7 @@ describe('Search component - Text widget', () => { jsonFile.categories[0].component.settings.field = 'cm:description'; navigationBarPage.clickContentServicesButton(); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon().enterTextAndPressEnter('*'); searchResultPage.tableIsLoaded(); diff --git a/e2e/search/search-component.e2e.ts b/e2e/search/search-component.e2e.ts index 1f0fed29c8..f6be03f0a1 100644 --- a/e2e/search/search-component.e2e.ts +++ b/e2e/search/search-component.e2e.ts @@ -29,13 +29,12 @@ import { FolderModel } from '../models/ACS/folderModel'; import TestConfig = require('../test.config'); import { Util } from '../util/util'; -import { StringUtil } from '@alfresco/adf-testing'; +import { StringUtil, LocalStorageUtil } from '@alfresco/adf-testing'; import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { SearchConfiguration } from './search.config'; -import { setConfigField } from '../proxy'; describe('Search component - Search Bar', () => { @@ -311,7 +310,7 @@ describe('Search component - Search Bar', () => { beforeAll(async () => { navigationBar.clickContentServicesButton(); - await setConfigField('search', JSON.stringify(searchConfiguration)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(searchConfiguration)); searchDialog .checkSearchIconIsVisible() diff --git a/e2e/search/search-filters.e2e.ts b/e2e/search/search-filters.e2e.ts index 6b64b48d32..8dfe24f8e0 100644 --- a/e2e/search/search-filters.e2e.ts +++ b/e2e/search/search-filters.e2e.ts @@ -24,14 +24,13 @@ import { FileModel } from '../models/ACS/fileModel'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import TestConfig = require('../test.config'); -import { StringUtil, DocumentListPage, PaginationPage, LoginPage } from '@alfresco/adf-testing'; +import { StringUtil, DocumentListPage, PaginationPage, LoginPage, LocalStorageUtil } from '@alfresco/adf-testing'; import resources = require('../util/resources'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { UploadActions } from '../actions/ACS/upload.actions'; import { browser } from 'protractor'; import { SearchConfiguration } from './search.config'; -import { setConfigField } from '../proxy'; describe('Search Filters', () => { @@ -184,11 +183,11 @@ describe('Search Filters', () => { }); }); - it('[C291802] Should be able to filter facet fields with "Contains"', async() => { + it('[C291802] Should be able to filter facet fields with "Contains"', async () => { navigationBarPage.clickContentServicesButton(); jsonFile['filterWithContains'] = true; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon() .enterTextAndPressEnter('*'); @@ -208,10 +207,10 @@ describe('Search Filters', () => { .checkSizeFacetQueryGroupIsDisplayed(); }); - it('[C291981] Should group search facets under the default label, by default', async() => { + it('[C291981] Should group search facets under the default label, by default', async () => { navigationBarPage.clickContentServicesButton(); - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon() .enterTextAndPressEnter('*'); @@ -260,12 +259,12 @@ describe('Search Filters', () => { }); - it('[C299124] Should be able to parse escaped empty spaced labels inside facetFields', async() => { + it('[C299124] Should be able to parse escaped empty spaced labels inside facetFields', async () => { navigationBarPage.clickContentServicesButton(); jsonFile.facetFields.fields[0].label = 'My File Types'; jsonFile.facetFields.fields[1].label = 'My File Sizes'; - await setConfigField('search', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('search', JSON.stringify(jsonFile)); searchDialog.clickOnSearchIcon() .enterTextAndPressEnter('*'); diff --git a/lib/core/services/automation.service.ts b/lib/core/services/automation.service.ts index da6478daf8..fb78c78bd9 100644 --- a/lib/core/services/automation.service.ts +++ b/lib/core/services/automation.service.ts @@ -17,12 +17,16 @@ import { Injectable } from '@angular/core'; import { AppConfigService } from '../app-config/app-config.service'; +import { AlfrescoApiService } from '../services/alfresco-api.service'; +import { StorageService } from './storage.service'; @Injectable({ providedIn: 'root' }) export class CoreAutomationService { - constructor(private appConfigService: AppConfigService) { + constructor(private appConfigService: AppConfigService, + private alfrescoApiService: AlfrescoApiService, + private storageService: StorageService) { } setup() { @@ -32,6 +36,18 @@ export class CoreAutomationService { this.appConfigService.config[field] = JSON.parse(value); }; + adfProxy.setStorageItem = (key: string, data: string) => { + this.storageService.setItem(key, data); + }; + + adfProxy.clearStorage = () => { + this.storageService.clear(); + }; + + adfProxy.apiReset = () => { + this.alfrescoApiService.reset(); + }; + window['adf'] = adfProxy; } } diff --git a/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts b/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts index 5cbf1aeaab..977d37d2cd 100644 --- a/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts +++ b/lib/testing/src/lib/content-services/dialog/content-node-selector-dialog.page.ts @@ -17,7 +17,7 @@ import { by, element } from 'protractor'; import { DocumentListPage } from '../pages/document-list.page'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class ContentNodeSelectorDialogPage { dialog = element(by.css(`adf-content-node-selector`)); diff --git a/lib/testing/src/lib/content-services/pages/document-list.page.ts b/lib/testing/src/lib/content-services/pages/document-list.page.ts index 84e17a1ad3..5630207944 100644 --- a/lib/testing/src/lib/content-services/pages/document-list.page.ts +++ b/lib/testing/src/lib/content-services/pages/document-list.page.ts @@ -17,7 +17,7 @@ import { by, element, ElementFinder, browser } from 'protractor'; import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class DocumentListPage { diff --git a/lib/testing/src/lib/core/actions/identity/group-identity.service.ts b/lib/testing/src/lib/core/actions/identity/group-identity.service.ts index 1cea809cf0..08d2544338 100644 --- a/lib/testing/src/lib/core/actions/identity/group-identity.service.ts +++ b/lib/testing/src/lib/core/actions/identity/group-identity.service.ts @@ -16,7 +16,7 @@ */ import { ApiService } from '../api.service'; -import { StringUtil } from '../../string.util'; +import { StringUtil } from '../../utils/string.util'; export class GroupIdentityService { diff --git a/lib/testing/src/lib/core/models/user.model.ts b/lib/testing/src/lib/core/models/user.model.ts index d3efd3db37..94169b22a0 100644 --- a/lib/testing/src/lib/core/models/user.model.ts +++ b/lib/testing/src/lib/core/models/user.model.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { StringUtil } from '../string.util'; +import { StringUtil } from '../utils/string.util'; export class UserModel { diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index 0f7d4861e4..61d9b07bb2 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -17,7 +17,7 @@ import { browser, by, element, protractor } from 'protractor'; import { ElementFinder, ElementArrayFinder } from 'protractor/built/element'; -import { BrowserVisibility } from '../browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; export class DataTableComponentPage { diff --git a/lib/testing/src/lib/core/pages/error.page.ts b/lib/testing/src/lib/core/pages/error.page.ts index ad07f823bb..0deda118d8 100644 --- a/lib/testing/src/lib/core/pages/error.page.ts +++ b/lib/testing/src/lib/core/pages/error.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; import { element, by } from 'protractor'; export class ErrorPage { diff --git a/lib/testing/src/lib/core/pages/form-controller.page.ts b/lib/testing/src/lib/core/pages/form-controller.page.ts index 9b2e566ee8..5c46c78df1 100644 --- a/lib/testing/src/lib/core/pages/form-controller.page.ts +++ b/lib/testing/src/lib/core/pages/form-controller.page.ts @@ -16,7 +16,7 @@ */ import { by } from 'protractor'; -import { BrowserVisibility } from '../browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; export class FormControllersPage { diff --git a/lib/testing/src/lib/core/pages/header.page.ts b/lib/testing/src/lib/core/pages/header.page.ts index 480bee699d..1c67f28590 100644 --- a/lib/testing/src/lib/core/pages/header.page.ts +++ b/lib/testing/src/lib/core/pages/header.page.ts @@ -16,7 +16,7 @@ */ import { element, by, protractor } from 'protractor'; -import { BrowserVisibility } from '../browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; export class HeaderPage { diff --git a/lib/testing/src/lib/core/pages/login-sso.page.ts b/lib/testing/src/lib/core/pages/login-sso.page.ts index e4a6316abb..a13e3bd516 100644 --- a/lib/testing/src/lib/core/pages/login-sso.page.ts +++ b/lib/testing/src/lib/core/pages/login-sso.page.ts @@ -16,7 +16,7 @@ */ import { element, by, browser, protractor } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; export class LoginSSOPage { diff --git a/lib/testing/src/lib/core/pages/login.page.ts b/lib/testing/src/lib/core/pages/login.page.ts index 0400a9178f..96d33928f2 100644 --- a/lib/testing/src/lib/core/pages/login.page.ts +++ b/lib/testing/src/lib/core/pages/login.page.ts @@ -17,10 +17,13 @@ import { FormControllersPage } from './form-controller.page'; import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../browser-visibility'; -import { SettingsPage } from './settings.page'; +import { BrowserVisibility } from '../utils/browser-visibility'; +import { LocalStorageUtil } from '../utils/local-storage.util'; export class LoginPage { + + loginURL = browser.baseUrl + '/login'; + formControllersPage = new FormControllersPage(); txtUsername = element(by.css('input[id="username"]')); txtPassword = element(by.css('input[id="password"]')); @@ -64,7 +67,6 @@ export class LoginPage { successRouteSwitch = element(by.id('adf-toggle-show-successRoute')); logoSwitch = element(by.id('adf-toggle-logo')); header = element(by.id('adf-header')); - settingsPage = new SettingsPage(); settingsIcon = element( by.cssContainingText( 'a[data-automation-id="settings"] mat-icon', @@ -72,6 +74,13 @@ export class LoginPage { ) ); + goToLoginPage() { + browser.waitForAngularEnabled(true); + browser.driver.get(this.loginURL); + this.waitForElements(); + return this; + } + waitForElements() { BrowserVisibility.waitUntilElementIsVisible(this.txtUsername); BrowserVisibility.waitUntilElementIsVisible(this.txtPassword); @@ -162,31 +171,31 @@ export class LoginPage { return this.signInButton.isEnabled(); } - loginToProcessServicesUsingUserModel(userModel) { - this.settingsPage.setProviderBpm(); - this.waitForElements(); + async loginToProcessServicesUsingUserModel(userModel) { + this.goToLoginPage(); + await LocalStorageUtil.clearStorage(); + await LocalStorageUtil.setStorageItem('providers', 'BPM'); + await LocalStorageUtil.apiReset(); this.login(userModel.email, userModel.password); } - loginToContentServicesUsingUserModel(userModel) { - this.settingsPage.setProviderEcm(); - this.waitForElements(); - + async loginToContentServicesUsingUserModel(userModel) { + this.goToLoginPage(); + await LocalStorageUtil.clearStorage(); + await LocalStorageUtil.setStorageItem('providers', 'ECM'); + await LocalStorageUtil.apiReset(); this.login(userModel.getId(), userModel.getPassword()); } - loginToContentServices(username, password) { - this.settingsPage.setProviderEcm(); + async loginToContentServices(username, password) { + this.goToLoginPage(); + await LocalStorageUtil.clearStorage(); + await LocalStorageUtil.setStorageItem('providers', 'ECM'); + await LocalStorageUtil.apiReset(); this.waitForElements(); this.login(username, password); } - goToLoginPage() { - browser.waitForAngularEnabled(true); - browser.driver.get(browser.baseUrl + '/login'); - this.waitForElements(); - } - clickSignInButton() { BrowserVisibility.waitUntilElementIsVisible(this.signInButton); this.signInButton.click(); diff --git a/lib/testing/src/lib/core/pages/pagination.page.ts b/lib/testing/src/lib/core/pages/pagination.page.ts index b900d104eb..613c91fd1d 100644 --- a/lib/testing/src/lib/core/pages/pagination.page.ts +++ b/lib/testing/src/lib/core/pages/pagination.page.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; export class PaginationPage { diff --git a/lib/testing/src/lib/core/pages/settings.page.ts b/lib/testing/src/lib/core/pages/settings.page.ts index fc506e6fa1..a5766ccda1 100644 --- a/lib/testing/src/lib/core/pages/settings.page.ts +++ b/lib/testing/src/lib/core/pages/settings.page.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; export class SettingsPage { diff --git a/lib/testing/src/lib/core/pages/user-info.page.ts b/lib/testing/src/lib/core/pages/user-info.page.ts index ebd92363ce..7f72cfaa67 100644 --- a/lib/testing/src/lib/core/pages/user-info.page.ts +++ b/lib/testing/src/lib/core/pages/user-info.page.ts @@ -16,7 +16,7 @@ */ import { element, by, browser, protractor } from 'protractor'; -import { BrowserVisibility } from '../browser-visibility'; +import { BrowserVisibility } from '../utils/browser-visibility'; import { TabsPage } from '../../material/pages/tabs.page'; export class UserInfoPage { diff --git a/lib/testing/src/lib/core/public-api.ts b/lib/testing/src/lib/core/public-api.ts index c8b49d3e7a..33bfe4594a 100644 --- a/lib/testing/src/lib/core/public-api.ts +++ b/lib/testing/src/lib/core/public-api.ts @@ -15,9 +15,8 @@ * limitations under the License. */ -export * from './browser-visibility'; export * from './actions/public-api'; export * from './pages/public-api'; export * from './models/public-api'; -export * from './string.util'; -export * from './protractor.util'; + +export * from './utils/public-api'; diff --git a/lib/testing/src/lib/core/browser-visibility.ts b/lib/testing/src/lib/core/utils/browser-visibility.ts similarity index 100% rename from lib/testing/src/lib/core/browser-visibility.ts rename to lib/testing/src/lib/core/utils/browser-visibility.ts diff --git a/lib/testing/src/lib/core/utils/local-storage.util.ts b/lib/testing/src/lib/core/utils/local-storage.util.ts new file mode 100644 index 0000000000..853e0b5bc3 --- /dev/null +++ b/lib/testing/src/lib/core/utils/local-storage.util.ts @@ -0,0 +1,45 @@ +/*! + * @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 { browser } from 'protractor'; + +export class LocalStorageUtil { + + static async setConfigField(field: string, value: string) { + await browser.executeScript( + 'window.adf.setConfigField(`' + field + '`, `' + value + '`);' + ); + } + + static async setStorageItem(field: string, value: string) { + await browser.executeScript( + 'window.adf.setStorageItem(`' + field + '`, `' + value + '`);' + ); + } + + static async clearStorage() { + await browser.executeScript( + 'window.adf.clearStorage();' + ); + } + + static async apiReset() { + await browser.executeScript( + `window.adf.apiReset();` + ); + } +} diff --git a/lib/testing/src/lib/core/protractor.util.ts b/lib/testing/src/lib/core/utils/protractor.util.ts similarity index 100% rename from lib/testing/src/lib/core/protractor.util.ts rename to lib/testing/src/lib/core/utils/protractor.util.ts diff --git a/e2e/proxy.ts b/lib/testing/src/lib/core/utils/public-api.ts similarity index 71% rename from e2e/proxy.ts rename to lib/testing/src/lib/core/utils/public-api.ts index 4cec020e5f..f76fa8f7e7 100644 --- a/e2e/proxy.ts +++ b/lib/testing/src/lib/core/utils/public-api.ts @@ -15,14 +15,7 @@ * limitations under the License. */ -/* tslint:disable */ - -import { browser } from 'protractor'; - -export async function setConfigField(field: string, value: string) { - - await browser.executeScript( - "window.adf.setConfigField(`" + field + "`, `" + value + "`);" - ); - -} +export * from './browser-visibility'; +export * from './string.util'; +export * from './protractor.util'; +export * from './local-storage.util'; diff --git a/lib/testing/src/lib/core/string.util.ts b/lib/testing/src/lib/core/utils/string.util.ts similarity index 100% rename from lib/testing/src/lib/core/string.util.ts rename to lib/testing/src/lib/core/utils/string.util.ts diff --git a/lib/testing/src/lib/material/pages/tabs.page.ts b/lib/testing/src/lib/material/pages/tabs.page.ts index b903167882..7aa15fd2eb 100644 --- a/lib/testing/src/lib/material/pages/tabs.page.ts +++ b/lib/testing/src/lib/material/pages/tabs.page.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class TabsPage { diff --git a/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts b/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts index bc5aa073fa..6fb12a2314 100644 --- a/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts +++ b/lib/testing/src/lib/process-services-cloud/app/app-list-cloud.page.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class AppListCloudPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts index 9cd5c77568..f6dfbc9f98 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts @@ -16,7 +16,7 @@ */ import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../../../core/browser-visibility'; +import { BrowserVisibility } from '../../../core/utils/browser-visibility'; export class EditProcessFilterDialogPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts index c86977900d..36826d0ea0 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/dialog/edit-task-filter-dialog.page.ts @@ -16,7 +16,7 @@ */ import { by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../../../core/browser-visibility'; +import { BrowserVisibility } from '../../../core/utils/browser-visibility'; export class EditTaskFilterDialogPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts index 5c56734899..7e24e9945f 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { by, element, protractor } from 'protractor'; import { EditProcessFilterDialogPage } from './dialog/edit-process-filter-dialog.page'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class EditProcessFilterCloudComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts index 10f35c6b55..4dbcea7adf 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts @@ -17,7 +17,7 @@ import { by, element, protractor } from 'protractor'; import { EditTaskFilterDialogPage } from './dialog/edit-task-filter-dialog.page'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class EditTaskFilterCloudComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts index 2616d7a9d2..b8247f2c4e 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/group-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class GroupCloudComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts index b43495f0aa..cdce1550f0 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/people-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { browser, by, element, protractor } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class PeopleCloudComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts index 757f435948..0b90914ad8 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-filters-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { by } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class ProcessFiltersCloudComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts index e741e51973..5c6974f30a 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-header-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class ProcessHeaderCloudPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts index 122b2ec6c7..a6f57abda1 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; import { element, by } from 'protractor'; diff --git a/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts index 5a48996e8d..3914db230a 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/start-process-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { by, element, Key, protractor, browser } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class StartProcessCloudPage { @@ -95,6 +95,7 @@ export class StartProcessCloudPage { } clickStartProcessButton() { + BrowserVisibility.waitUntilElementIsClickable(this.startProcessButton); return this.startProcessButton.click(); } diff --git a/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts index 0d483a62f0..7efae0d257 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/start-tasks-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { element, by, Key, protractor } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class StartTasksCloudPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts index 74708b8fac..0197902d42 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-filters-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { by } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class TaskFiltersCloudComponentPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts index 192361ef68..8a51329fee 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-header-cloud-component.page.ts @@ -16,7 +16,7 @@ */ import { element, by } from 'protractor'; -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; export class TaskHeaderCloudPage { diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts index 2f63478a6d..a795d691f6 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; import { DataTableComponentPage } from '../../core/pages/data-table-component.page'; import { element, by } from 'protractor'; diff --git a/lib/testing/src/lib/process-services/pages/form-fields.page.ts b/lib/testing/src/lib/process-services/pages/form-fields.page.ts index 91392ed884..f6843b9ae7 100644 --- a/lib/testing/src/lib/process-services/pages/form-fields.page.ts +++ b/lib/testing/src/lib/process-services/pages/form-fields.page.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { BrowserVisibility } from '../../core/browser-visibility'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; import { by, element } from 'protractor'; export class FormFieldsPage { From 03c9a1e5be3c7b40517e9b6c6ecc7862db8b6765 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Mon, 22 Apr 2019 03:31:00 +0300 Subject: [PATCH 132/208] [ADF-4420] TaskHeaderCloud - fix show endDate (#4631) --- .../src/lib/task/start-task/models/task-details-cloud.model.ts | 2 ++ .../task/task-header/components/task-header-cloud.component.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts index 6942194311..da403bc255 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts @@ -24,6 +24,7 @@ export class TaskDetailsCloudModel { appVersion: string; createdDate: Date; claimedDate: Date; + completedDate: Date; formKey: any; category: any; description: string; @@ -53,6 +54,7 @@ export class TaskDetailsCloudModel { this.appVersion = obj.appVersion || null; this.createdDate = obj.createdDate || null; this.claimedDate = obj.claimedDate || null; + this.completedDate = obj.completedDate || null; this.formKey = obj.formKey || null; this.description = obj.description || null; this.dueDate = obj.dueDate || null; diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index 04e050a555..9ec9bda32b 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -156,7 +156,7 @@ export class TaskHeaderCloudComponent implements OnInit { new CardViewDateItemModel( { label: 'ADF_CLOUD_TASK_HEADER.PROPERTIES.END_DATE', - value: '', + value: this.taskDetails.completedDate, format: 'DD-MM-YYYY', key: 'endDate' } From 46f7e98ecae8f41b1d1c50a730b1751cbfb24eb5 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Mon, 22 Apr 2019 01:31:38 +0100 Subject: [PATCH 133/208] remove -bbinsights --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5f6faa47bc..b1ce085e28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -187,7 +187,7 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "process-services-cloud$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder insights --skip-lint --use-dist -b || exit 1;); + (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder insights --skip-lint --use-dist || exit 1;); fi; - stage: Create Docker and Deploy Docker PR script: From 54adfaa56fc70c820173ebb8ef65d8eee4117929 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Mon, 22 Apr 2019 02:49:28 +0200 Subject: [PATCH 134/208] fail fast (#4633) --- package-lock.json | 17 +++++++++++++++++ package.json | 1 + protractor.conf.js | 3 +++ scripts/test-e2e-lib.sh | 2 +- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 8544d55b76..ea10e37386 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9534,6 +9534,23 @@ "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", "dev": true }, + "jasmine-fail-fast": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jasmine-fail-fast/-/jasmine-fail-fast-2.0.0.tgz", + "integrity": "sha1-5dguaimiX2YsZA5MMnDC+acTh+c=", + "dev": true, + "requires": { + "lodash": "3.10.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz", + "integrity": "sha1-k9UcZygopEFqEq9XIguoqHN+L7s=", + "dev": true + } + } + }, "jasmine-reporters": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.3.2.tgz", diff --git a/package.json b/package.json index 025c2a0b9f..932571adcd 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,7 @@ "husky": "^1.2.0", "jasmine-ajax": "3.2.0", "jasmine-core": "~2.8.0", + "jasmine-fail-fast": "^2.0.0", "jasmine-reporters": "^2.3.2", "jasmine-spec-reporter": "~4.2.1", "jasmine2-protractor-utils": "1.1.3", diff --git a/protractor.conf.js b/protractor.conf.js index 9d7c062451..e84da4f44f 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -221,6 +221,9 @@ exports.config = { retry.onPrepare(); + let failFast = require('jasmine-fail-fast'); + jasmine.getEnv().addReporter(failFast.init()); + global.TestConfig = TestConfig; require('ts-node').register({ project: 'e2e/tsconfig.e2e.json' diff --git a/scripts/test-e2e-lib.sh b/scripts/test-e2e-lib.sh index 78c677c9cd..eba8e2fdae 100755 --- a/scripts/test-e2e-lib.sh +++ b/scripts/test-e2e-lib.sh @@ -7,7 +7,7 @@ DEVELOPMENT=false EXECLINT=true LITESERVER=false EXEC_VERSION_JSAPI=false -TIMEOUT=20000 +TIMEOUT=10000 SELENIUM_PROMISE_MANAGER=1 show_help() { From 32647c8af54b03b1b6d1aadbe8ba9418756dc962 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Mon, 22 Apr 2019 20:19:39 +0300 Subject: [PATCH 135/208] [ADF-4430] Metadata- fix error message (#4635) --- .../card-view-textitem/card-view-textitem.component.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts index deeabaf1b7..2b3108cec2 100644 --- a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts +++ b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts @@ -87,6 +87,11 @@ export class CardViewTextItemComponent implements OnChanges { reset(): void { this.editedValue = this.property.multiline ? this.property.displayValue : this.property.value; this.setEditMode(false); + this.resetErrorMessages(); + } + + private resetErrorMessages() { + this.errorMessages = []; } update(): void { @@ -95,6 +100,7 @@ export class CardViewTextItemComponent implements OnChanges { this.cardViewUpdateService.update(this.property, updatedValue); this.property.value = updatedValue; this.setEditMode(false); + this.resetErrorMessages(); } else { this.errorMessages = this.property.getValidationErrors(this.editedValue); } From 6e4adfb09a37caaaf98daab4d7c3cf68ade361c5 Mon Sep 17 00:00:00 2001 From: dhrn <14145706+dhrn@users.noreply.github.com> Date: Mon, 22 Apr 2019 23:08:35 +0530 Subject: [PATCH 136/208] [ADF-4359] - Add the possibility to chose wich panel to show first in info-drawer (#4632) * [ADF-4359] - Add the possibility to chose which panel to show first in info-drawer * * docs added --- .../file-view/file-view.component.html | 17 ++++- .../file-view/file-view.component.ts | 6 ++ .../content-metadata-card.component.md | 1 + .../content-metadata-card.component.html | 1 + .../content-metadata-card.component.spec.ts | 14 ++++ .../content-metadata-card.component.ts | 16 +++- .../content-metadata.component.html | 6 +- .../content-metadata.component.spec.ts | 74 ++++++++++++++++++- .../content-metadata.component.ts | 8 ++ .../components/content-metadata/mock-data.ts | 74 +++++++++++++++++++ 10 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 lib/content-services/content-metadata/components/content-metadata/mock-data.ts diff --git a/demo-shell/src/app/components/file-view/file-view.component.html b/demo-shell/src/app/components/file-view/file-view.component.html index c2586757cd..d14163bbaf 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.html +++ b/demo-shell/src/app/components/file-view/file-view.component.html @@ -12,12 +12,14 @@ [multi]="multi" [preset]="customPreset" [readOnly]="isReadOnly" + [displayAspect]="showAspect" [displayDefaultProperties]="displayDefaultProperties" [displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card> <adf-content-metadata-card *ngIf="!isPreset" [node]="node" [multi]="multi" [readOnly]="isReadOnly" + [displayAspect]="showAspect" [displayDefaultProperties]="displayDefaultProperties" [displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card> @@ -71,6 +73,19 @@ </mat-slide-toggle> </p> + <p class="toggle"> + + <mat-form-field floatPlaceholder="float"> + <input matInput + placeholder="Display Aspect" + [(ngModel)]="desiredAspect"> + </mat-form-field> + + <button mat-raised-button (click)="applyAspect()" color="primary"> + Apply Aspect + </button> + </p> + <p class="toggle"> <ng-container *ngIf="isPreset"> <mat-form-field floatPlaceholder="float"> @@ -118,7 +133,7 @@ <p class="toggle"> <ng-container *ngIf="customName"> - <mat-form-field floatPlaceholder="float"> + <mat-form-field floatLabel="never"> <input matInput placeholder="Custom Name" [(ngModel)]="displayName" diff --git a/demo-shell/src/app/components/file-view/file-view.component.ts b/demo-shell/src/app/components/file-view/file-view.component.ts index f014d8fca0..e5b4187f87 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.ts +++ b/demo-shell/src/app/components/file-view/file-view.component.ts @@ -55,6 +55,8 @@ export class FileViewComponent implements OnInit { isCommentEnabled = false; showTabWithIcon = false; showTabWithIconAndLabel = false; + desiredAspect: string = null; + showAspect: string = null; constructor(private router: Router, private route: ActivatedRoute, @@ -188,4 +190,8 @@ export class FileViewComponent implements OnInit { this.isPreset = true; }, 100); } + + applyAspect() { + this.showAspect = this.desiredAspect; + } } diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index 773ed6b807..c280ae6f69 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -34,6 +34,7 @@ Displays and edits metadata related to a node. | preset | `string` | | (required) Name of the metadata preset, which defines aspects and their properties. | | readOnly | `boolean` | false | (optional) This flag sets the metadata in read only mode preventing changes. | | displayDefaultProperties | `boolean` | | (optional) This flag displays/hides the metadata properties. | +| displayAspect | `string` | | (optional) This flag displays the desired metadata property in the expanded card | ## Details diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html index 07068fd23f..6369ce8268 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html @@ -7,6 +7,7 @@ [displayEmpty]="displayEmpty" [editable]="editable" [multi]="multi" + [displayAspect]="displayAspect" [preset]="preset"> </adf-content-metadata> </mat-card-content> diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts index 7c1f730fa1..0e5bb7ab4f 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts @@ -22,6 +22,7 @@ import { ContentMetadataCardComponent } from './content-metadata-card.component' import { ContentMetadataComponent } from '../content-metadata/content-metadata.component'; import { setupTestBed, AllowableOperationsEnum } from '@alfresco/adf-core'; import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { SimpleChange } from '@angular/core'; describe('ContentMetadataCardComponent', () => { @@ -189,4 +190,17 @@ describe('ContentMetadataCardComponent', () => { const button = fixture.debugElement.query(By.css('[data-automation-id="meta-data-card-toggle-edit"]')); expect(button).not.toBeNull(); }); + + it('should expand the card when custom display aspect is valid', () => { + expect(component.expanded).toBeFalsy(); + + let displayAspect = new SimpleChange(null , 'EXIF', true); + component.ngOnChanges({ displayAspect }); + expect(component.expanded).toBeTruthy(); + + displayAspect = new SimpleChange('EXIF' , null, false); + component.ngOnChanges({ displayAspect }); + expect(component.expanded).toBeTruthy(); + }); + }); diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts index 54084f0db3..ddd2f99577 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core'; import { Node } from '@alfresco/js-api'; import { ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; @@ -26,7 +26,7 @@ import { ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; encapsulation: ViewEncapsulation.None, host: { 'class': 'adf-content-metadata-card' } }) -export class ContentMetadataCardComponent { +export class ContentMetadataCardComponent implements OnChanges { /** (required) The node entity to fetch metadata about */ @Input() node: Node; @@ -37,6 +37,12 @@ export class ContentMetadataCardComponent { @Input() displayEmpty: boolean = false; + /** (optional) This flag displays desired aspect when open for the first time + * fields. + */ + @Input() + displayAspect: string = null; + /** (required) Name of the metadata preset, which defines aspects * and their properties. */ @@ -77,6 +83,12 @@ export class ContentMetadataCardComponent { constructor(private contentService: ContentService) { } + ngOnChanges(changes: SimpleChanges): void { + if (changes.displayAspect && changes.displayAspect.currentValue) { + this.expanded = true; + } + } + onDisplayDefaultPropertiesChange(): void { this.expanded = !this._displayDefaultProperties; } diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html index e1c344b2c9..8f4876110a 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html @@ -2,8 +2,8 @@ <mat-accordion displayMode="flat" [multi]="multi"> <mat-expansion-panel *ngIf="displayDefaultProperties" - [expanded]="!expanded" - [hideToggle]="!expanded" + [expanded]="!expanded || !displayAspect" + [hideToggle]="!expanded || !displayAspect" [attr.data-automation-id]="'adf-metadata-group-properties'" > <mat-expansion-panel-header> <mat-panel-title> @@ -23,7 +23,7 @@ <div *ngFor="let group of groupedProperties; let first = first;" class="adf-metadata-grouped-properties-container"> <mat-expansion-panel *ngIf="showGroup(group) || editable" [attr.data-automation-id]="'adf-metadata-group-' + group.title" - [expanded]="!displayDefaultProperties && first"> + [expanded]="canExpandTheCard(group) || !displayDefaultProperties && first"> <mat-expansion-panel-header> <mat-panel-title> {{ group.title | translate }} diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts index ac6bfd0dec..a3fe638500 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -27,10 +27,12 @@ import { } from '@alfresco/adf-core'; import { throwError, of } from 'rxjs'; import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { mockGroupProperties } from './mock-data'; describe('ContentMetadataComponent', () => { let component: ContentMetadataComponent; let fixture: ComponentFixture<ContentMetadataComponent>; + let contentMetadataService: ContentMetadataService; let node: Node; let folderNode: Node; const preset = 'custom-preset'; @@ -43,6 +45,7 @@ describe('ContentMetadataComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ContentMetadataComponent); component = fixture.componentInstance; + contentMetadataService = TestBed.get(ContentMetadataService); node = <Node> { id: 'node-id', aspectNames: [], @@ -147,11 +150,10 @@ describe('ContentMetadataComponent', () => { }); describe('Properties loading', () => { - let expectedNode, contentMetadataService: ContentMetadataService; + let expectedNode; beforeEach(() => { expectedNode = Object.assign({}, node, { name: 'some-modified-value' }); - contentMetadataService = TestBed.get(ContentMetadataService); fixture.detectChanges(); }); @@ -294,4 +296,72 @@ describe('ContentMetadataComponent', () => { expect(component.displayDefaultProperties).toBe(true); }); }); + + describe('Expand the panel', () => { + let expectedNode; + + beforeEach(() => { + expectedNode = Object.assign({}, node, {name: 'some-modified-value'}); + spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of(mockGroupProperties)); + component.ngOnChanges({node: new SimpleChange(node, expectedNode, false)}); + }); + + it('should open and update drawer with expand section dynamically', async(() => { + component.displayAspect = 'EXIF'; + component.expanded = true; + component.displayEmpty = true; + + fixture.detectChanges(); + const defaultProp = queryDom(fixture); + const exifProp = queryDom(fixture, 'EXIF'); + const customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeFalsy(); + expect(exifProp.componentInstance.expanded).toBeTruthy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); + + component.displayAspect = 'CUSTOM'; + fixture.detectChanges(); + const updatedDefault = queryDom(fixture); + const updatedExif = queryDom(fixture, 'EXIF'); + const updatedCustom = queryDom(fixture, 'CUSTOM'); + expect(updatedDefault.componentInstance.expanded).toBeFalsy(); + expect(updatedExif.componentInstance.expanded).toBeFalsy(); + expect(updatedCustom.componentInstance.expanded).toBeTruthy(); + + })); + + it('should not expand anything if input is wrong', async(() => { + component.displayAspect = 'XXXX'; + component.expanded = true; + component.displayEmpty = true; + + fixture.detectChanges(); + const defaultProp = queryDom(fixture); + const exifProp = queryDom(fixture, 'EXIF'); + const customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeFalsy(); + expect(exifProp.componentInstance.expanded).toBeFalsy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); + + })); + + it('should expand the properties section when input is null', async(() => { + component.displayAspect = null; + component.expanded = true; + component.displayEmpty = true; + + fixture.detectChanges(); + const defaultProp = queryDom(fixture); + const exifProp = queryDom(fixture, 'EXIF'); + const customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeTruthy(); + expect(exifProp.componentInstance.expanded).toBeFalsy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); + + })); + }); }); + +function queryDom(fixture: ComponentFixture<ContentMetadataComponent>, properties: string = 'properties') { + return fixture.debugElement.query(By.css(`[data-automation-id="adf-metadata-group-${properties}"]`)); +} diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts index d3c4004263..b6d769cafb 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts @@ -61,6 +61,10 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { @Input() displayDefaultProperties: boolean = true; + /** (Optional) shows the given aspect in the expanded card */ + @Input() + displayAspect: string = null; + basicProperties$: Observable<CardViewItem[]>; groupedProperties$: Observable<CardViewGroup[]>; disposableNodeUpdate: Subscription; @@ -118,4 +122,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { this.disposableNodeUpdate.unsubscribe(); } + public canExpandTheCard(group: CardViewGroup): boolean { + return group.title === this.displayAspect; + } + } diff --git a/lib/content-services/content-metadata/components/content-metadata/mock-data.ts b/lib/content-services/content-metadata/components/content-metadata/mock-data.ts new file mode 100644 index 0000000000..4ea3974bcd --- /dev/null +++ b/lib/content-services/content-metadata/components/content-metadata/mock-data.ts @@ -0,0 +1,74 @@ +/*! + * @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. + */ + +export const mockGroupProperties = [ + { + 'title': 'EXIF', + 'properties': [ + { + 'label': 'Image Width', + 'value': 363, + 'key': 'properties.exif:pixelXDimension', + 'default': null, + 'editable': true, + 'clickable': false, + 'icon': '', + 'data': null, + 'type': 'int', + 'multiline': false, + 'pipes': [], + 'clickCallBack': null, + displayValue: 400 + }, + { + 'label': 'Image Height', + 'value': 400, + 'key': 'properties.exif:pixelYDimension', + 'default': null, + 'editable': true, + 'clickable': false, + 'icon': '', + 'data': null, + 'type': 'int', + 'multiline': false, + 'pipes': [], + 'clickCallBack': null, + displayValue: 400 + } + ] + }, + { + 'title': 'CUSTOM', + 'properties': [ + { + 'label': 'Height', + 'value': 400, + 'key': 'properties.custom:abc', + 'default': null, + 'editable': true, + 'clickable': false, + 'icon': '', + 'data': null, + 'type': 'int', + 'multiline': false, + 'pipes': [], + 'clickCallBack': null, + displayValue: 400 + } + ] + } +]; From b58e040d7ef39db9e1848757adb34698296652e0 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Tue, 23 Apr 2019 00:43:56 +0300 Subject: [PATCH 137/208] [ADF-4394]Add two more tests on copyContent (#4630) * Add two more tests * Update data-table-component.page.ts * Fix lint issues --- .../copy-content/datatable.component.html | 1 + .../copy-content/datatable.component.ts | 17 ++++-- .../datatable/data-table-component.e2e.ts | 20 +++++++ e2e/pages/adf/contentServicesPage.ts | 2 +- e2e/pages/adf/demo-shell/customSourcesPage.ts | 2 +- e2e/pages/adf/demo-shell/dataTablePage.ts | 24 ++++++--- e2e/pages/adf/permissionsPage.ts | 2 +- e2e/pages/adf/searchResultsPage.ts | 2 +- .../datatable/datatable.component.html | 3 +- .../core/pages/data-table-component.page.ts | 52 ++++++++++++------- .../pages/task-list-cloud-component.page.ts | 4 +- 11 files changed, 91 insertions(+), 38 deletions(-) diff --git a/demo-shell/src/app/components/datatable/copy-content/datatable.component.html b/demo-shell/src/app/components/datatable/copy-content/datatable.component.html index e4005850ee..832b6a8581 100644 --- a/demo-shell/src/app/components/datatable/copy-content/datatable.component.html +++ b/demo-shell/src/app/components/datatable/copy-content/datatable.component.html @@ -18,6 +18,7 @@ <data-column key="id" title="Id" [copyContent]="true"></data-column> <data-column key="name" title="Name" class="adf-full-width name-column" [copyContent]="false"></data-column> <data-column key="createdBy" title="Created By"></data-column> + <data-column key="json" type="json" title="Json" [copyContent]="true"></data-column> </data-columns> </adf-datatable> </div> diff --git a/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts b/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts index 585ed77935..64195a2dfc 100644 --- a/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts +++ b/demo-shell/src/app/components/datatable/copy-content/datatable.component.ts @@ -60,17 +60,26 @@ export class DataTableComponent { { id: 1, name: 'First', - createdBy: 'Created one' + createdBy: 'Created one', + json: null }, { id: 2, name: 'Second', - createdBy: 'Created two' + createdBy: 'Created two', + json: { + id: 4 + } }, { id: 3, name: 'Third', - createdBy: 'Created three' + createdBy: 'Created three', + json: { + id: 4, + name: 'Image 8', + createdOn: new Date(2016, 6, 2, 15, 8, 4) + } } ] ); @@ -119,7 +128,7 @@ export class DataTableComponent { { type: 'text', key: 'id', title: 'Id', sortable: true , cssClass: '', copyContent: true }, { type: 'text', key: 'name', title: 'Name', cssClass: 'adf-ellipsis-cell', sortable: true, copyContent: false }, { type: 'text', key: 'createdBy', title: 'Created By', sortable: true, cssClass: ''}, - { type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2'} + { type: 'json', key: 'json', title: 'Json', cssClass: 'adf-expand-cell-2', copyContent: true} ] ); } diff --git a/e2e/core/datatable/data-table-component.e2e.ts b/e2e/core/datatable/data-table-component.e2e.ts index cf14f36f8a..639af112f2 100644 --- a/e2e/core/datatable/data-table-component.e2e.ts +++ b/e2e/core/datatable/data-table-component.e2e.ts @@ -164,10 +164,30 @@ describe('Datatable component', () => { expect(copyContentDataTablePage.getClipboardInputText()).toEqual('1'); copyContentDataTablePage.clickOnIdColumn('2'); notificationPage.checkNotifyContains('Text copied to clipboard'); + copyContentDataTablePage.mouseOverIdColumn('3'); copyContentDataTablePage.clickOnIdColumn('3'); notificationPage.checkNotifyContains('Text copied to clipboard'); copyContentDataTablePage.pasteClipboard(); expect(copyContentDataTablePage.getClipboardInputText()).toEqual('3'); }); + + it('[C307100] A column value of type text and with copyContent set to true is copied when clicking on it', () => { + dataTablePage.mouseOverIdColumn('1'); + expect(dataTablePage.getCopyContentTooltip()).toEqual('Click to copy'); + dataTablePage.clickOnIdColumn('1'); + notificationPage.checkNotifyContains('Text copied to clipboard'); + dataTablePage.pasteClipboard(); + expect(dataTablePage.getClipboardInputText()).toEqual('1'); + }); + + it('[C307101] A column value of type json and with copyContent set to true is copied when clicking on it', () => { + const jsonValue = `{ "id": 4 }`; + copyContentDataTablePage.mouseOverJsonColumn(2); + expect(copyContentDataTablePage.getCopyContentTooltip()).toEqual('Click to copy'); + copyContentDataTablePage.clickOnJsonColumn(2); + notificationPage.checkNotifyContains('Text copied to clipboard'); + copyContentDataTablePage.pasteClipboard(); + expect(copyContentDataTablePage.getClipboardInputText()).toContain(jsonValue); + }); }); }); diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index a8310c56cf..4b263f7524 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -651,7 +651,7 @@ export class ContentServicesPage { } checkRowIsDisplayed(rowName) { - const row = this.contentList.dataTablePage().getRowElement('Display name', rowName); + const row = this.contentList.dataTablePage().getCellElementByValue('Display name', rowName); BrowserVisibility.waitUntilElementIsVisible(row); } diff --git a/e2e/pages/adf/demo-shell/customSourcesPage.ts b/e2e/pages/adf/demo-shell/customSourcesPage.ts index 95b4db8895..a989e867bf 100644 --- a/e2e/pages/adf/demo-shell/customSourcesPage.ts +++ b/e2e/pages/adf/demo-shell/customSourcesPage.ts @@ -71,7 +71,7 @@ export class CustomSources { } getStatusCell(rowName) { - const cell = this.dataTable.getCellByRowAndColumn('Name', rowName, column.status); + const cell = this.dataTable.getCellByRowContentAndColumn('Name', rowName, column.status); BrowserVisibility.waitUntilElementIsVisible(cell); return cell.getText(); } diff --git a/e2e/pages/adf/demo-shell/dataTablePage.ts b/e2e/pages/adf/demo-shell/dataTablePage.ts index bfe30ac248..2f9877b713 100644 --- a/e2e/pages/adf/demo-shell/dataTablePage.ts +++ b/e2e/pages/adf/demo-shell/dataTablePage.ts @@ -24,7 +24,8 @@ export class DataTablePage { columns = { id: 'Id', name: 'Name', - createdBy: 'Created By' + createdBy: 'Created By', + json: 'Json' }; data = { @@ -66,7 +67,7 @@ export class DataTablePage { } replaceRows(id) { - const rowID = this.dataTable.getRowElement(this.columns.id, id); + const rowID = this.dataTable.getCellElementByValue(this.columns.id, id); BrowserVisibility.waitUntilElementIsVisible(rowID); this.replaceRowsElement.click(); BrowserVisibility.waitUntilElementIsNotVisible(rowID); @@ -89,7 +90,7 @@ export class DataTablePage { } checkRowIsNotSelected(rowNumber) { - const isRowSelected = this.dataTable.getRowElement(this.columns.id, rowNumber) + const isRowSelected = this.dataTable.getCellElementByValue(this.columns.id, rowNumber) .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row custom-row-style ng-star-inserted is-selected')]`)); BrowserVisibility.waitUntilElementIsNotOnPage(isRowSelected); } @@ -116,13 +117,14 @@ export class DataTablePage { } clickCheckbox(rowNumber) { - const checkbox = this.dataTable.getRowElement(this.columns.id, rowNumber).element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); + const checkbox = this.dataTable.getCellElementByValue(this.columns.id, rowNumber) + .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]//mat-checkbox/label`)); BrowserVisibility.waitUntilElementIsVisible(checkbox); checkbox.click(); } selectRow(rowNumber) { - const locator = this.dataTable.getRowElement(this.columns.id, rowNumber); + const locator = this.dataTable.getCellElementByValue(this.columns.id, rowNumber); BrowserVisibility.waitUntilElementIsVisible(locator); BrowserVisibility.waitUntilElementIsClickable(locator); locator.click(); @@ -130,7 +132,7 @@ export class DataTablePage { } selectRowWithKeyboard(rowNumber) { - const row = this.dataTable.getRowElement(this.columns.id, rowNumber); + const row = this.dataTable.getCellElementByValue(this.columns.id, rowNumber); browser.actions().sendKeys(protractor.Key.COMMAND).click(row).perform(); } @@ -142,7 +144,7 @@ export class DataTablePage { } getRowCheckbox(rowNumber) { - return this.dataTable.getRowElement(this.columns.id, rowNumber).element(by.xpath(`ancestor::div/div/mat-checkbox[contains(@class, 'mat-checkbox-checked')]`)); + return this.dataTable.getCellElementByValue(this.columns.id, rowNumber).element(by.xpath(`ancestor::div/div/mat-checkbox[contains(@class, 'mat-checkbox-checked')]`)); } getCopyContentTooltip() { @@ -161,10 +163,18 @@ export class DataTablePage { return this.dataTable.mouseOverColumn(this.columns.id, name); } + mouseOverJsonColumn(rowNumber) { + return this.dataTable.mouseOverElement(this.dataTable.getCellByRowNumberAndColumnName(rowNumber - 1, this.columns.json)); + } + clickOnIdColumn(name) { return this.dataTable.clickColumn(this.columns.id, name); } + clickOnJsonColumn(rowNumber) { + return this.dataTable.clickElement(this.dataTable.getCellByRowNumberAndColumnName(rowNumber - 1, this.columns.json)); + } + clickOnNameColumn(name) { return this.dataTable.clickColumn(this.columns.name, name); } diff --git a/e2e/pages/adf/permissionsPage.ts b/e2e/pages/adf/permissionsPage.ts index f83c766852..284eb8271c 100644 --- a/e2e/pages/adf/permissionsPage.ts +++ b/e2e/pages/adf/permissionsPage.ts @@ -119,7 +119,7 @@ export class PermissionsPage { } getRoleCellValue(rowName) { - const locator = new DataTableComponentPage().getCellByRowAndColumn('Authority ID', rowName, column.role); + const locator = new DataTableComponentPage().getCellByRowContentAndColumn('Authority ID', rowName, column.role); BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getText(); } diff --git a/e2e/pages/adf/searchResultsPage.ts b/e2e/pages/adf/searchResultsPage.ts index 846876a027..e39e792011 100644 --- a/e2e/pages/adf/searchResultsPage.ts +++ b/e2e/pages/adf/searchResultsPage.ts @@ -29,7 +29,7 @@ export class SearchResultsPage { contentServices = new ContentServicesPage(); getNodeHighlight(content) { - return this.dataTable.getCellByRowAndColumn('Display name', content, 'Search'); + return this.dataTable.getCellByRowContentAndColumn('Display name', content, 'Search'); } tableIsLoaded() { diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index f1d25f0b22..71b6ccd003 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -159,8 +159,7 @@ [tooltip]="getCellTooltip(row, col)"> </adf-datatable-cell> </div> - <div *ngSwitchCase="'json'" class="adf-cell-value" - [attr.data-automation-id]="'text_' + data.getValue(row, col)"> + <div *ngSwitchCase="'json'" class="adf-cell-value"> <adf-json-cell [copyContent]="col.copyContent" [data]="data" diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index 61d9b07bb2..adbcf25dfe 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -102,13 +102,13 @@ export class DataTableComponentPage { } checkRowIsSelected(columnName, columnValue) { - const selectedRow = this.getRowElement(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + const selectedRow = this.getCellElementByValue(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); BrowserVisibility.waitUntilElementIsVisible(selectedRow); return this; } checkRowIsNotSelected(columnName, columnValue) { - const selectedRow = this.getRowElement(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); + const selectedRow = this.getCellElementByValue(columnName, columnValue).element(by.xpath(`ancestor::div[contains(@class, 'is-selected')]`)); BrowserVisibility.waitUntilElementIsNotOnPage(selectedRow); return this; } @@ -155,7 +155,7 @@ export class DataTableComponentPage { } getTooltip(columnName, columnValue) { - return this.getRowElement(columnName, columnValue).getAttribute('title'); + return this.getCellElementByValue(columnName, columnValue).getAttribute('title'); } getFileHyperlink(filename) { @@ -226,22 +226,17 @@ export class DataTableComponentPage { } checkContentIsDisplayed(columnName, columnValue) { - const row = this.getRowElement(columnName, columnValue); + const row = this.getCellElementByValue(columnName, columnValue); BrowserVisibility.waitUntilElementIsVisible(row); return this; } checkContentIsNotDisplayed(columnName, columnValue) { - const row = this.getRowElement(columnName, columnValue); + const row = this.getCellElementByValue(columnName, columnValue); BrowserVisibility.waitUntilElementIsNotOnPage(row); return this; } - contentInPosition(position) { - BrowserVisibility.waitUntilElementIsVisible(this.contents); - return this.contents.get(position - 1).getText(); - } - getRow(columnName, columnValue) { const row = this.rootElement.all(by.css(`div[title="${columnName}"] div[data-automation-id="text_${columnValue}"]`)).first() .element(by.xpath(`ancestor::div[contains(@class, 'adf-datatable-row')]`)); @@ -249,7 +244,12 @@ export class DataTableComponentPage { return row; } - getRowElement(columnName, columnValue) { + contentInPosition(position) { + BrowserVisibility.waitUntilElementIsVisible(this.contents); + return this.contents.get(position - 1).getText(); + } + + getCellElementByValue(columnName, columnValue) { return this.rootElement.all(by.css(`div[title="${columnName}"] div[data-automation-id="text_${columnValue}"] span`)).first(); } @@ -281,7 +281,11 @@ export class DataTableComponentPage { return this.list.count(); } - getCellByRowAndColumn(rowColumn, rowContent, columnName) { + getCellByRowNumberAndColumnName(rowNumber, columnName) { + return this.list.get(rowNumber).element(by.css(`div[title="${columnName}"] span`)); + } + + getCellByRowContentAndColumn(rowColumn, rowContent, columnName) { return this.getRow(rowColumn, rowContent).element(by.css(`div[title='${columnName}']`)); } @@ -320,17 +324,27 @@ export class DataTableComponentPage { } mouseOverColumn(columnName, columnValue) { - const column = this.getRowElement(columnName, columnValue); - BrowserVisibility.waitUntilElementIsVisible(column); - browser.actions().mouseMove(column).perform(); + const column = this.getCellElementByValue(columnName, columnValue); + this.mouseOverElement(column); + return this; + } + + mouseOverElement(elem) { + BrowserVisibility.waitUntilElementIsVisible(elem); + browser.actions().mouseMove(elem).perform(); return this; } clickColumn(columnName, columnValue) { - const column = this.getRowElement(columnName, columnValue); - BrowserVisibility.waitUntilElementIsVisible(column); - BrowserVisibility.waitUntilElementIsClickable(column); - column.click(); + const column = this.getCellElementByValue(columnName, columnValue); + this.clickElement(column); + return this; + } + + clickElement(elem) { + BrowserVisibility.waitUntilElementIsVisible(elem); + BrowserVisibility.waitUntilElementIsClickable(elem); + elem.click(); return this; } } diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts index a795d691f6..c0cf818f0e 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts @@ -67,7 +67,7 @@ export class TaskListCloudComponentPage { } getRow(taskName) { - return this.dataTable.getRowElement('Name', taskName); + return this.dataTable.getCellElementByValue('Name', taskName); } checkContentIsDisplayedByProcessInstanceId(taskName) { @@ -105,7 +105,7 @@ export class TaskListCloudComponentPage { } getIdCellValue(rowName) { - const locator = new DataTableComponentPage().getCellByRowAndColumn('Name', rowName, column.id); + const locator = new DataTableComponentPage().getCellByRowContentAndColumn('Name', rowName, column.id); BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getText(); } From 64391a48fa8b4cb0681e31decf543a006907fc74 Mon Sep 17 00:00:00 2001 From: dhrn <14145706+dhrn@users.noreply.github.com> Date: Tue, 23 Apr 2019 04:13:10 +0530 Subject: [PATCH 138/208] [ADF-4406] - Confirm Dialog doesn't support a third extra button option to be customised (#4608) * [ADF-4406] - Confirm Dialog doesn't support a third extra button option to be customised * * comments fixed * * docs and test added --- .../confirm-dialog-example.component.html | 11 ++++++ .../confirm-dialog-example.component.ts | 18 ++++++++++ .../dialogs/confirm.dialog.md | 32 ++++++++++++++++++ docs/docassets/images/ConfirmDialogYesAll.png | Bin 0 -> 8611 bytes .../dialogs/confirm.dialog.html | 1 + .../dialogs/confirm.dialog.spec.ts | 24 +++++++++++++ .../dialogs/confirm.dialog.ts | 3 ++ 7 files changed, 89 insertions(+) create mode 100644 docs/docassets/images/ConfirmDialogYesAll.png diff --git a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html index 8aa5bc2bce..dbe74d3a79 100644 --- a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html +++ b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.html @@ -15,4 +15,15 @@ </mat-expansion-panel-header> <button mat-raised-button (click)="openConfirmCustomDialog()">Open Custom Dialog</button> </mat-expansion-panel> + <mat-expansion-panel> + <mat-expansion-panel-header> + <mat-panel-title> + Confirm Dialog Third Option + </mat-panel-title> + <mat-panel-description> + Provide extra button in the action section + </mat-panel-description> + </mat-expansion-panel-header> + <button mat-raised-button (click)="openConfirmCustomActionDialog()">Open Custom Dialog</button> + </mat-expansion-panel> </mat-accordion> diff --git a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts index 66dc79ce91..8fb305700e 100644 --- a/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts +++ b/demo-shell/src/app/components/confirm-dialog/confirm-dialog-example.component.ts @@ -48,4 +48,22 @@ export class ConfirmDialogExampleComponent { minWidth: '250px' }); } + + openConfirmCustomActionDialog() { + const thirdOptionLabel = 'Yes. Don\'t Show it again'; + const dialog = this.dialog.open(ConfirmDialogComponent, { + data: { + title: 'Upload', + thirdOptionLabel: thirdOptionLabel, + message: `This is the default message` + }, + minWidth: '250px' + }); + dialog.afterClosed().subscribe((status) => { + // do the third option label operation + if ( status === thirdOptionLabel) { + // console.log('third option clicked'); + } + }); + } } diff --git a/docs/content-services/dialogs/confirm.dialog.md b/docs/content-services/dialogs/confirm.dialog.md index 5c5a4e7e45..e6e5cae879 100644 --- a/docs/content-services/dialogs/confirm.dialog.md +++ b/docs/content-services/dialogs/confirm.dialog.md @@ -10,7 +10,19 @@ Last reviewed: 2019-01-22 Requests a yes/no choice from the user. ![Confirm dialog](../../docassets/images/ConfirmDialog.png) +![Confirm dialog](../../docassets/images/ConfirmDialogYesAll.png) +## Dialog inputs +| Name | Type | Default value | Description | +| ---- | ---- | ---- | ----------- | +| title | `string` | `Confirm` | It will be placed in the dialog title section. | +| yesLabel | `string` | `yes` | It will be placed first in the dialog action section | +| noLabel | `string` | `no`| It will be placed last in the dialog action section | +| thirdOptionLabel (optional) | `string` | | It is not a mandatory input. it will be rendered in between yes and no label | +| message | `string` | `Do you want to proceed?` | It will be rendered in the dialog content area | +| htmlContent | `html` | | It will be rendered in the dialog content area | + +*note*: `if input is not passed, default value will be rendered` ## Basic Usage ```ts @@ -65,6 +77,26 @@ dialogRef.afterClosed().subscribe((result) => { }); ``` +### Rendering with thirdOptionLabel + +``` + const thirdOptionLabel = "YES. DON'T SHOW IT AGAIN"; + const dialog = this.dialog.open(ConfirmDialogComponent, { + data: { + title: 'Upload', + thirdOptionLabel: thirdOptionLabel, + message: `This is the default message` + }, + minWidth: '250px' + }); + dialog.afterClosed().subscribe((status) => { + // do the third option label operation + if ( status === thirdOptionLabel) { + // console.log('third option clicked'); + } + }); +``` + ## Details This component lets the user make a yes/no choice to confirm an action. Use the diff --git a/docs/docassets/images/ConfirmDialogYesAll.png b/docs/docassets/images/ConfirmDialogYesAll.png new file mode 100644 index 0000000000000000000000000000000000000000..d90c06aee7ae63989aea96983c6dc49a6beb401f GIT binary patch literal 8611 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 literal 0 HcmV?d00001 diff --git a/lib/content-services/dialogs/confirm.dialog.html b/lib/content-services/dialogs/confirm.dialog.html index 0d7869e587..5ffd7cbd6b 100644 --- a/lib/content-services/dialogs/confirm.dialog.html +++ b/lib/content-services/dialogs/confirm.dialog.html @@ -12,6 +12,7 @@ <span class="adf-dialog-spacer" data-automation-id="adf-confirm-dialog-spacer"></span> <button id="adf-confirm-accept" mat-button color="primary" data-automation-id="adf-confirm-dialog-confirmation" [mat-dialog-close]="true">{{ yesLabel | translate }}</button> + <button id="adf-confirm-all" mat-button *ngIf="thirdOptionLabel" [mat-dialog-close]="thirdOptionLabel" data-automation-id="adf-confirm-dialog-confirm-all">{{ thirdOptionLabel | translate }}</button> <button id="adf-confirm-cancel" mat-button [mat-dialog-close]="false" data-automation-id="adf-confirm-dialog-reject" cdkFocusInitial>{{ noLabel | translate }}</button> </mat-dialog-actions> diff --git a/lib/content-services/dialogs/confirm.dialog.spec.ts b/lib/content-services/dialogs/confirm.dialog.spec.ts index dba5684748..5c5d92c6a7 100644 --- a/lib/content-services/dialogs/confirm.dialog.spec.ts +++ b/lib/content-services/dialogs/confirm.dialog.spec.ts @@ -26,6 +26,7 @@ import { By } from '@angular/platform-browser'; describe('Confirm Dialog Component', () => { let fixture: ComponentFixture<ConfirmDialogComponent>; let component: ConfirmDialogComponent; + const dialogRef = { close: jasmine.createSpy('close') }; @@ -140,4 +141,27 @@ describe('Confirm Dialog Component', () => { expect(messageElement.nativeElement.innerText).toBe('MAYBE NO'); }); }); + + describe('thirdOptionLabel is given', () => { + + it('should NOT render the thirdOption if is thirdOptionLabel is not passed', () => { + component.thirdOptionLabel = undefined; + fixture.detectChanges(); + const thirdOptionElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-confirm-all"]') + ); + expect(thirdOptionElement).toBeFalsy(); + }); + + it('should render the thirdOption if thirdOptionLabel is passed', () => { + component.thirdOptionLabel = 'Yes All'; + fixture.detectChanges(); + const thirdOptionElement = fixture.debugElement.query( + By.css('[data-automation-id="adf-confirm-dialog-confirm-all"]') + ); + expect(thirdOptionElement).not.toBeNull(); + expect(thirdOptionElement.nativeElement.innerText).toBe('YES ALL'); + }); + }); + }); diff --git a/lib/content-services/dialogs/confirm.dialog.ts b/lib/content-services/dialogs/confirm.dialog.ts index b2ffef01ac..5e385abac5 100644 --- a/lib/content-services/dialogs/confirm.dialog.ts +++ b/lib/content-services/dialogs/confirm.dialog.ts @@ -32,6 +32,7 @@ export class ConfirmDialogComponent { message: string; yesLabel: string; noLabel: string; + thirdOptionLabel: string; htmlContent: string; constructor(@Inject(MAT_DIALOG_DATA) data, private sanitizer: DomSanitizer) { @@ -39,6 +40,7 @@ export class ConfirmDialogComponent { this.title = data.title || 'ADF_CONFIRM_DIALOG.CONFIRM'; this.message = data.message || 'ADF_CONFIRM_DIALOG.MESSAGE'; this.yesLabel = data.yesLabel || 'ADF_CONFIRM_DIALOG.YES_LABEL'; + this.thirdOptionLabel = data.thirdOptionLabel; this.noLabel = data.noLabel || 'ADF_CONFIRM_DIALOG.NO_LABEL'; this.htmlContent = data.htmlContent; } @@ -46,4 +48,5 @@ export class ConfirmDialogComponent { public sanitizedHtmlContent() { return this.sanitizer.sanitize(SecurityContext.HTML, this.htmlContent); } + } From df2644770184fd060cd3726a24ac46aa3d1f0ec0 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Tue, 23 Apr 2019 00:58:26 +0200 Subject: [PATCH 139/208] Revert "[ADF-4359] - Add the possibility to chose wich panel to show first in info-drawer (#4632)" (#4637) This reverts commit 6e4adfb09a37caaaf98daab4d7c3cf68ade361c5. --- .../file-view/file-view.component.html | 17 +---- .../file-view/file-view.component.ts | 6 -- .../content-metadata-card.component.md | 1 - .../content-metadata-card.component.html | 1 - .../content-metadata-card.component.spec.ts | 14 ---- .../content-metadata-card.component.ts | 16 +--- .../content-metadata.component.html | 6 +- .../content-metadata.component.spec.ts | 74 +------------------ .../content-metadata.component.ts | 8 -- .../components/content-metadata/mock-data.ts | 74 ------------------- 10 files changed, 8 insertions(+), 209 deletions(-) delete mode 100644 lib/content-services/content-metadata/components/content-metadata/mock-data.ts diff --git a/demo-shell/src/app/components/file-view/file-view.component.html b/demo-shell/src/app/components/file-view/file-view.component.html index d14163bbaf..c2586757cd 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.html +++ b/demo-shell/src/app/components/file-view/file-view.component.html @@ -12,14 +12,12 @@ [multi]="multi" [preset]="customPreset" [readOnly]="isReadOnly" - [displayAspect]="showAspect" [displayDefaultProperties]="displayDefaultProperties" [displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card> <adf-content-metadata-card *ngIf="!isPreset" [node]="node" [multi]="multi" [readOnly]="isReadOnly" - [displayAspect]="showAspect" [displayDefaultProperties]="displayDefaultProperties" [displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card> @@ -73,19 +71,6 @@ </mat-slide-toggle> </p> - <p class="toggle"> - - <mat-form-field floatPlaceholder="float"> - <input matInput - placeholder="Display Aspect" - [(ngModel)]="desiredAspect"> - </mat-form-field> - - <button mat-raised-button (click)="applyAspect()" color="primary"> - Apply Aspect - </button> - </p> - <p class="toggle"> <ng-container *ngIf="isPreset"> <mat-form-field floatPlaceholder="float"> @@ -133,7 +118,7 @@ <p class="toggle"> <ng-container *ngIf="customName"> - <mat-form-field floatLabel="never"> + <mat-form-field floatPlaceholder="float"> <input matInput placeholder="Custom Name" [(ngModel)]="displayName" diff --git a/demo-shell/src/app/components/file-view/file-view.component.ts b/demo-shell/src/app/components/file-view/file-view.component.ts index e5b4187f87..f014d8fca0 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.ts +++ b/demo-shell/src/app/components/file-view/file-view.component.ts @@ -55,8 +55,6 @@ export class FileViewComponent implements OnInit { isCommentEnabled = false; showTabWithIcon = false; showTabWithIconAndLabel = false; - desiredAspect: string = null; - showAspect: string = null; constructor(private router: Router, private route: ActivatedRoute, @@ -190,8 +188,4 @@ export class FileViewComponent implements OnInit { this.isPreset = true; }, 100); } - - applyAspect() { - this.showAspect = this.desiredAspect; - } } diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index c280ae6f69..773ed6b807 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -34,7 +34,6 @@ Displays and edits metadata related to a node. | preset | `string` | | (required) Name of the metadata preset, which defines aspects and their properties. | | readOnly | `boolean` | false | (optional) This flag sets the metadata in read only mode preventing changes. | | displayDefaultProperties | `boolean` | | (optional) This flag displays/hides the metadata properties. | -| displayAspect | `string` | | (optional) This flag displays the desired metadata property in the expanded card | ## Details diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html index 6369ce8268..07068fd23f 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html @@ -7,7 +7,6 @@ [displayEmpty]="displayEmpty" [editable]="editable" [multi]="multi" - [displayAspect]="displayAspect" [preset]="preset"> </adf-content-metadata> </mat-card-content> diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts index 0e5bb7ab4f..7c1f730fa1 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts @@ -22,7 +22,6 @@ import { ContentMetadataCardComponent } from './content-metadata-card.component' import { ContentMetadataComponent } from '../content-metadata/content-metadata.component'; import { setupTestBed, AllowableOperationsEnum } from '@alfresco/adf-core'; import { ContentTestingModule } from '../../../testing/content.testing.module'; -import { SimpleChange } from '@angular/core'; describe('ContentMetadataCardComponent', () => { @@ -190,17 +189,4 @@ describe('ContentMetadataCardComponent', () => { const button = fixture.debugElement.query(By.css('[data-automation-id="meta-data-card-toggle-edit"]')); expect(button).not.toBeNull(); }); - - it('should expand the card when custom display aspect is valid', () => { - expect(component.expanded).toBeFalsy(); - - let displayAspect = new SimpleChange(null , 'EXIF', true); - component.ngOnChanges({ displayAspect }); - expect(component.expanded).toBeTruthy(); - - displayAspect = new SimpleChange('EXIF' , null, false); - component.ngOnChanges({ displayAspect }); - expect(component.expanded).toBeTruthy(); - }); - }); diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts index ddd2f99577..54084f0db3 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { Component, Input, ViewEncapsulation } from '@angular/core'; import { Node } from '@alfresco/js-api'; import { ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; @@ -26,7 +26,7 @@ import { ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; encapsulation: ViewEncapsulation.None, host: { 'class': 'adf-content-metadata-card' } }) -export class ContentMetadataCardComponent implements OnChanges { +export class ContentMetadataCardComponent { /** (required) The node entity to fetch metadata about */ @Input() node: Node; @@ -37,12 +37,6 @@ export class ContentMetadataCardComponent implements OnChanges { @Input() displayEmpty: boolean = false; - /** (optional) This flag displays desired aspect when open for the first time - * fields. - */ - @Input() - displayAspect: string = null; - /** (required) Name of the metadata preset, which defines aspects * and their properties. */ @@ -83,12 +77,6 @@ export class ContentMetadataCardComponent implements OnChanges { constructor(private contentService: ContentService) { } - ngOnChanges(changes: SimpleChanges): void { - if (changes.displayAspect && changes.displayAspect.currentValue) { - this.expanded = true; - } - } - onDisplayDefaultPropertiesChange(): void { this.expanded = !this._displayDefaultProperties; } diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html index 8f4876110a..e1c344b2c9 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html @@ -2,8 +2,8 @@ <mat-accordion displayMode="flat" [multi]="multi"> <mat-expansion-panel *ngIf="displayDefaultProperties" - [expanded]="!expanded || !displayAspect" - [hideToggle]="!expanded || !displayAspect" + [expanded]="!expanded" + [hideToggle]="!expanded" [attr.data-automation-id]="'adf-metadata-group-properties'" > <mat-expansion-panel-header> <mat-panel-title> @@ -23,7 +23,7 @@ <div *ngFor="let group of groupedProperties; let first = first;" class="adf-metadata-grouped-properties-container"> <mat-expansion-panel *ngIf="showGroup(group) || editable" [attr.data-automation-id]="'adf-metadata-group-' + group.title" - [expanded]="canExpandTheCard(group) || !displayDefaultProperties && first"> + [expanded]="!displayDefaultProperties && first"> <mat-expansion-panel-header> <mat-panel-title> {{ group.title | translate }} diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts index a3fe638500..ac6bfd0dec 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -27,12 +27,10 @@ import { } from '@alfresco/adf-core'; import { throwError, of } from 'rxjs'; import { ContentTestingModule } from '../../../testing/content.testing.module'; -import { mockGroupProperties } from './mock-data'; describe('ContentMetadataComponent', () => { let component: ContentMetadataComponent; let fixture: ComponentFixture<ContentMetadataComponent>; - let contentMetadataService: ContentMetadataService; let node: Node; let folderNode: Node; const preset = 'custom-preset'; @@ -45,7 +43,6 @@ describe('ContentMetadataComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ContentMetadataComponent); component = fixture.componentInstance; - contentMetadataService = TestBed.get(ContentMetadataService); node = <Node> { id: 'node-id', aspectNames: [], @@ -150,10 +147,11 @@ describe('ContentMetadataComponent', () => { }); describe('Properties loading', () => { - let expectedNode; + let expectedNode, contentMetadataService: ContentMetadataService; beforeEach(() => { expectedNode = Object.assign({}, node, { name: 'some-modified-value' }); + contentMetadataService = TestBed.get(ContentMetadataService); fixture.detectChanges(); }); @@ -296,72 +294,4 @@ describe('ContentMetadataComponent', () => { expect(component.displayDefaultProperties).toBe(true); }); }); - - describe('Expand the panel', () => { - let expectedNode; - - beforeEach(() => { - expectedNode = Object.assign({}, node, {name: 'some-modified-value'}); - spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of(mockGroupProperties)); - component.ngOnChanges({node: new SimpleChange(node, expectedNode, false)}); - }); - - it('should open and update drawer with expand section dynamically', async(() => { - component.displayAspect = 'EXIF'; - component.expanded = true; - component.displayEmpty = true; - - fixture.detectChanges(); - const defaultProp = queryDom(fixture); - const exifProp = queryDom(fixture, 'EXIF'); - const customProp = queryDom(fixture, 'CUSTOM'); - expect(defaultProp.componentInstance.expanded).toBeFalsy(); - expect(exifProp.componentInstance.expanded).toBeTruthy(); - expect(customProp.componentInstance.expanded).toBeFalsy(); - - component.displayAspect = 'CUSTOM'; - fixture.detectChanges(); - const updatedDefault = queryDom(fixture); - const updatedExif = queryDom(fixture, 'EXIF'); - const updatedCustom = queryDom(fixture, 'CUSTOM'); - expect(updatedDefault.componentInstance.expanded).toBeFalsy(); - expect(updatedExif.componentInstance.expanded).toBeFalsy(); - expect(updatedCustom.componentInstance.expanded).toBeTruthy(); - - })); - - it('should not expand anything if input is wrong', async(() => { - component.displayAspect = 'XXXX'; - component.expanded = true; - component.displayEmpty = true; - - fixture.detectChanges(); - const defaultProp = queryDom(fixture); - const exifProp = queryDom(fixture, 'EXIF'); - const customProp = queryDom(fixture, 'CUSTOM'); - expect(defaultProp.componentInstance.expanded).toBeFalsy(); - expect(exifProp.componentInstance.expanded).toBeFalsy(); - expect(customProp.componentInstance.expanded).toBeFalsy(); - - })); - - it('should expand the properties section when input is null', async(() => { - component.displayAspect = null; - component.expanded = true; - component.displayEmpty = true; - - fixture.detectChanges(); - const defaultProp = queryDom(fixture); - const exifProp = queryDom(fixture, 'EXIF'); - const customProp = queryDom(fixture, 'CUSTOM'); - expect(defaultProp.componentInstance.expanded).toBeTruthy(); - expect(exifProp.componentInstance.expanded).toBeFalsy(); - expect(customProp.componentInstance.expanded).toBeFalsy(); - - })); - }); }); - -function queryDom(fixture: ComponentFixture<ContentMetadataComponent>, properties: string = 'properties') { - return fixture.debugElement.query(By.css(`[data-automation-id="adf-metadata-group-${properties}"]`)); -} diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts index b6d769cafb..d3c4004263 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts @@ -61,10 +61,6 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { @Input() displayDefaultProperties: boolean = true; - /** (Optional) shows the given aspect in the expanded card */ - @Input() - displayAspect: string = null; - basicProperties$: Observable<CardViewItem[]>; groupedProperties$: Observable<CardViewGroup[]>; disposableNodeUpdate: Subscription; @@ -122,8 +118,4 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { this.disposableNodeUpdate.unsubscribe(); } - public canExpandTheCard(group: CardViewGroup): boolean { - return group.title === this.displayAspect; - } - } diff --git a/lib/content-services/content-metadata/components/content-metadata/mock-data.ts b/lib/content-services/content-metadata/components/content-metadata/mock-data.ts deleted file mode 100644 index 4ea3974bcd..0000000000 --- a/lib/content-services/content-metadata/components/content-metadata/mock-data.ts +++ /dev/null @@ -1,74 +0,0 @@ -/*! - * @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. - */ - -export const mockGroupProperties = [ - { - 'title': 'EXIF', - 'properties': [ - { - 'label': 'Image Width', - 'value': 363, - 'key': 'properties.exif:pixelXDimension', - 'default': null, - 'editable': true, - 'clickable': false, - 'icon': '', - 'data': null, - 'type': 'int', - 'multiline': false, - 'pipes': [], - 'clickCallBack': null, - displayValue: 400 - }, - { - 'label': 'Image Height', - 'value': 400, - 'key': 'properties.exif:pixelYDimension', - 'default': null, - 'editable': true, - 'clickable': false, - 'icon': '', - 'data': null, - 'type': 'int', - 'multiline': false, - 'pipes': [], - 'clickCallBack': null, - displayValue: 400 - } - ] - }, - { - 'title': 'CUSTOM', - 'properties': [ - { - 'label': 'Height', - 'value': 400, - 'key': 'properties.custom:abc', - 'default': null, - 'editable': true, - 'clickable': false, - 'icon': '', - 'data': null, - 'type': 'int', - 'multiline': false, - 'pipes': [], - 'clickCallBack': null, - displayValue: 400 - } - ] - } -]; From 5c67547fd6214ace6f113a56a82b9f2e0adc23da Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 23 Apr 2019 00:01:30 +0100 Subject: [PATCH 140/208] move metadata test in content service where they has to be --- .../metadata}/aspect-oriented-config.e2e.ts | 0 .../metadata}/metadata-permissions.e2e.ts | 0 .../metadata}/metadata-properties.e2e.ts | 0 .../metadata}/metadata-smoke-tests.e2e.ts | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename e2e/{core/card-view => content-services/metadata}/aspect-oriented-config.e2e.ts (100%) rename e2e/{core/card-view => content-services/metadata}/metadata-permissions.e2e.ts (100%) rename e2e/{core/card-view => content-services/metadata}/metadata-properties.e2e.ts (100%) rename e2e/{core/card-view => content-services/metadata}/metadata-smoke-tests.e2e.ts (100%) diff --git a/e2e/core/card-view/aspect-oriented-config.e2e.ts b/e2e/content-services/metadata/aspect-oriented-config.e2e.ts similarity index 100% rename from e2e/core/card-view/aspect-oriented-config.e2e.ts rename to e2e/content-services/metadata/aspect-oriented-config.e2e.ts diff --git a/e2e/core/card-view/metadata-permissions.e2e.ts b/e2e/content-services/metadata/metadata-permissions.e2e.ts similarity index 100% rename from e2e/core/card-view/metadata-permissions.e2e.ts rename to e2e/content-services/metadata/metadata-permissions.e2e.ts diff --git a/e2e/core/card-view/metadata-properties.e2e.ts b/e2e/content-services/metadata/metadata-properties.e2e.ts similarity index 100% rename from e2e/core/card-view/metadata-properties.e2e.ts rename to e2e/content-services/metadata/metadata-properties.e2e.ts diff --git a/e2e/core/card-view/metadata-smoke-tests.e2e.ts b/e2e/content-services/metadata/metadata-smoke-tests.e2e.ts similarity index 100% rename from e2e/core/card-view/metadata-smoke-tests.e2e.ts rename to e2e/content-services/metadata/metadata-smoke-tests.e2e.ts From fafe80c021af6b0270094d3a72a8b8aa7d1017a4 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 23 Apr 2019 00:14:08 +0100 Subject: [PATCH 141/208] less common priority value --- .../task-list-properties.e2e.ts | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index c5663f6efc..a586447fda 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -17,10 +17,12 @@ import TestConfig = require('../test.config'); -import { StringUtil, TasksService, - ProcessDefinitionsService, ProcessInstancesService, - LoginSSOPage, ApiService, - SettingsPage, AppListCloudPage, LocalStorageUtil } from '@alfresco/adf-testing'; +import { + StringUtil, TasksService, + ProcessDefinitionsService, ProcessInstancesService, + LoginSSOPage, ApiService, + SettingsPage, AppListCloudPage, LocalStorageUtil +} from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { TaskListCloudConfiguration } from './taskListCloud.config'; @@ -96,11 +98,11 @@ describe('Edit task filters and task list properties', () => { const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); - tasksService = new TasksService(apiService); + tasksService = new TasksService(apiService); createdTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); await tasksService.claimTask(createdTask.entry.id, simpleApp); notAssigned = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); - priorityTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp, {priority: priority}); + priorityTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp, { priority: priority }); await tasksService.claimTask(priorityTask.entry.id, simpleApp); notDisplayedTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateUserApp); await tasksService.claimTask(notDisplayedTask.entry.id, candidateUserApp); @@ -218,7 +220,7 @@ describe('Edit task filters and task list properties', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); - tasksCloudDemoPage.editTaskFilterCloudComponent().setPriority('70'); + tasksCloudDemoPage.editTaskFilterCloudComponent().setPriority('700'); expect(tasksCloudDemoPage.taskListCloudComponent().getNoTasksFoundMessage()).toEqual(noTasksFoundMessage); }); @@ -247,7 +249,7 @@ describe('Edit task filters and task list properties', () => { expect(tasksCloudDemoPage.taskListCloudComponent().getNoTasksFoundMessage()).toEqual(noTasksFoundMessage); }); - it('[C297484] Task is displayed when typing into lastModifiedFrom field a date before the task CreatedDate', function () { + it('[C297484] Task is displayed when typing into lastModifiedFrom field a date before the task CreatedDate', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -258,7 +260,7 @@ describe('Edit task filters and task list properties', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(createdTask.entry.name); }); - it('[C297689] Task is not displayed when typing into lastModifiedFrom field the same date as tasks CreatedDate', function () { + it('[C297689] Task is not displayed when typing into lastModifiedFrom field the same date as tasks CreatedDate', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -266,7 +268,7 @@ describe('Edit task filters and task list properties', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(createdTask.entry.name); }); - it('[C297485] Task is displayed when typing into lastModifiedTo field a date after the task CreatedDate', function () { + it('[C297485] Task is displayed when typing into lastModifiedTo field a date after the task CreatedDate', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -277,7 +279,7 @@ describe('Edit task filters and task list properties', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(createdTask.entry.name); }); - it('[C297690] Task is not displayed when typing into lastModifiedTo field the same date as tasks CreatedDate', function () { + it('[C297690] Task is not displayed when typing into lastModifiedTo field the same date as tasks CreatedDate', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -286,7 +288,7 @@ describe('Edit task filters and task list properties', () => { }); xit('[C297691] Task is not displayed when typing into lastModifiedFrom field a date before the task due date ' + - 'and into lastModifiedTo a date before task due date', function () { + 'and into lastModifiedTo a date before task due date', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -297,7 +299,7 @@ describe('Edit task filters and task list properties', () => { }); xit('[C297692] Task is displayed when typing into lastModifiedFrom field a date before the tasks due date ' + - 'and into lastModifiedTo a date after', function () { + 'and into lastModifiedTo a date after', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -308,7 +310,7 @@ describe('Edit task filters and task list properties', () => { }); it('[C297693] Task is not displayed when typing into lastModifiedFrom field a date after the tasks due date ' + - 'and into lastModifiedTo a date after', function () { + 'and into lastModifiedTo a date after', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); From 834c32f23f39910be7291faf174f2bcf26ba9463 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Tue, 23 Apr 2019 12:00:46 +0300 Subject: [PATCH 142/208] [ADF-4403] ClipboardDirective - add default translation key and fix styling (#4610) * [ADF-4403] ClipboardDirective - add default translation key and fix style on sticky header * [ADF-4403] - lint * [ADF-4403] - revert datatable style * [ADF-4403] - fix unit tests * [ADF-4403] - fix e2e tests --- lib/core/clipboard/clipboard.component.scss | 24 +++++++++++++++++++ .../clipboard/clipboard.directive.spec.ts | 8 +++---- lib/core/clipboard/clipboard.directive.ts | 13 ++++++---- .../datatable/datatable-cell.component.ts | 2 +- .../datatable/datatable.component.scss | 11 --------- lib/core/styles/_index.scss | 2 ++ .../task-list-cloud.component.spec.ts | 8 +++---- .../core/pages/data-table-component.page.ts | 2 +- 8 files changed, 45 insertions(+), 25 deletions(-) create mode 100644 lib/core/clipboard/clipboard.component.scss diff --git a/lib/core/clipboard/clipboard.component.scss b/lib/core/clipboard/clipboard.component.scss new file mode 100644 index 0000000000..1c42383b65 --- /dev/null +++ b/lib/core/clipboard/clipboard.component.scss @@ -0,0 +1,24 @@ +@mixin adf-clipboard-theme($theme) { + $primary: map-get($theme, primary); + $config: mat-typography-config(); + + .adf-copy-tooltip { + position: absolute; + background: mat-color($primary); + color: mat-color($primary, default-contrast) !important; + font-size: mat-font-size($config, caption); + padding: 2px 5px; + border-radius: 5px; + bottom: 93%; + left:0; + z-index: 1001; + min-height: 20px; + } + + .adf-sticky-header { + .adf-copy-tooltip { + top:85% !important; + bottom:0 !important; + } + } +} diff --git a/lib/core/clipboard/clipboard.directive.spec.ts b/lib/core/clipboard/clipboard.directive.spec.ts index e9a0e11906..6a39509516 100644 --- a/lib/core/clipboard/clipboard.directive.spec.ts +++ b/lib/core/clipboard/clipboard.directive.spec.ts @@ -72,7 +72,7 @@ describe('CopyClipboardDirective', () => { @Component({ selector: 'adf-copy-conent-test-component', - template: `<span adf-clipboard='DOCUMENT_LIST.ACTIONS.DOCUMENT.CLICK_TO_COPY'>{{ mockText }}</span>` + template: `<span adf-clipboard>{{ mockText }}</span>` }) class TestCopyClipboardComponent { @@ -105,16 +105,16 @@ describe('CopyClipboardDirective', () => { const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span'); spanHTMLElement.dispatchEvent(new Event('mouseenter')); fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull(); })); it('should not show tooltip when element it is not hovered', (() => { const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span'); spanHTMLElement.dispatchEvent(new Event('mouseenter')); - expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull(); spanHTMLElement.dispatchEvent(new Event('mouseleave')); - expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull(); })); it('should copy the content of element when click it', fakeAsync(() => { diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index 167fc08ac3..38c96ca255 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Directive, Input, HostListener, Component, ViewContainerRef, ComponentFactoryResolver, ViewEncapsulation } from '@angular/core'; +import { Directive, Input, HostListener, Component, ViewContainerRef, ComponentFactoryResolver, ViewEncapsulation, OnInit } from '@angular/core'; import { ClipboardService } from './clipboard.service'; @Directive({ @@ -75,12 +75,17 @@ export class ClipboardDirective { } @Component({ - selector: 'adf-datatable-copy-content-tooltip', + selector: 'adf-copy-content-tooltip', template: ` - <span class='adf-datatable-copy-tooltip'>{{ placeholder | translate }} </span> + <span class='adf-copy-tooltip'>{{ placeholder | translate }} </span> `, + styleUrls: ['./clipboard.component.scss'], encapsulation: ViewEncapsulation.None }) -export class ClipboardComponent { +export class ClipboardComponent implements OnInit { placeholder: string; + + ngOnInit() { + this.placeholder = this.placeholder || 'CLIPBOARD.CLICK_TO_COPY'; + } } diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index bac6b1c12d..ffb9d75a09 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -36,7 +36,7 @@ import { Node } from '@alfresco/js-api'; template: ` <ng-container> <span *ngIf="copyContent; else defaultCell" - adf-clipboard="CLIPBOARD.CLICK_TO_COPY" + adf-clipboard [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'" [attr.aria-label]="value$ | async" [title]="tooltip" diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index 025e973631..5a18be2796 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -558,15 +558,4 @@ } } } - - .adf-datatable-copy-tooltip { - position: absolute; - background: mat-color($primary); - color: mat-color($primary, default-contrast) !important; - padding: 5px 10px; - border-radius: 5px; - bottom: 94%; - left:0; - z-index: 20; - } } diff --git a/lib/core/styles/_index.scss b/lib/core/styles/_index.scss index 4ead278054..9a147e1647 100644 --- a/lib/core/styles/_index.scss +++ b/lib/core/styles/_index.scss @@ -32,6 +32,7 @@ @import '../buttons-menu/buttons-menu.component'; @import '../login/components/login-dialog.component'; @import '../login/components/login-dialog-panel.component'; +@import '../../core/clipboard/clipboard.component'; @mixin adf-core-theme($theme) { @include adf-colors-theme($theme); @@ -66,4 +67,5 @@ @include adf-login-dialog-theme($theme); @include adf-login-dialog-panel-theme($theme); @include adf-sidenav-layout-theme($theme); + @include adf-clipboard-theme($theme); } diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts index 909fbb9e94..c202ec6af7 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts @@ -288,7 +288,7 @@ describe('TaskListCloudComponent', () => { const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); spanHTMLElement.dispatchEvent(new Event('mouseenter')); copyFixture.detectChanges(); - expect(copyFixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull(); }); customCopyComponent.taskList.appName = appName.currentValue; customCopyComponent.taskList.ngOnChanges({ 'appName': appName }); @@ -303,7 +303,7 @@ describe('TaskListCloudComponent', () => { const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="standalone-subtask"]'); spanHTMLElement.dispatchEvent(new Event('mouseenter')); copyFixture.detectChanges(); - expect(copyFixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + expect(copyFixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull(); }); }); customCopyComponent.taskList.appName = appName.currentValue; @@ -394,7 +394,7 @@ describe('TaskListCloudComponent', () => { const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); spanHTMLElement.dispatchEvent(new Event('mouseenter')); fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull(); }); }); @@ -413,7 +413,7 @@ describe('TaskListCloudComponent', () => { const spanHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('span[title="standalone-subtask"]'); spanHTMLElement.dispatchEvent(new Event('mouseenter')); fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull(); }); }); component.presetColumn = 'fakeCustomSchema'; diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index adbcf25dfe..1e13586516 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -43,7 +43,7 @@ export class DataTableComponentPage { this.selectedRowNumber = this.rootElement.element(by.css(`div[class*='is-selected'] div[data-automation-id*='text_']`)); this.allSelectedRows = this.rootElement.all(by.css(`div[class*='is-selected']`)); this.selectAll = this.rootElement.element(by.css(`div[class*='adf-datatable-header'] mat-checkbox`)); - this.copyColumnTooltip = this.rootElement.element(by.css(`adf-datatable-copy-content-tooltip span`)); + this.copyColumnTooltip = this.rootElement.element(by.css(`adf-copy-content-tooltip span`)); } checkAllRowsButtonIsDisplayed() { From 630b1043a96e283403e35826e299b5cd1cd6d11d Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano@alfresco.com> Date: Tue, 23 Apr 2019 12:24:39 +0200 Subject: [PATCH 143/208] [ADF-4405] [ADF-4423] Fix clipboard directive on json cell (#4623) * [ADF-4405] [ADF-4423] Fix clipboard directive on json cell * Update clipboard.directive.ts * fix spell --- .../content-node-share/content-node-share.dialog.html | 2 +- lib/core/clipboard/clipboard.directive.ts | 8 +++++--- .../datatable/components/datatable/json-cell.component.ts | 4 +--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/content-services/content-node-share/content-node-share.dialog.html b/lib/content-services/content-node-share/content-node-share.dialog.html index cc5e893393..5e1fe28e19 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.html +++ b/lib/content-services/content-node-share/content-node-share.dialog.html @@ -31,7 +31,7 @@ readonly="readonly"> <mat-icon class="adf-input-action" matSuffix [clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate" - [adf-clipboard] target="sharedLinkInput"> + [adf-clipboard] [target]="sharedLinkInput"> link </mat-icon> </mat-form-field> diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index 38c96ca255..68f27b50e3 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -49,9 +49,11 @@ export class ClipboardDirective { @HostListener('mouseenter') showTooltip() { - const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); - const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; - componentRef.placeholder = this.placeholder; + if (this.placeholder) { + const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); + const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; + componentRef.placeholder = this.placeholder; + } } @HostListener('mouseleave') diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts index 500a867e16..92c11e326f 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.ts +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -27,9 +27,7 @@ import { DataTableCellComponent } from './datatable-cell.component'; <pre class="adf-datatable-json-cell" [adf-clipboard]="'CLIPBOARD.CLICK_TO_COPY'" - [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"> - {{ value$ | async | json }} - </pre> + [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'">{{ value$ | async | json }}</pre> </span> </ng-container> <ng-template #defaultJsonTemplate> From 2676fe6637ba8e273cbae4d357915c56e477401f Mon Sep 17 00:00:00 2001 From: Andy Stark <30621568+therealandeeee@users.noreply.github.com> Date: Tue, 23 Apr 2019 14:27:01 +0100 Subject: [PATCH 144/208] [ADF-4416] Added upgrade guide 3.1 -> 3.2 (#4641) --- docs/upgrade-guide/upgrade31-32.md | 76 ++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/upgrade-guide/upgrade31-32.md diff --git a/docs/upgrade-guide/upgrade31-32.md b/docs/upgrade-guide/upgrade31-32.md new file mode 100644 index 0000000000..94a9c59315 --- /dev/null +++ b/docs/upgrade-guide/upgrade31-32.md @@ -0,0 +1,76 @@ +--- +Title: Upgrading from ADF v3.1 to v3.2 +--- + +# Upgrading from ADF v3.1 to v3.2 + +This guide explains how to upgrade your ADF v3.1 project to work with v3.2. + +**Note:** the steps described below might involve making changes +to your code. If you are working with a versioning system then you should +commit any changes you are currently working on. If you aren't using versioning +then be sure to make a backup copy of your project before going ahead with the +upgrade. + +## Library updates + +### Automatic update using the Yeoman Generator + +If your application has few changes from the original app created by the +[Yeoman generator](https://github.com/Alfresco/generator-ng2-alfresco-app) +then you may be able to update your project with the following steps: + +1. Update the Yeoman generator to the latest version (3.2.0). Note that + you might need to run these commands with `sudo` on Linux or MacOS: + + ```sh + npm uninstall -g generator-alfresco-adf-app + npm install -g generator-alfresco-adf-app + ``` + +2. Run the new yeoman app generator: + + ```sh + yo alfresco-adf-app + ``` + +3. Clean your old distribution and dependencies by deleting the `node_modules` folder + and the `package-lock.json` file. + +4. Install the dependencies: + ```sh + npm install + ``` + +At this point, the generator might have overwritten some of your code where it differs from +the original generated app. Be sure to check for any differences from your project code +(using a versioning system might make this easier) and if there are any differences, +retrofit your changes. When you have done this, you should be able to start the application +as usual: + +```sh +npm run start +``` + +After starting the app, if everything is working fine, that's all and you don't need to do anything else. However, if things don't work as they should then recover the original version of the project and try the manual approach. + +### Manual update + +1. Update the `package.json` file with the latest library versions: + ```json + "dependencies": { + ... + "@alfresco/adf-core": "3.2.0", + "@alfresco/adf-content-services": "3.2.0", + "@alfresco/adf-process-services-cloud": "3.2.0", + "@alfresco/adf-insights": "3.2.0", + "@alfresco/js-api": "3.2.0", + ... + ``` + +2. Clean your old distribution and dependencies by deleting `node_modules` and `package-lock.json`. + +3. Reinstall your dependencies + ```sh + npm install + ``` \ No newline at end of file From 0dc28ad9870872a48338d48ffe8722bae75913fc Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Tue, 23 Apr 2019 14:27:45 +0100 Subject: [PATCH 145/208] [NO-ISSUE] add check env is up also for CS ans PS (#4640) * add check env is up also for CS ans PS * remove logs --- .travis.yml | 16 +++++++++++----- scripts/check-cs-env.js | 27 +++++++++++++++++++++++++++ scripts/check-ps-env.js | 27 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100755 scripts/check-cs-env.js create mode 100755 scripts/check-ps-env.js diff --git a/.travis.yml b/.travis.yml index b1ce085e28..dc21dba65e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -141,7 +141,9 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "core$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder core --skip-lint -save --use-dist || exit 1;); + node ./scripts/check-ps-env.js --host "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" || exit 1; + node ./scripts/check-cs-env.js --host "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" || exit 1; + ./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder core --skip-lint -save --use-dist || exit 1; fi; - stage: e2e Test # Test process-services name: process-services @@ -150,7 +152,8 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "process-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder process-services --skip-lint --use-dist || exit 1;); + node ./scripts/check-ps-env.js --host "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" || exit 1; + ./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder process-services --skip-lint --use-dist || exit 1; fi; - stage: e2e Test # Test content-services name: content-services @@ -159,7 +162,8 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "content-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder content-services --skip-lint --use-dist || exit 1;); + node ./scripts/check-cs-env.js --host "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" || exit 1; + ./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder content-services --skip-lint --use-dist || exit 1; fi; - stage: e2e Test # Test search name: search @@ -168,7 +172,8 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "content-services$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder search --skip-lint --use-dist || exit 1;); + node ./scripts/check-cs-env.js --host "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" || exit 1; + ./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder search --skip-lint --use-dist || exit 1; fi; - stage: e2e Test # Test process-services-cloud name: process-services-cloud @@ -187,7 +192,8 @@ jobs: AFFECTED_LIBS="$(./scripts/affected-libs.sh -gnu -b $TRAVIS_BRANCH)"; if [[ $AFFECTED_LIBS =~ "process-services-cloud$" || $AFFECTED_E2E = "e2e" || $TRAVIS_PULL_REQUEST == "false" ]]; then - (./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder insights --skip-lint --use-dist || exit 1;); + node ./scripts/check-ps-env.js --host "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" || exit 1; + ./scripts/test-e2e-lib.sh -host localhost:4200 -proxy "$E2E_HOST" -u "$E2E_USERNAME" -p "$E2E_PASSWORD" -e "$E2E_EMAIL" --folder insights --skip-lint --use-dist || exit 1; fi; - stage: Create Docker and Deploy Docker PR script: diff --git a/scripts/check-cs-env.js b/scripts/check-cs-env.js new file mode 100755 index 0000000000..694f0c6954 --- /dev/null +++ b/scripts/check-cs-env.js @@ -0,0 +1,27 @@ +let alfrescoApi = require('@alfresco/js-api'); +let program = require('commander'); + +async function main() { + + program + .version('0.1.0') + .option('--host [type]', 'Remote environment host adf.lab.com ') + .option('-p, --password [type]', 'password ') + .option('-u, --username [type]', 'username ') + .parse(process.argv); + + try { + + this.alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility({ + provider: 'BPM', + hostEcm: program.host + }); + await this.alfrescoJsApi.login(program.username, program.password); + } catch (e) { + console.log('Login error environment down or inaccessible'); + process.exit(1); + } + +} + +main(); diff --git a/scripts/check-ps-env.js b/scripts/check-ps-env.js new file mode 100755 index 0000000000..5c519aa697 --- /dev/null +++ b/scripts/check-ps-env.js @@ -0,0 +1,27 @@ +let alfrescoApi = require('@alfresco/js-api'); +let program = require('commander'); + +async function main() { + + program + .version('0.1.0') + .option('--host [type]', 'Remote environment host adf.lab.com ') + .option('-p, --password [type]', 'password ') + .option('-u, --username [type]', 'username ') + .parse(process.argv); + + try { + + this.alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility({ + provider: 'ECM', + hostEcm: program.host + }); + await this.alfrescoJsApi.login(program.username, program.password); + } catch (e) { + console.log('Login error environment down or inaccessible'); + process.exit(1); + } + +} + +main(); From d427e06136951c93bbd43a6e3ded4fe80cde7f50 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Tue, 23 Apr 2019 14:30:08 +0100 Subject: [PATCH 146/208] Revert "[ADF-4405] [ADF-4423] Fix clipboard directive on json cell (#4623)" (#4642) This reverts commit 630b1043a96e283403e35826e299b5cd1cd6d11d. --- .../content-node-share/content-node-share.dialog.html | 2 +- lib/core/clipboard/clipboard.directive.ts | 8 +++----- .../datatable/components/datatable/json-cell.component.ts | 4 +++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/content-services/content-node-share/content-node-share.dialog.html b/lib/content-services/content-node-share/content-node-share.dialog.html index 5e1fe28e19..cc5e893393 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.html +++ b/lib/content-services/content-node-share/content-node-share.dialog.html @@ -31,7 +31,7 @@ readonly="readonly"> <mat-icon class="adf-input-action" matSuffix [clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate" - [adf-clipboard] [target]="sharedLinkInput"> + [adf-clipboard] target="sharedLinkInput"> link </mat-icon> </mat-form-field> diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index 68f27b50e3..38c96ca255 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -49,11 +49,9 @@ export class ClipboardDirective { @HostListener('mouseenter') showTooltip() { - if (this.placeholder) { - const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); - const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; - componentRef.placeholder = this.placeholder; - } + const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); + const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; + componentRef.placeholder = this.placeholder; } @HostListener('mouseleave') diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts index 92c11e326f..500a867e16 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.ts +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -27,7 +27,9 @@ import { DataTableCellComponent } from './datatable-cell.component'; <pre class="adf-datatable-json-cell" [adf-clipboard]="'CLIPBOARD.CLICK_TO_COPY'" - [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'">{{ value$ | async | json }}</pre> + [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"> + {{ value$ | async | json }} + </pre> </span> </ng-container> <ng-template #defaultJsonTemplate> From 11688f577812a39dcec2063d1808876571964ead Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 23 Apr 2019 17:37:10 +0100 Subject: [PATCH 147/208] add 1 minute retry --- scripts/check-cs-env.js | 30 ++++++++++++++++++++++++++---- scripts/check-ps-env.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/scripts/check-cs-env.js b/scripts/check-cs-env.js index 694f0c6954..e39b662763 100755 --- a/scripts/check-cs-env.js +++ b/scripts/check-cs-env.js @@ -1,6 +1,10 @@ let alfrescoApi = require('@alfresco/js-api'); let program = require('commander'); +let MAX_RETRY = 10; +let counter = 0; +let TIMEOUT = 60000; + async function main() { program @@ -10,18 +14,36 @@ async function main() { .option('-u, --username [type]', 'username ') .parse(process.argv); - try { + await checkEnv(); +} + +async function checkEnv() { + try { this.alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility({ - provider: 'BPM', - hostEcm: program.host + provider: 'ECM', + hostEcm: program.host }); + await this.alfrescoJsApi.login(program.username, program.password); } catch (e) { console.log('Login error environment down or inaccessible'); - process.exit(1); + counter++; + if (MAX_RETRY === counter) { + console.log('Give up'); + process.exit(1); + } else { + console.log(`Retry in 1 minute attempt N ${counter}`); + sleep(TIMEOUT); + checkEnv(); + } } +} + +function sleep(delay) { + var start = new Date().getTime(); + while (new Date().getTime() < start + delay) ; } main(); diff --git a/scripts/check-ps-env.js b/scripts/check-ps-env.js index 5c519aa697..b6440421f0 100755 --- a/scripts/check-ps-env.js +++ b/scripts/check-ps-env.js @@ -1,6 +1,10 @@ let alfrescoApi = require('@alfresco/js-api'); let program = require('commander'); +let MAX_RETRY = 10; +let counter = 0; +let TIMEOUT = 60000; + async function main() { program @@ -10,18 +14,36 @@ async function main() { .option('-u, --username [type]', 'username ') .parse(process.argv); - try { + await checkEnv(); +} + +async function checkEnv() { + try { this.alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility({ - provider: 'ECM', - hostEcm: program.host + provider: 'BPM', + hostBpm: program.host }); + await this.alfrescoJsApi.login(program.username, program.password); } catch (e) { console.log('Login error environment down or inaccessible'); - process.exit(1); + counter++; + if (MAX_RETRY === counter) { + console.log('Give up'); + process.exit(1); + } else { + console.log(`Retry in 1 minute attempt N ${counter}`); + sleep(TIMEOUT); + checkEnv(); + } } +} + +function sleep(delay) { + var start = new Date().getTime(); + while (new Date().getTime() < start + delay) ; } main(); From b371929170737031dbd8b85645ae850719b59849 Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Tue, 23 Apr 2019 17:55:24 +0100 Subject: [PATCH 148/208] [ADF-3876] StartTaskCloud - Be able to start a task with a form (#4590) * [ADF-3876] Added form cloud model * [ADF-3876] Added service to get forms * [ADF-3876] Added form selection to start task * [ADF-3876] Added tests * [ADF-3876] StartTaskCloud - Be able to start a task with a form * [ADF-3876] StartTaskCloud - Be able to start a task with a form * [ADF-3876] StartTaskCloud - Be able to start a task with a form * [ADF-3876] Added form cloud model * [ADF-3876] Added service to get forms * [ADF-3876] Added form selection to start task * [ADF-3876] Added tests * [ADF-3876] StartTaskCloud - Be able to start a task with a form * [ADF-3876] StartTaskCloud - changed name to component * [ADF-3876] StartTaskCloud - Renamed component * Rename form-selector-cloud.component.md to form-definition-selector-cloud.component.md * [ADF-3876] Improve and clean code and fix service * [ADF-3876] Fix unit test * Update app.module.ts * fix module * move components in the right folders * fix e2e task list --- ...orm-definition-selector-cloud.component.md | 27 +++++ .../task-list-selection.e2e.ts | 12 +-- ...m-definition-selector-cloud.component.html | 7 ++ ...m-definition-selector-cloud.component.scss | 5 + ...efinition-selector-cloud.component.spec.ts | 96 +++++++++++++++++ ...orm-definition-selector-cloud.component.ts | 53 ++++++++++ .../src/lib/form/form-cloud.module.ts | 21 ++-- .../form-definition-selector-cloud.model.ts | 33 ++++++ .../src/lib/form/public-api.ts | 6 +- .../form-definition-selector-cloud.service.ts | 75 +++++++++++++ .../src/lib/i18n/en.json | 3 +- .../src/lib/process-services-cloud.module.ts | 7 +- .../src/lib/styles/_index.scss | 14 +-- .../src/lib/task/directives/public-api.ts | 22 ++++ .../src/lib/task/public-api.ts | 6 +- .../start-task-cloud.component.html | 100 ++++++++++-------- .../start-task-cloud.component.spec.ts | 14 ++- .../components/start-task-cloud.component.ts | 20 +++- .../models/start-task-cloud-request.model.ts | 2 + .../start-task/start-task-cloud.module.ts | 18 ++-- .../src/lib/task/task-cloud.module.ts | 7 +- .../src/lib/task/task-filters/public-api.ts | 3 + .../components/task-form-cloud.component.html | 0 .../components/task-form-cloud.component.scss | 0 .../task-form-cloud.component.spec.ts | 17 ++- .../components/task-form-cloud.component.ts | 6 +- .../src/lib/task/task-form/public-api.ts | 20 ++++ .../task-form.module.ts} | 31 +++--- lib/process-services-cloud/src/public-api.ts | 2 +- 29 files changed, 512 insertions(+), 115 deletions(-) create mode 100644 docs/process-services-cloud/components/form-definition-selector-cloud.component.md create mode 100644 lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.html create mode 100644 lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.scss create mode 100644 lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts create mode 100644 lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts create mode 100644 lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts create mode 100644 lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts create mode 100644 lib/process-services-cloud/src/lib/task/directives/public-api.ts rename lib/process-services-cloud/src/lib/{form => task/task-form}/components/task-form-cloud.component.html (100%) rename lib/process-services-cloud/src/lib/{form => task/task-form}/components/task-form-cloud.component.scss (100%) rename lib/process-services-cloud/src/lib/{form => task/task-form}/components/task-form-cloud.component.spec.ts (95%) rename lib/process-services-cloud/src/lib/{form => task/task-form}/components/task-form-cloud.component.ts (95%) create mode 100644 lib/process-services-cloud/src/lib/task/task-form/public-api.ts rename lib/process-services-cloud/src/lib/task/{task.module.ts => task-form/task-form.module.ts} (54%) diff --git a/docs/process-services-cloud/components/form-definition-selector-cloud.component.md b/docs/process-services-cloud/components/form-definition-selector-cloud.component.md new file mode 100644 index 0000000000..c4ee8d865a --- /dev/null +++ b/docs/process-services-cloud/components/form-definition-selector-cloud.component.md @@ -0,0 +1,27 @@ + +# [Form Definition Selector Cloud](../../../lib/process-services-cloud/src/lib/form-definition-selector/components/form-definition-selector-cloud.component.ts "Defined in form-definition-selector-cloud.component.ts") + +Allows one form to be selected. + +## Basic Usage + +```html +<adf-cloud-form-definition-selector + [appName]="'simple-app'" + (selectForm)="onFormSelect($event)"> +</adf-cloud-form-definition-selector> +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| appName | `string` | | (**required**) Name of the application. If specified, this shows the users who have access to the app. + +### Events + +| Name | Type | Description | +| ---- | ---- | ----------- | +| selectForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`string`](../../../lib/core/userinfo/models/identity-user.model.ts)`>` | Emitted when a form is selected. | diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index f928f85367..ca3df24cc2 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -22,7 +22,6 @@ import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import { StringUtil } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; import resources = require('../util/resources'); describe('Task list cloud - selection', () => { @@ -58,6 +57,10 @@ describe('Task list cloud - selection', () => { tasks.push(response.entry.name); } + done(); + }); + + beforeEach(async (done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); appListCloudComponent.goToApp(simpleApp); @@ -67,12 +70,6 @@ describe('Task list cloud - selection', () => { done(); }); - afterEach(async (done) => { - await browser.refresh(); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().waitForTableBody(); - done(); - }); - it('[C291914] Should not be able to select any row when selection mode is set to None', () => { tasksCloudDemoPage.clickSettingsButton().selectSelectionMode('None'); tasksCloudDemoPage.clickSettingsButton().disableDisplayTaskDetails(); @@ -107,6 +104,7 @@ describe('Task list cloud - selection', () => { tasksCloudDemoPage.clickAppButton(); tasksCloudDemoPage.taskListCloudComponent().getDataTable().waitForTableBody(); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(tasks[0]); tasksCloudDemoPage.taskListCloudComponent().selectRow(tasks[0]); tasksCloudDemoPage.taskListCloudComponent().checkRowIsSelected(tasks[0]); diff --git a/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.html b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.html new file mode 100644 index 0000000000..09c16fcf82 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.html @@ -0,0 +1,7 @@ +<mat-form-field class="adf-form-definition-selector"> + <mat-label>{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.FORM'|translate}}</mat-label> + <mat-select class="adf-form-selector-dropdown" (selectionChange)="onSelect($event)"> + <mat-option [value]="''">{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.NONE'|translate}}</mat-option> + <mat-option *ngFor="let form of forms$ | async" [value]="form.id">{{ form.name }}</mat-option> + </mat-select> +</mat-form-field> diff --git a/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.scss b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.scss new file mode 100644 index 0000000000..d5db4f165d --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.scss @@ -0,0 +1,5 @@ +.adf { + &-form-definition-selector { + width: 100%; + } +} diff --git a/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts new file mode 100644 index 0000000000..eba60d81b9 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.spec.ts @@ -0,0 +1,96 @@ +/*! + * @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 { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AlfrescoApiService, AppConfigService, LogService, setupTestBed, StorageService, UserPreferencesService } from '@alfresco/adf-core'; +import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; +import { StartTaskCloudTestingModule } from '../../task/start-task/testing/start-task-cloud.testing.module'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { FormDefinitionSelectorCloudComponent } from './form-definition-selector-cloud.component'; +import { By } from '@angular/platform-browser'; +import { of } from 'rxjs'; +import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service'; + +describe('FormDefinitionCloudComponent', () => { + + let fixture: ComponentFixture<FormDefinitionSelectorCloudComponent>; + let service: FormDefinitionSelectorCloudService; + let element: HTMLElement; + let getFormsSpy: jasmine.Spy; + + setupTestBed({ + imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule], + providers: [FormDefinitionSelectorCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService, UserPreferencesService], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(FormDefinitionSelectorCloudComponent); + element = fixture.nativeElement; + service = TestBed.get(FormDefinitionSelectorCloudService); + getFormsSpy = spyOn(service, 'getForms').and.returnValue(of([{ id: 'fake-form', name: 'fakeForm' }])); + }); + + it('should load the forms by default', () => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + const clickMatSelect = fixture.debugElement.query(By.css(('.mat-select-trigger'))); + clickMatSelect.triggerEventHandler('click', null); + fixture.detectChanges(); + const options: any = fixture.debugElement.queryAll(By.css('mat-option')); + expect(options[0].nativeElement.innerText.trim()).toBe('ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.NONE'); + expect(options[1].nativeElement.innerText.trim()).toBe('fakeForm'); + expect(getFormsSpy).toHaveBeenCalled(); + }); + }); + + it('should load only None option when no forms exist', () => { + getFormsSpy.and.returnValue(of([])); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + const clickMatSelect = fixture.debugElement.query(By.css(('.mat-select-trigger'))); + clickMatSelect.triggerEventHandler('click', null); + fixture.detectChanges(); + const options: any = fixture.debugElement.queryAll(By.css('mat-option')); + expect((options).length).toBe(1); + }); + }); + + it('should not preselect any form by default', () => { + fixture.detectChanges(); + const formInput = element.querySelector('mat-select'); + expect(formInput).toBeDefined(); + expect(formInput.nodeValue).toBeNull(); + }); + + it('should display the name of the form that is selected', () => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const clickMatSelect = fixture.debugElement.query(By.css(('.mat-select-trigger'))); + clickMatSelect.triggerEventHandler('click', null); + fixture.detectChanges(); + const options: any = fixture.debugElement.queryAll(By.css('mat-option')); + options[1].triggerEventHandler('click', {}); + fixture.detectChanges(); + const selected = fixture.debugElement.query(By.css('mat-select')); + const selectedValue = ((selected).nativeElement.innerText); + expect(selectedValue.trim()).toBe('fakeForm'); + }); + }); +}); diff --git a/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts new file mode 100644 index 0000000000..80e395313c --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts @@ -0,0 +1,53 @@ +/*! + * @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, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Observable } from 'rxjs'; +import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service'; +import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model'; +import { MatSelectChange } from '@angular/material'; + +@Component({ + selector: 'adf-cloud-form-definition-selector', + templateUrl: './form-definition-selector-cloud.component.html', + styleUrls: ['./form-definition-selector-cloud.component.scss'] +}) + +export class FormDefinitionSelectorCloudComponent implements OnInit { + + /** Name of the application. If specified, this shows the users who have access to the app. */ + @Input() + appName: string; + + /** Emitted when a form is selected. */ + @Output() + selectForm: EventEmitter<string> = new EventEmitter<string>(); + + forms$: Observable<FormDefinitionSelectorCloudModel[]>; + + constructor(private formDefinitionCloudService: FormDefinitionSelectorCloudService) { + } + + ngOnInit(): void { + this.forms$ = this.formDefinitionCloudService.getForms(this.appName); + } + + onSelect(event: MatSelectChange) { + this.selectForm.emit(event.value); + } + +} diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts index b26be954e2..ea3b216953 100644 --- a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -20,31 +20,32 @@ import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; import { TemplateModule, FormBaseModule, PipeModule, CoreModule } from '@alfresco/adf-core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { FormCloudComponent } from './components/form-cloud.component'; import { UploadCloudWidgetComponent } from './components/upload-cloud.widget'; import { MaterialModule } from '../material.module'; -import { TaskFormCloudComponent } from './components/task-form-cloud.component'; -import { TaskCloudModule } from '../task/task-cloud.module'; +import { FormCloudComponent } from './components/form-cloud.component'; +import { FormDefinitionSelectorCloudComponent } from './components/form-definition-selector-cloud.component'; +import { FormDefinitionSelectorCloudService } from './services/form-definition-selector-cloud.service'; @NgModule({ imports: [ - CommonModule, - PipeModule, + CommonModule, + PipeModule, TemplateModule, FlexLayoutModule, MaterialModule, FormsModule, ReactiveFormsModule, FormBaseModule, - CoreModule, - TaskCloudModule + CoreModule ], - declarations: [FormCloudComponent, UploadCloudWidgetComponent, TaskFormCloudComponent], + declarations: [FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent], + providers: [FormDefinitionSelectorCloudService], entryComponents: [ UploadCloudWidgetComponent ], exports: [ - FormCloudComponent, UploadCloudWidgetComponent, TaskFormCloudComponent + FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent ] }) -export class FormCloudModule { } +export class FormCloudModule { +} diff --git a/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts new file mode 100644 index 0000000000..4b3bff172f --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/models/form-definition-selector-cloud.model.ts @@ -0,0 +1,33 @@ +/*! + * @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. + */ + +export class FormDefinitionSelectorCloudModel { + + id: number; + name: string; + description: string; + version: string; + + constructor(obj?: any) { + if (obj) { + this.id = obj.id || null; + this.name = obj.name || null; + this.description = obj.description || null; + this.version = obj.version || null; + } + } +} diff --git a/lib/process-services-cloud/src/lib/form/public-api.ts b/lib/process-services-cloud/src/lib/form/public-api.ts index 36df829477..68a5593f54 100644 --- a/lib/process-services-cloud/src/lib/form/public-api.ts +++ b/lib/process-services-cloud/src/lib/form/public-api.ts @@ -17,7 +17,11 @@ export * from './models/form-cloud.model'; export * from './models/task-variable-cloud.model'; +export * from './models/form-definition-selector-cloud.model'; + export * from './components/form-cloud.component'; export * from './components/upload-cloud.widget'; -export * from './components/task-form-cloud.component'; +export * from './components/form-definition-selector-cloud.component'; + export * from './services/form-cloud.service'; +export * from './services/form-definition-selector-cloud.service'; diff --git a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts new file mode 100644 index 0000000000..03826a00f4 --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts @@ -0,0 +1,75 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core'; +import { catchError, map } from 'rxjs/operators'; +import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model'; +import { from, Observable, throwError } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class FormDefinitionSelectorCloudService { + + contextRoot: string; + contentTypes = ['application/json']; + accepts = ['application/json']; + returnType = Object; + + constructor(private apiService: AlfrescoApiService, + private appConfigService: AppConfigService, + private logService: LogService) { + this.contextRoot = this.appConfigService.get('bpmHost', ''); + } + + /** + * Get all forms of an app. + * @param appName Name of the application + * @returns Details of the forms + */ + getForms(appName: string): Observable<FormDefinitionSelectorCloudModel[]> { + + const queryUrl = this.buildGetFormsUrl(appName); + const bodyParam = {}, pathParams = {}, queryParams = {}, headerParams = {}, + formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; + return from( + this.apiService + .getInstance() + .oauth2Auth.callCustomApi( + queryUrl, 'GET', pathParams, queryParams, + headerParams, formParams, bodyParam, + contentTypes, accepts, null, null) + ).pipe( + map((data: any) => { + return data.map((formData: any) => { + return <FormDefinitionSelectorCloudModel> formData.formRepresentation; + }); + }), + catchError((err) => this.handleError(err)) + ); + } + + private buildGetFormsUrl(appName: string): any { + return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms`; + } + + private handleError(error: any) { + this.logService.error(error); + return throwError(error || 'Server error'); + } +} diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 4943ac30d6..3aef9ccec8 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -66,7 +66,8 @@ "ASSIGNEE": "Assignee", "CANDIDATE_GROUP": "Candidate Group", "FORM": "Form", - "DATE": "Choose Date" + "DATE": "Choose Date", + "NONE": "None" }, "ACTION": { "START": "Start", diff --git a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts index 248bf6f02e..1289adf9e3 100644 --- a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts @@ -22,6 +22,7 @@ import { TaskCloudModule } from './task/task-cloud.module'; import { ProcessCloudModule } from './process/process-cloud.module'; import { GroupCloudModule } from './group/group-cloud.module'; import { FormCloudModule } from './form/form-cloud.module'; +import { TaskFormModule } from './task/task-form/task-form.module'; @NgModule({ imports: [ @@ -30,7 +31,8 @@ import { FormCloudModule } from './form/form-cloud.module'; ProcessCloudModule, TaskCloudModule, GroupCloudModule, - FormCloudModule + FormCloudModule, + TaskFormModule ], providers: [ { @@ -47,7 +49,8 @@ import { FormCloudModule } from './form/form-cloud.module'; ProcessCloudModule, TaskCloudModule, GroupCloudModule, - FormCloudModule + FormCloudModule, + TaskFormModule ] }) export class ProcessServicesCloudModule { } diff --git a/lib/process-services-cloud/src/lib/styles/_index.scss b/lib/process-services-cloud/src/lib/styles/_index.scss index 33cdc296d2..dc08214bf3 100644 --- a/lib/process-services-cloud/src/lib/styles/_index.scss +++ b/lib/process-services-cloud/src/lib/styles/_index.scss @@ -1,13 +1,13 @@ @import './../app/components/app-details-cloud.component'; @import './../app/components/app-list-cloud.component'; -@import './../task/task-filters/components/task-filters-cloud.component.scss'; -@import './../task/task-filters/components/edit-task-filter-cloud.component.scss'; -@import './../process/process-list/components/process-list-cloud.component.scss'; -@import './../task/start-task/components/start-task-cloud.component.scss'; -@import './../process/process-filters/components/edit-process-filter-cloud.component.scss'; -@import './../task/start-task/components/people-cloud/people-cloud.component.scss'; @import './../group/components/group-cloud.component'; -@import './../form/components/task-form-cloud.component'; +@import './../process/process-list/components/process-list-cloud.component.scss'; +@import './../process/process-filters/components/edit-process-filter-cloud.component.scss'; +@import './../task/task-form/components/task-form-cloud.component'; +@import './../task/start-task/components/people-cloud/people-cloud.component.scss'; +@import './../task/start-task/components/start-task-cloud.component.scss'; +@import './../task/task-filters/components/edit-task-filter-cloud.component.scss'; +@import './../task/task-filters/components/task-filters-cloud.component.scss'; @mixin adf-process-services-cloud-theme($theme) { diff --git a/lib/process-services-cloud/src/lib/task/directives/public-api.ts b/lib/process-services-cloud/src/lib/task/directives/public-api.ts new file mode 100644 index 0000000000..86f452a53e --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/directives/public-api.ts @@ -0,0 +1,22 @@ +/*! + * @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. + */ + +export * from './claim-task.directive'; +export * from './unclaim-task.directive'; +export * from './complete-task.directive'; + +export * from './task-directive.module'; diff --git a/lib/process-services-cloud/src/lib/task/public-api.ts b/lib/process-services-cloud/src/lib/task/public-api.ts index 1d0afddbc5..34f0abdf78 100644 --- a/lib/process-services-cloud/src/lib/task/public-api.ts +++ b/lib/process-services-cloud/src/lib/task/public-api.ts @@ -19,7 +19,9 @@ export * from './task-list/public-api'; export * from './task-filters/public-api'; export * from './start-task/public-api'; export * from './task-header/public-api'; +export * from './task-form/public-api'; +export * from './directives/public-api'; + +export * from './services/task-cloud.service'; export * from './task-cloud.module'; -export * from './directives/task-directive.module'; -export * from './services/task-cloud.service'; diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html index 95e19ac0a8..ac8628379f 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.html @@ -1,10 +1,11 @@ <mat-card> - <mat-card-header fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="10px" class="adf-cloud-start-task-heading"> + <mat-card-header fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="10px" + class="adf-cloud-start-task-heading"> <mat-card-title>{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.TITLE' | translate}}</mat-card-title> </mat-card-header> <form [formGroup]="taskForm" fxLayout="column" (ngSubmit)="saveTask()"> - <mat-card-content> + <mat-card-content> <div class="adf-task-name"> <mat-form-field fxFlex> <mat-label>{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.NAME' | translate }}</mat-label> @@ -17,7 +18,7 @@ {{ 'ADF_CLOUD_START_TASK.ERROR.REQUIRED' | translate }} </mat-error> <mat-error *ngIf="nameController.hasError('maxlength')"> - {{ 'ADF_CLOUD_START_TASK.ERROR.MAXIMUM_LENGTH' | translate : { characters : maxNameLength } }} + {{ 'ADF_CLOUD_START_TASK.ERROR.MAXIMUM_LENGTH' | translate : {characters: maxNameLength} }} </mat-error> </mat-form-field> </div> @@ -34,25 +35,25 @@ <mat-form-field fxFlex> <div style="height: 40px;"> - <input matInput type="number" placeholder="Priority" formControlName="priority"> + <input matInput type="number" placeholder="Priority" formControlName="priority"> </div> </mat-form-field> </div> <div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <mat-form-field fxFlex> <input matInput - [matDatepicker]="taskDatePicker" - (keydown)="true" - (focusout)="onDateChanged($event.srcElement.value)" - placeholder="{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}" - [(ngModel)]="dueDate" - [ngModelOptions]="{standalone: true}" - id="date_id"> - <mat-datepicker-toggle matSuffix [for]="taskDatePicker"></mat-datepicker-toggle> - <mat-datepicker #taskDatePicker - [touchUi]="true" - (dateChanged)="onDateChanged($event)"> - </mat-datepicker> + [matDatepicker]="taskDatePicker" + (keydown)="true" + (focusout)="onDateChanged($event.srcElement.value)" + placeholder="{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}" + [(ngModel)]="dueDate" + [ngModelOptions]="{standalone: true}" + id="date_id"> + <mat-datepicker-toggle matSuffix [for]="taskDatePicker"></mat-datepicker-toggle> + <mat-datepicker #taskDatePicker + [touchUi]="true" + (dateChanged)="onDateChanged($event)"> + </mat-datepicker> <div class="adf-cloud-date-error-container"> <div *ngIf="dateError"> <div class="adf-error-text">{{'ADF_CLOUD_START_TASK.ERROR.DATE' | translate}}</div> @@ -61,41 +62,46 @@ </div> </mat-form-field> <adf-cloud-people fxFlex #peopleInput *ngIf="currentUser" - [appName]="appName" - [preSelectUsers]="[currentUser]" - (selectUser)="onAssigneeSelect($event)" - [title]="'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'" - (removeUser)="onAssigneeRemove()"></adf-cloud-people> + [appName]="appName" + [preSelectUsers]="[currentUser]" + (selectUser)="onAssigneeSelect($event)" + [title]="'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE'" + (removeUser)="onAssigneeRemove()"></adf-cloud-people> </div> - <div class="input-row" fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> + <div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px"> <adf-cloud-group fxFlex #groupInput *ngIf="currentUser" - [mode]="'multiple'" - [title]="'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.CANDIDATE_GROUP'" - [appName]="appName" - (selectGroup)="onCandiateGroupSelect($event)" - (removeGroup)="onCandiateGroupRemove($event)"></adf-cloud-group> - <div fxFlex></div> + [mode]="'multiple'" + [title]="'ADF_CLOUD_TASK_LIST.START_TASK.FORM.LABEL.CANDIDATE_GROUP'" + [appName]="appName" + (selectGroup)="onCandidateGroupSelect($event)" + (removeGroup)="onCandidateGroupRemove($event)"> + </adf-cloud-group> + <adf-cloud-form-definition-selector fxFlex + [appName]="appName" + (selectForm)="onFormSelect($event)"> + </adf-cloud-form-definition-selector> </div> - </mat-card-content> + </mat-card-content> - <mat-card-actions> - <div class="adf-cloud-start-task-footer" fxLayout="row" fxLayoutAlign="end end" > - <button - mat-button - type="button" - (click)="onCancel()" - id="button-cancel"> - {{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.ACTION.CANCEL'|translate}} - </button> - <button - color="primary" - type="submit" [disabled]="dateError || !taskForm.valid || submitted || assignee.hasError() || candidateGroups.hasError()" - mat-button - id="button-start"> - {{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.ACTION.START'|translate}} - </button> - </div> - </mat-card-actions> + <mat-card-actions> + <div class="adf-cloud-start-task-footer" fxLayout="row" fxLayoutAlign="end end"> + <button + mat-button + type="button" + (click)="onCancel()" + id="button-cancel"> + {{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.ACTION.CANCEL'|translate}} + </button> + <button + color="primary" + type="submit" + [disabled]="dateError || !taskForm.valid || submitted || assignee.hasError() || candidateGroups.hasError()" + mat-button + id="button-start"> + {{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.ACTION.START'|translate}} + </button> + </div> + </mat-card-actions> </form> </mat-card> diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts index 2c929d9c73..5c17ed89e8 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.spec.ts @@ -33,6 +33,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { ProcessServiceCloudTestingModule } from './../../../testing/process-service-cloud.testing.module'; import { StartTaskCloudTestingModule } from '../testing/start-task-cloud.testing.module'; import { TaskDetailsCloudModel } from '../models/task-details-cloud.model'; +import { FormDefinitionSelectorCloudService } from '../../../form/services/form-definition-selector-cloud.service'; describe('StartTaskCloudComponent', () => { @@ -40,12 +41,21 @@ describe('StartTaskCloudComponent', () => { let fixture: ComponentFixture<StartTaskCloudComponent>; let service: StartTaskCloudService; let identityService: IdentityUserService; + let formDefinitionSelectorCloudService: FormDefinitionSelectorCloudService; let element: HTMLElement; let createNewTaskSpy: jasmine.Spy; setupTestBed({ imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule], - providers: [StartTaskCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService, UserPreferencesService], + providers: [ + StartTaskCloudService, + AlfrescoApiService, + AppConfigService, + LogService, + StorageService, + UserPreferencesService, + FormDefinitionSelectorCloudService + ], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] }); @@ -56,8 +66,10 @@ describe('StartTaskCloudComponent', () => { service = TestBed.get(StartTaskCloudService); identityService = TestBed.get(IdentityUserService); + formDefinitionSelectorCloudService = TestBed.get(FormDefinitionSelectorCloudService); createNewTaskSpy = spyOn(service, 'createNewTask').and.returnValue(of(taskDetailsMock)); spyOn(identityService, 'getCurrentUserInfo').and.returnValue(new IdentityUserModel({username: 'currentUser', firstName: 'Test', lastName: 'User'})); + spyOn(formDefinitionSelectorCloudService, 'getForms').and.returnValue(of([])); fixture.detectChanges(); })); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts index 5244b43b67..34d92591ae 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts @@ -97,6 +97,8 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { currentUser: IdentityUserModel; + formKey: string; + private localeSub: Subscription; private createTaskSub: Subscription; @@ -112,7 +114,6 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => { this.dateAdapter.setLocale(locale); }); - this.loadCurrentUser(); this.buildForm(); } @@ -131,7 +132,8 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { this.taskForm = this.formBuilder.group({ name: new FormControl(this.name, [Validators.required, Validators.maxLength(this.getMaxNameLength()), this.whitespaceValidator]), priority: new FormControl(), - description: new FormControl('', [this.whitespaceValidator]) + description: new FormControl('', [this.whitespaceValidator]), + formKey: new FormControl() }); } @@ -151,7 +153,9 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { newTask.appName = this.appName; newTask.dueDate = this.dueDate; newTask.assignee = this.assigneeName; + newTask.formKey = this.formKey; newTask.candidateGroups = this.candidateGroupNames; + this.createNewTask(new TaskDetailsCloudModel(newTask)); } @@ -192,15 +196,17 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { this.assigneeName = ''; } - onCandiateGroupSelect(candidateGroup: any) { + onCandidateGroupSelect(candidateGroup: any) { if (candidateGroup.name) { this.candidateGroupNames.push(candidateGroup.name); } } - onCandiateGroupRemove(candidateGroup: any) { + onCandidateGroupRemove(candidateGroup: any) { if (candidateGroup.name) { - this.candidateGroupNames = this.candidateGroupNames.filter((name: string) => { return name !== candidateGroup.name; }); + this.candidateGroupNames = this.candidateGroupNames.filter((name: string) => { + return name !== candidateGroup.name; + }); } } @@ -217,4 +223,8 @@ export class StartTaskCloudComponent implements OnInit, OnDestroy { get priorityController(): AbstractControl { return this.taskForm.get('priority'); } + + onFormSelect(formKey: string) { + this.formKey = formKey || ''; + } } diff --git a/lib/process-services-cloud/src/lib/task/start-task/models/start-task-cloud-request.model.ts b/lib/process-services-cloud/src/lib/task/start-task/models/start-task-cloud-request.model.ts index 6234f5636c..2981f90636 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/models/start-task-cloud-request.model.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/models/start-task-cloud-request.model.ts @@ -24,6 +24,7 @@ export class StartTaskCloudRequestModel { candidateUsers: string[]; candidateGroups: string[]; payloadType: string; + formKey: string; constructor(obj?: any) { if (obj) { @@ -34,6 +35,7 @@ export class StartTaskCloudRequestModel { this.dueDate = obj.dueDate || null; this.candidateUsers = obj.candidateUsers || null; this.candidateGroups = obj.candidateGroups || null; + this.formKey = obj.formKey || null; this.payloadType = 'CreateTaskPayload'; } } diff --git a/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts b/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts index 8535abf100..153cf55820 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/start-task-cloud.module.ts @@ -25,27 +25,31 @@ import { StartTaskCloudService } from './services/start-task-cloud.service'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { PeopleCloudComponent } from './components/people-cloud/people-cloud.component'; import { GroupCloudModule } from '../../group/group-cloud.module'; +import { TaskCloudService } from '../services/task-cloud.service'; +import { FormCloudModule } from '../../form/form-cloud.module'; @NgModule({ imports: [ - CommonModule, - PipeModule, + CommonModule, + PipeModule, TemplateModule, FlexLayoutModule, MaterialModule, FormsModule, ReactiveFormsModule, GroupCloudModule, - GroupCloudModule, - CoreModule + CoreModule, + FormCloudModule ], declarations: [StartTaskCloudComponent, PeopleCloudComponent], providers: [ - StartTaskCloudService - ], + StartTaskCloudService, + TaskCloudService + ], exports: [ StartTaskCloudComponent, PeopleCloudComponent ] }) -export class StartTaskCloudModule { } +export class StartTaskCloudModule { +} diff --git a/lib/process-services-cloud/src/lib/task/task-cloud.module.ts b/lib/process-services-cloud/src/lib/task/task-cloud.module.ts index ce53b22747..cb2e48c10b 100644 --- a/lib/process-services-cloud/src/lib/task/task-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/task/task-cloud.module.ts @@ -21,6 +21,7 @@ import { TaskFiltersCloudModule } from './task-filters/task-filters-cloud.module import { StartTaskCloudModule } from './start-task/start-task-cloud.module'; import { TaskHeaderCloudModule } from './task-header/task-header-cloud.module'; import { TaskDirectiveModule } from './directives/task-directive.module'; +import { TaskFormModule } from './task-form/task-form.module'; @NgModule({ imports: [ @@ -28,14 +29,16 @@ import { TaskDirectiveModule } from './directives/task-directive.module'; TaskFiltersCloudModule, StartTaskCloudModule, TaskHeaderCloudModule, - TaskDirectiveModule + TaskDirectiveModule, + TaskFormModule ], exports: [ TaskListCloudModule, TaskFiltersCloudModule, StartTaskCloudModule, TaskHeaderCloudModule, - TaskDirectiveModule + TaskDirectiveModule, + TaskFormModule ] }) export class TaskCloudModule { } diff --git a/lib/process-services-cloud/src/lib/task/task-filters/public-api.ts b/lib/process-services-cloud/src/lib/task/task-filters/public-api.ts index 94c87cf5d0..c19bbea7f8 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/public-api.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/public-api.ts @@ -17,6 +17,9 @@ export * from './components/task-filters-cloud.component'; export * from './components/edit-task-filter-cloud.component'; + export * from './models/filter-cloud.model'; + export * from './services/task-filter-cloud.service'; + export * from './task-filters-cloud.module'; diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html similarity index 100% rename from lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.html rename to lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.scss b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.scss similarity index 100% rename from lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.scss rename to lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.scss diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts similarity index 95% rename from lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts rename to lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts index 4de95293ca..15202f0bdf 100644 --- a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts @@ -15,12 +15,14 @@ * limitations under the License. */ -import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; -import { FormCloudModule } from '../form-cloud.module'; +import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; +import { TaskCloudModule } from '../../task-cloud.module'; +import { TaskDirectiveModule } from '../../directives/task-directive.module'; import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { TaskFormCloudComponent } from './task-form-cloud.component'; import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; -import { TaskCloudService, TaskDetailsCloudModel } from '../../task/public-api'; +import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; +import { TaskCloudService } from '../../services/task-cloud.service'; import { of } from 'rxjs'; import { DebugElement, CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; import { By } from '@angular/platform-browser'; @@ -52,14 +54,14 @@ describe('TaskFormCloudComponent', () => { let fixture: ComponentFixture<TaskFormCloudComponent>; setupTestBed({ - imports: [ProcessServiceCloudTestingModule, FormCloudModule], + imports: [ProcessServiceCloudTestingModule, TaskCloudModule, TaskDirectiveModule], schemas: [CUSTOM_ELEMENTS_SCHEMA] }); beforeEach(() => { taskDetails.status = 'ASSIGNED'; identityUserService = TestBed.get(IdentityUserService); - getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({username: 'admin.adf'}); + getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' }); taskCloudService = TestBed.get(TaskCloudService); getTaskSpy = spyOn(taskCloudService, 'getTaskById').and.returnValue(of(new TaskDetailsCloudModel(taskDetails))); @@ -74,6 +76,7 @@ describe('TaskFormCloudComponent', () => { }); describe('Complete button', () => { + it('should show complete button when status is ASSIGNED', async(() => { component.appName = 'app1'; component.taskId = 'task1'; @@ -115,6 +118,7 @@ describe('TaskFormCloudComponent', () => { }); describe('Claim/Unclaim buttons', () => { + it('should show unclaim button when status is ASSIGNED', async(() => { component.appName = 'app1'; component.taskId = 'task1'; @@ -185,6 +189,7 @@ describe('TaskFormCloudComponent', () => { }); describe('Cancel button', () => { + it('should show cancel button by default', async(() => { component.appName = 'app1'; component.taskId = 'task1'; @@ -212,6 +217,7 @@ describe('TaskFormCloudComponent', () => { }); describe('Inputs', () => { + it('should not show complete/claim/unclaim buttons when readOnly=true', async(() => { component.appName = 'app1'; component.taskId = 'task1'; @@ -258,6 +264,7 @@ describe('TaskFormCloudComponent', () => { }); describe('Events', () => { + it('should emit cancelClick when cancel button is clicked', (done) => { component.appName = 'app1'; component.taskId = 'task1'; diff --git a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts similarity index 95% rename from lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts rename to lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index eabf87a18c..c0d34b2f5e 100644 --- a/lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -19,8 +19,9 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; -import { FormCloud } from '../models/form-cloud.model'; -import { TaskDetailsCloudModel, TaskCloudService } from '../../task/public-api'; +import { FormCloud } from '../../../form/models/form-cloud.model'; +import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; +import { TaskCloudService } from '../../services/task-cloud.service'; import { IdentityUserService, FormOutcomeModel } from '@alfresco/adf-core'; @Component({ @@ -91,7 +92,6 @@ export class TaskFormCloudComponent implements OnChanges { constructor( private taskCloudService: TaskCloudService, private identityUserService: IdentityUserService) { - } ngOnChanges(changes: SimpleChanges) { diff --git a/lib/process-services-cloud/src/lib/task/task-form/public-api.ts b/lib/process-services-cloud/src/lib/task/task-form/public-api.ts new file mode 100644 index 0000000000..01ca90c2af --- /dev/null +++ b/lib/process-services-cloud/src/lib/task/task-form/public-api.ts @@ -0,0 +1,20 @@ +/*! + * @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. + */ + +export * from './components/task-form-cloud.component'; + +export * from './task-form.module'; diff --git a/lib/process-services-cloud/src/lib/task/task.module.ts b/lib/process-services-cloud/src/lib/task/task-form/task-form.module.ts similarity index 54% rename from lib/process-services-cloud/src/lib/task/task.module.ts rename to lib/process-services-cloud/src/lib/task/task-form/task-form.module.ts index 926e213c5f..66a83227cc 100644 --- a/lib/process-services-cloud/src/lib/task/task.module.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/task-form.module.ts @@ -16,24 +16,27 @@ */ import { NgModule } from '@angular/core'; -import { CompleteTaskDirective } from './directives/complete-task.directive'; -import { TaskCloudService } from './services/task-cloud.service'; -import { ClaimTaskDirective } from './directives/claim-task.directive'; -import { UnClaimTaskDirective } from './directives/unclaim-task.directive'; +import { CommonModule } from '@angular/common'; +import { MaterialModule } from '../../material.module'; +import { FormCloudModule } from '../../form/form-cloud.module'; +import { TaskDirectiveModule } from '../directives/task-directive.module'; + +import { TaskFormCloudComponent } from './components/task-form-cloud.component'; +import { CoreModule } from '@alfresco/adf-core'; @NgModule({ + imports: [ + CoreModule, + CommonModule, + MaterialModule, + FormCloudModule, + TaskDirectiveModule + ], declarations: [ - CompleteTaskDirective, - ClaimTaskDirective, - UnClaimTaskDirective + TaskFormCloudComponent ], exports: [ - CompleteTaskDirective, - ClaimTaskDirective, - UnClaimTaskDirective - ], - providers: [ - TaskCloudService + TaskFormCloudComponent ] }) -export class TaskModule { } +export class TaskFormModule { } diff --git a/lib/process-services-cloud/src/public-api.ts b/lib/process-services-cloud/src/public-api.ts index 5bbf0fc44a..39f3f4709a 100644 --- a/lib/process-services-cloud/src/public-api.ts +++ b/lib/process-services-cloud/src/public-api.ts @@ -21,5 +21,5 @@ export * from './lib/app/public-api'; export * from './lib/process/public-api'; export * from './lib/task/public-api'; export * from './lib/group/public-api'; -export * from './lib/services/public-api'; export * from './lib/form/public-api'; +export * from './lib/services/public-api'; From c9977c58fa3de1aad712a4433f5d9a93f0fcdb0e Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Tue, 23 Apr 2019 19:56:04 +0300 Subject: [PATCH 149/208] [ADF-4198] - fix user info close on esc key (#4644) --- .../userinfo/components/user-info.component.html | 2 +- .../userinfo/components/user-info.component.ts | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/core/userinfo/components/user-info.component.html b/lib/core/userinfo/components/user-info.component.html index 5303a54eb5..185ebd80a7 100644 --- a/lib/core/userinfo/components/user-info.component.html +++ b/lib/core/userinfo/components/user-info.component.html @@ -1,4 +1,4 @@ -<div id="userinfo_container" [class.adf-userinfo-name-right]="showOnRight()" +<div id="userinfo_container" [class.adf-userinfo-name-right]="showOnRight()" (keyup)="onKeyPress($event)" class="adf-userinfo-container" *ngIf="isLoggedIn()"> <ng-container *ngIf="showName"> diff --git a/lib/core/userinfo/components/user-info.component.ts b/lib/core/userinfo/components/user-info.component.ts index d5628b2d75..b4946f5a1a 100644 --- a/lib/core/userinfo/components/user-info.component.ts +++ b/lib/core/userinfo/components/user-info.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnInit, ViewEncapsulation, ViewChild } from '@angular/core'; import { AuthenticationService } from '../../services/authentication.service'; import { BpmUserModel } from './../models/bpm-user.model'; import { EcmUserModel } from './../models/ecm-user.model'; @@ -24,6 +24,7 @@ import { BpmUserService } from './../services/bpm-user.service'; import { EcmUserService } from './../services/ecm-user.service'; import { IdentityUserService } from '../services/identity-user.service'; import { of, Observable } from 'rxjs'; +import { MatMenuTrigger } from '@angular/material'; @Component({ selector: 'adf-userinfo', @@ -33,6 +34,8 @@ import { of, Observable } from 'rxjs'; }) export class UserInfoComponent implements OnInit { + @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger; + /** Custom path for the background banner image for ACS users. */ @Input() ecmBackgroundImage: string = './assets/images/ecm-background.png'; @@ -87,6 +90,16 @@ export class UserInfoComponent implements OnInit { } } + onKeyPress(event: KeyboardEvent) { + this.closeUserModal(event); + } + + private closeUserModal($event: KeyboardEvent) { + if ($event.keyCode === 27 ) { + this.trigger.closeMenu(); + } + } + isLoggedIn(): boolean { return this.authService.isLoggedIn(); } From d52671823ed00a544aaa512a4ac54a1c1e1450f5 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 23 Apr 2019 18:03:36 +0100 Subject: [PATCH 150/208] fix lint --- e2e/process-services-cloud/task-list-selection.e2e.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/process-services-cloud/task-list-selection.e2e.ts b/e2e/process-services-cloud/task-list-selection.e2e.ts index ca3df24cc2..109a31e805 100644 --- a/e2e/process-services-cloud/task-list-selection.e2e.ts +++ b/e2e/process-services-cloud/task-list-selection.e2e.ts @@ -104,7 +104,6 @@ describe('Task list cloud - selection', () => { tasksCloudDemoPage.clickAppButton(); tasksCloudDemoPage.taskListCloudComponent().getDataTable().waitForTableBody(); - tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(tasks[0]); tasksCloudDemoPage.taskListCloudComponent().selectRow(tasks[0]); tasksCloudDemoPage.taskListCloudComponent().checkRowIsSelected(tasks[0]); From a6552dbb176454cf74251be3eb2cc8d13582c062 Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Tue, 23 Apr 2019 20:34:39 +0100 Subject: [PATCH 151/208] [ADF-4387] Configuration option to change the dafault viewer zoom (#4645) * [ADF-4387] Configuration option to change the dafault viewer zoom --- docs/.DS_Store | Bin 6148 -> 8196 bytes docs/core/components/viewer.component.md | 17 ++ lib/core/app-config/schema.json | 14 ++ .../components/imgViewer.component.spec.ts | 39 ++++- .../viewer/components/imgViewer.component.ts | 22 ++- .../components/pdfViewer.component.spec.ts | 161 ++++++++++++++++++ .../viewer/components/pdfViewer.component.ts | 87 ++++++---- 7 files changed, 307 insertions(+), 33 deletions(-) diff --git a/docs/.DS_Store b/docs/.DS_Store index f87d80dfc55d4b79a2470dd568c344af60b012ba..648749ffc579fe20a382fe809e5b74452fadfcfa 100644 GIT binary patch literal 8196 zcmeHMO>YuG7=8y(7i=R3(~sL;OgzvADwZau31WNb!NiEsgPL|1kZxRd$?j5G5yQp! z7pndO;~z0zJo-cY0s6eNTe2+FdQuZ+$jm#;yw6PLd7qix0U{E$Ub95BLPQ!e+x%4& zGZOc6o=T~xWeHXQPZW?xEqvDLWXfALC<YV*iUGxdVn8wQKQMr2HYe?z=YH6$O2vR; zU@jTp^Fc>uTaD}}wDRacA+G?i88pj;I_?1yqer$H*->aE6k~?B2N6L<bj1)M9Q``G z!&W0Z3T+4{5yDACGmGekBINAA>C&A<HMFW!3@8Ss8Q{D70vTkILu(WF_YT>6w%agm z*Mtvmt2@Xyf69a!x0&+3Z_rD!fNx`j1|4EFuD8ff;6F{_8{|@lx<CXN!9=!^1N?fh zj`rpxUM$bVJMeE|#sIVXsCjgRF&fkJi?<1U23{_&ATiI6^Zd-d-;MbAYIbeQ4~oU_ zB9+cux_m{`a$0UN_q=}S_UnNW^!%FPJ>_o?jNs6W>W^I49@h=?vDNDD=da&$oxrf1 zmM6hhvjvxDPb{bD_G@m>Y5H=Udf1_9SuMMtUmXlKDwTr1QQR69^g*e7yIjz>%9Y_T zt1aIsZSNg)PF@XO58r&iYLG;9aMHE#`?&mw+L(!>y64!g(`Ep2mYQIwf%y26+aMX! zlmV}}CUW5YIEsjmIJk&RLI<gD35*6mc%f`VJyUa}w-f#gQY9Q=Mzs)k#=jtUGLGrb z30xjZ^W=J<O?)oUOJ+5JU%Ch{^>1T_UQ)Z6cZspG^pJMxF742L*cob<yX`c#+ZN?s zv$0-|2Cv$|OsxF`zr_3O50NoNfBDynUWTH#3VLaClLcL=6bpL!*5;I+Pq8|rbM^cl zoxkBKq41nkgaMs*z-xC_B;>gh=Q9h|d&qotSU}my2*{Hrj#z|$7wY!l-ITFwqs8L- zq-F)5J#l0Xe&MOM2K-En+=Fq<HJpHa4xa75Jt&1|J)X5Xxf|nXCRe3-U?3eXa)s~z zyLg<d-vQ<!>S~ROfk_5LW~aVWL)+Oa;$(Mt%h%C(5OuKM2pLvFP{`{zth|oHj{h)3 iU56_>RwFwKEn1NN`VRq<Z@B9D&u`=E`7gCNPsK0wH1j+F delta 138 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGjUEV6q~50D9Qwq2a6>#6f>kU=rZIn<Zmoo z&N$gXhGp_Y5$VlbB8-e1OYX2NX6N7#WCkh+0s(Fy;R-TlW8rt^$^0^oAbUUtv4Cix Pp&*OEVw>Z6<}d>Q_gxh1 diff --git a/docs/core/components/viewer.component.md b/docs/core/components/viewer.component.md index 867edd47a8..a2a23ea68d 100644 --- a/docs/core/components/viewer.component.md +++ b/docs/core/components/viewer.component.md @@ -467,6 +467,23 @@ You can enable a custom "More actions" menu by providing at least one action ins ![More actions](../../docassets/images/viewer-more-actions.png) +#### Custom zoom scaling + +You can set a default zoom scaling value for pdf viewer by adding the following code in `app.config.json`. +Note: For the pdf viewer the value has to be within the range of 25 - 1000. + +"adf-viewer": { + "pdf-viewer-scaling": 150 + } + +In the same way you can set a default zoom scaling value for the image viewer by adding the following code in `app.config.json`. + +"adf-viewer": { + "image-viewer-scaling": 150 + } + +By default the viewer's zoom scaling is set to 100%. + ### Printing You can configure the Viewer to let the user print the displayed content. The diff --git a/lib/core/app-config/schema.json b/lib/core/app-config/schema.json index bf6809bf16..1cb940c240 100644 --- a/lib/core/app-config/schema.json +++ b/lib/core/app-config/schema.json @@ -1325,6 +1325,20 @@ } } } + }, + "adf-viewer": { + "description": "Viewer default properties", + "type": "object", + "properties": { + "pdf-viewer-scaling": { + "type": "number", + "minimum": 25, + "maximum": 1000 + }, + "image-viewer-scaling": { + "type": "number" + } + } } } } diff --git a/lib/core/viewer/components/imgViewer.component.spec.ts b/lib/core/viewer/components/imgViewer.component.spec.ts index d5cf5bac2d..6c22628191 100644 --- a/lib/core/viewer/components/imgViewer.component.spec.ts +++ b/lib/core/viewer/components/imgViewer.component.spec.ts @@ -22,6 +22,7 @@ import { ContentService } from '../../services/content.service'; import { ImgViewerComponent } from './imgViewer.component'; import { setupTestBed } from '../../testing/setupTestBed'; import { CoreModule } from '../../core.module'; +import { AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core'; describe('Test Img viewer component ', () => { @@ -32,12 +33,15 @@ describe('Test Img viewer component ', () => { function createFakeBlob() { const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='); - return new Blob([data], {type: 'image/png'}); + return new Blob([data], { type: 'image/png' }); } setupTestBed({ imports: [ CoreModule.forRoot() + ], + providers: [ + { provide: AppConfigService, useClass: AppConfigServiceMock } ] }); @@ -250,4 +254,37 @@ describe('Test Img viewer component ', () => { }).not.toThrow(new Error('Attribute urlFile or blobFile is required')); expect(component.urlFile).toEqual('fake-blob-url'); }); + + describe('Zoom customization', () => { + + describe('default value', () => { + + it('should use default zoom if is not present a custom zoom in the app.config', () => { + expect(component.scaleX).toBe(1.0); + expect(component.scaleY).toBe(1.0); + }); + + }); + + describe('custom value', () => { + + beforeEach(() => { + const appConfig: AppConfigService = TestBed.get(AppConfigService); + appConfig.config['adf-viewer.image-viewer-scaling'] = 70; + component.initializeScaling(); + }); + + it('should use the custom zoom if it is present in the app.config', (done) => { + fixture.detectChanges(); + + fixture.whenStable().then(() => { + expect(component.scaleX).toBe(0.70); + expect(component.scaleY).toBe(0.70); + done(); + }); + }); + }); + + }); + }); diff --git a/lib/core/viewer/components/imgViewer.component.ts b/lib/core/viewer/components/imgViewer.component.ts index e6c176cd76..016387aba7 100644 --- a/lib/core/viewer/components/imgViewer.component.ts +++ b/lib/core/viewer/components/imgViewer.component.ts @@ -15,8 +15,18 @@ * limitations under the License. */ -import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation, ElementRef, OnInit, OnDestroy } from '@angular/core'; +import { + Component, + Input, + OnChanges, + SimpleChanges, + ViewEncapsulation, + ElementRef, + OnInit, + OnDestroy +} from '@angular/core'; import { ContentService } from '../../services/content.service'; +import { AppConfigService } from './../../app-config/app-config.service'; @Component({ selector: 'adf-img-viewer', @@ -60,8 +70,18 @@ export class ImgViewerComponent implements OnInit, OnChanges, OnDestroy { private element: HTMLElement; constructor( + private appConfigService: AppConfigService, private contentService: ContentService, private el: ElementRef) { + this.initializeScaling(); + } + + initializeScaling() { + const scaling = this.appConfigService.get<number>('adf-viewer.image-viewer-scaling', undefined) / 100; + if (scaling) { + this.scaleX = scaling; + this.scaleY = scaling; + } } ngOnInit() { diff --git a/lib/core/viewer/components/pdfViewer.component.spec.ts b/lib/core/viewer/components/pdfViewer.component.spec.ts index bf27dac71a..073f9af22d 100644 --- a/lib/core/viewer/components/pdfViewer.component.spec.ts +++ b/lib/core/viewer/components/pdfViewer.component.spec.ts @@ -28,6 +28,7 @@ import { CoreModule } from '../../core.module'; import { TranslationService } from '../../services/translation.service'; import { TranslationMock } from '../../mock/translation.service.mock'; import { take } from 'rxjs/operators'; +import { AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core'; declare const pdfjsLib: any; @@ -137,6 +138,7 @@ describe('Test PdfViewer component', () => { ], providers: [ { provide: TranslationService, useClass: TranslationMock }, + { provide: AppConfigService, useClass: AppConfigServiceMock }, { provide: MatDialog, useValue: { open: () => { @@ -634,4 +636,163 @@ describe('Test PdfViewer component', () => { }); + describe('Zoom customization', () => { + + describe('default value', () => { + + let fixtureUrlTestComponent: ComponentFixture<UrlTestComponent>; + let componentUrlTestComponent: UrlTestComponent; + let elementUrlTestComponent: HTMLElement; + + beforeEach((done) => { + fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); + componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; + elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; + + fixtureUrlTestComponent.detectChanges(); + + componentUrlTestComponent.pdfViewerComponent.rendered + .pipe(take(1)) + .subscribe(() => { + done(); + }); + }); + + afterEach(() => { + document.body.removeChild(elementUrlTestComponent); + }); + + it('should use default zoom if is not present a custom zoom in the app.config', (done) => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + + fixtureUrlTestComponent.detectChanges(); + fixtureUrlTestComponent.whenStable().then(() => { + expect(componentUrlTestComponent.pdfViewerComponent.currentScale).toBe(1); + done(); + }); + }); + }); + + describe('custom value', () => { + + let fixtureUrlTestComponent: ComponentFixture<UrlTestComponent>; + let componentUrlTestComponent: UrlTestComponent; + let elementUrlTestComponent: HTMLElement; + + beforeEach((done) => { + const appConfig: AppConfigService = TestBed.get(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 80; + + fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); + componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; + elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; + + fixtureUrlTestComponent.detectChanges(); + + componentUrlTestComponent.pdfViewerComponent.rendered + .pipe(take(1)) + .subscribe(() => { + done(); + }); + }); + + afterEach(() => { + document.body.removeChild(elementUrlTestComponent); + }); + + it('should use the custom zoom if it is present in the app.config', (done) => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + + fixtureUrlTestComponent.detectChanges(); + fixtureUrlTestComponent.whenStable().then(() => { + expect(componentUrlTestComponent.pdfViewerComponent.currentScale).toBe(0.8); + done(); + }); + }); + }); + + describe('less than the minimum allowed value', () => { + + let fixtureUrlTestComponent: ComponentFixture<UrlTestComponent>; + let componentUrlTestComponent: UrlTestComponent; + let elementUrlTestComponent: HTMLElement; + + beforeEach((done) => { + const appConfig: AppConfigService = TestBed.get(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 10; + + fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); + componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; + elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; + + fixtureUrlTestComponent.detectChanges(); + + componentUrlTestComponent.pdfViewerComponent.rendered + .pipe(take(1)) + .subscribe(() => { + done(); + }); + }); + + afterEach(() => { + document.body.removeChild(elementUrlTestComponent); + }); + + it('should use the minimum scale zoom if the value given in app.config is less than the minimum allowed scale', (done) => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + + fixtureUrlTestComponent.detectChanges(); + + fixtureUrlTestComponent.whenStable().then(() => { + expect(componentUrlTestComponent.pdfViewerComponent.currentScale).toBe(0.25); + done(); + }); + }); + + }); + + describe('greater than the maximum allowed value', () => { + + let fixtureUrlTestComponent: ComponentFixture<UrlTestComponent>; + let componentUrlTestComponent: UrlTestComponent; + let elementUrlTestComponent: HTMLElement; + + beforeEach((done) => { + const appConfig: AppConfigService = TestBed.get(AppConfigService); + appConfig.config['adf-viewer.pdf-viewer-scaling'] = 55555; + + fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); + componentUrlTestComponent = fixtureUrlTestComponent.componentInstance; + elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; + + fixtureUrlTestComponent.detectChanges(); + + componentUrlTestComponent.pdfViewerComponent.rendered + .pipe(take(1)) + .subscribe(() => { + done(); + }); + }); + + afterEach(() => { + document.body.removeChild(elementUrlTestComponent); + }); + + it('should use the maximum scale zoom if the value given in app.config is greater than the maximum allowed scale', (done) => { + spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => { + }); + + fixtureUrlTestComponent.detectChanges(); + fixtureUrlTestComponent.whenStable().then(() => { + expect(componentUrlTestComponent.pdfViewerComponent.currentScale).toBe(10); + done(); + + }); + + }); + }); + }); }); diff --git a/lib/core/viewer/components/pdfViewer.component.ts b/lib/core/viewer/components/pdfViewer.component.ts index beda5faa12..e0799de6d5 100644 --- a/lib/core/viewer/components/pdfViewer.component.ts +++ b/lib/core/viewer/components/pdfViewer.component.ts @@ -114,6 +114,26 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { this.onPagesLoaded = this.onPagesLoaded.bind(this); this.onPageRendered = this.onPageRendered.bind(this); this.randomPdfId = this.generateUuid(); + this.currentScale = this.getUserScaling(); + } + + getUserScaling(): number { + const scaleConfig = this.appConfigService.get<number>('adf-viewer.pdf-viewer-scaling', undefined) / 100; + if (scaleConfig) { + return this.checkLimits(scaleConfig); + } else { + return 1; + } + } + + checkLimits(scaleConfig: number): number { + if (scaleConfig > this.MAX_SCALE) { + return this.MAX_SCALE; + } else if (scaleConfig < this.MIN_SCALE) { + return this.MIN_SCALE; + } else { + return scaleConfig; + } } ngOnChanges(changes: SimpleChanges) { @@ -235,10 +255,10 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { scalePage(scaleMode) { this.currentScaleMode = scaleMode; - if (this.pdfViewer) { + const viewerContainer = document.getElementById(`${this.randomPdfId}-viewer-main-container`); + const documentContainer = document.getElementById(`${this.randomPdfId}-viewer-pdf-viewer`); - const viewerContainer = document.getElementById(`${this.randomPdfId}-viewer-main-container`); - const documentContainer = document.getElementById(`${this.randomPdfId}-viewer-pdf-viewer`); + if (this.pdfViewer && documentContainer) { let widthContainer; let heightContainer; @@ -257,37 +277,42 @@ export class PdfViewerComponent implements OnChanges, OnDestroy { const pageWidthScale = (widthContainer - padding) / currentPage.width * currentPage.scale; const pageHeightScale = (heightContainer - padding) / currentPage.width * currentPage.scale; - let scale; + let scale = this.getUserScaling(); + if (!scale) { + switch (this.currentScaleMode) { + case 'page-actual': + scale = 1; + break; + case 'page-width': + scale = pageWidthScale; + break; + case 'page-height': + scale = pageHeightScale; + break; + case 'page-fit': + scale = Math.min(pageWidthScale, pageHeightScale); + break; + case 'auto': + let horizontalScale; + if (this.isLandscape) { + horizontalScale = Math.min(pageHeightScale, pageWidthScale); + } else { + horizontalScale = pageWidthScale; + } + horizontalScale = Math.round(horizontalScale); + scale = Math.min(this.MAX_AUTO_SCALE, horizontalScale); - switch (this.currentScaleMode) { - case 'page-actual': - scale = 1; - break; - case 'page-width': - scale = pageWidthScale; - break; - case 'page-height': - scale = pageHeightScale; - break; - case 'page-fit': - scale = Math.min(pageWidthScale, pageHeightScale); - break; - case 'auto': - let horizontalScale; - if (this.isLandscape) { - horizontalScale = Math.min(pageHeightScale, pageWidthScale); - } else { - horizontalScale = pageWidthScale; - } - scale = Math.min(this.MAX_AUTO_SCALE, horizontalScale); + break; + default: + this.logService.error('pdfViewSetScale: \'' + scaleMode + '\' is an unknown zoom value.'); + return; + } - break; - default: - this.logService.error('pdfViewSetScale: \'' + scaleMode + '\' is an unknown zoom value.'); - return; + this.setScaleUpdatePages(scale); + } else { + this.currentScale = 0; + this.setScaleUpdatePages(scale); } - - this.setScaleUpdatePages(scale); } } From d4e7981b1dcac6d46a3dcf9577ad1c103d16a644 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 23 Apr 2019 23:41:19 +0100 Subject: [PATCH 152/208] simpleapp rename --- e2e/resources/activiti7/simpleApp.zip | Bin 3184 -> 0 bytes e2e/util/resources.js | 2 +- scripts/check-activiti-env.js | 19 ++++++++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) delete mode 100644 e2e/resources/activiti7/simpleApp.zip diff --git a/e2e/resources/activiti7/simpleApp.zip b/e2e/resources/activiti7/simpleApp.zip deleted file mode 100644 index d27baa2f4e0f583e4e9bd11c23774656b304d3c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3184 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 TGYegfh4z%uN|sDh1b}}5vU>uL diff --git a/e2e/util/resources.js b/e2e/util/resources.js index de5bb79f6f..b831d960b8 100644 --- a/e2e/util/resources.js +++ b/e2e/util/resources.js @@ -520,7 +520,7 @@ exports.ACTIVITI7_APPS = { }, SIMPLE_APP: { name: "simpleapp", - file_location: "/resources/activiti7/simpleApp.zip", + file_location: "/resources/activiti7/simpleapp.zip", processes: { processwithvariables: "processwithvariables", simpleProcess: "simpleProcess" diff --git a/scripts/check-activiti-env.js b/scripts/check-activiti-env.js index f87a0078a4..550b9aeb6c 100755 --- a/scripts/check-activiti-env.js +++ b/scripts/check-activiti-env.js @@ -69,17 +69,20 @@ async function checkIfAppIsReleased(apiService, absentApps) { for (let i = 0; i < absentApps.length; i++) { let currentAbsentApp = absentApps[i]; - let isPresent = listAppsInModeler.find((currentApp) => { + let app = listAppsInModeler.find((currentApp) => { return currentAbsentApp.name === currentApp.entry.name; }); - if (!isPresent) { - console.log(`uplodare ` + currentAbsentApp.name); + + if (!app) { let uploadedApp = await importApp(apiService, currentAbsentApp); if (uploadedApp) { await releaseApp(apiService, uploadedApp); await deployApp(apiService, uploadedApp); } + }else{ + await releaseApp(apiService, app); + await deployApp(apiService, app); } } } @@ -124,15 +127,16 @@ async function importApp(apiService, app) { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to upload the project ${app.name} ` + error); - process.exit(1); + if (error.status !== 409) { + console.log(`Not possible to upload the project ${app.name} ` + error.status); + process.exit(1); + } } } async function releaseApp(apiService, app) { const url = `${config.hostBpm}alfresco-modeling-service/v1/projects/${app.entry.id}/releases`; - console.log(url); const pathParams = {}, queryParams = {}, headerParams = {}, formParams = {}, bodyParam = {}, @@ -142,7 +146,7 @@ async function releaseApp(apiService, app) { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to release the project ${app.entry.name} ` + error); + console.log(`Not possible to release the project ${app.entry.name} ` + JSON.stringify(error)); process.exit(1); } @@ -159,6 +163,7 @@ async function getDeployedApplicationsByStatus(apiService, status) { try { data = await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); + return data.list.entries; } catch (error) { console.log(`Not possible get the application from alfresco-deployment-service` + error); From 32ba281b700967632ac42848c39220271f3f4c20 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Tue, 23 Apr 2019 23:41:44 +0100 Subject: [PATCH 153/208] simpleapp upload --- e2e/resources/activiti7/simpleapp.zip | Bin 0 -> 3199 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 e2e/resources/activiti7/simpleapp.zip diff --git a/e2e/resources/activiti7/simpleapp.zip b/e2e/resources/activiti7/simpleapp.zip new file mode 100644 index 0000000000000000000000000000000000000000..5614312c7346d9e4f0fec66627bf8e5ca95f5271 GIT binary patch literal 3199 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 literal 0 HcmV?d00001 From c6933e169a4632aa7dc70cfb1d73f8d79a9143b0 Mon Sep 17 00:00:00 2001 From: dhrn <dharan.g@muraai.com> Date: Fri, 19 Apr 2019 19:33:21 +0530 Subject: [PATCH 154/208] [ADF-4359] - Add the possibility to chose which panel to show first in info-drawer --- .../file-view/file-view.component.html | 17 ++++- .../file-view/file-view.component.ts | 6 ++ .../content-metadata-card.component.html | 1 + .../content-metadata-card.component.spec.ts | 14 ++++ .../content-metadata-card.component.ts | 16 +++- .../content-metadata.component.html | 6 +- .../content-metadata.component.spec.ts | 74 ++++++++++++++++++- .../content-metadata.component.ts | 8 ++ .../components/content-metadata/mock-data.ts | 74 +++++++++++++++++++ 9 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 lib/content-services/content-metadata/components/content-metadata/mock-data.ts diff --git a/demo-shell/src/app/components/file-view/file-view.component.html b/demo-shell/src/app/components/file-view/file-view.component.html index c2586757cd..d14163bbaf 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.html +++ b/demo-shell/src/app/components/file-view/file-view.component.html @@ -12,12 +12,14 @@ [multi]="multi" [preset]="customPreset" [readOnly]="isReadOnly" + [displayAspect]="showAspect" [displayDefaultProperties]="displayDefaultProperties" [displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card> <adf-content-metadata-card *ngIf="!isPreset" [node]="node" [multi]="multi" [readOnly]="isReadOnly" + [displayAspect]="showAspect" [displayDefaultProperties]="displayDefaultProperties" [displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card> @@ -71,6 +73,19 @@ </mat-slide-toggle> </p> + <p class="toggle"> + + <mat-form-field floatPlaceholder="float"> + <input matInput + placeholder="Display Aspect" + [(ngModel)]="desiredAspect"> + </mat-form-field> + + <button mat-raised-button (click)="applyAspect()" color="primary"> + Apply Aspect + </button> + </p> + <p class="toggle"> <ng-container *ngIf="isPreset"> <mat-form-field floatPlaceholder="float"> @@ -118,7 +133,7 @@ <p class="toggle"> <ng-container *ngIf="customName"> - <mat-form-field floatPlaceholder="float"> + <mat-form-field floatLabel="never"> <input matInput placeholder="Custom Name" [(ngModel)]="displayName" diff --git a/demo-shell/src/app/components/file-view/file-view.component.ts b/demo-shell/src/app/components/file-view/file-view.component.ts index f014d8fca0..e5b4187f87 100644 --- a/demo-shell/src/app/components/file-view/file-view.component.ts +++ b/demo-shell/src/app/components/file-view/file-view.component.ts @@ -55,6 +55,8 @@ export class FileViewComponent implements OnInit { isCommentEnabled = false; showTabWithIcon = false; showTabWithIconAndLabel = false; + desiredAspect: string = null; + showAspect: string = null; constructor(private router: Router, private route: ActivatedRoute, @@ -188,4 +190,8 @@ export class FileViewComponent implements OnInit { this.isPreset = true; }, 100); } + + applyAspect() { + this.showAspect = this.desiredAspect; + } } diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html index 07068fd23f..6369ce8268 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.html @@ -7,6 +7,7 @@ [displayEmpty]="displayEmpty" [editable]="editable" [multi]="multi" + [displayAspect]="displayAspect" [preset]="preset"> </adf-content-metadata> </mat-card-content> diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts index 7c1f730fa1..0e5bb7ab4f 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts @@ -22,6 +22,7 @@ import { ContentMetadataCardComponent } from './content-metadata-card.component' import { ContentMetadataComponent } from '../content-metadata/content-metadata.component'; import { setupTestBed, AllowableOperationsEnum } from '@alfresco/adf-core'; import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { SimpleChange } from '@angular/core'; describe('ContentMetadataCardComponent', () => { @@ -189,4 +190,17 @@ describe('ContentMetadataCardComponent', () => { const button = fixture.debugElement.query(By.css('[data-automation-id="meta-data-card-toggle-edit"]')); expect(button).not.toBeNull(); }); + + it('should expand the card when custom display aspect is valid', () => { + expect(component.expanded).toBeFalsy(); + + let displayAspect = new SimpleChange(null , 'EXIF', true); + component.ngOnChanges({ displayAspect }); + expect(component.expanded).toBeTruthy(); + + displayAspect = new SimpleChange('EXIF' , null, false); + component.ngOnChanges({ displayAspect }); + expect(component.expanded).toBeTruthy(); + }); + }); diff --git a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts index 54084f0db3..ddd2f99577 100644 --- a/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata-card/content-metadata-card.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core'; import { Node } from '@alfresco/js-api'; import { ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; @@ -26,7 +26,7 @@ import { ContentService, AllowableOperationsEnum } from '@alfresco/adf-core'; encapsulation: ViewEncapsulation.None, host: { 'class': 'adf-content-metadata-card' } }) -export class ContentMetadataCardComponent { +export class ContentMetadataCardComponent implements OnChanges { /** (required) The node entity to fetch metadata about */ @Input() node: Node; @@ -37,6 +37,12 @@ export class ContentMetadataCardComponent { @Input() displayEmpty: boolean = false; + /** (optional) This flag displays desired aspect when open for the first time + * fields. + */ + @Input() + displayAspect: string = null; + /** (required) Name of the metadata preset, which defines aspects * and their properties. */ @@ -77,6 +83,12 @@ export class ContentMetadataCardComponent { constructor(private contentService: ContentService) { } + ngOnChanges(changes: SimpleChanges): void { + if (changes.displayAspect && changes.displayAspect.currentValue) { + this.expanded = true; + } + } + onDisplayDefaultPropertiesChange(): void { this.expanded = !this._displayDefaultProperties; } diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html index e1c344b2c9..8f4876110a 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html @@ -2,8 +2,8 @@ <mat-accordion displayMode="flat" [multi]="multi"> <mat-expansion-panel *ngIf="displayDefaultProperties" - [expanded]="!expanded" - [hideToggle]="!expanded" + [expanded]="!expanded || !displayAspect" + [hideToggle]="!expanded || !displayAspect" [attr.data-automation-id]="'adf-metadata-group-properties'" > <mat-expansion-panel-header> <mat-panel-title> @@ -23,7 +23,7 @@ <div *ngFor="let group of groupedProperties; let first = first;" class="adf-metadata-grouped-properties-container"> <mat-expansion-panel *ngIf="showGroup(group) || editable" [attr.data-automation-id]="'adf-metadata-group-' + group.title" - [expanded]="!displayDefaultProperties && first"> + [expanded]="canExpandTheCard(group) || !displayDefaultProperties && first"> <mat-expansion-panel-header> <mat-panel-title> {{ group.title | translate }} diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts index ac6bfd0dec..a3fe638500 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -27,10 +27,12 @@ import { } from '@alfresco/adf-core'; import { throwError, of } from 'rxjs'; import { ContentTestingModule } from '../../../testing/content.testing.module'; +import { mockGroupProperties } from './mock-data'; describe('ContentMetadataComponent', () => { let component: ContentMetadataComponent; let fixture: ComponentFixture<ContentMetadataComponent>; + let contentMetadataService: ContentMetadataService; let node: Node; let folderNode: Node; const preset = 'custom-preset'; @@ -43,6 +45,7 @@ describe('ContentMetadataComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(ContentMetadataComponent); component = fixture.componentInstance; + contentMetadataService = TestBed.get(ContentMetadataService); node = <Node> { id: 'node-id', aspectNames: [], @@ -147,11 +150,10 @@ describe('ContentMetadataComponent', () => { }); describe('Properties loading', () => { - let expectedNode, contentMetadataService: ContentMetadataService; + let expectedNode; beforeEach(() => { expectedNode = Object.assign({}, node, { name: 'some-modified-value' }); - contentMetadataService = TestBed.get(ContentMetadataService); fixture.detectChanges(); }); @@ -294,4 +296,72 @@ describe('ContentMetadataComponent', () => { expect(component.displayDefaultProperties).toBe(true); }); }); + + describe('Expand the panel', () => { + let expectedNode; + + beforeEach(() => { + expectedNode = Object.assign({}, node, {name: 'some-modified-value'}); + spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of(mockGroupProperties)); + component.ngOnChanges({node: new SimpleChange(node, expectedNode, false)}); + }); + + it('should open and update drawer with expand section dynamically', async(() => { + component.displayAspect = 'EXIF'; + component.expanded = true; + component.displayEmpty = true; + + fixture.detectChanges(); + const defaultProp = queryDom(fixture); + const exifProp = queryDom(fixture, 'EXIF'); + const customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeFalsy(); + expect(exifProp.componentInstance.expanded).toBeTruthy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); + + component.displayAspect = 'CUSTOM'; + fixture.detectChanges(); + const updatedDefault = queryDom(fixture); + const updatedExif = queryDom(fixture, 'EXIF'); + const updatedCustom = queryDom(fixture, 'CUSTOM'); + expect(updatedDefault.componentInstance.expanded).toBeFalsy(); + expect(updatedExif.componentInstance.expanded).toBeFalsy(); + expect(updatedCustom.componentInstance.expanded).toBeTruthy(); + + })); + + it('should not expand anything if input is wrong', async(() => { + component.displayAspect = 'XXXX'; + component.expanded = true; + component.displayEmpty = true; + + fixture.detectChanges(); + const defaultProp = queryDom(fixture); + const exifProp = queryDom(fixture, 'EXIF'); + const customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeFalsy(); + expect(exifProp.componentInstance.expanded).toBeFalsy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); + + })); + + it('should expand the properties section when input is null', async(() => { + component.displayAspect = null; + component.expanded = true; + component.displayEmpty = true; + + fixture.detectChanges(); + const defaultProp = queryDom(fixture); + const exifProp = queryDom(fixture, 'EXIF'); + const customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeTruthy(); + expect(exifProp.componentInstance.expanded).toBeFalsy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); + + })); + }); }); + +function queryDom(fixture: ComponentFixture<ContentMetadataComponent>, properties: string = 'properties') { + return fixture.debugElement.query(By.css(`[data-automation-id="adf-metadata-group-${properties}"]`)); +} diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts index d3c4004263..b6d769cafb 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts @@ -61,6 +61,10 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { @Input() displayDefaultProperties: boolean = true; + /** (Optional) shows the given aspect in the expanded card */ + @Input() + displayAspect: string = null; + basicProperties$: Observable<CardViewItem[]>; groupedProperties$: Observable<CardViewGroup[]>; disposableNodeUpdate: Subscription; @@ -118,4 +122,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { this.disposableNodeUpdate.unsubscribe(); } + public canExpandTheCard(group: CardViewGroup): boolean { + return group.title === this.displayAspect; + } + } diff --git a/lib/content-services/content-metadata/components/content-metadata/mock-data.ts b/lib/content-services/content-metadata/components/content-metadata/mock-data.ts new file mode 100644 index 0000000000..4ea3974bcd --- /dev/null +++ b/lib/content-services/content-metadata/components/content-metadata/mock-data.ts @@ -0,0 +1,74 @@ +/*! + * @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. + */ + +export const mockGroupProperties = [ + { + 'title': 'EXIF', + 'properties': [ + { + 'label': 'Image Width', + 'value': 363, + 'key': 'properties.exif:pixelXDimension', + 'default': null, + 'editable': true, + 'clickable': false, + 'icon': '', + 'data': null, + 'type': 'int', + 'multiline': false, + 'pipes': [], + 'clickCallBack': null, + displayValue: 400 + }, + { + 'label': 'Image Height', + 'value': 400, + 'key': 'properties.exif:pixelYDimension', + 'default': null, + 'editable': true, + 'clickable': false, + 'icon': '', + 'data': null, + 'type': 'int', + 'multiline': false, + 'pipes': [], + 'clickCallBack': null, + displayValue: 400 + } + ] + }, + { + 'title': 'CUSTOM', + 'properties': [ + { + 'label': 'Height', + 'value': 400, + 'key': 'properties.custom:abc', + 'default': null, + 'editable': true, + 'clickable': false, + 'icon': '', + 'data': null, + 'type': 'int', + 'multiline': false, + 'pipes': [], + 'clickCallBack': null, + displayValue: 400 + } + ] + } +]; From 262a0387463229f076ae579b799d114033616c30 Mon Sep 17 00:00:00 2001 From: dhrn <dharan.g@muraai.com> Date: Mon, 22 Apr 2019 12:20:47 +0530 Subject: [PATCH 155/208] * docs added --- .../components/content-metadata-card.component.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index 773ed6b807..c280ae6f69 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -34,6 +34,7 @@ Displays and edits metadata related to a node. | preset | `string` | | (required) Name of the metadata preset, which defines aspects and their properties. | | readOnly | `boolean` | false | (optional) This flag sets the metadata in read only mode preventing changes. | | displayDefaultProperties | `boolean` | | (optional) This flag displays/hides the metadata properties. | +| displayAspect | `string` | | (optional) This flag displays the desired metadata property in the expanded card | ## Details From 374da200d27cb03d444062d8793c063e905e55fc Mon Sep 17 00:00:00 2001 From: dhrn <dharan.g@muraai.com> Date: Tue, 23 Apr 2019 18:39:41 +0530 Subject: [PATCH 156/208] * e2e fixed --- e2e/content-services/metadata/metadata-properties.e2e.ts | 2 +- e2e/pages/adf/metadataViewPage.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/e2e/content-services/metadata/metadata-properties.e2e.ts b/e2e/content-services/metadata/metadata-properties.e2e.ts index 6afc23d447..94da213ea8 100644 --- a/e2e/content-services/metadata/metadata-properties.e2e.ts +++ b/e2e/content-services/metadata/metadata-properties.e2e.ts @@ -135,7 +135,7 @@ describe('CardView Component - properties', () => { metadataViewPage.clickOnInformationButton(); metadataViewPage.checkMetadataGroupIsNotExpand('EXIF'); - metadataViewPage.checkMetadataGroupIsNotExpand('properties'); + metadataViewPage.checkMetadataGroupIsExpand('properties'); metadataViewPage.clickMetadataGroup('properties'); diff --git a/e2e/pages/adf/metadataViewPage.ts b/e2e/pages/adf/metadataViewPage.ts index 4a247f7364..0ab21906ba 100644 --- a/e2e/pages/adf/metadataViewPage.ts +++ b/e2e/pages/adf/metadataViewPage.ts @@ -115,6 +115,7 @@ export class MetadataViewPage { editIconClick(): promise.Promise<void> { BrowserVisibility.waitUntilElementIsVisible(this.editIcon); + BrowserVisibility.waitUntilElementIsClickable(this.editIcon); return this.editIcon.click(); } @@ -167,7 +168,7 @@ export class MetadataViewPage { editPropertyIconIsDisplayed(propertyName: string) { const editPropertyIcon = element(by.css('mat-icon[data-automation-id="card-textitem-edit-icon-' + propertyName + '"]')); - BrowserVisibility.waitUntilElementIsVisible(editPropertyIcon); + BrowserVisibility.waitUntilElementIsPresent(editPropertyIcon); } updatePropertyIconIsDisplayed(propertyName: string) { @@ -264,13 +265,13 @@ export class MetadataViewPage { checkMetadataGroupIsNotExpand(groupName: string) { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header')); - BrowserVisibility.waitUntilElementIsVisible(group); + BrowserVisibility.waitUntilElementIsPresent(group); expect(group.getAttribute('class')).not.toContain('mat-expanded'); } getMetadataGroupTitle(groupName: string): promise.Promise<string> { const group = element(by.css('mat-expansion-panel[data-automation-id="adf-metadata-group-' + groupName + '"] > mat-expansion-panel-header > span > mat-panel-title')); - BrowserVisibility.waitUntilElementIsVisible(group); + BrowserVisibility.waitUntilElementIsPresent(group); return group.getText(); } From 9866cf4d1d0a5b6ca9c1a0a1e6619493a1cfe2f7 Mon Sep 17 00:00:00 2001 From: dhrn <dharan.g@muraai.com> Date: Wed, 24 Apr 2019 12:30:52 +0530 Subject: [PATCH 157/208] * fixing the existing behavior --- .../metadata/metadata-properties.e2e.ts | 2 +- .../content-metadata.component.html | 4 +- .../content-metadata.component.spec.ts | 42 ++++++++----------- .../content-metadata.component.ts | 4 ++ 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/e2e/content-services/metadata/metadata-properties.e2e.ts b/e2e/content-services/metadata/metadata-properties.e2e.ts index 94da213ea8..6afc23d447 100644 --- a/e2e/content-services/metadata/metadata-properties.e2e.ts +++ b/e2e/content-services/metadata/metadata-properties.e2e.ts @@ -135,7 +135,7 @@ describe('CardView Component - properties', () => { metadataViewPage.clickOnInformationButton(); metadataViewPage.checkMetadataGroupIsNotExpand('EXIF'); - metadataViewPage.checkMetadataGroupIsExpand('properties'); + metadataViewPage.checkMetadataGroupIsNotExpand('properties'); metadataViewPage.clickMetadataGroup('properties'); diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html index 8f4876110a..d58b10ce2f 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.html @@ -2,8 +2,8 @@ <mat-accordion displayMode="flat" [multi]="multi"> <mat-expansion-panel *ngIf="displayDefaultProperties" - [expanded]="!expanded || !displayAspect" - [hideToggle]="!expanded || !displayAspect" + [expanded]="canExpandProperties()" + [hideToggle]="canExpandProperties()" [attr.data-automation-id]="'adf-metadata-group-properties'" > <mat-expansion-panel-header> <mat-panel-title> diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts index a3fe638500..fc263c9018 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -312,21 +312,30 @@ describe('ContentMetadataComponent', () => { component.displayEmpty = true; fixture.detectChanges(); - const defaultProp = queryDom(fixture); - const exifProp = queryDom(fixture, 'EXIF'); - const customProp = queryDom(fixture, 'CUSTOM'); + let defaultProp = queryDom(fixture); + let exifProp = queryDom(fixture, 'EXIF'); + let customProp = queryDom(fixture, 'CUSTOM'); expect(defaultProp.componentInstance.expanded).toBeFalsy(); expect(exifProp.componentInstance.expanded).toBeTruthy(); expect(customProp.componentInstance.expanded).toBeFalsy(); component.displayAspect = 'CUSTOM'; fixture.detectChanges(); - const updatedDefault = queryDom(fixture); - const updatedExif = queryDom(fixture, 'EXIF'); - const updatedCustom = queryDom(fixture, 'CUSTOM'); - expect(updatedDefault.componentInstance.expanded).toBeFalsy(); - expect(updatedExif.componentInstance.expanded).toBeFalsy(); - expect(updatedCustom.componentInstance.expanded).toBeTruthy(); + defaultProp = queryDom(fixture); + exifProp = queryDom(fixture, 'EXIF'); + customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeFalsy(); + expect(exifProp.componentInstance.expanded).toBeFalsy(); + expect(customProp.componentInstance.expanded).toBeTruthy(); + + component.displayAspect = 'Properties'; + fixture.detectChanges(); + defaultProp = queryDom(fixture); + exifProp = queryDom(fixture, 'EXIF'); + customProp = queryDom(fixture, 'CUSTOM'); + expect(defaultProp.componentInstance.expanded).toBeTruthy(); + expect(exifProp.componentInstance.expanded).toBeFalsy(); + expect(customProp.componentInstance.expanded).toBeFalsy(); })); @@ -344,21 +353,6 @@ describe('ContentMetadataComponent', () => { expect(customProp.componentInstance.expanded).toBeFalsy(); })); - - it('should expand the properties section when input is null', async(() => { - component.displayAspect = null; - component.expanded = true; - component.displayEmpty = true; - - fixture.detectChanges(); - const defaultProp = queryDom(fixture); - const exifProp = queryDom(fixture, 'EXIF'); - const customProp = queryDom(fixture, 'CUSTOM'); - expect(defaultProp.componentInstance.expanded).toBeTruthy(); - expect(exifProp.componentInstance.expanded).toBeFalsy(); - expect(customProp.componentInstance.expanded).toBeFalsy(); - - })); }); }); diff --git a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts index b6d769cafb..cfeb2893ee 100644 --- a/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts +++ b/lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts @@ -126,4 +126,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { return group.title === this.displayAspect; } + public canExpandProperties(): boolean { + return !this.expanded || this.displayAspect === 'Properties'; + } + } From db4d10137e642c9deeb93b6dd1c03acf5a3da24f Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Wed, 24 Apr 2019 15:50:00 +0300 Subject: [PATCH 158/208] [ADF-4310]Added sort tests for edit task filter cloud component (#4584) * Added some tests * Fix tests * Add missing tests for sort properties. --- .../process-services/tasksCloudDemoPage.ts | 12 +- .../task-list-properties.e2e.ts | 420 +++++++++++++++--- .../taskListCloud.config.ts | 30 ++ .../tasks-custom-filters.e2e.ts | 53 --- .../pages/task-list-cloud-component.page.ts | 72 ++- 5 files changed, 433 insertions(+), 154 deletions(-) diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index b173ca623d..445b05b1d7 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -70,21 +70,13 @@ export class TasksCloudDemoPage { return new TaskFiltersCloudComponentPage(this.completedTasks); } - customTaskFilter(filterName) { - return new TaskFiltersCloudComponentPage(element(by.css(`span[data-automation-id="${filterName}-filter"]`))); - } - getActiveFilterName() { BrowserVisibility.waitUntilElementIsVisible(this.activeFilter); return this.activeFilter.getText(); } - getAllRowsByIdColumn() { - return new TaskListCloudComponentPage().getAllRowsByColumn('Id'); - } - - getAllRowsByProcessDefIdColumn() { - return new TaskListCloudComponentPage().getAllRowsByColumn('Process Definition Id'); + customTaskFilter(filterName) { + return new TaskFiltersCloudComponentPage(element(by.css(`span[data-automation-id="${filterName}-filter"]`))); } clickOnTaskFilters() { diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index a586447fda..84e80dfe55 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -21,7 +21,7 @@ import { StringUtil, TasksService, ProcessDefinitionsService, ProcessInstancesService, LoginSSOPage, ApiService, - SettingsPage, AppListCloudPage, LocalStorageUtil + SettingsPage, AppListCloudPage, LocalStorageUtil, IdentityService, RolesService } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../pages/adf/navigationBarPage'; import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; @@ -31,92 +31,112 @@ import moment = require('moment'); import { DateUtil } from '../util/dateUtil'; import resources = require('../util/resources'); +import CONSTANTS = require('../util/constants'); describe('Edit task filters and task list properties', () => { - describe('Edit task filters and task list properties', () => { - const settingsPage = new SettingsPage(); - const loginSSOPage = new LoginSSOPage(); - const navigationBarPage = new NavigationBarPage(); + const settingsPage = new SettingsPage(); + const loginSSOPage = new LoginSSOPage(); + const navigationBarPage = new NavigationBarPage(); - const appListCloudComponent = new AppListCloudPage(); - const tasksCloudDemoPage = new TasksCloudDemoPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); - let tasksService: TasksService; - let processDefinitionService: ProcessDefinitionsService; - let processInstancesService: ProcessInstancesService; + let tasksService: TasksService; + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let identityService: IdentityService; + let rolesService: RolesService; - const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; - const candidateUserApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; + const candidateUserApp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; + const noTasksFoundMessage = 'No Tasks Found'; + const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; + let createdTask, notAssigned, notDisplayedTask, processDefinition, processInstance, priorityTask, subTask, otherOwnerTask; + const priority = 30; - const noTasksFoundMessage = 'No Tasks Found'; - const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; - let createdTask, notAssigned, notDisplayedTask, processDefinition, processInstance, priorityTask, subTask; - const priority = 30; + const beforeDate = moment().add(-1, 'days').format('DD/MM/YYYY'); + const currentDate = DateUtil.formatDate('DD/MM/YYYY'); + const afterDate = moment().add(1, 'days').format('DD/MM/YYYY'); - const beforeDate = moment().add(-1, 'days').format('DD/MM/YYYY'); - const currentDate = DateUtil.formatDate('DD/MM/YYYY'); - const afterDate = moment().add(1, 'days').format('DD/MM/YYYY'); + beforeAll(async (done) => { + const jsonFile = new TaskListCloudConfiguration().getConfiguration(); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); + loginSSOPage.clickOnSSOButton(); + loginSSOPage.loginSSOIdentityService(user, password); - beforeAll(async (done) => { - const jsonFile = new TaskListCloudConfiguration().getConfiguration(); - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); - loginSSOPage.clickOnSSOButton(); - loginSSOPage.loginSSOIdentityService(user, password); + await LocalStorageUtil.setConfigField('adf-cloud-task-list', JSON.stringify(jsonFile)); + await LocalStorageUtil.setConfigField('adf-edit-task-filter', JSON.stringify({ + 'filterProperties': [ + 'appName', + 'status', + 'assignee', + 'taskName', + 'parentTaskId', + 'priority', + 'standAlone', + 'owner', + 'processDefinitionId', + 'processInstanceId', + 'lastModified', + 'sort', + 'order' + ], + 'sortProperties': [ + 'id', + 'name', + 'createdDate', + 'priority', + 'processDefinitionId', + 'processInstanceId', + 'parentTaskId', + 'priority', + 'standAlone', + 'owner', + 'assignee' + ], + 'actions': [ + 'save', + 'saveAs', + 'delete' + ] + })); - await LocalStorageUtil.setConfigField('adf-cloud-task-list', JSON.stringify(jsonFile)); - await LocalStorageUtil.setConfigField('adf-edit-task-filter', JSON.stringify({ - 'filterProperties': [ - 'appName', - 'status', - 'assignee', - 'taskName', - 'parentTaskId', - 'priority', - 'standAlone', - 'owner', - 'processDefinitionId', - 'processInstanceId', - 'lastModified', - 'sort', - 'order' - ], - 'sortProperties': [ - 'id', - 'name', - 'createdDate', - 'priority', - 'processDefinitionId' - ], - 'actions': [ - 'save', - 'saveAs', - 'delete' - ] - })); + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + identityService = new IdentityService(apiService); + rolesService = new RolesService(apiService); + tasksService = new TasksService(apiService); - const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); - await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + const apsUser = await identityService.createIdentityUser(); + const apsUserRoleId = await rolesService.getRoleIdByRoleName(CONSTANTS.ROLES.APS_USER); + await identityService.assignRole(apsUser.idIdentityService, apsUserRoleId, CONSTANTS.ROLES.APS_USER); - tasksService = new TasksService(apiService); - createdTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); - await tasksService.claimTask(createdTask.entry.id, simpleApp); - notAssigned = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); - priorityTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp, { priority: priority }); - await tasksService.claimTask(priorityTask.entry.id, simpleApp); - notDisplayedTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateUserApp); - await tasksService.claimTask(notDisplayedTask.entry.id, candidateUserApp); + await apiService.login(apsUser.email, apsUser.password); + otherOwnerTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); + await tasksService.claimTask(otherOwnerTask.entry.id, simpleApp); - processDefinitionService = new ProcessDefinitionsService(apiService); - processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); - processInstancesService = new ProcessInstancesService(apiService); - processInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + createdTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); + await tasksService.claimTask(createdTask.entry.id, simpleApp); + notAssigned = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp); + priorityTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), simpleApp, {priority: priority}); + await tasksService.claimTask(priorityTask.entry.id, simpleApp); + notDisplayedTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateUserApp); + await tasksService.claimTask(notDisplayedTask.entry.id, candidateUserApp); - subTask = await tasksService.createStandaloneSubtask(createdTask.entry.id, simpleApp, StringUtil.generateRandomString()); - await tasksService.claimTask(subTask.entry.id, simpleApp); + processDefinitionService = new ProcessDefinitionsService(apiService); + processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + processInstancesService = new ProcessInstancesService(apiService); + processInstance = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); - done(); - }); + subTask = await tasksService.createStandaloneSubtask(createdTask.entry.id, simpleApp, StringUtil.generateRandomString()); + await tasksService.claimTask(subTask.entry.id, simpleApp); + + done(); + }); + + describe('Edit task filters and task list properties - filter properties', () => { beforeEach((done) => { navigationBarPage.navigateToProcessServicesCloudPage(); @@ -298,7 +318,7 @@ describe('Edit task filters and task list properties', () => { expect(tasksCloudDemoPage.taskListCloudComponent().getNoTasksFoundMessage()).toEqual(noTasksFoundMessage); }); - xit('[C297692] Task is displayed when typing into lastModifiedFrom field a date before the tasks due date ' + + it('[C297692] Task is displayed when typing into lastModifiedFrom field a date before the tasks due date ' + 'and into lastModifiedTo a date after', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); @@ -322,4 +342,258 @@ describe('Edit task filters and task list properties', () => { }); + describe('Edit task filters and task list properties - sort properties', () => { + + beforeEach((done) => { + navigationBarPage.navigateToProcessServicesCloudPage(); + appListCloudComponent.checkApsContainer(); + appListCloudComponent.goToApp(simpleApp); + tasksCloudDemoPage.editTaskFilterCloudComponent().clickCustomiseFilterHeader(); + tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); + done(); + }); + + it('[C306901] Should display tasks sorted by task name when taskName is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ASSIGNED') + .setSortFilterDropDown('Name').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsNameColumn().then( (list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsNameColumn().then( (list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C290156] Should display tasks ordered by id when Id is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ASSIGNED') + .setSortFilterDropDown('Id').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C306903] Should display tasks sorted by processDefinitionId when processDefinitionId is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ASSIGNED') + .setSortFilterDropDown('ProcessDefinitionId').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByProcessDefIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByProcessDefIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C306905] Should display tasks sorted by processInstanceId when processInstanceId is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().setStatusFilterDropDown('ASSIGNED') + .setSortFilterDropDown('ProcessInstanceId').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByProcessInstanceIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByProcessInstanceIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C306907] Should display tasks sorted by assignee when assignee is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().clearAssignee().setStatusFilterDropDown('ALL') + .setSortFilterDropDown('Assignee').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByAssigneeColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByAssigneeColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C306911] Should display tasks sorted by parentTaskId when parentTaskId is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().clearAssignee().setStatusFilterDropDown('ALL') + .setSortFilterDropDown('ParentTaskId').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByParentTaskIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByParentTaskIdColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C306909] Should display tasks sorted by priority when priority is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().clearAssignee().setStatusFilterDropDown('ALL') + .setSortFilterDropDown('Priority').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByPriorityColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByPriorityColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C307114] Should display tasks sorted by standAlone when standAlone is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().clearAssignee().setStatusFilterDropDown('ALL') + .setSortFilterDropDown('StandAlone').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByStandAloneColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByStandAloneColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + + it('[C307115] Should display tasks sorted by owner when owner is selected from sort dropdown', () => { + tasksCloudDemoPage.editTaskFilterCloudComponent().clearAssignee().setStatusFilterDropDown('ALL') + .setSortFilterDropDown('Owner').setOrderFilterDropDown('ASC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByOwnerColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); + tasksCloudDemoPage.taskListCloudComponent().getAllRowsByOwnerColumn().then((list) => { + const initialList = list.slice(0); + list.sort(function (firstStr, secondStr) { + return firstStr.localeCompare(secondStr); + }); + list.reverse(); + expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); + }); + }); + }); + }); diff --git a/e2e/process-services-cloud/taskListCloud.config.ts b/e2e/process-services-cloud/taskListCloud.config.ts index 3df314de53..71c1cc2e15 100644 --- a/e2e/process-services-cloud/taskListCloud.config.ts +++ b/e2e/process-services-cloud/taskListCloud.config.ts @@ -76,6 +76,36 @@ export class TaskListCloudConfiguration { 'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.LAST_MODIFIED', 'sortable': true, 'format': 'timeAgo' + }, + { + 'key': 'entry.assignee', + 'type': 'text', + 'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.ASSIGNEE', + 'sortable': true + }, + { + 'key': 'entry.parentTaskId', + 'type': 'text', + 'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PARENT_TASK_ID', + 'sortable': true + }, + { + 'key': 'entry.priority', + 'type': 'text', + 'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.PRIORITY', + 'sortable': true + }, + { + 'key': 'entry.standAlone', + 'type': 'text', + 'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.STAND_ALONE', + 'sortable': true + }, + { + 'key': 'entry.owner', + 'type': 'text', + 'title': 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.OWNER', + 'sortable': true } ] } diff --git a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts index e0b999725b..2d1de4d25a 100644 --- a/e2e/process-services-cloud/tasks-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/tasks-custom-filters.e2e.ts @@ -137,58 +137,5 @@ describe('Task filters cloud', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(completedTaskName); tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(deletedTaskName); }); - - it('[C290069] Should display tasks ordered by name when Name is selected from sort dropdown', () => { - tasksCloudDemoPage.editTaskFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('ASSIGNED') - .setSortFilterDropDown('Name').setOrderFilterDropDown('ASC'); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); - tasksCloudDemoPage.taskListCloudComponent().getAllRowsNameColumn().then( (list) => { - const initialList = list.slice(0); - list.sort(function (firstStr, secondStr) { - return firstStr.localeCompare(secondStr); - }); - expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); - }); - - tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); - tasksCloudDemoPage.taskListCloudComponent().getAllRowsNameColumn().then( (list) => { - const initialList = list.slice(0); - list.sort(function (firstStr, secondStr) { - return firstStr.localeCompare(secondStr); - }); - list.reverse(); - expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); - }); - }); - - it('[C290156] Should display tasks ordered by id when Id is selected from sort dropdown', () => { - tasksCloudDemoPage.editTaskFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('ASSIGNED') - .setSortFilterDropDown('Id').setOrderFilterDropDown('ASC'); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); - - tasksCloudDemoPage.getAllRowsByIdColumn().then((list) => { - const initialList = list.slice(0); - list.sort(function (firstStr, secondStr) { - return firstStr.localeCompare(secondStr); - }); - expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); - }); - - tasksCloudDemoPage.editTaskFilterCloudComponent().setOrderFilterDropDown('DESC'); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsDisplayed(); - tasksCloudDemoPage.taskListCloudComponent().getDataTable().checkSpinnerIsNotDisplayed(); - tasksCloudDemoPage.getAllRowsByIdColumn().then((list) => { - const initialList = list.slice(0); - list.sort(function (firstStr, secondStr) { - return firstStr.localeCompare(secondStr); - }); - list.reverse(); - expect(JSON.stringify(initialList) === JSON.stringify(list)).toEqual(true); - }); - }); }); }); diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts index c0cf818f0e..7162bb9653 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts @@ -20,7 +20,15 @@ import { DataTableComponentPage } from '../../core/pages/data-table-component.pa import { element, by } from 'protractor'; const column = { - id: 'Id' + id: 'Id', + name: 'Name', + processInstanceId: 'ProcessInstanceId', + processDefinitionId: 'ProcessDefinitionId', + assignee: 'Assignee', + parentTaskId: 'ParentTaskId', + priority: 'Priority', + standAlone: 'StandAlone', + owner: 'Owner' }; export class TaskListCloudComponentPage { @@ -35,55 +43,55 @@ export class TaskListCloudComponentPage { } clickCheckbox(taskName) { - return this.dataTable.clickCheckbox('Name', taskName); + return this.dataTable.clickCheckbox(column.name, taskName); } checkRowIsNotChecked(taskName) { - return this.dataTable.checkRowIsNotChecked('Name', taskName); + return this.dataTable.checkRowIsNotChecked(column.name, taskName); } checkRowIsChecked(taskName) { - return this.dataTable.checkRowIsChecked('Name', taskName); + return this.dataTable.checkRowIsChecked(column.name, taskName); } getRowsWithSameName(taskName) { - return this.dataTable.getRowsWithSameColumnValues('Name', taskName); + return this.dataTable.getRowsWithSameColumnValues(column.name, taskName); } checkRowIsSelected(taskName) { - return this.dataTable.checkRowIsSelected('Name', taskName); + return this.dataTable.checkRowIsSelected(column.name, taskName); } checkRowIsNotSelected(taskName) { - return this.dataTable.checkRowIsNotSelected('Name', taskName); + return this.dataTable.checkRowIsNotSelected(column.name, taskName); } selectRowWithKeyboard(taskName) { - return this.dataTable.selectRowWithKeyboard('Name', taskName); + return this.dataTable.selectRowWithKeyboard(column.name, taskName); } selectRow(taskName) { - return this.dataTable.selectRow('Name', taskName); + return this.dataTable.selectRow(column.name, taskName); } getRow(taskName) { - return this.dataTable.getCellElementByValue('Name', taskName); + return this.dataTable.getCellElementByValue(column.name, taskName); } checkContentIsDisplayedByProcessInstanceId(taskName) { - return this.dataTable.checkContentIsDisplayed('ProcessInstanceId', taskName); + return this.dataTable.checkContentIsDisplayed(column.processInstanceId, taskName); } checkContentIsDisplayedById(taskName) { - return this.dataTable.checkContentIsDisplayed('Id', taskName); + return this.dataTable.checkContentIsDisplayed(column.id, taskName); } checkContentIsDisplayedByName(taskName) { - return this.dataTable.checkContentIsDisplayed('Name', taskName); + return this.dataTable.checkContentIsDisplayed(column.name, taskName); } checkContentIsNotDisplayedByName(taskName) { - return this.dataTable.checkContentIsNotDisplayed('Name', taskName); + return this.dataTable.checkContentIsNotDisplayed(column.name, taskName); } checkTaskListIsLoaded() { @@ -97,15 +105,43 @@ export class TaskListCloudComponentPage { } getAllRowsNameColumn() { - return this.dataTable.getAllRowsColumnValues('Name'); + return this.dataTable.getAllRowsColumnValues(column.name); } - getAllRowsByColumn(columnName) { - return this.dataTable.getAllRowsColumnValues(columnName); + getAllRowsByIdColumn() { + return this.dataTable.getAllRowsColumnValues(column.id); + } + + getAllRowsByProcessDefIdColumn() { + return this.dataTable.getAllRowsColumnValues(column.processDefinitionId); + } + + getAllRowsByProcessInstanceIdColumn() { + return this.dataTable.getAllRowsColumnValues(column.processInstanceId); + } + + getAllRowsByAssigneeColumn() { + return this.dataTable.getAllRowsColumnValues(column.assignee); + } + + getAllRowsByParentTaskIdColumn() { + return this.dataTable.getAllRowsColumnValues(column.parentTaskId); + } + + getAllRowsByPriorityColumn() { + return this.dataTable.getAllRowsColumnValues(column.priority); + } + + getAllRowsByStandAloneColumn() { + return this.dataTable.getAllRowsColumnValues(column.standAlone); + } + + getAllRowsByOwnerColumn() { + return this.dataTable.getAllRowsColumnValues(column.owner); } getIdCellValue(rowName) { - const locator = new DataTableComponentPage().getCellByRowContentAndColumn('Name', rowName, column.id); + const locator = new DataTableComponentPage().getCellByRowContentAndColumn(column.name, rowName, column.id); BrowserVisibility.waitUntilElementIsVisible(locator); return locator.getText(); } From 90276dd4988b80cb0e4b6912b41e8d0c810a313c Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 24 Apr 2019 14:13:08 +0100 Subject: [PATCH 159/208] improve recovery script --- scripts/check-activiti-env.js | 219 +++++++++++++++++++++++++++++----- 1 file changed, 191 insertions(+), 28 deletions(-) diff --git a/scripts/check-activiti-env.js b/scripts/check-activiti-env.js index 550b9aeb6c..e74b1af6e3 100755 --- a/scripts/check-activiti-env.js +++ b/scripts/check-activiti-env.js @@ -6,8 +6,14 @@ let ACTIVITI7_APPS = require('../e2e/util/resources').ACTIVITI7_APPS; let config = {}; let absentApps = []; +let notRunningApps = []; let host; +let MAX_RETRY = 3; +let counter = 0; +let TIMEOUT = 180000; + + async function main() { program @@ -43,10 +49,108 @@ async function main() { console.log('Login error' + e); } - let appsDeployed = await getDeployedApplicationsByStatus(this.alfrescoJsApi, 'RUNNING'); + await deployAbsentApps(this.alfrescoJsApi); + let notRunning = await getNotRunningApps(this.alfrescoJsApi); + + if (notRunning && notRunning.length > 0) { + let notRunningAppAfterWait = await waitPossibleStaleApps(this.alfrescoJsApi, notRunning); + + await deleteStaleApps(this.alfrescoJsApi, notRunningAppAfterWait); + + await deployAbsentApps(this.alfrescoJsApi); + let notRunningSecondAttempt = await getNotRunningApps(this.alfrescoJsApi); + + if (notRunningSecondAttempt && notRunningSecondAttempt.length > 0) { + let notRunningAppAfterWaitSecondAttempt = await waitPossibleStaleApps(this.alfrescoJsApi, notRunningSecondAttempt); + + if (notRunningAppAfterWaitSecondAttempt && notRunningAppAfterWaitSecondAttempt.legnth > 0) { + console.log(`Not possible to recover the following apps in the environment`); + + notRunningAppAfterWaitSecondAttempt.forEach((currentApp) => { + console.log(`App ${currentApp.entry.name } current status ${JSON.stringify(currentApp.entry.status)}`); + }); + + process.exit(1); + } + }else{ + console.log(`Activiti 7 all ok :)`); + } + } else { + console.log(`Activiti 7 all ok :)`); + } +} + +async function deleteStaleApps(alfrescoJsApi, notRunningAppAfterWait) { + + notRunningAppAfterWait.forEach(async (currentApp) => { + await deleteApp(alfrescoJsApi, currentApp.entry.name); + }); + +} + +async function waitPossibleStaleApps(alfrescoJsApi, notRunning) { + + do { + console.log(`Wait stale app ${TIMEOUT}`); + + notRunning.forEach((currentApp) => { + console.log(`${currentApp.entry.name }`); + }); + + + sleep(TIMEOUT); + counter++; + + let runningApps = await getDeployedApplicationsByStatus(alfrescoJsApi, 'RUNNING'); + + notRunning.forEach((currentStaleApp) => { + let nowIsRunning = runningApps.find((currentRunnignApp) => { + return currentStaleApp.entry.name === currentRunnignApp.entry.name; + }); + + if (nowIsRunning) { + notRunning = notRunning.filter((item) => { + return item.entry.name !== nowIsRunning.entry.name + }) + } + + }); + } while (counter < MAX_RETRY && notRunning.length > 0); + + return notRunning; +} + +async function getNotRunningApps(alfrescoJsApi) { + let allStatusApps = await getDeployedApplicationsByStatus(alfrescoJsApi, ''); Object.keys(ACTIVITI7_APPS).forEach((key) => { - let isPresent = appsDeployed.find((currentApp) => { + let isNotRunning = allStatusApps.find((currentApp) => { + return ACTIVITI7_APPS[key].name === currentApp.entry.name && currentApp.entry.status !== 'Running'; + }); + + if (isNotRunning) { + notRunningApps.push(isNotRunning); + } + }); + + if (notRunningApps.length > 0) { + console.log(`The following apps are NOT running in the target env:`); + notRunningApps.forEach((currentApp) => { + console.log(`App ${currentApp.entry.name } current status ${JSON.stringify(currentApp.entry.status)}`); + }); + + await checkIfAppIsReleased(alfrescoJsApi, absentApps); + } + + return notRunningApps; +} + +async function deployAbsentApps(alfrescoJsApi) { + + let deployedApps = await getDeployedApplicationsByStatus(alfrescoJsApi, ''); + + Object.keys(ACTIVITI7_APPS).forEach((key) => { + let isPresent = deployedApps.find((currentApp) => { return ACTIVITI7_APPS[key].name === currentApp.entry.name; }); @@ -56,14 +160,13 @@ async function main() { }); if (absentApps.length > 0) { - console.log(`The following apps are missing in the target env ${JSON.stringify(absentApps)}`) + console.log(`The following apps are missing in the target env ${JSON.stringify(absentApps)}`); - await checkIfAppIsReleased(this.alfrescoJsApi, absentApps); - - process.exit(1); + await checkIfAppIsReleased(alfrescoJsApi, absentApps); } } + async function checkIfAppIsReleased(apiService, absentApps) { let listAppsInModeler = await getAppProjects(apiService); @@ -80,9 +183,22 @@ async function checkIfAppIsReleased(apiService, absentApps) { await releaseApp(apiService, uploadedApp); await deployApp(apiService, uploadedApp); } - }else{ - await releaseApp(apiService, app); - await deployApp(apiService, app); + } else { + let appRelease = undefined; + let appReleaseList = await getReleaseAppyProjectId(apiService, app.entry.id); + + if (!appReleaseList) { + appRelease = await releaseApp(apiService, app); + } else { + + appRelease = appReleaseList.list.entries.find((currentRelease) => { + return currentRelease.entry.version === 'latest'; + }); + } + + console.log('App to deploy ' + appRelease.entry.projectName + ' app release id ' + JSON.stringify(appRelease.entry.id)); + + await deployApp(apiService, appRelease); } } } @@ -90,25 +206,26 @@ async function checkIfAppIsReleased(apiService, absentApps) { async function deployApp(apiService, app) { const url = `${config.hostBpm}/alfresco-deployment-service/v1/applications`; - const pathParams = {}, - queryParams = { - "name": "re", - "releaseId": app.entry.id, - "security": [{"role": "APS_ADMIN", "groups": [], "users": ["admin.adf"]}, { - "role": "APS_USER", - "groups": [], - "users": ["admin.adf"] - }] - }; + const pathParams = {}; + const bodyParam = { + "name": app.entry.projectName, + "releaseId": app.entry.id, + "version": app.entry.name, + "security": [{"role": "APS_ADMIN", "groups": [], "users": ["admin.adf"]}, { + "role": "APS_USER", + "groups": [], + "users": ["admin.adf"] + }] + }; - const headerParams = {}, formParams = {}, bodyParam = {}, - contentTypes = ['multipart/form-data'], accepts = ['application/json']; + const headerParams = {}, formParams = {}, queryParams = {}, + contentTypes = ['application/json'], accepts = ['application/json']; try { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to deploy the project ${app.entry.name} ` + error); + console.log(`Not possible to deploy the project ${app.entry.projectName} status : ${JSON.stringify(error.status)} ${JSON.stringify(error)}`); process.exit(1); } } @@ -128,16 +245,34 @@ async function importApp(apiService, app) { contentTypes, accepts); } catch (error) { if (error.status !== 409) { - console.log(`Not possible to upload the project ${app.name} ` + error.status); + console.log(`Not possible to upload the project ${app.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.text)}`); process.exit(1); } } } -async function releaseApp(apiService, app) { - const url = `${config.hostBpm}alfresco-modeling-service/v1/projects/${app.entry.id}/releases`; +async function getReleaseAppyProjectId(apiService, projectId) { + const url = `${config.hostBpm}/alfresco-modeling-service/v1/projects/${projectId}/releases`; + const pathParams = {}, queryParams = {}, + headerParams = {}, formParams = {}, bodyParam = {}, + contentTypes = ['application/json'], accepts = ['application/json']; + + try { + return await apiService.oauth2Auth.callCustomApi(url, 'GET', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + } catch (error) { + console.log(`Not possible to get the release of the project ${projectId} ` + JSON.stringify(error)); + process.exit(1); + } + +} + +async function releaseApp(apiService, app) { + const url = `${config.hostBpm}/alfresco-modeling-service/v1/projects/${app.entry.id}/releases`; + + console.log('Release ID ' + app.entry.id); const pathParams = {}, queryParams = {}, headerParams = {}, formParams = {}, bodyParam = {}, contentTypes = ['application/json'], accepts = ['application/json']; @@ -146,7 +281,7 @@ async function releaseApp(apiService, app) { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to release the project ${app.entry.name} ` + JSON.stringify(error)); + console.log(`Not possible to release the project ${app.entry.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.text)}`); process.exit(1); } @@ -166,7 +301,7 @@ async function getDeployedApplicationsByStatus(apiService, status) { return data.list.entries; } catch (error) { - console.log(`Not possible get the application from alfresco-deployment-service` + error); + console.log(`Not possible get the applicationsfrom alfresco-deployment-service ${JSON.stringify(error)} `); process.exit(1); } @@ -185,9 +320,37 @@ async function getAppProjects(apiService, status) { contentTypes, accepts); return data.list.entries; } catch (error) { - console.log(`Not possible get the application from alfresco-modeling-service` + error); + console.log(`Not possible get the application from alfresco-modeling-service ` + error); process.exit(1); } } +async function deleteApp(apiService, appName) { + console.log(`Delete the app ${appName}`); + + const url = `${config.hostBpm}/alfresco-deployment-service/v1/applications/${appName}`; + + const pathParams = {}, queryParams = {}, + headerParams = {}, formParams = {}, bodyParam = {}, + contentTypes = ['application/json'], accepts = ['application/json']; + + try { + await apiService.oauth2Auth.callCustomApi(url, 'DELETE', pathParams, queryParams, headerParams, formParams, bodyParam, + contentTypes, accepts); + + ///it needs time + console.log(`Deleting apps stale wait 3 minutes`); + sleep(180000); + console.log(`App deleted`); + } catch (error) { + console.log(`Not possible to delete the application from alfresco-modeling-service` + error); + process.exit(1); + } +} + +function sleep(delay) { + var start = new Date().getTime(); + while (new Date().getTime() < start + delay) ; +} + main(); From 51e63d8f1cb9270f9e049d87b49f170b43f767a6 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 24 Apr 2019 15:34:27 +0100 Subject: [PATCH 160/208] remove invalid test case --- .../start-process-cloud.e2e.ts | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index 35aa47f907..8afb14f20b 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -95,28 +95,4 @@ describe('Start Process', () => { processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedByName(processName); }); - - it('[C291860] Should be able to start a process with variables', () => { - appListCloudComponent.checkAppIsDisplayed(simpleApp); - appListCloudComponent.goToApp(simpleApp); - processCloudDemoPage.openNewProcessForm(); - - startProcessPage.clearField(startProcessPage.processNameInput); - startProcessPage.enterProcessName(processName); - - startProcessPage.clearField(startProcessPage.processDefinition); - startProcessPage.blur(startProcessPage.processDefinition); - startProcessPage.checkValidationErrorIsDisplayed(requiredProcessError); - - startProcessPage.selectFromProcessDropdown(processWithVariables); - startProcessPage.checkStartProcessButtonIsEnabled(); - startProcessPage.clickStartProcessButton(); - processCloudDemoPage.clickOnProcessFilters(); - - processCloudDemoPage.runningProcessesFilter().clickProcessFilter(); - expect(processCloudDemoPage.getActiveFilterName()).toBe('Running Processes'); - processCloudDemoPage.processListCloudComponent().checkContentIsDisplayedByName(processName); - - }); - }); From 453415d73b022def9ef322b12504f2bdd1613f8f Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 24 Apr 2019 17:08:05 +0100 Subject: [PATCH 161/208] fix lint --- e2e/process-services-cloud/start-process-cloud.e2e.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e/process-services-cloud/start-process-cloud.e2e.ts b/e2e/process-services-cloud/start-process-cloud.e2e.ts index 8afb14f20b..c37f208fe9 100644 --- a/e2e/process-services-cloud/start-process-cloud.e2e.ts +++ b/e2e/process-services-cloud/start-process-cloud.e2e.ts @@ -35,8 +35,7 @@ describe('Start Process', () => { const processName255Characters = StringUtil.generateRandomString(255); const processNameBiggerThen255Characters = StringUtil.generateRandomString(256); const lengthValidationError = 'Length exceeded, 255 characters max.'; - const requiredError = 'Process Name is required', requiredProcessError = 'Process Definition is required'; - const processWithVariables = resources.ACTIVITI7_APPS.SIMPLE_APP.processes.processwithvariables; + const requiredError = 'Process Name is required'; const user = TestConfig.adf.adminEmail, password = TestConfig.adf.adminPassword; const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; From f2c954d91199e1f7508c68fe26d9c422d7f43e33 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Wed, 24 Apr 2019 20:00:52 +0300 Subject: [PATCH 162/208] [ADF-4028][ADF-4047]Add process list cloud selection tests (#4537) * Add process list cloud selection tests * Fix lint issues * Fix lint issues * Added columns to contentServicesPage * Fix lint error. * Add the possibility to test the selection mode for process details. --- demo-shell/resources/i18n/en.json | 3 +- .../cloud/cloud-settings.component.html | 3 + .../cloud/cloud-settings.component.ts | 10 +- .../cloud/processes-cloud-demo.component.ts | 6 +- .../cloud/services/cloud-layout.service.ts | 1 + .../document-list-properties.e2e.ts | 112 +++++++++++++ e2e/pages/adf/contentServicesPage.ts | 49 ++++-- .../process-services/processCloudDemoPage.ts | 1 - .../process-services/tasksCloudDemoPage.ts | 6 + .../process-list-selection-cloud.e2e.ts | 150 ++++++++++++++++++ .../process-list-cloud-component.page.ts | 41 ++++- 11 files changed, 360 insertions(+), 22 deletions(-) create mode 100644 e2e/content-services/document-list/document-list-properties.e2e.ts create mode 100644 e2e/process-services-cloud/process-list-selection-cloud.e2e.ts diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 17e745dcd7..bb329b5568 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -318,6 +318,7 @@ "MULTISELECTION": "Multiselection", "TESTING_MODE": "Testing Mode", "SELECTION_MODE": "Selection Mode", - "TASK_DETAILS_REDIRECTION": "Display task details on task click" + "TASK_DETAILS_REDIRECTION": "Display task details on task click", + "PROCESS_DETAILS_REDIRECTION": "Display process details on process click" } } diff --git a/demo-shell/src/app/components/cloud/cloud-settings.component.html b/demo-shell/src/app/components/cloud/cloud-settings.component.html index 3621839066..62d8ded230 100644 --- a/demo-shell/src/app/components/cloud/cloud-settings.component.html +++ b/demo-shell/src/app/components/cloud/cloud-settings.component.html @@ -8,6 +8,9 @@ <mat-slide-toggle [color]="'primary'" [checked]="taskDetailsRedirection" (change)="toggleTaskDetailsRedirection()" data-automation-id="taskDetailsRedirection"> {{ 'SETTINGS_CLOUD.TASK_DETAILS_REDIRECTION' | translate }} </mat-slide-toggle> + <mat-slide-toggle [color]="'primary'" [checked]="processDetailsRedirection" (change)="toggleProcessDetailsRedirection()" data-automation-id="processDetailsRedirection"> + {{ 'SETTINGS_CLOUD.PROCESS_DETAILS_REDIRECTION' | translate }} + </mat-slide-toggle> <mat-form-field data-automation-id="selectionMode"> <mat-label> {{ 'SETTINGS_CLOUD.SELECTION_MODE' | translate }} diff --git a/demo-shell/src/app/components/cloud/cloud-settings.component.ts b/demo-shell/src/app/components/cloud/cloud-settings.component.ts index 7d2932b258..cdb7a31fb8 100644 --- a/demo-shell/src/app/components/cloud/cloud-settings.component.ts +++ b/demo-shell/src/app/components/cloud/cloud-settings.component.ts @@ -29,6 +29,7 @@ export class CloudSettingsComponent implements OnInit { selectionMode: string; testingMode: boolean; taskDetailsRedirection: boolean; + processDetailsRedirection: boolean; selectionModeOptions = [ { value: '', title: 'None' }, @@ -49,6 +50,7 @@ export class CloudSettingsComponent implements OnInit { this.testingMode = settings.testingMode; this.selectionMode = settings.selectionMode; this.taskDetailsRedirection = settings.taskDetailsRedirection; + this.processDetailsRedirection = settings.processDetailsRedirection; } } @@ -67,6 +69,11 @@ export class CloudSettingsComponent implements OnInit { this.setSetting(); } + toggleProcessDetailsRedirection() { + this.processDetailsRedirection = !this.processDetailsRedirection; + this.setSetting(); + } + onSelectionModeChange() { this.setSetting(); } @@ -76,7 +83,8 @@ export class CloudSettingsComponent implements OnInit { multiselect: this.multiselect, testingMode: this.testingMode, selectionMode: this.selectionMode, - taskDetailsRedirection: this.taskDetailsRedirection + taskDetailsRedirection: this.taskDetailsRedirection, + processDetailsRedirection: this.processDetailsRedirection }); } } diff --git a/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts index 99ec46a3c6..31a417e206 100644 --- a/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts @@ -53,6 +53,7 @@ export class ProcessesCloudDemoComponent implements OnInit { selectedRows: string[] = []; testingMode: boolean; processFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] }; + processDetailsRedirection: boolean; editedFilter: ProcessFilterCloudModel; @@ -89,6 +90,7 @@ export class ProcessesCloudDemoComponent implements OnInit { this.multiselect = settings.multiselect; this.testingMode = settings.testingMode; this.selectionMode = settings.selectionMode; + this.processDetailsRedirection = settings.processDetailsRedirection; } } @@ -101,7 +103,9 @@ export class ProcessesCloudDemoComponent implements OnInit { } onRowClick(processInstanceId) { - this.router.navigate([`/cloud/${this.appName}/process-details/${processInstanceId}`]); + if (!this.multiselect && this.selectionMode !== 'multiple' && this.processDetailsRedirection) { + this.router.navigate([`/cloud/${this.appName}/process-details/${processInstanceId}`]); + } } onFilterChange(query: any) { diff --git a/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts b/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts index 6d8bb5ebcf..7bf710169c 100644 --- a/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts +++ b/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts @@ -27,6 +27,7 @@ export class CloudLayoutService { multiselect: false, testingMode: false, taskDetailsRedirection: true, + processDetailsRedirection: true, selectionMode: 'single' }; diff --git a/e2e/content-services/document-list/document-list-properties.e2e.ts b/e2e/content-services/document-list/document-list-properties.e2e.ts new file mode 100644 index 0000000000..58b419a460 --- /dev/null +++ b/e2e/content-services/document-list/document-list-properties.e2e.ts @@ -0,0 +1,112 @@ +/*! + * @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 { LoginPage } from '@alfresco/adf-testing'; +import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; +import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; + +import { AcsUserModel } from '../../models/ACS/acsUserModel'; +import TestConfig = require('../../test.config'); +import resources = require('../../util/resources'); + +import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; +import { UploadActions } from '../../actions/ACS/upload.actions'; +import { DropActions } from '../../actions/drop.actions'; +import { FileModel } from '../../models/ACS/fileModel'; + +describe('Document List Component - Properties', () => { + + const loginPage = new LoginPage(); + const contentServicesPage = new ContentServicesPage(); + const navigationBar = new NavigationBarPage(); + + let subFolder, parentFolder; + const uploadActions = new UploadActions(); + let acsUser = null; + + const pngFile = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); + + beforeAll(() => { + this.alfrescoJsApi = new AlfrescoApi({ + provider: 'ECM', + hostEcm: TestConfig.adf.url + }); + }); + + describe('Allow drop files property', async () => { + + beforeEach(async (done) => { + acsUser = new AcsUserModel(); + + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + await this.alfrescoJsApi.core.peopleApi.addPerson(acsUser); + + await this.alfrescoJsApi.login(acsUser.id, acsUser.password); + + parentFolder = await uploadActions.createFolder(this.alfrescoJsApi, 'parentFolder', '-my-'); + + subFolder = await uploadActions.createFolder(this.alfrescoJsApi, 'subFolder', parentFolder.entry.id); + + loginPage.loginToContentServicesUsingUserModel(acsUser); + + done(); + }); + + afterEach(async (done) => { + await this.alfrescoJsApi.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, subFolder.entry.id); + await uploadActions.deleteFilesOrFolder(this.alfrescoJsApi, parentFolder.entry.id); + done(); + }); + + it('[C299154] Should disallow upload content on a folder row if allowDropFiles is false', () => { + navigationBar.clickContentServicesButton(); + contentServicesPage.doubleClickRow(parentFolder.entry.name); + + contentServicesPage.disableDropFilesInAFolder(); + + const dragAndDropArea = contentServicesPage.getRowByName(subFolder.entry.name); + + const dragAndDrop = new DropActions(); + dragAndDrop.dropFile(dragAndDropArea, pngFile.location); + + contentServicesPage.checkContentIsDisplayed(pngFile.name); + contentServicesPage.doubleClickRow(subFolder.entry.name); + contentServicesPage.checkEmptyFolderTextToBe('This folder is empty'); + }); + + it('[C91319] Should allow upload content on a folder row if allowDropFiles is true', () => { + navigationBar.clickContentServicesButton(); + contentServicesPage.doubleClickRow(parentFolder.entry.name); + + contentServicesPage.enableDropFilesInAFolder(); + + const dragAndDropArea = contentServicesPage.getRowByName(subFolder.entry.name); + + const dragAndDrop = new DropActions(); + dragAndDrop.dropFile(dragAndDropArea, pngFile.location); + + contentServicesPage.checkContentIsNotDisplayed(pngFile.name); + contentServicesPage.doubleClickRow(subFolder.entry.name); + contentServicesPage.checkContentIsDisplayed(pngFile.name); + }); + }); +}); diff --git a/e2e/pages/adf/contentServicesPage.ts b/e2e/pages/adf/contentServicesPage.ts index 4b263f7524..3f0539d31f 100644 --- a/e2e/pages/adf/contentServicesPage.ts +++ b/e2e/pages/adf/contentServicesPage.ts @@ -18,6 +18,7 @@ import TestConfig = require('../../test.config'); import { CreateFolderDialog } from './dialog/createFolderDialog'; import { CreateLibraryDialog } from './dialog/createLibraryDialog'; +import { FormControllersPage } from '@alfresco/adf-testing'; import { DropActions } from '../../actions/drop.actions'; import { by, element, protractor, $$, browser } from 'protractor'; @@ -27,7 +28,17 @@ import { BrowserVisibility, DocumentListPage } from '@alfresco/adf-testing'; export class ContentServicesPage { + columns = { + name: 'Display name', + size: 'Size', + nodeId: 'Node id', + createdBy: 'Created by', + created: 'Created' + }; + contentList = new DocumentListPage(element.all(by.css('adf-upload-drag-area adf-document-list')).first()); + formControllersPage = new FormControllersPage(); + multipleFileUploadToggle = element(by.id('adf-document-list-enable-drop-files')); createFolderDialog = new CreateFolderDialog(); createLibraryDialog = new CreateLibraryDialog(); dragAndDropAction = new DropActions(); @@ -165,16 +176,26 @@ export class ContentServicesPage { return this; } + enableDropFilesInAFolder() { + this.formControllersPage.enableToggle(this.multipleFileUploadToggle); + return this; + } + + disableDropFilesInAFolder() { + this.formControllersPage.disableToggle(this.multipleFileUploadToggle); + return this; + } + getElementsDisplayedSize() { - return this.contentList.dataTablePage().getAllRowsColumnValues('Size'); + return this.contentList.dataTablePage().getAllRowsColumnValues(this.columns.size); } getElementsDisplayedName() { - return this.contentList.dataTablePage().getAllRowsColumnValues('Display name'); + return this.contentList.dataTablePage().getAllRowsColumnValues(this.columns.name); } getElementsDisplayedId() { - return this.contentList.dataTablePage().getAllRowsColumnValues('Node id'); + return this.contentList.dataTablePage().getAllRowsColumnValues(this.columns.nodeId); } checkElementsSortedAsc(elements) { @@ -311,7 +332,7 @@ export class ContentServicesPage { } getAllRowsNameColumn() { - return this.contentList.getAllRowsColumnValues('Display name'); + return this.contentList.getAllRowsColumnValues(this.columns.name); } sortByName(sortOrder) { @@ -336,19 +357,19 @@ export class ContentServicesPage { } async checkListIsSortedByNameColumn(sortOrder) { - return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, 'Display name'); + return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, this.columns.name); } async checkListIsSortedByCreatedColumn(sortOrder) { - return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, 'Created'); + return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, this.columns.created); } async checkListIsSortedByAuthorColumn(sortOrder) { - return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, 'Created by'); + return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, this.columns.createdBy); } async checkListIsSortedBySizeColumn(sortOrder) { - return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, 'Size'); + return await this.contentList.dataTablePage().checkListIsSorted(sortOrder, this.columns.size); } sortAndCheckListIsOrderedByAuthor(sortOrder) { @@ -396,7 +417,7 @@ export class ContentServicesPage { } checkContentIsDisplayed(content) { - this.contentList.dataTablePage().checkContentIsDisplayed('Display name', content); + this.contentList.dataTablePage().checkContentIsDisplayed(this.columns.name, content); return this; } @@ -408,7 +429,7 @@ export class ContentServicesPage { } checkContentIsNotDisplayed(content) { - this.contentList.dataTablePage().checkContentIsNotDisplayed('Display name', content); + this.contentList.dataTablePage().checkContentIsNotDisplayed(this.columns.name, content); return this; } @@ -551,7 +572,7 @@ export class ContentServicesPage { } getColumnValueForRow(file, columnName) { - return this.contentList.dataTablePage().getColumnValueForRow('Display name', file, columnName); + return this.contentList.dataTablePage().getColumnValueForRow(this.columns.name, file, columnName); } async getStyleValueForRowText(rowName, styleName) { @@ -651,7 +672,7 @@ export class ContentServicesPage { } checkRowIsDisplayed(rowName) { - const row = this.contentList.dataTablePage().getCellElementByValue('Display name', rowName); + const row = this.contentList.dataTablePage().getCellElementByValue(this.columns.name, rowName); BrowserVisibility.waitUntilElementIsVisible(row); } @@ -674,4 +695,8 @@ export class ContentServicesPage { this.multiSelectToggle.click(); } + getRowByName(rowName) { + return this.contentList.dataTable.getRow(this.columns.name, rowName); + } + } diff --git a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts index afb1f7f51e..bb14c563ec 100644 --- a/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/processCloudDemoPage.ts @@ -98,5 +98,4 @@ export class ProcessCloudDemoPage { this.createButton.click(); return this; } - } diff --git a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts index 445b05b1d7..18c191bc45 100644 --- a/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/tasksCloudDemoPage.ts @@ -34,6 +34,7 @@ export class TasksCloudDemoPage { modeDropDownArrow = element(by.css('mat-form-field[data-automation-id="selectionMode"] div[class*="arrow-wrapper"]')); modeSelector = element(by.css("div[class*='mat-select-panel']")); displayTaskDetailsToggle = element(by.css('mat-slide-toggle[data-automation-id="taskDetailsRedirection"]')); + displayProcessDetailsToggle = element(by.css('mat-slide-toggle[data-automation-id="processDetailsRedirection"]')); multiSelectionToggle = element(by.css('mat-slide-toggle[data-automation-id="multiSelection"]')); formControllersPage = new FormControllersPage(); @@ -45,6 +46,11 @@ export class TasksCloudDemoPage { return this; } + disableDisplayProcessDetails() { + this.formControllersPage.disableToggle(this.displayProcessDetailsToggle); + return this; + } + enableMultiSelection() { this.formControllersPage.enableToggle(this.multiSelectionToggle); return this; diff --git a/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts b/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts new file mode 100644 index 0000000000..96cf93c843 --- /dev/null +++ b/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts @@ -0,0 +1,150 @@ +/*! + * @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 TestConfig = require('../test.config'); +import { LoginSSOPage } from '@alfresco/adf-testing'; +import { SettingsPage } from '@alfresco/adf-testing'; +import { ProcessCloudDemoPage } from '../pages/adf/demo-shell/process-services/processCloudDemoPage'; +import { AppListCloudPage } from '@alfresco/adf-testing'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; +import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; + +import { ProcessDefinitionsService, ApiService } from '@alfresco/adf-testing'; +import { ProcessInstancesService } from '@alfresco/adf-testing'; + +import { browser } from 'protractor'; + +describe('Process list cloud', () => { + + describe('Process List - selection', () => { + const settingsPage = new SettingsPage(); + const loginSSOPage = new LoginSSOPage(); + const navigationBarPage = new NavigationBarPage(); + const appListCloudComponent = new AppListCloudPage(); + const processCloudDemoPage = new ProcessCloudDemoPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); + + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + + let silentLogin; + const simpleApp = 'simple-app'; + const noOfProcesses = 3; + let response; + const processInstances = []; + + beforeAll(async (done) => { + silentLogin = false; + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + loginSSOPage.clickOnSSOButton(); + browser.ignoreSynchronization = true; + loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + processDefinitionService = new ProcessDefinitionsService(apiService); + const processDefinition = await processDefinitionService.getProcessDefinitions(simpleApp); + + processInstancesService = new ProcessInstancesService(apiService); + for (let i = 0; i < noOfProcesses; i++) { + response = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, simpleApp); + processInstances.push(response.entry.id); + } + + navigationBarPage.navigateToProcessServicesCloudPage(); + appListCloudComponent.checkApsContainer(); + appListCloudComponent.goToApp(simpleApp); + processCloudDemoPage.clickOnProcessFilters(); + processCloudDemoPage.runningProcessesFilter().clickProcessFilter(); + expect(processCloudDemoPage.getActiveFilterName()).toBe('Running Processes'); + tasksCloudDemoPage.clickSettingsButton().disableDisplayProcessDetails(); + tasksCloudDemoPage.clickAppButton(); + done(); + + }); + + it('[C297469] Should NOT be able to select a process when settings are set to None', () => { + tasksCloudDemoPage.clickSettingsButton().selectSelectionMode('None'); + tasksCloudDemoPage.clickAppButton(); + expect(processCloudDemoPage.getActiveFilterName()).toEqual('Running Processes'); + + processCloudDemoPage.processListCloudComponent().selectRowById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().getDataTable().checkNoRowIsSelected(); + }); + + it('[C297468] Should be able to select only one process when settings are set to Single', () => { + tasksCloudDemoPage.clickSettingsButton().selectSelectionMode('Single'); + tasksCloudDemoPage.clickAppButton(); + expect(processCloudDemoPage.getActiveFilterName()).toEqual('Running Processes'); + + processCloudDemoPage.processListCloudComponent().selectRowById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkRowIsSelectedById(processInstances[0]); + expect(processCloudDemoPage.processListCloudComponent().getDataTable().getNumberOfSelectedRows()).toEqual(1); + processCloudDemoPage.processListCloudComponent().selectRowById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsSelectedById(processInstances[1]); + expect(processCloudDemoPage.processListCloudComponent().getDataTable().getNumberOfSelectedRows()).toEqual(1); + }); + + it('[C297470] Should be able to select multiple processes using keyboard', () => { + tasksCloudDemoPage.clickSettingsButton().selectSelectionMode('Multiple'); + tasksCloudDemoPage.clickAppButton(); + expect(processCloudDemoPage.getActiveFilterName()).toEqual('Running Processes'); + + processCloudDemoPage.processListCloudComponent().selectRowById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkRowIsSelectedById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().selectRowWithKeyboard(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsSelectedById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkRowIsSelectedById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsNotSelectedById(processInstances[2]); + expect(processCloudDemoPage.processListCloudComponent().getDataTable().getNumberOfSelectedRows()).toEqual(2); + }); + + it('[C297465] Should be able to select multiple processes using checkboxes', () => { + tasksCloudDemoPage.clickSettingsButton().enableMultiSelection(); + tasksCloudDemoPage.clickAppButton(); + expect(processCloudDemoPage.getActiveFilterName()).toEqual('Running Processes'); + + processCloudDemoPage.processListCloudComponent().checkCheckboxById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkCheckboxById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[2]); + processCloudDemoPage.processListCloudComponent().checkCheckboxById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[0]); + }); + + it('[C299125] Should be possible to select all the rows when multiselect is true', () => { + tasksCloudDemoPage.clickSettingsButton().enableMultiSelection(); + tasksCloudDemoPage.clickAppButton(); + expect(processCloudDemoPage.getActiveFilterName()).toEqual('Running Processes'); + + processCloudDemoPage.processListCloudComponent().getDataTable().checkAllRowsButtonIsDisplayed().checkAllRows(); + processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[2]); + + processCloudDemoPage.processListCloudComponent().getDataTable().checkAllRowsButtonIsDisplayed().checkAllRows(); + processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[0]); + processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[1]); + processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[2]); + }); + + }); + +}); diff --git a/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts index a6f57abda1..e1a4938541 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/process-list-cloud-component.page.ts @@ -21,6 +21,11 @@ import { element, by } from 'protractor'; export class ProcessListCloudComponentPage { + columns = { + id: 'Id', + name: 'Name' + }; + processList = element(by.css('adf-cloud-process-list')); noProcessFound = element.all(by.css("div[class='adf-empty-content__title']")).first(); @@ -31,27 +36,51 @@ export class ProcessListCloudComponentPage { } selectRow(processName) { - return this.dataTable.selectRow('Name', processName); + return this.dataTable.selectRow(this.columns.name, processName); } selectRowById(processId) { - return this.dataTable.selectRow('Id', processId); + return this.dataTable.selectRow(this.columns.id, processId); + } + + checkRowIsSelectedById(processId) { + return this.dataTable.checkRowIsSelected(this.columns.id, processId); + } + + checkRowIsNotSelectedById(processId) { + return this.dataTable.checkRowIsNotSelected(this.columns.id, processId); + } + + checkRowIsCheckedById(processId) { + return this.dataTable.checkRowIsChecked(this.columns.id, processId); + } + + checkRowIsNotCheckedById(processId) { + return this.dataTable.checkRowIsNotChecked(this.columns.id, processId); + } + + checkCheckboxById(processId) { + return this.dataTable.clickCheckbox(this.columns.id, processId); } checkContentIsDisplayedByName(processName) { - return this.dataTable.checkContentIsDisplayed('Name', processName); + return this.dataTable.checkContentIsDisplayed(this.columns.name, processName); } checkContentIsDisplayedById(processId) { - return this.dataTable.checkContentIsDisplayed('Id', processId); + return this.dataTable.checkContentIsDisplayed(this.columns.id, processId); } checkContentIsNotDisplayedById(processId) { - return this.dataTable.checkContentIsNotDisplayed('Id', processId); + return this.dataTable.checkContentIsNotDisplayed(this.columns.id, processId); + } + + selectRowWithKeyboard(processId) { + return this.dataTable.selectRowWithKeyboard(this.columns.id, processId); } getAllRowsNameColumn() { - return this.dataTable.getAllRowsColumnValues('Name'); + return this.dataTable.getAllRowsColumnValues(this.columns.name); } checkProcessListIsLoaded() { From 0f63122a274aecc9e8cde82a3c5ac3618f3743bf Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Wed, 24 Apr 2019 20:24:55 +0100 Subject: [PATCH 163/208] fix new merged process list selection test --- .../process-list-selection-cloud.e2e.ts | 16 ++++++++-------- .../lib/core/pages/data-table-component.page.ts | 9 +++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts b/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts index 96cf93c843..858f857e08 100644 --- a/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts +++ b/e2e/process-services-cloud/process-list-selection-cloud.e2e.ts @@ -26,7 +26,7 @@ import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tas import { ProcessDefinitionsService, ApiService } from '@alfresco/adf-testing'; import { ProcessInstancesService } from '@alfresco/adf-testing'; -import { browser } from 'protractor'; +import resources = require('../util/resources'); describe('Process list cloud', () => { @@ -41,17 +41,14 @@ describe('Process list cloud', () => { let processDefinitionService: ProcessDefinitionsService; let processInstancesService: ProcessInstancesService; - let silentLogin; - const simpleApp = 'simple-app'; + const simpleApp = resources.ACTIVITI7_APPS.SIMPLE_APP.name; const noOfProcesses = 3; let response; const processInstances = []; beforeAll(async (done) => { - silentLogin = false; - settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, silentLogin); + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); loginSSOPage.clickOnSSOButton(); - browser.ignoreSynchronization = true; loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); @@ -66,6 +63,10 @@ describe('Process list cloud', () => { processInstances.push(response.entry.id); } + done(); + }); + + beforeEach(async (done) => { navigationBarPage.navigateToProcessServicesCloudPage(); appListCloudComponent.checkApsContainer(); appListCloudComponent.goToApp(simpleApp); @@ -75,7 +76,6 @@ describe('Process list cloud', () => { tasksCloudDemoPage.clickSettingsButton().disableDisplayProcessDetails(); tasksCloudDemoPage.clickAppButton(); done(); - }); it('[C297469] Should NOT be able to select a process when settings are set to None', () => { @@ -139,7 +139,7 @@ describe('Process list cloud', () => { processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[1]); processCloudDemoPage.processListCloudComponent().checkRowIsCheckedById(processInstances[2]); - processCloudDemoPage.processListCloudComponent().getDataTable().checkAllRowsButtonIsDisplayed().checkAllRows(); + processCloudDemoPage.processListCloudComponent().getDataTable().checkAllRowsButtonIsDisplayed().uncheckAllRows(); processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[0]); processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[1]); processCloudDemoPage.processListCloudComponent().checkRowIsNotCheckedById(processInstances[2]); diff --git a/lib/testing/src/lib/core/pages/data-table-component.page.ts b/lib/testing/src/lib/core/pages/data-table-component.page.ts index 1e13586516..1381589c07 100644 --- a/lib/testing/src/lib/core/pages/data-table-component.page.ts +++ b/lib/testing/src/lib/core/pages/data-table-component.page.ts @@ -60,6 +60,15 @@ export class DataTableComponentPage { return this; } + uncheckAllRows() { + BrowserVisibility.waitUntilElementIsVisible(this.selectAll); + BrowserVisibility.waitUntilElementIsClickable(this.selectAll).then(() => { + this.selectAll.click(); + BrowserVisibility.waitUntilElementIsNotOnPage(this.selectAll.element(by.css('input[aria-checked="true"]'))); + }); + return this; + } + clickCheckbox(columnName, columnValue) { const checkbox = this.getRowCheckbox(columnName, columnValue); BrowserVisibility.waitUntilElementIsClickable(checkbox); From 83cb98f4356320fcd94ba33cf8e2988ebef18107 Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Thu, 25 Apr 2019 02:27:45 +0300 Subject: [PATCH 164/208] Add complete task tests (#4639) --- .../taskDetailsCloudDemoPage.ts | 17 ++ .../task-form-cloud-component.e2e.ts | 151 ++++++++++++++++++ .../pages/public-api.ts | 1 + .../pages/task-form-cloud-component.page.ts | 48 ++++++ 4 files changed, 217 insertions(+) create mode 100644 e2e/process-services-cloud/task-form-cloud-component.e2e.ts create mode 100644 lib/testing/src/lib/process-services-cloud/pages/task-form-cloud-component.page.ts diff --git a/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts b/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts index 0fa41b9f3e..a25e38c8dc 100644 --- a/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts +++ b/e2e/pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage.ts @@ -17,12 +17,29 @@ import { BrowserVisibility } from '@alfresco/adf-testing'; import { element, by } from 'protractor'; +import { TaskHeaderCloudPage, TaskFormCloudComponent } from '@alfresco/adf-testing'; export class TaskDetailsCloudDemoPage { + taskHeaderCloudPage = new TaskHeaderCloudPage(); + taskFormCloudPage = new TaskFormCloudComponent(); + taskDetailsHeader = element(by.css(`h4[data-automation-id='task-details-header']`)); releaseButton = element(by.css('button[adf-cloud-unclaim-task]')); + taskHeaderCloud() { + return this.taskHeaderCloudPage; + } + + taskFormCloud() { + return this.taskFormCloudPage; + } + + checkTaskDetailsHeaderIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsHeader); + return this; + } + getTaskDetailsHeader() { BrowserVisibility.waitUntilElementIsVisible(this.taskDetailsHeader); return this.taskDetailsHeader.getText(); diff --git a/e2e/process-services-cloud/task-form-cloud-component.e2e.ts b/e2e/process-services-cloud/task-form-cloud-component.e2e.ts new file mode 100644 index 0000000000..bb69850445 --- /dev/null +++ b/e2e/process-services-cloud/task-form-cloud-component.e2e.ts @@ -0,0 +1,151 @@ +/*! + * @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 TestConfig = require('../test.config'); + +import { AppListCloudPage, StringUtil, ApiService, LoginSSOPage, SettingsPage, TasksService, QueryService, + ProcessDefinitionsService, ProcessInstancesService } from '@alfresco/adf-testing'; +import { NavigationBarPage } from '../pages/adf/navigationBarPage'; +import { TasksCloudDemoPage } from '../pages/adf/demo-shell/process-services/tasksCloudDemoPage'; +import { TaskDetailsCloudDemoPage } from '../pages/adf/demo-shell/process-services/taskDetailsCloudDemoPage'; + +import resources = require('../util/resources'); + +describe('Complete task - cloud directive', () => { + + const settingsPage = new SettingsPage(); + const loginSSOPage = new LoginSSOPage(); + const navigationBarPage = new NavigationBarPage(); + const appListCloudComponent = new AppListCloudPage(); + const tasksCloudDemoPage = new TasksCloudDemoPage(); + const taskDetailsCloudDemoPage = new TaskDetailsCloudDemoPage(); + + let tasksService: TasksService; + let processDefinitionService: ProcessDefinitionsService; + let processInstancesService: ProcessInstancesService; + let queryService: QueryService; + + let completedTask, createdTask, assigneeTask, toBeCompletedTask, completedProcess, claimedTask; + const candidateuserapp = resources.ACTIVITI7_APPS.CANDIDATE_USER_APP.name; + const completedTaskName = StringUtil.generateRandomString(), assignedTaskName = StringUtil.generateRandomString(); + + beforeAll(async (done) => { + settingsPage.setProviderBpmSso(TestConfig.adf.hostBPM, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false); + loginSSOPage.clickOnSSOButton(); + loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + const apiService = new ApiService('activiti', TestConfig.adf.hostBPM, TestConfig.adf.hostSso, 'BPM'); + await apiService.login(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + + tasksService = new TasksService(apiService); + createdTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateuserapp); + + assigneeTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateuserapp); + await tasksService.claimTask(assigneeTask.entry.id, candidateuserapp); + + toBeCompletedTask = await tasksService.createStandaloneTask(StringUtil.generateRandomString(), candidateuserapp); + await tasksService.claimTask(toBeCompletedTask.entry.id, candidateuserapp); + + completedTask = await tasksService.createStandaloneTask(assignedTaskName, candidateuserapp); + await tasksService.claimTask(completedTask.entry.id, candidateuserapp); + await tasksService.createAndCompleteTask(completedTaskName, candidateuserapp); + + processDefinitionService = new ProcessDefinitionsService(apiService); + const processDefinition = await processDefinitionService.getProcessDefinitions(candidateuserapp); + + processInstancesService = new ProcessInstancesService(apiService); + completedProcess = await processInstancesService.createProcessInstance(processDefinition.list.entries[0].entry.key, candidateuserapp); + + queryService = new QueryService(apiService); + const task = await queryService.getProcessInstanceTasks(completedProcess.entry.id, candidateuserapp); + tasksService = new TasksService(apiService); + claimedTask = await tasksService.claimTask(task.list.entries[0].entry.id, candidateuserapp); + + done(); + }); + + beforeEach((done) => { + navigationBarPage.navigateToProcessServicesCloudPage(); + appListCloudComponent.checkApsContainer(); + appListCloudComponent.goToApp(candidateuserapp); + done(); + }); + + it('[C307093] Complete button is not displayed when the task is already completed', () => { + tasksCloudDemoPage.completedTasksFilter().clickTaskFilter(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('Completed Tasks'); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(completedTaskName); + tasksCloudDemoPage.taskListCloudComponent().selectRow(completedTaskName); + taskDetailsCloudDemoPage.checkTaskDetailsHeaderIsDisplayed(); + taskDetailsCloudDemoPage.taskFormCloud().checkCompleteButtonIsNotDisplayed(); + }); + + it('[C307095] Task can not be completed by owner user', () => { + tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + tasksCloudDemoPage.editTaskFilterCloudComponent().clickCustomiseFilterHeader().clearAssignee().setStatusFilterDropDown('CREATED'); + + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(createdTask.entry.name); + tasksCloudDemoPage.taskListCloudComponent().selectRow(createdTask.entry.name); + taskDetailsCloudDemoPage.checkTaskDetailsHeaderIsDisplayed(); + taskDetailsCloudDemoPage.taskFormCloud().checkCompleteButtonIsNotDisplayed(); + }); + + it('[C307110] Task list is displayed after clicking on Cancel button', () => { + tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(assigneeTask.entry.name); + tasksCloudDemoPage.taskListCloudComponent().selectRow(assigneeTask.entry.name); + taskDetailsCloudDemoPage.checkTaskDetailsHeaderIsDisplayed(); + taskDetailsCloudDemoPage.taskFormCloud().clickCancelButton(); + + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(assigneeTask.entry.name); + }); + + it('[C307094] Standalone Task can be completed by a user that is owner and assignee', () => { + tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(toBeCompletedTask.entry.name); + tasksCloudDemoPage.taskListCloudComponent().selectRow(toBeCompletedTask.entry.name); + taskDetailsCloudDemoPage.checkTaskDetailsHeaderIsDisplayed(); + taskDetailsCloudDemoPage.taskFormCloud().checkCompleteButtonIsDisplayed().clickCompleteButton(); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(toBeCompletedTask.entry.name); + + tasksCloudDemoPage.completedTasksFilter().clickTaskFilter(); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(toBeCompletedTask.entry.name); + taskDetailsCloudDemoPage.taskFormCloud().checkCompleteButtonIsNotDisplayed(); + }); + + it('[C307111] Task of a process can be completed by a user that is owner and assignee', () => { + tasksCloudDemoPage.myTasksFilter().clickTaskFilter(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(claimedTask.entry.name); + tasksCloudDemoPage.taskListCloudComponent().selectRow(claimedTask.entry.name); + taskDetailsCloudDemoPage.checkTaskDetailsHeaderIsDisplayed(); + taskDetailsCloudDemoPage.taskFormCloud().checkCompleteButtonIsDisplayed().clickCompleteButton(); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(claimedTask.entry.name); + + tasksCloudDemoPage.completedTasksFilter().clickTaskFilter(); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedByName(claimedTask.entry.name); + taskDetailsCloudDemoPage.taskFormCloud().checkCompleteButtonIsNotDisplayed(); + }); + +}); diff --git a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts index 9fd6becfc7..56c2c2b11c 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/public-api.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/public-api.ts @@ -27,5 +27,6 @@ export * from './process-list-cloud-component.page'; export * from './task-filters-cloud-component.page'; export * from './task-list-cloud-component.page'; export * from './start-process-cloud-component.page'; +export * from './task-form-cloud-component.page'; export * from './dialog/public-api'; diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-form-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-form-cloud-component.page.ts new file mode 100644 index 0000000000..6378fd4143 --- /dev/null +++ b/lib/testing/src/lib/process-services-cloud/pages/task-form-cloud-component.page.ts @@ -0,0 +1,48 @@ +/*! + * @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 { element, by } from 'protractor'; +import { BrowserVisibility } from '../../core/utils/browser-visibility'; + +export class TaskFormCloudComponent { + + cancelButton = element(by.css("button[id='adf-cloud-cancel-task']")); + completeButton = element(by.css('button[adf-cloud-complete-task]')); + + checkCompleteButtonIsDisplayed() { + BrowserVisibility.waitUntilElementIsVisible(this.completeButton); + return this; + } + + checkCompleteButtonIsNotDisplayed() { + BrowserVisibility.waitUntilElementIsNotVisible(this.completeButton); + return this; + } + + clickCompleteButton() { + BrowserVisibility.waitUntilElementIsVisible(this.completeButton); + this.completeButton.click(); + return this; + } + + clickCancelButton() { + BrowserVisibility.waitUntilElementIsVisible(this.cancelButton); + this.cancelButton.click(); + return this; + } + +} From 3b83539b13d59531a8f4eaa02171bd231d0fc0a4 Mon Sep 17 00:00:00 2001 From: Cilibiu Bogdan <pionnegru@users.noreply.github.com> Date: Thu, 25 Apr 2019 02:48:41 +0300 Subject: [PATCH 165/208] [ADF-4227] Sidenav Layout - support direction (#4583) * basic ui direction service * direction property * demo shell integration * move the direction in up sidenav layout to allow also the header to reorganize use the configuration editor to change rtl ltr add documenation * Update app.component.html * fix unit tests * fix overlay viewer e2e * fix e2e --- demo-shell/src/app/app.component.html | 2 +- demo-shell/src/app/app.component.ts | 10 -- demo-shell/src/app/app.routes.ts | 106 +++++++++--------- .../app-layout/app-layout.component.html | 2 +- .../app-layout/app-layout.component.ts | 8 ++ .../components/sidenav-layout.component.md | 1 + docs/user-guide/rtl-support.md | 12 ++ e2e/core/viewer/viewer-properties.e2e.ts | 1 + e2e/pages/adf/navigationBarPage.ts | 8 +- .../sidenav-layout.component.html | 52 ++++----- .../sidenav-layout.component.scss | 11 ++ .../sidenav-layout.component.spec.ts | 4 +- .../sidenav-layout.component.ts | 4 +- 13 files changed, 124 insertions(+), 97 deletions(-) diff --git a/demo-shell/src/app/app.component.html b/demo-shell/src/app/app.component.html index d06c2af228..1fa3c352d9 100644 --- a/demo-shell/src/app/app.component.html +++ b/demo-shell/src/app/app.component.html @@ -1,4 +1,4 @@ -<div [dir]="textOrientation" class="adf-demo-app-container" > +<div class="adf-demo-app-container"> <router-outlet></router-outlet> <router-outlet name="overlay"></router-outlet> </div> diff --git a/demo-shell/src/app/app.component.ts b/demo-shell/src/app/app.component.ts index 365e7095fa..f4db0e4f2e 100644 --- a/demo-shell/src/app/app.component.ts +++ b/demo-shell/src/app/app.component.ts @@ -17,7 +17,6 @@ import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { - UserPreferencesService, AuthenticationService, AlfrescoApiService, PageTitleService @@ -33,24 +32,15 @@ import { MatDialog } from '@angular/material'; }) export class AppComponent implements OnInit { - textOrientation: string = 'ltr'; - constructor(private pageTitleService: PageTitleService, private alfrescoApiService: AlfrescoApiService, private authenticationService: AuthenticationService, - private userPreferencesService: UserPreferencesService, private router: Router, private dialogRef: MatDialog) { - this.userPreferencesService.set('textOrientation', this.textOrientation); - } ngOnInit() { - this.userPreferencesService.select('textOrientation').subscribe((textOrientation) => { - this.textOrientation = textOrientation; - }); - this.pageTitleService.setTitle('title'); this.alfrescoApiService.getInstance().on('error', (error) => { diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index e3d521ac41..b7f17bb126 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -85,67 +85,61 @@ export const appRoutes: Routes = [ ] }, { path: 'preview/s/:id', component: SharedLinkViewComponent }, - { - path: 'breadcrumb', - canActivate: [AuthGuardEcm], - component: AppLayoutComponent, - loadChildren: 'app/components/breadcrumb-demo/breadcrumb-demo.module#AppBreadcrumbModule' - }, - { - path: 'notifications', - component: AppLayoutComponent, - children: [ - { - path: '', - loadChildren: 'app/components/notifications/notifications.module#AppNotificationsModule' - } - ] - }, - { - path: 'config-editor', - component: AppLayoutComponent, - children: [ - { - path: '', - loadChildren: 'app/components/config-editor/config-editor.module#AppConfigEditorModule' - } - ] - }, - { - path: 'card-view', - component: AppLayoutComponent, - children: [ - { - path: '', - loadChildren: 'app/components/card-view/card-view.module#AppCardViewModule' - } - ] - }, - { - path: 'sites', - component: AppLayoutComponent, - children: [ - { - path: '', - loadChildren: 'app/components/sites/sites.module#SitesModule' - } - ] - }, - { - path: 'header-data', - component: AppLayoutComponent, - children: [ - { - path: '', - loadChildren: 'app/components/header-data/header-data.module#AppHeaderDataModule' - } - ] - }, { path: '', component: AppLayoutComponent, canActivate: [AuthGuard], children: [ + { + path: 'breadcrumb', + canActivate: [AuthGuardEcm], + loadChildren: 'app/components/breadcrumb-demo/breadcrumb-demo.module#AppBreadcrumbModule' + }, + { + path: 'notifications', + children: [ + { + path: '', + loadChildren: 'app/components/notifications/notifications.module#AppNotificationsModule' + } + ] + }, + { + path: 'config-editor', + children: [ + { + path: '', + loadChildren: 'app/components/config-editor/config-editor.module#AppConfigEditorModule' + } + ] + }, + { + path: 'card-view', + children: [ + { + path: '', + loadChildren: 'app/components/card-view/card-view.module#AppCardViewModule' + } + ] + }, + { + path: 'sites', + children: [ + { + path: '', + loadChildren: 'app/components/sites/sites.module#SitesModule' + } + ] + }, + { + path: 'header-data', + children: [ + { + path: '', + loadChildren: 'app/components/header-data/header-data.module#AppHeaderDataModule' + } + ] + }, { path: '', component: HomeComponent diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.html b/demo-shell/src/app/components/app-layout/app-layout.component.html index 1cc1e35967..5157b2218a 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.html +++ b/demo-shell/src/app/components/app-layout/app-layout.component.html @@ -1,4 +1,4 @@ -<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav" +<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav" [direction]="direction" [expandedSidenav]="expandedSidenav" (expanded)="setState($event)" [position]="position"> <adf-sidenav-layout-header> diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index 7518587bc6..9344a33eab 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -84,6 +84,7 @@ export class AppLayoutComponent implements OnInit { expandedSidenav = false; position = 'start'; + direction = 'ltr'; hideSidenav = false; showMenu = true; @@ -113,16 +114,23 @@ export class AppLayoutComponent implements OnInit { this.headerService.tooltip.subscribe((tooltip) => this.tooltip = tooltip); this.headerService.position.subscribe((position) => this.position = position); this.headerService.hideSidenav.subscribe((hideSidenav) => this.hideSidenav = hideSidenav); + + this.userPreferencesService.select('textOrientation').subscribe((textOrientation) => { + this.direction = textOrientation; + }); } constructor( private userPreferences: UserPreferencesService, private config: AppConfigService, private alfrescoApiService: AlfrescoApiService, + private userPreferencesService: UserPreferencesService, private headerService: HeaderDataService) { if (this.alfrescoApiService.getInstance().isOauthConfiguration()) { this.enableRedirect = false; } + + this.userPreferencesService.set('textOrientation', this.direction); } setState(state) { diff --git a/docs/core/components/sidenav-layout.component.md b/docs/core/components/sidenav-layout.component.md index 12c571a1e2..9909512001 100644 --- a/docs/core/components/sidenav-layout.component.md +++ b/docs/core/components/sidenav-layout.component.md @@ -75,6 +75,7 @@ sub-components (note the use of `<ng-template>` in the sub-components' body sect | sidenavMax | `number` | | Maximum size of the navigation region. | | sidenavMin | `number` | | Minimum size of the navigation region. | | stepOver | `number` | | Screen size at which display switches from small screen to large screen configuration. | +| direction | `string` | `ltr` | The direction of the layout. 'ltr' or 'rtl' | ### Events diff --git a/docs/user-guide/rtl-support.md b/docs/user-guide/rtl-support.md index d50e1c6dbc..b4327203be 100644 --- a/docs/user-guide/rtl-support.md +++ b/docs/user-guide/rtl-support.md @@ -18,6 +18,18 @@ added to the main `<body>` element in `index.html`. When the attribute is set to </body> ``` +If you use the [Sidenav Layout component](../core/components/sidenav-layout.component.md) you can choose set the direction property in it using the property direction ans set it to **'rtl'** + + +```html +<adf-sidenav-layout + [direction]="'rtl'"> +...... +</adf-sidenav-layout> +``` + + + Also, we have a [translation file](internationalization.md) for Arabic (code: "ar"), which is the [most widely used](https://en.wikipedia.org/wiki/List_of_languages_by_number_of_native_speakers) diff --git a/e2e/core/viewer/viewer-properties.e2e.ts b/e2e/core/viewer/viewer-properties.e2e.ts index ba5db13ea8..76c764308d 100644 --- a/e2e/core/viewer/viewer-properties.e2e.ts +++ b/e2e/core/viewer/viewer-properties.e2e.ts @@ -187,6 +187,7 @@ describe('Viewer - properties', () => { it('[C260100] Should be possible to disable Overlay viewer', () => { viewerPage.clickCloseButton(); + navigationBarPage.scrollTo(navigationBarPage.overlayViewerButton); navigationBarPage.clickOverlayViewerButton(); dataTable.doubleClickRow('Name', fileForOverlay.name); diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index 31d72c2c0c..d90e02bf29 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { browser, by, element } from 'protractor'; +import { browser, by, element, ElementFinder } from 'protractor'; import { ProcessServicesPage } from './process-services/processServicesPage'; import { AppListCloudPage } from '@alfresco/adf-testing'; import TestConfig = require('../../test.config'); @@ -24,6 +24,7 @@ import { BrowserVisibility } from '@alfresco/adf-testing'; export class NavigationBarPage { + linkListContainer = element(by.css('.adf-sidenav-linklist')); contentServicesButton = element(by.css('a[data-automation-id="Content Services"]')); dataTableButton = element(by.css('a[data-automation-id="Datatable"]')); dataTableNestedButton = element(by.css('button[data-automation-id="Datatable"]')); @@ -247,4 +248,9 @@ export class NavigationBarPage { BrowserVisibility.waitUntilElementIsVisible(this.customSourcesButton); this.customSourcesButton.click(); } + + scrollTo(el: ElementFinder) { + browser.executeScript(`return arguments[0].scrollTop = arguments[1].offsetTop`, this.linkListContainer.getWebElement(), el.getWebElement()); + return this; + } } diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html index 294ddb56d1..2155d9b30b 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.html @@ -1,27 +1,29 @@ -<ng-container *ngIf="!isHeaderInside"> - <ng-container class="adf-sidenav-layout-outer-header" - *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> -</ng-container> - -<adf-layout-container #container - [position]="position" - [sidenavMin]="sidenavMin" - [sidenavMax]="sidenavMax" - [mediaQueryList]="mediaQueryList" - [hideSidenav]="hideSidenav" - [expandedSidenav]="expandedSidenav" - data-automation-id="adf-layout-container" - class="adf-layout__content"> - - <ng-container app-layout-navigation - *ngTemplateOutlet="navigationTemplate; context:templateContext"></ng-container> - - <ng-container app-layout-content> - <ng-container *ngIf="isHeaderInside"> - <ng-container *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> - </ng-container> - <ng-container *ngTemplateOutlet="contentTemplate; context:templateContext"></ng-container> +<div [dir]="direction" class="adf-sidenav-layout-full-space"> + <ng-container *ngIf="!isHeaderInside"> + <ng-container class="adf-sidenav-layout-outer-header" + *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> </ng-container> -</adf-layout-container> -<ng-template #emptyTemplate></ng-template> + <adf-layout-container #container + [position]="position" + [sidenavMin]="sidenavMin" + [sidenavMax]="sidenavMax" + [mediaQueryList]="mediaQueryList" + [hideSidenav]="hideSidenav" + [expandedSidenav]="expandedSidenav" + data-automation-id="adf-layout-container" + class="adf-layout__content"> + + <ng-container app-layout-navigation + *ngTemplateOutlet="navigationTemplate; context:templateContext"></ng-container> + + <ng-container app-layout-content> + <ng-container *ngIf="isHeaderInside"> + <ng-container *ngTemplateOutlet="headerTemplate; context:templateContext"></ng-container> + </ng-container> + <ng-container *ngTemplateOutlet="contentTemplate; context:templateContext"></ng-container> + </ng-container> + </adf-layout-container> + + <ng-template #emptyTemplate></ng-template> +</div> diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss index 3b4e21fe08..e09993c521 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss @@ -2,6 +2,17 @@ $adf-sidenav-max: 300px !default; .adf-sidenav-layout { + + &-full-space { + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + overflow: hidden; + min-height: 0; + width: 100%; + } + @include flex-column; width: 100%; diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.spec.ts b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.spec.ts index 5b59352694..7ca53632b5 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.spec.ts +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.spec.ts @@ -144,8 +144,8 @@ describe('SidenavLayoutComponent', () => { describe('adf-sidenav-layout-header', () => { - const outerHeaderSelector = By.css('.adf-sidenav-layout > #header-test'), - innerHeaderSelector = By.css('.adf-sidenav-layout [data-automation-id="adf-layout-container"] #header-test'); + const outerHeaderSelector = By.css('.adf-sidenav-layout-full-space > #header-test'); + const innerHeaderSelector = By.css('.adf-layout__content > #header-test'); it('should contain the transcluded header template outside of the layout-container', () => { mediaQueryList.matches = false; diff --git a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts index 006dc56c30..7ba0cff6b1 100644 --- a/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts +++ b/lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts @@ -42,9 +42,11 @@ import { BehaviorSubject, Observable } from 'rxjs'; host: { class: 'adf-sidenav-layout' } }) export class SidenavLayoutComponent implements OnInit, AfterViewInit, OnDestroy { - static STEP_OVER = 600; + /** The direction of the layout. 'ltr' or 'rtl' */ + @Input() direction = 'ltr'; + /** The side that the drawer is attached to. Possible values are 'start' and 'end'. */ @Input() position = 'start'; From b87c18bc1307fa6b6e3e0dbb9149af2dfb631bbc Mon Sep 17 00:00:00 2001 From: cristinaj <Cristina.Jalba@ness.com> Date: Thu, 25 Apr 2019 12:41:59 +0300 Subject: [PATCH 166/208] [ADF-4388]Added edit task filter cloud component - taskId filter tests (#4596) * Added edit task filter cloud component - taskId filter tests * Update edit-task-filter-cloud-component.page.ts * Fix tests * Fix property test * Fix lint issues --- .../task-list-properties.e2e.ts | 26 +++++++++++++++++-- .../edit-task-filter-cloud-component.page.ts | 9 +++++++ .../pages/task-list-cloud-component.page.ts | 12 ++++++--- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/e2e/process-services-cloud/task-list-properties.e2e.ts b/e2e/process-services-cloud/task-list-properties.e2e.ts index 84e80dfe55..066048d4ad 100644 --- a/e2e/process-services-cloud/task-list-properties.e2e.ts +++ b/e2e/process-services-cloud/task-list-properties.e2e.ts @@ -68,6 +68,7 @@ describe('Edit task filters and task list properties', () => { await LocalStorageUtil.setConfigField('adf-cloud-task-list', JSON.stringify(jsonFile)); await LocalStorageUtil.setConfigField('adf-edit-task-filter', JSON.stringify({ 'filterProperties': [ + 'taskId', 'appName', 'status', 'assignee', @@ -163,6 +164,28 @@ describe('Edit task filters and task list properties', () => { tasksCloudDemoPage.taskListCloudComponent().checkContentIsNotDisplayedByName(createdTask.entry.name); }); + it('[C291906] Should be able to see only the task with specific taskId when typing it in the task Id field', () => { + tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setId(createdTask.entry.id); + expect(tasksCloudDemoPage.editTaskFilterCloudComponent().getId()).toEqual(createdTask.entry.id); + tasksCloudDemoPage.taskListCloudComponent().checkContentIsDisplayedById(createdTask.entry.id); + tasksCloudDemoPage.taskListCloudComponent().getRowsWithSameId(createdTask.entry.id).then((list) => { + expect(list.length).toEqual(1); + }); + }); + + it('[C291907] Should be able to see No tasks found when typing an invalid task id', () => { + tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); + expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); + + tasksCloudDemoPage.editTaskFilterCloudComponent().setId('invalidId'); + expect(tasksCloudDemoPage.editTaskFilterCloudComponent().getId()).toEqual('invalidId'); + + expect(tasksCloudDemoPage.taskListCloudComponent().getNoTasksFoundMessage()).toEqual(noTasksFoundMessage); + }); + it('[C297476] Filter by taskName', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); @@ -239,8 +262,7 @@ describe('Edit task filters and task list properties', () => { it('[C297687] Should be able to see No tasks found when typing unused value for priority field', () => { tasksCloudDemoPage.myTasksFilter().checkTaskFilterIsDisplayed(); expect(tasksCloudDemoPage.getActiveFilterName()).toBe('My Tasks'); - - tasksCloudDemoPage.editTaskFilterCloudComponent().setPriority('700'); + tasksCloudDemoPage.editTaskFilterCloudComponent().setPriority('87650'); expect(tasksCloudDemoPage.taskListCloudComponent().getNoTasksFoundMessage()).toEqual(noTasksFoundMessage); }); diff --git a/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts index 4dbcea7adf..518448c3d4 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/edit-task-filter-cloud-component.page.ts @@ -26,6 +26,7 @@ export class EditTaskFilterCloudComponentPage { assignee = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-assignee"]')); priority = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-priority"]')); taskName = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-taskName"]')); + id = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-taskId"]')); processDefinitionId = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-processDefinitionId"]')); processInstanceId = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-processInstanceId"]')); lastModifiedFrom = element(by.css('input[data-automation-id="adf-cloud-edit-task-property-lastModifiedFrom"]')); @@ -230,6 +231,14 @@ export class EditTaskFilterCloudComponentPage { return locator.getText(); } + setId(option) { + return this.setProperty('taskId', option); + } + + getId() { + return this.id.getAttribute('value'); + } + setTaskName(option) { return this.setProperty('taskName', option); } diff --git a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts index 7162bb9653..848a87ed7e 100644 --- a/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts +++ b/lib/testing/src/lib/process-services-cloud/pages/task-list-cloud-component.page.ts @@ -58,6 +58,10 @@ export class TaskListCloudComponentPage { return this.dataTable.getRowsWithSameColumnValues(column.name, taskName); } + getRowsWithSameId(taskId) { + return this.dataTable.getRowsWithSameColumnValues('Id', taskId); + } + checkRowIsSelected(taskName) { return this.dataTable.checkRowIsSelected(column.name, taskName); } @@ -78,12 +82,12 @@ export class TaskListCloudComponentPage { return this.dataTable.getCellElementByValue(column.name, taskName); } - checkContentIsDisplayedByProcessInstanceId(taskName) { - return this.dataTable.checkContentIsDisplayed(column.processInstanceId, taskName); + checkContentIsDisplayedById(taskId) { + return this.dataTable.checkContentIsDisplayed(column.id, taskId); } - checkContentIsDisplayedById(taskName) { - return this.dataTable.checkContentIsDisplayed(column.id, taskName); + checkContentIsDisplayedByProcessInstanceId(taskName) { + return this.dataTable.checkContentIsDisplayed(column.processInstanceId, taskName); } checkContentIsDisplayedByName(taskName) { From be49e722088d82ecce11a66884ee2cfa8972b0a7 Mon Sep 17 00:00:00 2001 From: Maurizio Vitale <maurizio.vitale@alfresco.com> Date: Thu, 25 Apr 2019 16:23:07 +0200 Subject: [PATCH 167/208] [ADF-4340] FormCloud - Be able to upload a file from the local source (#4647) * Add a shiny upload button * Fix tslint * Enable the viewer on the content click * Call the process storage in case the form has an upload * Fix the lint * Fix unit tests * Fix tslint on unit tests * Fix the lint * Fix the lint --- demo-shell/src/app/app.module.ts | 2 + demo-shell/src/app/app.routes.ts | 6 ++ .../cloud/cloud-viewer.component.css | 3 + .../cloud/cloud-viewer.component.html | 4 + .../cloud/cloud-viewer.component.ts | 46 ++++++++++ .../task-details-cloud-demo.component.ts | 4 + .../widgets/core/form-field.model.ts | 3 +- .../components/form-cloud.component.spec.ts | 86 ++++++++++--------- .../form/components/form-cloud.component.ts | 68 ++++++++++----- .../form/components/upload-cloud.widget.html | 6 +- .../form/components/upload-cloud.widget.scss | 42 +++++++++ .../form/components/upload-cloud.widget.ts | 52 ++++++----- .../src/lib/form/models/form-cloud.model.ts | 12 ++- .../form/services/form-cloud.service.spec.ts | 45 ++++++++-- .../lib/form/services/form-cloud.service.ts | 8 +- 15 files changed, 290 insertions(+), 97 deletions(-) create mode 100644 demo-shell/src/app/components/cloud/cloud-viewer.component.css create mode 100644 demo-shell/src/app/components/cloud/cloud-viewer.component.html create mode 100644 demo-shell/src/app/components/cloud/cloud-viewer.component.ts diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 14dd77cee5..60b2d6e54e 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -72,6 +72,7 @@ import { AppsCloudDemoComponent } from './components/cloud/apps-cloud-demo.compo import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component'; import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component'; import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; +import { CloudViewerComponent } from './components/cloud/cloud-viewer.component'; import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component'; import { StartProcessCloudDemoComponent } from './components/cloud/start-process-cloud-demo.component'; @@ -139,6 +140,7 @@ import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/ TasksCloudDemoComponent, ProcessesCloudDemoComponent, TaskDetailsCloudDemoComponent, + CloudViewerComponent, ProcessDetailsCloudDemoComponent, StartTaskCloudDemoComponent, StartProcessCloudDemoComponent, diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index b7f17bb126..10441b9c7c 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -47,6 +47,7 @@ import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud- import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component'; import { StartProcessCloudDemoComponent } from './components/cloud/start-process-cloud-demo.component'; import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component'; +import { CloudViewerComponent } from './components/cloud/cloud-viewer.component'; import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component'; import { TemplateDemoComponent } from './components/template-list/template-demo.component'; import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component'; @@ -152,6 +153,7 @@ export const appRoutes: Routes = [ path: 'cloud', canActivate: [AuthGuardSsoRoleService], data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403'}, + children: [ { path: '', @@ -192,6 +194,10 @@ export const appRoutes: Routes = [ path: 'task-details/:taskId', component: TaskDetailsCloudDemoComponent }, + { + path: 'task-details/:taskId/files/:nodeId/view', + component: CloudViewerComponent + }, { path: 'process-details/:processInstanceId', component: ProcessDetailsCloudDemoComponent diff --git a/demo-shell/src/app/components/cloud/cloud-viewer.component.css b/demo-shell/src/app/components/cloud/cloud-viewer.component.css new file mode 100644 index 0000000000..0e5cdfdd65 --- /dev/null +++ b/demo-shell/src/app/components/cloud/cloud-viewer.component.css @@ -0,0 +1,3 @@ +.activiti-form-viewer { + margin: 10px; +} diff --git a/demo-shell/src/app/components/cloud/cloud-viewer.component.html b/demo-shell/src/app/components/cloud/cloud-viewer.component.html new file mode 100644 index 0000000000..f224ceba15 --- /dev/null +++ b/demo-shell/src/app/components/cloud/cloud-viewer.component.html @@ -0,0 +1,4 @@ +<adf-viewer + [overlayMode]="true" + [nodeId]="nodeId"> +</adf-viewer> diff --git a/demo-shell/src/app/components/cloud/cloud-viewer.component.ts b/demo-shell/src/app/components/cloud/cloud-viewer.component.ts new file mode 100644 index 0000000000..a65bfe0b5c --- /dev/null +++ b/demo-shell/src/app/components/cloud/cloud-viewer.component.ts @@ -0,0 +1,46 @@ +/*! + * @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, OnDestroy, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Subscription } from 'rxjs'; +import { Params } from '@angular/router/src/shared'; + +@Component({ + selector: 'app-cloud-viewer', + templateUrl: './cloud-viewer.component.html' +}) +export class CloudViewerComponent implements OnInit, OnDestroy { + + nodeId: string; + + private sub: Subscription; + + constructor(private route: ActivatedRoute) { + } + + ngOnInit() { + this.sub = this.route.params.subscribe((params: Params) => { + this.nodeId = params['nodeId']; + }); + } + + ngOnDestroy() { + this.sub.unsubscribe(); + } + +} diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts index 3f590ba456..d003313993 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts @@ -69,6 +69,10 @@ export class TaskDetailsCloudDemoComponent { this.goBack(); } + onFormContentClicked(resourceId) { + this.router.navigate([`/cloud/${this.appName}/task-details/${this.taskId}/files/${resourceId.nodeId}/view`]); + } + onFormSaved() { this.notificationService.openSnackMessage('Task has been saved successfully'); } diff --git a/lib/core/form/components/widgets/core/form-field.model.ts b/lib/core/form/components/widgets/core/form-field.model.ts index 56a6cc9e71..c3c3957e16 100644 --- a/lib/core/form/components/widgets/core/form-field.model.ts +++ b/lib/core/form/components/widgets/core/form-field.model.ts @@ -374,10 +374,11 @@ export class FormFieldModel extends FormWidgetModel { } break; case FormFieldTypes.UPLOAD: + this.form.hasUpload = true; if (this.value && this.value.length > 0) { this.form.values[this.id] = this.value.map((elem) => elem.id).join(','); } else { - this.form.values[this.id] = null; + this.form.values[this.id] = []; } break; case FormFieldTypes.TYPEAHEAD: diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts index 342f5a7c97..2486aa13f0 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -17,7 +17,7 @@ import { SimpleChange } from '@angular/core'; import { Observable, of, throwError } from 'rxjs'; -import { FormFieldModel, FormFieldTypes, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService } from '@alfresco/adf-core'; +import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService } from '@alfresco/adf-core'; import { FormCloudService } from '../services/form-cloud.service'; import { FormCloudComponent } from './form-cloud.component'; import { FormCloud } from '../models/form-cloud.model'; @@ -25,7 +25,8 @@ import { cloudFormMock } from '../mocks/cloud-form.mock'; describe('FormCloudComponent', () => { - let formService: FormCloudService; + let formCloudService: FormCloudService; + let formService: FormService; let formComponent: FormCloudComponent; let visibilityService: WidgetVisibilityService; let logService: LogService; @@ -34,8 +35,9 @@ describe('FormCloudComponent', () => { logService = new LogService(null); visibilityService = new WidgetVisibilityService(null, logService); spyOn(visibilityService, 'refreshVisibility').and.stub(); - formService = new FormCloudService(null, null, logService); - formComponent = new FormCloudComponent(formService, visibilityService); + formCloudService = new FormCloudService(null, null, logService); + formService = new FormService(null, null, logService); + formComponent = new FormCloudComponent(formCloudService, formService, null, visibilityService); }); it('should check form', () => { @@ -144,15 +146,15 @@ describe('FormCloudComponent', () => { }); it('should get task variables if a task form is rendered', () => { - spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => { + spyOn(formCloudService, 'getTaskForm').and.callFake((currentTaskId) => { return new Observable((observer) => { observer.next({ formRepresentation: { taskId: currentTaskId }}); observer.complete(); }); }); - spyOn(formService, 'getTaskVariables').and.returnValue(of({})); - spyOn(formService, 'getTask').and.callFake((currentTaskId) => { + spyOn(formCloudService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formCloudService, 'getTask').and.callFake((currentTaskId) => { return new Observable((observer) => { observer.next({ formRepresentation: { taskId: currentTaskId }}); observer.complete(); @@ -165,25 +167,25 @@ describe('FormCloudComponent', () => { formComponent.taskId = taskId; formComponent.loadForm(); - expect(formService.getTaskVariables).toHaveBeenCalledWith(appName, taskId); + expect(formCloudService.getTaskVariables).toHaveBeenCalledWith(appName, taskId); }); it('should not get task variables and form if task id is not specified', () => { - spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => { + spyOn(formCloudService, 'getTaskForm').and.callFake((currentTaskId) => { return new Observable((observer) => { observer.next({ taskId: currentTaskId }); observer.complete(); }); }); - spyOn(formService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formCloudService, 'getTaskVariables').and.returnValue(of({})); formComponent.appName = 'test-app'; formComponent.taskId = null; formComponent.loadForm(); - expect(formService.getTaskForm).not.toHaveBeenCalled(); - expect(formService.getTaskVariables).not.toHaveBeenCalled(); + expect(formCloudService.getTaskForm).not.toHaveBeenCalled(); + expect(formCloudService.getTaskVariables).not.toHaveBeenCalled(); }); it('should get form definition by form id on load', () => { @@ -200,7 +202,7 @@ describe('FormCloudComponent', () => { }); it('should refresh visibility when the form is loaded', () => { - spyOn(formService, 'getForm').and.returnValue(of({formRepresentation: {formDefinition: {}}})); + spyOn(formCloudService, 'getForm').and.returnValue(of({formRepresentation: {formDefinition: {}}})); const formId = '123'; const appName = 'test-app'; @@ -208,7 +210,7 @@ describe('FormCloudComponent', () => { formComponent.formId = formId; formComponent.loadForm(); - expect(formService.getForm).toHaveBeenCalledWith(appName, formId); + expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId); expect(visibilityService.refreshVisibility).toHaveBeenCalled(); }); @@ -376,12 +378,12 @@ describe('FormCloudComponent', () => { const appName = 'test-app'; const taskId = '456'; - spyOn(formService, 'getTask').and.returnValue(of({})); - spyOn(formService, 'getTaskVariables').and.returnValue(of({})); - spyOn(formService, 'getTaskForm').and.returnValue(of({formRepresentation: {taskId: taskId, formDefinition: {selectedOutcome: 'custom-outcome'}}})); + spyOn(formCloudService, 'getTask').and.returnValue(of({})); + spyOn(formCloudService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formCloudService, 'getTaskForm').and.returnValue(of({formRepresentation: {taskId: taskId, formDefinition: {selectedOutcome: 'custom-outcome'}}})); formComponent.formLoaded.subscribe(() => { - expect(formService.getTaskForm).toHaveBeenCalledWith(appName, taskId); + expect(formCloudService.getTaskForm).toHaveBeenCalledWith(appName, taskId); expect(formComponent.form).toBeDefined(); expect(formComponent.form.taskId).toBe(taskId); done(); @@ -395,10 +397,10 @@ describe('FormCloudComponent', () => { it('should handle error when getting form by task id', (done) => { const error = 'Some error'; - spyOn(formService, 'getTask').and.returnValue(of({})); - spyOn(formService, 'getTaskVariables').and.returnValue(of({})); + spyOn(formCloudService, 'getTask').and.returnValue(of({})); + spyOn(formCloudService, 'getTaskVariables').and.returnValue(of({})); spyOn(formComponent, 'handleError').and.stub(); - spyOn(formService, 'getTaskForm').and.callFake(() => { + spyOn(formCloudService, 'getTaskForm').and.callFake(() => { return throwError(error); }); @@ -409,7 +411,7 @@ describe('FormCloudComponent', () => { }); it('should fetch and parse form definition by id', (done) => { - spyOn(formService, 'getForm').and.callFake((currentAppName, currentFormId) => { + spyOn(formCloudService, 'getForm').and.callFake((currentAppName, currentFormId) => { return new Observable((observer) => { observer.next({ formRepresentation: {id: currentFormId, formDefinition: {}}}); observer.complete(); @@ -433,14 +435,14 @@ describe('FormCloudComponent', () => { const error = 'Some error'; spyOn(formComponent, 'handleError').and.stub(); - spyOn(formService, 'getForm').and.callFake(() => throwError(error)); + spyOn(formCloudService, 'getForm').and.callFake(() => throwError(error)); formComponent.getFormById('test-app', '123'); expect(formComponent.handleError).toHaveBeenCalledWith(error); }); it('should save task form and raise corresponding event', () => { - spyOn(formService, 'saveTaskForm').and.callFake(() => { + spyOn(formCloudService, 'saveTaskForm').and.callFake(() => { return new Observable((observer) => { observer.next(); observer.complete(); @@ -475,14 +477,14 @@ describe('FormCloudComponent', () => { formComponent.saveTaskForm(); - expect(formService.saveTaskForm).toHaveBeenCalledWith(appName, formModel.taskId, formModel.id, formModel.values); + expect(formCloudService.saveTaskForm).toHaveBeenCalledWith(appName, formModel.taskId, formModel.id, formModel.values); expect(saved).toBeTruthy(); expect(savedForm).toEqual(formModel); }); it('should handle error during form save', () => { const error = 'Error'; - spyOn(formService, 'saveTaskForm').and.callFake(() => throwError(error)); + spyOn(formCloudService, 'saveTaskForm').and.callFake(() => throwError(error)); spyOn(formComponent, 'handleError').and.stub(); const taskId = '123-223'; @@ -509,7 +511,7 @@ describe('FormCloudComponent', () => { }); it('should require form with appName and taskId to save', () => { - spyOn(formService, 'saveTaskForm').and.stub(); + spyOn(formCloudService, 'saveTaskForm').and.stub(); formComponent.form = null; formComponent.saveTaskForm(); @@ -523,11 +525,11 @@ describe('FormCloudComponent', () => { formComponent.taskId = '123'; formComponent.saveTaskForm(); - expect(formService.saveTaskForm).not.toHaveBeenCalled(); + expect(formCloudService.saveTaskForm).not.toHaveBeenCalled(); }); it('should require form with appName and taskId to complete', () => { - spyOn(formService, 'completeTaskForm').and.stub(); + spyOn(formCloudService, 'completeTaskForm').and.stub(); formComponent.form = null; formComponent.completeTaskForm('save'); @@ -540,11 +542,11 @@ describe('FormCloudComponent', () => { formComponent.taskId = '123'; formComponent.completeTaskForm('complete'); - expect(formService.completeTaskForm).not.toHaveBeenCalled(); + expect(formCloudService.completeTaskForm).not.toHaveBeenCalled(); }); it('should complete form and raise corresponding event', () => { - spyOn(formService, 'completeTaskForm').and.callFake(() => { + spyOn(formCloudService, 'completeTaskForm').and.callFake(() => { return new Observable((observer) => { observer.next(); observer.complete(); @@ -575,7 +577,7 @@ describe('FormCloudComponent', () => { formComponent.appName = appName; formComponent.completeTaskForm(outcome); - expect(formService.completeTaskForm).toHaveBeenCalledWith(appName, formModel.taskId, formModel.id, formModel.values, outcome); + expect(formCloudService.completeTaskForm).toHaveBeenCalledWith(appName, formModel.taskId, formModel.id, formModel.values, outcome); expect(completed).toBeTruthy(); }); @@ -714,7 +716,7 @@ describe('FormCloudComponent', () => { formComponent.onOutcomeClicked(outcome); }); - it('should refresh form values when data is changed', () => { + it('should refresh form values when data is changed', (done) => { formComponent.form = new FormCloud(JSON.parse(JSON.stringify(cloudFormMock))); let formFields = formComponent.form.getFormFields(); @@ -723,17 +725,23 @@ describe('FormCloudComponent', () => { expect(labelField.value).toBeNull(); expect(radioField.value).toBeUndefined(); - const formValues: any[] = [{name: 'text1', value: 'test'}, {name: 'number1', value: 23}]; + const formValues: any[] = [{name: 'text1', value: 'test'}, {name: 'number1', value: 99}]; const change = new SimpleChange(null, formValues, false); formComponent.data = formValues; + + formComponent.formLoaded.subscribe( (form) => { + formFields = form.getFormFields(); + labelField = formFields.find((field) => field.id === 'text1'); + radioField = formFields.find((field) => field.id === 'number1'); + expect(labelField.value).toBe('test'); + expect(radioField.value).toBe(99); + + done(); + }); + formComponent.ngOnChanges({ 'data': change }); - formFields = formComponent.form.getFormFields(); - labelField = formFields.find((field) => field.id === 'text1'); - radioField = formFields.find((field) => field.id === 'number1'); - expect(labelField.value).toBe('test'); - expect(radioField.value).toBe(23); }); it('should refresh radio buttons value when id is given to data', () => { diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts index f0a832a0a0..6d4f80ef89 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts @@ -22,7 +22,7 @@ import { import { Observable, of, forkJoin } from 'rxjs'; import { switchMap } from 'rxjs/operators'; import { Subscription } from 'rxjs'; -import { FormBaseComponent, FormFieldModel, FormOutcomeEvent, FormOutcomeModel, WidgetVisibilityService } from '@alfresco/adf-core'; +import { FormBaseComponent, FormFieldModel, FormOutcomeEvent, FormOutcomeModel, WidgetVisibilityService, FormService, NotificationService } from '@alfresco/adf-core'; import { FormCloudService } from '../services/form-cloud.service'; import { FormCloud } from '../models/form-cloud.model'; import { TaskVariableCloud } from '../models/task-variable-cloud.model'; @@ -81,12 +81,21 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { @Output() formDataRefreshed: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); + @Output() + formContentClicked: EventEmitter<string> = new EventEmitter<string>(); + protected subscriptions: Subscription[] = []; nodeId: string; - constructor(protected formService: FormCloudService, + constructor(protected formCloudService: FormCloudService, + protected formService: FormService, + private notificationService: NotificationService, protected visibilityService: WidgetVisibilityService) { super(); + + this.formService.formContentClicked.subscribe((content: any) => { + this.formContentClicked.emit(content); + }); } ngOnChanges(changes: SimpleChanges) { @@ -136,10 +145,10 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { } findProcessVariablesByTaskId(appName: string, taskId: string): Observable<any> { - return this.formService.getTask(appName, taskId).pipe( + return this.formCloudService.getTask(appName, taskId).pipe( switchMap((task: any) => { if (this.isAProcessTask(task)) { - return this.formService.getTaskVariables(appName, taskId); + return this.formCloudService.getTaskVariables(appName, taskId); } else { return of({}); } @@ -153,8 +162,8 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { getFormByTaskId(appName, taskId: string): Promise<FormCloud> { return new Promise<FormCloud>((resolve, reject) => { - forkJoin(this.formService.getTaskForm(appName, taskId), - this.formService.getTaskVariables(appName, taskId)) + forkJoin(this.formCloudService.getTaskForm(appName, taskId), + this.formCloudService.getTaskVariables(appName, taskId)) .subscribe( (data) => { this.data = data[1]; @@ -163,7 +172,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { this.visibilityService.refreshVisibility(<any> parsedForm); parsedForm.validateForm(); this.form = parsedForm; - this.form.nodeId = this.nodeId; this.onFormLoaded(this.form); resolve(this.form); }, @@ -176,17 +184,8 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { }); } - async getFormDefinitionWithFolderTask(appName: string, taskId: string) { - await this.getFolderTask(appName, taskId); - await this.getFormByTaskId(appName, taskId); - } - - async getFolderTask(appName: string, taskId: string) { - this.nodeId = await this.formService.getProcessStorageFolderTask(appName, taskId).toPromise(); - } - getFormById(appName: string, formId: string) { - this.formService + this.formCloudService .getForm(appName, formId) .subscribe( (form) => { @@ -195,7 +194,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { this.visibilityService.refreshVisibility(<any> parsedForm); parsedForm.validateForm(); this.form = parsedForm; - this.form.nodeId = this.nodeId; this.onFormLoaded(this.form); }, (error) => { @@ -204,9 +202,37 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { ); } + getFormDefinitionWithFolderTask(appName: string, taskId: string) { + this.getFormDefinitionWithFolderByTaskId(appName, taskId); + } + + async getFormDefinitionWithFolderByTaskId(appName: string, taskId: string) { + try { + await this.getFormByTaskId(appName, taskId); + + const hasUploadWidget = (<any> this.form).hasUpload; + if (hasUploadWidget) { + try { + await this.getFolderTask(appName, taskId); + this.form.nodeId = this.nodeId; + } catch (error) { + this.notificationService.openSnackMessage('The content repo is not configured'); + } + } + + } catch (error) { + this.notificationService.openSnackMessage('Form service an error occour'); + } + + } + + async getFolderTask(appName: string, taskId: string) { + this.nodeId = await this.formCloudService.getProcessStorageFolderTask(appName, taskId).toPromise(); + } + saveTaskForm() { if (this.form && this.appName && this.taskId) { - this.formService + this.formCloudService .saveTaskForm(this.appName, this.taskId, this.form.id, this.form.values) .subscribe( () => { @@ -219,7 +245,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { completeTaskForm(outcome?: string) { if (this.form && this.appName && this.taskId) { - this.formService + this.formCloudService .completeTaskForm(this.appName, this.taskId, this.form.id, this.form.values, outcome) .subscribe( () => { @@ -232,7 +258,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { parseForm(json: any): FormCloud { if (json) { - const form = new FormCloud(json, this.data, this.readOnly, this.formService); + const form = new FormCloud(json, this.data, this.readOnly, this.formCloudService); if (!json.formRepresentation.formDefinition || !json.formRepresentation.formDefinition.fields) { form.outcomes = this.getFormDefinitionOutcomes(form); } diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html index 1e8b6a207f..2bfe986a4f 100644 --- a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.html @@ -2,13 +2,13 @@ [class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly"> <label class="adf-label" [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label> - <div class="adf-upload-widget-container"> + <div class="adf-cloud-upload-widget-container"> <div> <mat-list *ngIf="hasFile"> - <mat-list-item class="adf-upload-files-row" *ngFor="let file of field.value"> + <mat-list-item class="adf-upload-files-row" *ngFor="let file of currentFiles"> <img mat-list-icon class="adf-upload-widget__icon" [id]="'file-'+file.id+'-icon'" - [src]="getIcon(file.mimeType)" + [src]="getIcon(file.content.mimeType)" [alt]="mimeTypeIcon" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)" diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss index e69de29bb2..80365289e4 100644 --- a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.scss @@ -0,0 +1,42 @@ + +.adf-cloud { + + &-upload-widget-container { + margin-bottom: 15px; + + input { + cursor: pointer; + height: 100%; + right: 0; + opacity: 0; + position: absolute; + top: 0; + width: 300px; + z-index: 4; + } + } + + &-upload-widget { + width: 100%; + word-break: break-all; + padding: 0.4375em 0; + border-top: 0.84375em solid transparent; + } + + &-upload-widget__icon { + padding: 6px; + float: left; + cursor: pointer; + } + + &-upload-widget__reset { + margin-top: -2px; + } + + &-upload-files-row { + .mat-line { + margin-bottom: 0; + } + } + +} diff --git a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts index 7a4f8b2beb..764ef8e531 100644 --- a/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/upload-cloud.widget.ts @@ -19,8 +19,8 @@ import { Component, ElementRef, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { Observable, from } from 'rxjs'; -import { mergeMap, map } from 'rxjs/operators'; -import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService } from '@alfresco/adf-core'; +import { mergeMap, map, catchError } from 'rxjs/operators'; +import { WidgetComponent, baseHost, LogService, FormService, ThumbnailService, ProcessContentService } from '@alfresco/adf-core'; import { FormCloudService } from '../services/form-cloud.service'; @Component({ @@ -37,12 +37,15 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni multipleOption: string = ''; mimeTypeIcon: string; + currentFiles = []; + @ViewChild('uploadFiles') fileInput: ElementRef; constructor(public formService: FormService, private thumbnailService: ThumbnailService, private formCloudService: FormCloudService, + public processContentService: ProcessContentService, private logService: LogService) { super(formService); } @@ -52,6 +55,7 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni this.field.value && this.field.value.length > 0) { this.hasFile = true; + this.currentFiles = [...this.field.value]; } this.getMultipleFileParam(); } @@ -64,26 +68,27 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni onFileChanged(event: any) { const files = event.target.files; - let filesSaved = []; - - if (this.field.json.value) { - filesSaved = [...this.field.json.value]; - } if (files && files.length > 0) { from(files) .pipe(mergeMap((file) => this.uploadRawContent(file))) .subscribe( - (res) => filesSaved.push(res), + (res) => { + this.currentFiles.push(res); + }, (error) => this.logService.error(`Error uploading file. See console output for more details. ${error}` ), () => { - this.field.form.values[this.field.id] = filesSaved; + this.fixIncompatibilityFromPreviousAndNewForm(this.currentFiles); this.hasFile = true; } ); } } + fixIncompatibilityFromPreviousAndNewForm(filesSaved) { + this.field.form.values[this.field.id] = filesSaved; + } + getIcon(mimeType) { return this.thumbnailService.getMimeTypeIcon(mimeType); } @@ -93,11 +98,16 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni .pipe( map((response: any) => { this.logService.info(response); - return { nodeId : response.id}; - }) + return { nodeId : response.id, name: response.name, content: response.content, createdAt: response.createdAt }; + }), + catchError((err) => this.handleError(err)) ); } + private handleError(error: any): any { + return this.logService.error(error || 'Server error'); + } + getMultipleFileParam() { if (this.field && this.field.params && @@ -107,29 +117,25 @@ export class UploadCloudWidgetComponent extends WidgetComponent implements OnIni } private removeElementFromList(file) { - const index = this.field.value.indexOf(file); - - // remove from content too + const index = this.currentFiles.indexOf(file); if (index !== -1) { - this.field.value.splice(index, 1); - this.field.json.value = this.field.value; - this.field.updateForm(); + this.currentFiles.splice(index, 1); + this.fixIncompatibilityFromPreviousAndNewForm(this.currentFiles); } - this.hasFile = this.field.value.length > 0; + this.hasFile = this.currentFiles.length > 0; this.resetFormValueWithNoFiles(); } private resetFormValueWithNoFiles() { - if (this.field.value.length === 0) { - this.field.value = []; - this.field.json.value = []; + if (this.currentFiles.length === 0) { + this.currentFiles = []; } } - fileClicked(contentLinkModel: any): void { - + fileClicked(nodeId: any): void { + this.formService.formContentClicked.next(nodeId); } } diff --git a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts index 1f557675bd..57ade28cfe 100644 --- a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts @@ -81,8 +81,9 @@ export class FormCloud { this.fields = this.parseRootFields(json); - if (formData) { + if (formData && formData.length > 0) { this.loadData(formData); + this.fixIncompatibilityFromPreviousAndNewForm(formData); } for (let i = 0; i < this.fields.length; i++) { @@ -123,6 +124,15 @@ export class FormCloud { this.validateForm(); } + fixIncompatibilityFromPreviousAndNewForm(formData) { + Object.keys(this.values).forEach( (propertyName) => { + const fieldValue = formData.find((value) => { return value.name === propertyName; }); + if (fieldValue) { + this.values[propertyName] = fieldValue.value; + } + }); + } + hasTabs(): boolean { return this.tabs && this.tabs.length > 0; } diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts index 2714d0508b..6cc3123c18 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.spec.ts @@ -94,7 +94,7 @@ describe('Form Cloud service', () => { expect(result).toBeDefined(); expect(result.id).toBe(responseBody.entry.id); expect(result.name).toBe(responseBody.entry.name); - expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/rb/v1/tasks/${taskId}`)).toBeTruthy(); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/query/v1/tasks/${taskId}`)).toBeTruthy(); expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET'); done(); }); @@ -102,12 +102,47 @@ describe('Form Cloud service', () => { }); it('should fetch task variables', (done) => { - oauth2Auth.callCustomApi.and.returnValue(Promise.resolve({ content: { name: 'abc' } })); + oauth2Auth.callCustomApi.and.returnValue(Promise.resolve({ + 'list': { + 'entries': [ + { + 'entry': { + 'serviceName': 'fake-rb', + 'serviceFullName': 'fake-rb', + 'serviceVersion': '', + 'appName': 'fake', + 'appVersion': '', + 'serviceType': null, + 'id': 25, + 'type': 'string', + 'name': 'fakeProperty', + 'createTime': 1556112661342, + 'lastUpdatedTime': 1556112661342, + 'executionId': null, + 'value': 'fakeValue', + 'markedAsDeleted': false, + 'processInstanceId': '18e16bc7-6694-11e9-9c1b-0a586460028a', + 'taskId': '18e192da-6694-11e9-9c1b-0a586460028a', + 'taskVariable': true + } + } + ], + 'pagination': { + 'skipCount': 0, + 'maxItems': 100, + 'count': 1, + 'hasMoreItems': false, + 'totalItems': 1 + } + } + })); - service.getTaskVariables(appName, taskId).subscribe((result: any) => { + service.getTaskVariables(appName, taskId).subscribe((result) => { expect(result).toBeDefined(); - expect(result.name).toBe('abc'); - expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/rb/v1/tasks/${taskId}/variables`)).toBeTruthy(); + expect(result.length).toBe(1); + expect(result[0].name).toBe('fakeProperty'); + expect(result[0].value).toBe('fakeValue'); + expect(oauth2Auth.callCustomApi.calls.mostRecent().args[0].endsWith(`${appName}/query/v1/tasks/${taskId}/variables`)).toBeTruthy(); expect(oauth2Auth.callCustomApi.calls.mostRecent().args[1]).toBe('GET'); done(); }); diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts index eeced9d7f1..3396ba691c 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -92,7 +92,7 @@ export class FormCloudService { .getInstance() .oauth2Auth.callCustomApi(apiUrl, 'POST', null, null, null, - { filedata: file, nodeType: 'cm:content' }, null, + { filedata: file, nodeType: 'cm:content', overwrite: true }, null, ['multipart/form-data'], this.accepts, this.returnType, null, null) ).pipe( @@ -191,7 +191,7 @@ export class FormCloudService { this.returnType, null, null) ).pipe( map((res: any) => { - return <TaskVariableCloud[]> res.content; + return res.list.entries.map((variable) => new TaskVariableCloud(variable.entry)); }), catchError((err) => this.handleError(err)) ); @@ -245,7 +245,7 @@ export class FormCloudService { } private buildGetTaskUrl(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks/${taskId}`; + return `${this.appConfigService.get('bpmHost')}/${appName}/query/v1/tasks/${taskId}`; } private buildGetFormUrl(appName: string, formId: string): string { @@ -265,7 +265,7 @@ export class FormCloudService { } private buildGetTaskVariablesUrl(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks/${taskId}/variables`; + return `${this.appConfigService.get('bpmHost')}/${appName}/query/v1/tasks/${taskId}/variables`; } private buildFolderTask(appName: string, taskId: string): string { From 37f52a139e8e183d7b686e42f3f35ccdcf9755d6 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Thu, 25 Apr 2019 17:17:44 +0200 Subject: [PATCH 168/208] [ADF-4411] Create script to remove Alfresco Dependencies from package (#4651) * [ADF-4411] Create script to remove Alfresco Dependencies from package.json --- scripts/remove-alfresco-dependencies.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 scripts/remove-alfresco-dependencies.sh diff --git a/scripts/remove-alfresco-dependencies.sh b/scripts/remove-alfresco-dependencies.sh new file mode 100755 index 0000000000..470f880dc9 --- /dev/null +++ b/scripts/remove-alfresco-dependencies.sh @@ -0,0 +1,9 @@ +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +echo "====== Removing Alfresco dependencies from package.json =====" + +grep -wirn '@alfresco*' $DIR/../package.json + +sed -i '' '/@alfresco*/,// d' $DIR/../package.json + +echo "====== Alfresco dependencies removed from package.json =====" From f94eb5872abae55c6e06ffbd60a0838c0da4b985 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 25 Apr 2019 19:49:38 +0100 Subject: [PATCH 169/208] [ADF-4405] [ADF-4423] Fix clipboard directive on json cell (#4643) * [ADF-4405] [ADF-4423] Fix clipboard directive on json cell * [ADF-4405] Fix unit tests * [ADF-4405] Fix e2e test --- .../content-node-share/content-node-share.dialog.html | 2 +- lib/core/clipboard/clipboard.directive.spec.ts | 3 ++- lib/core/clipboard/clipboard.directive.ts | 8 +++++--- .../components/datatable/datatable-cell.component.ts | 2 +- .../datatable/components/datatable/json-cell.component.ts | 4 +--- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/content-services/content-node-share/content-node-share.dialog.html b/lib/content-services/content-node-share/content-node-share.dialog.html index cc5e893393..5e1fe28e19 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.html +++ b/lib/content-services/content-node-share/content-node-share.dialog.html @@ -31,7 +31,7 @@ readonly="readonly"> <mat-icon class="adf-input-action" matSuffix [clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate" - [adf-clipboard] target="sharedLinkInput"> + [adf-clipboard] [target]="sharedLinkInput"> link </mat-icon> </mat-form-field> diff --git a/lib/core/clipboard/clipboard.directive.spec.ts b/lib/core/clipboard/clipboard.directive.spec.ts index 6a39509516..3e56c66a24 100644 --- a/lib/core/clipboard/clipboard.directive.spec.ts +++ b/lib/core/clipboard/clipboard.directive.spec.ts @@ -72,11 +72,12 @@ describe('CopyClipboardDirective', () => { @Component({ selector: 'adf-copy-conent-test-component', - template: `<span adf-clipboard>{{ mockText }}</span>` + template: `<span adf-clipboard="placeholder">{{ mockText }}</span>` }) class TestCopyClipboardComponent { mockText = 'text to copy'; + placeholder = 'copy text'; @ViewChild(ClipboardDirective) clipboardDirective: ClipboardDirective; diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index 38c96ca255..68f27b50e3 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -49,9 +49,11 @@ export class ClipboardDirective { @HostListener('mouseenter') showTooltip() { - const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); - const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; - componentRef.placeholder = this.placeholder; + if (this.placeholder) { + const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); + const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; + componentRef.placeholder = this.placeholder; + } } @HostListener('mouseleave') diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index ffb9d75a09..bac6b1c12d 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -36,7 +36,7 @@ import { Node } from '@alfresco/js-api'; template: ` <ng-container> <span *ngIf="copyContent; else defaultCell" - adf-clipboard + adf-clipboard="CLIPBOARD.CLICK_TO_COPY" [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'" [attr.aria-label]="value$ | async" [title]="tooltip" diff --git a/lib/core/datatable/components/datatable/json-cell.component.ts b/lib/core/datatable/components/datatable/json-cell.component.ts index 500a867e16..92c11e326f 100644 --- a/lib/core/datatable/components/datatable/json-cell.component.ts +++ b/lib/core/datatable/components/datatable/json-cell.component.ts @@ -27,9 +27,7 @@ import { DataTableCellComponent } from './datatable-cell.component'; <pre class="adf-datatable-json-cell" [adf-clipboard]="'CLIPBOARD.CLICK_TO_COPY'" - [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"> - {{ value$ | async | json }} - </pre> + [clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'">{{ value$ | async | json }}</pre> </span> </ng-container> <ng-template #defaultJsonTemplate> From 7caf50b2a69567cf6e4b0c95c40ccbc8585ee731 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 25 Apr 2019 19:57:58 +0100 Subject: [PATCH 170/208] fix typeahead validation (#4653) --- .../form/components/widgets/core/form-field-validator.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/core/form/components/widgets/core/form-field-validator.ts b/lib/core/form/components/widgets/core/form-field-validator.ts index 8795a03846..393fdff581 100644 --- a/lib/core/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/form/components/widgets/core/form-field-validator.ts @@ -15,7 +15,7 @@ * limitations under the License. */ - /* tslint:disable:component-selector */ +/* tslint:disable:component-selector */ import moment from 'moment-es6'; import { FormFieldTypes } from './form-field-types'; @@ -24,6 +24,7 @@ import { FormFieldModel } from './form-field.model'; export interface FormFieldValidator { isSupported(field: FormFieldModel): boolean; + validate(field: FormFieldModel): boolean; } @@ -500,8 +501,8 @@ export class FixedValueFieldValidator implements FormFieldValidator { return field.options.find((item) => item.name && item.name.toLocaleLowerCase() === field.value.toLocaleLowerCase()) ? true : false; } - hasValidId(field: FormFieldModel) { - return field.options[field.value - 1] ? true : false; + hasValidId(field: FormFieldModel): boolean { + return field.options.find((item) => item.id === field.value) ? true : false; } hasStringValue(field: FormFieldModel) { From 2ae5452fe268936e80a21dd7c958596d5b82d5a8 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Thu, 25 Apr 2019 23:23:42 +0200 Subject: [PATCH 171/208] [ADF-4437][ADF-4445] Fix docs about Task Form Cloud component (#4656) --- .../components/task-form-cloud.component.md | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/process-services-cloud/components/task-form-cloud.component.md b/docs/process-services-cloud/components/task-form-cloud.component.md index 457c972cc9..7fbe9449a6 100644 --- a/docs/process-services-cloud/components/task-form-cloud.component.md +++ b/docs/process-services-cloud/components/task-form-cloud.component.md @@ -11,11 +11,11 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl ## Contents -- [Basic Usage](#basic-usage) -- [Class members](#class-members) - - [Properties](#properties) - - [Events](#events) -- [See also](#see-also) +- [Basic Usage](#basic-usage) +- [Class members](#class-members) + - [Properties](#properties) + - [Events](#events) +- [See also](#see-also) ## Basic Usage @@ -35,13 +35,10 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl | ---- | ---- | ------------- | ----------- | | appName | `string` | | App id to fetch corresponding form and values. | | taskId | `string` | | Task id to fetch corresponding form and values. | -| showRefreshButton | `boolean` | false | Toggle rendering of the `Refresh` button. | | showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. | | showCancelButton | `boolean` | true | Toggle rendering of the `Cancel` outcome button. | | showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | -| showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. | -| readOnly | `boolean` | false | Toggle readonly state of the task. | - +| readOnly | `boolean` | false | Toggle readOnly state of the task. | ### Events @@ -55,9 +52,8 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl | cancelClick | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`string`>` | Emitted when the cancel button is clicked. | | error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when any error occurs. | - ## See also -- [Form component](./form-cloud.component.md) -- [Form field model](../../core/models/form-field.model.md) -- [Form cloud service](../services/form-cloud.service.md) +- [Form component](./form-cloud.component.md) +- [Form field model](../../core/models/form-field.model.md) +- [Form cloud service](../services/form-cloud.service.md) From 2ef34e2d89eb81c158269a3ef4bd4e16241c1213 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Thu, 25 Apr 2019 22:24:48 +0100 Subject: [PATCH 172/208] C307975 automated (#4655) --- .../metadata/metadata-properties.e2e.ts | 27 +++++++++++++++++++ e2e/pages/adf/metadataViewPage.ts | 13 +++++++++ 2 files changed, 40 insertions(+) diff --git a/e2e/content-services/metadata/metadata-properties.e2e.ts b/e2e/content-services/metadata/metadata-properties.e2e.ts index 6afc23d447..daeb72a688 100644 --- a/e2e/content-services/metadata/metadata-properties.e2e.ts +++ b/e2e/content-services/metadata/metadata-properties.e2e.ts @@ -186,4 +186,31 @@ describe('CardView Component - properties', () => { metadataViewPage.informationButtonIsNotDisplayed(); }); + + it('[C307975] Should be able to choose which aspect to show expanded in the info-drawer', () => { + viewerPage.viewFile(pngFileModel.name); + viewerPage.clickInfoButton(); + viewerPage.checkInfoSideBarIsDisplayed(); + metadataViewPage.clickOnPropertiesTab(); + + metadataViewPage.typeAspectName('EXIF'); + metadataViewPage.clickApplyAspect(); + + metadataViewPage.checkMetadataGroupIsExpand('EXIF'); + metadataViewPage.checkMetadataGroupIsNotExpand('properties'); + check(metadataViewPage.displayEmptySwitch); + + metadataViewPage.checkPropertyIsVisible('properties.exif:flash', 'boolean'); + metadataViewPage.checkPropertyIsVisible('properties.exif:model', 'textitem'); + + metadataViewPage.typeAspectName('nonexistent'); + metadataViewPage.clickApplyAspect(); + metadataViewPage.checkMetadataGroupIsNotPresent('nonexistent'); + + metadataViewPage.typeAspectName('Properties'); + metadataViewPage.clickApplyAspect(); + metadataViewPage.checkMetadataGroupIsPresent('properties'); + metadataViewPage.checkMetadataGroupIsExpand('properties'); + + }); }); diff --git a/e2e/pages/adf/metadataViewPage.ts b/e2e/pages/adf/metadataViewPage.ts index 0ab21906ba..d476660e87 100644 --- a/e2e/pages/adf/metadataViewPage.ts +++ b/e2e/pages/adf/metadataViewPage.ts @@ -44,6 +44,8 @@ export class MetadataViewPage { presetSwitch = element(by.id('adf-toggle-custom-preset')); defaultPropertiesSwitch = element(by.id('adf-metadata-default-properties')); closeButton = element(by.cssContainingText('button.mat-button span', 'Close')); + displayAspect = element(by.css(`input[placeholder='Display Aspect']`)); + applyAspect = element(by.cssContainingText(`button span.mat-button-wrapper`, 'Apply Aspect')); getTitle(): promise.Promise<string> { BrowserVisibility.waitUntilElementIsVisible(this.title); @@ -289,4 +291,15 @@ export class MetadataViewPage { BrowserVisibility.waitUntilElementIsVisible(this.closeButton); this.closeButton.click(); } + + typeAspectName(aspectName) { + BrowserVisibility.waitUntilElementIsVisible(this.displayAspect); + this.displayAspect.clear(); + this.displayAspect.sendKeys(aspectName); + } + + clickApplyAspect() { + BrowserVisibility.waitUntilElementIsVisible(this.applyAspect); + this.applyAspect.click(); + } } From 9297c63a212724cdcac55da4ffc19eaec8227091 Mon Sep 17 00:00:00 2001 From: Marouan Bentaleb <38426175+marouanbentaleb@users.noreply.github.com> Date: Fri, 26 Apr 2019 02:37:14 +0100 Subject: [PATCH 173/208] [ADF-4407] Automate test for user without permission redirection (#4612) --- e2e/core/auth-guard/auth-guard-sso.e2e.ts | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 e2e/core/auth-guard/auth-guard-sso.e2e.ts diff --git a/e2e/core/auth-guard/auth-guard-sso.e2e.ts b/e2e/core/auth-guard/auth-guard-sso.e2e.ts new file mode 100644 index 0000000000..1fc2dd6e2b --- /dev/null +++ b/e2e/core/auth-guard/auth-guard-sso.e2e.ts @@ -0,0 +1,36 @@ +/*! + * @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 { ErrorPage, LoginSSOPage, SettingsPage } from '@alfresco/adf-testing'; +import TestConfig = require('../../test.config'); +import { browser } from 'protractor'; + +describe('Auth Guard SSO', () => { + + const settingsPage = new SettingsPage(); + const loginSSOPage = new LoginSSOPage(); + const errorPage = new ErrorPage(); + + it('[C307058] Should be redirected to 403 when user doesn\'t have permissions', async () => { + settingsPage.setProviderEcmSso(TestConfig.adf.url, TestConfig.adf.hostSso, TestConfig.adf.hostIdentity, false, true, 'alfresco'); + loginSSOPage.clickOnSSOButton(); + await loginSSOPage.loginSSOIdentityService(TestConfig.adf.adminEmail, TestConfig.adf.adminPassword); + browser.get(TestConfig.adf.url + '/cloud/simple-app'); + expect(errorPage.getErrorCode()).toBe('403'); + }); + +}); From 669c64fb46eec47b221b66c1dab9374f06c0cee9 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Fri, 26 Apr 2019 14:37:30 +0200 Subject: [PATCH 174/208] [ADF-4411] Keep js-api dependecy in remove script (#4661) --- scripts/remove-alfresco-dependencies.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/remove-alfresco-dependencies.sh b/scripts/remove-alfresco-dependencies.sh index 470f880dc9..bf3bf31893 100755 --- a/scripts/remove-alfresco-dependencies.sh +++ b/scripts/remove-alfresco-dependencies.sh @@ -2,8 +2,8 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" echo "====== Removing Alfresco dependencies from package.json =====" -grep -wirn '@alfresco*' $DIR/../package.json - -sed -i '' '/@alfresco*/,// d' $DIR/../package.json +grep -wirn '@alfresco\/adf*' $DIR/../package.json +sed -i '' 's/"@alfresco\/adf-[^,]*,//' $DIR/../package.json +sed -i '' '/^[[:space:]]*$/d' $DIR/../package.json echo "====== Alfresco dependencies removed from package.json =====" From 934386fb16ba76b16e92b58707d67e821c4177da Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Fri, 26 Apr 2019 14:33:44 +0100 Subject: [PATCH 175/208] fix update script travis configuration --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dc21dba65e..b18e83f1ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -129,7 +129,7 @@ jobs: - stage: Update children projects dependency # Test Update activiti-modeling-app name: Update alfresco modeler activiti app if: tag =~ .*beta.* - script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n Activiti/activiti-modeling-app' + script: ./scripts/update-project.sh -gnu -t $GITHUB_TOKEN -n 'Activiti/activiti-modeling-app' - stage: Update children projects dependency # Test alfresco-admin-app name: Update alfresco admin app if: tag =~ .*beta.* From f24245aa238cd89c6e519871b728542cb4810564 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Fri, 26 Apr 2019 17:22:22 +0100 Subject: [PATCH 176/208] C307984 automated (#4657) --- .../datatable-dnd.component.html | 2 +- .../datatable/data-table-component.e2e.ts | 28 +++++++++++++++++++ e2e/pages/adf/demo-shell/dataTablePage.ts | 9 ++++++ e2e/pages/adf/navigationBarPage.ts | 8 ++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html index 1a5cc482f3..6342702eac 100644 --- a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html +++ b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html @@ -1,5 +1,5 @@ <h1>DataTable Drag and Drop Demo</h1> -<div +<div data-automation-id="datatable" (header-drop)="onDrop($event)" (cell-drop)="onDrop($event)"> <adf-datatable [data]="data"></adf-datatable> diff --git a/e2e/core/datatable/data-table-component.e2e.ts b/e2e/core/datatable/data-table-component.e2e.ts index 639af112f2..90933fe189 100644 --- a/e2e/core/datatable/data-table-component.e2e.ts +++ b/e2e/core/datatable/data-table-component.e2e.ts @@ -24,16 +24,25 @@ import TestConfig = require('../../test.config'); import { AlfrescoApiCompatibility as AlfrescoApi } from '@alfresco/js-api'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { NotificationPage } from '../../pages/adf/notificationPage'; +import { DropActions } from '../../actions/drop.actions'; +import resources = require('../../util/resources'); +import { FileModel } from '../../models/ACS/fileModel'; describe('Datatable component', () => { const dataTablePage = new DataTablePage('defaultTable'); const copyContentDataTablePage = new DataTablePage('copyClipboardDataTable'); + const dragAndDropDataTablePage = new DataTablePage(); const loginPage = new LoginPage(); const acsUser = new AcsUserModel(); const navigationBarPage = new NavigationBarPage(); const dataTableComponent = new DataTableComponentPage(); const notificationPage = new NotificationPage(); + const dragAndDrop = new DropActions(); + const pngFile = new FileModel({ + 'name': resources.Files.ADF_DOCUMENTS.PNG.file_name, + 'location': resources.Files.ADF_DOCUMENTS.PNG.file_location + }); beforeAll(async (done) => { this.alfrescoJsApi = new AlfrescoApi({ @@ -190,4 +199,23 @@ describe('Datatable component', () => { expect(copyContentDataTablePage.getClipboardInputText()).toContain(jsonValue); }); }); + + describe('Datatable component - Drag and Drop', () => { + + beforeAll(async (done) => { + navigationBarPage.navigateToDragAndDropDatatable(); + done(); + }); + + it('[C307984] Should trigger the event handling header-drop and cell-drop', () => { + const dragAndDropHeader = dragAndDropDataTablePage.getDropTargetIdColumnHeader(); + dragAndDrop.dropFile(dragAndDropHeader, pngFile.location); + notificationPage.checkNotifyContains('Dropped data on [ id ] header'); + notificationPage.checkNotificationSnackBarIsNotDisplayed(); + + const dragAndDropCell = dragAndDropDataTablePage.getDropTargetIdColumnCell(1); + dragAndDrop.dropFile(dragAndDropCell, pngFile.location); + notificationPage.checkNotifyContains('Dropped data on [ id ] cell'); + }); + }); }); diff --git a/e2e/pages/adf/demo-shell/dataTablePage.ts b/e2e/pages/adf/demo-shell/dataTablePage.ts index 2f9877b713..646f9192f2 100644 --- a/e2e/pages/adf/demo-shell/dataTablePage.ts +++ b/e2e/pages/adf/demo-shell/dataTablePage.ts @@ -45,6 +45,7 @@ export class DataTablePage { replaceRowsElement = element(by.xpath(`//span[contains(text(),'Replace rows')]/..`)); replaceColumnsElement = element(by.xpath(`//span[contains(text(),'Replace columns')]/..`)); createdOnColumn = element(by.css(`div[data-automation-id='auto_id_createdOn']`)); + idColumnHeader = element(by.css(`div[data-automation-id='auto_id_id']`)); pasteClipboardInput = element(by.css(`input[data-automation-id='paste clipboard input']`)); constructor(data?) { @@ -167,6 +168,14 @@ export class DataTablePage { return this.dataTable.mouseOverElement(this.dataTable.getCellByRowNumberAndColumnName(rowNumber - 1, this.columns.json)); } + getDropTargetIdColumnCell(rowNumber) { + return this.dataTable.getCellByRowNumberAndColumnName(rowNumber - 1, this.columns.id); + } + + getDropTargetIdColumnHeader() { + return this.idColumnHeader; + } + clickOnIdColumn(name) { return this.dataTable.clickColumn(this.columns.id, name); } diff --git a/e2e/pages/adf/navigationBarPage.ts b/e2e/pages/adf/navigationBarPage.ts index d90e02bf29..ddb66483d7 100644 --- a/e2e/pages/adf/navigationBarPage.ts +++ b/e2e/pages/adf/navigationBarPage.ts @@ -29,6 +29,7 @@ export class NavigationBarPage { dataTableButton = element(by.css('a[data-automation-id="Datatable"]')); dataTableNestedButton = element(by.css('button[data-automation-id="Datatable"]')); dataTableCopyContentButton = element(by.css('button[data-automation-id="Copy Content"]')); + dataTableDragAndDropButton = element(by.css('button[data-automation-id="Drag and Drop"]')); taskListButton = element(by.css("a[data-automation-id='Task List']")); configEditorButton = element(by.css('a[data-automation-id="Configuration Editor"]')); processServicesButton = element(by.css('a[data-automation-id="Process Services"]')); @@ -74,6 +75,13 @@ export class NavigationBarPage { this.dataTableCopyContentButton.click(); } + navigateToDragAndDropDatatable() { + BrowserVisibility.waitUntilElementIsVisible(this.dataTableButton); + this.dataTableButton.click(); + BrowserVisibility.waitUntilElementIsVisible(this.dataTableDragAndDropButton); + this.dataTableDragAndDropButton.click(); + } + clickContentServicesButton() { BrowserVisibility.waitUntilElementIsVisible(this.contentServicesButton); this.contentServicesButton.click(); From 8231a5a37e4793e47e99c7ef09589bc36906f6e7 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Fri, 26 Apr 2019 18:15:31 +0100 Subject: [PATCH 177/208] Improve recovery strategy Activiti 7 --- e2e/resources/activiti7/subProcessApp.zip | Bin 2815 -> 2852 bytes e2e/util/resources.js | 4 +- scripts/check-activiti-env.js | 121 ++++++++++++++++++---- 3 files changed, 101 insertions(+), 24 deletions(-) diff --git a/e2e/resources/activiti7/subProcessApp.zip b/e2e/resources/activiti7/subProcessApp.zip index 6bf3c95510f26e636584d1fab5e2af858dae28e9..938393d4928612cca03618ac71f065f5c773fefa 100644 GIT binary patch delta 1952 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 A+yDRo literal 2815 zcmWIWW@Zs#;Nak3`06pyj{ymAF$gmh6y+zU78j=$>z5YrGcbPqF3W}xVrB^NX6FFu zV1jB3z-gEggEo?30T5#Y5{pvvO7xNna`TJ~^eS?5N(<B(7`gT}R3a?FrF3i9>Ab}T zB6q)QPx#*A&QZBy%Pg~%CPBA5)nqfvPTb(D;A%Ulrc!VJOpvK%%gdy)8~eV`dtCgE zHShiRz!h&iPGz2vN$4qAAkdcNGxL2ze7^rHo;&yN-l_6Da)wnc`qYXE3u7i$_UM0` zW2GRV6qyk<@A={yo37w^<I=kq>h{~@2RJCL2s*}^($QeGdd;<y-OBrYo^U$eI{fQt z=rn_p+N7vkr~9A2+BvuL<<^y_-ygT>(R;2leQnQiwa3g;{MwEzxWOpn=IIgQvvB?) z4h^Pdc7p2-lx!M1OpbO*_hhX37&NO$Q_(UuMEbm8)1ohrxL;`;owu_8n@sa=Y1fr+ zy)H=zp7XByy4lLz__Xrvm0jB}ug!|Q5wLfqZ7Am@-sGfN7p~bZFz~$1_*yHSH~3J? z9@Y4_oTpg6I8|y~>Y0+jE7KP!cJjoe{fkP^E&0DP;_Z{nlWCWAVi)UOYB@IZL-NhK za_LXzllOYeJ7iJLE4W8qV(--|N70UJ?k}6RbA^6jp4xcmv5xB#^_$;*Tn(GXo<Cv# z?kWeLZ|U4s<t_$1`xPC_Lu9;W<P|J^srET5a;m!|{}iR}2caHZFa7L%c{q-z^o8c! z_SkytNZ9j;?MouB<?NGveR*d3*Qtw(3KpNAlHIf}sCN1?#m{zOdu!kKDYQJC{B(8I zL#d5h<tP8~`V`9)`|0>y<#XXa>tB`myuWqT=x<L|>L0;<+tx_h_=q31(OYfq*m*a~ zocDfTZ2N?XYMWw2d&6DklpYHez9YDu?Iw%CN{2gXFSl9UeZ$Ddw^FC`;v>a#64UN8 zut&7{SX&&}@?^U5@(30_iQ5jG9AB9OZL@i$*ZQY-Jm>oT<k5^>Grnc=@fOe4i+%E8 z!ijyNs)^ZQg7eNqond?Q%(-x`w1|tn*sqPIQtJ}W9N&GwYQN+1k9u6SPm<3_EqrSJ zV96Js|C=tUFZwHHuU=VL_uJ*|;sgKpDzB3Kw?_Gu=l(ZeQZBswY*D?TSg*t-eYebu z%i4>7H%+JyzjgEd)w^fyL0Qh|d!YOeV4j=B$pFlPxbm+$g8{BAr<+<)lA2eXnV(mz zmsOmfS6ZOMz&QJu<U}0#4qd(MX+ypS1s;Y2`%AWQN{Bo)XF6IU(2;6j_~-6}io<&k z2+Ca9%_4NrHs@IICW*<u89rBDyv>@}bg63Q^W;!DwFS!q#q=T%>{SlmC4D(y{sXJ5 zr#1gx{bdIEZBtg({BU4#k_5!K{ievEh3PlvjLe)Al+r|vfpOaU=d~EVLRUF87*?3* zyg#^SmYT+rAa6G*&6h4-+NI)_+qkD4P<SKq?EP_zBduq)yn6G_^m*ZV)3|%(sf_m` zl`B<+UhI}*@tM$7G*R`#)1U3e?cZ0=e!5Z5RUr7=G1hP?t;T1ZlI4@s4Z>IT31;2C zmg~Gd%SfbRUVq&7*|sMmJ7x8j9BMMK*wAyUC4A~k#Z$8czihZ|m&tkmb6zt?ZvE2N zXJ>f+EMNKZJa_-3^Ol)bNj6c(#Px*T-YZt>_+IgK-C(r(Pk+Gzdv2TUlSP>Pgf$8y z#m_91N$1s54A^mUM%5wJ$);*&y1w5osBArVZ&~YVX@<7ft7dl@X!bq{u-<NWOffp3 z{ao6SPA9Wsu`Atk9><!*?`gev_m9L&#V5OxpDg*X@j~7z%a^N#Z`n2O-h3|k9Cy~9 zHPUNOtW0s5`DeB2uj?-**4KBst-b%%-1x!0ZS3+&lbL*zZX`@O{`b(O&t*K7SF*pI zNIUS3OJ|1bEWgJN{So48=AT#F{AcAMyW?LYA12&Bobl{|SFX@=r4_20o${+DFA#dt zlfKifZS%j2Tj#9$bE$;0=g)%mb?OEkHnED<BD>~gb#$-$T=%A6m*L+z7vtYoeq{$G zo{)?6xknfo7`RyQB_1^feH@7gJ)M^pXfrTgRN3c(Jq4jFUmbSJCva1cmc}W6KV7|R zrlvkVCVpFeF8Uf8dtWm(^fSG@)yL4_qOXzp#tlBkW(M0mi~?7&f@@Jh?nf@>z$9;q zH`z-uC^G;n#H`fhlJLxujNsBFAP-bQLvyh_1Ec*4m6f=a0A1*P#y50R5SPZO^IpDs zoac2;a_IRoeVP>9-95Er%Bi64F5}Oi8?<;D_Ds3*=*glpO+p<VLAqc!YO9_Jv;?}( z9_&U&CJ_eIh6Ah>0BSg(0z~j(X+{KiqZ)-=x`CPv2;d83B8-B1osvcby4A>q52*M= zfCJ1ptwv7;q!y;=jzCVtpmGiY<^Yp5hX2vaveE)#OFeXpk<%b3k08KJHe42CdY+^l mgYE?6BnC?C2r!u)n58L6`T^doKwmI0umRyFU{W;)w_E`j^F=EF diff --git a/e2e/util/resources.js b/e2e/util/resources.js index b831d960b8..f5f0da2254 100644 --- a/e2e/util/resources.js +++ b/e2e/util/resources.js @@ -527,7 +527,7 @@ exports.ACTIVITI7_APPS = { } }, SUB_PROCESS_APP: { - name: "subprocess-app", - file_location: "/resources/activiti7/subProcessApp.zip", + name: "subprocessapp", + file_location: "/resources/activiti7/subprocessapp.zip", } }; diff --git a/scripts/check-activiti-env.js b/scripts/check-activiti-env.js index e74b1af6e3..2b763fb99e 100755 --- a/scripts/check-activiti-env.js +++ b/scripts/check-activiti-env.js @@ -63,7 +63,7 @@ async function main() { if (notRunningSecondAttempt && notRunningSecondAttempt.length > 0) { let notRunningAppAfterWaitSecondAttempt = await waitPossibleStaleApps(this.alfrescoJsApi, notRunningSecondAttempt); - if (notRunningAppAfterWaitSecondAttempt && notRunningAppAfterWaitSecondAttempt.legnth > 0) { + if (notRunningAppAfterWaitSecondAttempt && notRunningAppAfterWaitSecondAttempt.length > 0) { console.log(`Not possible to recover the following apps in the environment`); notRunningAppAfterWaitSecondAttempt.forEach((currentApp) => { @@ -72,8 +72,8 @@ async function main() { process.exit(1); } - }else{ - console.log(`Activiti 7 all ok :)`); + } else { + console.log(`Activiti 7 all ok :)`); } } else { console.log(`Activiti 7 all ok :)`); @@ -89,7 +89,6 @@ async function deleteStaleApps(alfrescoJsApi, notRunningAppAfterWait) { } async function waitPossibleStaleApps(alfrescoJsApi, notRunning) { - do { console.log(`Wait stale app ${TIMEOUT}`); @@ -125,6 +124,7 @@ async function getNotRunningApps(alfrescoJsApi) { Object.keys(ACTIVITI7_APPS).forEach((key) => { let isNotRunning = allStatusApps.find((currentApp) => { + //console.log(currentApp.entry.name + ' ' +currentApp.entry.status); return ACTIVITI7_APPS[key].name === currentApp.entry.name && currentApp.entry.status !== 'Running'; }); @@ -146,7 +146,6 @@ async function getNotRunningApps(alfrescoJsApi) { } async function deployAbsentApps(alfrescoJsApi) { - let deployedApps = await getDeployedApplicationsByStatus(alfrescoJsApi, ''); Object.keys(ACTIVITI7_APPS).forEach((key) => { @@ -178,37 +177,44 @@ async function checkIfAppIsReleased(apiService, absentApps) { if (!app) { - let uploadedApp = await importApp(apiService, currentAbsentApp); + console.log('Missing project, create the project for ' + currentAbsentApp.name); + + let uploadedApp = await importProjectApp(apiService, currentAbsentApp); + + console.log('Project uploaded ' + currentAbsentApp.name); + if (uploadedApp) { await releaseApp(apiService, uploadedApp); - await deployApp(apiService, uploadedApp); + await deployApp(apiService, uploadedApp, currentAbsentApp.name); } } else { - let appRelease = undefined; - let appReleaseList = await getReleaseAppyProjectId(apiService, app.entry.id); + console.log('Project for ' + currentAbsentApp.name + 'present'); - if (!appReleaseList) { + let appRelease = undefined; + let appReleaseList = await getReleaseAppProjectId(apiService, app.entry.id); + + if (appReleaseList.list.entries.length === 0) { + console.log('1 '); appRelease = await releaseApp(apiService, app); } else { - appRelease = appReleaseList.list.entries.find((currentRelease) => { return currentRelease.entry.version === 'latest'; }); } - console.log('App to deploy ' + appRelease.entry.projectName + ' app release id ' + JSON.stringify(appRelease.entry.id)); + console.log('App to deploy app release id ' + JSON.stringify(appRelease)); - await deployApp(apiService, appRelease); + await deployApp(apiService, appRelease, currentAbsentApp.name); } } } -async function deployApp(apiService, app) { +async function deployApp(apiService, app, name) { const url = `${config.hostBpm}/alfresco-deployment-service/v1/applications`; const pathParams = {}; const bodyParam = { - "name": app.entry.projectName, + "name": name, "releaseId": app.entry.id, "version": app.entry.name, "security": [{"role": "APS_ADMIN", "groups": [], "users": ["admin.adf"]}, { @@ -225,12 +231,12 @@ async function deployApp(apiService, app) { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to deploy the project ${app.entry.projectName} status : ${JSON.stringify(error.status)} ${JSON.stringify(error)}`); + console.log(`Not possible to deploy the project ${app.entry.projectName} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`); process.exit(1); } } -async function importApp(apiService, app) { +async function importProjectApp(apiService, app) { const pathFile = path.join('./e2e/' + app.file_location); const file = fs.createReadStream(pathFile); @@ -241,18 +247,22 @@ async function importApp(apiService, app) { contentTypes = ['multipart/form-data'], accepts = ['application/json']; try { + console.log('import app ' + app.file_location); return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { if (error.status !== 409) { - console.log(`Not possible to upload the project ${app.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.text)}`); + console.log(`Not possible to upload the project ${app.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`); process.exit(1); + } else { + console.log(`Not possible to upload the project because inconsistency CS - Modelling try to delete manually the node`); + await deleteSiteByName(app.name); + await importProjectApp(apiService, app); } } - } -async function getReleaseAppyProjectId(apiService, projectId) { +async function getReleaseAppProjectId(apiService, projectId) { const url = `${config.hostBpm}/alfresco-modeling-service/v1/projects/${projectId}/releases`; const pathParams = {}, queryParams = {}, @@ -281,7 +291,7 @@ async function releaseApp(apiService, app) { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to release the project ${app.entry.name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.text)}`); + console.log(`Not possible to release the project ${app.entry.name} status : $ ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`); process.exit(1); } @@ -301,7 +311,7 @@ async function getDeployedApplicationsByStatus(apiService, status) { return data.list.entries; } catch (error) { - console.log(`Not possible get the applicationsfrom alfresco-deployment-service ${JSON.stringify(error)} `); + console.log(`Not possible get the applications from alfresco-deployment-service ${JSON.stringify(error)} `); process.exit(1); } @@ -353,4 +363,71 @@ function sleep(delay) { while (new Date().getTime() < start + delay) ; } +async function deleteChildrenNodeByName(alfrescoJsApi, nameNodeToDelete, nodeId) { + let childrenNodes = await alfrescoJsApi.core.nodesApi.getNodeChildren(nodeId); + + let childrenToDelete = childrenNodes.list.entries.find((currentNode) => { + console.log(currentNode.entry.name); + return currentNode.entry.name === nameNodeToDelete; + }); + + console.log('childrenToDelete ' + childrenToDelete); + + if (childrenToDelete) { + await alfrescoJsApi.core.nodesApi.deleteNode(childrenToDelete.entry.id); + } + + +} + +async function deleteSiteByName(name) { + + console.log(`====== Delete Site ${name} ${program.host} ======`); + + let alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility({ + provider: 'ECM', + hostEcm: `http://${program.host}` + }); + + await alfrescoJsApi.login(program.username, program.password); + + let listSites = []; + + try { + listSites = await alfrescoJsApi.core.sitesApi.getSites(); + } catch (error) { + console.log('error get list sites' + JSON.stringify(error)); + process.exit(1); + } + + let apsModelingNodeId; + let apsReleaseNodeId; + + if (listSites && listSites.list.entries.length > 0) { + for (let i = 0; i < listSites.list.entries.length; i++) { + if (listSites.list.entries[i].entry.id === name) { + try { + await alfrescoJsApi.core.sitesApi.deleteSite(listSites.list.entries[i].entry.id, {options: {permanent: true}}); + } catch (error) { + console.log('error' + JSON.stringify(error)); + } + } + + if (listSites.list.entries[i].entry.id === 'ApsModeling') { + apsModelingNodeId = listSites.list.entries[i].entry.guid; + } + + if (listSites.list.entries[i].entry.id === 'ApsRelease') { + apsReleaseNodeId = listSites.list.entries[i].entry.guid; + } + } + } + + console.log(`====== Delete Folder in apsModeling`); + await deleteChildrenNodeByName(alfrescoJsApi, name, apsModelingNodeId); + + console.log(`====== Delete Folder in apsRelease`); + await deleteChildrenNodeByName(alfrescoJsApi, name, apsReleaseNodeId); +} + main(); From 54a2b1428562842edae75b71fb1650ae5bb6229b Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Mon, 29 Apr 2019 11:20:09 +0100 Subject: [PATCH 178/208] [ADF-4339] Fix documentList and ContentServices UI for IE11 (#4660) * [ADF-4339] Fix documentList and ContentServices UI for IE11 * [ADF-4339] Fixed syntax mistake --- ...content-node-selector-panel.component.scss | 5 ++++ .../upload-drag-area.component.scss | 6 +++- .../datatable/datatable.component.html | 8 ++--- .../datatable/datatable.component.scss | 30 +++++++++++++++++++ .../layout-container.component.html | 2 +- .../layout-container.component.scss | 4 +++ 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/content-services/content-node-selector/content-node-selector-panel.component.scss b/lib/content-services/content-node-selector/content-node-selector-panel.component.scss index 8b5a8a9f83..f900d3adbd 100644 --- a/lib/content-services/content-node-selector/content-node-selector-panel.component.scss +++ b/lib/content-services/content-node-selector/content-node-selector-panel.component.scss @@ -121,6 +121,11 @@ .adf-datatable-body .adf-datatable-row { min-height: 40px; + @media screen and (-ms-high-contrast: active), + screen and (-ms-high-contrast: none) { + padding-top: 15px; + } + &:first-child { .adf-datatable-cell { border-top: none; diff --git a/lib/content-services/upload/components/upload-drag-area.component.scss b/lib/content-services/upload/components/upload-drag-area.component.scss index 2db0052669..b498c0a741 100644 --- a/lib/content-services/upload/components/upload-drag-area.component.scss +++ b/lib/content-services/upload/components/upload-drag-area.component.scss @@ -15,7 +15,11 @@ $adf-upload-dragging-level1-border: 1px dashed #2196f3 !default; @include flex-column; .adf-upload-border { - @include flex-column; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + min-height: 0; vertical-align: unset; text-align: unset; width: 100%; diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 71b6ccd003..e005de1475 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -110,7 +110,7 @@ *ngIf="row.isSelected && !multiselect; else no_selected_row" svgIcon="selected"> </mat-icon> <ng-template #no_selected_row> - <img + <img class="adf-datatable-center-img-ie" [attr.aria-label]="data.getValue(row, col) | fileType" alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}" src="{{ data.getValue(row, col) }}" @@ -124,7 +124,7 @@ </div> <div *ngSwitchCase="'date'" class="adf-cell-value" [attr.data-automation-id]="'date_' + (data.getValue(row, col) | date: 'medium') "> - <adf-date-cell + <adf-date-cell class = "adf-datatable-center-date-column-ie" [data]="data" [column]="col" [row]="row" @@ -142,7 +142,7 @@ </div> <div *ngSwitchCase="'fileSize'" class="adf-cell-value" [attr.data-automation-id]="'fileSize_' + data.getValue(row, col)"> - <adf-filesize-cell + <adf-filesize-cell class="adf-datatable-center-size-column-ie" [data]="data" [column]="col" [row]="row" @@ -185,7 +185,7 @@ <!-- Actions (right) --> <div *ngIf="actions && actionsPosition === 'right'" role="gridcell" - class="adf-datatable-cell adf-datatable__actions-cell"> + class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie"> <button mat-icon-button [matMenuTriggerFor]="menu" [title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate" [attr.id]="'action_menu_right_' + idx" diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index 5a18be2796..b24b0b39c7 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -169,6 +169,31 @@ background-color: mat-color($background, card); border: $data-table-dividers; + @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) { + .adf-datatable-center-size-column-ie { + padding-top: 17px; + } + + .adf-datatable-center-actions-column-ie { + padding-top: 7px !important; + } + .adf-datatable-center-date-column-ie { + position: relative !important; + + .adf-datatable-cell-value { + width: 100%; + } + } + + .adf-datatable-center-img-ie { + padding:0; + min-width: 0; + width: 24px; + height: 56px; + } + + } + .adf-datatable-header { display: flex; flex-direction: column; @@ -341,6 +366,11 @@ word-break: break-word; padding: 10px; display: block; + + @media screen and (-ms-high-contrast: active), + screen and (-ms-high-contrast: none) { + padding: 17px 10px 10px; + } } &:focus { diff --git a/lib/core/layout/components/layout-container/layout-container.component.html b/lib/core/layout/components/layout-container/layout-container.component.html index 19aaf18447..f6bb4c6dc3 100644 --- a/lib/core/layout/components/layout-container/layout-container.component.html +++ b/lib/core/layout/components/layout-container/layout-container.component.html @@ -10,7 +10,7 @@ </mat-sidenav> <div> - <div class="adf-rtl-container-alignment" [@contentAnimationLeft]="getContentAnimationStateLeft()" [@contentAnimationRight]="getContentAnimationStateRight()"> + <div class="adf-rtl-container-alignment adf-container-full-width" [@contentAnimationLeft]="getContentAnimationStateLeft()" [@contentAnimationRight]="getContentAnimationStateRight()"> <ng-content select="[app-layout-content]"></ng-content> </div> </div> diff --git a/lib/core/layout/components/layout-container/layout-container.component.scss b/lib/core/layout/components/layout-container/layout-container.component.scss index c3e4324621..614ee0b5a2 100644 --- a/lib/core/layout/components/layout-container/layout-container.component.scss +++ b/lib/core/layout/components/layout-container/layout-container.component.scss @@ -13,6 +13,10 @@ margin-left: 10px!important; } + .adf-container-full-width { + width: 100%; + } + .adf-sidenav--hidden { visibility: hidden !important; width: 0 !important; From 1658eb97e357c2df2bc1994597aaaf6c4a87f6d7 Mon Sep 17 00:00:00 2001 From: arditdomi <32884230+arditdomi@users.noreply.github.com> Date: Mon, 29 Apr 2019 14:54:17 +0100 Subject: [PATCH 179/208] [ADF-4434] Remove unnecessary icon in custom empty content template (#4665) * [ADF-4339] Fix documentList and ContentServices UI for IE11 * [ADF-4339] Fixed syntax mistake * [ADF-4434] Remove unnecessary icon in custom empty content template --- .../app/components/template-list/template-demo.component.html | 1 - 1 file changed, 1 deletion(-) diff --git a/demo-shell/src/app/components/template-list/template-demo.component.html b/demo-shell/src/app/components/template-list/template-demo.component.html index 83f8050c41..901123610f 100644 --- a/demo-shell/src/app/components/template-list/template-demo.component.html +++ b/demo-shell/src/app/components/template-list/template-demo.component.html @@ -31,6 +31,5 @@ <adf-document-list #customEmptyDocumentList> <adf-custom-empty-content-template> <div>This is a custom no content template</div> - <mat-icon>cancel_presentation</mat-icon> </adf-custom-empty-content-template> </adf-document-list> From 2bc2f095258f8c84da1b264cbc02a00032c0f55e Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Mon, 29 Apr 2019 14:55:45 +0100 Subject: [PATCH 180/208] [ADF-4445] Add showRefreshButton to TaskFormCloud component doc (#4666) --- .../components/cloud/task-details-cloud-demo.component.html | 4 ++-- .../components/task-form-cloud.component.md | 6 +++--- .../components/process-list-cloud.component.scss | 2 +- lib/process-services-cloud/src/lib/styles/_index.scss | 6 +++--- .../start-task/components/start-task-cloud.component.scss | 2 +- .../task-form/components/task-form-cloud.component.scss | 2 +- .../task/task-form/components/task-form-cloud.component.ts | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html index bd9b9593fb..ff921d6858 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html @@ -3,7 +3,7 @@ <div fxLayout="column" fxFill fxLayoutGap="2px"> <div fxLayout="row" fxFill> <div fxLayout="column" fxFlex="80%"> - <adf-task-form-cloud + <adf-cloud-task-form [appName]="appName" [taskId]="taskId" (cancelClick)="goBack()" @@ -11,7 +11,7 @@ (taskCompleted)="onTaskCompleted()" (taskUnclaimed)="onUnclaimTask()" (formSaved)="onFormSaved()"> - </adf-task-form-cloud> + </adf-cloud-task-form> </div> <adf-cloud-task-header fxFlex [appName]="appName" diff --git a/docs/process-services-cloud/components/task-form-cloud.component.md b/docs/process-services-cloud/components/task-form-cloud.component.md index 7fbe9449a6..748b0837d1 100644 --- a/docs/process-services-cloud/components/task-form-cloud.component.md +++ b/docs/process-services-cloud/components/task-form-cloud.component.md @@ -20,13 +20,12 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl ## Basic Usage ```html -<adf-task-form-cloud +<adf-cloud-task-form [appName]="appName" [taskId]="taskId"> -</adf-task-form-cloud> +</adf-cloud-task-form> ``` - ## Class members ### Properties @@ -35,6 +34,7 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl | ---- | ---- | ------------- | ----------- | | appName | `string` | | App id to fetch corresponding form and values. | | taskId | `string` | | Task id to fetch corresponding form and values. | +| showRefreshButton | `boolean` | false | Toggle rendering of the `Refresh` button. | | showValidationIcon | `boolean` | true | Toggle rendering of the `Validation` icon. | | showCancelButton | `boolean` | true | Toggle rendering of the `Cancel` outcome button. | | showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | diff --git a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.scss b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.scss index 20ec263d60..7a41730a76 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.scss @@ -1,4 +1,4 @@ -@mixin adf-process-filters-cloud-theme($theme) { +@mixin adf-cloud-process-filters-theme($theme) { .adf { diff --git a/lib/process-services-cloud/src/lib/styles/_index.scss b/lib/process-services-cloud/src/lib/styles/_index.scss index dc08214bf3..ff3368aaaf 100644 --- a/lib/process-services-cloud/src/lib/styles/_index.scss +++ b/lib/process-services-cloud/src/lib/styles/_index.scss @@ -16,9 +16,9 @@ @include adf-cloud-task-filters-theme($theme); @include adf-cloud-edit-task-filters-theme($theme); @include adf-cloud-edit-process-filter-theme($theme); - @include adf-process-filters-cloud-theme($theme); - @include adf-start-task-cloud-theme($theme); + @include adf-cloud-process-filters-theme($theme); + @include adf-cloud-start-task-theme($theme); @include adf-cloud-people-theme($theme); @include adf-cloud-group-theme($theme); - @include adf-task-form-cloud-theme($theme); + @include adf-cloud-task-form-theme($theme); } diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.scss b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.scss index 4e78c28b34..5c02cf2235 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.scss @@ -1,4 +1,4 @@ -@mixin adf-start-task-cloud-theme($theme) { +@mixin adf-cloud-start-task-theme($theme) { $primary: map-get($theme, primary); $accent: map-get($theme, accent); $warn: map-get($theme, warn); diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.scss b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.scss index 11e52617b9..b54b91bfe5 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.scss @@ -1,4 +1,4 @@ -@mixin adf-task-form-cloud-theme($theme) { +@mixin adf-cloud-task-form-theme($theme) { $config: mat-typography-config(); diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index c0d34b2f5e..8a5f5b9568 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -25,7 +25,7 @@ import { TaskCloudService } from '../../services/task-cloud.service'; import { IdentityUserService, FormOutcomeModel } from '@alfresco/adf-core'; @Component({ - selector: 'adf-task-form-cloud', + selector: 'adf-cloud-task-form', templateUrl: './task-form-cloud.component.html', styleUrls: ['./task-form-cloud.component.scss'] }) From 5f3d665ab5c17aa402628fb657b94b1be88dacfc Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eugenio.romano@alfresco.com> Date: Mon, 29 Apr 2019 17:58:30 +0100 Subject: [PATCH 181/208] improve check activiti log --- scripts/check-activiti-env.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/scripts/check-activiti-env.js b/scripts/check-activiti-env.js index 2b763fb99e..962b47dc23 100755 --- a/scripts/check-activiti-env.js +++ b/scripts/check-activiti-env.js @@ -93,7 +93,7 @@ async function waitPossibleStaleApps(alfrescoJsApi, notRunning) { console.log(`Wait stale app ${TIMEOUT}`); notRunning.forEach((currentApp) => { - console.log(`${currentApp.entry.name }`); + console.log(`${currentApp.entry.name } ${currentApp.entry.status}`); }); @@ -188,13 +188,12 @@ async function checkIfAppIsReleased(apiService, absentApps) { await deployApp(apiService, uploadedApp, currentAbsentApp.name); } } else { - console.log('Project for ' + currentAbsentApp.name + 'present'); + console.log('Project for ' + currentAbsentApp.name + ' present'); let appRelease = undefined; let appReleaseList = await getReleaseAppProjectId(apiService, app.entry.id); if (appReleaseList.list.entries.length === 0) { - console.log('1 '); appRelease = await releaseApp(apiService, app); } else { appRelease = appReleaseList.list.entries.find((currentRelease) => { @@ -202,7 +201,7 @@ async function checkIfAppIsReleased(apiService, absentApps) { }); } - console.log('App to deploy app release id ' + JSON.stringify(appRelease)); + console.log('App to deploy app release id ' + app.entry.id); await deployApp(apiService, appRelease, currentAbsentApp.name); } @@ -231,7 +230,8 @@ async function deployApp(apiService, app, name) { return await apiService.oauth2Auth.callCustomApi(url, 'POST', pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts); } catch (error) { - console.log(`Not possible to deploy the project ${app.entry.projectName} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`); + console.log(`Not possible to deploy the project ${name} status : ${JSON.stringify(error.status)} ${JSON.stringify(error.response.text)}`); + await deleteSiteByName(name); process.exit(1); } } @@ -367,11 +367,10 @@ async function deleteChildrenNodeByName(alfrescoJsApi, nameNodeToDelete, nodeId) let childrenNodes = await alfrescoJsApi.core.nodesApi.getNodeChildren(nodeId); let childrenToDelete = childrenNodes.list.entries.find((currentNode) => { - console.log(currentNode.entry.name); return currentNode.entry.name === nameNodeToDelete; }); - console.log('childrenToDelete ' + childrenToDelete); + console.log('childrenToDelete ' + childrenToDelete.entry.name); if (childrenToDelete) { await alfrescoJsApi.core.nodesApi.deleteNode(childrenToDelete.entry.id); @@ -389,7 +388,7 @@ async function deleteSiteByName(name) { hostEcm: `http://${program.host}` }); - await alfrescoJsApi.login(program.username, program.password); + await this.alfrescoJsApi.login(program.username, program.password); let listSites = []; From 860529058cedabb0cd3f2da32e89fd505ef74a31 Mon Sep 17 00:00:00 2001 From: Silviu Popa <silviucpopa@gmail.com> Date: Tue, 30 Apr 2019 12:13:10 +0300 Subject: [PATCH 182/208] [ADF-4409] DemoShell - ADF compatibility with Activiti 7 (#4646) * [ADF-4409] PorcessServicesCloud - add community page * [ADF-4409] - add process and task details page * [ADF-4409] fix lint and reset package-lock * [ADF-4409] - PR changes * [ADF-4409] - PR changes * [ADF-4409] - fix start task/process redirection * [ADF-4409] - fix unit tests --- demo-shell/resources/i18n/en.json | 3 +- demo-shell/src/app/app.module.ts | 18 ++- demo-shell/src/app/app.routes.ts | 37 +++++ .../app-layout/app-layout.component.ts | 1 + .../community/community-cloud.component.html | 36 +++++ .../community/community-cloud.component.ts | 68 +++++++++ .../community-filters.component.html | 31 ++++ .../community/community-filters.component.ts | 94 ++++++++++++ ...unity-process-details-cloud.component.html | 24 ++++ ...unity-process-details-cloud.component.scss | 14 ++ ...mmunity-process-details-cloud.component.ts | 49 +++++++ .../community-processes-cloud.component.html | 44 ++++++ .../community-processes-cloud.component.ts | 134 ++++++++++++++++++ ...mmunity-start-process-cloud.component.html | 7 + ...community-start-process-cloud.component.ts | 56 ++++++++ .../community-start-task-cloud.component.html | 5 + .../community-start-task-cloud.component.ts | 49 +++++++ .../community-task-cloud.component.html | 48 +++++++ .../community-task-cloud.component.ts | 131 +++++++++++++++++ ...ommunity-task-details-cloud.component.html | 21 +++ ...ommunity-task-details-cloud.component.scss | 20 +++ .../community-task-details-cloud.component.ts | 75 ++++++++++ .../src/lib/process-services-cloud.module.ts | 4 +- .../edit-process-filter-cloud.component.ts | 4 +- .../process-header-cloud.component.ts | 2 +- .../services/process-header-cloud.service.ts | 9 +- .../process-list-cloud.component.ts | 4 +- .../services/process-list-cloud.service.ts | 10 +- .../start-process-cloud.component.ts | 2 +- .../services/start-process-cloud.service.ts | 14 +- .../src/lib/services/base-cloud.service.ts | 35 +++++ .../lib/task/services/task-cloud.service.ts | 21 ++- .../people-cloud.component.spec.ts | 53 +++---- .../services/start-task-cloud.service.ts | 8 +- .../edit-task-filter-cloud.component.ts | 4 +- .../services/task-filter-cloud.service.ts | 1 - .../components/task-header-cloud.component.ts | 4 +- .../components/task-list-cloud.component.ts | 2 +- .../services/task-list-cloud.service.ts | 10 +- 39 files changed, 1074 insertions(+), 78 deletions(-) create mode 100644 demo-shell/src/app/components/cloud/community/community-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-cloud.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-filters.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-filters.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.scss create mode 100644 demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-processes-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-task-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts create mode 100644 demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html create mode 100644 demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss create mode 100644 demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts create mode 100644 lib/process-services-cloud/src/lib/services/base-cloud.service.ts diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index bb329b5568..ae7b463f39 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -95,7 +95,8 @@ "PEOPLE_GROUPS_CLOUD": "People/Group Cloud", "PEOPLE_CLOUD": "People Cloud Component", "GROUPS_CLOUD": "Groups Cloud Component", - "CONFIRM-DIALOG": "Confirmation Dialog" + "CONFIRM-DIALOG": "Confirmation Dialog", + "COMMUNITY": "Community" }, "TRASHCAN": { "ACTIONS": { diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index 60b2d6e54e..8ccd1eb82f 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -84,6 +84,14 @@ import { CloudSettingsComponent } from './components/cloud/cloud-settings.compon import { NestedMenuPositionDirective } from './components/cloud/directives/nested-menu-position.directive'; import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component'; import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component'; +import { CommunityCloudComponent } from './components/cloud/community/community-cloud.component'; +import { CommunityTasksCloudDemoComponent } from './components/cloud/community/community-task-cloud.component'; +import { CommunityCloudFiltersDemoComponent } from './components/cloud/community/community-filters.component'; +import { CommunityStartProcessCloudDemoComponent } from './components/cloud/community/community-start-process-cloud.component'; +import { CommunityStartTaskCloudDemoComponent } from './components/cloud/community/community-start-task-cloud.component'; +import { CommunityProcessDetailsCloudDemoComponent } from './components/cloud/community/community-process-details-cloud.component'; +import { CommunityProcessesCloudDemoComponent } from './components/cloud/community/community-processes-cloud.component'; +import { CommunityTaskDetailsCloudDemoComponent } from './components/cloud/community/community-task-details-cloud.component'; @NgModule({ imports: [ @@ -152,7 +160,15 @@ import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/ NestedMenuPositionDirective, ConfirmDialogExampleComponent, FormCloudDemoComponent, - ConfirmDialogExampleComponent + ConfirmDialogExampleComponent, + CommunityCloudComponent, + CommunityTasksCloudDemoComponent, + CommunityCloudFiltersDemoComponent, + CommunityProcessesCloudDemoComponent, + CommunityStartProcessCloudDemoComponent, + CommunityStartTaskCloudDemoComponent, + CommunityProcessDetailsCloudDemoComponent, + CommunityTaskDetailsCloudDemoComponent ], providers: [ { diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 10441b9c7c..175388d1a8 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -52,6 +52,13 @@ import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-det import { TemplateDemoComponent } from './components/template-list/template-demo.component'; import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component'; import { ConfirmDialogExampleComponent } from './components/confirm-dialog/confirm-dialog-example.component'; +import { CommunityTasksCloudDemoComponent } from './components/cloud/community/community-task-cloud.component'; +import { CommunityCloudComponent } from './components/cloud/community/community-cloud.component'; +import { CommunityStartProcessCloudDemoComponent } from './components/cloud/community/community-start-process-cloud.component'; +import { CommunityStartTaskCloudDemoComponent } from './components/cloud/community/community-start-task-cloud.component'; +import { CommunityProcessDetailsCloudDemoComponent } from './components/cloud/community/community-process-details-cloud.component'; +import { CommunityProcessesCloudDemoComponent } from './components/cloud/community/community-processes-cloud.component'; +import { CommunityTaskDetailsCloudDemoComponent } from './components/cloud/community/community-task-details-cloud.component'; export const appRoutes: Routes = [ { path: 'login', component: LoginComponent }, @@ -163,6 +170,36 @@ export const appRoutes: Routes = [ path: 'people-group-cloud', component: PeopleGroupCloudDemoComponent }, + { + path: 'community', + component: CommunityCloudComponent, + children: [ + { + path: 'tasks', + component: CommunityTasksCloudDemoComponent + }, + { + path: 'processes', + component: CommunityProcessesCloudDemoComponent + }, + { + path: 'start-task', + component: CommunityStartTaskCloudDemoComponent + }, + { + path: 'start-process', + component: CommunityStartProcessCloudDemoComponent + }, + { + path: 'task-details/:taskId', + component: CommunityTaskDetailsCloudDemoComponent + }, + { + path: 'process-details/:processInstanceId', + component: CommunityProcessDetailsCloudDemoComponent + } + ] + }, { path: ':appName', canActivate: [AuthGuardSsoRoleService], diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts index 9344a33eab..7133e54810 100644 --- a/demo-shell/src/app/components/app-layout/app-layout.component.ts +++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts @@ -48,6 +48,7 @@ export class AppLayoutComponent implements OnInit { { href: '/task-list', icon: 'assignment', title: 'APP_LAYOUT.TASK_LIST' }, { href: '/cloud', icon: 'cloud', title: 'APP_LAYOUT.PROCESS_CLOUD', children: [ { href: '/cloud/', icon: 'cloud', title: 'APP_LAYOUT.HOME' }, + { href: '/cloud/community', icon: 'cloud', title: 'APP_LAYOUT.COMMUNITY' }, { href: '/form-cloud', icon: 'poll', title: 'APP_LAYOUT.FORM' }, { href: '/cloud/people-group-cloud', icon: 'group', title: 'APP_LAYOUT.PEOPLE_GROUPS_CLOUD' } ]}, diff --git a/demo-shell/src/app/components/cloud/community/community-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-cloud.component.html new file mode 100644 index 0000000000..051349524a --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-cloud.component.html @@ -0,0 +1,36 @@ +<mat-tab-group fxFill class="adf-cloud-layout-tab-body"> + <mat-tab label="{{'PS_CLOUD_TAB.APPS_TAB' | translate}}"> + <div fxFill fxLayout> + <adf-sidenav-layout fxFlex [sidenavMin]="70" [sidenavMax]="270" [stepOver]="780"> + <adf-sidenav-layout-navigation> + <ng-template> + <adf-sidebar-action-menu [expanded]="true" [width]="205" title="{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.CREATE' | translate}}"> + <mat-icon adf-sidebar-menu-title-icon>arrow_drop_down</mat-icon> + <div adf-sidebar-menu-options> + <button mat-menu-item data-automation-id="btn-start-task" (click)="onStartTask()"> + <mat-icon>assessment</mat-icon> + <span>{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.NEW_TASK' | translate}}</span> + </button> + </div> + <div adf-sidebar-menu-options> + <button mat-menu-item data-automation-id="btn-start-process" (click)="onStartProcess()"> + <mat-icon>assessment</mat-icon> + <span>{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.NEW_PROCESS' | translate}}</span> + </button> + </div> + </adf-sidebar-action-menu> + <app-community-cloud-filters-demo></app-community-cloud-filters-demo> + </ng-template> + </adf-sidenav-layout-navigation> + <adf-sidenav-layout-content> + <ng-template> + <router-outlet></router-outlet> + </ng-template> + </adf-sidenav-layout-content> + </adf-sidenav-layout> + </div> + </mat-tab> + <mat-tab label="{{'PS_CLOUD_TAB.SETTINGS_TAB' | translate}}"> + <app-cloud-settings></app-cloud-settings> + </mat-tab> + </mat-tab-group> diff --git a/demo-shell/src/app/components/cloud/community/community-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-cloud.component.ts new file mode 100644 index 0000000000..6303699344 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-cloud.component.ts @@ -0,0 +1,68 @@ +/*! + * @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, ViewEncapsulation } from '@angular/core'; +import { Router, ActivatedRoute } from '@angular/router'; +import { CloudLayoutService } from '../services/cloud-layout.service'; + +@Component({ + templateUrl: './community-cloud.component.html', + styles: [`.adf-cloud-layout-overflow { + overflow: auto; + } + + .adf-cloud-layout-tab-body .mat-tab-body-wrapper { + height: 100% !important; + } + `], + encapsulation: ViewEncapsulation.None +}) +export class CommunityCloudComponent { + + appName: string = ''; + + constructor( + private router: Router, + private route: ActivatedRoute, + private cloudLayoutService: CloudLayoutService + ) { } + + ngOnInit() { + let root: string = ''; + if (this.route.snapshot && this.route.snapshot.firstChild) { + root = this.route.snapshot.firstChild.url[0].path; + } + + this.route.queryParams.subscribe((params) => { + if (root === 'tasks' && params.id) { + this.cloudLayoutService.setCurrentTaskFilterParam({ id: params.id }); + } + + if (root === 'processes' && params.id) { + this.cloudLayoutService.setCurrentProcessFilterParam({ id: params.id }); + } + }); + } + + onStartTask() { + this.router.navigate([`/cloud/community/start-task/`]); + } + + onStartProcess() { + this.router.navigate([`/cloud/community/start-process/`]); + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-filters.component.html b/demo-shell/src/app/components/cloud/community/community-filters.component.html new file mode 100644 index 0000000000..7daa8b33ac --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-filters.component.html @@ -0,0 +1,31 @@ +<mat-accordion> + <mat-expansion-panel [expanded]="expandTaskFilter" (opened)="onTaskFilterOpen()" (closed)="onTaskFilterClose()" data-automation-id='Task Filters'> + <mat-expansion-panel-header> + <mat-panel-title> + Task Filters + </mat-panel-title> + </mat-expansion-panel-header> + <adf-cloud-task-filters + *ngIf="expandTaskFilter" + [appName]="appName" + [showIcons]="true" + [filterParam]="currentTaskFilter$ | async" + (filterClick)="onTaskFilterSelected($event)"> + </adf-cloud-task-filters> + </mat-expansion-panel> + + <mat-expansion-panel [expanded]="expandProcessFilter" (opened)="onProcessFilterOpen()" (closed)="onProcessFilterClose()" data-automation-id='Process Filters'> + <mat-expansion-panel-header> + <mat-panel-title> + Process Filters + </mat-panel-title> + </mat-expansion-panel-header> + <adf-cloud-process-filters + *ngIf="expandProcessFilter" + [appName]="appName" + [showIcons]="true" + [filterParam]="currentProcessFilter$ | async" + (filterClick)="onProcessFilterSelected($event)"> + </adf-cloud-process-filters> + </mat-expansion-panel> + </mat-accordion> diff --git a/demo-shell/src/app/components/cloud/community/community-filters.component.ts b/demo-shell/src/app/components/cloud/community/community-filters.component.ts new file mode 100644 index 0000000000..39e64d288f --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-filters.component.ts @@ -0,0 +1,94 @@ +/*! + * @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, ViewEncapsulation, Input, OnInit } from '@angular/core'; +import { Observable } from 'rxjs'; +import { Router, ActivatedRoute } from '@angular/router'; +import { CloudLayoutService } from '../services/cloud-layout.service'; +@Component({ + selector: 'app-community-cloud-filters-demo', + templateUrl: './community-filters.component.html', + encapsulation: ViewEncapsulation.None +}) +export class CommunityCloudFiltersDemoComponent implements OnInit { + + @Input() + appName: string = 'community'; + + currentTaskFilter$: Observable<any>; + currentProcessFilter$: Observable<any>; + + toggleTaskFilter = true; + toggleProcessFilter = true; + + expandTaskFilter = true; + expandProcessFilter = false; + + constructor( + private cloudLayoutService: CloudLayoutService, + private router: Router, + private route: ActivatedRoute + ) {} + + ngOnInit() { + this.currentTaskFilter$ = this.cloudLayoutService.getCurrentTaskFilterParam(); + this.currentProcessFilter$ = this.cloudLayoutService.getCurrentProcessFilterParam(); + let root = ''; + if (this.route.snapshot && this.route.snapshot.firstChild) { + root = this.route.snapshot.firstChild.url[0].path; + if (root === 'tasks') { + this.expandTaskFilter = true; + this.expandProcessFilter = false; + } else if (root === 'processes') { + this.expandProcessFilter = true; + this.expandTaskFilter = false; + } + } + } + + onTaskFilterSelected(filter) { + this.cloudLayoutService.setCurrentTaskFilterParam({id: filter.id}); + const currentFilter = Object.assign({}, filter); + this.router.navigate([`/cloud/community/tasks/`], { queryParams: currentFilter }); + } + + onProcessFilterSelected(filter) { + this.cloudLayoutService.setCurrentProcessFilterParam({id: filter.id}); + const currentFilter = Object.assign({}, filter); + this.router.navigate([`/cloud/community/processes/`], { queryParams: currentFilter }); + } + + onTaskFilterOpen(): boolean { + this.expandTaskFilter = true; + this.expandProcessFilter = false; + return this.toggleTaskFilter; + } + + onTaskFilterClose(): boolean { + return !this.toggleTaskFilter; + } + + onProcessFilterOpen(): boolean { + this.expandProcessFilter = true; + this.expandTaskFilter = false; + return this.toggleProcessFilter; + } + + onProcessFilterClose(): boolean { + return !this.toggleProcessFilter; + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html new file mode 100644 index 0000000000..6fc529df18 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html @@ -0,0 +1,24 @@ + +<button data-automation-id="go-back" mat-icon-button (click)="onGoBack()"> + <mat-icon>arrow_back</mat-icon> Go Back +</button> + +<h4 data-automation-id="process-details-header">Simple page to show the process instance: {{ processInstanceId }} of the app: {{ appName }}</h4> + +<div class="adf-process-cloud-container"> + + <adf-cloud-task-list + fxFlex + class="adf-cloud-layout-overflow" + [processInstanceId]="processInstanceId" + (rowClick)="onRowClick($event)" + #taskCloud> + </adf-cloud-task-list> + + <adf-cloud-process-header + class="adf-process-cloud-header" + [appName]="''" + [processInstanceId]="processInstanceId"> + </adf-cloud-process-header> +</div> + diff --git a/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.scss b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.scss new file mode 100644 index 0000000000..3ad46f3b2c --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.scss @@ -0,0 +1,14 @@ +.adf { + &-process-cloud-container { + display: flex; + } + + &-cloud-layout-overflow { + width:67%; + } + + &-process-cloud-header { + margin-left: 10px; + width: 25%; + } + } diff --git a/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.ts new file mode 100644 index 0000000000..aa959a46e9 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.ts @@ -0,0 +1,49 @@ +/*! + * @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 } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + templateUrl: './community-process-details-cloud.component.html', + styleUrls: ['./community-process-details-cloud.component.scss'] +}) +export class CommunityProcessDetailsCloudDemoComponent { + + processInstanceId: string; + appName: string; + + constructor(private route: ActivatedRoute, private router: Router) { + this.route.params.subscribe((params) => { + this.processInstanceId = params.processInstanceId; + }); + + this.route.parent.params.subscribe((params) => { + this.appName = params.appName; + }); + } + + onGoBack() { + this.router.navigate([`/cloud/community/`]); + } + + onRowClick(taskId: string) { + if (taskId) { + this.router.navigate([`/cloud/community/task-details/${taskId}`]); + } + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.html new file mode 100644 index 0000000000..fb5071c765 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.html @@ -0,0 +1,44 @@ +<div fxLayout="column" fxFill fxLayoutGap="2px"> + <adf-cloud-edit-process-filter + [id]="filterId" + [appName]="'community'" + [filterProperties]="processFilterProperties.filterProperties" + [sortProperties]="processFilterProperties.sortProperties" + [actions]="processFilterProperties.actions" + (filterChange)="onFilterChange($event)" + (action)="onProcessFilterAction($event)"> + </adf-cloud-edit-process-filter> + <div fxLayout="column" fxFlex fxLayoutAlign="space-between" *ngIf="editedFilter"> + <adf-cloud-process-list #processCloud + fxFlex + [appName]="''" + class="adf-cloud-layout-overflow" + [initiator]="editedFilter.initiator" + [processDefinitionId]="editedFilter.processDefinitionId" + [processDefinitionKey]="editedFilter.processDefinitionKey" + [id]="editedFilter.processInstanceId" + [status]="editedFilter.status" + [name]="editedFilter.processName" + [businessKey]="editedFilter.businessKey" + [lastModifiedFrom]="editedFilter.lastModifiedFrom" + [lastModifiedTo]="editedFilter.lastModifiedTo" + [sorting]="sortArray" + [selectionMode]="selectionMode" + [multiselect]="multiselect" + (rowClick)="onRowClick($event)" + (rowsSelected)="onRowsSelected($event)"> + </adf-cloud-process-list> + <adf-pagination + [target]="processCloud" + (changePageSize)="onChangePageSize($event)" + (nextPage)="resetSelectedRows()" + (prevPage)="resetSelectedRows()"> + </adf-pagination> + <div *ngIf="testingMode"> + Selected rows: + <ul> + <li *ngFor="let row of selectedRows">{{ row.id }}</li> + </ul> + </div> + </div> +</div> diff --git a/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts new file mode 100644 index 0000000000..c7d658b9b1 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts @@ -0,0 +1,134 @@ +/*! + * @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, ViewChild, OnInit } from '@angular/core'; +import { + ProcessListCloudComponent, + ProcessFilterCloudModel, + ProcessListCloudSortingModel, + ProcessFiltersCloudComponent, + ProcessFilterCloudService +} from '@alfresco/adf-process-services-cloud'; + +import { ActivatedRoute, Router } from '@angular/router'; +import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core'; +import { CloudLayoutService } from '../services/cloud-layout.service'; + +@Component({ + templateUrl: './community-processes-cloud.component.html' +}) +export class CommunityProcessesCloudDemoComponent implements OnInit { + + public static ACTION_SAVE_AS = 'saveAs'; + static PROCESS_FILTER_PROPERTY_KEYS = 'adf-edit-process-filter'; + + @ViewChild('processCloud') + processCloud: ProcessListCloudComponent; + + @ViewChild('processFiltersCloud') + processFiltersCloud: ProcessFiltersCloudComponent; + + appName: string = ''; + isFilterLoaded: boolean; + + filterId: string = ''; + sortArray: any = []; + selectedRow: any; + multiselect: boolean; + selectionMode: string; + selectedRows: string[] = []; + testingMode: boolean; + processFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] }; + + editedFilter: ProcessFilterCloudModel; + + constructor( + private route: ActivatedRoute, + private router: Router, + private cloudLayoutService: CloudLayoutService, + private userPreference: UserPreferencesService, + private processFilterCloudService: ProcessFilterCloudService, + private appConfig: AppConfigService) { + const properties = this.appConfig.get<Array<any>>(CommunityProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS); + if (properties) { + this.processFilterProperties = properties; + } + } + + ngOnInit() { + this.isFilterLoaded = false; + this.route.parent.params.subscribe((params) => { + this.appName = params.appName; + }); + + this.route.queryParams.subscribe((params) => { + if (Object.keys(params).length > 0) { + this.isFilterLoaded = true; + this.onFilterChange(params); + this.filterId = params.id; + } else { + this.loadDefaultFilters(); + } + }); + + this.cloudLayoutService.getCurrentSettings() + .subscribe((settings) => this.setCurrentSettings(settings)); + } + + loadDefaultFilters() { + this.processFilterCloudService.getProcessFilters('community').subscribe( (filters: ProcessFilterCloudModel[]) => { + this.onFilterChange(filters[0]); + }); + } + + setCurrentSettings(settings) { + if (settings) { + this.multiselect = settings.multiselect; + this.testingMode = settings.testingMode; + this.selectionMode = settings.selectionMode; + } + } + + onChangePageSize(event) { + this.userPreference.paginationSize = event.maxItems; + } + + resetSelectedRows() { + this.selectedRows = []; + } + + onRowClick(processInstanceId) { + this.router.navigate([`/cloud/community/process-details/${processInstanceId}`]); + } + + onFilterChange(query: any) { + this.editedFilter = Object.assign({}, query); + this.sortArray = [new ProcessListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })]; + } + + onProcessFilterAction(filterAction: any) { + this.cloudLayoutService.setCurrentProcessFilterParam({ id: filterAction.filter.id }); + if (filterAction.actionType === CommunityProcessesCloudDemoComponent.ACTION_SAVE_AS) { + this.router.navigate([`/cloud/community/processes/`], { queryParams: filterAction.filter }); + } + } + + onRowsSelected(nodes) { + this.resetSelectedRows(); + this.selectedRows = nodes.map((node) => node.obj.entry); + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.html new file mode 100644 index 0000000000..df2ca1cb8b --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.html @@ -0,0 +1,7 @@ +<adf-cloud-start-process + [name]="processName" + [appName]="''" + (error)="openSnackMessage($event)" + (success)="onStartProcessSuccess()" + (cancel)="onCancelStartProcess()"> +</adf-cloud-start-process> diff --git a/demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.ts new file mode 100644 index 0000000000..54ab9090df --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-start-process-cloud.component.ts @@ -0,0 +1,56 @@ +/*! + * @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, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { NotificationService, AppConfigService } from '@alfresco/adf-core'; +import { CloudLayoutService } from '../services/cloud-layout.service'; + +@Component({ + templateUrl: './community-start-process-cloud.component.html' +}) +export class CommunityStartProcessCloudDemoComponent implements OnInit { + + processName: string; + + constructor(private appConfig: AppConfigService, + private cloudLayoutService: CloudLayoutService, + private notificationService: NotificationService, + private router: Router) { + } + + ngOnInit() { + this.processName = this.appConfig.get<string>('adf-start-process.name'); + } + + onStartProcessSuccess() { + this.cloudLayoutService.setCurrentProcessFilterParam({ key: 'running-processes' }); + this.router.navigate([`/cloud/community/processes`]); + } + + onCancelStartProcess() { + this.cloudLayoutService.setCurrentProcessFilterParam({ key: 'all-processes' }); + this.router.navigate([`/cloud/community/processes`]); + } + + openSnackMessage(event: any) { + this.notificationService.openSnackMessage( + event.response.body.message, + 4000 + ); + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html new file mode 100644 index 0000000000..9975b99cc6 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html @@ -0,0 +1,5 @@ +<adf-cloud-start-task + (error)="openSnackMessage($event)" + (success)="onStartTaskSuccess()" + (cancel)="onCancelStartTask()"> +</adf-cloud-start-task> diff --git a/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.ts new file mode 100644 index 0000000000..fda2cd29b2 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.ts @@ -0,0 +1,49 @@ +/*! + * @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 } from '@angular/core'; +import { Router } from '@angular/router'; +import { NotificationService } from '@alfresco/adf-core'; +import { CloudLayoutService } from '../services/cloud-layout.service'; +@Component({ + templateUrl: './community-start-task-cloud.component.html' +}) +export class CommunityStartTaskCloudDemoComponent { + + constructor( + private cloudLayoutService: CloudLayoutService, + private notificationService: NotificationService, + private router: Router) { + } + + onStartTaskSuccess() { + this.cloudLayoutService.setCurrentTaskFilterParam({key: 'community'}); + this.router.navigate([`/cloud/community/tasks`]); + } + + onCancelStartTask() { + this.cloudLayoutService.setCurrentTaskFilterParam({key: 'community'}); + this.router.navigate([`/cloud/community/tasks`]); + } + + openSnackMessage(event: any) { + this.notificationService.openSnackMessage( + event.response.body.message, + 4000 + ); + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-task-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-task-cloud.component.html new file mode 100644 index 0000000000..cf431267d5 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-task-cloud.component.html @@ -0,0 +1,48 @@ +<div fxLayout="column" fxFill fxLayoutGap="2px"> + <adf-cloud-edit-task-filter + [id]="filterId" + [appName]="'community'" + [filterProperties]="taskFilterProperties.filterProperties" + [sortProperties]="taskFilterProperties.sortProperties" + [actions]="taskFilterProperties.actions" + (action)="onTaskFilterAction($event)" + (filterChange)="onFilterChange($event)"> + </adf-cloud-edit-task-filter> + <div fxLayout="column" fxFlex fxLayoutAlign="space-between" *ngIf="editedFilter"> + <adf-cloud-task-list #taskCloud + fxFlex + [appName]="''" + class="adf-cloud-layout-overflow" + [processDefinitionId]="editedFilter.processDefinitionId" + [processInstanceId]="editedFilter.processInstanceId" + [name]="editedFilter.taskName" + [id]="editedFilter.taskId" + [parentTaskId]="editedFilter.parentTaskId" + [priority]="editedFilter.priority" + [owner]="editedFilter.owner" + [lastModifiedFrom]="editedFilter.lastModifiedFrom" + [lastModifiedTo]="editedFilter.lastModifiedTo" + [status]="editedFilter.status" + [assignee]="editedFilter.assignee" + [createdDate]="editedFilter.createdDate" + [dueDate]="editedFilter.dueDate" + [sorting]="sortArray" + [multiselect]="multiselect" + [selectionMode]="selectionMode" + (rowClick)="onRowClick($event)" + (rowsSelected)="onRowsSelected($event)"> + </adf-cloud-task-list> + <adf-pagination + [target]="taskCloud" + (changePageSize)="onChangePageSize($event)" + (nextPage)="resetSelectedRows()" + (prevPage)="resetSelectedRows()"> + </adf-pagination> + <div *ngIf="testingMode"> + Selected rows: + <ul> + <li *ngFor="let row of selectedRows" [attr.data-automation-id]="row.id">{{ row.name }}</li> + </ul> + </div> + </div> +</div> diff --git a/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts new file mode 100644 index 0000000000..1e77a51372 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts @@ -0,0 +1,131 @@ +/*! + * @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, ViewChild, OnInit } from '@angular/core'; +import { TaskListCloudComponent, TaskListCloudSortingModel, TaskFilterCloudModel, TaskFilterCloudService } from '@alfresco/adf-process-services-cloud'; +import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { CloudLayoutService } from '../services/cloud-layout.service'; + +@Component({ + templateUrl: './community-task-cloud.component.html', + styles: [`.adf-cloud-layout-tab-body .mat-tab-body-wrapper { + height: 100%; + } + `] +}) +export class CommunityTasksCloudDemoComponent implements OnInit { + + public static ACTION_SAVE_AS = 'saveAs'; + static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter'; + + @ViewChild('taskCloud') + taskCloud: TaskListCloudComponent; + + isFilterLoaded = false; + + selectedRow: any; + + sortArray: TaskListCloudSortingModel[]; + editedFilter: TaskFilterCloudModel; + taskFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] }; + + filterId; + multiselect: boolean; + selectedRows: string[] = []; + testingMode: boolean; + selectionMode: string; + taskDetailsRedirection: boolean; + + constructor( + private cloudLayoutService: CloudLayoutService, + private route: ActivatedRoute, + private router: Router, + private taskFilterCloudService: TaskFilterCloudService, + private userPreference: UserPreferencesService, + private appConfig: AppConfigService) { + + const properties = this.appConfig.get<Array<any>>(CommunityTasksCloudDemoComponent.TASK_FILTER_PROPERTY_KEYS); + if (properties) { + this.taskFilterProperties = properties; + } + } + + ngOnInit() { + this.isFilterLoaded = false; + this.route.queryParams.subscribe((params) => { + if (Object.keys(params).length > 0) { + this.isFilterLoaded = true; + this.onFilterChange(params); + this.filterId = params.id; + } else { + setTimeout( () => { + this.loadDefaultFilters(); + }); + } + }); + + this.cloudLayoutService.getCurrentSettings() + .subscribe((settings) => this.setCurrentSettings(settings)); + } + + loadDefaultFilters() { + this.taskFilterCloudService.getTaskListFilters('community').subscribe( (filters: TaskFilterCloudModel[]) => { + this.onFilterChange(filters[0]); + }); + } + + setCurrentSettings(settings) { + if (settings) { + this.multiselect = settings.multiselect; + this.testingMode = settings.testingMode; + this.selectionMode = settings.selectionMode; + this.taskDetailsRedirection = settings.taskDetailsRedirection; + } + } + + onChangePageSize(event) { + this.userPreference.paginationSize = event.maxItems; + } + + resetSelectedRows() { + this.selectedRows = []; + } + + onRowClick(taskId) { + if (!this.multiselect && this.selectionMode !== 'multiple' && this.taskDetailsRedirection) { + this.router.navigate([`/cloud/community/task-details/${taskId}`]); + } + } + + onRowsSelected(nodes) { + this.resetSelectedRows(); + this.selectedRows = nodes.map((node) => node.obj.entry); + } + + onFilterChange(filter: any) { + this.editedFilter = Object.assign({}, filter); + this.sortArray = [new TaskListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })]; + } + + onTaskFilterAction(filterAction: any) { + this.cloudLayoutService.setCurrentTaskFilterParam({ id: filterAction.filter.id }); + if (filterAction.actionType === CommunityTasksCloudDemoComponent.ACTION_SAVE_AS) { + this.router.navigate([`/cloud/community/tasks/`], { queryParams: filterAction.filter }); + } + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html new file mode 100644 index 0000000000..541e5c8549 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html @@ -0,0 +1,21 @@ +<h4 data-automation-id="task-details-header">Simple page to show the taskId: {{ taskId }} of the app: {{ appName }}</h4> + +<div fxLayout="column" fxFill fxLayoutGap="2px"> + <div fxLayout="row" fxFill> + <div fxLayout="column" fxFlex="80%"> + <adf-task-form-cloud + [appName]="''" + [taskId]="taskId" + (cancelClick)="goBack()" + (taskClaimed)="onClaimTask()" + (taskCompleted)="onTaskCompleted()" + (taskUnclaimed)="onUnclaimTask()" + (formSaved)="onFormSaved()"> + </adf-task-form-cloud> + </div> + <adf-cloud-task-header fxFlex + [appName]="''" + [taskId]="taskId"> + </adf-cloud-task-header> + </div> +</div> diff --git a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss new file mode 100644 index 0000000000..e97ca949e4 --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss @@ -0,0 +1,20 @@ + +.adf { + + &-task-detail-container { + display: flex; + } + + &-task-tiitle { + margin-left:15px; + } + + &-task-control { + width:70%; + } + + &-demop-card-container { + width:30%; + font-family: inherit; + } +} diff --git a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts new file mode 100644 index 0000000000..b08e56669b --- /dev/null +++ b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts @@ -0,0 +1,75 @@ +/*! + * @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 } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; +import { NotificationService, FormRenderingService } from '@alfresco/adf-core'; + +@Component({ + templateUrl: './community-task-details-cloud.component.html', + styleUrls: ['./community-task-details-cloud.component.scss'] +}) +export class CommunityTaskDetailsCloudDemoComponent { + + taskId: string; + appName: string; + + constructor( + private route: ActivatedRoute, + private router: Router, + private formRenderingService: FormRenderingService, + private notificationService: NotificationService + ) { + this.route.params.subscribe((params) => { + this.taskId = params.taskId; + }); + this.route.parent.params.subscribe((params) => { + this.appName = params.appName; + }); + this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); + + } + + isTaskValid(): boolean { + return this.appName !== undefined && this.taskId !== undefined; + } + + goBack() { + this.router.navigate([`/cloud/community/`]); + } + + onCompletedTask() { + this.goBack(); + } + + onUnclaimTask() { + this.goBack(); + } + + onClaimTask() { + this.goBack(); + } + + onTaskCompleted() { + this.goBack(); + } + + onFormSaved() { + this.notificationService.openSnackMessage('Task has been saved successfully'); + } +} diff --git a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts index 1289adf9e3..01aa3ed579 100644 --- a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts @@ -23,6 +23,7 @@ import { ProcessCloudModule } from './process/process-cloud.module'; import { GroupCloudModule } from './group/group-cloud.module'; import { FormCloudModule } from './form/form-cloud.module'; import { TaskFormModule } from './task/task-form/task-form.module'; +import { BaseCloudService } from './services/base-cloud.service'; @NgModule({ imports: [ @@ -42,7 +43,8 @@ import { TaskFormModule } from './task/task-form/task-form.module'; name: 'adf-process-services-cloud', source: 'assets/adf-process-services-cloud' } - } + }, + BaseCloudService ], exports: [ AppListCloudModule, diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts index d13275505a..60a652d011 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts @@ -219,7 +219,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges { } } - createSortProperties(): any { + get createSortProperties(): any { this.checkMandatorySortProperties(); const sortProperties = this.sortProperties.map((property: string) => { return <ProcessFilterOptions> { label: property.charAt(0).toUpperCase() + property.slice(1), value: property }; @@ -505,7 +505,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges { type: 'select', key: 'sort', value: currentProcessFilter.sort || this.createSortProperties[0].value, - options: this.createSortProperties() + options: this.createSortProperties }), new ProcessFilterProperties({ label: 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DIRECTION', diff --git a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts index d6eddbe24d..7f2becdd81 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/components/process-header-cloud.component.ts @@ -47,7 +47,7 @@ export class ProcessHeaderCloudComponent implements OnChanges { } ngOnChanges() { - if (this.appName && this.processInstanceId) { + if ((this.appName || this.appName === '') && this.processInstanceId) { this.loadProcessInstanceDetails(this.appName, this.processInstanceId); } } diff --git a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts index 3eb4eedcd4..939d978173 100644 --- a/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-header/services/process-header-cloud.service.ts @@ -20,11 +20,12 @@ import { Injectable } from '@angular/core'; import { Observable, from, throwError } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model'; +import { BaseCloudService } from '../../../services/base-cloud.service'; @Injectable({ providedIn: 'root' }) -export class ProcessHeaderCloudService { +export class ProcessHeaderCloudService extends BaseCloudService { contextRoot: string; contentTypes = ['application/json']; accepts = ['application/json']; @@ -33,6 +34,7 @@ export class ProcessHeaderCloudService { constructor(private alfrescoApiService: AlfrescoApiService, private appConfigService: AppConfigService, private logService: LogService) { + super(); this.contextRoot = this.appConfigService.get('bpmHost', ''); } @@ -43,9 +45,8 @@ export class ProcessHeaderCloudService { * @returns Process instance details */ getProcessInstanceById(appName: string, processInstanceId: string): Observable<ProcessInstanceCloud> { - if (appName && processInstanceId) { - - const queryUrl = `${this.contextRoot}/${appName}/query/v1/process-instances/${processInstanceId}`; + if ((appName || appName === '') && processInstanceId) { + const queryUrl = `${this.getBasePath(appName)}/query/v1/process-instances/${processInstanceId}`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', null, null, null, diff --git a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts index 84139f196e..076f2a9da9 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.ts @@ -43,7 +43,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan /** The name of the application. */ @Input() - appName: string = ''; + appName: string; /** Name of the initiator of the process. */ @Input() @@ -156,7 +156,7 @@ export class ProcessListCloudComponent extends DataTableSchema implements OnChan reload() { this.requestNode = this.createRequestNode(); - if (this.requestNode.appName) { + if (this.requestNode.appName || this.requestNode.appName === '') { this.load(this.requestNode); } else { this.rows = []; diff --git a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts index 32047521f9..418954ec6d 100644 --- a/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/process-list/services/process-list-cloud.service.ts @@ -19,8 +19,10 @@ import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf- import { ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model'; import { Observable, from, throwError } from 'rxjs'; import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model'; +import { BaseCloudService } from '../../../services/base-cloud.service'; + @Injectable() -export class ProcessListCloudService { +export class ProcessListCloudService extends BaseCloudService { contentTypes = ['application/json']; accepts = ['application/json']; @@ -28,6 +30,7 @@ export class ProcessListCloudService { constructor(private apiService: AlfrescoApiService, private appConfigService: AppConfigService, private logService: LogService) { + super(); } /** @@ -36,7 +39,7 @@ export class ProcessListCloudService { * @returns Process information */ getProcessByRequest(requestNode: ProcessQueryCloudRequestModel): Observable<any> { - if (requestNode.appName) { + if (requestNode.appName || requestNode.appName === '') { const queryUrl = this.buildQueryUrl(requestNode); const queryParams = this.buildQueryParams(requestNode); const sortingParams = this.buildSortingParam(requestNode.sorting); @@ -55,7 +58,8 @@ export class ProcessListCloudService { } } private buildQueryUrl(requestNode: ProcessQueryCloudRequestModel) { - return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}/query/v1/process-instances`; + this.contextRoot = this.appConfigService.get('bpmHost', ''); + return `${this.getBasePath(requestNode.appName)}/query/v1/process-instances`; } private isPropertyValueValid(requestNode, property) { diff --git a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts index 9814ad4f66..cbc55641bd 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts @@ -122,7 +122,7 @@ export class StartProcessCloudComponent implements OnChanges, OnInit { } private getProcessDefinitionList(processDefinitionName: string): ProcessDefinitionCloud[] { - return this.processDefinitionList.filter((option) => option.name.toLowerCase().includes(processDefinitionName.toLowerCase())); + return this.processDefinitionList.filter((option) => option.name && option.name.toLowerCase().includes(processDefinitionName.toLowerCase())); } private getProcessIfExists(processDefinitionName: string): ProcessDefinitionCloud { diff --git a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts index 0e4af4c6b2..d5368d843a 100755 --- a/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/process/start-process/services/start-process-cloud.service.ts @@ -22,11 +22,12 @@ import { map, catchError } from 'rxjs/operators'; import { ProcessInstanceCloud } from '../models/process-instance-cloud.model'; import { ProcessPayloadCloud } from '../models/process-payload-cloud.model'; import { ProcessDefinitionCloud } from '../models/process-definition-cloud.model'; +import { BaseCloudService } from '../../../services/base-cloud.service'; @Injectable({ providedIn: 'root' }) -export class StartProcessCloudService { +export class StartProcessCloudService extends BaseCloudService { contextRoot: string; contentTypes = ['application/json']; @@ -34,8 +35,9 @@ export class StartProcessCloudService { returnType = Object; constructor(private alfrescoApiService: AlfrescoApiService, - private appConfigService: AppConfigService, - private logService: LogService) { + private logService: LogService, + private appConfigService: AppConfigService) { + super(); this.contextRoot = this.appConfigService.get('bpmHost', ''); } @@ -46,8 +48,8 @@ export class StartProcessCloudService { */ getProcessDefinitions(appName: string): Observable<ProcessDefinitionCloud[]> { - if (appName) { - const queryUrl = `${this.contextRoot}/${appName}/rb/v1/process-definitions`; + if (appName || appName === '') { + const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-definitions`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', @@ -75,7 +77,7 @@ export class StartProcessCloudService { */ startProcess(appName: string, requestPayload: ProcessPayloadCloud): Observable<ProcessInstanceCloud> { - const queryUrl = `${this.contextRoot}/${appName}/rb/v1/process-instances`; + const queryUrl = `${this.getBasePath(appName)}/rb/v1/process-instances`; return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', diff --git a/lib/process-services-cloud/src/lib/services/base-cloud.service.ts b/lib/process-services-cloud/src/lib/services/base-cloud.service.ts new file mode 100644 index 0000000000..b253d34c3c --- /dev/null +++ b/lib/process-services-cloud/src/lib/services/base-cloud.service.ts @@ -0,0 +1,35 @@ +/*! + * @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 { Injectable } from '@angular/core'; + +@Injectable() +export class BaseCloudService { + + public contextRoot: string; + + getBasePath(appName: string) { + if (this.isValidAppName(appName)) { + return `${this.contextRoot}/${appName}`; + } + return this.contextRoot; + } + + private isValidAppName(appName: string) { + return appName && appName !== ''; + } +} diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index 706839aecd..a6af517e40 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -20,13 +20,13 @@ import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService } import { from, throwError, Observable } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { TaskDetailsCloudModel } from '../start-task/models/task-details-cloud.model'; +import { BaseCloudService } from '../../services/base-cloud.service'; @Injectable({ providedIn: 'root' }) -export class TaskCloudService { +export class TaskCloudService extends BaseCloudService { - contextRoot: string; contentTypes = ['application/json']; accepts = ['application/json']; returnType = Object; @@ -37,6 +37,7 @@ export class TaskCloudService { private logService: LogService, private identityUserService: IdentityUserService ) { + super(); this.contextRoot = this.appConfigService.get('bpmHost', ''); } @@ -102,8 +103,7 @@ export class TaskCloudService { */ claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - - const queryUrl = `${this.contextRoot}/${appName}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; + const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', null, null, null, @@ -130,8 +130,7 @@ export class TaskCloudService { */ unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { if (appName && taskId) { - - const queryUrl = `${this.contextRoot}/${appName}/rb/v1/tasks/${taskId}/release`; + const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', null, null, null, @@ -157,9 +156,8 @@ export class TaskCloudService { * @returns Task details */ getTaskById(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { - if (appName && taskId) { - - const queryUrl = `${this.contextRoot}/${appName}/query/v1/tasks/${taskId}`; + if ((appName || appName === '') && taskId) { + const queryUrl = `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'GET', null, null, null, @@ -189,8 +187,7 @@ export class TaskCloudService { if (appName && taskId) { updatePayload.payloadType = 'UpdateTaskPayload'; - - const queryUrl = `${this.contextRoot}/${appName}/rb/v1/tasks/${taskId}`; + const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'PUT', null, null, null, @@ -210,7 +207,7 @@ export class TaskCloudService { } private buildCompleteTaskUrl(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks/${taskId}/complete`; + return `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/complete`; } private handleError(error: any) { diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 7469ca0c67..01a171afae 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -17,7 +17,7 @@ import { PeopleCloudComponent } from './people-cloud.component'; import { ComponentFixture, TestBed, async } from '@angular/core/testing'; -import { IdentityUserService, AlfrescoApiService, AlfrescoApiServiceMock, CoreModule, IdentityUserModel } from '@alfresco/adf-core'; +import { IdentityUserService, AlfrescoApiService, CoreModule, IdentityUserModel, setupTestBed } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; import { of } from 'rxjs'; import { mockUsers } from '../../mock/user-cloud.mock'; @@ -43,31 +43,23 @@ describe('PeopleCloudComponent', () => { { id: mockUsers[2].id, username: mockUsers[2].username } ]; - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [ - CoreModule.forRoot(), - ProcessServiceCloudTestingModule, - StartTaskCloudModule - ], - providers: [ - IdentityUserService - ] - }) - .overrideComponent(PeopleCloudComponent, { - set: { - providers: [ - { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock } - ] - } - }).compileComponents(); - })); + setupTestBed({ + imports: [ + CoreModule.forRoot(), + ProcessServiceCloudTestingModule, + StartTaskCloudModule + ], + providers: [ + IdentityUserService + ] + }); beforeEach(() => { fixture = TestBed.createComponent(PeopleCloudComponent); component = fixture.componentInstance; identityService = TestBed.get(IdentityUserService); alfrescoApiService = TestBed.get(AlfrescoApiService); + spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); }); it('should create PeopleCloudComponent', () => { @@ -79,7 +71,6 @@ describe('PeopleCloudComponent', () => { let findUsersByNameSpy: jasmine.Spy; beforeEach(async(() => { - spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); findUsersByNameSpy = spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); fixture.detectChanges(); element = fixture.nativeElement; @@ -173,7 +164,6 @@ describe('PeopleCloudComponent', () => { let findUsersByNameSpy: jasmine.Spy; beforeEach(async(() => { - spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); findUsersByNameSpy = spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); checkUserHasAccessSpy = spyOn(identityService, 'checkUserHasClientApp').and.returnValue(of(true)); checkUserHasAnyClientAppRoleSpy = spyOn(identityService, 'checkUserHasAnyClientAppRole').and.returnValue(of(true)); @@ -318,7 +308,6 @@ describe('PeopleCloudComponent', () => { beforeEach(async(() => { component.roles = ['mock-role-1', 'mock-role-2']; - spyOn(alfrescoApiService, 'getInstance').and.returnValue(mock); spyOn(identityService, 'findUsersByName').and.returnValue(of(mockUsers)); checkUserHasRoleSpy = spyOn(identityService, 'checkUserHasRole').and.returnValue(of(true)); fixture.detectChanges(); @@ -458,6 +447,7 @@ describe('PeopleCloudComponent', () => { component.preSelectUsers = <any> mockPreselectedUsers; fixture.detectChanges(); element = fixture.nativeElement; + alfrescoApiService = TestBed.get(AlfrescoApiService); })); afterEach(() => { @@ -473,8 +463,9 @@ describe('PeopleCloudComponent', () => { }); })); - it('should pre-select all preSelectUsers when mode=multiple', async(() => { + it('should pre-select all preSelectUsers when mode=multiple validation disabled', async(() => { component.mode = 'multiple'; + fixture.detectChanges(); component.ngOnChanges({ 'preSelectUsers': change }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -496,15 +487,11 @@ describe('PeopleCloudComponent', () => { component.mode = 'multiple'; component.validate = true; component.preSelectUsers = <any> mockPreselectedUsers; - fixture.detectChanges(); element = fixture.nativeElement; + alfrescoApiService = TestBed.get(AlfrescoApiService); + fixture.detectChanges(); })); - afterEach(() => { - fixture.destroy(); - TestBed.resetTestingModule(); - }); - it('should show chip list when mode=multiple', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { @@ -514,9 +501,9 @@ describe('PeopleCloudComponent', () => { })); it('should pre-select all preSelectUsers when mode=multiple', async(() => { - fixture.detectChanges(); spyOn(component, 'searchUser').and.returnValue(Promise.resolve(mockPreselectedUsers)); component.mode = 'multiple'; + fixture.detectChanges(); component.ngOnChanges({ 'preSelectUsers': change }); fixture.detectChanges(); fixture.whenStable().then(() => { @@ -527,7 +514,6 @@ describe('PeopleCloudComponent', () => { })); it('should emit removeUser when a selected user is removed if mode=multiple', async(() => { - fixture.detectChanges(); const removeUserSpy = spyOn(component.removeUser, 'emit'); component.mode = 'multiple'; fixture.detectChanges(); @@ -559,6 +545,7 @@ describe('PeopleCloudComponent', () => { const findByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(of(mockUsers[0])); component.mode = 'multiple'; component.validate = true; + fixture.detectChanges(); component.preSelectUsers = <any> [{ id: mockUsers[0].id }, { id: mockUsers[1].id }]; component.ngOnChanges({ 'preSelectUsers': change }); fixture.detectChanges(); @@ -587,6 +574,7 @@ describe('PeopleCloudComponent', () => { it('should filter user by email if validate true', async(() => { const findUserByEmailSpy = spyOn(identityService, 'findUserByEmail').and.returnValue(of(mockUsers)); + fixture.detectChanges(); component.mode = 'multiple'; component.validate = true; component.preSelectUsers = <any> [{ email: mockUsers[1].email }, { email: mockUsers[2].email }]; @@ -604,6 +592,7 @@ describe('PeopleCloudComponent', () => { const findUserByIdSpy = spyOn(identityService, 'findUserById').and.returnValue(of(mockUsers[0])); component.mode = 'single'; component.validate = true; + fixture.detectChanges(); component.preSelectUsers = <any> [{ id: mockUsers[0].id }]; fixture.detectChanges(); fixture.whenStable().then(() => { diff --git a/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts index 99c3e150fa..419ccbc529 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/services/start-task-cloud.service.ts @@ -25,15 +25,16 @@ import { from, Observable, throwError } from 'rxjs'; import { StartTaskCloudRequestModel } from '../models/start-task-cloud-request.model'; import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../models/task-details-cloud.model'; import { map, catchError } from 'rxjs/operators'; +import { BaseCloudService } from '../../../services/base-cloud.service'; @Injectable() -export class StartTaskCloudService { +export class StartTaskCloudService extends BaseCloudService { constructor( private apiService: AlfrescoApiService, private appConfigService: AppConfigService, private logService: LogService - ) {} + ) { super(); } /** * Creates a new standalone task. @@ -62,7 +63,8 @@ export class StartTaskCloudService { } private buildCreateTaskUrl(appName: string): any { - return `${this.appConfigService.get('bpmHost')}/${appName}/rb/v1/tasks`; + this.contextRoot = this.appConfigService.get('bpmHost'); + return `${this.getBasePath(appName)}/rb/v1/tasks`; } private buildRequestBody(taskDetails: any) { diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts index 2771a3ecce..36b4fa0317 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts @@ -231,7 +231,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges { return this.filterProperties.indexOf(EditTaskFilterCloudComponent.LAST_MODIFIED) >= 0; } - createSortProperties(): any { + get createSortProperties(): any { this.checkMandatorySortProperties(); const sortProperties = this.sortProperties.map((property: string) => { return <FilterOptions> { label: property.charAt(0).toUpperCase() + property.slice(1), value: property }; @@ -523,7 +523,7 @@ export class EditTaskFilterCloudComponent implements OnInit, OnChanges { type: 'select', key: 'sort', value: currentTaskFilter.sort || this.createSortProperties[0].value, - options: this.createSortProperties() + options: this.createSortProperties }), new TaskFilterProperties({ label: 'ADF_CLOUD_EDIT_TASK_FILTER.LABEL.DIRECTION', diff --git a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts index 90ed79d974..2aa79df927 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts @@ -52,7 +52,6 @@ export class TaskFilterCloudService { const username = this.getUsername(); const key = `task-filters-${appName}-${username}`; const filters = JSON.parse(this.storage.getItem(key) || '[]'); - if (filters.length === 0) { this.createDefaultFilters(appName); } else { diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index 9ec9bda32b..1b726e4429 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -67,7 +67,7 @@ export class TaskHeaderCloudComponent implements OnInit { ) { } ngOnInit() { - if (this.appName && this.taskId) { + if ((this.appName || this.appName === '') && this.taskId) { this.loadTaskDetailsById(this.appName, this.taskId); } @@ -226,7 +226,7 @@ export class TaskHeaderCloudComponent implements OnInit { } isTaskValid() { - return this.appName && this.taskId; + return (this.appName || this.appName === '') && this.taskId; } isTaskAssigned() { diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts index 7355f7c4ea..034844cd3f 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts @@ -193,7 +193,7 @@ export class TaskListCloudComponent extends DataTableSchema implements OnChanges reload() { this.requestNode = this.createRequestNode(); - if (this.requestNode.appName) { + if (this.requestNode.appName || this.requestNode.appName === '') { this.load(this.requestNode); } else { this.rows = []; diff --git a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts index 717847862a..8cfcf69794 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/services/task-list-cloud.service.ts @@ -20,13 +20,15 @@ import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf- import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model'; import { Observable, from, throwError } from 'rxjs'; import { TaskListCloudSortingModel } from '../models/task-list-sorting.model'; +import { BaseCloudService } from '../../../services/base-cloud.service'; @Injectable() -export class TaskListCloudService { +export class TaskListCloudService extends BaseCloudService { constructor(private apiService: AlfrescoApiService, private appConfigService: AppConfigService, private logService: LogService) { + super(); } contentTypes = ['application/json']; @@ -38,7 +40,8 @@ export class TaskListCloudService { * @returns Task information */ getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> { - if (requestNode.appName) { + + if (requestNode.appName || requestNode.appName === '') { const queryUrl = this.buildQueryUrl(requestNode); const queryParams = this.buildQueryParams(requestNode); const sortingParams = this.buildSortingParam(requestNode.sorting); @@ -58,7 +61,8 @@ export class TaskListCloudService { } private buildQueryUrl(requestNode: TaskQueryCloudRequestModel) { - return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}/query/v1/tasks`; + this.contextRoot = this.appConfigService.get('bpmHost', ''); + return `${this.getBasePath(requestNode.appName)}/query/v1/tasks`; } private buildQueryParams(requestNode: TaskQueryCloudRequestModel) { From 3291ecaccb50ae8908c89205efd031003c69bd6b Mon Sep 17 00:00:00 2001 From: siva kumar <siva.kumar@muraai.com> Date: Tue, 30 Apr 2019 14:51:37 +0530 Subject: [PATCH 183/208] [ADF-4432] TaskFormCloudComponent - should be read only if the task is unclaimed. (#4654) * [ADF-4432] FormCloud - should be read only if the task is unclaimed.* Modifed formCloud component related claim/unclaim custom buttons.* Added unit tests to the recent changes* Created an component to project custom form outcomes. * * Added documentation to the formcloudcustomoutcome component. --- .../form-cloud-custom-outcomes.component.png | Bin 0 -> 16934 bytes .../form-cloud-custom-outcome.component.md | 34 ++++++ .../components/form-cloud.component.md | 22 ++++ .../form-cloud-custom-outcomes.component.ts | 24 +++++ .../form/components/form-cloud.component.html | 1 + .../components/form-cloud.component.spec.ts | 92 +++++++++------- .../form/components/form-cloud.component.ts | 49 --------- .../src/lib/form/form-cloud.module.ts | 5 +- .../src/lib/form/models/form-cloud.model.ts | 4 - .../components/task-form-cloud.component.html | 15 ++- .../task-form-cloud.component.spec.ts | 99 +++++++++++++++++- .../components/task-form-cloud.component.ts | 31 +----- 12 files changed, 243 insertions(+), 133 deletions(-) create mode 100644 docs/docassets/images/form-cloud-custom-outcomes.component.png create mode 100644 docs/process-services-cloud/components/form-cloud-custom-outcome.component.md create mode 100644 lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts diff --git a/docs/docassets/images/form-cloud-custom-outcomes.component.png b/docs/docassets/images/form-cloud-custom-outcomes.component.png new file mode 100644 index 0000000000000000000000000000000000000000..6f991d2b4a61cafeb7ca108442cdfc875ad9e241 GIT binary patch literal 16934 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 K>E!eJ_x~>edSkEv literal 0 HcmV?d00001 diff --git a/docs/process-services-cloud/components/form-cloud-custom-outcome.component.md b/docs/process-services-cloud/components/form-cloud-custom-outcome.component.md new file mode 100644 index 0000000000..fc2c5c1482 --- /dev/null +++ b/docs/process-services-cloud/components/form-cloud-custom-outcome.component.md @@ -0,0 +1,34 @@ +--- +Title: Form cloud custom outcomes component +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-12 +--- + +# [Form cloud custom outcomes component](../../../lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts "Defined in form-cloud-custom-outcomes.component.ts") + +Supplies custom outcome buttons to be included in [Form cloud component](form-cloud.component.md). + +![](../../docassets/images/form-cloud-custom-outcomes.component.png) + +## Basic Usage + +```html +<adf-cloud-form> + <adf-cloud-form-custom-outcomes> + <button mat-button (click)="onCustomOutcome1()"> + Custom-outcome-1 + </button> + <button mat-button (click)="onCustomOutcome2()"> + Custom-outcome-2 + </button> + <button mat-button (click)="onCustomOutcome3()"> + Custom-outcome-3 + </button> + </adf-cloud-form-custom-outcomes> +</adf-cloud-form> +``` + +## See Also + +- [Form cloud component](form-cloud.component.md) diff --git a/docs/process-services-cloud/components/form-cloud.component.md b/docs/process-services-cloud/components/form-cloud.component.md index 039cb58ac9..3b75144917 100644 --- a/docs/process-services-cloud/components/form-cloud.component.md +++ b/docs/process-services-cloud/components/form-cloud.component.md @@ -32,6 +32,28 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl </adf-cloud-form> ``` +### Custom form outcomes template + +You can set the custom form outcomes using an `<adf-cloud-form-custom-outcomes>` element. + +```html +<adf-cloud-form .... > + + <adf-cloud-form-custom-outcomes> + <button mat-button (click)="onCustomOutcome1()"> + Custom-outcome-1 + </button> + <button mat-button (click)="onCustomOutcome2()"> + Custom-outcome-2 + </button> + <button mat-button (click)="onCustomOutcome3()"> + Custom-outcome-3 + </button> + </adf-cloud-form-custom-outcomes> + +</adf-cloud-form> +``` + ### Empty form template The template defined inside `empty-form` will be shown when no form definition is found: diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts new file mode 100644 index 0000000000..14ac5d655d --- /dev/null +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts @@ -0,0 +1,24 @@ +/*! + * @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 } from '@angular/core'; + +@Component({ + selector: 'adf-cloud-form-custom-outcomes', + template: '<ng-content></ng-content>' +}) +export class FormCustomOutcomesComponent {} diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html index 116db6e634..7eb246ab38 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.html @@ -35,6 +35,7 @@ </adf-form-renderer> </mat-card-content> <mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions"> + <ng-content select="adf-cloud-form-custom-outcomes"></ng-content> <button [id]="'adf-form-'+ outcome.name | formatSpace" *ngFor="let outcome of form.outcomes" [color]="getColorForOutcome(outcome.name)" mat-button [disabled]="!isOutcomeButtonEnabled(outcome)" [class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)" diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts index 2486aa13f0..59f0ef38b0 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -15,9 +15,12 @@ * limitations under the License. */ -import { SimpleChange } from '@angular/core'; +import { SimpleChange, DebugElement, CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Observable, of, throwError } from 'rxjs'; -import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService } from '@alfresco/adf-core'; +import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService, setupTestBed } from '@alfresco/adf-core'; +import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; import { FormCloudService } from '../services/form-cloud.service'; import { FormCloudComponent } from './form-cloud.component'; import { FormCloud } from '../models/form-cloud.model'; @@ -758,52 +761,61 @@ describe('FormCloudComponent', () => { radioFieldById = formFields.find((field) => field.id === 'radiobuttons1'); expect(radioFieldById.value).toBe('option_2'); }); +}); - it('should emit executeOutcome on [claim] outcome click', (done) => { - const formModel = new FormCloud(); - const outcome = new FormOutcomeModel(<any> formModel, { - id: FormCloud.CLAIM_OUTCOME, - name: 'CLAIM', - isSystem: true - }); +@Component({ + selector: 'adf-form-cloud-with-custom-outcomes', + template: ` + <adf-cloud-form #adfCloudForm> + <adf-cloud-form-custom-outcomes> + <button mat-button id="adf-custom-outcome-1" (click)="onButtonClick()"> + CUSTOM-BUTTON-1 + </button> + <button mat-button id="adf-custom-outcome-2" (click)="onButtonClick()"> + CUSTOM-BUTTON-2 + </button> + </adf-cloud-form-custom-outcomes> + </adf-cloud-form>` +}) - formComponent.form = formModel; - formComponent.executeOutcome.subscribe(() => { - done(); - }); +class FormCloudWithCustomOutComesComponent { - formComponent.onOutcomeClicked(outcome); + onButtonClick() {} +} + +describe('FormCloudWithCustomOutComesComponent', () => { + + let fixture: ComponentFixture<FormCloudWithCustomOutComesComponent>; + let component: FormCloudWithCustomOutComesComponent; + let debugElement: DebugElement; + + setupTestBed({ + imports: [ProcessServiceCloudTestingModule], + declarations: [FormCloudWithCustomOutComesComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] }); - it('should emit executeOutcome on [unclaim] outcome click', (done) => { - const formModel = new FormCloud(); - const outcome = new FormOutcomeModel(<any> formModel, { - id: FormCloud.UNCLAIM_OUTCOME, - name: 'UNCLAIM', - isSystem: true - }); - - formComponent.form = formModel; - formComponent.executeOutcome.subscribe(() => { - done(); - }); - - formComponent.onOutcomeClicked(outcome); + beforeEach(() => { + fixture = TestBed.createComponent(FormCloudWithCustomOutComesComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); }); - it('should emit executeOutcome on [cancel] outcome click', (done) => { - const formModel = new FormCloud(); - const outcome = new FormOutcomeModel(<any> formModel, { - id: FormCloud.CANCEL_OUTCOME, - name: 'CANCEL', - isSystem: true - }); + afterEach(() => { + fixture.destroy(); + }); - formComponent.form = formModel; - formComponent.executeOutcome.subscribe(() => { - done(); - }); + it('should create instance of FormCloudWithCustomOutComesComponent', () => { + expect(component instanceof FormCloudWithCustomOutComesComponent).toBe(true, 'should create FormCloudWithCustomOutComesComponent'); + }); - formComponent.onOutcomeClicked(outcome); + it('should be able to inject custom outcomes and click on custom outcomes', () => { + fixture.detectChanges(); + const cancelSpy = spyOn(component, 'onButtonClick').and.callThrough(); + const cancelBtn = debugElement.query(By.css('#adf-custom-outcome-1')); + cancelBtn.nativeElement.click(); + expect(cancelSpy).toHaveBeenCalled(); + expect(cancelBtn.nativeElement.innerText).toBe('CUSTOM-BUTTON-1'); }); }); diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts index 6d4f80ef89..69e61f9f30 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts @@ -53,18 +53,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { @Input() data: TaskVariableCloud[]; - /** Toggle rendering of the `Cancel` outcome button. */ - @Input() - showCancelButton = false; - - /** Toggle rendering of the `Claim` outcome button. */ - @Input() - showClaimButton = false; - - /** Toggle rendering of the `Unclaim` outcome button. */ - @Input() - showUnclaimButton = false; - /** Emitted when the form is submitted with the `Save` or custom outcomes. */ @Output() formSaved: EventEmitter<FormCloud> = new EventEmitter<FormCloud>(); @@ -168,7 +156,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { (data) => { this.data = data[1]; const parsedForm = this.parseForm(data[0]); - this.appendCustomOutcomes(parsedForm); this.visibilityService.refreshVisibility(<any> parsedForm); parsedForm.validateForm(); this.form = parsedForm; @@ -190,7 +177,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { .subscribe( (form) => { const parsedForm = this.parseForm(form); - this.appendCustomOutcomes(parsedForm); this.visibilityService.refreshVisibility(<any> parsedForm); parsedForm.validateForm(); this.form = parsedForm; @@ -333,39 +319,4 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges { protected storeFormAsMetadata() { } - - private appendCustomOutcomes(form: FormCloud): FormCloud { - - if (this.showClaimButton) { - const claimOutcome = new FormOutcomeModel(<any> form, { - id: FormCloud.CLAIM_OUTCOME, - name: 'CLAIM', - isSystem: true - }); - - form.outcomes.unshift(claimOutcome); - } - - if (this.showUnclaimButton) { - const unclaimOutcome = new FormOutcomeModel(<any> form, { - id: FormCloud.UNCLAIM_OUTCOME, - name: 'UNCLAIM', - isSystem: true - }); - - form.outcomes.unshift(unclaimOutcome); - } - - if (this.showCancelButton) { - const cancelOutcome = new FormOutcomeModel(<any> form, { - id: FormCloud.CANCEL_OUTCOME, - name: 'CANCEL', - isSystem: true - }); - - form.outcomes.unshift(cancelOutcome); - } - - return form; - } } diff --git a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts index ea3b216953..19c21a898c 100644 --- a/lib/process-services-cloud/src/lib/form/form-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/form/form-cloud.module.ts @@ -25,6 +25,7 @@ import { MaterialModule } from '../material.module'; import { FormCloudComponent } from './components/form-cloud.component'; import { FormDefinitionSelectorCloudComponent } from './components/form-definition-selector-cloud.component'; import { FormDefinitionSelectorCloudService } from './services/form-definition-selector-cloud.service'; +import { FormCustomOutcomesComponent } from './components/form-cloud-custom-outcomes.component'; @NgModule({ imports: [ @@ -38,13 +39,13 @@ import { FormDefinitionSelectorCloudService } from './services/form-definition-s FormBaseModule, CoreModule ], - declarations: [FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent], + declarations: [FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent, FormCustomOutcomesComponent], providers: [FormDefinitionSelectorCloudService], entryComponents: [ UploadCloudWidgetComponent ], exports: [ - FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent + FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent, FormCustomOutcomesComponent ] }) export class FormCloudModule { diff --git a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts index 57ade28cfe..56ab1a39fc 100644 --- a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts @@ -28,10 +28,6 @@ export class FormCloud { static COMPLETE_OUTCOME: string = '$complete'; static START_PROCESS_OUTCOME: string = '$startProcess'; - static CANCEL_OUTCOME: string = '$cancel'; - static CLAIM_OUTCOME: string = '$claim'; - static UNCLAIM_OUTCOME: string = '$unclaim'; - readonly id: string; nodeId: string; readonly name: string; diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html index 910ed18fd1..5aff40e02f 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.html @@ -7,13 +7,20 @@ [showValidationIcon]="showValidationIcon" [showCompleteButton]="canCompleteTask()" [showSaveButton]="canCompleteTask()" - [showCancelButton]="showCancelButton" - [showClaimButton]="canClaimTask()" - [showUnclaimButton]="canUnclaimTask()" - (executeOutcome)="onExecuteOutcome($event.outcome)" (formSaved)="onFormSaved($event)" (formCompleted)="onFormCompleted($event)" (formError)="onError($event)"> + <adf-cloud-form-custom-outcomes> + <button mat-button *ngIf="showCancelButton" id="adf-cloud-cancel-task" (click)="onCancelClick()"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL' | translate}} + </button> + <button mat-button *ngIf="canClaimTask()" adf-cloud-claim-task [appName]="appName" [taskId]="taskId" (success)="onClaimTask()"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM' | translate}} + </button> + <button mat-button *ngIf="canUnclaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId" (success)="onUnclaimTask()"> + {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM' | translate}} + </button> + </adf-cloud-form-custom-outcomes> </adf-cloud-form> <ng-template #withoutForm> diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts index 15202f0bdf..90ee8e16e1 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.spec.ts @@ -15,17 +15,17 @@ * limitations under the License. */ +import { DebugElement, CUSTOM_ELEMENTS_SCHEMA, SimpleChange, Component } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of } from 'rxjs'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { TaskCloudModule } from '../../task-cloud.module'; import { TaskDirectiveModule } from '../../directives/task-directive.module'; -import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { TaskFormCloudComponent } from './task-form-cloud.component'; -import { setupTestBed, IdentityUserService } from '@alfresco/adf-core'; import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import { TaskCloudService } from '../../services/task-cloud.service'; -import { of } from 'rxjs'; -import { DebugElement, CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; -import { By } from '@angular/platform-browser'; const taskDetails = { appName: 'simple-app', @@ -348,5 +348,94 @@ describe('TaskFormCloudComponent', () => { }); }); +}); +@Component({ + selector: 'adf-task-form-cloud-with-custom-outcomes', + template: ` + <adf-cloud-form #adfCloudForm> + <adf-cloud-form-custom-outcomes> + <button mat-button *ngIf="showCancelButton" id="adf-cloud-cancel-task" (click)="onCancel()"> + CANCEL + </button> + <button mat-button *ngIf="canClaimTask()" adf-cloud-claim-task [appName]="appName" [taskId]="taskId" (click)="onClaim()"> + CLAIM + </button> + <button mat-button *ngIf="canUnclaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId" (click)="onUnclaim()"> + UNCLAIM + </button> + </adf-cloud-form-custom-outcomes> + </adf-cloud-form>` +}) + +class TaskFormWithCustomOutComesComponent { + + appName = 'simple-app'; + taskId = 'mock-task-id'; + showCancelButton = true; + + canClaimTask() { return true; } + + canUnclaimTask() { return true; } + + onUnclaim() {} + + onClaim() {} + + onCancel() {} +} + +describe('TaskFormWithCustomOutComesComponent', () => { + + let fixture: ComponentFixture<TaskFormWithCustomOutComesComponent>; + let component: TaskFormWithCustomOutComesComponent; + let debugElement: DebugElement; + + setupTestBed({ + imports: [ProcessServiceCloudTestingModule, TaskCloudModule, TaskDirectiveModule], + declarations: [TaskFormWithCustomOutComesComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TaskFormWithCustomOutComesComponent); + component = fixture.componentInstance; + debugElement = fixture.debugElement; + fixture.detectChanges(); + }); + + afterEach(() => { + fixture.destroy(); + }); + + it('should create instance of TaskFormWithCustomOutComesComponent', () => { + expect(component instanceof TaskFormWithCustomOutComesComponent).toBe(true, 'should create TaskFormWithCustomOutComesComponent'); + }); + + it('should be able to display and click on cancel button', () => { + fixture.detectChanges(); + const cancelSpy = spyOn(component, 'onCancel').and.callThrough(); + const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); + cancelBtn.nativeElement.click(); + expect(cancelSpy).toHaveBeenCalled(); + expect(cancelBtn.nativeElement.innerText).toBe('CANCEL'); + }); + + it('should be able to display and click on claim button', () => { + fixture.detectChanges(); + const claimSpy = spyOn(component, 'onClaim').and.callThrough(); + const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); + claimBtn.nativeElement.click(); + expect(claimSpy).toHaveBeenCalled(); + expect(claimBtn.nativeElement.innerText).toBe('CLAIM'); + }); + + it('should be able to display and click on unclaim button', () => { + fixture.detectChanges(); + const unClaimSpy = spyOn(component, 'onUnclaim').and.callThrough(); + const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); + unclaimBtn.nativeElement.click(); + expect(unClaimSpy).toHaveBeenCalled(); + expect(unclaimBtn.nativeElement.innerText).toBe('UNCLAIM'); + }); }); diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index 8a5f5b9568..34ff76b407 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -22,7 +22,6 @@ import { import { FormCloud } from '../../../form/models/form-cloud.model'; import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import { TaskCloudService } from '../../services/task-cloud.service'; -import { IdentityUserService, FormOutcomeModel } from '@alfresco/adf-core'; @Component({ selector: 'adf-cloud-task-form', @@ -90,8 +89,7 @@ export class TaskFormCloudComponent implements OnChanges { taskDetails: TaskDetailsCloudModel; constructor( - private taskCloudService: TaskCloudService, - private identityUserService: IdentityUserService) { + private taskCloudService: TaskCloudService) { } ngOnChanges(changes: SimpleChanges) { @@ -132,7 +130,7 @@ export class TaskFormCloudComponent implements OnChanges { } isReadOnly(): boolean { - return this.readOnly || this.taskDetails.isCompleted(); + return this.readOnly || !this.taskCloudService.canCompleteTask(this.taskDetails); } onCompleteTask() { @@ -151,31 +149,6 @@ export class TaskFormCloudComponent implements OnChanges { this.cancelClick.emit(this.taskId); } - claimTask() { - const currentUser = this.identityUserService.getCurrentUserInfo().username; - this.taskCloudService.claimTask(this.appName, this.taskId, currentUser).subscribe( - () => { - this.taskClaimed.emit(this.taskId); - }); - } - - unclaimTask() { - this.taskCloudService.unclaimTask(this.appName, this.taskId).subscribe( - () => { - this.taskUnclaimed.emit(this.taskId); - }); - } - - onExecuteOutcome(outcome: FormOutcomeModel) { - if (outcome.id === FormCloud.CANCEL_OUTCOME) { - this.onCancelClick(); - } else if (outcome.id === FormCloud.CLAIM_OUTCOME) { - this.claimTask(); - } else if (outcome.id === FormCloud.UNCLAIM_OUTCOME) { - this.unclaimTask(); - } - } - onFormSaved(form: FormCloud) { this.formSaved.emit(form); } From a3487cd3b3933edcabb7a536ff38275012a40e8a Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Tue, 30 Apr 2019 11:05:25 +0100 Subject: [PATCH 184/208] [ADF-4460] Fix for empty value upload widget on a form (#4670) --- .../community/community-task-details-cloud.component.html | 4 ++-- lib/core/form/components/widgets/core/form-field.model.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html index 541e5c8549..17d4a65d03 100644 --- a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html +++ b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.html @@ -3,7 +3,7 @@ <div fxLayout="column" fxFill fxLayoutGap="2px"> <div fxLayout="row" fxFill> <div fxLayout="column" fxFlex="80%"> - <adf-task-form-cloud + <adf-cloud-task-form [appName]="''" [taskId]="taskId" (cancelClick)="goBack()" @@ -11,7 +11,7 @@ (taskCompleted)="onTaskCompleted()" (taskUnclaimed)="onUnclaimTask()" (formSaved)="onFormSaved()"> - </adf-task-form-cloud> + </adf-cloud-task-form> </div> <adf-cloud-task-header fxFlex [appName]="''" diff --git a/lib/core/form/components/widgets/core/form-field.model.ts b/lib/core/form/components/widgets/core/form-field.model.ts index c3c3957e16..9ade572e7a 100644 --- a/lib/core/form/components/widgets/core/form-field.model.ts +++ b/lib/core/form/components/widgets/core/form-field.model.ts @@ -378,7 +378,7 @@ export class FormFieldModel extends FormWidgetModel { if (this.value && this.value.length > 0) { this.form.values[this.id] = this.value.map((elem) => elem.id).join(','); } else { - this.form.values[this.id] = []; + this.form.values[this.id] = null; } break; case FormFieldTypes.TYPEAHEAD: From 2edee23bdd40f5e965c9320e27b9b36db3feed43 Mon Sep 17 00:00:00 2001 From: gmandakini <45559635+gmandakini@users.noreply.github.com> Date: Tue, 30 Apr 2019 14:51:29 +0100 Subject: [PATCH 185/208] automated ADF-4198 - Escape key doesn't work to close the user profile dialog. (#4671) --- e2e/core/user-info-component-cloud.e2e.ts | 2 +- e2e/core/user-info-component.e2e.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/core/user-info-component-cloud.e2e.ts b/e2e/core/user-info-component-cloud.e2e.ts index 9b43ce973a..d9614f3308 100644 --- a/e2e/core/user-info-component-cloud.e2e.ts +++ b/e2e/core/user-info-component-cloud.e2e.ts @@ -56,7 +56,7 @@ describe('User Info - SSO', () => { expect(userInfoPage.getSsoTitle()).toEqual(identityUser.firstName + ' ' + identityUser.lastName); expect(userInfoPage.getSsoEmail()).toEqual(identityUser.email); userInfoPage.closeUserProfile(); - + userInfoPage.dialogIsNotDisplayed(); }); }); diff --git a/e2e/core/user-info-component.e2e.ts b/e2e/core/user-info-component.e2e.ts index f19561679c..e7b3e35e22 100644 --- a/e2e/core/user-info-component.e2e.ts +++ b/e2e/core/user-info-component.e2e.ts @@ -125,6 +125,7 @@ describe('User Info component', () => { userInfoPage.APSProfileImageNotDisplayed(); userInfoPage.ACSProfileImageNotDisplayed(); userInfoPage.closeUserProfile(); + userInfoPage.dialogIsNotDisplayed(); }); it('[C260115] Should display UserInfo when Process Services is enabled and Content Services is disabled', () => { From 55113f37b651c126e7b2e847144adb1972a50f5b Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Tue, 30 Apr 2019 14:53:37 +0100 Subject: [PATCH 186/208] [ADF-4444] drag and drop fixes (#4674) * more granular control over drag and drop * fix performance, internal drop-zone directive --- .../datatable-dnd.component.html | 2 + .../drag-and-drop/datatable-dnd.component.ts | 4 + docs/core/components/datatable.component.md | 35 ++++++++ .../directives/file-draggable.directive.ts | 2 +- .../datatable/datatable.component.html | 6 +- .../datatable/datatable.component.ts | 36 -------- .../datatable/drop-zone.directive.ts | 90 +++++++++++++++++++ lib/core/datatable/datatable.module.ts | 7 +- lib/core/datatable/public-api.ts | 2 +- 9 files changed, 140 insertions(+), 44 deletions(-) create mode 100644 lib/core/datatable/components/datatable/drop-zone.directive.ts diff --git a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html index 6342702eac..d623895216 100644 --- a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html +++ b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.html @@ -1,6 +1,8 @@ <h1>DataTable Drag and Drop Demo</h1> <div data-automation-id="datatable" + (header-dragover)="onDragOver($event)" (header-drop)="onDrop($event)" + (cell-dragover)="onDragOver($event)" (cell-drop)="onDrop($event)"> <adf-datatable [data]="data"></adf-datatable> </div> diff --git a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts index 5b4f90e3e5..4193026c6d 100644 --- a/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts +++ b/demo-shell/src/app/components/datatable/drag-and-drop/datatable-dnd.component.ts @@ -88,6 +88,10 @@ export class DataTableDnDComponent implements OnInit { this.data.setSorting(new DataSorting('id', 'asc')); } + onDragOver(event: CustomEvent) { + event.preventDefault(); + } + onDrop(event: DataTableDropEvent) { event.preventDefault(); diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 7a463c3ba3..45f125f9a5 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -401,7 +401,9 @@ These events bubble up the component tree and can be handled by any parent compo | row-unselect | Raised after user unselects a row | | row-keyup | Raised on the 'keyup' event for the focused row. | | sorting-changed | Raised after user clicks the sortable column header. | +| header-dragover | Raised when dragging content over the header. | | header-drop | Raised when data is dropped on the column header. | +| cell-dragover | Raised when dragging data over the cell. | | cell-drop | Raised when data is dropped on the column cell. | #### Drop Events @@ -424,6 +426,39 @@ export interface DataTableDropEvent { Note that `event` is the original `drop` event, and `row` is not available for Header events. +According to the [HTML5 Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API), +you need to handle both `dragover` and `drop` events to handle the drop correctly. + +Given that DataTable raises bubbling DOM events, you can handle drop behavior from the parent elements as well: + +```html +<div + (header-dragover)="onDragOver($event)" + (header-drop)="onDrop($event)" + (cell-dragover)="onDragOver($event)" + (cell-drop)="onDrop($event)"> + + <adf-datatable [data]="data"> + </adf-datatable> +</div> +``` + +Where the implementation of the handlers can look like following: + +```ts +onDragOver(event: CustomEvent) { + // always needed for custom drop handlers (!) + event.preventDefault(); +} + +onDrop(event: DataTableDropEvent) { + event.preventDefault(); + + const { column, row, target } = event.detail; + // do something with the details +} +``` + #### Example ```html diff --git a/lib/content-services/upload/directives/file-draggable.directive.ts b/lib/content-services/upload/directives/file-draggable.directive.ts index ceb3d6f62b..eea5b2637b 100644 --- a/lib/content-services/upload/directives/file-draggable.directive.ts +++ b/lib/content-services/upload/directives/file-draggable.directive.ts @@ -24,7 +24,7 @@ import { Directive, ElementRef, EventEmitter, Input, NgZone, OnDestroy, OnInit, * Directive selectors without adf- prefix will be deprecated on 3.0.0 */ @Directive({ - selector: '[adf-file-draggable], [file-draggable]' + selector: '[adf-file-draggable]' }) export class FileDraggableDirective implements OnInit, OnDestroy { diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index e005de1475..4c42a77fc8 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -26,8 +26,7 @@ role="columnheader" tabindex="0" title="{{ col.title | translate }}" - (dragover)="onDragOver($event)" - (drop)="onHeaderDrop($event, col)"> + adf-drop-zone dropTarget="header" [dropColumn]="col"> <span *ngIf="col.srTitle" class="adf-sr-only">{{ col.srTitle | translate }}</span> <span *ngIf="col.title" class="adf-datatable-cell-value">{{ col.title | translate}}</span> </div> @@ -98,8 +97,7 @@ (keydown.enter)="onEnterKeyPressed(row, $event)" [adf-context-menu]="getContextMenuActions(row, col)" [adf-context-menu-enabled]="contextMenu" - (dragover)="onDragOver($event)" - (drop)="onCellDrop($event, col, row)"> + adf-drop-zone dropTarget="cell" [dropColumn]="col" [dropRow]="row"> <div *ngIf="!col.template" class="adf-datatable-cell-container"> <ng-container [ngSwitch]="col.type"> <div *ngSwitchCase="'image'" class="adf-cell-value"> diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 8dd36c03c0..82785b92af 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -701,42 +701,6 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, const name = this.getNameColumnValue(); return name ? row.getValue(name.key) : ''; } - - onDragOver(event: Event) { - event.preventDefault(); - } - - onHeaderDrop(event: Event, column: DataColumn) { - event.preventDefault(); - - this.elementRef.nativeElement.dispatchEvent( - new CustomEvent('header-drop', { - detail: { - target: 'header', - event, - column - }, - bubbles: true - }) - ); - } - - onCellDrop(event: Event, column: DataColumn, row: DataRow) { - event.preventDefault(); - - this.elementRef.nativeElement.dispatchEvent( - new CustomEvent('cell-drop', { - detail: { - target: 'cell', - event, - column, - row - }, - bubbles: true - }) - ); - } - } export interface DataTableDropEvent { diff --git a/lib/core/datatable/components/datatable/drop-zone.directive.ts b/lib/core/datatable/components/datatable/drop-zone.directive.ts new file mode 100644 index 0000000000..9097e02d80 --- /dev/null +++ b/lib/core/datatable/components/datatable/drop-zone.directive.ts @@ -0,0 +1,90 @@ +/*! + * @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 { Directive, Input, ElementRef, NgZone, OnInit, OnDestroy } from '@angular/core'; +import { DataRow } from '../../data/data-row.model'; +import { DataColumn } from '../../data/data-column.model'; + +@Directive({ + selector: '[adf-drop-zone]' +}) +export class DropZoneDirective implements OnInit, OnDestroy { + private element: HTMLElement; + + @Input() + dropTarget: 'header' | 'cell' = 'cell'; + + @Input() + dropRow: DataRow; + + @Input() + dropColumn: DataColumn; + + constructor(elementRef: ElementRef, private ngZone: NgZone) { + this.element = elementRef.nativeElement; + } + + ngOnInit() { + this.ngZone.runOutsideAngular(() => { + this.element.addEventListener('dragover', this.onDragOver.bind(this)); + this.element.addEventListener('drop', this.onDrop.bind(this)); + }); + } + + ngOnDestroy() { + this.element.removeEventListener('dragover', this.onDragOver); + this.element.removeEventListener('drop', this.onDrop); + } + + onDragOver(event: Event) { + const domEvent = new CustomEvent(`${this.dropTarget}-dragover`, { + detail: { + target: this.dropTarget, + event, + column: this.dropColumn, + row: this.dropRow + }, + bubbles: true + }); + + this.element.dispatchEvent(domEvent); + + if (domEvent.defaultPrevented) { + event.preventDefault(); + event.stopPropagation(); + } + } + + onDrop(event: Event) { + const domEvent = new CustomEvent(`${this.dropTarget}-drop`, { + detail: { + target: this.dropTarget, + event, + column: this.dropColumn, + row: this.dropRow + }, + bubbles: true + }); + + this.element.dispatchEvent(domEvent); + + if (domEvent.defaultPrevented) { + event.preventDefault(); + event.stopPropagation(); + } + } +} diff --git a/lib/core/datatable/datatable.module.ts b/lib/core/datatable/datatable.module.ts index 3b1c21abd2..23611bc2e1 100644 --- a/lib/core/datatable/datatable.module.ts +++ b/lib/core/datatable/datatable.module.ts @@ -42,6 +42,7 @@ import { CustomLoadingContentTemplateDirective } from './directives/custom-loadi import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive'; import { JsonCellComponent } from './components/datatable/json-cell.component'; import { ClipboardModule } from '../clipboard/clipboard.module'; +import { DropZoneDirective } from './components/datatable/drop-zone.directive'; @NgModule({ imports: [ @@ -70,7 +71,8 @@ import { ClipboardModule } from '../clipboard/clipboard.module'; LoadingContentTemplateDirective, CustomEmptyContentTemplateDirective, CustomLoadingContentTemplateDirective, - CustomNoPermissionTemplateDirective + CustomNoPermissionTemplateDirective, + DropZoneDirective ], exports: [ DataTableComponent, @@ -88,7 +90,8 @@ import { ClipboardModule } from '../clipboard/clipboard.module'; LoadingContentTemplateDirective, CustomEmptyContentTemplateDirective, CustomLoadingContentTemplateDirective, - CustomNoPermissionTemplateDirective + CustomNoPermissionTemplateDirective, + DropZoneDirective ] }) diff --git a/lib/core/datatable/public-api.ts b/lib/core/datatable/public-api.ts index 94a15b276c..35551ba887 100644 --- a/lib/core/datatable/public-api.ts +++ b/lib/core/datatable/public-api.ts @@ -28,7 +28,7 @@ export * from './data/object-datacolumn.model'; export * from './components/datatable/data-cell.event'; export * from './components/datatable/data-row-action.event'; - +export * from './components/datatable/drop-zone.directive'; export * from './components/datatable/datatable-cell.component'; export * from './components/datatable/datatable.component'; export * from './components/datatable/date-cell.component'; From 0c7581acba13c8f0b6577aba3a484432c492c235 Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Wed, 1 May 2019 10:28:41 +0100 Subject: [PATCH 187/208] [ADF-4422] Fix unit/e2e tests (#4673) * [ADF-4422] Unexclude C291783 e2e test * [ADF-4422] Fix Edit process cloud unit test * [ADF-4422] Fix spy not been called * Fix unit test --- e2e/process-services-cloud/process-custom-filters.e2e.ts | 2 +- .../components/edit-process-filter-cloud.component.spec.ts | 4 ++-- .../components/people-cloud/people-cloud.component.spec.ts | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/e2e/process-services-cloud/process-custom-filters.e2e.ts b/e2e/process-services-cloud/process-custom-filters.e2e.ts index 9dc7dda83a..0da87e9f49 100644 --- a/e2e/process-services-cloud/process-custom-filters.e2e.ts +++ b/e2e/process-services-cloud/process-custom-filters.e2e.ts @@ -123,7 +123,7 @@ describe('Process list cloud', () => { }); }); - xit('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async () => { + it('[C291783] Should display processes ordered by id when Id is selected from sort dropdown', async () => { processCloudDemoPage.editProcessFilterCloudComponent().clickCustomiseFilterHeader().setStatusFilterDropDown('RUNNING') .setSortFilterDropDown('Id').setOrderFilterDropDown('ASC'); processCloudDemoPage.processListCloudComponent().getDataTable().checkSpinnerIsDisplayed().checkSpinnerIsNotDisplayed(); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts index ccb5372b6b..65af081f40 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts @@ -252,7 +252,7 @@ describe('EditProcessFilterCloudComponent', () => { })); }); - it('should able to filter filterProperties when input is defined', async(() => { + it('should be able to filter filterProperties when input is defined', async(() => { fixture.detectChanges(); component.filterProperties = ['appName', 'processName']; fixture.detectChanges(); @@ -261,7 +261,7 @@ describe('EditProcessFilterCloudComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(component.processFilterProperties.length).toEqual(1); + expect(component.processFilterProperties.length).toEqual(2); expect(component.processFilterProperties[0].key).toEqual('appName'); expect(component.processFilterProperties[1].key).toEqual('processName'); }); diff --git a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts index 01a171afae..f2636fe43d 100644 --- a/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.spec.ts @@ -514,14 +514,15 @@ describe('PeopleCloudComponent', () => { })); it('should emit removeUser when a selected user is removed if mode=multiple', async(() => { - const removeUserSpy = spyOn(component.removeUser, 'emit'); + spyOn(component.removeUser, 'emit'); component.mode = 'multiple'; fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); const removeIcon = fixture.debugElement.query(By.css('mat-chip mat-icon')); removeIcon.nativeElement.click(); - expect(removeUserSpy).toHaveBeenCalled(); + fixture.detectChanges(); + expect(component.removeUser.emit).toHaveBeenCalled(); }); })); From 7016dabb6cc8dcf39cbc320a6184e81098fc9815 Mon Sep 17 00:00:00 2001 From: Deepak Paul <deepak.paul@muraai.com> Date: Wed, 1 May 2019 17:32:16 +0530 Subject: [PATCH 188/208] [ADF-4454] Map upload field to UploadCloudWidget in task cloud form (#4672) * [ADF-4454] Moved upload widget maping to task form * Update community-task-details-cloud.component.ts --- .../community/community-task-details-cloud.component.ts | 6 +----- .../components/cloud/task-details-cloud-demo.component.ts | 5 +---- .../task/task-form/components/task-form-cloud.component.ts | 6 +++++- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts index b08e56669b..91ffdf593f 100644 --- a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts +++ b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.ts @@ -17,8 +17,7 @@ import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; -import { NotificationService, FormRenderingService } from '@alfresco/adf-core'; +import { NotificationService } from '@alfresco/adf-core'; @Component({ templateUrl: './community-task-details-cloud.component.html', @@ -32,7 +31,6 @@ export class CommunityTaskDetailsCloudDemoComponent { constructor( private route: ActivatedRoute, private router: Router, - private formRenderingService: FormRenderingService, private notificationService: NotificationService ) { this.route.params.subscribe((params) => { @@ -41,8 +39,6 @@ export class CommunityTaskDetailsCloudDemoComponent { this.route.parent.params.subscribe((params) => { this.appName = params.appName; }); - this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); - } isTaskValid(): boolean { diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts index d003313993..ec04eca612 100644 --- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts @@ -17,8 +17,7 @@ import { Component } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { UploadCloudWidgetComponent } from '@alfresco/adf-process-services-cloud'; -import { NotificationService, FormRenderingService } from '@alfresco/adf-core'; +import { NotificationService } from '@alfresco/adf-core'; @Component({ templateUrl: './task-details-cloud-demo.component.html', @@ -32,7 +31,6 @@ export class TaskDetailsCloudDemoComponent { constructor( private route: ActivatedRoute, private router: Router, - private formRenderingService: FormRenderingService, private notificationService: NotificationService ) { this.route.params.subscribe((params) => { @@ -41,7 +39,6 @@ export class TaskDetailsCloudDemoComponent { this.route.parent.params.subscribe((params) => { this.appName = params.appName; }); - this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); } diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index 34ff76b407..962eaaca4b 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -22,6 +22,8 @@ import { import { FormCloud } from '../../../form/models/form-cloud.model'; import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import { TaskCloudService } from '../../services/task-cloud.service'; +import { FormRenderingService } from '@alfresco/adf-core'; +import { UploadCloudWidgetComponent } from '../../../form/components/upload-cloud.widget'; @Component({ selector: 'adf-cloud-task-form', @@ -89,7 +91,9 @@ export class TaskFormCloudComponent implements OnChanges { taskDetails: TaskDetailsCloudModel; constructor( - private taskCloudService: TaskCloudService) { + private taskCloudService: TaskCloudService, + private formRenderingService: FormRenderingService) { + this.formRenderingService.setComponentTypeResolver('upload', () => UploadCloudWidgetComponent, true); } ngOnChanges(changes: SimpleChanges) { From a172543b8fb0de9d2cad5afaf3dfe33b1d3b0f4b Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Wed, 1 May 2019 14:12:09 +0100 Subject: [PATCH 189/208] [ADF-4455] Fix whitespaces trim in multivalue metadata field (#4663) --- .../card-view-textitem/card-view-textitem.component.ts | 6 +++--- lib/core/pipes/multi-value.pipe.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts index 2b3108cec2..0ae8acd7ea 100644 --- a/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts +++ b/lib/core/card-view/components/card-view-textitem/card-view-textitem.component.ts @@ -107,11 +107,11 @@ export class CardViewTextItemComponent implements OnChanges { } prepareValueForUpload(property: CardViewTextItemModel, value: string): string | string [] { - const listOfValues = value; if (property.multivalued) { - return listOfValues.split(this.valueSeparator); + const listOfValues = value.split(this.valueSeparator.trim()).map((item) => item.trim()); + return listOfValues; } - return listOfValues; + return value; } onTextAreaInputChange() { diff --git a/lib/core/pipes/multi-value.pipe.ts b/lib/core/pipes/multi-value.pipe.ts index a75a2959f0..608b3b56d5 100644 --- a/lib/core/pipes/multi-value.pipe.ts +++ b/lib/core/pipes/multi-value.pipe.ts @@ -25,8 +25,8 @@ export class MultiValuePipe implements PipeTransform { transform(values: string | string [], valueSeparator: string = MultiValuePipe.DEFAULT_SEPARATOR): string { if (values && values instanceof Array) { - values.map((value) => value.trim()); - return values.join(valueSeparator); + const valueList = values.map((value) => value.trim()); + return valueList.join(valueSeparator); } return <string> values; From 1afcfa1d5a0c19fd77f463d193584ec12686cf11 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Wed, 1 May 2019 15:52:06 +0100 Subject: [PATCH 190/208] [LOC-119] i18n 3.2.0 (#4678) * i18n 3.2.0 * i18n 3.2.0 * i18n 3.2.0 --- demo-shell/resources/i18n/ar.json | 11 +- demo-shell/resources/i18n/cs.json | 324 +++++++++++++ demo-shell/resources/i18n/da.json | 324 +++++++++++++ demo-shell/resources/i18n/de.json | 7 +- demo-shell/resources/i18n/es.json | 7 +- demo-shell/resources/i18n/fi.json | 324 +++++++++++++ demo-shell/resources/i18n/fr.json | 7 +- demo-shell/resources/i18n/it.json | 7 +- demo-shell/resources/i18n/ja.json | 7 +- demo-shell/resources/i18n/nb.json | 7 +- demo-shell/resources/i18n/nl.json | 7 +- demo-shell/resources/i18n/pl.json | 324 +++++++++++++ demo-shell/resources/i18n/pt-BR.json | 7 +- demo-shell/resources/i18n/ru.json | 9 +- demo-shell/resources/i18n/sv.json | 324 +++++++++++++ demo-shell/resources/i18n/zh-CN.json | 7 +- demo-shell/src/app.config.json | 20 + lib/content-services/i18n/ar.json | 6 +- lib/content-services/i18n/cs.json | 366 +++++++++++++++ lib/content-services/i18n/da.json | 366 +++++++++++++++ lib/content-services/i18n/de.json | 6 +- lib/content-services/i18n/es.json | 6 +- lib/content-services/i18n/fi.json | 366 +++++++++++++++ lib/content-services/i18n/fr.json | 6 +- lib/content-services/i18n/it.json | 8 +- lib/content-services/i18n/ja.json | 6 +- lib/content-services/i18n/nb.json | 6 +- lib/content-services/i18n/nl.json | 6 +- lib/content-services/i18n/pl.json | 366 +++++++++++++++ lib/content-services/i18n/pt-BR.json | 6 +- lib/content-services/i18n/ru.json | 10 +- lib/content-services/i18n/sv.json | 366 +++++++++++++++ lib/content-services/i18n/zh-CN.json | 6 +- lib/core/i18n/ar.json | 40 ++ lib/core/i18n/cs.json | 433 ++++++++++++++++++ lib/core/i18n/da.json | 433 ++++++++++++++++++ lib/core/i18n/de.json | 40 ++ lib/core/i18n/en.json | 2 +- lib/core/i18n/es.json | 40 ++ lib/core/i18n/fi.json | 433 ++++++++++++++++++ lib/core/i18n/fr.json | 40 ++ lib/core/i18n/it.json | 40 ++ lib/core/i18n/ja.json | 40 ++ lib/core/i18n/nb.json | 40 ++ lib/core/i18n/nl.json | 40 ++ lib/core/i18n/pl.json | 433 ++++++++++++++++++ lib/core/i18n/pt-BR.json | 40 ++ lib/core/i18n/ru.json | 44 +- lib/core/i18n/sv.json | 433 ++++++++++++++++++ lib/core/i18n/zh-CN.json | 40 ++ lib/insights/i18n/cs.json | 51 +++ lib/insights/i18n/da.json | 51 +++ lib/insights/i18n/fi.json | 51 +++ lib/insights/i18n/pl.json | 51 +++ lib/insights/i18n/sv.json | 51 +++ .../src/lib/i18n/ar.json | 32 +- .../src/lib/i18n/cs.json | 245 ++++++++++ .../src/lib/i18n/da.json | 245 ++++++++++ .../src/lib/i18n/de.json | 34 +- .../src/lib/i18n/en.json | 2 +- .../src/lib/i18n/es.json | 32 +- .../src/lib/i18n/fi.json | 245 ++++++++++ .../src/lib/i18n/fr.json | 34 +- .../src/lib/i18n/it.json | 34 +- .../src/lib/i18n/ja.json | 34 +- .../src/lib/i18n/nb.json | 32 +- .../src/lib/i18n/nl.json | 32 +- .../src/lib/i18n/pl.json | 245 ++++++++++ .../src/lib/i18n/pt-BR.json | 32 +- .../src/lib/i18n/ru.json | 42 +- .../src/lib/i18n/sv.json | 245 ++++++++++ .../src/lib/i18n/zh-CN.json | 32 +- lib/process-services/i18n/ar.json | 2 +- lib/process-services/i18n/cs.json | 333 ++++++++++++++ lib/process-services/i18n/da.json | 333 ++++++++++++++ lib/process-services/i18n/de.json | 6 +- lib/process-services/i18n/es.json | 2 +- lib/process-services/i18n/fi.json | 333 ++++++++++++++ lib/process-services/i18n/fr.json | 6 +- lib/process-services/i18n/it.json | 6 +- lib/process-services/i18n/ja.json | 6 +- lib/process-services/i18n/nb.json | 4 +- lib/process-services/i18n/nl.json | 2 +- lib/process-services/i18n/pl.json | 333 ++++++++++++++ lib/process-services/i18n/pt-BR.json | 2 +- lib/process-services/i18n/ru.json | 4 +- lib/process-services/i18n/sv.json | 333 ++++++++++++++ lib/process-services/i18n/zh-CN.json | 4 +- 88 files changed, 9668 insertions(+), 129 deletions(-) create mode 100644 demo-shell/resources/i18n/cs.json create mode 100644 demo-shell/resources/i18n/da.json create mode 100644 demo-shell/resources/i18n/fi.json create mode 100644 demo-shell/resources/i18n/pl.json create mode 100644 demo-shell/resources/i18n/sv.json create mode 100644 lib/content-services/i18n/cs.json create mode 100644 lib/content-services/i18n/da.json create mode 100644 lib/content-services/i18n/fi.json create mode 100644 lib/content-services/i18n/pl.json create mode 100644 lib/content-services/i18n/sv.json create mode 100644 lib/core/i18n/cs.json create mode 100644 lib/core/i18n/da.json create mode 100644 lib/core/i18n/fi.json create mode 100644 lib/core/i18n/pl.json create mode 100644 lib/core/i18n/sv.json create mode 100644 lib/insights/i18n/cs.json create mode 100644 lib/insights/i18n/da.json create mode 100644 lib/insights/i18n/fi.json create mode 100644 lib/insights/i18n/pl.json create mode 100644 lib/insights/i18n/sv.json create mode 100644 lib/process-services-cloud/src/lib/i18n/cs.json create mode 100644 lib/process-services-cloud/src/lib/i18n/da.json create mode 100644 lib/process-services-cloud/src/lib/i18n/fi.json create mode 100644 lib/process-services-cloud/src/lib/i18n/pl.json create mode 100644 lib/process-services-cloud/src/lib/i18n/sv.json create mode 100644 lib/process-services/i18n/cs.json create mode 100644 lib/process-services/i18n/da.json create mode 100644 lib/process-services/i18n/fi.json create mode 100644 lib/process-services/i18n/pl.json create mode 100644 lib/process-services/i18n/sv.json diff --git a/demo-shell/resources/i18n/ar.json b/demo-shell/resources/i18n/ar.json index 333cddd0a2..1d182a8f2c 100644 --- a/demo-shell/resources/i18n/ar.json +++ b/demo-shell/resources/i18n/ar.json @@ -7,7 +7,7 @@ "VERSIONS": "الإصدارات" }, "HOME": { - "TITLE": "Alfresco المكونات الزاوّية لـ", + "TITLE": "المكونات الزاوّية لـ Alfresco", "DOCUMENTATION": "الوثائق" }, "LOGOUT": { @@ -57,6 +57,7 @@ "APP_NAME": "تطبيق ADF التوضيحي", "HOME": "رئيسية", "NODE-SELECTOR": "محدد العقدة", + "SITES": "المواقع", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "مسار التنقل", "NOTIFICATIONS": "إعلامات", @@ -93,7 +94,8 @@ "ICONS": "أيقونات", "PEOPLE_GROUPS_CLOUD": "سحابة الأشخاص/المجموعة", "PEOPLE_CLOUD": "مكون سحابة الأشخاص", - "GROUPS_CLOUD": "مكون سحابة المجموعة" + "GROUPS_CLOUD": "مكون سحابة المجموعة", + "CONFIRM-DIALOG": "مربع حوار التأكيد" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "تحديد متعدد", "TESTING_MODE": "وضع الاختبار", "SELECTION_MODE": "وضع التحديد", - "TASK_DETAILS_REDIRECTION": "عرض تفاصيل المهمة عند النقر فوق المهمة" + "TASK_DETAILS_REDIRECTION": "عرض تفاصيل المهمة عند النقر فوق المهمة", + "PROCESS_DETAILS_REDIRECTION": "عرض تفاصيل العملية عند النقر على العملية" } -} +} \ No newline at end of file diff --git a/demo-shell/resources/i18n/cs.json b/demo-shell/resources/i18n/cs.json new file mode 100644 index 0000000000..8bba6ce832 --- /dev/null +++ b/demo-shell/resources/i18n/cs.json @@ -0,0 +1,324 @@ +{ + "APP": { + "INFO_DRAWER": { + "TITLE": "Podrobnosti", + "COMMENTS": "Poznámky", + "PROPERTIES": "Vlastnosti", + "VERSIONS": "Verze" + }, + "HOME": { + "TITLE": "Součásti Angular pro produkty Alfresco", + "DOCUMENTATION": "Dokumentace" + }, + "LOGOUT": { + "TITLE": "Stránka pro odhlášení", + "SUB_TITLE": "Byli jste odhlášeni", + "LOGIN": "Přihlášení", + "HOME": "Domů" + }, + "ADF_VERSION_MANAGER": { + "ALLOW_DELETE": "Povolit odstranění", + "SHOW_COMMENTS": "Zobrazit komentáře k verzím", + "ALLOW_DOWNLOAD": "Povolit stažení verze", + "READ_ONLY": "Pouze ke čtení", + "COMMENTS": "Zobrazit komentáře" + }, + "PERSONAL-FILES": "Osobní soubory", + "WARN-MULTIPLE-UPLOADS": "Zobrazit upozornění v případě hromadného odesílání", + "CUSTOM-PERMISSION-MESSAGE": "Povolit přizpůsobené oznámení o oprávnění", + "MEDIUM-TIME-FORMAT": "Povolit střední formát času v seznamu dokumentů", + "SEARCH": { + "RADIO": { + "NONE": "Žádné", + "ALL": "Vše", + "FOLDER": "Složka", + "DOCUMENT": "Dokument" + } + } + }, + "title": "Vítejte", + "VERSION": { + "NO_PERMISSION": "Nemáte potřebná oprávnění pro správu verzí tohoto obsahu", + "NO_PERMISSION_EVENT": "Nemáte oprávnění „${event.permission}“ potřebná k použití akce „${event.action}“ pro „${event.type}“", + "CHOOSE_FILE": "Vyberte soubor, jehož verze si chcete prohlédnout", + "DIALOG": { + "CLOSE": "Zavřít", + "TITLE": "Spravovat verze" + } + }, + "METADATA": { + "DIALOG": { + "CLOSE": "Zavřít", + "TITLE": "Metadata" + } + }, + "APP_LAYOUT": { + "APP": "Aplikace", + "APP_NAME": "Ukázková aplikace ADF", + "HOME": "Domů", + "NODE-SELECTOR": "Selektor uzlu", + "SITES": "Místa", + "CONTENT_SERVICES": "Content Services", + "BREADCRUMB": "Popis cesty", + "NOTIFICATIONS": "Upozornění", + "TASK_LIST": "Seznam úkolů", + "PROCESS_LIST": "Seznam procesů", + "PROCESS_CLOUD": "Activiti Cloud", + "CARD_VIEW": "Zobrazení karty", + "PROCESS_SERVICES": "Process Services", + "LOGIN": "Přihlášení", + "CUSTOM_SOURCES": "Vlastní zdroje", + "DATATABLE": "Datová tabulka", + "DATATABLE_LAZY": "Datová tabulka (jednoduchá)", + "DOCUMENT_LIST": "Seznam dokumentů", + "TEMPLATE": "Šablona", + "FORM": "Formulář", + "FORM_LIST": "Seznam formulářů", + "FORM_LOADING": "Načítání formuláře", + "UPLOADER": "Nástroj pro odesílání", + "WEBSCRIPT": "Webový skript", + "TAG": "Tag", + "TRASHCAN": "Koš", + "SOCIAL": "Sociální", + "SETTINGS": "Nastavení", + "CONFIG-EDITOR": "Editor konfigurace", + "OVERLAY_VIEWER": "Zobrazení překrytí", + "ABOUT": "O aplikaci", + "SEARCH": "Rozšířené hledání", + "EXTENDED_SEARCH_QUERY_BODY": "Rozšířené hledání s textem dotazu", + "WORD_TO_SEARCH": "Hledat slovo", + "SEARCH_CREATED_BY": "Vytvořil(a)", + "SEARCH_SERVICE_APPROACH": "Označením této možnosti zakážete vstupní vlastnost a ke konfiguraci použijete službu", + "HEADER_DATA": "Data záhlaví", + "TREE_VIEW": "Stromová struktura", + "ICONS": "Ikony", + "PEOPLE_GROUPS_CLOUD": "Cloud osob/skupin", + "PEOPLE_CLOUD": "Součást cloudu osob", + "GROUPS_CLOUD": "Součást cloudu skupin", + "CONFIRM-DIALOG": "Dialogové okno s potvrzením" + }, + "TRASHCAN": { + "ACTIONS": { + "DELETE_PERMANENT": "Trvale odstranit", + "RESTORE": "Obnovit" + }, + "EMPTY_STATE": { + "TITLE": "Koš je prázdný", + "FIRST_TEXT": "Odstraněné položky se přesunou do koše.", + "SECOND_TEXT": "Vysypáním koše můžete položky trvale odstranit." + } + }, + "DOCUMENT_LIST": { + "MULTISELECT_CHECKBOXES": "Hromadný výběr (pomocí zaškrtávacích polí)", + "THUMBNAILS": "Povolit miniatury", + "ALLOW_DROP_FILES": "Povolit přetažení souborů do složky", + "MULTIPLE_FILE_UPLOAD": "Odeslání více souborů", + "FOLDER_UPLOAD": "Odeslat složku", + "CUSTOM_FILTER": "Vlastní filtr rozšíření", + "MAX_SIZE": "Filtr max. velikosti", + "ENABLE_VERSIONING": "Povolit více verzí", + "DESCRIPTION_UPLOAD": "Povolit odeslání", + "ENABLE_INFINITE_SCROLL": "Povolit nekonečné procházení", + "MULTISELECT_DESCRIPTION": "Pomocí klávesy Ctrl (Windows) nebo Cmd (Mac) můžete přepínat výběr více položek", + "RECENT": { + "EMPTY_STATE": { + "TITLE": "Seznam nedávných souborů je prázdný" + }, + "TITLE": "Nedávné soubory" + }, + "COLUMNS": { + "DISPLAY_NAME": "Zobrazované jméno", + "IS_LOCKED": "Zamknout", + "TAG": "Tag", + "NODE_ID": "ID uzlu", + "CREATED_BY": "Vytvořil(a)", + "CREATED_ON": "Vytvořeno", + "CREATED": "Vytvořeno", + "SIZE": "Velikost", + "DELETED_ON": "Odstraněno", + "DELETED_BY": "Odstranil(a)" + }, + "TOOLBAR": { + "CARDVIEW": "Režim zobrazení karet", + "SHARE_EDIT": "Upravit nastavení", + "NEW_FOLDER": "Nová složka", + "EDIT_FOLDER": "Upravit složku", + "DOWNLOAD": "Stáhnout", + "DELETE": "Odstranit", + "FAVORITES": "Přidat mezi oblíbené", + "SHARE": "Sdílet", + "THEME": "Vybrat motiv", + "SHOW_VERSION": "Zobrazit verzi", + "HIDE_VERSION": "Skrýt verzi", + "LISTVIEW": "Režim zobrazení seznamu", + "CREATE_LIBRARY": "Vytvořit knihovnu" + }, + "ACTIONS": { + "VERSIONS": "Spravovat verze", + "LOCK": "Zamknout", + "METADATA": "Informace", + "DOWNLOAD": "Stáhnout", + "PERMISSION": "Oprávnění", + "FOLDER": { + "COPY": "Kopírovat", + "MOVE": "Přesunout", + "DELETE": "Odstranit" + }, + "DOCUMENT": { + "COPY": "Kopírovat", + "MOVE": "Přesunout", + "DELETE": "Odstranit", + "PROCESS_ACTION": "Zahájit proces" + } + } + }, + "DATATABLE": { + "RESET_DEFAULT": "Obnovit výchozí", + "ADD_ROW": "Přidat řádek", + "REPLACE_ROWS": "Nahradit řádky", + "REPLACE_COLUMNS": "Nahradit sloupce", + "LOAD_NODE": "Načíst uzel", + "MULTISELECT": "Hromadný výběr", + "MULTISELECT_DESCRIPTION": "Pomocí klávesy Ctrl (Windows) nebo Cmd (Mac) můžete přepínat výběr více položek" + }, + "ANALYTICS_REPORT": { + "NO_REPORT_MESSAGE": "Nebyly zvoleny žádné zprávy. Vyberte zprávu ze seznamu" + }, + "PS-TAB": { + "TASKS-TAB": "Úkoly", + "PROCESSES-TAB": "Proces", + "REPORTS-TAB": "Protokoly", + "SETTINGS-TAB": "Nastavení", + "START-TASK": "Zahájit úkol", + "START-PROCESS": "Zahájit proces", + "PROCESS-AUDIT-LOG": "Protokol auditu pro proces", + "TASK-AUDIT-LOG": "Protokol auditu pro úkol", + "TASK-SHOW-HEADER": "Zobrazit záhlaví podrobností" + }, + "PS_CLOUD_TAB": { + "APPS_TAB": "Aplikace", + "SETTINGS_TAB": "Nastavení" + }, + "FORM-LIST": { + "STORE": "Uložit", + "RESTORE": "Obnovit" + }, + "FORM-LOADING": { + "FORM_DATA": "Data formuláře", + "FORM_DATA_MESSAGE": "Zadejte hodnoty do formuláře", + "TYPEAHEAD_PLACEHOLDER": "Začněte psát", + "RADIO_PLACEHOLDER": "Přepínač", + "SELECT_PLACEHOLDER": "Rozevírací seznam" + }, + "LOGIN": { + "CONTENT_SERVICES": "Content Services", + "PROCESS_SERVICES": "Process Services", + "LOGIN_FOOTER": "Zápatí přihlašování", + "SHOW_REMEMBERME": "Zobrazit tlačítko „Zapamatovat přihlášení“", + "SHOW_SUCCESS_ROUTE": "Zobrazit okna pro úspěšné přihlášení", + "CUSTOM_LOGO": "Vlastní logo" + }, + "SEARCH": { + "RESULTS": "Výsledky hledání", + "NO_RESULT": "Nebyly nalezeny žádné výsledky", + "FACET_FIELDS": { + "TYPE": "1:Typ", + "SIZE": "2:Velikost", + "CREATOR": "3:Autor", + "MODIFIER": "4:Upravil(a)", + "CREATED": "5:Vytvořeno" + }, + "FACET_QUERIES": { + "MY_FACET_QUERIES": "Moje dotazy na aspekty", + "CREATED_THIS_YEAR": "1.Vytvořeno tento rok", + "MIMETYPE": "2.Typ: HTML", + "XTRASMALL": "3.Velikost: extra malé", + "SMALL": "3.Velikost: malé", + "MEDIUM": "3.Velikost: střední", + "LARGE": "3.Velikost: velké", + "XTRALARGE": "3.Velikost: extra velké", + "XXTRALARGE": "3.Velikost: XX velké" + } + }, + "SOCIAL": { + "LIKE": "Komponenta pro Líbí se mi", + "RATING": "Komponenta pro Hodnocení" + }, + "TAG": { + "LIST": "Uvádět tagy Content Services", + "INSERT": "Vložit ID uzlu", + "NODE_LIST": "Řadit tagy dle ID uzlu" + }, + "DEMO_PERMISSION": { + "INHERIT_PERMISSION_BUTTON": "Dědění oprávnění", + "INHERITED_PERMISSIONS_BUTTON": "Oprávnění bylo zděděno" + }, + "TASK_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Vložit ID aplikace", + "APP_ID_TYPE_ERROR": "ID aplikace musí být číslo", + "NUMBER_TYPE_ERROR": "Hodnota musí být číslo", + "NUMBER_GREATER_THAN": "Hodnota musí být rovna nebo větší než {{ value }}" + }, + "TOOLTIP_MESSAGE": { + "START_INPUT": "Počáteční strana" + } + }, + "PROCESS_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Vložit ID aplikace", + "APP_ID_TYPE_ERROR": "ID aplikace musí být číslo", + "NUMBER_GREATER_THAN": "Hodnota musí být rovna nebo větší než {{ value }}" + } + }, + "GROUP-TITLE1-TRANSLATION-KEY": "Vlastní překlad názvu 1", + "GROUP-TITLE2-TRANSLATION-KEY": "Vlastní překlad názvu 2", + "ERROR_CONTENT": { + "507": { + "TITLE": "Disk ACS plný", + "DESCRIPTION": "Obsah přesahuje celkovou kvótu úložiště nastavenou pro síť nebo systém", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + } + }, + "PROCESS_LIST_CLOUD_DEMO": { + "TITLE": "Cloudová ukázka seznamu procesů", + "CUSTOMIZE_FILTERS": "Přizpůsobit filtr" + }, + "TASK_LIST_CLOUD_DEMO": { + "CUSTOMIZE_FILTERS": "Přizpůsobit filtr" + }, + "PEOPLE_GROUPS_CLOUD": { + "SINGLE": "Volba jedné položky", + "MULTI": "Volba více položek", + "PRESELECTED_VALUE": "Předvolená hodnota: ", + "ROLE": "Role: ", + "APP_NAME": "Název aplikace", + "APP_FILTER_MODE": "Filtrovat podle názvu aplikace", + "ROLE_FILTER_MODE": "Filtrovat podle role", + "PRESELECT_VALIDATION": "Ověření předvolené hodnoty" + }, + "ABOUT": { + "TITLE": "Doplňky", + "TABLE_HEADERS": { + "ID": "ID", + "NAME": "Název", + "VERSION": "Verze", + "VENDOR": "Dodavatel", + "LICENSE": "Licence", + "RUNTIME": "Délka", + "DESCRIPTION": "Popis" + } + }, + "SETTINGS_CLOUD": { + "MULTISELECTION": "Hromadný výběr", + "TESTING_MODE": "Testovací režim", + "SELECTION_MODE": "Režim výběru", + "TASK_DETAILS_REDIRECTION": "Zobrazit podrobnosti o úkolu při kliknutí na úkol", + "PROCESS_DETAILS_REDIRECTION": "Zobrazit podrobnosti o průběhu při kliknutí na proces" + } +} \ No newline at end of file diff --git a/demo-shell/resources/i18n/da.json b/demo-shell/resources/i18n/da.json new file mode 100644 index 0000000000..9db3adb983 --- /dev/null +++ b/demo-shell/resources/i18n/da.json @@ -0,0 +1,324 @@ +{ + "APP": { + "INFO_DRAWER": { + "TITLE": "Detaljer", + "COMMENTS": "Kommentarer", + "PROPERTIES": "Egenskaber", + "VERSIONS": "Versioner" + }, + "HOME": { + "TITLE": "Angular-komponenter til Alfresco", + "DOCUMENTATION": "Dokumentation" + }, + "LOGOUT": { + "TITLE": "Side til at logge af", + "SUB_TITLE": "Du er nu logget af", + "LOGIN": "Log ind", + "HOME": "Hjem" + }, + "ADF_VERSION_MANAGER": { + "ALLOW_DELETE": "Tillad sletning", + "SHOW_COMMENTS": "Vis kommentarer til versioner", + "ALLOW_DOWNLOAD": "Aktivér versionsdownload", + "READ_ONLY": "Skrivebeskyttet", + "COMMENTS": "Vis kommentarer" + }, + "PERSONAL-FILES": "Personlige filer", + "WARN-MULTIPLE-UPLOADS": "Vis advarsler for flere uploads.", + "CUSTOM-PERMISSION-MESSAGE": "Tillad meddelelse om brugerdefineret tilladelse", + "MEDIUM-TIME-FORMAT": "Tillad mellemlangt tidsformat for dokumentliste", + "SEARCH": { + "RADIO": { + "NONE": "Ingen", + "ALL": "Alle", + "FOLDER": "Mappe", + "DOCUMENT": "Dokument" + } + } + }, + "title": "Velkommen", + "VERSION": { + "NO_PERMISSION": "Du har ikke tilladelse til at administrere versioner af dette indhold", + "NO_PERMISSION_EVENT": "Du har ikke tilladelsen ${event.permission} til at ${event.action} ${event.type}", + "CHOOSE_FILE": "Vælg en fil for at få vist dens versioner", + "DIALOG": { + "CLOSE": "Luk", + "TITLE": "Administrer versioner" + } + }, + "METADATA": { + "DIALOG": { + "CLOSE": "Luk", + "TITLE": "Metadata" + } + }, + "APP_LAYOUT": { + "APP": "App", + "APP_NAME": "ADF-demoapp", + "HOME": "Hjem", + "NODE-SELECTOR": "Nodevælger", + "SITES": "Websteder", + "CONTENT_SERVICES": "Indholdstjenester", + "BREADCRUMB": "Brødkrumme", + "NOTIFICATIONS": "Meddelelser", + "TASK_LIST": "Opgaveliste", + "PROCESS_LIST": "Procesliste", + "PROCESS_CLOUD": "Activiti Cloud", + "CARD_VIEW": "Kortvisning", + "PROCESS_SERVICES": "Process Services", + "LOGIN": "Log ind", + "CUSTOM_SOURCES": "Brugerdefinerede kilder", + "DATATABLE": "Datatabel", + "DATATABLE_LAZY": "Datatabel (Lazy)", + "DOCUMENT_LIST": "Dokumentliste", + "TEMPLATE": "Skabelon", + "FORM": "Formular", + "FORM_LIST": "Formularliste", + "FORM_LOADING": "Formular indlæses", + "UPLOADER": "Uploader", + "WEBSCRIPT": "Webscript", + "TAG": "Tag", + "TRASHCAN": "Papirkurv", + "SOCIAL": "Social", + "SETTINGS": "Indstillinger", + "CONFIG-EDITOR": "Konfigurationseditor", + "OVERLAY_VIEWER": "Overlejringsfremviser", + "ABOUT": "Om", + "SEARCH": "Udvidet søgning", + "EXTENDED_SEARCH_QUERY_BODY": "Udvidet søgning med forespørgselstekst", + "WORD_TO_SEARCH": "Søg efter ord", + "SEARCH_CREATED_BY": "Oprettet af", + "SEARCH_SERVICE_APPROACH": "Vælg dette felt for at deaktivere inputegenskaben og konfigurere ved hjælp af tjenesten", + "HEADER_DATA": "Headerdata", + "TREE_VIEW": "Trævisning", + "ICONS": "Ikoner", + "PEOPLE_GROUPS_CLOUD": "Person/gruppecloud", + "PEOPLE_CLOUD": "Personcloudkomponent", + "GROUPS_CLOUD": "Gruppecloudkomponent", + "CONFIRM-DIALOG": "Bekræftelsesdialogboks" + }, + "TRASHCAN": { + "ACTIONS": { + "DELETE_PERMANENT": "Slet permanent", + "RESTORE": "Gendan" + }, + "EMPTY_STATE": { + "TITLE": "Papirkurven er tom", + "FIRST_TEXT": "De elementer, du sletter, flyttes til papirkurven.", + "SECOND_TEXT": "Tøm papirkurven for at slette elementerne permanent." + } + }, + "DOCUMENT_LIST": { + "MULTISELECT_CHECKBOXES": "Vælg flere (med afkrydsningsfelter)", + "THUMBNAILS": "Aktivér miniaturevisninger", + "ALLOW_DROP_FILES": "Aktivér Slip filer i en mappe", + "MULTIPLE_FILE_UPLOAD": "Upload af flere filer", + "FOLDER_UPLOAD": "Upload af mappe", + "CUSTOM_FILTER": "Filter for brugerdefinerede udvidelser", + "MAX_SIZE": "Filtrer efter maksimal størrelse", + "ENABLE_VERSIONING": "Aktivér versionering", + "DESCRIPTION_UPLOAD": "Tillad upload", + "ENABLE_INFINITE_SCROLL": "Aktivér uendelig rulning", + "MULTISELECT_DESCRIPTION": "Brug Kommando (Mac) eller Ctrl (Windows) for at vælge flere elementer", + "RECENT": { + "EMPTY_STATE": { + "TITLE": "Listen over de seneste filer er tom" + }, + "TITLE": "Seneste filer" + }, + "COLUMNS": { + "DISPLAY_NAME": "Visningsnavn", + "IS_LOCKED": "Lås", + "TAG": "Tag", + "NODE_ID": "Node-id", + "CREATED_BY": "Oprettet af", + "CREATED_ON": "Oprettet den", + "CREATED": "Oprettet", + "SIZE": "Størrelse", + "DELETED_ON": "Slettet", + "DELETED_BY": "Slettet af" + }, + "TOOLBAR": { + "CARDVIEW": "Kortvisning", + "SHARE_EDIT": "Rediger indstillinger", + "NEW_FOLDER": "Ny mappe", + "EDIT_FOLDER": "Rediger mappe", + "DOWNLOAD": "Download", + "DELETE": "Slet", + "FAVORITES": "Angiv som favorit", + "SHARE": "Del", + "THEME": "Vælg et tema", + "SHOW_VERSION": "Vis version", + "HIDE_VERSION": "Skjul version", + "LISTVIEW": "Listevisning", + "CREATE_LIBRARY": "Opret bibliotek" + }, + "ACTIONS": { + "VERSIONS": "Administrer versioner", + "LOCK": "Lås", + "METADATA": "Oplysninger", + "DOWNLOAD": "Download", + "PERMISSION": "Tilladelse", + "FOLDER": { + "COPY": "Kopiér", + "MOVE": "Flyt", + "DELETE": "Slet" + }, + "DOCUMENT": { + "COPY": "Kopiér", + "MOVE": "Flyt", + "DELETE": "Slet", + "PROCESS_ACTION": "Start proces" + } + } + }, + "DATATABLE": { + "RESET_DEFAULT": "Nulstil til standard", + "ADD_ROW": "Tilføj række", + "REPLACE_ROWS": "Erstat rækker", + "REPLACE_COLUMNS": "Erstat kolonner", + "LOAD_NODE": "Indlæs node", + "MULTISELECT": "Vælg flere", + "MULTISELECT_DESCRIPTION": "Brug Kommando (Mac) eller Ctrl (Windows) for at vælge flere elementer" + }, + "ANALYTICS_REPORT": { + "NO_REPORT_MESSAGE": "Du skal vælge en rapport på listen til venstre" + }, + "PS-TAB": { + "TASKS-TAB": "Opgaver", + "PROCESSES-TAB": "Proces", + "REPORTS-TAB": "Rapporter", + "SETTINGS-TAB": "Indstillinger", + "START-TASK": "Start opgave", + "START-PROCESS": "Start proces", + "PROCESS-AUDIT-LOG": "Procesovervågningslog", + "TASK-AUDIT-LOG": "Opgaveovervågningslog", + "TASK-SHOW-HEADER": "Vis detaljer for header" + }, + "PS_CLOUD_TAB": { + "APPS_TAB": "App", + "SETTINGS_TAB": "Indstillinger" + }, + "FORM-LIST": { + "STORE": "Gem", + "RESTORE": "Gendan" + }, + "FORM-LOADING": { + "FORM_DATA": "Formulardata", + "FORM_DATA_MESSAGE": "Indtast værdier for at udfylde formularen", + "TYPEAHEAD_PLACEHOLDER": "Automatisk fuldførelse", + "RADIO_PLACEHOLDER": "Alternativknap", + "SELECT_PLACEHOLDER": "Rulleliste" + }, + "LOGIN": { + "CONTENT_SERVICES": "Indholdstjenester", + "PROCESS_SERVICES": "Process Services", + "LOGIN_FOOTER": "Sidefod til login", + "SHOW_REMEMBERME": "Vis Husk mig", + "SHOW_SUCCESS_ROUTE": "Vis succesrute", + "CUSTOM_LOGO": "Brugerdefineret logo" + }, + "SEARCH": { + "RESULTS": "Søgeresultater", + "NO_RESULT": "Der blev ikke fundet nogen resultater", + "FACET_FIELDS": { + "TYPE": "1: Type", + "SIZE": "2: Størrelse", + "CREATOR": "3: Opretter", + "MODIFIER": "4: Modifikator", + "CREATED": "5: Oprettet" + }, + "FACET_QUERIES": { + "MY_FACET_QUERIES": "Mine facetforespørgsler", + "CREATED_THIS_YEAR": "1. Oprettet i år", + "MIMETYPE": "2. Type: HTML", + "XTRASMALL": "3. Størrelse: xtra small", + "SMALL": "4. Størrelse: small", + "MEDIUM": "5. Størrelse: medium", + "LARGE": "6. Størrelse: large", + "XTRALARGE": "7. Størrelse: xtra large", + "XXTRALARGE": "8. Størrelse: XX large" + } + }, + "SOCIAL": { + "LIKE": "Synes om-komponent", + "RATING": "Bedømmelse-komponent" + }, + "TAG": { + "LIST": "Vis indholdstjenester for tags", + "INSERT": "Indsæt node-id", + "NODE_LIST": "Tagliste efter node-id" + }, + "DEMO_PERMISSION": { + "INHERIT_PERMISSION_BUTTON": "Nedarv tilladelse", + "INHERITED_PERMISSIONS_BUTTON": "Tilladelsen er nedarvet" + }, + "TASK_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Indsæt app-id", + "APP_ID_TYPE_ERROR": "App-id'et skal være et tal", + "NUMBER_TYPE_ERROR": "Værdien skal være et tal", + "NUMBER_GREATER_THAN": "Værdien skal være større end eller lig med {{ value }}" + }, + "TOOLTIP_MESSAGE": { + "START_INPUT": "Startside" + } + }, + "PROCESS_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Indsæt app-id", + "APP_ID_TYPE_ERROR": "App-id'et skal være et tal", + "NUMBER_GREATER_THAN": "Værdien skal være større end eller lig med {{ value }}" + } + }, + "GROUP-TITLE1-TRANSLATION-KEY": "Brugerdefineret titel oversættelse et", + "GROUP-TITLE2-TRANSLATION-KEY": "Brugerdefineret titel oversættelse to", + "ERROR_CONTENT": { + "507": { + "TITLE": "ACS-disken er fuld", + "DESCRIPTION": "Indholdet overskrider den generelle lagerkvotegrænse, der er konfigureret for netværket eller systemet", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + } + }, + "PROCESS_LIST_CLOUD_DEMO": { + "TITLE": "CLOUDDEMO AF PROCESLISTE", + "CUSTOMIZE_FILTERS": "Tilpas dit filter" + }, + "TASK_LIST_CLOUD_DEMO": { + "CUSTOMIZE_FILTERS": "Tilpas dit filter" + }, + "PEOPLE_GROUPS_CLOUD": { + "SINGLE": "Enkeltvalg", + "MULTI": "Multivalg", + "PRESELECTED_VALUE": "Forudvælg: ", + "ROLE": "Roller: ", + "APP_NAME": "Appnavn", + "APP_FILTER_MODE": "Filtrer efter appnavn", + "ROLE_FILTER_MODE": "Filtrer efter rolle", + "PRESELECT_VALIDATION": "Forudvælg validering" + }, + "ABOUT": { + "TITLE": "Plug-ins", + "TABLE_HEADERS": { + "ID": "Id", + "NAME": "Navn", + "VERSION": "Version", + "VENDOR": "Leverandør", + "LICENSE": "Licens", + "RUNTIME": "Kørselstidspunkt", + "DESCRIPTION": "Beskrivelse" + } + }, + "SETTINGS_CLOUD": { + "MULTISELECTION": "Multivalg", + "TESTING_MODE": "Testtilstand", + "SELECTION_MODE": "Valgtilstand", + "TASK_DETAILS_REDIRECTION": "Vis opgavedetaljer på opgave ved at klikke", + "PROCESS_DETAILS_REDIRECTION": "Vis behandlingsdetaljer for processen ved at klikke" + } +} \ No newline at end of file diff --git a/demo-shell/resources/i18n/de.json b/demo-shell/resources/i18n/de.json index fadc40e103..58bc3d1274 100644 --- a/demo-shell/resources/i18n/de.json +++ b/demo-shell/resources/i18n/de.json @@ -57,6 +57,7 @@ "APP_NAME": "ADF-Demoanwendung", "HOME": "Startseite", "NODE-SELECTOR": "Node-Auswahl", + "SITES": "Sites", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Breadcrumb", "NOTIFICATIONS": "Benachrichtigungen", @@ -93,7 +94,8 @@ "ICONS": "Symbole", "PEOPLE_GROUPS_CLOUD": "Personen-/Gruppen-Cloud", "PEOPLE_CLOUD": "Personen-Cloud-Komponente", - "GROUPS_CLOUD": "Gruppen-Cloud-Komponente" + "GROUPS_CLOUD": "Gruppen-Cloud-Komponente", + "CONFIRM-DIALOG": "Bestätigungsdialog" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Mehrfachauswahl", "TESTING_MODE": "Testmodus", "SELECTION_MODE": "Auswahlmodus", - "TASK_DETAILS_REDIRECTION": "Bei Klicken auf Aufgabe Aufgabendetails einblenden" + "TASK_DETAILS_REDIRECTION": "Bei Klicken auf Aufgabe Aufgabendetails einblenden", + "PROCESS_DETAILS_REDIRECTION": "Bei Klicken auf Prozess Prozessdetails anzeigen" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/es.json b/demo-shell/resources/i18n/es.json index 7d9f47954c..d06359e254 100644 --- a/demo-shell/resources/i18n/es.json +++ b/demo-shell/resources/i18n/es.json @@ -57,6 +57,7 @@ "APP_NAME": "Aplicación ADF Demo", "HOME": "Inicio", "NODE-SELECTOR": "Selector de nodo", + "SITES": "Sitios", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Ruta de navegación", "NOTIFICATIONS": "Notificaciones", @@ -93,7 +94,8 @@ "ICONS": "Iconos", "PEOPLE_GROUPS_CLOUD": "Personas/Grupos en la nube", "PEOPLE_CLOUD": "Componente en la nube de personas", - "GROUPS_CLOUD": "Componente en la nube de grupos" + "GROUPS_CLOUD": "Componente en la nube de grupos", + "CONFIRM-DIALOG": "Cuadro de diálogo de confirmación" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Selección múltiple", "TESTING_MODE": "Modo de prueba", "SELECTION_MODE": "Modo de selección", - "TASK_DETAILS_REDIRECTION": "Mostrar detalles de la tarea haciendo clic en la tarea" + "TASK_DETAILS_REDIRECTION": "Mostrar detalles de la tarea haciendo clic en la tarea", + "PROCESS_DETAILS_REDIRECTION": "Mostrar detalles del proceso al hacer clic en el proceso" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/fi.json b/demo-shell/resources/i18n/fi.json new file mode 100644 index 0000000000..3f1e255d2e --- /dev/null +++ b/demo-shell/resources/i18n/fi.json @@ -0,0 +1,324 @@ +{ + "APP": { + "INFO_DRAWER": { + "TITLE": "Tiedot", + "COMMENTS": "Kommentit", + "PROPERTIES": "Ominaisuudet", + "VERSIONS": "Versiot" + }, + "HOME": { + "TITLE": "Angular-komponentit Alfrescolle", + "DOCUMENTATION": "Dokumentaatio" + }, + "LOGOUT": { + "TITLE": "Uloskirjautumissivu", + "SUB_TITLE": "Olet nyt kirjautunut ulos", + "LOGIN": "Kirjaudu sisään", + "HOME": "Aloitussivu" + }, + "ADF_VERSION_MANAGER": { + "ALLOW_DELETE": "Salli poistaminen", + "SHOW_COMMENTS": "Näytä kommentit versioissa", + "ALLOW_DOWNLOAD": "Ota version lataaminen käyttöön", + "READ_ONLY": "Vain luku", + "COMMENTS": "Näytä kommentit" + }, + "PERSONAL-FILES": "Omat tiedostot", + "WARN-MULTIPLE-UPLOADS": "Näytä varoitus useille latauksille.", + "CUSTOM-PERMISSION-MESSAGE": "Muokkaa omaa oikeusilmoitusta", + "MEDIUM-TIME-FORMAT": "Ota Medium-aikamuoto käyttöön asiakirjaluettelossa", + "SEARCH": { + "RADIO": { + "NONE": "Ei mitään", + "ALL": "Kaikki", + "FOLDER": "Kansio", + "DOCUMENT": "Asiakirja" + } + } + }, + "title": "Tervetuloa", + "VERSION": { + "NO_PERMISSION": "Sinulla ei ole oikeutta hallita tämän sisällön versioita", + "NO_PERMISSION_EVENT": "Sinulla ei ole oikeutta ${event.permission} tapahtumalle ${event.action} tapahtumatyypissä ${event.type}", + "CHOOSE_FILE": "Jos haluat nähdä tiedoston versiot, valitse haluamasi tiedosto", + "DIALOG": { + "CLOSE": "Sulje", + "TITLE": "Hallitse versioita" + } + }, + "METADATA": { + "DIALOG": { + "CLOSE": "Sulje", + "TITLE": "Metatiedot" + } + }, + "APP_LAYOUT": { + "APP": "Sovellus", + "APP_NAME": "ADF-demosovellus", + "HOME": "Aloitussivu", + "NODE-SELECTOR": "Solmuvalitsin", + "SITES": "Sivustot", + "CONTENT_SERVICES": "Content Services", + "BREADCRUMB": "Siirtymispolku", + "NOTIFICATIONS": "Ilmoitukset", + "TASK_LIST": "Tehtäväluettelo", + "PROCESS_LIST": "Prosessiluettelo", + "PROCESS_CLOUD": "Prosessipilvi", + "CARD_VIEW": "Korttinäkymä", + "PROCESS_SERVICES": "Process Services", + "LOGIN": "Kirjaudu sisään", + "CUSTOM_SOURCES": "Omat lähteet", + "DATATABLE": "Tietotaulukko", + "DATATABLE_LAZY": "Tietotaulukko (Lazy)", + "DOCUMENT_LIST": "Asiakirjaluettelo", + "TEMPLATE": "Malli", + "FORM": "Lomake", + "FORM_LIST": "Lomakeluettelo", + "FORM_LOADING": "Lomakelataus", + "UPLOADER": "Lataustoiminto", + "WEBSCRIPT": "Verkkokomentosarja", + "TAG": "Tunniste", + "TRASHCAN": "Roskakori", + "SOCIAL": "Sosiaalinen", + "SETTINGS": "Asetukset", + "CONFIG-EDITOR": "Määrityseditori", + "OVERLAY_VIEWER": "Peittokatselutoiminto", + "ABOUT": "Tietoja", + "SEARCH": "Laajennettu haku", + "EXTENDED_SEARCH_QUERY_BODY": "Laajennettu haku kyselyn rungon avulla", + "WORD_TO_SEARCH": "Hakusana", + "SEARCH_CREATED_BY": "Tekijä:", + "SEARCH_SERVICE_APPROACH": "Jos haluat poistaa käytöstä annetun ominaisuuden ja määrittää palvelun avulla, valitse tämä", + "HEADER_DATA": "Otsikkotiedot", + "TREE_VIEW": "Puunäkymä", + "ICONS": "Kuvakkeet", + "PEOPLE_GROUPS_CLOUD": "Ihmispilvi/Ryhmäpilvi", + "PEOPLE_CLOUD": "Ihmispilvi-komponentti", + "GROUPS_CLOUD": "Ryhmäpilvi-komponentti", + "CONFIRM-DIALOG": "Vahvistusvalintaikkuna" + }, + "TRASHCAN": { + "ACTIONS": { + "DELETE_PERMANENT": "Poista pysyvästi", + "RESTORE": "Palauta" + }, + "EMPTY_STATE": { + "TITLE": "Roskakori on tyhjä", + "FIRST_TEXT": "Poistamasi kohteet siirretään roskakoriin.", + "SECOND_TEXT": "Jos haluat poistaa kohteet pysyvästi, tyhjennä roskakori." + } + }, + "DOCUMENT_LIST": { + "MULTISELECT_CHECKBOXES": "Monivalinta (valintaruuduilla)", + "THUMBNAILS": "Ota pikkukuvat käyttöön", + "ALLOW_DROP_FILES": "Ota tiedostojen kansioon pudottaminen käyttöön", + "MULTIPLE_FILE_UPLOAD": "Useiden tiedostojen lataaminen", + "FOLDER_UPLOAD": "Kansion lataaminen", + "CUSTOM_FILTER": "Mukautettu tiedostomuotosuodatin", + "MAX_SIZE": "Enimmäiskoon suodatin", + "ENABLE_VERSIONING": "Ota versionhallinta käyttöön", + "DESCRIPTION_UPLOAD": "Ota lataus käyttöön", + "ENABLE_INFINITE_SCROLL": "Ota rajaton vieritys käyttöön", + "MULTISELECT_DESCRIPTION": "Voit valita useita kohteita Cmd- (Mac) tai Ctrl-näppäimen (Windows) avulla", + "RECENT": { + "EMPTY_STATE": { + "TITLE": "Viimeisimpien tiedostojen luettelo on tyhjä" + }, + "TITLE": "Viimeisimmät tiedostot" + }, + "COLUMNS": { + "DISPLAY_NAME": "Näyttönimi", + "IS_LOCKED": "Lukitse", + "TAG": "Tunniste", + "NODE_ID": "Solmutunnus", + "CREATED_BY": "Tekijä:", + "CREATED_ON": "Luotu", + "CREATED": "Luotu", + "SIZE": "Koko", + "DELETED_ON": "Poistettu", + "DELETED_BY": "Poistaja:" + }, + "TOOLBAR": { + "CARDVIEW": "Korttinäkymätila", + "SHARE_EDIT": "Muokkaa asetuksia", + "NEW_FOLDER": "Uusi kansio", + "EDIT_FOLDER": "Muokkaa kansiota", + "DOWNLOAD": "Lataa", + "DELETE": "Poista", + "FAVORITES": "Lisää suosikkeihin", + "SHARE": "Jaa", + "THEME": "Valitse teema", + "SHOW_VERSION": "Näytä versio", + "HIDE_VERSION": "Piilota versio", + "LISTVIEW": "Luettelonäkymätila", + "CREATE_LIBRARY": "Luo kirjasto" + }, + "ACTIONS": { + "VERSIONS": "Hallitse versioita", + "LOCK": "Lukitse", + "METADATA": "Tiedot", + "DOWNLOAD": "Lataa", + "PERMISSION": "Oikeus", + "FOLDER": { + "COPY": "Kopioi", + "MOVE": "Siirrä", + "DELETE": "Poista" + }, + "DOCUMENT": { + "COPY": "Kopioi", + "MOVE": "Siirrä", + "DELETE": "Poista", + "PROCESS_ACTION": "Käynnistä prosessi" + } + } + }, + "DATATABLE": { + "RESET_DEFAULT": "Palauta oletukseen", + "ADD_ROW": "Lisää rivi", + "REPLACE_ROWS": "Korvaa rivejä", + "REPLACE_COLUMNS": "Korvaa sarakkeita", + "LOAD_NODE": "Lataa solmu", + "MULTISELECT": "Monivalinta", + "MULTISELECT_DESCRIPTION": "Voit valita useita kohteita Cmd- (Mac) tai Ctrl-näppäimen (Windows) avulla" + }, + "ANALYTICS_REPORT": { + "NO_REPORT_MESSAGE": "Yhtään raporttia ei ole valittuna. Valitse raportti luettelosta." + }, + "PS-TAB": { + "TASKS-TAB": "Tehtävät", + "PROCESSES-TAB": "Prosessi", + "REPORTS-TAB": "Raportit", + "SETTINGS-TAB": "Asetukset", + "START-TASK": "Aloita tehtävä", + "START-PROCESS": "Käynnistä prosessi", + "PROCESS-AUDIT-LOG": "Prosessitarkastusloki", + "TASK-AUDIT-LOG": "Tehtävätarkastusloki", + "TASK-SHOW-HEADER": "Näytä tieto-otsikko" + }, + "PS_CLOUD_TAB": { + "APPS_TAB": "Sovellus", + "SETTINGS_TAB": "Asetukset" + }, + "FORM-LIST": { + "STORE": "Tallenna", + "RESTORE": "Palauta" + }, + "FORM-LOADING": { + "FORM_DATA": "Lomaketiedot", + "FORM_DATA_MESSAGE": "Anna lomakkeeseen lisättävät arvot", + "TYPEAHEAD_PLACEHOLDER": "Typeahead", + "RADIO_PLACEHOLDER": "Valintanappi", + "SELECT_PLACEHOLDER": "Avattava valikko" + }, + "LOGIN": { + "CONTENT_SERVICES": "Content Services", + "PROCESS_SERVICES": "Process Services", + "LOGIN_FOOTER": "Kirjautumisalatunniste", + "SHOW_REMEMBERME": "Näytä Muista minut -toiminto", + "SHOW_SUCCESS_ROUTE": "Näytä onnistumispolku", + "CUSTOM_LOGO": "Oma logo" + }, + "SEARCH": { + "RESULTS": "Hakutulokset", + "NO_RESULT": "Tuloksia ei löydy", + "FACET_FIELDS": { + "TYPE": "1: tyyppi", + "SIZE": "2: koko", + "CREATOR": "3: tekijä", + "MODIFIER": "4: muokkaaja", + "CREATED": "5: luotu" + }, + "FACET_QUERIES": { + "MY_FACET_QUERIES": "Omat kyselyt", + "CREATED_THIS_YEAR": "1. Luotu tänä vuonna", + "MIMETYPE": "2. Tyyppi: HTML", + "XTRASMALL": "3. Koko: XS", + "SMALL": "4. Koko: S", + "MEDIUM": "5. Koko: M", + "LARGE": "6. Koko: L", + "XTRALARGE": "7. Koko: XL", + "XXTRALARGE": "8. Koko: XXL" + } + }, + "SOCIAL": { + "LIKE": "Tykkäyskomponentti", + "RATING": "Arviokomponentti" + }, + "TAG": { + "LIST": "Luettelotunnisteet – Content Services", + "INSERT": "Lisää solmutunnus", + "NODE_LIST": "Tunnisteluettelo solmutunnuksen mukaan" + }, + "DEMO_PERMISSION": { + "INHERIT_PERMISSION_BUTTON": "Peri oikeus", + "INHERITED_PERMISSIONS_BUTTON": "Oikeus peritty" + }, + "TASK_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Lisää sovellustunnus", + "APP_ID_TYPE_ERROR": "Sovellustunnuksen täytyy olla numero", + "NUMBER_TYPE_ERROR": "Arvon täytyy olla numero", + "NUMBER_GREATER_THAN": "Arvon täytyy olla yhtä suuri tai suurempi kuin {{ value }}" + }, + "TOOLTIP_MESSAGE": { + "START_INPUT": "Aloitussivu" + } + }, + "PROCESS_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Lisää sovellustunnus", + "APP_ID_TYPE_ERROR": "Sovellustunnuksen täytyy olla numero", + "NUMBER_GREATER_THAN": "Arvon täytyy olla yhtä suuri tai suurempi kuin {{ value }}" + } + }, + "GROUP-TITLE1-TRANSLATION-KEY": "Oma otsikkokäännös yksi", + "GROUP-TITLE2-TRANSLATION-KEY": "Oma otsikkokäännös kaksi", + "ERROR_CONTENT": { + "507": { + "TITLE": "ACS-levy täynnä", + "DESCRIPTION": "Sisältö ylittää verkolle tai järjestelmälle määritetyn tallennustilan kokonaisrajoituksen", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + } + }, + "PROCESS_LIST_CLOUD_DEMO": { + "TITLE": "PROCESS LIST CLOUD DEMO", + "CUSTOMIZE_FILTERS": "Muokkaa suodatinta" + }, + "TASK_LIST_CLOUD_DEMO": { + "CUSTOMIZE_FILTERS": "Muokkaa suodatinta" + }, + "PEOPLE_GROUPS_CLOUD": { + "SINGLE": "Yksittäinen valinta", + "MULTI": "Monivalinta", + "PRESELECTED_VALUE": "Esivalittu: ", + "ROLE": "Roolit: ", + "APP_NAME": "Sovelluksen nimi", + "APP_FILTER_MODE": "Suodata sovelluksen nimen perusteella", + "ROLE_FILTER_MODE": "Suodata roolin perusteella", + "PRESELECT_VALIDATION": "Vahvistus esivalittu" + }, + "ABOUT": { + "TITLE": "Lisäosat", + "TABLE_HEADERS": { + "ID": "Tunnus", + "NAME": "Nimi", + "VERSION": "Versio", + "VENDOR": "Toimittaja", + "LICENSE": "Käyttöoikeus", + "RUNTIME": "Suorituspalvelu", + "DESCRIPTION": "Kuvaus" + } + }, + "SETTINGS_CLOUD": { + "MULTISELECTION": "Monivalinta", + "TESTING_MODE": "Testaustila", + "SELECTION_MODE": "Valintatila", + "TASK_DETAILS_REDIRECTION": "Näytä tehtävätiedot tehtävää napsauttamalla", + "PROCESS_DETAILS_REDIRECTION": "Näyttää prosessin tiedot prosessia napsautettaessa" + } +} \ No newline at end of file diff --git a/demo-shell/resources/i18n/fr.json b/demo-shell/resources/i18n/fr.json index 65bcc99127..6c9720cff0 100644 --- a/demo-shell/resources/i18n/fr.json +++ b/demo-shell/resources/i18n/fr.json @@ -57,6 +57,7 @@ "APP_NAME": "Application Démo ADF", "HOME": "Accueil", "NODE-SELECTOR": "Sélecteur de nœud", + "SITES": "Sites", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Fil d'Ariane", "NOTIFICATIONS": "Notifications", @@ -93,7 +94,8 @@ "ICONS": "Icônes", "PEOPLE_GROUPS_CLOUD": "Cloud des personnes/groupes", "PEOPLE_CLOUD": "Composant cloud des personnes", - "GROUPS_CLOUD": "Composant cloud des groupes" + "GROUPS_CLOUD": "Composant cloud des groupes", + "CONFIRM-DIALOG": "Boîte de dialogue de confirmation" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Multisélection", "TESTING_MODE": "Mode de test", "SELECTION_MODE": "Mode de sélection", - "TASK_DETAILS_REDIRECTION": "Afficher les détails de la tâche en cliquant dessus" + "TASK_DETAILS_REDIRECTION": "Afficher les détails de la tâche en cliquant dessus", + "PROCESS_DETAILS_REDIRECTION": "Afficher les détails du processus en cliquant dessus" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/it.json b/demo-shell/resources/i18n/it.json index 40e0f1447b..a8b2030ae1 100644 --- a/demo-shell/resources/i18n/it.json +++ b/demo-shell/resources/i18n/it.json @@ -57,6 +57,7 @@ "APP_NAME": "Applicazione demo ADF", "HOME": "Home", "NODE-SELECTOR": "Selezione nodo", + "SITES": "Siti", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Breadcrumb", "NOTIFICATIONS": "Notifiche", @@ -93,7 +94,8 @@ "ICONS": "Icone", "PEOPLE_GROUPS_CLOUD": "Cloud persone/gruppi", "PEOPLE_CLOUD": "Componente Cloud persone", - "GROUPS_CLOUD": "Componente Cloud gruppi" + "GROUPS_CLOUD": "Componente Cloud gruppi", + "CONFIRM-DIALOG": "Finestra di conferma" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Selezione multipla", "TESTING_MODE": "Modalità di test", "SELECTION_MODE": "Modalità di selezione", - "TASK_DETAILS_REDIRECTION": "Mostra dettagli compito dopo clic su compito" + "TASK_DETAILS_REDIRECTION": "Mostra dettagli compito dopo clic su compito", + "PROCESS_DETAILS_REDIRECTION": "Mostra i dettagli dopo il clic sul processo" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/ja.json b/demo-shell/resources/i18n/ja.json index c1f1b81005..00c1622323 100644 --- a/demo-shell/resources/i18n/ja.json +++ b/demo-shell/resources/i18n/ja.json @@ -57,6 +57,7 @@ "APP_NAME": "ADF デモアプリケーション", "HOME": "ホーム", "NODE-SELECTOR": "ノードセレクター", + "SITES": "サイト", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "階層リンク", "NOTIFICATIONS": "通知", @@ -93,7 +94,8 @@ "ICONS": "アイコン", "PEOPLE_GROUPS_CLOUD": "メンバー/グループのクラウド", "PEOPLE_CLOUD": "メンバーのクラウドコンポーネント", - "GROUPS_CLOUD": "グループのクラウドコンポーネント" + "GROUPS_CLOUD": "グループのクラウドコンポーネント", + "CONFIRM-DIALOG": "確認ダイアログ" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "複数選択", "TESTING_MODE": "テストモード", "SELECTION_MODE": "選択モード", - "TASK_DETAILS_REDIRECTION": "タスクのクリック時にタスクの詳細を表示" + "TASK_DETAILS_REDIRECTION": "タスクのクリック時にタスクの詳細を表示", + "PROCESS_DETAILS_REDIRECTION": "プロセスのクリックでプロセスの詳細を表示" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/nb.json b/demo-shell/resources/i18n/nb.json index 084c50f555..58192ace52 100644 --- a/demo-shell/resources/i18n/nb.json +++ b/demo-shell/resources/i18n/nb.json @@ -57,6 +57,7 @@ "APP_NAME": "ADF-demoprogam", "HOME": "Hjem", "NODE-SELECTOR": "Nodevelger", + "SITES": "Områder", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Søkebane", "NOTIFICATIONS": "Varsler", @@ -93,7 +94,8 @@ "ICONS": "Ikoner", "PEOPLE_GROUPS_CLOUD": "Person-/gruppesky", "PEOPLE_CLOUD": "Personsky-komponent", - "GROUPS_CLOUD": "Gruppesky-kompontent" + "GROUPS_CLOUD": "Gruppesky-kompontent", + "CONFIRM-DIALOG": "Bekreftelsesdialog" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Flervalg", "TESTING_MODE": "Testmodus", "SELECTION_MODE": "Valgmodus", - "TASK_DETAILS_REDIRECTION": "Vis oppgavedetaljer ved oppgaveklikk" + "TASK_DETAILS_REDIRECTION": "Vis oppgavedetaljer ved oppgaveklikk", + "PROCESS_DETAILS_REDIRECTION": "Vis prosessdetaljer ved prosessklikk" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/nl.json b/demo-shell/resources/i18n/nl.json index da6bd99efe..48b86594ae 100644 --- a/demo-shell/resources/i18n/nl.json +++ b/demo-shell/resources/i18n/nl.json @@ -57,6 +57,7 @@ "APP_NAME": "ADF-demotoepassing", "HOME": "Home", "NODE-SELECTOR": "Selectiefunctie voor node", + "SITES": "Sites", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Navigatiepad", "NOTIFICATIONS": "Meldingen", @@ -93,7 +94,8 @@ "ICONS": "Pictogrammen", "PEOPLE_GROUPS_CLOUD": "Personen-/groepencloud", "PEOPLE_CLOUD": "Component Personencloud", - "GROUPS_CLOUD": "Component Groepencloud" + "GROUPS_CLOUD": "Component Groepencloud", + "CONFIRM-DIALOG": "Bevestigingsdialoogvenster" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Multiselectie", "TESTING_MODE": "Testmodus", "SELECTION_MODE": "Selectiemodus", - "TASK_DETAILS_REDIRECTION": "Taakdetails weergeven bij klikken op taak" + "TASK_DETAILS_REDIRECTION": "Taakdetails weergeven bij klikken op taak", + "PROCESS_DETAILS_REDIRECTION": "Procesdetails weergeven bij klikken op proces" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/pl.json b/demo-shell/resources/i18n/pl.json new file mode 100644 index 0000000000..b94c7b4162 --- /dev/null +++ b/demo-shell/resources/i18n/pl.json @@ -0,0 +1,324 @@ +{ + "APP": { + "INFO_DRAWER": { + "TITLE": "Szczegóły", + "COMMENTS": "Komentarze", + "PROPERTIES": "Właściwości", + "VERSIONS": "Wersje" + }, + "HOME": { + "TITLE": "Składniki Angular dla Alfresco", + "DOCUMENTATION": "Dokumentacja" + }, + "LOGOUT": { + "TITLE": "Strona wylogowywania", + "SUB_TITLE": "Wylogowanie przebiegło pomyślnie.", + "LOGIN": "Zaloguj", + "HOME": "Strona główna" + }, + "ADF_VERSION_MANAGER": { + "ALLOW_DELETE": "Zezwól na usunięcie", + "SHOW_COMMENTS": "Pokaż komentarze do wersji", + "ALLOW_DOWNLOAD": "Włącz pobieranie wersji", + "READ_ONLY": "Tylko do odczytu", + "COMMENTS": "Pokaż komentarze" + }, + "PERSONAL-FILES": "Pliki osobiste", + "WARN-MULTIPLE-UPLOADS": "Wyświetl ostrzeżenie dla wielu operacji przesyłania.", + "CUSTOM-PERMISSION-MESSAGE": "Włącz komunikat o niestandardowych uprawnieniach", + "MEDIUM-TIME-FORMAT": "Włącz format czasu nośnika dla listy dokumentów", + "SEARCH": { + "RADIO": { + "NONE": "Brak", + "ALL": "Wszystkie", + "FOLDER": "Folder", + "DOCUMENT": "Dokument" + } + } + }, + "title": "Witaj", + "VERSION": { + "NO_PERMISSION": "Nie masz uprawnień do zarządzania wersjami tej zawartości", + "NO_PERMISSION_EVENT": "Nie masz uprawnienia ${event.permission} do akcji ${event.action} typu ${event.type}.", + "CHOOSE_FILE": "Wybierz plik, aby wyświetlić jego wersje.", + "DIALOG": { + "CLOSE": "Zamknij", + "TITLE": "Zarządzaj wersjami" + } + }, + "METADATA": { + "DIALOG": { + "CLOSE": "Zamknij", + "TITLE": "Metadane" + } + }, + "APP_LAYOUT": { + "APP": "Aplikacja", + "APP_NAME": "Wersja demonstracyjna aplikacji ADF", + "HOME": "Strona główna", + "NODE-SELECTOR": "Selektor węzłów", + "SITES": "Witryny", + "CONTENT_SERVICES": "Content Services", + "BREADCRUMB": "Ścieżka nawigacyjna", + "NOTIFICATIONS": "Powiadomienia", + "TASK_LIST": "Lista zadań", + "PROCESS_LIST": "Lista procesów", + "PROCESS_CLOUD": "Activiti Cloud", + "CARD_VIEW": "CardView", + "PROCESS_SERVICES": "Process Services", + "LOGIN": "Zaloguj", + "CUSTOM_SOURCES": "Źródła niestandardowe", + "DATATABLE": "Tabela danych", + "DATATABLE_LAZY": "Tabela danych (z opóźnieniem)", + "DOCUMENT_LIST": "Lista dokumentów", + "TEMPLATE": "Szablon", + "FORM": "Formularz", + "FORM_LIST": "Lista formularzy", + "FORM_LOADING": "Wczytywanie formularza", + "UPLOADER": "Program do przesyłania", + "WEBSCRIPT": "Skrypt internetowy", + "TAG": "Znacznik", + "TRASHCAN": "Kosz", + "SOCIAL": "Społecznościowy", + "SETTINGS": "Ustawienia", + "CONFIG-EDITOR": "Edytor konfiguracji", + "OVERLAY_VIEWER": "Przeglądarka nakładek", + "ABOUT": "Informacje", + "SEARCH": "Wyszukiwanie rozszerzone", + "EXTENDED_SEARCH_QUERY_BODY": "Wyszukiwanie rozszerzone z treścią zapytania", + "WORD_TO_SEARCH": "Szukany wyraz", + "SEARCH_CREATED_BY": "Utworzone przez", + "SEARCH_SERVICE_APPROACH": "Kliknij ten element, aby wyłączyć właściwość wejściową i skonfigurować korzystając z usługi", + "HEADER_DATA": "Dane nagłówka", + "TREE_VIEW": "Widok drzewa", + "ICONS": "Ikony", + "PEOPLE_GROUPS_CLOUD": "Chmura dla osób/grup", + "PEOPLE_CLOUD": "Składnik Chmura dla osób", + "GROUPS_CLOUD": "Składnik Chmura dla grup", + "CONFIRM-DIALOG": "Okno dialogowe potwierdzenia" + }, + "TRASHCAN": { + "ACTIONS": { + "DELETE_PERMANENT": "Usuń trwale", + "RESTORE": "Przywróć" + }, + "EMPTY_STATE": { + "TITLE": "Kosz jest pusty", + "FIRST_TEXT": "Usuwane elementy są przesyłane do kosza.", + "SECOND_TEXT": "Aby trwale usunąć elementy, opróżnij kosz." + } + }, + "DOCUMENT_LIST": { + "MULTISELECT_CHECKBOXES": "Wybór wielokrotny (przy użyciu pól wyboru)", + "THUMBNAILS": "Włącz miniatury", + "ALLOW_DROP_FILES": "Włącz upuszczanie plików w folderze", + "MULTIPLE_FILE_UPLOAD": "Przesyłanie wielu plików", + "FOLDER_UPLOAD": "Przesyłanie folderu", + "CUSTOM_FILTER": "Niestandardowy filtr rozszerzeń", + "MAX_SIZE": "Filtr rozmiaru maksymalnego", + "ENABLE_VERSIONING": "Włącz kontrolę wersji", + "DESCRIPTION_UPLOAD": "Włącz przesyłanie", + "ENABLE_INFINITE_SCROLL": "Włącz nieograniczone przewijanie", + "MULTISELECT_DESCRIPTION": "Używaj klawiszy Cmd (system Mac) lub Ctrl (system Windows), aby przełączać wybieranie wielu elementów.", + "RECENT": { + "EMPTY_STATE": { + "TITLE": "Lista bieżących plików jest pusta." + }, + "TITLE": "Bieżące pliki" + }, + "COLUMNS": { + "DISPLAY_NAME": "Nazwa wyświetlana", + "IS_LOCKED": "Blokada", + "TAG": "Znacznik", + "NODE_ID": "Identyfikator węzła", + "CREATED_BY": "Utworzone przez", + "CREATED_ON": "Data utworzenia", + "CREATED": "Utworzono", + "SIZE": "Rozmiar", + "DELETED_ON": "Usunięte", + "DELETED_BY": "Usunięte przez" + }, + "TOOLBAR": { + "CARDVIEW": "Tryb widoku karty", + "SHARE_EDIT": "Edytuj ustawienia", + "NEW_FOLDER": "Nowy folder", + "EDIT_FOLDER": "Edytuj folder", + "DOWNLOAD": "Pobierz", + "DELETE": "Usuń", + "FAVORITES": "Dodaj do ulubionych", + "SHARE": "Udostępnij", + "THEME": "Wybierz motyw", + "SHOW_VERSION": "Pokaż wersję", + "HIDE_VERSION": "Ukryj wersję", + "LISTVIEW": "Tryb widoku listy", + "CREATE_LIBRARY": "Utwórz bibliotekę" + }, + "ACTIONS": { + "VERSIONS": "Zarządzaj wersjami", + "LOCK": "Blokada", + "METADATA": "Informacje", + "DOWNLOAD": "Pobierz", + "PERMISSION": "Uprawnienie", + "FOLDER": { + "COPY": "Kopiuj", + "MOVE": "Przenieś", + "DELETE": "Usuń" + }, + "DOCUMENT": { + "COPY": "Kopiuj", + "MOVE": "Przenieś", + "DELETE": "Usuń", + "PROCESS_ACTION": "Rozpocznij proces" + } + } + }, + "DATATABLE": { + "RESET_DEFAULT": "Resetuj do domyślnych", + "ADD_ROW": "Dodaj wiersz", + "REPLACE_ROWS": "Zastąp wiersze", + "REPLACE_COLUMNS": "Zastąp kolumny", + "LOAD_NODE": "Wczytaj węzeł", + "MULTISELECT": "Wybór wielokrotny", + "MULTISELECT_DESCRIPTION": "Używaj klawiszy Cmd (system Mac) lub Ctrl (system Windows), aby przełączać wybieranie wielu elementów." + }, + "ANALYTICS_REPORT": { + "NO_REPORT_MESSAGE": "Nie wybrano raportu. Wybierz raport z listy." + }, + "PS-TAB": { + "TASKS-TAB": "Zadania", + "PROCESSES-TAB": "Proces", + "REPORTS-TAB": "Raporty", + "SETTINGS-TAB": "Ustawienia", + "START-TASK": "Rozpocznij zadanie", + "START-PROCESS": "Rozpocznij proces", + "PROCESS-AUDIT-LOG": "Dziennik inspekcji procesu", + "TASK-AUDIT-LOG": "Dziennik inspekcji zadania", + "TASK-SHOW-HEADER": "Pokaż nagłówek szczegółów" + }, + "PS_CLOUD_TAB": { + "APPS_TAB": "Aplikacja", + "SETTINGS_TAB": "Ustawienia" + }, + "FORM-LIST": { + "STORE": "Magazyn", + "RESTORE": "Przywróć" + }, + "FORM-LOADING": { + "FORM_DATA": "Dane formularza", + "FORM_DATA_MESSAGE": "Wprowadź wartości, aby wypełnić formularz.", + "TYPEAHEAD_PLACEHOLDER": "Wpisywanie z wyprzedzeniem", + "RADIO_PLACEHOLDER": "Przycisk radiowy", + "SELECT_PLACEHOLDER": "Menu rozwijane" + }, + "LOGIN": { + "CONTENT_SERVICES": "Content Services", + "PROCESS_SERVICES": "Process Services", + "LOGIN_FOOTER": "Stopka logowania", + "SHOW_REMEMBERME": "Pokaż opcję „Zapamiętaj mnie”", + "SHOW_SUCCESS_ROUTE": "Pokaż ścieżkę powodzenia", + "CUSTOM_LOGO": "Logo niestandardowe" + }, + "SEARCH": { + "RESULTS": "Wyniki wyszukiwania", + "NO_RESULT": "Brak wyników", + "FACET_FIELDS": { + "TYPE": "1: Typ", + "SIZE": "2: Rozmiar", + "CREATOR": "3: Twórca", + "MODIFIER": "4: Modyfikator", + "CREATED": "5: Utworzono" + }, + "FACET_QUERIES": { + "MY_FACET_QUERIES": "Moje zapytania dotyczące aspektu", + "CREATED_THIS_YEAR": "1. Utworzone w tym roku", + "MIMETYPE": "2. Typ: HTML", + "XTRASMALL": "3. Rozmiar: bardzo mały", + "SMALL": "4. Rozmiar: mały", + "MEDIUM": "5. Rozmiar: średni", + "LARGE": "6. Rozmiar: duży", + "XTRALARGE": "7. Rozmiar: bardzo duży", + "XXTRALARGE": "8. Rozmiar: wyjątkowo duży" + } + }, + "SOCIAL": { + "LIKE": "Składnik Like", + "RATING": "Składnik Rating" + }, + "TAG": { + "LIST": "Wyświetl znaczniki Content Services", + "INSERT": "Wstaw identyfikator węzła", + "NODE_LIST": "Lista znaczników według identyfikatora węzła" + }, + "DEMO_PERMISSION": { + "INHERIT_PERMISSION_BUTTON": "Dziedzicz uprawnienie", + "INHERITED_PERMISSIONS_BUTTON": "Odziedziczone uprawnienie" + }, + "TASK_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Wstaw identyfikator aplikacji", + "APP_ID_TYPE_ERROR": "Identyfikator aplikacji musi być liczbą.", + "NUMBER_TYPE_ERROR": "Wartość musi być liczbą.", + "NUMBER_GREATER_THAN": "Wartość musi być większa od lub równa wartości {{ value }}" + }, + "TOOLTIP_MESSAGE": { + "START_INPUT": "Strona początkowa" + } + }, + "PROCESS_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Wstaw identyfikator aplikacji", + "APP_ID_TYPE_ERROR": "Identyfikator aplikacji musi być liczbą.", + "NUMBER_GREATER_THAN": "Wartość musi być większa od lub równa wartości {{ value }}" + } + }, + "GROUP-TITLE1-TRANSLATION-KEY": "Tytuł niestandardowy — tłumaczenie pierwsze", + "GROUP-TITLE2-TRANSLATION-KEY": "Tytuł niestandardowy — tłumaczenie drugie", + "ERROR_CONTENT": { + "507": { + "TITLE": "Dysk ACS pełny", + "DESCRIPTION": "Zawartość przekracza limit łącznego przydziału miejsca w magazynie skonfigurowany w sieci lub systemie", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + } + }, + "PROCESS_LIST_CLOUD_DEMO": { + "TITLE": "PROCESS LIST CLOUD DEMO", + "CUSTOMIZE_FILTERS": "Dostosuj swój filtr" + }, + "TASK_LIST_CLOUD_DEMO": { + "CUSTOMIZE_FILTERS": "Dostosuj swój filtr" + }, + "PEOPLE_GROUPS_CLOUD": { + "SINGLE": "Wybór pojedynczy", + "MULTI": "Wybór wielokrotny", + "PRESELECTED_VALUE": "Wstępny wybór: ", + "ROLE": "Role: ", + "APP_NAME": "Nazwa aplikacji", + "APP_FILTER_MODE": "Filtruj według nazwy aplikacji", + "ROLE_FILTER_MODE": "Filtruj według roli", + "PRESELECT_VALIDATION": "Sprawdzanie poprawności wstępnego wyboru" + }, + "ABOUT": { + "TITLE": "Dodatki typu plugin", + "TABLE_HEADERS": { + "ID": "Identyfikator", + "NAME": "Nazwa", + "VERSION": "Wersja", + "VENDOR": "Sprzedawca", + "LICENSE": "Licencja", + "RUNTIME": "Środowisko uruchomieniowe", + "DESCRIPTION": "Opis" + } + }, + "SETTINGS_CLOUD": { + "MULTISELECTION": "Wybór wielokrotny", + "TESTING_MODE": "Tryb testowania", + "SELECTION_MODE": "Tryb wyboru", + "TASK_DETAILS_REDIRECTION": "Wyświetlaj szczegóły zadania po kliknięciu zadania", + "PROCESS_DETAILS_REDIRECTION": "Wyświetlaj szczegóły procesu po kliknięciu procesu" + } +} \ No newline at end of file diff --git a/demo-shell/resources/i18n/pt-BR.json b/demo-shell/resources/i18n/pt-BR.json index 724508a55c..3634595b2e 100644 --- a/demo-shell/resources/i18n/pt-BR.json +++ b/demo-shell/resources/i18n/pt-BR.json @@ -57,6 +57,7 @@ "APP_NAME": "Aplicativo Demo ADF", "HOME": "Página Inicial", "NODE-SELECTOR": "Seletor de nó", + "SITES": "Sites", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Trilha de navegação", "NOTIFICATIONS": "Notificações", @@ -93,7 +94,8 @@ "ICONS": "Ícones", "PEOPLE_GROUPS_CLOUD": "Nuvem de Pessoas/Grupo", "PEOPLE_CLOUD": "Componente da Nuvem de Pessoas", - "GROUPS_CLOUD": "Componente da Nuvem de Grupos" + "GROUPS_CLOUD": "Componente da Nuvem de Grupos", + "CONFIRM-DIALOG": "Caixa de diálogo de confirmação" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Seleção Múltipla", "TESTING_MODE": "Modo de Teste", "SELECTION_MODE": "Modo de Seleção", - "TASK_DETAILS_REDIRECTION": "Exibir detalhes da tarefa ao clicar na tarefa" + "TASK_DETAILS_REDIRECTION": "Exibir detalhes da tarefa ao clicar na tarefa", + "PROCESS_DETAILS_REDIRECTION": "Exibir detalhes do processo ao clicar no processo" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/ru.json b/demo-shell/resources/i18n/ru.json index 6a6314bfa3..3d74f5f158 100644 --- a/demo-shell/resources/i18n/ru.json +++ b/demo-shell/resources/i18n/ru.json @@ -12,7 +12,7 @@ }, "LOGOUT": { "TITLE": "Страница выхода из системы", - "SUB_TITLE": "Вы не вышли из системы", + "SUB_TITLE": "Вы вышли из системы", "LOGIN": "Войти", "HOME": "Домашняя" }, @@ -57,6 +57,7 @@ "APP_NAME": "Демонстрационное приложение ADF", "HOME": "Домашняя", "NODE-SELECTOR": "Селектор узлов", + "SITES": "Сайты", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "Иерархия", "NOTIFICATIONS": "Оповещения", @@ -93,7 +94,8 @@ "ICONS": "Значки", "PEOPLE_GROUPS_CLOUD": "Облако пользователей/групп", "PEOPLE_CLOUD": "Компонент облака «Пользователи»", - "GROUPS_CLOUD": "Компонент облака «Группы»" + "GROUPS_CLOUD": "Компонент облака «Группы»", + "CONFIRM-DIALOG": "Диалоговое окно подтверждения" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "Выбор нескольких", "TESTING_MODE": "Режим тестирования", "SELECTION_MODE": "Режим выбора", - "TASK_DETAILS_REDIRECTION": "Отображать подробные сведения о задаче при нажатии на задачу" + "TASK_DETAILS_REDIRECTION": "Отображать подробные сведения о задаче при нажатии на задачу", + "PROCESS_DETAILS_REDIRECTION": "Показывать сведения о процессе при нажатии на процессе" } } \ No newline at end of file diff --git a/demo-shell/resources/i18n/sv.json b/demo-shell/resources/i18n/sv.json new file mode 100644 index 0000000000..aefb447cfe --- /dev/null +++ b/demo-shell/resources/i18n/sv.json @@ -0,0 +1,324 @@ +{ + "APP": { + "INFO_DRAWER": { + "TITLE": "Detaljer", + "COMMENTS": "Kommentarer", + "PROPERTIES": "Egenskaper", + "VERSIONS": "Versioner" + }, + "HOME": { + "TITLE": "Angular-komponenter till Alfresco", + "DOCUMENTATION": "Dokumentation" + }, + "LOGOUT": { + "TITLE": "Utloggningssida", + "SUB_TITLE": "Du är nu utloggad", + "LOGIN": "Inloggning", + "HOME": "Hem" + }, + "ADF_VERSION_MANAGER": { + "ALLOW_DELETE": "Tillåt radering", + "SHOW_COMMENTS": "Visa kommentarer om versioner", + "ALLOW_DOWNLOAD": "Aktivera version nedladdning", + "READ_ONLY": "Skrivskyddad", + "COMMENTS": "Visa kommentarer" + }, + "PERSONAL-FILES": "Personliga filer", + "WARN-MULTIPLE-UPLOADS": "Visa varning för flera uppladningar", + "CUSTOM-PERMISSION-MESSAGE": "Aktivera anpassat behörighetersmeddelande", + "MEDIUM-TIME-FORMAT": "Aktivera mellantidsformat för dokumentlista", + "SEARCH": { + "RADIO": { + "NONE": "Ingen", + "ALL": "Alla", + "FOLDER": "Mapp", + "DOCUMENT": "Dokument" + } + } + }, + "title": "Välkommen", + "VERSION": { + "NO_PERMISSION": "Du har inte behörighet att hantera versioner av det här innehållet", + "NO_PERMISSION_EVENT": "Du har inte ${event.permission} behörighet att ${event.action} ${event.type}", + "CHOOSE_FILE": "Välj en fil för att se dess versioner", + "DIALOG": { + "CLOSE": "Stäng", + "TITLE": "Hantera versioner" + } + }, + "METADATA": { + "DIALOG": { + "CLOSE": "Stäng", + "TITLE": "Metadata" + } + }, + "APP_LAYOUT": { + "APP": "Program", + "APP_NAME": "ADF-demoprogram", + "HOME": "Hem", + "NODE-SELECTOR": "Nodväljare", + "SITES": "Webbplatser", + "CONTENT_SERVICES": "Content Services", + "BREADCRUMB": "Brödsmula", + "NOTIFICATIONS": "Aviseringar", + "TASK_LIST": "Uppgiftslista", + "PROCESS_LIST": "Processlista", + "PROCESS_CLOUD": "Activiti Cloud", + "CARD_VIEW": "CardView", + "PROCESS_SERVICES": "Process Services", + "LOGIN": "Inloggning", + "CUSTOM_SOURCES": "Anpassade källor", + "DATATABLE": "Datatabell", + "DATATABLE_LAZY": "Datatabell (lat)", + "DOCUMENT_LIST": "Dokumentlista", + "TEMPLATE": "Mall", + "FORM": "Formulär", + "FORM_LIST": "Formulärlista", + "FORM_LOADING": "Formulär läses in", + "UPLOADER": "Uppladdare", + "WEBSCRIPT": "Webbskript", + "TAG": "Tagg", + "TRASHCAN": "Papperskorg", + "SOCIAL": "Social", + "SETTINGS": "Inställningar", + "CONFIG-EDITOR": "Konfigurationseditor", + "OVERLAY_VIEWER": "Överdragsvisare", + "ABOUT": "Om", + "SEARCH": "Utvidgad sökning", + "EXTENDED_SEARCH_QUERY_BODY": "Utvidgad sökning med frågetext", + "WORD_TO_SEARCH": "Sökord", + "SEARCH_CREATED_BY": "Skapad av", + "SEARCH_SERVICE_APPROACH": "Kontrollera den här för att avaktivera indataegenskap och konfigurera genom att använda tjänsten", + "HEADER_DATA": "Sidhuvuddata", + "TREE_VIEW": "Trädvy", + "ICONS": "Ikoner", + "PEOPLE_GROUPS_CLOUD": "Personer/grupp moln", + "PEOPLE_CLOUD": "Personer moln-komponent", + "GROUPS_CLOUD": "Grupper moln-komponent", + "CONFIRM-DIALOG": "Bekräftelsedialog" + }, + "TRASHCAN": { + "ACTIONS": { + "DELETE_PERMANENT": "Radera permanent", + "RESTORE": "Återställ" + }, + "EMPTY_STATE": { + "TITLE": "Papperskorgen är tom", + "FIRST_TEXT": "Objekt du raderar flyttas till papperskorgen.", + "SECOND_TEXT": "Töm papperskorgen för att radera objekt permanent" + } + }, + "DOCUMENT_LIST": { + "MULTISELECT_CHECKBOXES": "Flera val (med kryssrutor)", + "THUMBNAILS": "Aktivera miniatyrbilder", + "ALLOW_DROP_FILES": "Aktivera släpp filer i en mapp", + "MULTIPLE_FILE_UPLOAD": "Uppladdning av flera filer", + "FOLDER_UPLOAD": "Mappuppladdning", + "CUSTOM_FILTER": "Anpassade tilläggsfilter", + "MAX_SIZE": "Maxstorlek filter", + "ENABLE_VERSIONING": "Aktivera versionering", + "DESCRIPTION_UPLOAD": "Aktivera uppladdning", + "ENABLE_INFINITE_SCROLL": "Aktivera oändlig skrollning", + "MULTISELECT_DESCRIPTION": "Använd Cmd (Mac) eller Ctrl (Windows) för att växla val av flera objekt", + "RECENT": { + "EMPTY_STATE": { + "TITLE": "Listan med de senaste filerna är tom" + }, + "TITLE": "De senaste filerna" + }, + "COLUMNS": { + "DISPLAY_NAME": "Visa namn", + "IS_LOCKED": "Lås", + "TAG": "Tagg", + "NODE_ID": "Nod-ID", + "CREATED_BY": "Skapad av", + "CREATED_ON": "Skapad den", + "CREATED": "Skapad", + "SIZE": "Storlek", + "DELETED_ON": "Raderad", + "DELETED_BY": "Raderad av" + }, + "TOOLBAR": { + "CARDVIEW": "Kortvyläge", + "SHARE_EDIT": "Redigera inställningar", + "NEW_FOLDER": "Ny mapp", + "EDIT_FOLDER": "Redigera mapp", + "DOWNLOAD": "Ladda ner", + "DELETE": "Radera", + "FAVORITES": "Lägg till favoriter", + "SHARE": "Dela", + "THEME": "Välj ett tema", + "SHOW_VERSION": "Visa version", + "HIDE_VERSION": "Dölj version", + "LISTVIEW": "Listvyläge", + "CREATE_LIBRARY": "Skapa bibliotek" + }, + "ACTIONS": { + "VERSIONS": "Hantera versioner", + "LOCK": "Lås", + "METADATA": "Info", + "DOWNLOAD": "Ladda ner", + "PERMISSION": "Behörighet", + "FOLDER": { + "COPY": "Kopiera", + "MOVE": "Flytta", + "DELETE": "Radera" + }, + "DOCUMENT": { + "COPY": "Kopiera", + "MOVE": "Flytta", + "DELETE": "Radera", + "PROCESS_ACTION": "Starta process" + } + } + }, + "DATATABLE": { + "RESET_DEFAULT": "Återställ till standard", + "ADD_ROW": "Lägg till rad", + "REPLACE_ROWS": "Ersätt rader", + "REPLACE_COLUMNS": "Ersätt kolumner", + "LOAD_NODE": "Ladda upp nod", + "MULTISELECT": "Flera val", + "MULTISELECT_DESCRIPTION": "Använd Cmd (Mac) eller Ctrl (Windows) för att växla val av flera objekt" + }, + "ANALYTICS_REPORT": { + "NO_REPORT_MESSAGE": "Ingen rapport vald. Välj en rapport från listan" + }, + "PS-TAB": { + "TASKS-TAB": "Uppgifter", + "PROCESSES-TAB": "Process", + "REPORTS-TAB": "Rapporter", + "SETTINGS-TAB": "Inställningar", + "START-TASK": "Starta uppgift", + "START-PROCESS": "Starta process", + "PROCESS-AUDIT-LOG": "Processgranskningslogg", + "TASK-AUDIT-LOG": "Uppgiftsgranskningslogg", + "TASK-SHOW-HEADER": "Visa detaljer rubrik" + }, + "PS_CLOUD_TAB": { + "APPS_TAB": "Program", + "SETTINGS_TAB": "Inställningar" + }, + "FORM-LIST": { + "STORE": "Lagra", + "RESTORE": "Återställ" + }, + "FORM-LOADING": { + "FORM_DATA": "Formulärdata", + "FORM_DATA_MESSAGE": "Ange värden för att fylla formuläret", + "TYPEAHEAD_PLACEHOLDER": "Typeahead", + "RADIO_PLACEHOLDER": "Radioknapp", + "SELECT_PLACEHOLDER": "DropDown" + }, + "LOGIN": { + "CONTENT_SERVICES": "Content Services", + "PROCESS_SERVICES": "Process Services", + "LOGIN_FOOTER": "Inloggningssidfot", + "SHOW_REMEMBERME": "Visa kom ihåg mig", + "SHOW_SUCCESS_ROUTE": "Visa framgångsväg", + "CUSTOM_LOGO": "Anpassad logotyp" + }, + "SEARCH": { + "RESULTS": "Sökresultat", + "NO_RESULT": "Inga resultat hittades", + "FACET_FIELDS": { + "TYPE": "1:Typ", + "SIZE": "2:Storlek", + "CREATOR": "3:Skapat av", + "MODIFIER": "4:Ändrat av", + "CREATED": "5:Skapad den" + }, + "FACET_QUERIES": { + "MY_FACET_QUERIES": "Mina facet-förfrågningar", + "CREATED_THIS_YEAR": "1.Skapad det här året", + "MIMETYPE": "2.Typ: HTML", + "XTRASMALL": "3.Storlek: extra small", + "SMALL": "4.Storlek: small", + "MEDIUM": "5.Storlek: medium", + "LARGE": "6.Storlek: large", + "XTRALARGE": "7.Storlek: extra large", + "XXTRALARGE": "8.Storlek: XX large" + } + }, + "SOCIAL": { + "LIKE": "Som komponent", + "RATING": "Klassificeringskomponent" + }, + "TAG": { + "LIST": "Lista taggar Content Services", + "INSERT": "Infoga nod-ID", + "NODE_LIST": "Tagglista per nod-ID" + }, + "DEMO_PERMISSION": { + "INHERIT_PERMISSION_BUTTON": "Ärv behörighet", + "INHERITED_PERMISSIONS_BUTTON": "Behörighet ärvt" + }, + "TASK_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Infoga program-ID", + "APP_ID_TYPE_ERROR": "Program-ID måste vara ett nummer", + "NUMBER_TYPE_ERROR": "Värdet måste vara ett nummer", + "NUMBER_GREATER_THAN": "Värdet måste vara större än eller lika med {{ value }}" + }, + "TOOLTIP_MESSAGE": { + "START_INPUT": "Startsida" + } + }, + "PROCESS_LIST_DEMO": { + "ERROR_MESSAGE": { + "APP_ID_REQUIRED_ERROR": "Infoga program-ID", + "APP_ID_TYPE_ERROR": "Program-ID måste vara ett nummer", + "NUMBER_GREATER_THAN": "Värdet måste vara större än eller lika med {{ value }}" + } + }, + "GROUP-TITLE1-TRANSLATION-KEY": "Anpassad titelöversättning ett", + "GROUP-TITLE2-TRANSLATION-KEY": "Anpassad titelöversättning två", + "ERROR_CONTENT": { + "507": { + "TITLE": "ACS disk full", + "DESCRIPTION": "Innehållet överskrider övergripande kvotbegränsning som är konfigurerad för nätverket eller systemet", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + } + }, + "PROCESS_LIST_CLOUD_DEMO": { + "TITLE": "PROCESS LIST CLOUD DEMO", + "CUSTOMIZE_FILTERS": "Anpassa ditt filter" + }, + "TASK_LIST_CLOUD_DEMO": { + "CUSTOMIZE_FILTERS": "Anpassa ditt filter" + }, + "PEOPLE_GROUPS_CLOUD": { + "SINGLE": "Enskilt val", + "MULTI": "Flerval", + "PRESELECTED_VALUE": "Förvälj: ", + "ROLE": "Roller: ", + "APP_NAME": "Programnamn", + "APP_FILTER_MODE": "Filterera på programnamn", + "ROLE_FILTER_MODE": "Filtrera på roll", + "PRESELECT_VALIDATION": "Förval validering" + }, + "ABOUT": { + "TITLE": "Plugins", + "TABLE_HEADERS": { + "ID": "ID", + "NAME": "Namn", + "VERSION": "Version", + "VENDOR": "Säljare", + "LICENSE": "Licens", + "RUNTIME": "Runtime", + "DESCRIPTION": "Beskrivning" + } + }, + "SETTINGS_CLOUD": { + "MULTISELECTION": "Flerval", + "TESTING_MODE": "Testläge", + "SELECTION_MODE": "Urvalsläge", + "TASK_DETAILS_REDIRECTION": "Visa uppgiftsdetaljer vid klick på uppgift", + "PROCESS_DETAILS_REDIRECTION": "Visa processinformation vid processklick" + } +} \ No newline at end of file diff --git a/demo-shell/resources/i18n/zh-CN.json b/demo-shell/resources/i18n/zh-CN.json index 045424f321..52daf4e307 100644 --- a/demo-shell/resources/i18n/zh-CN.json +++ b/demo-shell/resources/i18n/zh-CN.json @@ -57,6 +57,7 @@ "APP_NAME": "ADF 演示应用程序", "HOME": "主页", "NODE-SELECTOR": "节点选择器", + "SITES": "站点", "CONTENT_SERVICES": "Content Services", "BREADCRUMB": "面包屑", "NOTIFICATIONS": "通知", @@ -93,7 +94,8 @@ "ICONS": "图标", "PEOPLE_GROUPS_CLOUD": "人员/一组云", "PEOPLE_CLOUD": "人员云组件", - "GROUPS_CLOUD": "组云组件" + "GROUPS_CLOUD": "组云组件", + "CONFIRM-DIALOG": "确认对话" }, "TRASHCAN": { "ACTIONS": { @@ -316,6 +318,7 @@ "MULTISELECTION": "多重选择", "TESTING_MODE": "测试模式", "SELECTION_MODE": "选择模式", - "TASK_DETAILS_REDIRECTION": "单击任务时显示任务详情" + "TASK_DETAILS_REDIRECTION": "单击任务时显示任务详情", + "PROCESS_DETAILS_REDIRECTION": "单击流程时显示流程详细信息" } } \ No newline at end of file diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index 5d1cc26da5..9f6b48e01f 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -76,6 +76,26 @@ { "key": "ar", "label": "عربى" + }, + { + "key": "cz", + "label": "Czech" + }, + { + "key": "pl", + "label": "Polish" + }, + { + "key": "fi", + "label": "Finnish" + }, + { + "key": "da", + "label": "Danish" + }, + { + "key": "sv", + "label": "Swedish" } ], "search": { diff --git a/lib/content-services/i18n/ar.json b/lib/content-services/i18n/ar.json index 84bbac1c92..1cbc224205 100644 --- a/lib/content-services/i18n/ar.json +++ b/lib/content-services/i18n/ar.json @@ -128,6 +128,9 @@ "TITLE": "إلغاء التحميل", "TEXT": "قم بإيقاف التحميل وإزالة الملفات التي تم تحميلها بالفعل." } + }, + "ARIA-LABEL": { + "VERSION": "إصدار الملف" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "خطأ في خادم الإنترنت، حاول مرة أخرى أو اتصل بدعم تكنولوجيا المعلومات [500]", "504": "انتهلت مهلة الخادم، حاول مرة أخرى أو اتصل بدعم تكنولوجيا المعلومات [504]", "403": "أذونات غير كافية للتحميل في هذا المكان [403]", - "404": "مكان التحميل لم يعد موجودًا [404]" + "404": "مكان التحميل لم يعد موجودًا [404]", + "409": "يوجد بالفعل ملف يحمل الاسم ذاته [409]" }, "ARIA-LABEL": { "ERROR": "خطأ في التحميل" diff --git a/lib/content-services/i18n/cs.json b/lib/content-services/i18n/cs.json new file mode 100644 index 0000000000..e2e3f46352 --- /dev/null +++ b/lib/content-services/i18n/cs.json @@ -0,0 +1,366 @@ +{ + "ADF_VERSION_LIST": { + "ACTIONS": { + "RESTORE": "Obnovit", + "DELETE": "Odstranit", + "DOWNLOAD": "Stáhnout", + "UPLOAD": { + "TITLE": "Odeslat novou verzi", + "TOOLTIP": "Omezení: Pokud chcete vytvořit novou verzi souboru, musíte nahrát soubor se stejným názvem", + "MAJOR": "hlavní změny (2.0)", + "MINOR": "vedlejší změny (1.1)", + "COMMENT": "Vložit komentář", + "ADD": "Přidat novou verzi", + "CANCEL": "Zrušit" + } + }, + "CONFIRM_DELETE": { + "TITLE": "Odstranit verzi", + "MESSAGE": "Odstraněné verze souboru nelze obnovit. Chcete pokračovat?", + "YES_LABEL": "Ano", + "NO_LABEL": "Ne" + } + }, + "ADF_DROPDOWN": { + "LOADING": "Načítání..." + }, + "ADF_CONFIRM_DIALOG": { + "TITLE": "Potvrdit", + "ACTION": "Chcete pokračovat?", + "YES_LABEL": "Ano", + "NO_LABEL": "Ne" + }, + "ADF-DOCUMENT-LIST": { + "EMPTY": { + "HEADER": "Tato složka je prázdná" + }, + "NO_PERMISSION": "Nemáte potřebná oprávněni pro zobrazení tohoto souboru nebo složky.", + "LAYOUT": { + "CREATED": "Vytvořeno", + "THUMBNAIL": "Miniatura", + "NAME": "Název", + "LOCATION": "Umístění", + "SIZE": "Velikost", + "DELETED_ON": "Odstraněno", + "DELETED_BY": "Odstranil(a)", + "STATUS": "Stav", + "MODIFIED_ON": "Změněno", + "MODIFIED_BY": "Změnil(a)", + "SHARED_BY": "Sdílel(a)", + "LOAD_MORE": "Načíst další" + }, + "MENU_ACTIONS": { + "VIEW": "Zobrazit", + "REMOVE": "Odstranit", + "DOWNLOAD": "Stáhnout" + } + }, + "ALFRESCO_DOCUMENT_LIST": { + "BUTTON": { + "ACTION_CREATE": "Vytvořit...", + "ACTION_NEW_FOLDER": "Nová složka", + "CREATE": "Vytvořit", + "CANCEL": "Zrušit" + } + }, + "DROPDOWN": { + "PLACEHOLDER_LABEL": "Seznam společných míst", + "MY_FILES_OPTION": "Moje soubory" + }, + "NODE_SELECTOR": { + "CANCEL": "Zrušit", + "CHOOSE": "Vybrat", + "COPY": "Kopírovat", + "COPY_ITEM": "Zkopírovat položku '{{ name }}' do...", + "MOVE": "Přesunout", + "MOVE_ITEM": "Přesunout položku '{{ name }}' do...", + "NO_RESULTS": "Nebyly nalezeny žádné výsledky", + "SEARCH": "Hledat", + "SEARCH_RESULTS": "Výsledky hledání", + "SELECT_LOCATION": "Vybrat umístění" + }, + "OPERATION": { + "SUCCESS": { + "CONTENT": { + "COPY": "Kopírování proběhlo úspěšně", + "MOVE": "Přesunutí proběhlo úspěšně" + }, + "FOLDER": { + "COPY": "Kopírování proběhlo úspěšně", + "MOVE": "Přesunutí proběhlo úspěšně" + } + }, + "ERROR": { + "CONFLICT": "Tento název se již používá. Zvolte jiný.", + "UNKNOWN": "Akce se nezdařila. Zkuste to znovu nebo se obraťte na oddělení IT.", + "PERMISSION": "Nemáte dostatečná přístupová oprávnění." + } + }, + "TAG": { + "LABEL": { + "NEWTAG": "Nový tag" + }, + "MESSAGES": { + "EXIST": "Tag již existuje" + }, + "BUTTON": { + "ADD": "Přidat tag" + } + }, + "ADF_FILE_UPLOAD": { + "BUTTON": { + "MINIMIZE": "Minimalizovat", + "MAXIMIZE": "Maximalizovat", + "CLOSE": "Zavřít", + "CANCEL_ALL": "Zrušit odesílání", + "CANCEL_FILE": "Zrušit odesílání", + "REMOVE_FILE": "Odebrat odeslaný soubor" + }, + "STATUS": { + "FILE_CANCELED_STATUS": "Zrušeno" + }, + "CONFIRMATION": { + "BUTTON": { + "CANCEL": "Ano", + "CONTINUE": "Ne" + }, + "MESSAGE": { + "TITLE": "Zrušit odesílání", + "TEXT": "Zastavit odesílání a odebrat již odeslané soubory." + } + }, + "ARIA-LABEL": { + "VERSION": "Verze souboru" + } + }, + "FILE_UPLOAD": { + "BUTTON": { + "UPLOAD_FILE": "Odeslat soubor", + "UPLOAD_FOLDER": "Odeslat složku" + }, + "VERSION": { + "MESSAGES": { + "NO_ACCEPTED_FILE_TYPES": "Mějte na paměti, že nastavení „acceptedFilesType“ nemá žádný vliv na odeslané nové verze. Typ souboru bude shodný s původním souborem.", + "INCOMPATIBLE_VERSION": "Jako novou verzi je možné odeslat pouze soubor stejného typu." + } + }, + "MESSAGES": { + "UPLOAD_CANCELED": "Odeslání zrušeno", + "UPLOAD_PROGRESS": "Odesláno: {{ completed }} / {{ total }}", + "UPLOAD_ERROR": "Některé položky ({{ total }}) se nepodařilo odeslat", + "UPLOAD_ERRORS": "Některé položky ({{ total }}) se nepodařilo odeslat", + "PROGRESS": "Probíhá odesílání...", + "FOLDER_ALREADY_EXIST": "Složka „{0}“ již existuje", + "FOLDER_NOT_SUPPORTED": "Váš prohlížeč nepodporuje odeslání souboru. Zkuste použít jiný prohlížeč.", + "REMOVE_FILE_ERROR": "Soubor „{{ fileName }}“ se nepodařilo odebrat. Zkuste to znovu nebo se obraťte na oddělení IT.", + "REMOVE_FILES_ERROR": "Některé soubory ({{ total }}) se nepodařilo odebrat. Zkuste to znovu nebo se obraťte na oddělení IT.", + "EXCEED_MAX_FILE_SIZE": "Velikost souboru „{{ fileName }}“ překračuje povolený limit" + }, + "ACTION": { + "UNDO": "Zpět" + }, + "ERRORS": { + "GENERIC": "Odeslání se nezdařilo. Pokud problém přetrvá, obraťte se na oddělení IT.", + "500": "Interní chyba serveru. Pokus opakujte nebo se obraťte na podporu IT [500]", + "504": "Vypršel časový limit serveru. Pokus opakujte nebo se obraťte na podporu IT [504]", + "403": "Nedostatečná oprávnění pro odeslání do tohoto umístění [403]", + "404": "Umístění pro odesílání položek již neexistuje [404]", + "409": "Soubor se stejným názvem již existuje [409]" + }, + "ARIA-LABEL": { + "ERROR": "Chyba při nahrávání" + } + }, + "WEBSCRIPT": { + "ERROR": "Akci nelze dokončit. Sdělte oddělení IT následující zprávu: Chyba při deserializaci „{{data}}“ ({{contentType}})." + }, + "SEARCH": { + "CONTROL": {}, + "BUTTON": { + "TOOLTIP": "Hledat", + "ARIA-LABEL": "Tlačítko Hledat" + }, + "INPUT": { + "ARIA-LABEL": "Zadání hledaného výrazu" + }, + "RESULTS": { + "SUMMARY": "Nalezeno několik výsledků ({{numResults}}) pro hledaný výraz „{{searchTerm}}“", + "NONE": "Nenalezeny žádné výsledky pro hledaný výraz „{{searchTerm}}“", + "ERROR": "Během hledání došlo k problému. Zkuste to znovu.", + "COLUMNS": { + "NAME": "Zobrazované jméno", + "MODIFIED_BY": "Změnil(a)", + "MODIFIED_AT": "Upraveno k" + } + }, + "FILTER": { + "ACTIONS": { + "CLEAR": "Vymazat", + "APPLY": "Použít", + "CLEAR-ALL": "Vymazat vše", + "SHOW-MORE": "Zobrazit více", + "SHOW-LESS": "Zobrazit méně", + "FILTER-CATEGORY": "Filtrovat kategorii" + }, + "BUTTONS": { + "CLEAR-ALL": { + "LABEL": "Vymazat vše", + "TOOLTIP": "Tím se odstraní všechny výběry" + }, + "RESET-ALL": { + "LABEL": "Resetovat vše", + "TOOLTIP": "Resetuje všechny výběry a všechny filtry" + } + }, + "RANGE": { + "FROM": "Od", + "TO": "Do", + "FROM-DATE": "Od", + "TO-DATE": "Do" + }, + "VALIDATION": { + "REQUIRED-VALUE": "Požadovaná hodnota", + "NO-DAYS": "Nejsou určeny žádné dny.", + "INVALID-FORMAT": "Neplatný formát", + "INVALID-DATE": "Neplatné datum. Datum musí být ve formátu '{{ requiredFormat }}'.", + "BEYOND-MAX-DATE": "Datum nesplňuje limit pro nejvzdálenější datum." + } + }, + "ICONS": { + "ft_ic_raster_image": "Soubor s obrázkem", + "ft_ic_pdf": "Dokument PDF", + "ft_ic_ms_excel": "Soubor Microsoft Excel", + "ft_ic_ms_word": "Dokument Microsoft Word", + "ft_ic_ms_powerpoint": "Soubor Microsoft PowerPoint", + "ft_ic_video": "Soubor s videem", + "ft_ic_document": "Soubor s dokumentem", + "ft_ic_website": "Webový zdroj", + "ft_ic_archive": "Soubor s archivem", + "ft_ic_presentation": "Soubor s prezentací", + "ft_ic_spreadsheet": "Soubor s tabulkou" + }, + "DOCUMENT_LIST": { + "COLUMNS": { + "DISPLAY_NAME": "Zobrazované jméno", + "CREATED_BY": "Vytvořil(a)", + "CREATED_ON": "Vytvořeno" + }, + "ACTIONS": { + "FOLDER": { + "DELETE": "Odstranit", + "MOVE": "Přesunout", + "COPY": "Kopírovat" + }, + "DOCUMENT": { + "DOWNLOAD": "Stáhnout", + "DELETE": "Odstranit", + "MOVE": "Přesunout", + "COPY": "Kopírovat", + "PROCESS_ACTION": "Zahájit proces" + } + } + } + }, + "PERMISSION": { + "LACKOF": "Nemáte potřebná oprávnění „{{permission}}“ k použití akce „{{action}}“ pro „{{type}}“" + }, + "METADATA": { + "BASIC": { + "HEADER": "Vlastnosti", + "NAME": "Název", + "TITLE": "Označení", + "DESCRIPTION": "Popis", + "AUTHOR": "Autor", + "MIMETYPE": "Typ MIME", + "SIZE": "Velikost", + "CREATOR": "Autor", + "CREATED_DATE": "Datum vytvoření", + "MODIFIER": "Upravující", + "MODIFIED_DATE": "Datum úpravy" + } + }, + "SHARE": { + "PUBLIC-LINK": "Veřejný odkaz", + "DIALOG-TITLE": "Sdílet", + "DESCRIPTION": "Kliknutím na následující odkaz jej zkopírujete do schránky.", + "TITLE": "Odkaz pro sdílení", + "EXPIRES": "Platnost vyprší k", + "CLIPBOARD-MESSAGE": "Odkaz zkopírován do schránky", + "CLOSE": "Zavřít", + "CONFIRMATION": { + "DIALOG-TITLE": "Odebrat tento sdílený odkaz", + "MESSAGE": "Tento odkaz se odstraní a při dalším sdílení tohoto souboru se vytvoří odkaz nový", + "CANCEL": "Zrušit", + "REMOVE": "Odstranit" + } + }, + "PERMISSION_MANAGER": { + "PERMISSION_DISPLAY": { + "INHERITED": "S dědičností", + "AUTHORITY_ID": "ID autority", + "ROLE": "Role", + "LOCALLY_SET": "Místní nastavení", + "NO_PERMISSIONS": "Bez oprávnění" + }, + "ADD-PERMISSION": { + "SEARCH": "Hledat", + "TYPE-MESSAGE": "Začněte hledat skupiny nebo osoby jednoduše zadáním textu", + "NO-RESULT": "Hledanému výrazu neodpovídají žádné výsledky", + "ADD-ACTION": "Přidat", + "CLOSE-ACTION": "Zavřít", + "BASE-DIALOG-TITLE": "Vyhledejte skupinu nebo osoby, které chcete přidat...", + "EVERYONE": "Každý" + }, + "ERROR": { + "DUPLICATE-PERMISSION": "Alespoň jedno z vámi nastavených oprávnění již existuje: {{list}}", + "NOT-ALLOWED": "Nemáte oprávnění měnit oprávnění" + } + }, + "ADF-TREE-VIEW": { + "MISSING-ID": "Nebylo zadáno ID uzlu!" + }, + "LIBRARY": { + "DIALOG": { + "CREATE_TITLE": "Vytvořit knihovnu", + "CREATE": "Vytvořit", + "UPDATE": "Aktualizovat", + "EDIT": "Upravit", + "CANCEL": "Zrušit", + "FORM": { + "DESCRIPTION": "Popis", + "SITE_ID": "ID knihovny", + "NAME": "Název", + "VISIBILITY": "Viditelnost" + } + }, + "ROLE": { + "MANAGER": "Správce", + "COLLABORATOR": "Spolupracovník", + "CONTRIBUTOR": "Přispěvatel", + "CONSUMER": "Spotřebitel" + }, + "VISIBILITY": { + "PRIVATE": "Soukromé", + "PUBLIC": "Veřejné", + "MODERATED": "Moderováno" + }, + "HINTS": { + "SITE_TITLE_EXISTS": "Název knihovny se již používá" + }, + "ERRORS": { + "GENERIC": "Došlo k problému", + "EXISTENT_SITE": "Toto ID knihovny není dostupné. Použijte jiné ID.", + "CONFLICT": "ID knihovny se již používá. Prohlédněte si obsah koše.", + "ID_TOO_LONG": "Název URL může obsahovat maximálně 72 znaků", + "DESCRIPTION_TOO_LONG": "Popis může obsahovat maximálně 512 znaků", + "TITLE_TOO_LONG": "Označení může obsahovat maximálně 256 znaků", + "TITLE_TOO_SHORT": "Označení musí obsahovat alespoň 2 znaky", + "ILLEGAL_CHARACTERS": "Používejte pouze písmena a čísla", + "ONLY_SPACES": "Název knihovny nemůže obsahovat pouze mezery", + "LIBRARY_UPDATE_ERROR": "Při pokusu upravit vlastnosti knihovny došlo k chybě" + }, + "SUCCESS": { + "LIBRARY_UPDATED": "Vlastnosti knihovny byly upraveny" + } + } +} \ No newline at end of file diff --git a/lib/content-services/i18n/da.json b/lib/content-services/i18n/da.json new file mode 100644 index 0000000000..42f9a84828 --- /dev/null +++ b/lib/content-services/i18n/da.json @@ -0,0 +1,366 @@ +{ + "ADF_VERSION_LIST": { + "ACTIONS": { + "RESTORE": "Gendan", + "DELETE": "Slet", + "DOWNLOAD": "Download", + "UPLOAD": { + "TITLE": "Upload ny version", + "TOOLTIP": "Begrænsning: Du skal uploade en fil med det samme navn for at oprette en ny version af filen", + "MAJOR": "større ændringer (2.0)", + "MINOR": "mindre ændringer (1.1)", + "COMMENT": "Skriv en kommentar", + "ADD": "Tilføj ny version", + "CANCEL": "Annuller" + } + }, + "CONFIRM_DELETE": { + "TITLE": "Slet version", + "MESSAGE": "Slettede filversioner kan ikke gendannes. Vil du fortsætte?", + "YES_LABEL": "Ja", + "NO_LABEL": "Nej" + } + }, + "ADF_DROPDOWN": { + "LOADING": "Indlæser ..." + }, + "ADF_CONFIRM_DIALOG": { + "TITLE": "Bekræft", + "ACTION": "Vil du fortsætte?", + "YES_LABEL": "Ja", + "NO_LABEL": "Nej" + }, + "ADF-DOCUMENT-LIST": { + "EMPTY": { + "HEADER": "Denne mappe er tom" + }, + "NO_PERMISSION": "Du har ikke tilladelse til at se denne fil eller mappe.", + "LAYOUT": { + "CREATED": "Oprettet", + "THUMBNAIL": "Miniaturevisning", + "NAME": "Navn", + "LOCATION": "Placering", + "SIZE": "Størrelse", + "DELETED_ON": "Slettet", + "DELETED_BY": "Slettet af", + "STATUS": "Status", + "MODIFIED_ON": "Ændret", + "MODIFIED_BY": "Ændret af", + "SHARED_BY": "Delt af", + "LOAD_MORE": "Indlæs flere" + }, + "MENU_ACTIONS": { + "VIEW": "Vis", + "REMOVE": "Fjern", + "DOWNLOAD": "Download" + } + }, + "ALFRESCO_DOCUMENT_LIST": { + "BUTTON": { + "ACTION_CREATE": "Opret...", + "ACTION_NEW_FOLDER": "Ny mappe", + "CREATE": "Opret", + "CANCEL": "Annuller" + } + }, + "DROPDOWN": { + "PLACEHOLDER_LABEL": "Siteliste", + "MY_FILES_OPTION": "Mine filer" + }, + "NODE_SELECTOR": { + "CANCEL": "Annuller", + "CHOOSE": "Vælg", + "COPY": "Kopiér", + "COPY_ITEM": "Kopiér '{{ name }}' til...", + "MOVE": "Flyt", + "MOVE_ITEM": "Flyt '{{ name }}' til...", + "NO_RESULTS": "Der blev ikke fundet nogen resultater", + "SEARCH": "Søg", + "SEARCH_RESULTS": "Søgeresultater", + "SELECT_LOCATION": "Vælg placering" + }, + "OPERATION": { + "SUCCESS": { + "CONTENT": { + "COPY": "Kopieringen er fuldført", + "MOVE": "Flytningen er fuldført" + }, + "FOLDER": { + "COPY": "Kopieringen er fuldført", + "MOVE": "Flytningen er fuldført" + } + }, + "ERROR": { + "CONFLICT": "Navnet er allerede i brug. Prøv et andet navn.", + "UNKNOWN": "Handlingen blev ikke fuldført. Prøv igen, eller kontakt dit it-team.", + "PERMISSION": "Du har ikke adgang til dette." + } + }, + "TAG": { + "LABEL": { + "NEWTAG": "Ny tag" + }, + "MESSAGES": { + "EXIST": "Denne tag findes allerede" + }, + "BUTTON": { + "ADD": "Tilføj tag" + } + }, + "ADF_FILE_UPLOAD": { + "BUTTON": { + "MINIMIZE": "Minimer", + "MAXIMIZE": "Maksimer", + "CLOSE": "Luk", + "CANCEL_ALL": "Annuller uploads", + "CANCEL_FILE": "Annuller upload", + "REMOVE_FILE": "Fjern den uploadede fil" + }, + "STATUS": { + "FILE_CANCELED_STATUS": "Annulleret" + }, + "CONFIRMATION": { + "BUTTON": { + "CANCEL": "Ja", + "CONTINUE": "Nej" + }, + "MESSAGE": { + "TITLE": "Annuller upload", + "TEXT": "Stop med at uploade, og fjern de filer, der allerede er uploadet." + } + }, + "ARIA-LABEL": { + "VERSION": "Filversion" + } + }, + "FILE_UPLOAD": { + "BUTTON": { + "UPLOAD_FILE": "Upload fil", + "UPLOAD_FOLDER": "Upload mappe" + }, + "VERSION": { + "MESSAGES": { + "NO_ACCEPTED_FILE_TYPES": "Bemærk, at indstillingen \"acceptedFilesType\" ikke har nogen effekt for upload af nye versioner. Filtypen vil være den samme som for den oprindelige fil.", + "INCOMPATIBLE_VERSION": "Det er kun en fil med samme filtype, der kan uploades som en ny version." + } + }, + "MESSAGES": { + "UPLOAD_CANCELED": "Upload annulleret", + "UPLOAD_PROGRESS": "{{ completed }}/{{ total }} uploadet", + "UPLOAD_ERROR": "{{ total }} kunne ikke uploades", + "UPLOAD_ERRORS": "{{ total }} kunne ikke uploades", + "PROGRESS": "Upload i gang...", + "FOLDER_ALREADY_EXIST": "Mappen {0} findes allerede", + "FOLDER_NOT_SUPPORTED": "Browseren understøtter ikke upload af mapper. Prøv en anden browser", + "REMOVE_FILE_ERROR": "{{ fileName }} kunne ikke fjernes. Prøv igen, eller kontakt din it-afdeling.", + "REMOVE_FILES_ERROR": "{{ total }} kunne ikke fjernes. Prøv igen, eller kontakt din it-afdeling.", + "EXCEED_MAX_FILE_SIZE": "Filen {{ fileName }} er større end den tilladte filstørrelse" + }, + "ACTION": { + "UNDO": "Fortryd" + }, + "ERRORS": { + "GENERIC": "Der kunne ikke uploades. Kontakt din it-afdeling, hvis problemet fortsætter", + "500": "Der opstod en intern serverfejl. Prøv igen, eller kontakt it-support [500]", + "504": "Der opstod en timeout for serveren. Prøv igen, eller kontakt it-support [504]", + "403": "Du har ikke de nødvendige tilladelser til at uploade på denne placering [403]", + "404": "Uploadplaceringen findes ikke længere [404]", + "409": "Der findes allerede en fil med dette navn [409]" + }, + "ARIA-LABEL": { + "ERROR": "Uploadfejl" + } + }, + "WEBSCRIPT": { + "ERROR": "Handlingen kunne ikke fuldføres. Giv følgende meddelelse til din it-afdeling: Fejl under deserialisering af {{data}} som {{contentType}}" + }, + "SEARCH": { + "CONTROL": {}, + "BUTTON": { + "TOOLTIP": "Søg", + "ARIA-LABEL": "Søgeknap" + }, + "INPUT": { + "ARIA-LABEL": "Søgeinput" + }, + "RESULTS": { + "SUMMARY": "{{numResults}} resultater fundet for {{searchTerm}}", + "NONE": "Der blev ikke fundet nogen resultater for {{searchTerm}}", + "ERROR": "Der er opstået et problem under søgningen – prøv igen.", + "COLUMNS": { + "NAME": "Visningsnavn", + "MODIFIED_BY": "Ændret af", + "MODIFIED_AT": "Ændret kl." + } + }, + "FILTER": { + "ACTIONS": { + "CLEAR": "Ryd", + "APPLY": "Anvend", + "CLEAR-ALL": "Ryd alt", + "SHOW-MORE": "Vis flere", + "SHOW-LESS": "Vis færre", + "FILTER-CATEGORY": "Filterkategori" + }, + "BUTTONS": { + "CLEAR-ALL": { + "LABEL": "Ryd alt", + "TOOLTIP": "Denne handling fjerner alle valg" + }, + "RESET-ALL": { + "LABEL": "Nulstil alle", + "TOOLTIP": "Denne handling nulstiller alle valg og filtre" + } + }, + "RANGE": { + "FROM": "Fra", + "TO": "Til", + "FROM-DATE": "Fra", + "TO-DATE": "Til" + }, + "VALIDATION": { + "REQUIRED-VALUE": "Påkrævet værdi", + "NO-DAYS": "Der er ikke valgt nogen dage.", + "INVALID-FORMAT": "Ugyldigt format", + "INVALID-DATE": "Ugyldig dato. Datoen skal være i formatet '{{ requiredFormat }}'", + "BEYOND-MAX-DATE": "Datoen er senere end tilladt." + } + }, + "ICONS": { + "ft_ic_raster_image": "Billedfil", + "ft_ic_pdf": "PDF-dokument", + "ft_ic_ms_excel": "Microsoft Excel-fil", + "ft_ic_ms_word": "Microsoft Word-dokument", + "ft_ic_ms_powerpoint": "Microsoft PowerPoint-fil", + "ft_ic_video": "Videofil", + "ft_ic_document": "Dokumentfil", + "ft_ic_website": "Webressource", + "ft_ic_archive": "Arkivfil", + "ft_ic_presentation": "Præsentationsfil", + "ft_ic_spreadsheet": "Regnearksfil" + }, + "DOCUMENT_LIST": { + "COLUMNS": { + "DISPLAY_NAME": "Visningsnavn", + "CREATED_BY": "Oprettet af", + "CREATED_ON": "Oprettet" + }, + "ACTIONS": { + "FOLDER": { + "DELETE": "Slet", + "MOVE": "Flyt", + "COPY": "Kopiér" + }, + "DOCUMENT": { + "DOWNLOAD": "Download", + "DELETE": "Slet", + "MOVE": "Flyt", + "COPY": "Kopiér", + "PROCESS_ACTION": "Start proces" + } + } + } + }, + "PERMISSION": { + "LACKOF": "Du har ikke tilladelsen {{permission}} til at {{action}} {{type}}" + }, + "METADATA": { + "BASIC": { + "HEADER": "Egenskaber", + "NAME": "Navn", + "TITLE": "Titel", + "DESCRIPTION": "Beskrivelse", + "AUTHOR": "Forfatter", + "MIMETYPE": "Mimetype", + "SIZE": "Størrelse", + "CREATOR": "Oprettet af", + "CREATED_DATE": "Oprettelsesdato", + "MODIFIER": "Ændret af", + "MODIFIED_DATE": "Ændringsdato" + } + }, + "SHARE": { + "PUBLIC-LINK": "Offentligt link", + "DIALOG-TITLE": "Del", + "DESCRIPTION": "Klik på linket nedenfor for at kopiere det til udklipsholderen.", + "TITLE": "Link til deling", + "EXPIRES": "Udløber den", + "CLIPBOARD-MESSAGE": "Link kopieret til udklipsholderen", + "CLOSE": "Luk", + "CONFIRMATION": { + "DIALOG-TITLE": "Fjern dette delte link", + "MESSAGE": "Dette link bliver slettet, og der oprettes et nyt link, når filen deles næste gang", + "CANCEL": "Annuller", + "REMOVE": "Fjern" + } + }, + "PERMISSION_MANAGER": { + "PERMISSION_DISPLAY": { + "INHERITED": "Nedarvet", + "AUTHORITY_ID": "Autoritets-id", + "ROLE": "Rolle", + "LOCALLY_SET": "Angivet lokalt", + "NO_PERMISSIONS": "Ingen tilladelser" + }, + "ADD-PERMISSION": { + "SEARCH": "Søg", + "TYPE-MESSAGE": "Skriv noget for at begynde at søge efter grupper eller personer", + "NO-RESULT": "Der blev ikke fundet nogen resultater for denne søgning", + "ADD-ACTION": "Tilføj", + "CLOSE-ACTION": "Luk", + "BASE-DIALOG-TITLE": "Søg efter en gruppe eller personer, du vil tilføje...", + "EVERYONE": "Alle" + }, + "ERROR": { + "DUPLICATE-PERMISSION": "En eller flere af de angivne tilladelser findes allerede: {{list}}", + "NOT-ALLOWED": "Du har ikke tilladelse til at ændre tilladelserne" + } + }, + "ADF-TREE-VIEW": { + "MISSING-ID": "Der er ikke angivet et node-id!" + }, + "LIBRARY": { + "DIALOG": { + "CREATE_TITLE": "Opret bibliotek", + "CREATE": "Opret", + "UPDATE": "Opdater", + "EDIT": "Rediger", + "CANCEL": "Annuller", + "FORM": { + "DESCRIPTION": "Beskrivelse", + "SITE_ID": "Biblioteks-id", + "NAME": "Navn", + "VISIBILITY": "Synlighed" + } + }, + "ROLE": { + "MANAGER": "Chef", + "COLLABORATOR": "Samarbejdspartner", + "CONTRIBUTOR": "Bidragyder", + "CONSUMER": "Forbruger" + }, + "VISIBILITY": { + "PRIVATE": "Privat", + "PUBLIC": "Offentlig", + "MODERATED": "Modereret" + }, + "HINTS": { + "SITE_TITLE_EXISTS": "Biblioteksnavnet er allerede i brug" + }, + "ERRORS": { + "GENERIC": "Der er opstået et problem", + "EXISTENT_SITE": "Dette biblioteks-id er ikke tilgængeligt. Prøv et andet biblioteks-id.", + "CONFLICT": "Dette biblioteks-id er allerede i brug. Se eventuelt papirkurven.", + "ID_TOO_LONG": "URL-navnet må ikke være på mere end 72 tegn", + "DESCRIPTION_TOO_LONG": "Beskrivelsen må ikke være på mere end 512 tegn", + "TITLE_TOO_LONG": "Titlen må ikke være på mere end 256 tegn", + "TITLE_TOO_SHORT": "Titlen skal være på mindst 2 tegn", + "ILLEGAL_CHARACTERS": "Brug kun tal og bogstaver", + "ONLY_SPACES": "Biblioteksnavnet skal indeholde andet end mellemrum", + "LIBRARY_UPDATE_ERROR": "Der opstod fejl under opdatering af egenskaberne for biblioteket" + }, + "SUCCESS": { + "LIBRARY_UPDATED": "Egenskaberne for biblioteket er blevet opdateret" + } + } +} \ No newline at end of file diff --git a/lib/content-services/i18n/de.json b/lib/content-services/i18n/de.json index 0a24c4f11d..ce44d62b53 100644 --- a/lib/content-services/i18n/de.json +++ b/lib/content-services/i18n/de.json @@ -128,6 +128,9 @@ "TITLE": "Upload abbrechen", "TEXT": "Beenden Sie das Hochladen und entfernen Sie bereits hochgeladene Dateien." } + }, + "ARIA-LABEL": { + "VERSION": "Dateiversion" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Interner Serverfehler. Versuchen Sie es noch einmal oder wenden Sie sich an den IT-Support [500]", "504": "Server-Timeout. Versuchen Sie es noch einmal oder wenden Sie sich an den IT-Support [504]", "403": "Sie verfügen nicht die erforderlichen Benutzerrechte, um etwas an diesen Speicherort hochzuladen [403]", - "404": "Speicherort für Upload nicht mehr vorhanden [404]" + "404": "Speicherort für Upload nicht mehr vorhanden [404]", + "409": "Eine Datei mit diesem Namen gibt es bereits [409]" }, "ARIA-LABEL": { "ERROR": "Fehler beim Hochladen" diff --git a/lib/content-services/i18n/es.json b/lib/content-services/i18n/es.json index bdfe2d2f91..45c18da03f 100644 --- a/lib/content-services/i18n/es.json +++ b/lib/content-services/i18n/es.json @@ -128,6 +128,9 @@ "TITLE": "Cancelar carga", "TEXT": "Detener la carga y eliminar los ficheros ya cargados." } + }, + "ARIA-LABEL": { + "VERSION": "Versión del fichero" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Error de servidor interno; vuelva a intentarlo o póngase en contacto con el equipo de TI", "504": "Se ha agotado el tiempo de espera del servidor; póngase en contacto con el equipo de asistencia de TI [504]", "403": "Permisos insuficientes para cargar en esta ubicación [403]", - "404": "La ubicación de carga ya no existe [404]" + "404": "La ubicación de carga ya no existe [404]", + "409": "Ya existe un fichero con el mismo nombre [409]" }, "ARIA-LABEL": { "ERROR": "Error de carga" diff --git a/lib/content-services/i18n/fi.json b/lib/content-services/i18n/fi.json new file mode 100644 index 0000000000..df28175f0d --- /dev/null +++ b/lib/content-services/i18n/fi.json @@ -0,0 +1,366 @@ +{ + "ADF_VERSION_LIST": { + "ACTIONS": { + "RESTORE": "Palauta", + "DELETE": "Poista", + "DOWNLOAD": "Lataa", + "UPLOAD": { + "TITLE": "Lataa uusi versio", + "TOOLTIP": "Rajoitus: jos haluat luoda tiedostosta uuden version, sinun täytyy ladata tiedosto samalla nimellä", + "MAJOR": "merkittäviä muutoksia (2.0)", + "MINOR": "vähäisiä muutoksia (1.1)", + "COMMENT": "Jätä kommentti", + "ADD": "Lisää uusi versio", + "CANCEL": "Peruuta" + } + }, + "CONFIRM_DELETE": { + "TITLE": "Poista versio", + "MESSAGE": "Poistettuja tiedostoversioita ei voi palauttaa. Jatketaanko?", + "YES_LABEL": "Kyllä", + "NO_LABEL": "Ei" + } + }, + "ADF_DROPDOWN": { + "LOADING": "Ladataan..." + }, + "ADF_CONFIRM_DIALOG": { + "TITLE": "Vahvista", + "ACTION": "Haluatko jatkaa?", + "YES_LABEL": "Kyllä", + "NO_LABEL": "Ei" + }, + "ADF-DOCUMENT-LIST": { + "EMPTY": { + "HEADER": "Tämä kansio on tyhjä" + }, + "NO_PERMISSION": "Sinulla ei ole oikeutta tarkastella tätä tiedostoa tai kansiota.", + "LAYOUT": { + "CREATED": "Luotu", + "THUMBNAIL": "Pikkukuva", + "NAME": "Nimi", + "LOCATION": "Sijainti", + "SIZE": "Koko", + "DELETED_ON": "Poistettu", + "DELETED_BY": "Poistaja:", + "STATUS": "Tila", + "MODIFIED_ON": "Muokattu", + "MODIFIED_BY": "Muokkaaja:", + "SHARED_BY": "Jakaja:", + "LOAD_MORE": "Lataa lisää" + }, + "MENU_ACTIONS": { + "VIEW": "Näytä", + "REMOVE": "Poista", + "DOWNLOAD": "Lataa" + } + }, + "ALFRESCO_DOCUMENT_LIST": { + "BUTTON": { + "ACTION_CREATE": "Luo...", + "ACTION_NEW_FOLDER": "Uusi kansio", + "CREATE": "Luo", + "CANCEL": "Peruuta" + } + }, + "DROPDOWN": { + "PLACEHOLDER_LABEL": "Sivustoluettelo", + "MY_FILES_OPTION": "Omat tiedostot" + }, + "NODE_SELECTOR": { + "CANCEL": "Peruuta", + "CHOOSE": "Valitse", + "COPY": "Kopioi", + "COPY_ITEM": "Kopioi '{{ name }}' kohteeseen...", + "MOVE": "Siirrä", + "MOVE_ITEM": "Siirrä '{{ name }}' kohteeseen...", + "NO_RESULTS": "Tuloksia ei löydy", + "SEARCH": "Hae", + "SEARCH_RESULTS": "Hakutulokset", + "SELECT_LOCATION": "Valitse sijainti" + }, + "OPERATION": { + "SUCCESS": { + "CONTENT": { + "COPY": "Kopioiminen onnistui", + "MOVE": "Siirtäminen onnistui" + }, + "FOLDER": { + "COPY": "Kopioiminen onnistui", + "MOVE": "Siirtäminen onnistui" + } + }, + "ERROR": { + "CONFLICT": "Tämä nimi on jo käytössä. Käytä toista nimeä.", + "UNKNOWN": "Toiminto ei onnistunut. Yritä uudelleen tai ota yhteyttä IT-tukeesi.", + "PERMISSION": "Sinulla ei ole oikeuksia tähän." + } + }, + "TAG": { + "LABEL": { + "NEWTAG": "Uusi tunniste" + }, + "MESSAGES": { + "EXIST": "Tunniste on jo olemassa" + }, + "BUTTON": { + "ADD": "Lisää tunniste" + } + }, + "ADF_FILE_UPLOAD": { + "BUTTON": { + "MINIMIZE": "Pienennä", + "MAXIMIZE": "Suurenna", + "CLOSE": "Sulje", + "CANCEL_ALL": "Peruuta lataukset", + "CANCEL_FILE": "Peruuta lataus", + "REMOVE_FILE": "Poista ladattu tiedosto" + }, + "STATUS": { + "FILE_CANCELED_STATUS": "Peruutettu" + }, + "CONFIRMATION": { + "BUTTON": { + "CANCEL": "Kyllä", + "CONTINUE": "Ei" + }, + "MESSAGE": { + "TITLE": "Peruuta lataus", + "TEXT": "Lopeta lataaminen ja poista jo ladatut tiedostot." + } + }, + "ARIA-LABEL": { + "VERSION": "Tiedostoversio" + } + }, + "FILE_UPLOAD": { + "BUTTON": { + "UPLOAD_FILE": "Lataa tiedosto", + "UPLOAD_FOLDER": "Lataa kansio" + }, + "VERSION": { + "MESSAGES": { + "NO_ACCEPTED_FILE_TYPES": "Ota huomioon, että sallittujen tiedostotyyppien asetus ei vaikuta uusien versioiden lataamiseen. Tiedostotyyppi on sama kuin alkuperäisellä tiedostolla.", + "INCOMPATIBLE_VERSION": "Voit ladata uudeksi versioksi vain samaa tiedostotyyppiä olevan tiedoston." + } + }, + "MESSAGES": { + "UPLOAD_CANCELED": "Lataus peruutettiin", + "UPLOAD_PROGRESS": "Ladattu {{ completed }}/{{ total }}", + "UPLOAD_ERROR": "{{ total }} lataus epäonnistui", + "UPLOAD_ERRORS": "{{ total }} latausta epäonnistui", + "PROGRESS": "Lataus on käynnissä...", + "FOLDER_ALREADY_EXIST": "Kansio {0} on jo olemassa", + "FOLDER_NOT_SUPPORTED": "Selaimesi ei tue kansiolataamista. Kokeile toista selainta.", + "REMOVE_FILE_ERROR": "Tiedoston {{ fileName }} poistaminen ei onnistunut. Yritä uudelleen tai ota yhteyttä IT-tukeen.", + "REMOVE_FILES_ERROR": "{{ total }} tiedoston poistaminen ei onnistunut. Yritä uudelleen tai ota yhteyttä IT-tukeen.", + "EXCEED_MAX_FILE_SIZE": "{{ fileName }} ylittää suurimman sallitun tiedostokoon" + }, + "ACTION": { + "UNDO": "Kumoa" + }, + "ERRORS": { + "GENERIC": "Lataus epäonnistui. Jos ongelma jatkuu, ota yhteyttä IT-tukeen.", + "500": "Sisäisessä palvelimessa ilmeni virhe. Yritä uudelleen tai ota yhteyttä IT-tukeen. [500]", + "504": "Palvelin aikakatkaistiin. Yritä uudelleen tai ota yhteyttä IT-tukeen. [504]", + "403": "Oikeudet eivät riitä tähän sijaintiin lataamiseen [403]", + "404": "Lataussijaintia ei ole enää olemassa [404]", + "409": "Samanniminen tiedosto on jo olemassa [409]" + }, + "ARIA-LABEL": { + "ERROR": "Latausvirhe" + } + }, + "WEBSCRIPT": { + "ERROR": "Toiminnon suorittaminen ei onnistu. Ilmoita IT-tuelle seuraava ilmoitus: kohteen {{data}} sarjoituksen poistamisessa muotoon {{contentType}} tapahtui virhe" + }, + "SEARCH": { + "CONTROL": {}, + "BUTTON": { + "TOOLTIP": "Hae", + "ARIA-LABEL": "Hakupainike" + }, + "INPUT": { + "ARIA-LABEL": "Hakusanat" + }, + "RESULTS": { + "SUMMARY": "Haulla {{searchTerm}} löytyi {{numResults}} tulos", + "NONE": "Haulla {{searchTerm}} ei löydy yhtään tulosta", + "ERROR": "Haussa ilmeni ongelma. Yritä uudelleen.", + "COLUMNS": { + "NAME": "Näyttönimi", + "MODIFIED_BY": "Muokkaaja:", + "MODIFIED_AT": "Muokattu" + } + }, + "FILTER": { + "ACTIONS": { + "CLEAR": "Tyhjennä", + "APPLY": "Käytä", + "CLEAR-ALL": "Tyhjennä kaikki", + "SHOW-MORE": "Näytä lisää", + "SHOW-LESS": "Näytä vähemmän", + "FILTER-CATEGORY": "Suodatusluokka" + }, + "BUTTONS": { + "CLEAR-ALL": { + "LABEL": "Tyhjennä kaikki", + "TOOLTIP": "Tämä poistaa kaikki valinnat" + }, + "RESET-ALL": { + "LABEL": "Nollaa kaikki", + "TOOLTIP": "Tämä nollaa kaikki valinnat ja suodattimet" + } + }, + "RANGE": { + "FROM": "Alku", + "TO": "Loppu", + "FROM-DATE": "Alku", + "TO-DATE": "Loppu" + }, + "VALIDATION": { + "REQUIRED-VALUE": "Pakollinen arvo", + "NO-DAYS": "Päiviä ei ole valittu", + "INVALID-FORMAT": "Virheellinen muoto", + "INVALID-DATE": "Päivämäärä on virheellinen. Päivämäärän täytyy olla muodossa '{{ requiredFormat }}'.", + "BEYOND-MAX-DATE": "Päivämäärä ei ole sallitulla alueella." + } + }, + "ICONS": { + "ft_ic_raster_image": "Kuvatiedosto", + "ft_ic_pdf": "PDF-tiedosto", + "ft_ic_ms_excel": "Microsoft Excel -tiedosto", + "ft_ic_ms_word": "Microsoft Word -tiedosto", + "ft_ic_ms_powerpoint": "Microsoft PowerPoint -tiedosto", + "ft_ic_video": "Videotiedosto", + "ft_ic_document": "Asiakirjatiedosto", + "ft_ic_website": "Verkkoresurssi", + "ft_ic_archive": "Arkistotiedosto", + "ft_ic_presentation": "Esitystiedosto", + "ft_ic_spreadsheet": "Laskentataulukkotiedosto" + }, + "DOCUMENT_LIST": { + "COLUMNS": { + "DISPLAY_NAME": "Näyttönimi", + "CREATED_BY": "Tekijä:", + "CREATED_ON": "Luotu" + }, + "ACTIONS": { + "FOLDER": { + "DELETE": "Poista", + "MOVE": "Siirrä", + "COPY": "Kopioi" + }, + "DOCUMENT": { + "DOWNLOAD": "Lataa", + "DELETE": "Poista", + "MOVE": "Siirrä", + "COPY": "Kopioi", + "PROCESS_ACTION": "Käynnistä prosessi" + } + } + } + }, + "PERMISSION": { + "LACKOF": "Sinulla ei ole oikeutta {{permission}} tapahtumalle {{action}} tapahtumatyypissä {{type}}" + }, + "METADATA": { + "BASIC": { + "HEADER": "Ominaisuudet", + "NAME": "Nimi", + "TITLE": "Otsikko", + "DESCRIPTION": "Kuvaus", + "AUTHOR": "Tekijä", + "MIMETYPE": "MIME-tyyppi", + "SIZE": "Koko", + "CREATOR": "Tekijä", + "CREATED_DATE": "Luontipäivämäärä", + "MODIFIER": "Muokkaaja", + "MODIFIED_DATE": "Muokkauspäivämäärä" + } + }, + "SHARE": { + "PUBLIC-LINK": "Julkinen linkki", + "DIALOG-TITLE": "Jaa", + "DESCRIPTION": "Kopioi se leikepöydälle napsauttamalla alla olevaa linkkiä.", + "TITLE": "Jakolinkki", + "EXPIRES": "Vanhentuu", + "CLIPBOARD-MESSAGE": "Linkki kopioitu leikepöydälle", + "CLOSE": "Sulje", + "CONFIRMATION": { + "DIALOG-TITLE": "Poista tämä jaettu linkki", + "MESSAGE": "Tämä linkki poistetaan ja uusi linkki luodaan, kun tiedosto jaetaan seuraavan kerran", + "CANCEL": "Peruuta", + "REMOVE": "Poista" + } + }, + "PERMISSION_MANAGER": { + "PERMISSION_DISPLAY": { + "INHERITED": "Peritty", + "AUTHORITY_ID": "Auktoriteettitunnus", + "ROLE": "Rooli", + "LOCALLY_SET": "Paikallisesti määritetty", + "NO_PERMISSIONS": "Ei oikeuksia" + }, + "ADD-PERMISSION": { + "SEARCH": "Hae", + "TYPE-MESSAGE": "Aloita ryhmien tai ihmisten hakeminen kirjoittamalla jotain", + "NO-RESULT": "Tällä haulla ei löydy yhtään tulosta", + "ADD-ACTION": "Lisää", + "CLOSE-ACTION": "Sulje", + "BASE-DIALOG-TITLE": "Hae lisättävää ryhmää tai ihmistä...", + "EVERYONE": "Kaikki" + }, + "ERROR": { + "DUPLICATE-PERMISSION": "Ainakin yksi jo määrittämistäsi oikeuksista on jo mukana: {{list}}", + "NOT-ALLOWED": "Et voi muokata oikeuksia" + } + }, + "ADF-TREE-VIEW": { + "MISSING-ID": "Solmutunnusta ei ole annettu!" + }, + "LIBRARY": { + "DIALOG": { + "CREATE_TITLE": "Luo kirjasto", + "CREATE": "Luo", + "UPDATE": "Päivitä", + "EDIT": "Muokkaa", + "CANCEL": "Peruuta", + "FORM": { + "DESCRIPTION": "Kuvaus", + "SITE_ID": "Kirjastotunnus", + "NAME": "Nimi", + "VISIBILITY": "Näkyvyys" + } + }, + "ROLE": { + "MANAGER": "Vastaava", + "COLLABORATOR": "Yhteistyökumppani", + "CONTRIBUTOR": "Osallistuja", + "CONSUMER": "Kuluttaja" + }, + "VISIBILITY": { + "PRIVATE": "Yksityinen", + "PUBLIC": "Julkinen", + "MODERATED": "Valvottu" + }, + "HINTS": { + "SITE_TITLE_EXISTS": "Kirjaston nimi on jo käytössä" + }, + "ERRORS": { + "GENERIC": "Ilmeni ongelma", + "EXISTENT_SITE": "Kirjastotunnus ei ole käytettävissä. Käytä toista kirjastotunnusta.", + "CONFLICT": "Kirjastotunnus on jo käytössä. Tarkista roskakori.", + "ID_TOO_LONG": "URL-osoitteessa voi olla enintään 72 merkkiä", + "DESCRIPTION_TOO_LONG": "Kuvauksessa voi olla enintään 512 merkkiä", + "TITLE_TOO_LONG": "Otsikossa voi olla enintään 256 merkkiä", + "TITLE_TOO_SHORT": "Nimessä pitää olla vähintään kaksi merkkiä", + "ILLEGAL_CHARACTERS": "Käytä vain kirjaimia ja numeroita", + "ONLY_SPACES": "Kirjaston nimi ei voi sisältää pelkkiä välilyöntejä", + "LIBRARY_UPDATE_ERROR": "Kirjaston ominaisuuksien päivittämisessä tapahtui virhe" + }, + "SUCCESS": { + "LIBRARY_UPDATED": "Kirjaston ominaisuudet päivitettiin" + } + } +} \ No newline at end of file diff --git a/lib/content-services/i18n/fr.json b/lib/content-services/i18n/fr.json index 7bc3549278..3856ccd4cf 100644 --- a/lib/content-services/i18n/fr.json +++ b/lib/content-services/i18n/fr.json @@ -128,6 +128,9 @@ "TITLE": "Annuler l'Importation", "TEXT": "Arrêter l'importation et supprimer les fichiers déjà importés." } + }, + "ARIA-LABEL": { + "VERSION": "Version du fichier" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Erreur de serveur interne. Réessayez ou contactez le support technique [500]", "504": "Le délai d'attente du serveur a expiré. Réessayez ou contactez le support technique [504]", "403": "Droits d'accès insuffisants pour importer dans cet emplacement [403]", - "404": "L'emplacement de destination de l'importation n'existe plus [404]" + "404": "L'emplacement de destination de l'importation n'existe plus [404]", + "409": "Un fichier portant le même nom existe déjà [409]" }, "ARIA-LABEL": { "ERROR": "Erreur d'importation" diff --git a/lib/content-services/i18n/it.json b/lib/content-services/i18n/it.json index 0e2e39b860..f041b1bed1 100644 --- a/lib/content-services/i18n/it.json +++ b/lib/content-services/i18n/it.json @@ -75,7 +75,7 @@ "MOVE": "Sposta", "MOVE_ITEM": "Sposta '{{ name }}' in...", "NO_RESULTS": "Nessun risultato trovato", - "SEARCH": "Ricerca", + "SEARCH": "Cerca", "SEARCH_RESULTS": "Risultati della ricerca", "SELECT_LOCATION": "Seleziona località" }, @@ -128,6 +128,9 @@ "TITLE": "Annulla caricamento", "TEXT": "Interrompi il caricamento e rimuovi i file già caricati." } + }, + "ARIA-LABEL": { + "VERSION": "Versione file" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Errore interno del server. Riprovare o contattare il supporto IT [500]", "504": "Timeout del server. Riprovare o contattare il supporto IT [504]", "403": "Autorizzazioni insufficienti per caricare in questa posizione [403]", - "404": "La posizione di caricamento non esiste più [404]" + "404": "La posizione di caricamento non esiste più [404]", + "409": "Esiste già un file con lo stesso nome [409]" }, "ARIA-LABEL": { "ERROR": "Carica errore" diff --git a/lib/content-services/i18n/ja.json b/lib/content-services/i18n/ja.json index 6fbdc14049..900d7c7f8f 100644 --- a/lib/content-services/i18n/ja.json +++ b/lib/content-services/i18n/ja.json @@ -128,6 +128,9 @@ "TITLE": "アップロードのキャンセル", "TEXT": "アップロードを中止し、アップロード済みのファイルを削除します。" } + }, + "ARIA-LABEL": { + "VERSION": "ファイルのバージョン" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "内部サーバーエラーが発生しました。もう一度操作をやり直すか、IT 担当者に連絡してください。 [500]", "504": "サーバーがタイムアウトになりました。もう一度操作をやり直すか、IT 担当者に連絡してください。[504]", "403": "この場所にアップロードするための権限がありません [403]", - "404": "アップロード場所は削除されました [404]" + "404": "アップロード場所は削除されました [404]", + "409": "同じ名前のファイルが既に存在します [409]" }, "ARIA-LABEL": { "ERROR": "アップロードエラー" diff --git a/lib/content-services/i18n/nb.json b/lib/content-services/i18n/nb.json index 71218d2f05..5f7ec439f3 100644 --- a/lib/content-services/i18n/nb.json +++ b/lib/content-services/i18n/nb.json @@ -128,6 +128,9 @@ "TITLE": "Avbryt opplasting", "TEXT": "Stopp opplasting, og fjern filer som allerede er opplastet." } + }, + "ARIA-LABEL": { + "VERSION": "Filversjon" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Intern serverfeil. Prøv på nytt eller kontakt IT-støtten [500]", "504": "Serveren ble tidsavbrutt. Prøv på nytt eller kontakt IT-støtten [504]", "403": "Ikke tilstrekkelige tillatelser til å laste opp på dette stedet [403]", - "404": "Opplastingsstedet finnes ikke lenger [404]" + "404": "Opplastingsstedet finnes ikke lenger [404]", + "409": "En fil med samme navn finnes allerede [409]" }, "ARIA-LABEL": { "ERROR": "Opplastingsfeil" diff --git a/lib/content-services/i18n/nl.json b/lib/content-services/i18n/nl.json index 3b969e709d..252234c721 100644 --- a/lib/content-services/i18n/nl.json +++ b/lib/content-services/i18n/nl.json @@ -128,6 +128,9 @@ "TITLE": "Uploaden annuleren", "TEXT": "Stop het uploaden en verwijder de bestanden die al zijn geüpload." } + }, + "ARIA-LABEL": { + "VERSION": "Bestandsversie" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Interne serverfout, probeer het opnieuw of neem contact op met de IT-ondersteuning [500]", "504": "Er is een time-out opgetreden in de server, probeer het opnieuw of neem contact op met de IT-ondersteuning [504]", "403": "Onvoldoende rechten voor uploaden op deze locatie [403]", - "404": "Uploadlocatie bestaat niet meer [404]" + "404": "Uploadlocatie bestaat niet meer [404]", + "409": "Er bestaat al een bestand met dezelfde naam [409]" }, "ARIA-LABEL": { "ERROR": "Uploadfout" diff --git a/lib/content-services/i18n/pl.json b/lib/content-services/i18n/pl.json new file mode 100644 index 0000000000..98ae025b51 --- /dev/null +++ b/lib/content-services/i18n/pl.json @@ -0,0 +1,366 @@ +{ + "ADF_VERSION_LIST": { + "ACTIONS": { + "RESTORE": "Przywróć", + "DELETE": "Usuń", + "DOWNLOAD": "Pobierz", + "UPLOAD": { + "TITLE": "Prześlij nową wersję", + "TOOLTIP": "Ograniczenie: aby utworzyć nową wersję pliku, należy przesłać plik o tej samej nazwie.", + "MAJOR": "istotne zmiany (2.0)", + "MINOR": "drobne zmiany (1.1)", + "COMMENT": "Pozostaw komentarz", + "ADD": "Dodaj nową wersję", + "CANCEL": "Anuluj" + } + }, + "CONFIRM_DELETE": { + "TITLE": "Usuń wersję", + "MESSAGE": "Nie można przywrócić usuniętych wersji plików. Czy kontynuować?", + "YES_LABEL": "Tak", + "NO_LABEL": "Nie" + } + }, + "ADF_DROPDOWN": { + "LOADING": "Wczytywanie..." + }, + "ADF_CONFIRM_DIALOG": { + "TITLE": "Potwierdź", + "ACTION": "Czy chcesz kontynuować?", + "YES_LABEL": "Tak", + "NO_LABEL": "Nie" + }, + "ADF-DOCUMENT-LIST": { + "EMPTY": { + "HEADER": "Ten folder jest pusty" + }, + "NO_PERMISSION": "Nie masz uprawnień do wyświetlenia tego pliku lub folderu.", + "LAYOUT": { + "CREATED": "Utworzono", + "THUMBNAIL": "Miniatura", + "NAME": "Nazwa", + "LOCATION": "Lokalizacja", + "SIZE": "Rozmiar", + "DELETED_ON": "Usunięte", + "DELETED_BY": "Usunięte przez", + "STATUS": "Status", + "MODIFIED_ON": "Zmodyfikowane", + "MODIFIED_BY": "Zmodyfikowane przez", + "SHARED_BY": "Udostępnione przez", + "LOAD_MORE": "Wczytaj więcej" + }, + "MENU_ACTIONS": { + "VIEW": "Widok", + "REMOVE": "Usuń", + "DOWNLOAD": "Pobierz" + } + }, + "ALFRESCO_DOCUMENT_LIST": { + "BUTTON": { + "ACTION_CREATE": "Utwórz...", + "ACTION_NEW_FOLDER": "Nowy folder", + "CREATE": "Utwórz", + "CANCEL": "Anuluj" + } + }, + "DROPDOWN": { + "PLACEHOLDER_LABEL": "Lista witryn", + "MY_FILES_OPTION": "Moje pliki" + }, + "NODE_SELECTOR": { + "CANCEL": "Anuluj", + "CHOOSE": "Wybierz", + "COPY": "Kopiuj", + "COPY_ITEM": "Kopiuj '{{ name }}' do...", + "MOVE": "Przenieś", + "MOVE_ITEM": "Przenieś '{{ name }}' do...", + "NO_RESULTS": "Brak wyników", + "SEARCH": "Szukaj", + "SEARCH_RESULTS": "Wyniki wyszukiwania", + "SELECT_LOCATION": "Wybierz lokalizację" + }, + "OPERATION": { + "SUCCESS": { + "CONTENT": { + "COPY": "Skopiowano pomyślnie", + "MOVE": "Przeniesiono pomyślnie" + }, + "FOLDER": { + "COPY": "Skopiowano pomyślnie", + "MOVE": "Przeniesiono pomyślnie" + } + }, + "ERROR": { + "CONFLICT": "Ta nazwa jest już używana. Spróbuj użyć innej nazwy.", + "UNKNOWN": "Wykonanie czynności nie powiodło się. Spróbuj ponownie lub skontaktuj się z zespołem IT.", + "PERMISSION": "Nie masz dostępu umożliwiającego wykonanie tej czynności." + } + }, + "TAG": { + "LABEL": { + "NEWTAG": "Nowy znacznik" + }, + "MESSAGES": { + "EXIST": "Znacznik już istnieje." + }, + "BUTTON": { + "ADD": "Dodaj znacznik" + } + }, + "ADF_FILE_UPLOAD": { + "BUTTON": { + "MINIMIZE": "Zminimalizuj", + "MAXIMIZE": "Zmaksymalizuj", + "CLOSE": "Zamknij", + "CANCEL_ALL": "Anuluj przesyłania", + "CANCEL_FILE": "Anuluj przesyłanie", + "REMOVE_FILE": "Usuń przesłany plik" + }, + "STATUS": { + "FILE_CANCELED_STATUS": "Anulowane" + }, + "CONFIRMATION": { + "BUTTON": { + "CANCEL": "Tak", + "CONTINUE": "Nie" + }, + "MESSAGE": { + "TITLE": "Anuluj przesyłanie", + "TEXT": "Zatrzymaj przesyłanie i usuń już przesłane pliki." + } + }, + "ARIA-LABEL": { + "VERSION": "Wersja pliku" + } + }, + "FILE_UPLOAD": { + "BUTTON": { + "UPLOAD_FILE": "Prześlij plik", + "UPLOAD_FOLDER": "Prześlij folder" + }, + "VERSION": { + "MESSAGES": { + "NO_ACCEPTED_FILE_TYPES": "Uwaga: ustawienie „acceptedFilesType” nie ma wpływu na operacje przesyłania nowej wersji. Typ pliku będzie taki sam jak oryginalnego pliku.", + "INCOMPATIBLE_VERSION": "Jako nową wersję można przesłać wyłącznie plik tego samego typu." + } + }, + "MESSAGES": { + "UPLOAD_CANCELED": "Anulowano operację przesyłania.", + "UPLOAD_PROGRESS": "Przesłano {{ completed }} / {{ total }}", + "UPLOAD_ERROR": "Operacja przesyłania (łączna liczba elementów: {{ total }}) nie powiodła się.", + "UPLOAD_ERRORS": "Nie powiodła się następująca liczba operacji przesyłania: {{ total }}", + "PROGRESS": "Trwa przesyłanie...", + "FOLDER_ALREADY_EXIST": "Folder {0} już istnieje", + "FOLDER_NOT_SUPPORTED": "Przesyłanie folderów nie jest obsługiwane przez Twoją przeglądarkę. Spróbuj użyć innej przeglądarki.", + "REMOVE_FILE_ERROR": "Nie można usunąć pliku {{ fileName }}. Spróbuj ponownie lub skonsultuj się z zespołem IT.", + "REMOVE_FILES_ERROR": "Nie można usunąć następującej liczby plików: {{ total }}. Spróbuj ponownie lub skonsultuj się z zespołem IT.", + "EXCEED_MAX_FILE_SIZE": "Rozmiar pliku {{ fileName }} przekracza dozwoloną wielkość." + }, + "ACTION": { + "UNDO": "Cofnij" + }, + "ERRORS": { + "GENERIC": "Przesyłanie nie powiodło się. Skontaktuj się z działem IT, jeśli problem nie ustąpi", + "500": "Błąd wewnętrzny serwera, spróbuj ponownie lub skontaktuj się z działem IT [500]", + "504": "Upłynął limit czasu serwera, spróbuj ponownie lub skontaktuj się z działem IT [504]", + "403": "Niewystarczające uprawnienia, aby przesłać w tej lokalizacji [403]", + "404": "Lokalizacja przesyłania już nie istnieje [404]", + "409": "Istnieje już plik o tej samej nazwie [409]" + }, + "ARIA-LABEL": { + "ERROR": "Błąd przesyłania" + } + }, + "WEBSCRIPT": { + "ERROR": "Nie można wykonać czynności. Udostępnij zespołowi IT następujący komunikat: Błąd podczas deserializacji {{data}} jako {{contentType}}." + }, + "SEARCH": { + "CONTROL": {}, + "BUTTON": { + "TOOLTIP": "Szukaj", + "ARIA-LABEL": "Przycisk wyszukiwania" + }, + "INPUT": { + "ARIA-LABEL": "Wprowadzanie szukanego terminu" + }, + "RESULTS": { + "SUMMARY": "Dla terminu {{searchTerm}} znaleziono następującą liczbę wyników: {{numResults}}.", + "NONE": "Brak wyników dla terminu {{searchTerm}}", + "ERROR": "Podczas wyszukiwania wystąpił problem. Spróbuj ponownie.", + "COLUMNS": { + "NAME": "Nazwa wyświetlana", + "MODIFIED_BY": "Zmodyfikowane przez", + "MODIFIED_AT": "Zmodyfikowano o" + } + }, + "FILTER": { + "ACTIONS": { + "CLEAR": "Wyczyść", + "APPLY": "Zastosuj", + "CLEAR-ALL": "Wyczyść wszystko", + "SHOW-MORE": "Pokaż więcej", + "SHOW-LESS": "Pokaż mniej", + "FILTER-CATEGORY": "Filtruj kategorie" + }, + "BUTTONS": { + "CLEAR-ALL": { + "LABEL": "Wyczyść wszystko", + "TOOLTIP": "Spowoduje to usunięcie wszystkich wyborów" + }, + "RESET-ALL": { + "LABEL": "Resetuj wszystko", + "TOOLTIP": "Spowoduje to zresetowanie wszystkich wyborów i wszystkich filtrów" + } + }, + "RANGE": { + "FROM": "Od", + "TO": "Do", + "FROM-DATE": "Od", + "TO-DATE": "Do" + }, + "VALIDATION": { + "REQUIRED-VALUE": "Wymagana wartość", + "NO-DAYS": "Nie wybrano dni.", + "INVALID-FORMAT": "Nieprawidłowy format", + "INVALID-DATE": "Nieprawidłowa data. Data musi być w formacie '{{ requiredFormat }}'.", + "BEYOND-MAX-DATE": "Data jest późniejsza niż maksymalna." + } + }, + "ICONS": { + "ft_ic_raster_image": "Plik obrazu", + "ft_ic_pdf": "Dokument PDF", + "ft_ic_ms_excel": "Plik programu Microsoft Excel", + "ft_ic_ms_word": "Dokument programu Microsoft Word", + "ft_ic_ms_powerpoint": "Plik programu Microsoft PowerPoint", + "ft_ic_video": "Plik wideo", + "ft_ic_document": "Plik dokumentu", + "ft_ic_website": "Zasób sieci Web", + "ft_ic_archive": "Plik archiwum", + "ft_ic_presentation": "Plik prezentacji", + "ft_ic_spreadsheet": "Plik arkusza kalkulacyjnego" + }, + "DOCUMENT_LIST": { + "COLUMNS": { + "DISPLAY_NAME": "Nazwa wyświetlana", + "CREATED_BY": "Utworzone przez", + "CREATED_ON": "Utworzono" + }, + "ACTIONS": { + "FOLDER": { + "DELETE": "Usuń", + "MOVE": "Przenieś", + "COPY": "Kopiuj" + }, + "DOCUMENT": { + "DOWNLOAD": "Pobierz", + "DELETE": "Usuń", + "MOVE": "Przenieś", + "COPY": "Kopiuj", + "PROCESS_ACTION": "Rozpocznij proces" + } + } + } + }, + "PERMISSION": { + "LACKOF": "Nie masz uprawnienia {{permission}} do działania {{action}} typu {{type}}." + }, + "METADATA": { + "BASIC": { + "HEADER": "Właściwości", + "NAME": "Nazwa", + "TITLE": "Tytuł", + "DESCRIPTION": "Opis", + "AUTHOR": "Autor", + "MIMETYPE": "Typ MIME", + "SIZE": "Rozmiar", + "CREATOR": "Twórca", + "CREATED_DATE": "Data utworzenia", + "MODIFIER": "Modyfikator", + "MODIFIED_DATE": "Data modyfikacji" + } + }, + "SHARE": { + "PUBLIC-LINK": "Link publiczny", + "DIALOG-TITLE": "Udostępnij", + "DESCRIPTION": "Kliknij link poniżej, aby skopiować go do schowka.", + "TITLE": "Link do udostępnienia", + "EXPIRES": "Wygasa", + "CLIPBOARD-MESSAGE": "Link został skopiowany do schowka.", + "CLOSE": "Zamknij", + "CONFIRMATION": { + "DIALOG-TITLE": "Usuń udostępniony link", + "MESSAGE": "Ten link zostanie usunięty, a przy następnym udostępnieniu tego pliku zostanie utworzony nowy link.", + "CANCEL": "Anuluj", + "REMOVE": "Usuń" + } + }, + "PERMISSION_MANAGER": { + "PERMISSION_DISPLAY": { + "INHERITED": "Dziedziczone", + "AUTHORITY_ID": "Identyfikator autoryzacji", + "ROLE": "Rola", + "LOCALLY_SET": "Ustawione lokalnie", + "NO_PERMISSIONS": "Brak uprawnień" + }, + "ADD-PERMISSION": { + "SEARCH": "Szukaj", + "TYPE-MESSAGE": "Wpisz jakiś tekst, aby rozpocząć wyszukiwanie grup lub osób.", + "NO-RESULT": "Brak wyników dla tego wyszukiwania.", + "ADD-ACTION": "Dodaj", + "CLOSE-ACTION": "Zamknij", + "BASE-DIALOG-TITLE": "Wyszukaj grupę lub osoby do dodania...", + "EVERYONE": "Wszyscy" + }, + "ERROR": { + "DUPLICATE-PERMISSION": "Co najmniej jedno ustawione dla Ciebie uprawnienie już występuje: {{list}}", + "NOT-ALLOWED": "Nie masz zezwolenia na zmianę uprawnień." + } + }, + "ADF-TREE-VIEW": { + "MISSING-ID": "Nie określono identyfikatora węzła!" + }, + "LIBRARY": { + "DIALOG": { + "CREATE_TITLE": "Utwórz bibliotekę", + "CREATE": "Utwórz", + "UPDATE": "Aktualizuj", + "EDIT": "Edytuj", + "CANCEL": "Anuluj", + "FORM": { + "DESCRIPTION": "Opis", + "SITE_ID": "Identyfikator biblioteki", + "NAME": "Nazwa", + "VISIBILITY": "Widoczność" + } + }, + "ROLE": { + "MANAGER": "Menedżer", + "COLLABORATOR": "Współpracownik", + "CONTRIBUTOR": "Współautor", + "CONSUMER": "Konsument" + }, + "VISIBILITY": { + "PRIVATE": "Prywatne", + "PUBLIC": "Publiczne", + "MODERATED": "Moderowane" + }, + "HINTS": { + "SITE_TITLE_EXISTS": "Nazwa biblioteki jest już w użyciu" + }, + "ERRORS": { + "GENERIC": "Wystąpił problem", + "EXISTENT_SITE": "Wprowadzony identyfikator biblioteki jest niedostępny. Wprowadź inny.", + "CONFLICT": "Identyfikator tej biblioteki jest już w użyciu. Sprawdź w koszu.", + "ID_TOO_LONG": "W adresie URL można użyć maksymalnie 72 znaków", + "DESCRIPTION_TOO_LONG": "W opisie można użyć maksymalnie 512 znaków", + "TITLE_TOO_LONG": "W tytule można użyć maksymalnie 256 znaków", + "TITLE_TOO_SHORT": "Tytuł musi mieć co najmniej 2 znaki długości", + "ILLEGAL_CHARACTERS": "Użyj tylko cyfr i liter", + "ONLY_SPACES": "Nazwa biblioteki nie może zawierać wyłącznie spacji", + "LIBRARY_UPDATE_ERROR": "Podczas aktualizowania właściwości biblioteki wystąpił błąd" + }, + "SUCCESS": { + "LIBRARY_UPDATED": "Zaktualizowano właściwości biblioteki" + } + } +} \ No newline at end of file diff --git a/lib/content-services/i18n/pt-BR.json b/lib/content-services/i18n/pt-BR.json index f81d137fdf..42cefeb90a 100644 --- a/lib/content-services/i18n/pt-BR.json +++ b/lib/content-services/i18n/pt-BR.json @@ -128,6 +128,9 @@ "TITLE": "Cancelar upload", "TEXT": "Interrompa o carregamento e remova os arquivos carregados." } + }, + "ARIA-LABEL": { + "VERSION": "Versão do arquivo" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Erro interno no servidor. Tente novamente ou entre em contato com a TI [500]", "504": "Tempo expirado no servidor, tente novamente ou entre em contato com o suporte de TI [504]", "403": "Permissões insuficientes para carregar neste local [403]", - "404": "O local para carregar não existe mais [404]" + "404": "O local para carregar não existe mais [404]", + "409": "Já existe um arquivo com o mesmo nome [409]" }, "ARIA-LABEL": { "ERROR": "Erro ao carregar" diff --git a/lib/content-services/i18n/ru.json b/lib/content-services/i18n/ru.json index b4ed72179e..6187c5f4b0 100644 --- a/lib/content-services/i18n/ru.json +++ b/lib/content-services/i18n/ru.json @@ -125,9 +125,12 @@ "CONTINUE": "Нет" }, "MESSAGE": { - "TITLE": "Отменить выгрузку", + "TITLE": "Отменить загрузку", "TEXT": "Остановите выгрузку и удалите уже выгруженные файлы." } + }, + "ARIA-LABEL": { + "VERSION": "Версия файла" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "Внутренняя ошибка сервера. Повторите попытку или обратитесь в службу поддержки [500]", "504": "Время сеанса сервера истекло. Повторите попытку или обратитесь в службу поддержки [504]", "403": "Недостаточно разрешений для отправки в это местоположение [403]", - "404": "Местоположение, в которое выполняется отправка, больше не существует [404]" + "404": "Местоположение, в которое выполняется отправка, больше не существует [404]", + "409": "Файл с таким именем уже существует [409]" }, "ARIA-LABEL": { "ERROR": "Ошибка загрузки" @@ -320,7 +324,7 @@ "CREATE_TITLE": "Создание библиотеки", "CREATE": "Создать", "UPDATE": "Обновить", - "EDIT": "Правка", + "EDIT": "Редактировать", "CANCEL": "Отмена", "FORM": { "DESCRIPTION": "Описание", diff --git a/lib/content-services/i18n/sv.json b/lib/content-services/i18n/sv.json new file mode 100644 index 0000000000..6c2b18436c --- /dev/null +++ b/lib/content-services/i18n/sv.json @@ -0,0 +1,366 @@ +{ + "ADF_VERSION_LIST": { + "ACTIONS": { + "RESTORE": "Återställ", + "DELETE": "Radera", + "DOWNLOAD": "Ladda ner", + "UPLOAD": { + "TITLE": "Ladda upp ny version", + "TOOLTIP": "Begränsning: du måste ladda upp en fil med samma namn för att skapa en ny version av den.", + "MAJOR": "större förändringar (2.0)", + "MINOR": "mindre förändringar (1.1)", + "COMMENT": "Lämna en kommentar", + "ADD": "Lägg till ny version", + "CANCEL": "Avbryt" + } + }, + "CONFIRM_DELETE": { + "TITLE": "Radera version", + "MESSAGE": "Raderade filversioner kan inte återställas. Fortsätt?", + "YES_LABEL": "Ja", + "NO_LABEL": "Nej" + } + }, + "ADF_DROPDOWN": { + "LOADING": "Läser in..." + }, + "ADF_CONFIRM_DIALOG": { + "TITLE": "Bekräfta", + "ACTION": "Vill du fortsätta?", + "YES_LABEL": "Ja", + "NO_LABEL": "Nej" + }, + "ADF-DOCUMENT-LIST": { + "EMPTY": { + "HEADER": "Den här mappen är tom" + }, + "NO_PERMISSION": "Du har inte behörighet att visa den här filen eller mappen.", + "LAYOUT": { + "CREATED": "Skapad", + "THUMBNAIL": "Miniatyrbild", + "NAME": "Namn", + "LOCATION": "Plats", + "SIZE": "Storlek", + "DELETED_ON": "Raderad", + "DELETED_BY": "Raderad av", + "STATUS": "Status", + "MODIFIED_ON": "Modifierad", + "MODIFIED_BY": "Modifierad av", + "SHARED_BY": "Delad av", + "LOAD_MORE": "Läs in mer" + }, + "MENU_ACTIONS": { + "VIEW": "Visa", + "REMOVE": "Ta bort", + "DOWNLOAD": "Ladda ner" + } + }, + "ALFRESCO_DOCUMENT_LIST": { + "BUTTON": { + "ACTION_CREATE": "Skapa...", + "ACTION_NEW_FOLDER": "Ny mapp", + "CREATE": "Skapa", + "CANCEL": "Avbryt" + } + }, + "DROPDOWN": { + "PLACEHOLDER_LABEL": "Lista med samarbetsytor", + "MY_FILES_OPTION": "Mina filer" + }, + "NODE_SELECTOR": { + "CANCEL": "Avbryt", + "CHOOSE": "Välj", + "COPY": "Kopiera", + "COPY_ITEM": "Kopiera '{{ name }}' till...", + "MOVE": "Flytta", + "MOVE_ITEM": "Flytta '{{ name }}' till...", + "NO_RESULTS": "Inga resultat hittades", + "SEARCH": "Sök", + "SEARCH_RESULTS": "Sökresultat", + "SELECT_LOCATION": "Välj plats" + }, + "OPERATION": { + "SUCCESS": { + "CONTENT": { + "COPY": "Kopiering lyckades", + "MOVE": "Flytt lyckades" + }, + "FOLDER": { + "COPY": "Kopiering lyckades", + "MOVE": "Flytt lyckades" + } + }, + "ERROR": { + "CONFLICT": "Det här namnet används redan, testa ett annat namn.", + "UNKNOWN": "Åtgärden lyckades inte. Försök igen eller kontakta din IT-avdelning.", + "PERMISSION": "Du har inte åtkomst att göra detta." + } + }, + "TAG": { + "LABEL": { + "NEWTAG": "Ny tagg" + }, + "MESSAGES": { + "EXIST": "Tagg finns redan" + }, + "BUTTON": { + "ADD": "Lägg till tagg" + } + }, + "ADF_FILE_UPLOAD": { + "BUTTON": { + "MINIMIZE": "Minimera", + "MAXIMIZE": "Maximera", + "CLOSE": "Stäng", + "CANCEL_ALL": "Avbryt uppladdningar", + "CANCEL_FILE": "Avbryt uppladdning", + "REMOVE_FILE": "Ta bort uppladdad fil" + }, + "STATUS": { + "FILE_CANCELED_STATUS": "Avbruten" + }, + "CONFIRMATION": { + "BUTTON": { + "CANCEL": "Ja", + "CONTINUE": "Nej" + }, + "MESSAGE": { + "TITLE": "Avbryt uppladdning", + "TEXT": "Stoppa uppladdning och ta bort filer som redan laddats upp" + } + }, + "ARIA-LABEL": { + "VERSION": "Filversion" + } + }, + "FILE_UPLOAD": { + "BUTTON": { + "UPLOAD_FILE": "Ladda upp fil", + "UPLOAD_FOLDER": "Ladda upp mapp" + }, + "VERSION": { + "MESSAGES": { + "NO_ACCEPTED_FILE_TYPES": "Notera att inställningen av \"acceptedFilesType\" inte har någon effekt på de nya versionsuppladdningarna. Filtypen kommer att vara samma som den ursprungliga filens.", + "INCOMPATIBLE_VERSION": "Bara ett filter av samma typ får laddas upp som ny version." + } + }, + "MESSAGES": { + "UPLOAD_CANCELED": "Uppladning avbruten", + "UPLOAD_PROGRESS": "Uppladdad {{ completed }} / {{ total }}", + "UPLOAD_ERROR": "{{ total }} uppladdning lyckades inte", + "UPLOAD_ERRORS": "{{ total }} uppladdningar lyckades inte", + "PROGRESS": "Uppladdning pågår...", + "FOLDER_ALREADY_EXIST": "Mappen {0} finns redan", + "FOLDER_NOT_SUPPORTED": "Mappuppladdning stöds inte av din webbläsare, testa en annan webbläsare", + "REMOVE_FILE_ERROR": "{{ fileName }} kunde inte flyttas, försök igen eller kolla med IT-avdelningen.", + "REMOVE_FILES_ERROR": "{{ total }} kunde inte flyttas, försök igen eller kolla med IT-avdelningen.", + "EXCEED_MAX_FILE_SIZE": "Fil {{ fileName }} är större än den tillåtna filstorleken" + }, + "ACTION": { + "UNDO": "Ångra" + }, + "ERRORS": { + "GENERIC": "Uppladdningen misslyckades. Kontakta IT-avdelningen om det här problemet kvarstår", + "500": "Internt serverfel, försök igen eller kontakta IT-supporten [500]", + "504": "Tidsgränsen för servern överskreds, försök igen eller kontakta IT-supporten [504]", + "403": "Otillräckliga behörigheter för att ladda upp på den här platsen [403]", + "404": "Uppladdningsplats finns inte längre [404]", + "409": "Det finns redan en fil med samma namn [409]" + }, + "ARIA-LABEL": { + "ERROR": "Uppladdningsfel" + } + }, + "WEBSCRIPT": { + "ERROR": "Kunde inte slutföra åtgärden. Dela det här meddelandet med din IT-avdelning: Fel under deserialisering av {{data}} som {{contentType}}" + }, + "SEARCH": { + "CONTROL": {}, + "BUTTON": { + "TOOLTIP": "Sök", + "ARIA-LABEL": "Sökknapp" + }, + "INPUT": { + "ARIA-LABEL": "Sökindata" + }, + "RESULTS": { + "SUMMARY": "{{numResults}} resultat hittades för {{searchTerm}}", + "NONE": "Inga resultat hittades för {{searchTerm}}", + "ERROR": "Vi stötte på ett problem under sökningen - försök igen.", + "COLUMNS": { + "NAME": "Visa namn", + "MODIFIED_BY": "Modifierad av", + "MODIFIED_AT": "Modiferad den" + } + }, + "FILTER": { + "ACTIONS": { + "CLEAR": "Rensa", + "APPLY": "Tillämpa", + "CLEAR-ALL": "Rensa alla", + "SHOW-MORE": "Visa mer", + "SHOW-LESS": "Visa mindre", + "FILTER-CATEGORY": "Filterkategori" + }, + "BUTTONS": { + "CLEAR-ALL": { + "LABEL": "Rensa alla", + "TOOLTIP": "Detta kommer att ta bort alla val" + }, + "RESET-ALL": { + "LABEL": "Återställ alla", + "TOOLTIP": "Detta kommer att återställa alla val och alla filter" + } + }, + "RANGE": { + "FROM": "Från", + "TO": "Till", + "FROM-DATE": "Från", + "TO-DATE": "Till" + }, + "VALIDATION": { + "REQUIRED-VALUE": "Obligatoriskt värde", + "NO-DAYS": "Inga dagar valda", + "INVALID-FORMAT": "Ogiltigt format", + "INVALID-DATE": "Ogiltigt datum. Datumet måste vara i formatet '{{ requiredFormat }}'", + "BEYOND-MAX-DATE": "Datumet ligger bortom maximidatum" + } + }, + "ICONS": { + "ft_ic_raster_image": "Bild-fil", + "ft_ic_pdf": "PDF-dokument", + "ft_ic_ms_excel": "Microsoft Excel-fil", + "ft_ic_ms_word": "Microsoft Word-dokument", + "ft_ic_ms_powerpoint": "Microsoft PowerPoint fil", + "ft_ic_video": "Videofil", + "ft_ic_document": "Dokumentfil", + "ft_ic_website": "Webbresurs", + "ft_ic_archive": "Arkivfil", + "ft_ic_presentation": "Presentationsfil", + "ft_ic_spreadsheet": "Kalkylarkfil" + }, + "DOCUMENT_LIST": { + "COLUMNS": { + "DISPLAY_NAME": "Visa namn", + "CREATED_BY": "Skapad av", + "CREATED_ON": "Skapad" + }, + "ACTIONS": { + "FOLDER": { + "DELETE": "Radera", + "MOVE": "Flytta", + "COPY": "Kopiera" + }, + "DOCUMENT": { + "DOWNLOAD": "Ladda ner", + "DELETE": "Radera", + "MOVE": "Flytta", + "COPY": "Kopiera", + "PROCESS_ACTION": "Starta process" + } + } + } + }, + "PERMISSION": { + "LACKOF": "Du har inte {{permission}} behörighet att {{action}} {{type}}" + }, + "METADATA": { + "BASIC": { + "HEADER": "Egenskaper", + "NAME": "Namn", + "TITLE": "Titel", + "DESCRIPTION": "Beskrivning", + "AUTHOR": "Författare", + "MIMETYPE": "Mime-typ", + "SIZE": "Storlek", + "CREATOR": "Upphovsperson", + "CREATED_DATE": "Skapad datum", + "MODIFIER": "Modifierare", + "MODIFIED_DATE": "Modifieringsdatum" + } + }, + "SHARE": { + "PUBLIC-LINK": "Offentlig länk", + "DIALOG-TITLE": "Dela", + "DESCRIPTION": "Klicka på länken nedan för att kopiera den till urklipp", + "TITLE": "Länk att dela", + "EXPIRES": "Löper ut den", + "CLIPBOARD-MESSAGE": "Länk kopierad till urklipp", + "CLOSE": "Stäng", + "CONFIRMATION": { + "DIALOG-TITLE": "Ta bort den här delade länken", + "MESSAGE": "Den här länken kommer att raderas och en ny länk kommer att skapas nästa gång den här filen delas", + "CANCEL": "Avbryt", + "REMOVE": "Ta bort" + } + }, + "PERMISSION_MANAGER": { + "PERMISSION_DISPLAY": { + "INHERITED": "Ärvd", + "AUTHORITY_ID": "Befogenhets-ID", + "ROLE": "Roll", + "LOCALLY_SET": "Lokalt inställd", + "NO_PERMISSIONS": "Inga behörigheter" + }, + "ADD-PERMISSION": { + "SEARCH": "Sök", + "TYPE-MESSAGE": "Skriv något för att börja söka grupper eller personer", + "NO-RESULT": "Inga resultat hittades för den här sökningen", + "ADD-ACTION": "Lägg till", + "CLOSE-ACTION": "Stäng", + "BASE-DIALOG-TITLE": "Sök en grupp eller personer att lägga till...", + "EVERYONE": "Alla" + }, + "ERROR": { + "DUPLICATE-PERMISSION": "Ett eller flera av de behörigheter du har ställt in finns redan: {{list}}", + "NOT-ALLOWED": "Du har inte tillåtelse att ändra behörigheter" + } + }, + "ADF-TREE-VIEW": { + "MISSING-ID": "Ingen nod-ID tillhandahållen!" + }, + "LIBRARY": { + "DIALOG": { + "CREATE_TITLE": "Skapa bibliotek", + "CREATE": "Skapa", + "UPDATE": "Uppdatera", + "EDIT": "Redigera", + "CANCEL": "Avbryt", + "FORM": { + "DESCRIPTION": "Beskrivning", + "SITE_ID": "Biblioteks-ID", + "NAME": "Namn", + "VISIBILITY": "Synlighet" + } + }, + "ROLE": { + "MANAGER": "Hanterare", + "COLLABORATOR": "Medarbetare", + "CONTRIBUTOR": "Deltagare", + "CONSUMER": "Förbrukare" + }, + "VISIBILITY": { + "PRIVATE": "Privat", + "PUBLIC": "Offentlig", + "MODERATED": "Modererad" + }, + "HINTS": { + "SITE_TITLE_EXISTS": "Biblioteknamn används redan" + }, + "ERRORS": { + "GENERIC": "Vi har stött på ett problem", + "EXISTENT_SITE": "Det här biblioteks-ID:t är inte tillgängligt Testa ett annat biblioteks-ID.", + "CONFLICT": "Det här Biblioteks-ID:t används redan. Kontrollera papperskorgen", + "ID_TOO_LONG": "Använd 72 tecken eller färre för URL-namnet", + "DESCRIPTION_TOO_LONG": "Använd 512 tecken eller färre till beskrivningen", + "TITLE_TOO_LONG": "Använd 256 tecken eller färre till titeln", + "TITLE_TOO_SHORT": "Titeln måste vara minst 2 tecken lång", + "ILLEGAL_CHARACTERS": "Använd bara siffror och bokstäver", + "ONLY_SPACES": "Biblioteksnamnet kan inte innehålla enbart mellanrum", + "LIBRARY_UPDATE_ERROR": "Det uppstod ett fel när biblioteksegenskaperna uppdaterades" + }, + "SUCCESS": { + "LIBRARY_UPDATED": "Biblioteksegenskaper uppdaterade" + } + } +} \ No newline at end of file diff --git a/lib/content-services/i18n/zh-CN.json b/lib/content-services/i18n/zh-CN.json index 6c85423a2c..0e1f1b4356 100644 --- a/lib/content-services/i18n/zh-CN.json +++ b/lib/content-services/i18n/zh-CN.json @@ -128,6 +128,9 @@ "TITLE": "取消上传", "TEXT": "停止上传并移除已上传文件。" } + }, + "ARIA-LABEL": { + "VERSION": "文件版本" } }, "FILE_UPLOAD": { @@ -161,7 +164,8 @@ "500": "内部服务器错误,请重试或联系 IT 支持人员 [500]", "504": "服务器超时,请重试或联系 IT 支持人员 [504]", "403": "权限不足,无法在此位置中进行上传 [403]", - "404": "上传位置不再存在 [404]" + "404": "上传位置不再存在 [404]", + "409": "已存在同名文件 [409]" }, "ARIA-LABEL": { "ERROR": "上传错误" diff --git a/lib/core/i18n/ar.json b/lib/core/i18n/ar.json index 8050ccfb23..7bde5c9fce 100644 --- a/lib/core/i18n/ar.json +++ b/lib/core/i18n/ar.json @@ -1,6 +1,9 @@ { "SAVE": "حفظ", "COMPLETE": "تم", + "CANCEL": "إلغاء", + "CLAIM": "مطالبة", + "UNCLAIM": "تحرير", "START PROCESS": "بدء العملية", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "أدخل {{ minLength }} حرف (حرفًا) على الأقل", "NO_LONGER_THAN": "أدخل {{ maxLength }} حرف (حرفًا) كحد أقصى" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "مهمة بدون اسم" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "عودة إلى الرئيسية" } + }, + "500": { + "TITLE": "حدث خطأ.", + "DESCRIPTION": "خطأ في الخادم الداخلي، حاول مرة أخرى أو اتصل بدعم تكنولوجيا المعلومات [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "عودة إلى الرئيسية" + } + }, + "502": { + "TITLE": "حدث خطأ.", + "DESCRIPTION": "بوابة غير صحيحة، حاول مرة أخرى أو اتصل بدعم تكنولوجيا المعلومات [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "عودة إلى الرئيسية" + } + }, + "504": { + "TITLE": "حدث خطأ.", + "DESCRIPTION": "انتهت مهلة الخادم، حاول مرة أخرى أو اتصل بدعم تكنولوجيا المعلومات [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "عودة إلى الرئيسية" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "تم تمكين مستند تشفير" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "انقر للنسخ", + "SUCCESS_COPY": "تم نسخ النص إلى الحافظة" } } \ No newline at end of file diff --git a/lib/core/i18n/cs.json b/lib/core/i18n/cs.json new file mode 100644 index 0000000000..80aac8779f --- /dev/null +++ b/lib/core/i18n/cs.json @@ -0,0 +1,433 @@ +{ + "SAVE": "Uložit", + "COMPLETE": "Dokončit", + "CANCEL": "Zrušit", + "CLAIM": "Převzít", + "UNCLAIM": "Vzdát se", + "START PROCESS": "Zahájit proces", + "FORM": { + "START_FORM": { + "TITLE": "Spustit formulář" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "Náhled není k dispozici" + }, + "FIELD": { + "LOCALSTORAGE": "Místní úložiště", + "SOURCE": "Vybrat zdroj z ", + "SHOW_FILE": "Zobrazit", + "DOWNLOAD_FILE": "Stáhnout", + "REMOVE_FILE": "Odstranit", + "UPLOAD": "Odeslat", + "REQUIRED": "*Požadováno", + "VALIDATOR": { + "INVALID_NUMBER": "Použijte jiný formát čísla", + "INVALID_DATE": "Použijte jiný formát data", + "INVALID_VALUE": "Zadejte jinou hodnotu", + "NOT_GREATER_THAN": "Nesmí být vyšší než {{ maxValue }}", + "NOT_LESS_THAN": "Nesmí být nižší než {{ minValue }}", + "AT_LEAST_LONG": "Zadejte alespoň následující počet znaků: {{ minLength }}", + "NO_LONGER_THAN": "Zadat můžete nejvýše následující počet znaků: {{ maxLength }}" + } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Úloha bez názvu" + } + }, + "CORE": { + "HEADER": { + "LOGO_ARIA": "Logo společnosti" + }, + "FILE_SIZE": { + "BYTES": "bajtů", + "KB": "kB", + "MB": "MB", + "GB": "GB", + "TB": "TB", + "PB": "PB", + "EB": "EB", + "ZB": "ZB", + "YB": "YB" + }, + "PAGINATION": { + "ARIA": { + "ITEMS_PER_PAGE": "Selektor velikosti stránky", + "CURRENT_PAGE": "Selektor současné stránky", + "PREVIOUS_PAGE": "Tlačítko Předchozí stránka", + "NEXT_PAGE": "Tlačítko Další stránka" + }, + "ITEMS_RANGE": "Zobrazeno {{ range }} z {{ total }}", + "ITEMS_PER_PAGE": "Položky na stránce", + "CURRENT_PAGE": "Str. {{ number }}", + "TOTAL_PAGES": "z {{ total }}" + }, + "DIALOG": { + "DOWNLOAD_ZIP": { + "ACTIONS": { + "CANCEL": "Zrušit" + }, + "TITLE": "Probíhá vkládání souborů do archivu ZIP. Akce může několik minut trvat." + } + }, + "FILE_DIALOG": { + "FILE_LOCK": "Uzamknout soubor", + "ALLOW_OTHERS_CHECKBOX": "Povolit uživateli měnit tento soubor", + "FILE_LOCK_CHECKBOX": "Uzamknout soubor", + "TIME_LOCK_CHECKBOX": "Časový zámek", + "SAVE_BUTTON": { + "LABEL": "Uložit" + }, + "CANCEL_BUTTON": { + "LABEL": "Zrušit" + } + }, + "FOLDER_DIALOG": { + "CREATE_FOLDER_TITLE": "Vytvořit novou složku", + "EDIT_FOLDER_TITLE": "Upravit složku", + "FOLDER_NAME": { + "LABEL": "Název", + "ERRORS": { + "REQUIRED": "Je nutné zadat název složky", + "SPECIAL_CHARACTERS": "Název složky nesmí obsahovat následující znaky * \" < > \\ / ? : |", + "ENDING_DOT": "Název složky nesmí začínat ani končit tečkou", + "ONLY_SPACES": "Název složky nesmí obsahovat pouze mezery" + } + }, + "FOLDER_DESCRIPTION": { + "LABEL": "Popis" + }, + "CREATE_BUTTON": { + "LABEL": "Vytvořit" + }, + "UPDATE_BUTTON": { + "LABEL": "Aktualizovat" + }, + "CANCEL_BUTTON": { + "LABEL": "Zrušit" + } + }, + "MESSAGES": { + "ERRORS": { + "GENERIC": "Akce se nezdařila. Zkuste to znovu nebo se obraťte na oddělení IT.", + "EXISTENT_FOLDER": "Složka s tímto názvem již existuje. Zadejte jiný název." + } + }, + "RESTORE_NODE": { + "VIEW": "Zobrazit", + "PARTIAL_PLURAL": "Některé položky ({{ number }}) nebylo možné obnovit, protože došlo k potížím s umístěním obnovených položek", + "NODE_EXISTS": "Položku „{{ name }}“ nebylo možné obnovit, protože již existuje", + "LOCATION_MISSING": "Položku „{{ name }}“ nebylo možné obnovit, protože původní umístění již neexistuje", + "GENERIC": "Při pokusu o obnovení položky „{{ name }}“ došlo k potížím", + "PLURAL": "Obnovení proběhlo úspěšně", + "SINGULAR": "Položku „{{ name }}“​se podařilo úspěšně obnovit" + }, + "DELETE_NODE": { + "SINGULAR": "„{{ name }}“ se podařilo úspěšně odstranit", + "PLURAL": "Položky ({{ number }}) byly odstraněny", + "PARTIAL_SINGULAR": "Odstraněné položky: {{ success }}. Některé položky ({{ failed }}) se nepodařilo odstranit.", + "PARTIAL_PLURAL": "Odstraněné položky: {{ success }}. Některé položky ({{ failed }}) se nepodařilo odstranit.", + "ERROR_SINGULAR": "„{{ name }}“ nebylo možné odstranit", + "ERROR_PLURAL": "Některé položky ({{ number }}) nebylo možné odstranit" + }, + "HOST_SETTINGS": { + "TYPE-AUTH": "Typ ověřování", + "BASIC": "Základní ověřování", + "SSO": "Jednotné přihlášení", + "IMPLICIT-FLOW": "Implicitní tok", + "PROVIDER": "Poskytovatel", + "REQUIRED": "Toto pole je povinné", + "CS_URL_ERROR": "Adresa Content Services neodpovídá formátu adresy URL", + "PS_URL_ERROR": "Adresa Process Services neodpovídá formátu adresy URL", + "TITLE": "Nastavení", + "CS-HOST": "Adresa URL pro Content Services", + "BP-HOST": "Adresa URL pro Process Services", + "BACK": "Zpět", + "APPLY": "Použít", + "NOT_VALID": "http(s)://host|ip:port(/path) nelze rozeznat. Použijte jinou adresu URL.", + "REDIRECT": "URI pro přesměrování", + "REDIRECT_LOGOUT": "URI pro přesměrování (odhlášení)", + "SILENT": "Přihlášení na pozadí", + "SCOPE": "Rozsah", + "CLIENT": "ID klienta" + }, + "CARDVIEW": { + "KEYVALUEPAIRS": { + "ADD": "Přidat nové", + "NAME": "Název", + "VALUE": "Hodnota" + }, + "VALIDATORS": { + "FLOAT_VALIDATION_ERROR": "Použít formát čísla", + "INT_VALIDATION_ERROR": "Použít formát celého čísla" + } + }, + "METADATA": { + "BASIC": { + "HEADER": "Vlastnosti", + "NAME": "Název", + "TITLE": "Označení", + "DESCRIPTION": "Popis", + "AUTHOR": "Autor", + "MIMETYPE": "Typ MIME", + "SIZE": "Velikost", + "CREATOR": "Autor", + "CREATED_DATE": "Datum vytvoření", + "MODIFIER": "Upravující", + "MODIFIED_DATE": "Datum úpravy" + }, + "ACTIONS": { + "EDIT": "Upravit", + "SAVE": "Uložit", + "CANCEL": "Zrušit", + "TOGGLE": "Přepnout hodnotu" + } + } + }, + "COMMENTS": { + "NONE": "Žádné komentáře", + "ADD": "Přidat", + "HEADER": "Komentáře ({{ count }})", + "CREATED_BY_HEADER": "Vytvořil(a)", + "MESSAGE_HEADER": "Zpráva", + "DIALOG": { + "TITLE": "Nový komentář", + "LABELS": { + "MESSAGE": "Zpráva" + }, + "BUTTON": { + "ADD": "Přidat komentář", + "CANCEL": "Zrušit" + } + } + }, + "LOGIN": { + "LOGO": "Alfresco", + "LABEL": { + "LOGIN": "Přihlásit se", + "USERNAME": "Uživatelské jméno", + "PASSWORD": "Heslo", + "REMEMBER": "Zapamatovat přihlášení" + }, + "MESSAGES": { + "USERNAME-REQUIRED": "Požadováno", + "USERNAME-MIN": "Vaše uživatelské jméno musí obsahovat alespoň {{ minLength }} znaků.", + "PASSWORD-REQUIRED": "Přihlaste se zadáním hesla", + "LOGIN-ERROR-CREDENTIALS": "Zadali jste neznámé uživatelské jméno nebo heslo", + "LOGIN-ERROR-PROVIDERS": "Poskytovatele nelze ponechat nedefinované", + "LOGIN-ERROR-CORS": "Výjimka CORS. Zkontrolujte konfiguraci serveru.", + "LOGIN-ERROR-CSRF": "Výjimka CSRF. Použijte u parametru „login.component“ hodnotu [disableCsrf]=\"true\".", + "LOGIN-ECM-LICENSE": "Úložiště Alfresco Content Services je v režimu „Pouze ke čtení“.", + "SSO-WRONG-CONFIGURATION": "Server ověrování pomocí jednotného přihlášení je nedostupný" + }, + "BUTTON": { + "LOGIN": "Přihlásit se", + "CHECKING": "Kontrola", + "WELCOME": "Vítejte", + "SSO": "Jednotné přihlášení" + }, + "ACTION": { + "HELP": "Potřebujete pomoc?", + "REGISTER": "Zaregistrovat" + }, + "DIALOG": { + "CANCEL": "Zrušit", + "CHOOSE": "Vybrat" + } + }, + "ADF-DATATABLE": { + "EMPTY": { + "HEADER": "Tento seznam je prázdný", + "DRAG-AND-DROP": { + "TITLE": "Přetažením", + "SUBTITLE": "odešlete soubory" + } + }, + "CONTENT-ACTIONS": { + "TOOLTIP": "Akce pro obsah" + }, + "ACCESSIBILITY": { + "SELECT_ALL": "Vybrat vše", + "SELECT_FILE": "Vybrat soubor" + } + }, + "USER_PROFILE": { + "LABELS": { + "ECM": { + "JOB_TITLE": "Název funkce" + }, + "BPM": { + "TENANT": "Tenant" + } + }, + "TAB": { + "CS": "Content Services", + "PS": "Process Services" + } + }, + "ADF_VIEWER": { + "ACTIONS": { + "BACK": "Zpět", + "OPEN_WITH": "Otevřít v", + "DOWNLOAD": "Stáhnout", + "PRINT": "Tisk", + "SHARE": "Sdílet", + "MORE_ACTIONS": "Další akce", + "INFO": "Informace", + "FULLSCREEN": "Aktivovat režim celé obrazovky", + "CLOSE": "Zavřít", + "NEXT_FILE": "Další soubor", + "PREV_FILE": "Předchozí soubor" + }, + "ARIA": { + "PREVIOUS_PAGE": "Předchozí stránka", + "NEXT_PAGE": "Další stránka", + "ZOOM_IN": "Přiblížit", + "ZOOM_OUT": "Oddálit", + "FIT_PAGE": "Přizpůsobit na stránku", + "ROTATE_LEFT": "Otočit vlevo", + "ROTATE_RIGHT": "Otočit vpravo", + "RESET": "Reset" + }, + "PAGE_LABEL": { + "SHOWING": "Zobrazeno", + "OF": "z" + }, + "LOADING": "Načítání", + "UNKNOWN_FORMAT": "Náhled se nepodařilo načíst", + "SIDEBAR": { + "THUMBNAILS": { + "PAGE": "Stránka {{ pageNum }}" + }, + "METADATA": { + "MORE_INFORMATION": "Další informace", + "LESS_INFORMATION": "Méně informací" + } + }, + "PDF_DIALOG": { + "SUBMIT": "Odeslat", + "CLOSE": "Zavřít", + "PLACEHOLDER": "Heslo", + "ERROR": "Heslo je chybné" + } + }, + "ERROR_CONTENT": { + "UNKNOWN": { + "TITLE": "Došlo k problému.", + "DESCRIPTION": "Vypadá to, že se něco pokazilo.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + }, + "403": { + "TITLE": "Nemáte potřebná oprávněni pro přístup k tomuto serveru.", + "DESCRIPTION": "Nemáte potřebná oprávněni pro přístup k těmto prostředkům na serveru.", + "SECONDARY_BUTTON": { + "TEXT": "Nahlásit problém" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + }, + "404": { + "TITLE": "Došlo k chybě.", + "DESCRIPTION": "Stránku, kterou hledáte, se nepodařilo najít.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + }, + "500": { + "TITLE": "Došlo k chybě.", + "DESCRIPTION": "Došlo k interní chybě serveru. Zkuste to znovu nebo se obraťte na podporu IT [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + }, + "502": { + "TITLE": "Došlo k chybě.", + "DESCRIPTION": "Chybná brána. Zkuste to znovu nebo se obraťte na podporu IT [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + }, + "504": { + "TITLE": "Došlo k chybě.", + "DESCRIPTION": "Vypršel časový limit serveru. Zkuste to znovu nebo se obraťte na podporu IT [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zpět domů" + } + } + }, + "ABOUT": { + "SERVER_SETTINGS": { + "TITLE": "Nastavení serveru", + "DESCRIPTION": "Následující hodnoty pochází z AppConfigService", + "CONTENT_SERVICE_HOST": "Adresa URL pro Alfresco Content Services: {{ value }}", + "PROCESS_SERVICE_HOST": "Adresa URL pro Alfresco Process Services: {{ value }}" + }, + "VERSIONS": { + "TITLE": "Verze produktu", + "CONTENT_SERVICE": "ECM", + "PROCESS_SERVICE": "BPM", + "LABELS": { + "EDITION": "Edice", + "VERSION": "Verze", + "LICENSE": "Licence", + "STATUS": "Stav", + "MODULES": "Moduly" + } + }, + "SOURCE_CODE": { + "TITLE": "Zdrojový kód", + "DESCRIPTION": "Projekt vychází z následujícího commitu:" + }, + "PACKAGES": { + "TITLE": "Balíčky", + "DESCRIPTION": "Aktuální projekt používá následující knihovny ADF:" + }, + "TABLE_HEADERS": { + "MODULES": { + "ID": "ID", + "TITLE": "Označení", + "DESCRIPTION": "Popis", + "INSTALL_DATE": "Datum instalace", + "INSTALL_STATE": "Stav instalace", + "VERSION_MIN": "Vedlejší verze", + "VERSION_MAX": "Hlavní verze" + }, + "STATUS": { + "READ_ONLY": "Pouze ke čtení", + "AUDIT_ENABLED": "Je povolen audit", + "QUICK_SHARE_ENABLED": "Je povoleno rychlé sdílení", + "THUMBNAIL_ENABLED": "Vytváření miniatury" + }, + "LICENSE": { + "ISSUES_AT": "Vydáno:", + "EXPIRES_AT": "Vyprší:", + "REMAINING_DAYS": "Zbývající dny", + "HOLDER": "Držitel", + "MODE": "Režim", + "CLUSTER_ENABLED": "Je povolen cluster", + "CRYPTODOC_ENABLED": "Je povolen Cryptodoc" + } + } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Kliknutím zkopírovat", + "SUCCESS_COPY": "Text zkopírovaný do schránky" + } +} \ No newline at end of file diff --git a/lib/core/i18n/da.json b/lib/core/i18n/da.json new file mode 100644 index 0000000000..dd9dafda25 --- /dev/null +++ b/lib/core/i18n/da.json @@ -0,0 +1,433 @@ +{ + "SAVE": "Gem", + "COMPLETE": "Fuldført", + "CANCEL": "Annuller", + "CLAIM": "Gør krav på", + "UNCLAIM": "Frigiv", + "START PROCESS": "Start proces", + "FORM": { + "START_FORM": { + "TITLE": "Åbn formular" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "Forhåndsvisning er ikke tilgængelig" + }, + "FIELD": { + "LOCALSTORAGE": "Lokalt lager", + "SOURCE": "Vælg kilde fra ", + "SHOW_FILE": "Vis", + "DOWNLOAD_FILE": "Download", + "REMOVE_FILE": "Fjern", + "UPLOAD": "Upload", + "REQUIRED": "*Påkrævet", + "VALIDATOR": { + "INVALID_NUMBER": "Brug et andet talformat", + "INVALID_DATE": "Brug et andet datoformat", + "INVALID_VALUE": "Angiv en anden værdi", + "NOT_GREATER_THAN": "Må ikke være større end {{ maxValue }}", + "NOT_LESS_THAN": "Må ikke være mindre end {{ minValue }}", + "AT_LEAST_LONG": "Skriv mindst {{ minLength }} tegn", + "NO_LONGER_THAN": "Skriv højst {{ maxLength }} tegn" + } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Opgave uden navn" + } + }, + "CORE": { + "HEADER": { + "LOGO_ARIA": "Firmalogo" + }, + "FILE_SIZE": { + "BYTES": "Byte", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB", + "PB": "PB", + "EB": "EB", + "ZB": "ZB", + "YB": "YB" + }, + "PAGINATION": { + "ARIA": { + "ITEMS_PER_PAGE": "Sidestørrelsevælger", + "CURRENT_PAGE": "Aktuel sidevælger", + "PREVIOUS_PAGE": "Knappen Forrige side", + "NEXT_PAGE": "Knappen Næste side" + }, + "ITEMS_RANGE": "Viser {{ range }} af {{ total }}", + "ITEMS_PER_PAGE": "Elementer pr. side", + "CURRENT_PAGE": "Side {{ number }}", + "TOTAL_PAGES": "af {{ total }}" + }, + "DIALOG": { + "DOWNLOAD_ZIP": { + "ACTIONS": { + "CANCEL": "Annuller" + }, + "TITLE": "Føjer filer til zip-filen. Dette kan tage nogle minutter" + } + }, + "FILE_DIALOG": { + "FILE_LOCK": "Lås fil", + "ALLOW_OTHERS_CHECKBOX": "Tillad, at ejeren ændrer filen", + "FILE_LOCK_CHECKBOX": "Lås fil", + "TIME_LOCK_CHECKBOX": "Tidslås", + "SAVE_BUTTON": { + "LABEL": "Gem" + }, + "CANCEL_BUTTON": { + "LABEL": "Annuller" + } + }, + "FOLDER_DIALOG": { + "CREATE_FOLDER_TITLE": "Opret ny mappe", + "EDIT_FOLDER_TITLE": "Rediger mappe", + "FOLDER_NAME": { + "LABEL": "Navn", + "ERRORS": { + "REQUIRED": "Du skal angive et mappenavn", + "SPECIAL_CHARACTERS": "Mappenavnet må ikke indeholde følgende tegn: * \" < > / ? : |", + "ENDING_DOT": "Mappenavnet må ikke slutte med et punktum.", + "ONLY_SPACES": "Mappenavnet skal indeholde andet end mellemrum" + } + }, + "FOLDER_DESCRIPTION": { + "LABEL": "Beskrivelse" + }, + "CREATE_BUTTON": { + "LABEL": "Opret" + }, + "UPDATE_BUTTON": { + "LABEL": "Opdater" + }, + "CANCEL_BUTTON": { + "LABEL": "Annuller" + } + }, + "MESSAGES": { + "ERRORS": { + "GENERIC": "Handlingen blev ikke fuldført. Prøv igen, eller kontakt dit it-team.", + "EXISTENT_FOLDER": "Der er allerede en mappe med det navn. Prøv et andet navn." + } + }, + "RESTORE_NODE": { + "VIEW": "Vis", + "PARTIAL_PLURAL": "{{ number }} elementer kunne ikke gendannes, fordi der er problemer med placeringen for gendannelse", + "NODE_EXISTS": "Der kan ikke gendannes, da elementet {{ name }} allerede findes", + "LOCATION_MISSING": "Elementet {{ name }} kan ikke gendannes. Den oprindelige placering findes ikke længere", + "GENERIC": "Der opstod et problem under forsøget på at gendanne elementet {{ name }}", + "PLURAL": "Gendannelsen er fuldført", + "SINGULAR": "Elementet {{ name }} er gendannet" + }, + "DELETE_NODE": { + "SINGULAR": "{{ name }} er blevet slettet", + "PLURAL": "{{ number }} elementer er blevet slettet", + "PARTIAL_SINGULAR": "{{ success }} element er blevet slettet. {{ failed }} elementer kunne ikke slettes", + "PARTIAL_PLURAL": "{{ success }} elementer er blevet slettet. {{ failed }} elementer kunne ikke slettes", + "ERROR_SINGULAR": "{{ name }} kunne ikke slettes", + "ERROR_PLURAL": "{{ number }} elementer kunne ikke slettes" + }, + "HOST_SETTINGS": { + "TYPE-AUTH": "Godkendelsestype", + "BASIC": "Grundlæggende godkendelse", + "SSO": "SSO", + "IMPLICIT-FLOW": "Implicit flow", + "PROVIDER": "Udbyder", + "REQUIRED": "Dette felt er påkrævet", + "CS_URL_ERROR": "Adressen til indholdstjenesterne matcher ikke URL-adresseformatet", + "PS_URL_ERROR": "Process Services-adressen matcher ikke URL-adresseformatet", + "TITLE": "Indstillinger", + "CS-HOST": "URL-adresse til indholdstjenester", + "BP-HOST": "URL-adresse til Process Services", + "BACK": "Tilbage", + "APPLY": "Anvend", + "NOT_VALID": "http(s)://vært|ip-adresse:port(/sti) blev ikke genkendt. Prøv en anden URL-adresse.", + "REDIRECT": "URI til omdirigering", + "REDIRECT_LOGOUT": "Omdiriger URI til aflogning", + "SILENT": "Uovervåget login", + "SCOPE": "Omfang", + "CLIENT": "Klient-id" + }, + "CARDVIEW": { + "KEYVALUEPAIRS": { + "ADD": "Tilføj ny(t)", + "NAME": "Navn", + "VALUE": "Værdi" + }, + "VALIDATORS": { + "FLOAT_VALIDATION_ERROR": "Brug et talformat", + "INT_VALIDATION_ERROR": "Brug et heltalsformat" + } + }, + "METADATA": { + "BASIC": { + "HEADER": "Egenskaber", + "NAME": "Navn", + "TITLE": "Titel", + "DESCRIPTION": "Beskrivelse", + "AUTHOR": "Forfatter", + "MIMETYPE": "Mimetype", + "SIZE": "Størrelse", + "CREATOR": "Oprettet af", + "CREATED_DATE": "Oprettelsesdato", + "MODIFIER": "Ændret af", + "MODIFIED_DATE": "Ændringsdato" + }, + "ACTIONS": { + "EDIT": "Rediger", + "SAVE": "Gem", + "CANCEL": "Annuller", + "TOGGLE": "Slå værdi til/fra" + } + } + }, + "COMMENTS": { + "NONE": "Ingen kommentarer", + "ADD": "Tilføj", + "HEADER": "Kommentarer ({{ count }})", + "CREATED_BY_HEADER": "Oprettet af", + "MESSAGE_HEADER": "Meddelelse", + "DIALOG": { + "TITLE": "Ny kommentar", + "LABELS": { + "MESSAGE": "Meddelelse" + }, + "BUTTON": { + "ADD": "Tilføj kommentar", + "CANCEL": "Annuller" + } + } + }, + "LOGIN": { + "LOGO": "Alfresco", + "LABEL": { + "LOGIN": "Log ind", + "USERNAME": "Brugernavn", + "PASSWORD": "Adgangskode", + "REMEMBER": "Husk mig" + }, + "MESSAGES": { + "USERNAME-REQUIRED": "Påkrævet", + "USERNAME-MIN": "Dit brugernavn skal være på mindst {{ minLength }} tegn.", + "PASSWORD-REQUIRED": "Skriv din adgangskode for at logge på", + "LOGIN-ERROR-CREDENTIALS": "Du har skrevet et ukendt brugernavn eller en ukendt adgangskode", + "LOGIN-ERROR-PROVIDERS": "Der skal angives en definition for udbydere", + "LOGIN-ERROR-CORS": "CORS-undtagelse. Kontrollér din serverkonfiguration", + "LOGIN-ERROR-CSRF": "CSRF-undtagelse. Angiv [disableCsrf]=\"true\" i login.component", + "LOGIN-ECM-LICENSE": "Alfresco Content Services-lageret er i skrivebeskyttet tilstand", + "SSO-WRONG-CONFIGURATION": "Der kan ikke oprettes forbindelse til SSO-godkendelsesserveren" + }, + "BUTTON": { + "LOGIN": "Log ind", + "CHECKING": "Kontrollerer", + "WELCOME": "Velkommen", + "SSO": "Log på SSO" + }, + "ACTION": { + "HELP": "Har du brug for hjælp?", + "REGISTER": "Tilmeld" + }, + "DIALOG": { + "CANCEL": "Annuller", + "CHOOSE": "Vælg" + } + }, + "ADF-DATATABLE": { + "EMPTY": { + "HEADER": "Denne liste er tom", + "DRAG-AND-DROP": { + "TITLE": "Træk og slip", + "SUBTITLE": "for at uploade filer" + } + }, + "CONTENT-ACTIONS": { + "TOOLTIP": "Indholdshandlinger" + }, + "ACCESSIBILITY": { + "SELECT_ALL": "Vælg alle", + "SELECT_FILE": "Vælg fil" + } + }, + "USER_PROFILE": { + "LABELS": { + "ECM": { + "JOB_TITLE": "Jobtitel" + }, + "BPM": { + "TENANT": "Tenant" + } + }, + "TAB": { + "CS": "Indholdstjenester", + "PS": "Process Services" + } + }, + "ADF_VIEWER": { + "ACTIONS": { + "BACK": "Tilbage", + "OPEN_WITH": "Åbn med", + "DOWNLOAD": "Download", + "PRINT": "Udskriv", + "SHARE": "Del", + "MORE_ACTIONS": "Flere handlinger", + "INFO": "Oplysninger", + "FULLSCREEN": "Aktivér fuld skærm", + "CLOSE": "Luk", + "NEXT_FILE": "Næste fil", + "PREV_FILE": "Forrige fil" + }, + "ARIA": { + "PREVIOUS_PAGE": "Forrige side", + "NEXT_PAGE": "Næste side", + "ZOOM_IN": "Zoom ind", + "ZOOM_OUT": "Zoom ud", + "FIT_PAGE": "Tilpas side", + "ROTATE_LEFT": "Roter til venstre", + "ROTATE_RIGHT": "Roter til højre", + "RESET": "Nulstil" + }, + "PAGE_LABEL": { + "SHOWING": "Viser", + "OF": "af" + }, + "LOADING": "Indlæser", + "UNKNOWN_FORMAT": "Forhåndsvisningen kunne ikke indlæses", + "SIDEBAR": { + "THUMBNAILS": { + "PAGE": "Side {{ pageNum }}" + }, + "METADATA": { + "MORE_INFORMATION": "Flere oplysninger", + "LESS_INFORMATION": "Færre oplysninger" + } + }, + "PDF_DIALOG": { + "SUBMIT": "Send", + "CLOSE": "Luk", + "PLACEHOLDER": "Adgangskode", + "ERROR": "Adgangskoden er forkert" + } + }, + "ERROR_CONTENT": { + "UNKNOWN": { + "TITLE": "Der er opstået et problem.", + "DESCRIPTION": "Det ser ud til, at noget gik forkert.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + }, + "403": { + "TITLE": "Du har ikke tilladelse til at få adgang til serveren.", + "DESCRIPTION": "Du har ikke tilladt adgang til denne ressource på serveren.", + "SECONDARY_BUTTON": { + "TEXT": "Rapportér problem" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + }, + "404": { + "TITLE": "Der opstod en fejl.", + "DESCRIPTION": "Vi kunne ikke finde den side, du ledte efter.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + }, + "500": { + "TITLE": "Der opstod en fejl.", + "DESCRIPTION": "Intern serverfejl. Prøv igen, eller kontakt it-support [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + }, + "502": { + "TITLE": "Der opstod en fejl.", + "DESCRIPTION": "Forkert gateway. Prøv igen, eller kontakt it-support [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + }, + "504": { + "TITLE": "Der opstod en fejl.", + "DESCRIPTION": "Der opstod timeout for serveren. Prøv igen, eller kontakt it-support [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbage til forsiden" + } + } + }, + "ABOUT": { + "SERVER_SETTINGS": { + "TITLE": "Serverindstillinger", + "DESCRIPTION": "Nedenstående værdier er taget fra AppConfigService", + "CONTENT_SERVICE_HOST": "URL-adresse til Alfresco-indholdstjenester: {{ value }}", + "PROCESS_SERVICE_HOST": "URL-adresse til Alfresco-procestjenester: {{ value }}" + }, + "VERSIONS": { + "TITLE": "Produktversioner", + "CONTENT_SERVICE": "ECM", + "PROCESS_SERVICE": "BPM", + "LABELS": { + "EDITION": "Version", + "VERSION": "Version", + "LICENSE": "Licens", + "STATUS": "Status", + "MODULES": "Moduler" + } + }, + "SOURCE_CODE": { + "TITLE": "Kildekode", + "DESCRIPTION": "Du kører projektet på baggrund af følgende bekræftelse:" + }, + "PACKAGES": { + "TITLE": "Pakker", + "DESCRIPTION": "Det aktuelle projekt bruger følgende ADF-biblioteker:" + }, + "TABLE_HEADERS": { + "MODULES": { + "ID": "Id", + "TITLE": "Titel", + "DESCRIPTION": "Beskrivelse", + "INSTALL_DATE": "Installationsdato", + "INSTALL_STATE": "Installationstilstand", + "VERSION_MIN": "Mindre version", + "VERSION_MAX": "Maksimumversion" + }, + "STATUS": { + "READ_ONLY": "Skrivebeskyttet", + "AUDIT_ENABLED": "Er aktiveret til overvågning", + "QUICK_SHARE_ENABLED": "Er aktiveret til hurtig deling", + "THUMBNAIL_ENABLED": "Miniaturegeneration" + }, + "LICENSE": { + "ISSUES_AT": "Udstedt den", + "EXPIRES_AT": "Udløber den", + "REMAINING_DAYS": "Resterende dage", + "HOLDER": "Holder", + "MODE": "Tilstand", + "CLUSTER_ENABLED": "Er aktiveret til klynge", + "CRYPTODOC_ENABLED": "Er aktiveret til kryptodok" + } + } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Klik for at kopiere", + "SUCCESS_COPY": "Teksten er kopieret til Udklipsholder" + } +} \ No newline at end of file diff --git a/lib/core/i18n/de.json b/lib/core/i18n/de.json index 1d6d32c925..4caeb586fc 100644 --- a/lib/core/i18n/de.json +++ b/lib/core/i18n/de.json @@ -1,6 +1,9 @@ { "SAVE": "Speichern", "COMPLETE": "Abschließen", + "CANCEL": "Abbrechen", + "CLAIM": "Beanspruchen", + "UNCLAIM": "Anspruch aufheben", "START PROCESS": "Prozess starten", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Geben Sie mindestens {{ minLength }} Zeichen ein", "NO_LONGER_THAN": "Geben Sie höchstens {{ maxLength }} Zeichen ein" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Namenlose Aufgabe" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Zurück zur Startseite" } + }, + "500": { + "TITLE": "Es ist ein Fehler aufgetreten.", + "DESCRIPTION": "Interner Serverfehler. Versuchen Sie es noch einmal oder wenden Sie sich an den IT-Support. [500]", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zurück zur Startseite" + } + }, + "502": { + "TITLE": "Es ist ein Fehler aufgetreten.", + "DESCRIPTION": "Ungültiges Gateway. Versuchen Sie es noch einmal oder wenden Sie sich an den IT-Support. [502]", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zurück zur Startseite" + } + }, + "504": { + "TITLE": "Es ist ein Fehler aufgetreten.", + "DESCRIPTION": "Server-Timeout. Versuchen Sie es noch einmal oder wenden Sie sich an den IT-Support. [504]", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Zurück zur Startseite" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Ist Cryptodoc aktiviert" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Zum Kopieren klicken", + "SUCCESS_COPY": "Text in Zwischenablage kopiert" } } \ No newline at end of file diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json index fa01565df3..e4ac621af8 100644 --- a/lib/core/i18n/en.json +++ b/lib/core/i18n/en.json @@ -3,7 +3,7 @@ "COMPLETE": "COMPLETE", "CANCEL": "CANCEL", "CLAIM": "CLAIM", - "UNCLAIM": "UNCLAIM", + "UNCLAIM": "RELEASE", "START PROCESS": "START PROCESS", "FORM": { "START_FORM": { diff --git a/lib/core/i18n/es.json b/lib/core/i18n/es.json index 366d75cbc2..5a5670913a 100644 --- a/lib/core/i18n/es.json +++ b/lib/core/i18n/es.json @@ -1,6 +1,9 @@ { "SAVE": "Guardar", "COMPLETE": "Completar", + "CANCEL": "Cancelar", + "CLAIM": "Pedir", + "UNCLAIM": "Liberar", "START PROCESS": "Iniciar proceso", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Introducir al menos {{ minLength }} caracteres", "NO_LONGER_THAN": "No introducir más de {{ maxLength }} caracteres" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Tarea sin nombre" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Volver al inicio" } + }, + "500": { + "TITLE": "Se ha producido un error.", + "DESCRIPTION": "Error de servidor interno; vuelva a intentarlo o póngase en contacto con el equipo de TI [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Volver al inicio" + } + }, + "502": { + "TITLE": "Se ha producido un error.", + "DESCRIPTION": "Puerta de enlace incorrecta; vuelva a intentarlo o póngase en contacto con el equipo de TI [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Volver al inicio" + } + }, + "504": { + "TITLE": "Se ha producido un error.", + "DESCRIPTION": "Se ha agotado el tiempo de espera del servidor; vuelva a intentarlo o póngase en contacto con el equipo de TI [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Volver al inicio" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Compatible con Cryptodoc" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Haga clic para copiar", + "SUCCESS_COPY": "Texto copiado al portapapeles" } } \ No newline at end of file diff --git a/lib/core/i18n/fi.json b/lib/core/i18n/fi.json new file mode 100644 index 0000000000..8613842485 --- /dev/null +++ b/lib/core/i18n/fi.json @@ -0,0 +1,433 @@ +{ + "SAVE": "Tallenna", + "COMPLETE": "Merkitse valmiiksi", + "CANCEL": "Peruuta", + "CLAIM": "Varaa", + "UNCLAIM": "Vapauta", + "START PROCESS": "Käynnistä prosessi", + "FORM": { + "START_FORM": { + "TITLE": "Aloita lomake" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "Esikatselu ei ole käytettävissä" + }, + "FIELD": { + "LOCALSTORAGE": "Paikallinen tallennustila", + "SOURCE": "Valitse lähde kohteesta: ", + "SHOW_FILE": "Näytä", + "DOWNLOAD_FILE": "Lataa", + "REMOVE_FILE": "Poista", + "UPLOAD": "Lataa", + "REQUIRED": "*Pakollinen", + "VALIDATOR": { + "INVALID_NUMBER": "Käytä toista numeromuotoa", + "INVALID_DATE": "Käytä toista päivämäärämuotoa", + "INVALID_VALUE": "Anna toinen arvo", + "NOT_GREATER_THAN": "Ei voi olla suurempi kuin {{ maxValue }}", + "NOT_LESS_THAN": "Ei voi olla pienempi kuin {{ minValue }}", + "AT_LEAST_LONG": "Anna vähintään {{ minLength }} merkkiä", + "NO_LONGER_THAN": "Anna enintään {{ maxLength }} merkkiä" + } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Nimetön tehtävä" + } + }, + "CORE": { + "HEADER": { + "LOGO_ARIA": "Yrityksen logo" + }, + "FILE_SIZE": { + "BYTES": "tavua", + "KB": "kt", + "MB": "Mt", + "GB": "Gt", + "TB": "Tt", + "PB": "Pt", + "EB": "Et", + "ZB": "ZB", + "YB": "YB" + }, + "PAGINATION": { + "ARIA": { + "ITEMS_PER_PAGE": "Sivukoon valitsin", + "CURRENT_PAGE": "Nykyinen sivuvalitsin", + "PREVIOUS_PAGE": "Edellisen sivun painike", + "NEXT_PAGE": "Seuraavan sivun painike" + }, + "ITEMS_RANGE": "Näytetään {{ range }}/{{ total }}", + "ITEMS_PER_PAGE": "Kohteita sivulla", + "CURRENT_PAGE": "Sivu {{ number }}", + "TOTAL_PAGES": "/{{ total }}" + }, + "DIALOG": { + "DOWNLOAD_ZIP": { + "ACTIONS": { + "CANCEL": "Peruuta" + }, + "TITLE": "Tiedostoja lisätään zip-kansioon. Tämä voi kestää muutaman minuutin." + } + }, + "FILE_DIALOG": { + "FILE_LOCK": "Lukitse tiedosto", + "ALLOW_OTHERS_CHECKBOX": "Salli omistajan muokata tätä tiedostoa", + "FILE_LOCK_CHECKBOX": "Lukitse tiedosto", + "TIME_LOCK_CHECKBOX": "Aikalukko", + "SAVE_BUTTON": { + "LABEL": "Tallenna" + }, + "CANCEL_BUTTON": { + "LABEL": "Peruuta" + } + }, + "FOLDER_DIALOG": { + "CREATE_FOLDER_TITLE": "Luo uusi kansio", + "EDIT_FOLDER_TITLE": "Muokkaa kansiota", + "FOLDER_NAME": { + "LABEL": "Nimi", + "ERRORS": { + "REQUIRED": "Kansion nimi on pakollinen", + "SPECIAL_CHARACTERS": "Kansion nimi ei voi sisältää seuraavia merkkejä: * \" < > \\ / ? : |", + "ENDING_DOT": "Kansion nimi ei voi loppua pisteeseen (.)", + "ONLY_SPACES": "Kansion nimessä ei voi olla välilyöntejä" + } + }, + "FOLDER_DESCRIPTION": { + "LABEL": "Kuvaus" + }, + "CREATE_BUTTON": { + "LABEL": "Luo" + }, + "UPDATE_BUTTON": { + "LABEL": "Päivitä" + }, + "CANCEL_BUTTON": { + "LABEL": "Peruuta" + } + }, + "MESSAGES": { + "ERRORS": { + "GENERIC": "Toiminto ei onnistunut. Yritä uudelleen tai ota yhteyttä IT-tukeesi.", + "EXISTENT_FOLDER": "Samanniminen kansio on jo olemassa. Käytä toista nimeä." + } + }, + "RESTORE_NODE": { + "VIEW": "Näytä", + "PARTIAL_PLURAL": "{{ number }} kohdetta ei palautettu palautussijainnin ongelmien vuoksi", + "NODE_EXISTS": "Palauttaminen ei onnistu: {{ name }} on jo olemassa", + "LOCATION_MISSING": "Kohteen {{ name }} palauttaminen ei onnistu, koska alkuperäistä sijaintia ei ole enää olemassa", + "GENERIC": "Kohteen {{ name }} palauttamisessa ilmeni ongelma", + "PLURAL": "Palautus onnistui", + "SINGULAR": "{{ name }} palautettiin" + }, + "DELETE_NODE": { + "SINGULAR": "{{ name }} poistettiin", + "PLURAL": "{{ number }} kohdetta poistettiin", + "PARTIAL_SINGULAR": "Poistettiin {{ success }} kohde, {{ failed }} kohteen poistaminen ei onnistunut", + "PARTIAL_PLURAL": "Poistettiin {{ success }} kohdetta, {{ failed }} kohteen poistaminen ei onnistunut", + "ERROR_SINGULAR": "Kohteen {{ name }} poistaminen ei onnistunut", + "ERROR_PLURAL": "{{ number }} kohteen poistaminen ei onnistunut" + }, + "HOST_SETTINGS": { + "TYPE-AUTH": "Todennustyyppi", + "BASIC": "Perustodennus", + "SSO": "Kertakirjautuminen", + "IMPLICIT-FLOW": "Epäsuora kulku", + "PROVIDER": "Palvelu", + "REQUIRED": "Tämä kenttä on pakollinen", + "CS_URL_ERROR": "Content Services -osoite ei täsmää URL-muodon kanssa", + "PS_URL_ERROR": "Process Services -osoite ei täsmää URL-muodon kanssa", + "TITLE": "Asetukset", + "CS-HOST": "Content Servicesin URL-osoite", + "BP-HOST": "Process Servicesin URL-osoite", + "BACK": "Takaisin", + "APPLY": "Käytä", + "NOT_VALID": "Osoitetta http(s)://host|ip:port(/path) ei tunnisteta. Kokeile toista URL-osoitetta.", + "REDIRECT": "Uudelleenohjauksen URI-osoite", + "REDIRECT_LOGOUT": "Uudelleenohjauksen URI-osoite – uloskirjautuminen", + "SILENT": "Hiljainen kirjautuminen", + "SCOPE": "Laajuus", + "CLIENT": "Asiakastunnus" + }, + "CARDVIEW": { + "KEYVALUEPAIRS": { + "ADD": "Lisää uusi", + "NAME": "Nimi", + "VALUE": "Arvo" + }, + "VALIDATORS": { + "FLOAT_VALIDATION_ERROR": "Käytä numeromuotoa", + "INT_VALIDATION_ERROR": "Käytä kokonaislukumuotoa" + } + }, + "METADATA": { + "BASIC": { + "HEADER": "Ominaisuudet", + "NAME": "Nimi", + "TITLE": "Otsikko", + "DESCRIPTION": "Kuvaus", + "AUTHOR": "Tekijä", + "MIMETYPE": "MIME-tyyppi", + "SIZE": "Koko", + "CREATOR": "Tekijä", + "CREATED_DATE": "Luontipäivämäärä", + "MODIFIER": "Muokkaaja", + "MODIFIED_DATE": "Muokkauspäivämäärä" + }, + "ACTIONS": { + "EDIT": "Muokkaa", + "SAVE": "Tallenna", + "CANCEL": "Peruuta", + "TOGGLE": "Vaihda arvoa" + } + } + }, + "COMMENTS": { + "NONE": "Ei kommentteja", + "ADD": "Lisää", + "HEADER": "Kommentit ({{ count }})", + "CREATED_BY_HEADER": "Tekijä:", + "MESSAGE_HEADER": "Viesti", + "DIALOG": { + "TITLE": "Uusi kommentti", + "LABELS": { + "MESSAGE": "Viesti" + }, + "BUTTON": { + "ADD": "Lisää kommentti", + "CANCEL": "Peruuta" + } + } + }, + "LOGIN": { + "LOGO": "Alfresco", + "LABEL": { + "LOGIN": "Kirjaudu sisään", + "USERNAME": "Käyttäjänimi", + "PASSWORD": "Salasana", + "REMEMBER": "Muista minut" + }, + "MESSAGES": { + "USERNAME-REQUIRED": "Pakollinen", + "USERNAME-MIN": "Käyttäjänimessä täytyy olla vähintään {{ minLength }} merkkiä.", + "PASSWORD-REQUIRED": "Jos haluat kirjautua sisään, anna salasanasi", + "LOGIN-ERROR-CREDENTIALS": "Annoit tuntemattoman käyttäjänimen tai salasanan", + "LOGIN-ERROR-PROVIDERS": "Palveluiden määritystä ei voi poistaa", + "LOGIN-ERROR-CORS": "Ilmeni CORS-poikkeus, tarkista palvelinmääritykset", + "LOGIN-ERROR-CSRF": "Ilmeni CSRF-poikkeus, määritä asetuksen [disableCsrf] arvoksi \"true\" kohteessa login.component", + "LOGIN-ECM-LICENSE": "Alfresco Content Services -säilö on Vain luku -tilassa", + "SSO-WRONG-CONFIGURATION": "Kertakirjautumisen todennuspalvelimeen ei saada yhteyttä" + }, + "BUTTON": { + "LOGIN": "Kirjaudu sisään", + "CHECKING": "Tarkistetaan", + "WELCOME": "Tervetuloa", + "SSO": "Kertakirjautuminen" + }, + "ACTION": { + "HELP": "Tarvitsetko apua?", + "REGISTER": "Rekisteröidy" + }, + "DIALOG": { + "CANCEL": "Peruuta", + "CHOOSE": "Valitse" + } + }, + "ADF-DATATABLE": { + "EMPTY": { + "HEADER": "Tämä luettelo on tyhjä", + "DRAG-AND-DROP": { + "TITLE": "Lataa tiedostoja", + "SUBTITLE": "vetämällä ja pudottamalla" + } + }, + "CONTENT-ACTIONS": { + "TOOLTIP": "Sisältötoiminnot" + }, + "ACCESSIBILITY": { + "SELECT_ALL": "Valitse kaikki", + "SELECT_FILE": "Valitse tiedosto" + } + }, + "USER_PROFILE": { + "LABELS": { + "ECM": { + "JOB_TITLE": "Tehtävänimi" + }, + "BPM": { + "TENANT": "Tilaaja" + } + }, + "TAB": { + "CS": "Content Services", + "PS": "Process Services" + } + }, + "ADF_VIEWER": { + "ACTIONS": { + "BACK": "Takaisin", + "OPEN_WITH": "Avaa seuraavalla:", + "DOWNLOAD": "Lataa", + "PRINT": "Tulosta", + "SHARE": "Jaa", + "MORE_ACTIONS": "Lisää toimintoja", + "INFO": "Tiedot", + "FULLSCREEN": "Ota koko näytön tila käyttöön", + "CLOSE": "Sulje", + "NEXT_FILE": "Seuraava tiedosto", + "PREV_FILE": "Edellinen tiedosto" + }, + "ARIA": { + "PREVIOUS_PAGE": "Edellinen sivu", + "NEXT_PAGE": "Seuraava sivu", + "ZOOM_IN": "Lähennä", + "ZOOM_OUT": "Loitonna", + "FIT_PAGE": "Sovita sivu", + "ROTATE_LEFT": "Käännä vasemmalle", + "ROTATE_RIGHT": "Käännä oikealle", + "RESET": "Nollaa" + }, + "PAGE_LABEL": { + "SHOWING": "Näytetään", + "OF": "/" + }, + "LOADING": "Ladataan", + "UNKNOWN_FORMAT": "Esikatselun lataaminen ei onnistu", + "SIDEBAR": { + "THUMBNAILS": { + "PAGE": "Sivu {{ pageNum }}" + }, + "METADATA": { + "MORE_INFORMATION": "Lisää tietoja", + "LESS_INFORMATION": "Vähemmän tietoja" + } + }, + "PDF_DIALOG": { + "SUBMIT": "Lähetä", + "CLOSE": "Sulje", + "PLACEHOLDER": "Salasana", + "ERROR": "Salasana on väärä" + } + }, + "ERROR_CONTENT": { + "UNKNOWN": { + "TITLE": "Ilmeni ongelma.", + "DESCRIPTION": "Jokin meni ilmeisesti vikaan.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + }, + "403": { + "TITLE": "Sinulla ei ole oikeutta tämän palvelimen käyttöön.", + "DESCRIPTION": "Sinulla ei ole oikeuksia tämän resurssin käyttöön palvelimessa.", + "SECONDARY_BUTTON": { + "TEXT": "Ilmoita ongelmasta" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + }, + "404": { + "TITLE": "Tapahtui virhe.", + "DESCRIPTION": "Etsimääsi sivua ei löydy.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + }, + "500": { + "TITLE": "Tapahtui virhe.", + "DESCRIPTION": "Ilmeni sisäinen palvelinvirhe, yritä uudelleen tai ota yhteyttä IT-tukeen [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + }, + "502": { + "TITLE": "Tapahtui virhe.", + "DESCRIPTION": "Virheellinen yhdyskäytävä, yritä uudelleen tai ota yhteyttä IT-tukeen [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + }, + "504": { + "TITLE": "Tapahtui virhe.", + "DESCRIPTION": "Palvelin aikakatkaistiin, yritä uudelleen tai ota yhteyttä IT-tukeen [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Takaisin aloitussivulle" + } + } + }, + "ABOUT": { + "SERVER_SETTINGS": { + "TITLE": "Palvelinasetukset", + "DESCRIPTION": "Alla olevat arvot on otettu sovellusmäärityspalvelusta", + "CONTENT_SERVICE_HOST": "Alfresco Content Servicesin URL-osoite: {{ value }}", + "PROCESS_SERVICE_HOST": "Alfresco Process Servicesin URL-osoite: {{ value }}" + }, + "VERSIONS": { + "TITLE": "Tuoteversiot", + "CONTENT_SERVICE": "ECM", + "PROCESS_SERVICE": "BPM", + "LABELS": { + "EDITION": "Versio", + "VERSION": "Versio", + "LICENSE": "Käyttöoikeus", + "STATUS": "Tila", + "MODULES": "Moduulit" + } + }, + "SOURCE_CODE": { + "TITLE": "Lähdekoodi", + "DESCRIPTION": "Suoritat projektin seuraavan vahvistuksen perusteella:" + }, + "PACKAGES": { + "TITLE": "Paketit", + "DESCRIPTION": "Nykyinen projekti käyttää seuraavia ADF-kirjastoja:" + }, + "TABLE_HEADERS": { + "MODULES": { + "ID": "Tunnus", + "TITLE": "Otsikko", + "DESCRIPTION": "Kuvaus", + "INSTALL_DATE": "Asennuspäivämäärä", + "INSTALL_STATE": "Asennustila", + "VERSION_MIN": "Versio (ala)", + "VERSION_MAX": "Versio (pää)" + }, + "STATUS": { + "READ_ONLY": "Vain luku", + "AUDIT_ENABLED": "Tarkastus on käytössä", + "QUICK_SHARE_ENABLED": "Pikajako on käytössä", + "THUMBNAIL_ENABLED": "Pikkukuvan luominen" + }, + "LICENSE": { + "ISSUES_AT": "Myönnetty", + "EXPIRES_AT": "Vanhentuu", + "REMAINING_DAYS": "Päiviä jäljellä", + "HOLDER": "Haltija", + "MODE": "Tila", + "CLUSTER_ENABLED": "Klusteri on käytössä", + "CRYPTODOC_ENABLED": "Asiakirjasalaus on käytössä" + } + } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Kopioi napsauttamalla", + "SUCCESS_COPY": "Teksti kopioitiin leikepöydälle" + } +} \ No newline at end of file diff --git a/lib/core/i18n/fr.json b/lib/core/i18n/fr.json index 199c9ff213..0ac959081c 100644 --- a/lib/core/i18n/fr.json +++ b/lib/core/i18n/fr.json @@ -1,6 +1,9 @@ { "SAVE": "Enregistrer", "COMPLETE": "Terminer", + "CANCEL": "Annuler", + "CLAIM": "S'attribuer", + "UNCLAIM": "Libérer", "START PROCESS": "Démarrer le processus", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Saisir {{ minLength }} caractères minimum", "NO_LONGER_THAN": "Saisir {{ maxLength }} caractères maximum" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Tâche sans nom" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Retour à l'accueil" } + }, + "500": { + "TITLE": "Une erreur est survenue.", + "DESCRIPTION": "Erreur de serveur interne. Réessayez ou contactez le service informatique [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Retour à l'accueil" + } + }, + "502": { + "TITLE": "Une erreur est survenue.", + "DESCRIPTION": "Passerelle incorrecte. Réessayez ou contactez le service informatique [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Retour à l'accueil" + } + }, + "504": { + "TITLE": "Une erreur est survenue.", + "DESCRIPTION": "Le délai d'attente du serveur a expiré. Réessayez ou contactez le service informatique [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Retour à l'accueil" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Cryptodoc est-il activé" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Cliquer pour copier", + "SUCCESS_COPY": "Texte copié dans le presse-papiers" } } \ No newline at end of file diff --git a/lib/core/i18n/it.json b/lib/core/i18n/it.json index ed40888d97..0533c99e98 100644 --- a/lib/core/i18n/it.json +++ b/lib/core/i18n/it.json @@ -1,6 +1,9 @@ { "SAVE": "Salva", "COMPLETE": "Completa", + "CANCEL": "Annulla", + "CLAIM": "Richiedi", + "UNCLAIM": "Restituisci", "START PROCESS": "Avvia processo", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Immettere almeno {{ minLength }} caratteri", "NO_LONGER_THAN": "Immettere non più di {{ maxLength }} caratteri" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Compito senza nome" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Torna alla home" } + }, + "500": { + "TITLE": "Si è verificato un errore.", + "DESCRIPTION": "Errore interno del server. Riprovare o contattare il supporto IT [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Torna alla home" + } + }, + "502": { + "TITLE": "Si è verificato un errore.", + "DESCRIPTION": "Gateway non valido. Riprovare o contattare il supporto IT [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Torna alla home" + } + }, + "504": { + "TITLE": "Si è verificato un errore.", + "DESCRIPTION": "Time out del server. Riprovare o contattare il supporto [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Torna alla home" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Crittografia documenti abilitata" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Fare clic per copiare", + "SUCCESS_COPY": "Testo copiato negli appunti" } } \ No newline at end of file diff --git a/lib/core/i18n/ja.json b/lib/core/i18n/ja.json index f947295577..f588759533 100644 --- a/lib/core/i18n/ja.json +++ b/lib/core/i18n/ja.json @@ -1,6 +1,9 @@ { "SAVE": "保存", "COMPLETE": "完了", + "CANCEL": "キャンセル", + "CLAIM": "担当する", + "UNCLAIM": "担当解除", "START PROCESS": "プロセスの開始", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "{{ minLength }} 文字以上で入力してください", "NO_LONGER_THAN": "{{ maxLength }} 文字以内で入力してください" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "無名のタスク" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "ホームへ戻る" } + }, + "500": { + "TITLE": "エラーが発生しました。", + "DESCRIPTION": "内部サーバーエラーが発生しました。もう一度操作をやり直すか、IT 担当者に連絡してください [500]。", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "ホームへ戻る" + } + }, + "502": { + "TITLE": "エラーが発生しました。", + "DESCRIPTION": "不正なゲートウェイです。もう一度操作をやり直すか、IT 担当者に連絡してください [502]。", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "ホームへ戻る" + } + }, + "504": { + "TITLE": "エラーが発生しました。", + "DESCRIPTION": "サーバーがタイムアウトになりました。もう一度操作をやり直すか、IT 担当者に連絡してください [504]。", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "ホームへ戻る" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Cryptodoc - 有効" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "コピーするにはクリックします", + "SUCCESS_COPY": "テキストがクリップボードにコピーされました" } } \ No newline at end of file diff --git a/lib/core/i18n/nb.json b/lib/core/i18n/nb.json index 9c4bcfdaf1..ce4fc0c67e 100644 --- a/lib/core/i18n/nb.json +++ b/lib/core/i18n/nb.json @@ -1,6 +1,9 @@ { "SAVE": "Lagre", "COMPLETE": "Fullfør", + "CANCEL": "Avbryt", + "CLAIM": "Krev", + "UNCLAIM": "Frigi", "START PROCESS": "Start prosess", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Angi minst {{ minLength }} tegn", "NO_LONGER_THAN": "Angi opptil {{ maxLength }} tegn" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Navnløs oppgave" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Tilbake til startsiden" } + }, + "500": { + "TITLE": "Det oppstod en feil.", + "DESCRIPTION": "Intern serverfeil. Prøv igjen eller kontakt IT-støtten [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbake til startsiden" + } + }, + "502": { + "TITLE": "Det oppstod en feil.", + "DESCRIPTION": "Ugyldig gateway. Prøv igjen eller kontakt IT-støtten [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbake til startsiden" + } + }, + "504": { + "TITLE": "Det oppstod en feil.", + "DESCRIPTION": "Serveren ble tidsavbrutt. Prøv igjen eller kontakt IT-støtten [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tilbake til startsiden" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Er Cryptodoc-aktivert" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Klikk for å kopiere", + "SUCCESS_COPY": "Tekst kopiert til utklippstavle" } } \ No newline at end of file diff --git a/lib/core/i18n/nl.json b/lib/core/i18n/nl.json index cd5f5b4787..31b7c52d3b 100644 --- a/lib/core/i18n/nl.json +++ b/lib/core/i18n/nl.json @@ -1,6 +1,9 @@ { "SAVE": "Opslaan", "COMPLETE": "Voltooid", + "CANCEL": "Annuleren", + "CLAIM": "Claimen", + "UNCLAIM": "Vrijgeven", "START PROCESS": "Proces starten", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Voer ten minste {{ minLength }} tekens in", "NO_LONGER_THAN": "Voer niet meer dan {{ maxLength }} tekens in" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Naamloze taak" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Terug naar Home" } + }, + "500": { + "TITLE": "Er is een fout opgetreden.", + "DESCRIPTION": "Interne serverfout, probeer het opnieuw of neem contact op met de IT-ondersteuning [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Terug naar Home" + } + }, + "502": { + "TITLE": "Er is een fout opgetreden.", + "DESCRIPTION": "Ongeldige gateway, probeer het opnieuw of neem contact op met de IT-ondersteuning [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Terug naar Home" + } + }, + "504": { + "TITLE": "Er is een fout opgetreden.", + "DESCRIPTION": "Er is een time-out opgetreden in de server, probeer het opnieuw of neem contact op met de IT-ondersteuning [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Terug naar Home" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Is ingeschakeld voor Cryptodoc" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Klik om te kopiëren", + "SUCCESS_COPY": "Tekst gekopieerd naar Klembord" } } \ No newline at end of file diff --git a/lib/core/i18n/pl.json b/lib/core/i18n/pl.json new file mode 100644 index 0000000000..a2b60899ac --- /dev/null +++ b/lib/core/i18n/pl.json @@ -0,0 +1,433 @@ +{ + "SAVE": "Zapisz", + "COMPLETE": "Zakończ", + "CANCEL": "Anuluj", + "CLAIM": "Przejmij", + "UNCLAIM": "Zwolnij", + "START PROCESS": "Rozpocznij proces", + "FORM": { + "START_FORM": { + "TITLE": "Uruchom formularz" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "Podgląd niedostępny" + }, + "FIELD": { + "LOCALSTORAGE": "Magazyn lokalny", + "SOURCE": "Wybierz źródło z ", + "SHOW_FILE": "Pokaż", + "DOWNLOAD_FILE": "Pobierz", + "REMOVE_FILE": "Usuń", + "UPLOAD": "Prześlij", + "REQUIRED": "*Wymagane", + "VALIDATOR": { + "INVALID_NUMBER": "Użyj innego formatu liczby.", + "INVALID_DATE": "Użyj innego formatu daty.", + "INVALID_VALUE": "Wprowadź inną wartość.", + "NOT_GREATER_THAN": "Wartość nie może być większa niż {{ maxValue }}.", + "NOT_LESS_THAN": "Wartość nie może być mniejsza niż {{ minValue }}.", + "AT_LEAST_LONG": "Wprowadź co najmniej następującą liczbę znaków: {{ minLength }}.", + "NO_LONGER_THAN": "Możesz wprowadzić maksymalnie następującą liczbę znaków: {{ maxLength }}." + } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Zadanie bez nazwy" + } + }, + "CORE": { + "HEADER": { + "LOGO_ARIA": "Logo firmy" + }, + "FILE_SIZE": { + "BYTES": "B", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB", + "PB": "PB", + "EB": "EB", + "ZB": "ZB", + "YB": "YB" + }, + "PAGINATION": { + "ARIA": { + "ITEMS_PER_PAGE": "Selektor rozmiaru strony", + "CURRENT_PAGE": "Selektor bieżącej strony", + "PREVIOUS_PAGE": "Przycisk poprzedniej strony", + "NEXT_PAGE": "Przycisk następnej strony" + }, + "ITEMS_RANGE": "Wyświetlanie {{ range }} z {{ total }}", + "ITEMS_PER_PAGE": "Liczba elementów na stronie", + "CURRENT_PAGE": "Strona {{ number }}", + "TOTAL_PAGES": "z {{ total }}" + }, + "DIALOG": { + "DOWNLOAD_ZIP": { + "ACTIONS": { + "CANCEL": "Anuluj" + }, + "TITLE": "Trwa dodawanie plików do archiwum zip. Może to potrwać kilka minut." + } + }, + "FILE_DIALOG": { + "FILE_LOCK": "Zablokuj plik", + "ALLOW_OTHERS_CHECKBOX": "Zezwól właścicielowi na modyfikowanie tego pliku", + "FILE_LOCK_CHECKBOX": "Zablokuj plik", + "TIME_LOCK_CHECKBOX": "Blokada czasu", + "SAVE_BUTTON": { + "LABEL": "Zapisz" + }, + "CANCEL_BUTTON": { + "LABEL": "Anuluj" + } + }, + "FOLDER_DIALOG": { + "CREATE_FOLDER_TITLE": "Utwórz nowy folder", + "EDIT_FOLDER_TITLE": "Edytuj folder", + "FOLDER_NAME": { + "LABEL": "Nazwa", + "ERRORS": { + "REQUIRED": "Nazwa folderu jest wymagana.", + "SPECIAL_CHARACTERS": "Nazwa folderu nie może zawierać następujących znaków: * \" < > \\ / ? : |.", + "ENDING_DOT": "Nazwa folderu nie może być zakończona kropką (.).", + "ONLY_SPACES": "Nazwa folderu nie może składać się wyłącznie ze spacji." + } + }, + "FOLDER_DESCRIPTION": { + "LABEL": "Opis" + }, + "CREATE_BUTTON": { + "LABEL": "Utwórz" + }, + "UPDATE_BUTTON": { + "LABEL": "Aktualizuj" + }, + "CANCEL_BUTTON": { + "LABEL": "Anuluj" + } + }, + "MESSAGES": { + "ERRORS": { + "GENERIC": "Wykonanie czynności nie powiodło się. Spróbuj ponownie lub skontaktuj się z zespołem IT.", + "EXISTENT_FOLDER": "Istnieje już folder o tej nazwie. Spróbuj użyć innej nazwy." + } + }, + "RESTORE_NODE": { + "VIEW": "Widok", + "PARTIAL_PLURAL": "Liczba elementów, które nie zostały przywrócone z powodu problemów z lokalizacją przywracania: {{ number }}.", + "NODE_EXISTS": "Nie można przywrócić elementu {{ name }}, ponieważ już istnieje.", + "LOCATION_MISSING": "Nie można przywrócić elementu {{ name }}, ponieważ jego pierwotna lokalizacja już nie istnieje.", + "GENERIC": "Podczas przywracania elementu {{ name }} wystąpił problem.", + "PLURAL": "Przywracanie zostało zakończone pomyślnie.", + "SINGULAR": "Przywrócono element {{ name }}." + }, + "DELETE_NODE": { + "SINGULAR": "Usunięto: {{ name }}", + "PLURAL": "Usunięto elementów: {{ number }}", + "PARTIAL_SINGULAR": "Usunięto element {{ success }}, nie można usunąć: {{ failed }}", + "PARTIAL_PLURAL": "Usunięto elementy: {{ success }}, nie można usunąć: {{ failed }}", + "ERROR_SINGULAR": "Nie można usunąć elementu {{ name }}.", + "ERROR_PLURAL": "Nie można usunąć następującej liczby elementów: {{ number }}." + }, + "HOST_SETTINGS": { + "TYPE-AUTH": "Typ uwierzytelnienia", + "BASIC": "Uwierzytelnienie podstawowe", + "SSO": "Logowanie jednokrotne", + "IMPLICIT-FLOW": "Niejawny przepływ", + "PROVIDER": "Dostawca", + "REQUIRED": "To pole jest wymagane.", + "CS_URL_ERROR": "Adres usług Content Services jest niezgodny z formatem adresu URL.", + "PS_URL_ERROR": "Adres usług Process Services jest niezgodny z formatem adresu URL.", + "TITLE": "Ustawienia", + "CS-HOST": "Adres URL usług Content Services", + "BP-HOST": "Adres URL usług Process Services", + "BACK": "Wstecz", + "APPLY": "Zastosuj", + "NOT_VALID": "Nie rozpoznano adresu http(s)://host|ip:port(/path). Spróbuj użyć innego adresu URL.", + "REDIRECT": "Identyfikator URI przekierowania", + "REDIRECT_LOGOUT": "Identyfikator URI przekierowania — wylogowanie", + "SILENT": "Ciche logowanie", + "SCOPE": "Zakres", + "CLIENT": "Identyfikator klienta" + }, + "CARDVIEW": { + "KEYVALUEPAIRS": { + "ADD": "Dodaj nowe", + "NAME": "Nazwa", + "VALUE": "Wartość" + }, + "VALIDATORS": { + "FLOAT_VALIDATION_ERROR": "Użyj formatu liczby", + "INT_VALIDATION_ERROR": "Użyj formatu liczby całkowitej" + } + }, + "METADATA": { + "BASIC": { + "HEADER": "Właściwości", + "NAME": "Nazwa", + "TITLE": "Tytuł", + "DESCRIPTION": "Opis", + "AUTHOR": "Autor", + "MIMETYPE": "Typ MIME", + "SIZE": "Rozmiar", + "CREATOR": "Twórca", + "CREATED_DATE": "Data utworzenia", + "MODIFIER": "Modyfikator", + "MODIFIED_DATE": "Data modyfikacji" + }, + "ACTIONS": { + "EDIT": "Edytuj", + "SAVE": "Zapisz", + "CANCEL": "Anuluj", + "TOGGLE": "Przełącz wartość" + } + } + }, + "COMMENTS": { + "NONE": "Brak komentarzy", + "ADD": "Dodaj", + "HEADER": "Liczba komentarzy: ({{ count }})", + "CREATED_BY_HEADER": "Utworzone przez", + "MESSAGE_HEADER": "Komunikat", + "DIALOG": { + "TITLE": "Nowy komentarz", + "LABELS": { + "MESSAGE": "Komunikat" + }, + "BUTTON": { + "ADD": "Dodaj komentarz", + "CANCEL": "Anuluj" + } + } + }, + "LOGIN": { + "LOGO": "Alfresco", + "LABEL": { + "LOGIN": "Zaloguj się", + "USERNAME": "Nazwa użytkownika", + "PASSWORD": "Hasło", + "REMEMBER": "Zapamiętaj mnie" + }, + "MESSAGES": { + "USERNAME-REQUIRED": "Wymagane", + "USERNAME-MIN": "Nazwa użytkownika musi się składać z co najmniej następującej liczby znaków: {{ minLength }}.", + "PASSWORD-REQUIRED": "Wprowadź hasło, aby się zalogować.", + "LOGIN-ERROR-CREDENTIALS": "Wprowadzono nieznaną nazwę użytkownika lub hasło.", + "LOGIN-ERROR-PROVIDERS": "Nie można zidentyfikować dostawców.", + "LOGIN-ERROR-CORS": "Wystąpił wyjątek CORS. Sprawdź konfigurację serwera.", + "LOGIN-ERROR-CSRF": "Wystąpił wyjątek CSRF. Ustaw w składniku logowania wartość [disableCsrf]=\"true\".", + "LOGIN-ECM-LICENSE": "Repozytorium usług Alfresco Content Services jest w trybie tylko do odczytu.", + "SSO-WRONG-CONFIGURATION": "Serwer uwierzytelniania SSO jest nieosiągalny" + }, + "BUTTON": { + "LOGIN": "Zaloguj się", + "CHECKING": "Sprawdzanie", + "WELCOME": "Witaj", + "SSO": "Zaloguj się, używając logowania jednokrotnego" + }, + "ACTION": { + "HELP": "Potrzebujesz pomocy?", + "REGISTER": "Zarejestruj się" + }, + "DIALOG": { + "CANCEL": "Anuluj", + "CHOOSE": "Wybierz" + } + }, + "ADF-DATATABLE": { + "EMPTY": { + "HEADER": "Ta lista jest pusta.", + "DRAG-AND-DROP": { + "TITLE": "Przeciągnij i upuść", + "SUBTITLE": "aby przesłać pliki" + } + }, + "CONTENT-ACTIONS": { + "TOOLTIP": "Czynności dotyczące zawartości" + }, + "ACCESSIBILITY": { + "SELECT_ALL": "Wybierz wszystko", + "SELECT_FILE": "Wybierz plik" + } + }, + "USER_PROFILE": { + "LABELS": { + "ECM": { + "JOB_TITLE": "Tytuł zadania" + }, + "BPM": { + "TENANT": "Dzierżawca" + } + }, + "TAB": { + "CS": "Content Services", + "PS": "Process Services" + } + }, + "ADF_VIEWER": { + "ACTIONS": { + "BACK": "Wstecz", + "OPEN_WITH": "Otwórz za pomocą", + "DOWNLOAD": "Pobierz", + "PRINT": "Drukuj", + "SHARE": "Udostępnij", + "MORE_ACTIONS": "Więcej czynności", + "INFO": "Informacje", + "FULLSCREEN": "Uaktywnij tryb pełnoekranowy", + "CLOSE": "Zamknij", + "NEXT_FILE": "Następny plik", + "PREV_FILE": "Poprzedni plik" + }, + "ARIA": { + "PREVIOUS_PAGE": "Poprzednia strona", + "NEXT_PAGE": "Następna strona", + "ZOOM_IN": "Powiększ", + "ZOOM_OUT": "Pomniejsz", + "FIT_PAGE": "Zmieść na stronie", + "ROTATE_LEFT": "Obróć w lewo", + "ROTATE_RIGHT": "Obróć w prawo", + "RESET": "Resetuj" + }, + "PAGE_LABEL": { + "SHOWING": "Wyświetlanie", + "OF": "z" + }, + "LOADING": "Wczytywanie", + "UNKNOWN_FORMAT": "Nie można wczytać podglądu.", + "SIDEBAR": { + "THUMBNAILS": { + "PAGE": "Strona {{ pageNum }}" + }, + "METADATA": { + "MORE_INFORMATION": "Więcej informacji", + "LESS_INFORMATION": "Mniej informacji" + } + }, + "PDF_DIALOG": { + "SUBMIT": "Prześlij", + "CLOSE": "Zamknij", + "PLACEHOLDER": "Hasło", + "ERROR": "Hasło jest nieprawidłowe." + } + }, + "ERROR_CONTENT": { + "UNKNOWN": { + "TITLE": "Wystąpił problem.", + "DESCRIPTION": "Wygląda na to, że coś poszło nie tak.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + }, + "403": { + "TITLE": "Nie masz uprawnień dostępu do tego serwera.", + "DESCRIPTION": "Nie masz uprawnień dostępu do tego zasobu na serwerze.", + "SECONDARY_BUTTON": { + "TEXT": "Zgłoś problem" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + }, + "404": { + "TITLE": "Wystąpił błąd.", + "DESCRIPTION": "Nie znaleziono szukanej strony.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + }, + "500": { + "TITLE": "Wystąpił błąd.", + "DESCRIPTION": "Błąd wewnętrzny serwera, spróbuj ponownie lub skontaktuj się z działem IT [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + }, + "502": { + "TITLE": "Wystąpił błąd.", + "DESCRIPTION": "Nieodpowiednia brama, spróbuj ponownie lub skontaktuj się z działem IT [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + }, + "504": { + "TITLE": "Wystąpił błąd.", + "DESCRIPTION": "Upłynął limit czasu serwera, spróbuj ponownie lub skontaktuj się z działem IT [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Powrót do strony głównej" + } + } + }, + "ABOUT": { + "SERVER_SETTINGS": { + "TITLE": "Ustawienia serwera", + "DESCRIPTION": "Wartości widoczne poniżej pochodzą z usługi AppConfigService", + "CONTENT_SERVICE_HOST": "Adres URL rozwiązania Alfresco Content Services: {{ value }}", + "PROCESS_SERVICE_HOST": "Adres URL rozwiązania Alfresco Process Services: {{ value }}" + }, + "VERSIONS": { + "TITLE": "Wersje produktu", + "CONTENT_SERVICE": "ECM", + "PROCESS_SERVICE": "BPM", + "LABELS": { + "EDITION": "Wydanie", + "VERSION": "Wersja", + "LICENSE": "Licencja", + "STATUS": "Status", + "MODULES": "Moduły" + } + }, + "SOURCE_CODE": { + "TITLE": "Kod źródłowy", + "DESCRIPTION": "Uruchamiasz projekt na podstawie następującego zatwierdzenia:" + }, + "PACKAGES": { + "TITLE": "Pakiety", + "DESCRIPTION": "Bieżący projekt korzysta z następujących bibliotek ADF:" + }, + "TABLE_HEADERS": { + "MODULES": { + "ID": "Identyfikator", + "TITLE": "Tytuł", + "DESCRIPTION": "Opis", + "INSTALL_DATE": "Data instalacji", + "INSTALL_STATE": "Stan instalacji", + "VERSION_MIN": "Wersja pomocnicza", + "VERSION_MAX": "Wersja główna" + }, + "STATUS": { + "READ_ONLY": "Tylko do odczytu", + "AUDIT_ENABLED": "Czy inspekcja jest włączona", + "QUICK_SHARE_ENABLED": "Czy funkcja Quick Share jest włączona", + "THUMBNAIL_ENABLED": "Generowanie miniatur" + }, + "LICENSE": { + "ISSUES_AT": "Wystawiono dnia", + "EXPIRES_AT": "Wygasa dnia", + "REMAINING_DAYS": "Pozostało dni", + "HOLDER": "Posiadacz", + "MODE": "Tryb", + "CLUSTER_ENABLED": "Czy klaster jest włączony", + "CRYPTODOC_ENABLED": "Czy funkcja Cryptodoc jest włączona" + } + } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Kliknij, aby skopiować", + "SUCCESS_COPY": "Tekst skopiowano do schowka" + } +} \ No newline at end of file diff --git a/lib/core/i18n/pt-BR.json b/lib/core/i18n/pt-BR.json index f1df1a3da7..da1d46d30b 100644 --- a/lib/core/i18n/pt-BR.json +++ b/lib/core/i18n/pt-BR.json @@ -1,6 +1,9 @@ { "SAVE": "Salvar", "COMPLETE": "Completar", + "CANCEL": "Cancelar", + "CLAIM": "Reivindicar", + "UNCLAIM": "Liberar", "START PROCESS": "Iniciar processo", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Insira no mínimo {{ minLength }} caracteres", "NO_LONGER_THAN": "Insira no máximo {{ maxLength }} caracteres" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Tarefa sem nome" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Voltar para a página inicial" } + }, + "500": { + "TITLE": "Ocorreu um erro.", + "DESCRIPTION": "Erro interno do servidor, tente novamente ou entre em contato com o suporte de TI [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Voltar para a página inicial" + } + }, + "502": { + "TITLE": "Ocorreu um erro.", + "DESCRIPTION": "Gateway incorreto, tente novamente ou entre em contato com o suporte de TI [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Voltar para a página inicial" + } + }, + "504": { + "TITLE": "Ocorreu um erro.", + "DESCRIPTION": "O servidor atingiu o tempo limite, tente novamente ou entre em contato com o suporte de TI [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Voltar para a página inicial" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Com cryptodoc ativado" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Clique para copiar", + "SUCCESS_COPY": "Texto copiado para a área de transferência" } } \ No newline at end of file diff --git a/lib/core/i18n/ru.json b/lib/core/i18n/ru.json index 02d9ef2671..6e8070c836 100644 --- a/lib/core/i18n/ru.json +++ b/lib/core/i18n/ru.json @@ -1,7 +1,10 @@ { "SAVE": "Сохранить", "COMPLETE": "Завершить", - "START PROCESS": "Запустить процесс", + "CANCEL": "Отмена", + "CLAIM": "Принять", + "UNCLAIM": "Освободить", + "START PROCESS": "Начать процесс", "FORM": { "START_FORM": { "TITLE": "Запустить форму" @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "Введите не менее {{ minLength }} символов", "NO_LONGER_THAN": "Введите не более {{ maxLength }} символов" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Задача без имени" } }, "CORE": { @@ -179,7 +185,7 @@ }, "COMMENTS": { "NONE": "Нет комментариев", - "ADD": "Добавить комментарий", + "ADD": "Добавить", "HEADER": "Комментарии ({{ count }})", "CREATED_BY_HEADER": "Создано пользователем", "MESSAGE_HEADER": "Сообщение", @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "Назад на главную" } + }, + "500": { + "TITLE": "Произошла ошибка.", + "DESCRIPTION": "Внутренняя ошибка сервера. Повторите попытку или обратитесь в службу ИТ-поддержки [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Назад на главную" + } + }, + "502": { + "TITLE": "Произошла ошибка.", + "DESCRIPTION": "Ошибка шлюза. Повторите попытку или обратитесь в службу ИТ-поддержки [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Назад на главную" + } + }, + "504": { + "TITLE": "Произошла ошибка.", + "DESCRIPTION": "Истекло время ожидания ответа от сервера. Повторите попытку или обратитесь в службу ИТ-поддержки [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Назад на главную" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "Cryptodoc включен" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Нажмите, чтобы скопировать", + "SUCCESS_COPY": "Текст скопирован в буфер обмена" } } \ No newline at end of file diff --git a/lib/core/i18n/sv.json b/lib/core/i18n/sv.json new file mode 100644 index 0000000000..e4f3a36950 --- /dev/null +++ b/lib/core/i18n/sv.json @@ -0,0 +1,433 @@ +{ + "SAVE": "Spara", + "COMPLETE": "Slutför", + "CANCEL": "Avbryt", + "CLAIM": "Anta", + "UNCLAIM": "Avsäga", + "START PROCESS": "Starta process", + "FORM": { + "START_FORM": { + "TITLE": "Startformulär" + }, + "PREVIEW": { + "IMAGE_NOT_AVAILABLE": "Förhandgranskning inte tillgänglig" + }, + "FIELD": { + "LOCALSTORAGE": "Lokal lagring", + "SOURCE": "Välj källa från ", + "SHOW_FILE": "Visa", + "DOWNLOAD_FILE": "Ladda ner", + "REMOVE_FILE": "Ta bort", + "UPLOAD": "Ladda upp", + "REQUIRED": "*Obligatorisk", + "VALIDATOR": { + "INVALID_NUMBER": "Använd ett annat nummerformat", + "INVALID_DATE": "Använd ett annat datumformat", + "INVALID_VALUE": "Ange ett annat värde", + "NOT_GREATER_THAN": "Kan inte vara större än {{ maxValue }}", + "NOT_LESS_THAN": "Kan inte vara mindre än {{ minValue }}", + "AT_LEAST_LONG": "Ange minst {{ minLength }} tecken", + "NO_LONGER_THAN": "Ange inte fler än {{ maxLength }} tecken" + } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "Namnlös uppgift" + } + }, + "CORE": { + "HEADER": { + "LOGO_ARIA": "Företagslogotyp" + }, + "FILE_SIZE": { + "BYTES": "Byte", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB", + "PB": "PB", + "EB": "EB", + "ZB": "ZB", + "YB": "YB" + }, + "PAGINATION": { + "ARIA": { + "ITEMS_PER_PAGE": "Sidstorleksväljare", + "CURRENT_PAGE": "Aktuell sidväljare", + "PREVIOUS_PAGE": "Knappen föregående sida", + "NEXT_PAGE": "Knappen nästa sida" + }, + "ITEMS_RANGE": "Visar {{ range }} av {{ total }}", + "ITEMS_PER_PAGE": "Objekt per sida", + "CURRENT_PAGE": "Sida {{ number }}", + "TOTAL_PAGES": "av {{ total }}" + }, + "DIALOG": { + "DOWNLOAD_ZIP": { + "ACTIONS": { + "CANCEL": "Avbryt" + }, + "TITLE": "Lägg till filer till zip, det här kan ta några minuter" + } + }, + "FILE_DIALOG": { + "FILE_LOCK": "Lås fil", + "ALLOW_OTHERS_CHECKBOX": "Tillåt ägaren att modifiera den här filen", + "FILE_LOCK_CHECKBOX": "Lås fil", + "TIME_LOCK_CHECKBOX": "Tidslås", + "SAVE_BUTTON": { + "LABEL": "Spara" + }, + "CANCEL_BUTTON": { + "LABEL": "Avbryt" + } + }, + "FOLDER_DIALOG": { + "CREATE_FOLDER_TITLE": "Skapa en ny mapp", + "EDIT_FOLDER_TITLE": "Redigera mapp", + "FOLDER_NAME": { + "LABEL": "Namn", + "ERRORS": { + "REQUIRED": "Mappnamn krävs", + "SPECIAL_CHARACTERS": "Mappnamnet får inte innehålla de här tecknen * \" < > \\ / ? : |", + "ENDING_DOT": "Mappnamnet får inte sluta med en punkt .", + "ONLY_SPACES": "Mappnamnet får inte bara innehålla mellanslag" + } + }, + "FOLDER_DESCRIPTION": { + "LABEL": "Beskrivning" + }, + "CREATE_BUTTON": { + "LABEL": "Skapa" + }, + "UPDATE_BUTTON": { + "LABEL": "Uppdatera" + }, + "CANCEL_BUTTON": { + "LABEL": "Avbryt" + } + }, + "MESSAGES": { + "ERRORS": { + "GENERIC": "Åtgärden lyckades inte. Försök igen eller kontakta din IT-avdelning.", + "EXISTENT_FOLDER": "Det finns redan en mapp med det här namnet. Testa ett annat namn" + } + }, + "RESTORE_NODE": { + "VIEW": "Visa", + "PARTIAL_PLURAL": "{{ number }} objekt ej återställda på grund av problem med återställningsplatsen", + "NODE_EXISTS": "Kan inte återställa, {{ name }} objektet finns redan", + "LOCATION_MISSING": "Kan inte återställa {{ name }} objekt, den ursprungliga platsen finns inte längre", + "GENERIC": "Det var ett problem med att återställa objektet {{ name }}", + "PLURAL": "Återställning lyckades", + "SINGULAR": "{{ name }} objekt återställt" + }, + "DELETE_NODE": { + "SINGULAR": "{{ name }} raderad", + "PLURAL": "{{ number }} objekt raderade", + "PARTIAL_SINGULAR": "Raderade {{ success }} objekt, {{ failed }} kunde inte raderas", + "PARTIAL_PLURAL": "Raderade {{ success }} objekt, {{ failed }} kunde inte raderas", + "ERROR_SINGULAR": "{{ name }} kunde inte raderas", + "ERROR_PLURAL": "{{ number }} objekt kunde inte raderas" + }, + "HOST_SETTINGS": { + "TYPE-AUTH": "Autentiseringstyp", + "BASIC": "Grundläggande autenticering", + "SSO": "SSO", + "IMPLICIT-FLOW": "Implicit flöde", + "PROVIDER": "Leverantör", + "REQUIRED": "Det här fältet är obligatoriskt", + "CS_URL_ERROR": "Content Services-adressen matchar inte URL-formatet", + "PS_URL_ERROR": "Process Services-adressen matchar inte URL-formatet", + "TITLE": "Inställningar", + "CS-HOST": "Content Services-URL", + "BP-HOST": "Process Services-URL", + "BACK": "Tillbaka", + "APPLY": "Tillämpa", + "NOT_VALID": "http(s)://host|ip:port(/path) kändes inte igen, testa annan URL.", + "REDIRECT": "Omdirigera URI", + "REDIRECT_LOGOUT": "Omdirigera URI-utloggning", + "SILENT": "Tyst inloggning", + "SCOPE": "Definitionsområde", + "CLIENT": "Klient-ID" + }, + "CARDVIEW": { + "KEYVALUEPAIRS": { + "ADD": "Lägg till ny", + "NAME": "Namn", + "VALUE": "Värde" + }, + "VALIDATORS": { + "FLOAT_VALIDATION_ERROR": "Använd ett nummerformat", + "INT_VALIDATION_ERROR": "Använd ett heltalsformat" + } + }, + "METADATA": { + "BASIC": { + "HEADER": "Egenskaper", + "NAME": "Namn", + "TITLE": "Titel", + "DESCRIPTION": "Beskrivning", + "AUTHOR": "Författare", + "MIMETYPE": "Mime-typ", + "SIZE": "Storlek", + "CREATOR": "Upphovsperson", + "CREATED_DATE": "Skapad datum", + "MODIFIER": "Modifierare", + "MODIFIED_DATE": "Modifieringsdatum" + }, + "ACTIONS": { + "EDIT": "Redigera", + "SAVE": "Spara", + "CANCEL": "Avbryt", + "TOGGLE": "Växla värde" + } + } + }, + "COMMENTS": { + "NONE": "Inga kommentarer", + "ADD": "Lägg till", + "HEADER": "Kommentarer ({{ count }})", + "CREATED_BY_HEADER": "Skapad av", + "MESSAGE_HEADER": "Meddelande", + "DIALOG": { + "TITLE": "Ny kommentar", + "LABELS": { + "MESSAGE": "Meddelande" + }, + "BUTTON": { + "ADD": "Lägg till kommentar", + "CANCEL": "Avbryt" + } + } + }, + "LOGIN": { + "LOGO": "Alfresco", + "LABEL": { + "LOGIN": "Logga in", + "USERNAME": "Användarnamn", + "PASSWORD": "Lösenord", + "REMEMBER": "Kom ihåg mig" + }, + "MESSAGES": { + "USERNAME-REQUIRED": "Obligatorisk", + "USERNAME-MIN": "Ditt användarmna måste vara minst {{ minLength }} tecken.", + "PASSWORD-REQUIRED": "Ange ditt lösenord för att logga in", + "LOGIN-ERROR-CREDENTIALS": "Du har angett ett okänt användarnamn eller lösenord", + "LOGIN-ERROR-PROVIDERS": "Leverantörer kan inte avdefinieras", + "LOGIN-ERROR-CORS": "CORS-undantag, kontrollera din serverkonfiguration", + "LOGIN-ERROR-CSRF": "CSRF-undantag, ställ in [disableCsrf]=\"true\" i login.component", + "LOGIN-ECM-LICENSE": "Alfresco Content Services-datakatalog är i skrivskyddat läge", + "SSO-WRONG-CONFIGURATION": "SSO-autenticeringsserver kan inte nås" + }, + "BUTTON": { + "LOGIN": "Logga in", + "CHECKING": "Kontrollerar", + "WELCOME": "Välkommen", + "SSO": "Sign in SSO" + }, + "ACTION": { + "HELP": "Behöver du hjälp?", + "REGISTER": "Handling" + }, + "DIALOG": { + "CANCEL": "Avbryt", + "CHOOSE": "Välj" + } + }, + "ADF-DATATABLE": { + "EMPTY": { + "HEADER": "Den här listan är tom", + "DRAG-AND-DROP": { + "TITLE": "Dra och släpp", + "SUBTITLE": "för att ladda upp filer" + } + }, + "CONTENT-ACTIONS": { + "TOOLTIP": "Innehållsåtgärder" + }, + "ACCESSIBILITY": { + "SELECT_ALL": "Välj alla", + "SELECT_FILE": "Välj fil" + } + }, + "USER_PROFILE": { + "LABELS": { + "ECM": { + "JOB_TITLE": "Jobbtitel" + }, + "BPM": { + "TENANT": "Kund" + } + }, + "TAB": { + "CS": "Content Services", + "PS": "Process Services" + } + }, + "ADF_VIEWER": { + "ACTIONS": { + "BACK": "Tillbaka", + "OPEN_WITH": "Öppna med", + "DOWNLOAD": "Ladda ner", + "PRINT": "Skriv ut", + "SHARE": "Dela", + "MORE_ACTIONS": "Fler åtgärder", + "INFO": "Info", + "FULLSCREEN": "Aktivera helskärmsläge", + "CLOSE": "Stäng", + "NEXT_FILE": "Nästa fil", + "PREV_FILE": "Föregående fil" + }, + "ARIA": { + "PREVIOUS_PAGE": "Tidigare sida", + "NEXT_PAGE": "Nästa sida", + "ZOOM_IN": "Zooma in", + "ZOOM_OUT": "Zooma ut", + "FIT_PAGE": "Passa in sida", + "ROTATE_LEFT": "Rotera till vänster", + "ROTATE_RIGHT": "Rotera till höger", + "RESET": "Återställ" + }, + "PAGE_LABEL": { + "SHOWING": "Visar", + "OF": "av" + }, + "LOADING": "Laddar upp", + "UNKNOWN_FORMAT": "Kunde inte läsa in förhandsgranskning", + "SIDEBAR": { + "THUMBNAILS": { + "PAGE": "Sida {{ pageNum }}" + }, + "METADATA": { + "MORE_INFORMATION": "Mer information", + "LESS_INFORMATION": "Mindre information" + } + }, + "PDF_DIALOG": { + "SUBMIT": "Skicka in", + "CLOSE": "Stäng", + "PLACEHOLDER": "Lösenord", + "ERROR": "Lösenordet är fel" + } + }, + "ERROR_CONTENT": { + "UNKNOWN": { + "TITLE": "Vi har stött på ett problem.", + "DESCRIPTION": "Det verkar som om något gått fel.", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + }, + "403": { + "TITLE": "Du har inte behörighet att komma åt den här servern.", + "DESCRIPTION": "Du är inte tillåten åtkomst till den här resursen på servern.", + "SECONDARY_BUTTON": { + "TEXT": "Rapportera problem" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + }, + "404": { + "TITLE": "Ett fel inträffade.", + "DESCRIPTION": "Vi kunde inte hitta sidan du letade efter", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + }, + "500": { + "TITLE": "Ett fel inträffade.", + "DESCRIPTION": "Internt serverfel, försök igen eller kontakta IT-support [500].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + }, + "502": { + "TITLE": "Ett fel inträffade.", + "DESCRIPTION": "Felaktig gateway, försök igen eller kontakta IT-support [502].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + }, + "504": { + "TITLE": "Ett fel inträffade.", + "DESCRIPTION": "Server-time out, försök igen eller kontakta IT-support [504].", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "Tillbaka hem" + } + } + }, + "ABOUT": { + "SERVER_SETTINGS": { + "TITLE": "Serverinställningar", + "DESCRIPTION": "Värdena nedan tas från AppConfigService", + "CONTENT_SERVICE_HOST": "Alfresco Content Services URL: {{ value }}", + "PROCESS_SERVICE_HOST": "Alfresco Process Services URL: {{ value }}" + }, + "VERSIONS": { + "TITLE": "Produktversioner", + "CONTENT_SERVICE": "ECM", + "PROCESS_SERVICE": "BPM", + "LABELS": { + "EDITION": "Version", + "VERSION": "Version", + "LICENSE": "Licens", + "STATUS": "Status", + "MODULES": "Moduler" + } + }, + "SOURCE_CODE": { + "TITLE": "källkod", + "DESCRIPTION": "Du driver projektet baserat på följande åtaganden:" + }, + "PACKAGES": { + "TITLE": "Paket", + "DESCRIPTION": "Det aktuella projektet använder följande ADF-bibliotek:" + }, + "TABLE_HEADERS": { + "MODULES": { + "ID": "ID", + "TITLE": "Titel", + "DESCRIPTION": "Beskrivning", + "INSTALL_DATE": "Installationsdatum", + "INSTALL_STATE": "Installationstillstånd", + "VERSION_MIN": "Version mindre", + "VERSION_MAX": "Version max" + }, + "STATUS": { + "READ_ONLY": "ReadOnly", + "AUDIT_ENABLED": "Är revision aktiverad", + "QUICK_SHARE_ENABLED": "Är snabbdelad aktiverad", + "THUMBNAIL_ENABLED": "Miniatyrbildsgenerering" + }, + "LICENSE": { + "ISSUES_AT": "Utgiven den", + "EXPIRES_AT": "Löper ut den", + "REMAINING_DAYS": "Kvarvarande dagar", + "HOLDER": "Innehavare", + "MODE": "Läge", + "CLUSTER_ENABLED": "Är Kluster aktiverat", + "CRYPTODOC_ENABLED": "Är Cryptodoc aktiverat" + } + } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "Klicka för att kopiera", + "SUCCESS_COPY": "Texten har kopierats till urklipp" + } +} \ No newline at end of file diff --git a/lib/core/i18n/zh-CN.json b/lib/core/i18n/zh-CN.json index 3e69d9f6b3..d06fbac2ce 100644 --- a/lib/core/i18n/zh-CN.json +++ b/lib/core/i18n/zh-CN.json @@ -1,6 +1,9 @@ { "SAVE": "保存", "COMPLETE": "完成", + "CANCEL": "取消", + "CLAIM": "申领", + "UNCLAIM": "释放", "START PROCESS": "启动流程", "FORM": { "START_FORM": { @@ -26,6 +29,9 @@ "AT_LEAST_LONG": "至少输入 {{ minLength }} 个字符", "NO_LONGER_THAN": "输入不超过 {{ maxLength }} 个字符" } + }, + "FORM_RENDERER": { + "NAMELESS_TASK": "无名称的任务" } }, "CORE": { @@ -334,6 +340,36 @@ "RETURN_BUTTON": { "TEXT": "返回到主页" } + }, + "500": { + "TITLE": "出现错误。", + "DESCRIPTION": "内部服务器错误,请重试或联系 IT 支持 [500]。", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "返回到主页" + } + }, + "502": { + "TITLE": "出现错误。", + "DESCRIPTION": "错误网关,请重试或联系 IT 支持 [502]。", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "返回到主页" + } + }, + "504": { + "TITLE": "出现错误。", + "DESCRIPTION": "服务器超时,请重试或联系 IT 支持 [504]。", + "SECONDARY_BUTTON": { + "TEXT": "" + }, + "RETURN_BUTTON": { + "TEXT": "返回到主页" + } } }, "ABOUT": { @@ -389,5 +425,9 @@ "CRYPTODOC_ENABLED": "是否已启用 Cryptodoc" } } + }, + "CLIPBOARD": { + "CLICK_TO_COPY": "单击以复制", + "SUCCESS_COPY": "复制到剪贴板上的文本" } } \ No newline at end of file diff --git a/lib/insights/i18n/cs.json b/lib/insights/i18n/cs.json new file mode 100644 index 0000000000..a918f79f1f --- /dev/null +++ b/lib/insights/i18n/cs.json @@ -0,0 +1,51 @@ +{ + "ANALYTICS": { + "TITLE": "Analýza", + "MESSAGES": { + "UNKNOWN-WIDGET-TYPE": "Neznámý typ widgetu", + "FILL-PARAMETER": "Vyberte z možností zpráv", + "NO-DATA-FOUND": "Nenalezena žádná data", + "ZERO-DATA-FOUND": "Zjištěny pouze nulové hodnoty", + "ICON-SETTING": "Nastavení", + "ICON-SAVE": "Uložit", + "ICON-DELETE": "Odstranit", + "ICON-EXPORT-CSV": "Exportovat" + } + }, + "__KEY_REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-DEFINITION-OVERVIEW": { + "GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Celkový počet definicí procesu", + "GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Celkový počet instancí procesu", + "GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Celkový počet aktivních instancí procesu", + "GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Celkový počet ukončených instancí procesu" + } + } + }, + "REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-HEAT-MAP": { + "TYPE-FILTERING": "Zahrnout průchozí kroky, jako je zahájení událostí a brány" + }, + "PROCESS-INSTANCES-OVERVIEW": { + "PROCESS-DEFINITION": "Definice procesu", + "DATE-RANGE": "Rozsah dat", + "SLOW-PROC-INST-NUMBER": "Kolik nejpomalejších instancí procesu si přejete zobrazit?" + }, + "TASK-OVERVIEW": { + "PROCESS-DEFINITION": "Definice procesu", + "DATE-RANGE": "Rozsah dat", + "DATE-RANGE-INTERVAL": "Seskupit data podle" + }, + "TASK-SLA": { + "TASK": "Úkol", + "PROCESS-DEFINITION": "Definice procesu", + "DATE-RANGE": "Rozsah dat", + "SLA-DURATION": "Čas na dokončení splňující požadavky smlouvy SLA" + } + }, + "PROCESS-STATUS": "Stav procesu", + "TASK-STATUS": "Stav úkolu" + }, + "DIAGRAMS": "Diagramy" +} \ No newline at end of file diff --git a/lib/insights/i18n/da.json b/lib/insights/i18n/da.json new file mode 100644 index 0000000000..bf67f083d0 --- /dev/null +++ b/lib/insights/i18n/da.json @@ -0,0 +1,51 @@ +{ + "ANALYTICS": { + "TITLE": "Analyse", + "MESSAGES": { + "UNKNOWN-WIDGET-TYPE": "Ukendt widgettype", + "FILL-PARAMETER": "Vælg fra rapportindstillingerne", + "NO-DATA-FOUND": "Der blev ikke fundet nogen data", + "ZERO-DATA-FOUND": "Der er kun nul-værdier", + "ICON-SETTING": "Indstillinger", + "ICON-SAVE": "Gem", + "ICON-DELETE": "Slet", + "ICON-EXPORT-CSV": "Eksportér" + } + }, + "__KEY_REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-DEFINITION-OVERVIEW": { + "GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Det samlede antal procesdefinitioner", + "GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Det samlede antal procesforekomster", + "GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Det samlede antal aktive procesforekomster", + "GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Det samlede antal fuldførte procesforekomster" + } + } + }, + "REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-HEAT-MAP": { + "TYPE-FILTERING": "Inkluder gennemløbstrin, f.eks. starthændelser og gateways" + }, + "PROCESS-INSTANCES-OVERVIEW": { + "PROCESS-DEFINITION": "Procesdefinition", + "DATE-RANGE": "Dateinterval", + "SLOW-PROC-INST-NUMBER": "Hvor mange af de langsomste procesforekomster skal der vises?" + }, + "TASK-OVERVIEW": { + "PROCESS-DEFINITION": "Procesdefinition", + "DATE-RANGE": "Dateinterval", + "DATE-RANGE-INTERVAL": "Gruppér datoer efter" + }, + "TASK-SLA": { + "TASK": "Opgave", + "PROCESS-DEFINITION": "Procesdefinition", + "DATE-RANGE": "Dateinterval", + "SLA-DURATION": "Påkrævet fuldførelsestid ifølge serviceniveauaftale" + } + }, + "PROCESS-STATUS": "Processtatus", + "TASK-STATUS": "Opgavestatus" + }, + "DIAGRAMS": "Diagrammer" +} \ No newline at end of file diff --git a/lib/insights/i18n/fi.json b/lib/insights/i18n/fi.json new file mode 100644 index 0000000000..6776c7b52f --- /dev/null +++ b/lib/insights/i18n/fi.json @@ -0,0 +1,51 @@ +{ + "ANALYTICS": { + "TITLE": "Analytiikka", + "MESSAGES": { + "UNKNOWN-WIDGET-TYPE": "Tuntematon piensovellustyyppi", + "FILL-PARAMETER": "Valitse raporttiasetuksista", + "NO-DATA-FOUND": "Tietoja ei löydy", + "ZERO-DATA-FOUND": "Mukana on vain nolla -arvoja", + "ICON-SETTING": "Asetukset", + "ICON-SAVE": "Tallenna", + "ICON-DELETE": "Poista", + "ICON-EXPORT-CSV": "Vie" + } + }, + "__KEY_REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-DEFINITION-OVERVIEW": { + "GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Prosessimääritelmien kokonaismäärä", + "GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Prosessiesiintymien kokonaismäärä", + "GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Aktiivisten prosessiesiintymien kokonaismäärä", + "GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Suoritettujen prosessiesiintymien kokonaismäärä" + } + } + }, + "REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-HEAT-MAP": { + "TYPE-FILTERING": "Sisällytä läpivientivaiheet, esimerkiksi käynnistystapahtumat ja yhdyskäytävät" + }, + "PROCESS-INSTANCES-OVERVIEW": { + "PROCESS-DEFINITION": "Prosessimääritelmä", + "DATE-RANGE": "Päivämääräalue", + "SLOW-PROC-INST-NUMBER": "Kuinka monta hitaimmista prosessiesiintymistä näytetään?" + }, + "TASK-OVERVIEW": { + "PROCESS-DEFINITION": "Prosessimääritelmä", + "DATE-RANGE": "Päivämääräalue", + "DATE-RANGE-INTERVAL": "Ryhmittele päivämäärät tämän perusteella:" + }, + "TASK-SLA": { + "TASK": "Tehtävä", + "PROCESS-DEFINITION": "Prosessimääritelmä", + "DATE-RANGE": "Päivämääräalue", + "SLA-DURATION": "Palvelutasosopimuksen edellyttämä valmistumisaika" + } + }, + "PROCESS-STATUS": "Prosessin tila", + "TASK-STATUS": "Tehtävän tila" + }, + "DIAGRAMS": "Kaaviot" +} \ No newline at end of file diff --git a/lib/insights/i18n/pl.json b/lib/insights/i18n/pl.json new file mode 100644 index 0000000000..b33de89d39 --- /dev/null +++ b/lib/insights/i18n/pl.json @@ -0,0 +1,51 @@ +{ + "ANALYTICS": { + "TITLE": "ANALITYKA", + "MESSAGES": { + "UNKNOWN-WIDGET-TYPE": "NIEZNANY TYP WIDŻETU", + "FILL-PARAMETER": "Wybierz odpowiednie opcje raportu", + "NO-DATA-FOUND": "Nie znaleziono danych", + "ZERO-DATA-FOUND": "Występują tylko wartości zerowe.", + "ICON-SETTING": "Ustawienia", + "ICON-SAVE": "Zapisz", + "ICON-DELETE": "Usuń", + "ICON-EXPORT-CSV": "Eksportuj" + } + }, + "__KEY_REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-DEFINITION-OVERVIEW": { + "GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Całkowita liczba definicji procesu", + "GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Całkowita liczba wystąpień procesu", + "GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Całkowita liczba aktywnych wystąpień procesu", + "GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Całkowita liczba zakończonych wystąpień procesu" + } + } + }, + "REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-HEAT-MAP": { + "TYPE-FILTERING": "Uwzględnij przejście przez etapy, takie jak zdarzenia początkowe i bramy." + }, + "PROCESS-INSTANCES-OVERVIEW": { + "PROCESS-DEFINITION": "Definicja procesu", + "DATE-RANGE": "Zakres dat", + "SLOW-PROC-INST-NUMBER": "Ile najwolniejszych wystąpień procesu ma być wyświetlonych?" + }, + "TASK-OVERVIEW": { + "PROCESS-DEFINITION": "Definicja procesu", + "DATE-RANGE": "Zakres dat", + "DATE-RANGE-INTERVAL": "Grupuj daty według" + }, + "TASK-SLA": { + "TASK": "Zadanie", + "PROCESS-DEFINITION": "Definicja procesu", + "DATE-RANGE": "Zakres dat", + "SLA-DURATION": "Wymagany przez SLA czas zakończenia" + } + }, + "PROCESS-STATUS": "Status procesu", + "TASK-STATUS": "Status zadania" + }, + "DIAGRAMS": "Schematy" +} \ No newline at end of file diff --git a/lib/insights/i18n/sv.json b/lib/insights/i18n/sv.json new file mode 100644 index 0000000000..3fda8b2fa4 --- /dev/null +++ b/lib/insights/i18n/sv.json @@ -0,0 +1,51 @@ +{ + "ANALYTICS": { + "TITLE": "Analytics", + "MESSAGES": { + "UNKNOWN-WIDGET-TYPE": "Okänd widgettyp", + "FILL-PARAMETER": "Välj från rapportalternativen", + "NO-DATA-FOUND": "Inga data hittades", + "ZERO-DATA-FOUND": "Det finns bara nollvärden", + "ICON-SETTING": "Inställningar", + "ICON-SAVE": "Spara", + "ICON-DELETE": "Radera", + "ICON-EXPORT-CSV": "Exportera" + } + }, + "__KEY_REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-DEFINITION-OVERVIEW": { + "GENERAL-TABLE-TOTAL-PROCESS-DEFINITIONS": "Totalt antal processdefinitioner", + "GENERAL-TABLE-TOTAL-PROCESS-INSTANCES": "Totalt antal processinstancer", + "GENERAL-TABLE-ACTIVE-PROCESS-INSTANCES": "Totalt antal aktiva processinstanser", + "GENERAL-TABLE-COMPLETED-PROCESS-INSTANCES": "Totalt antal slutförda processinstanser" + } + } + }, + "REPORTING": { + "DEFAULT-REPORTS": { + "PROCESS-HEAT-MAP": { + "TYPE-FILTERING": "Inkludera genomgångssteg såsom starthändelser och gateways" + }, + "PROCESS-INSTANCES-OVERVIEW": { + "PROCESS-DEFINITION": "Processdefinition", + "DATE-RANGE": "Datumintervall", + "SLOW-PROC-INST-NUMBER": "Hur många av de långsammaste processinstanserna ska visas?" + }, + "TASK-OVERVIEW": { + "PROCESS-DEFINITION": "Processdefinition", + "DATE-RANGE": "Datumintervall", + "DATE-RANGE-INTERVAL": "Gruppdatum per" + }, + "TASK-SLA": { + "TASK": "Uppgift", + "PROCESS-DEFINITION": "Processdefinition", + "DATE-RANGE": "Datumintervall", + "SLA-DURATION": "Serviceavtal begärd slutförandetid" + } + }, + "PROCESS-STATUS": "Processtatus", + "TASK-STATUS": "Uppgiftsstatus" + }, + "DIAGRAMS": "Diagram" +} \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/ar.json b/lib/process-services-cloud/src/lib/i18n/ar.json index da2c4edb40..48e001a42a 100644 --- a/lib/process-services-cloud/src/lib/i18n/ar.json +++ b/lib/process-services-cloud/src/lib/i18n/ar.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "لم يتم العثور على تطبيقات", - "SUBTITLE": "أنشئ تطبيقًا جديدًا تريد العثور عليه بسهولة لاحقًا" + "NO_APPS": { + "TITLE": "لم يتم العثور على تطبيقات", + "SUBTITLE": "أنشئ تطبيقًا جديدًا تريد العثور عليه بسهولة لاحقًا" + }, + "ERROR": { + "TITLE": "حدث خطأ", + "SUBTITLE": "تأكد أن لديك الإذن بالوصول إلى التطبيق" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "معين له", "CANDIDATE_GROUP": "المجموعة المرشحة", "FORM": "نموذج", - "DATE": "اختيار تاريخ" + "DATE": "اختيار تاريخ", + "NONE": "بلا" }, "ACTION": { "START": "بدء", @@ -76,7 +83,8 @@ "PRIORITY": "أولوية", "CREATED_DATE": "تاريخ الإنشاء", "LAST_MODIFIED": "آخر تعديل", - "CREATED": "تم الإنشاء" + "CREATED": "تم الإنشاء", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "ApplicationName", + "TASK_ID": "معرف المهمة", "PROCESS_DEF_ID": "ProcessDefinitionId", "STATUS": "الحالة", "ASSIGNMENT": "معين له", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "مطالبة", - "UNCLAIM": "إعادة وضع في قائمة الانتظار" + "RELEASE": "تحرير" }, "PROPERTIES": { "TASK_NAME": "مهمة", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "المعرف", "NAME": "الاسم", + "NAME_DEFAULT": "بدون اسم", "DESCRIPTION": "الوصف", "DESCRIPTION_DEFAULT": "لا يوجد وصف", "STATUS": "الحالة", @@ -219,5 +229,17 @@ "PARENT_ID": "المعرف الأصلي", "NONE": "بلا" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "لا يوجد نموذج", + "SUBTITLE": "قم بإرفاق نموذج يمكن عرضه لاحقًا", + "BUTTONS": { + "COMPLETE": "تم", + "CANCEL": "إلغاء", + "CLAIM": "مطالبة", + "UNCLAIM": "تحرير" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/cs.json b/lib/process-services-cloud/src/lib/i18n/cs.json new file mode 100644 index 0000000000..8b92ca0ba1 --- /dev/null +++ b/lib/process-services-cloud/src/lib/i18n/cs.json @@ -0,0 +1,245 @@ +{ + "ADF_CLOUD_PROCESS_LIST": { + "MESSAGES": { + "TITLE": "Nenalezeny žádné procesy", + "SUBTITLE": "Pro lepší přehlednost vytvořte nový proces", + "NONE": "Nebyl zvolen žádný filtr instancí." + }, + "PROPERTIES": { + "NAME": "Název", + "CREATED": "Vytvořeno", + "STATUS": "Stav", + "START_DATE": "Datum zahájení", + "ID": "ID", + "INITIATOR": "Iniciátor", + "APP_NAME": "Název aplikace", + "BUSINESS_KEY": "Obchodní klíč", + "DESCRIPTION": "Popis", + "LAST_MODIFIED": "Poslední úprava", + "PROCESS_NAME": "Název procesu", + "PARENT_TASK_ID": "ID nadřazeného úkolu", + "PROCESS_DEF_ID": "ID definice procesu", + "PROCESS_DEF_KEY": "Klíč definice procesu" + }, + "ADF_CLOUD_START_PROCESS": { + "BUTTON": "Zahájit proces", + "NO_PROCESS_DEFINITIONS": "Proces nelze zahájit, protože nejsou k dispozici žádné definice procesu", + "FORM": { + "TITLE": "Zahájit proces", + "LABEL": { + "TYPE": "Vybrat proces", + "NAME": "Název procesu" + }, + "TYPE_PLACEHOLDER": "Vyberte...", + "ACTION": { + "START": "Zahájit proces", + "CANCEL": "Zrušit" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Definice procesu se nepodařilo načíst. Zkontrolujte svá přístupová oprávnění.", + "START": "Nepodařilo se spustit novou instanci procesu. Zkontrolujte svá přístupová oprávnění.", + "PROCESS_NAME_REQUIRED": "Název procesu je povinný", + "PROCESS_DEFINITION_REQUIRED": "Definice procesu je povinná", + "MAXIMUM_LENGTH": "Přesáhli jste délku (maximálně lze zadat {{characters}} znaků)." + } + } + }, + "ADF_CLOUD_TASK_LIST": { + "APPS": { + "NO_APPS": { + "TITLE": "Nenalezeny žádné aplikace", + "SUBTITLE": "Pro lepší přehlednost vytvořte novou aplikaci" + }, + "ERROR": { + "TITLE": "Došlo k chybě", + "SUBTITLE": "Ověřte svá oprávnění pro přístup k aplikacím" + } + }, + "START_TASK": { + "FORM": { + "TITLE": "Zahájit úkol", + "LABEL": { + "NAME": "Název", + "DESCRIPTION": "Popis", + "ATTACHFORM": "Připojit formulář", + "ASSIGNEE": "Pověřená osoba", + "CANDIDATE_GROUP": "Skupina kandidáta", + "FORM": "Formulář", + "DATE": "Zvolit datum", + "NONE": "Žádné" + }, + "ACTION": { + "START": "Spustit", + "CANCEL": "Zrušit" + } + } + }, + "PROPERTIES": { + "NAME": "Název", + "ASSIGNEE": "Pověřená osoba", + "ID": "ID", + "STATUS": "Stav", + "PRIORITY": "Priorita", + "CREATED_DATE": "Datum vytvoření", + "LAST_MODIFIED": "Poslední úprava", + "CREATED": "Vytvořeno", + "JSON_CELL": "Json" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Nenalezeny žádné úkoly", + "SUBTITLE": "Pro lepší přehlednost vytvořte nový úkol", + "NONE": "Nenalezeny žádné seznamy úkolů" + } + } + }, + "ADF_CLOUD_TASK_FILTERS": { + "MY_TASKS": "Moje úkoly", + "COMPLETED_TASKS": "Dokončené úkoly" + }, + "ADF_CLOUD_PROCESS_FILTERS": { + "ALL_PROCESSES": "Všechny procesy", + "RUNNING_PROCESSES": "Spuštěné procesy", + "COMPLETED_PROCESSES": "Dokončené procesy" + }, + "ADF_CLOUD_START_TASK": { + "ERROR": { + "MESSAGE": "Zadejte jinou hodnotu", + "REQUIRED": "Povinné pole", + "DATE": "Formát data je DD/MM/RRRR", + "MAXIMUM_LENGTH": "Přesáhli jste délku (maximálně lze zadat {{characters}} znaků)." + } + }, + "ADF_CLOUD_EDIT_TASK_FILTER": { + "TITLE": "Přizpůsobte svůj filtr", + "TOOL_TIP": { + "SAVE": "Uložit filtr", + "SAVE_AS": "Uložit filtr jako", + "DELETE": "Odstranit filtr" + }, + "LABEL": { + "APP_NAME": "Název aplikace", + "TASK_ID": "ID úkolu", + "PROCESS_DEF_ID": "ID definice procesu", + "STATUS": "Stav", + "ASSIGNMENT": "Pověřená osoba", + "DIRECTION": "Směr", + "PROCESS_INSTANCE_ID": "ID instance procesu", + "TASK_NAME": "Název úlohy", + "PARENT_TASK_ID": "ID nadřazené úlohy", + "PRIORITY": "Priorita", + "STAND_ALONE": "Samostatná", + "LAST_MODIFIED_FROM": "Poslední úprava od", + "LAST_MODIFIED_TO": "Poslední úprava do", + "OWNER": "Vlastník", + "DUE_DATE": "Termín", + "SORT": "Třídění", + "START_DATE": "Datum zahájení" + }, + "DIALOG": { + "TITLE": "Uložit filtr jako", + "SAVE": "Uložit", + "CANCEL": "Zrušit" + } + }, + "ADF_CLOUD_EDIT_PROCESS_FILTER": { + "TITLE": "Přizpůsobte svůj filtr", + "LABEL": { + "APP_NAME": "Název aplikace", + "PROCESS_INS_ID": "ID instance procesu", + "STATUS": "Stav", + "INITIATOR": "Iniciátor", + "ASSIGNMENT": "Pověřená osoba", + "SORT": "Třídění", + "DIRECTION": "Směr", + "PROCESS_DEF_ID": "ID definice procesu", + "PROCESS_DEF_KEY": "Klíč definice procesu", + "LAST_MODIFIED": "Poslední úprava", + "LAST_MODIFIED_DATE_FORM": "Poslední úprava od", + "LAST_MODIFIED_TO": "Poslední úprava do", + "PROCESS_NAME": "Název procesu" + }, + "ERROR": { + "DATE": "Formát data je DD/MM/RRRR" + }, + "TOOL_TIP": { + "SAVE": "Uložit filtr", + "SAVE_AS": "Uložit filtr jako", + "DELETE": "Odstranit filtr" + }, + "DIALOG": { + "TITLE": "Uložit filtr jako", + "SAVE": "Uložit", + "CANCEL": "Zrušit" + } + }, + "ADF_CLOUD_GROUPS": { + "SEARCH-GROUP": "Skupiny", + "ERROR": { + "NOT_FOUND": "Nenalezena žádná skupina s názvem {{groupName}}" + } + }, + "ADF_CLOUD_TASK_HEADER": { + "BUTTON": { + "CLAIM": "Převzít", + "RELEASE": "Vzdát se" + }, + "PROPERTIES": { + "TASK_NAME": "Úkol", + "THUMBNAIL": "Miniatura", + "DURATION": "Trvání", + "PARENT_TASK_ID": "ID nadřazeného úkolu", + "NAME": "Název", + "ASSIGNEE": "Pověřená osoba", + "ASSIGNEE_DEFAULT": "Žádná pověřená osoba", + "PRIORITY": "Priorita", + "DUE_DATE": "Termín", + "DUE_DATE_DEFAULT": "Žádné datum", + "STATUS": "Stav", + "CATEGORY": "Kategorie", + "CATEGORY_DEFAULT": "Žádná kategorie", + "PARENT_NAME": "Název nadřazené složky", + "PARENT_NAME_DEFAULT": "Žádná nadřazená složka", + "CREATED_BY": "Vytvořil(a)", + "CREATED": "Vytvořeno", + "END_DATE": "Datum ukončení", + "ID": "ID", + "DESCRIPTION": "Popis", + "DESCRIPTION_DEFAULT": "Žádný popis", + "FORM_NAME": "Název formuláře", + "FORM_NAME_DEFAULT": "Žádný formulář" + }, + "FORM_VALIDATION": { + "INVALID_FIELD": "Zadejte jinou hodnotu" + } + }, + "ADF_CLOUD_PROCESS_HEADER": { + "PROPERTIES": { + "ID": "ID", + "NAME": "Název", + "NAME_DEFAULT": "Bez názvu", + "DESCRIPTION": "Popis", + "DESCRIPTION_DEFAULT": "Žádný popis", + "STATUS": "Stav", + "BUSINESS_KEY": "Obchodní klíč", + "INITIATOR": "Iniciátor", + "START_DATE": "Datum zahájení", + "LAST_MODIFIED": "Poslední úprava", + "PARENT_ID": "ID nadřazené položky", + "NONE": "Žádné" + } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Není k dispozici žádný formulář", + "SUBTITLE": "Připojte formulář pro pozdější použití", + "BUTTONS": { + "COMPLETE": "Dokončit", + "CANCEL": "Zrušit", + "CLAIM": "Převzít", + "UNCLAIM": "Vzdát se" + } + } + } +} \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/da.json b/lib/process-services-cloud/src/lib/i18n/da.json new file mode 100644 index 0000000000..6086e54d85 --- /dev/null +++ b/lib/process-services-cloud/src/lib/i18n/da.json @@ -0,0 +1,245 @@ +{ + "ADF_CLOUD_PROCESS_LIST": { + "MESSAGES": { + "TITLE": "Der blev ikke fundet nogen processer", + "SUBTITLE": "Opret en ny proces, som skal være nem at finde senere", + "NONE": "Der er ikke valgt et filter for procesforekomster." + }, + "PROPERTIES": { + "NAME": "Navn", + "CREATED": "Oprettet", + "STATUS": "Status", + "START_DATE": "Startdato", + "ID": "Id", + "INITIATOR": "Initiativtager", + "APP_NAME": "Appnavn", + "BUSINESS_KEY": "Forretningsnøgle", + "DESCRIPTION": "Beskrivelse", + "LAST_MODIFIED": "Senest ændret", + "PROCESS_NAME": "Procesnavn", + "PARENT_TASK_ID": "Id for overordnet opgave", + "PROCESS_DEF_ID": "Id for procesdefinition", + "PROCESS_DEF_KEY": "Procesdefinitionsnøgle" + }, + "ADF_CLOUD_START_PROCESS": { + "BUTTON": "Start proces", + "NO_PROCESS_DEFINITIONS": "Du kan ikke starte en proces, da der ikke er nogen tilgængelige procesdefinitioner", + "FORM": { + "TITLE": "Start proces", + "LABEL": { + "TYPE": "Vælg proces", + "NAME": "Procesnavn" + }, + "TYPE_PLACEHOLDER": "Vælg en...", + "ACTION": { + "START": "Start proces", + "CANCEL": "Annuller" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Der kunne ikke indlæses nogen procesdefinitioner. Kontrollér, om du har adgang til dem.", + "START": "Der kunne ikke startes en ny procesforekomst. Kontrollér, om du har adgang.", + "PROCESS_NAME_REQUIRED": "Procesnavn er påkrævet", + "PROCESS_DEFINITION_REQUIRED": "Procesdefinition er påkrævet", + "MAXIMUM_LENGTH": "Længden er overskredet, maks. {{characters}} tegn." + } + } + }, + "ADF_CLOUD_TASK_LIST": { + "APPS": { + "NO_APPS": { + "TITLE": "Der blev ikke fundet nogen programmer", + "SUBTITLE": "Opret et nyt program, som skal være nemt at finde senere" + }, + "ERROR": { + "TITLE": "Der opstod en fejl", + "SUBTITLE": "Kontrollér, at du har adgangstilladelse til disse apps" + } + }, + "START_TASK": { + "FORM": { + "TITLE": "Start opgave", + "LABEL": { + "NAME": "Navn", + "DESCRIPTION": "Beskrivelse", + "ATTACHFORM": "Vedhæft formular", + "ASSIGNEE": "Modtager", + "CANDIDATE_GROUP": "Kandidatgruppe", + "FORM": "Formular", + "DATE": "Vælg dato", + "NONE": "Ingen" + }, + "ACTION": { + "START": "Start", + "CANCEL": "Annuller" + } + } + }, + "PROPERTIES": { + "NAME": "Navn", + "ASSIGNEE": "Modtager", + "ID": "Id", + "STATUS": "Status", + "PRIORITY": "Prioritet", + "CREATED_DATE": "Oprettelsesdato", + "LAST_MODIFIED": "Senest ændret", + "CREATED": "Oprettet", + "JSON_CELL": "Json" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Der blev ikke fundet nogen opgaver", + "SUBTITLE": "Opret en ny opgave, som skal være nem at finde senere", + "NONE": "Der blev ikke fundet nogen opgavelister" + } + } + }, + "ADF_CLOUD_TASK_FILTERS": { + "MY_TASKS": "Mine opgaver", + "COMPLETED_TASKS": "Fuldførte opgaver" + }, + "ADF_CLOUD_PROCESS_FILTERS": { + "ALL_PROCESSES": "Alle processer", + "RUNNING_PROCESSES": "Kørsel af processer", + "COMPLETED_PROCESSES": "Fuldførte processer" + }, + "ADF_CLOUD_START_TASK": { + "ERROR": { + "MESSAGE": "Angiv en anden værdi", + "REQUIRED": "Obligatorisk felt", + "DATE": "Datoformat DD/MM/ÅÅÅÅ", + "MAXIMUM_LENGTH": "Længden er overskredet, maks. {{characters}} tegn." + } + }, + "ADF_CLOUD_EDIT_TASK_FILTER": { + "TITLE": "Tilpas dit filter", + "TOOL_TIP": { + "SAVE": "Gem filter", + "SAVE_AS": "Gem filter som", + "DELETE": "Slet filter" + }, + "LABEL": { + "APP_NAME": "Programnavn", + "TASK_ID": "Opgave-id", + "PROCESS_DEF_ID": "Procesdefinitions-id", + "STATUS": "Status", + "ASSIGNMENT": "Modtager", + "DIRECTION": "Retning", + "PROCESS_INSTANCE_ID": "Procesforekomst-id", + "TASK_NAME": "Opgavenavn", + "PARENT_TASK_ID": "OverordnetOpgave-id", + "PRIORITY": "Prioritet", + "STAND_ALONE": "Separat", + "LAST_MODIFIED_FROM": "Sidst redigeret fra", + "LAST_MODIFIED_TO": "Sidst redigeret til", + "OWNER": "Ejer", + "DUE_DATE": "Forfaldsdato", + "SORT": "Sortér", + "START_DATE": "Startdato" + }, + "DIALOG": { + "TITLE": "Gem filter som", + "SAVE": "Gem", + "CANCEL": "Annuller" + } + }, + "ADF_CLOUD_EDIT_PROCESS_FILTER": { + "TITLE": "Tilpas dit filter", + "LABEL": { + "APP_NAME": "Programnavn", + "PROCESS_INS_ID": "Procesforekomst-id", + "STATUS": "Status", + "INITIATOR": "Initiativtager", + "ASSIGNMENT": "Modtager", + "SORT": "Sortér", + "DIRECTION": "Retning", + "PROCESS_DEF_ID": "Procesdefinitions-id", + "PROCESS_DEF_KEY": "Procesdefinitionsnøgle", + "LAST_MODIFIED": "Sidst redigeret", + "LAST_MODIFIED_DATE_FORM": "Sidst redigeret fra", + "LAST_MODIFIED_TO": "Sidst redigeret til", + "PROCESS_NAME": "Procesnavn" + }, + "ERROR": { + "DATE": "Datoformat DD/MM/ÅÅÅÅ" + }, + "TOOL_TIP": { + "SAVE": "Gem filter", + "SAVE_AS": "Gem filter som", + "DELETE": "Slet filter" + }, + "DIALOG": { + "TITLE": "Gem filter som", + "SAVE": "Gem", + "CANCEL": "Annuller" + } + }, + "ADF_CLOUD_GROUPS": { + "SEARCH-GROUP": "Grupper", + "ERROR": { + "NOT_FOUND": "Der blev ikke fundet en gruppe med navnet {{groupName}}" + } + }, + "ADF_CLOUD_TASK_HEADER": { + "BUTTON": { + "CLAIM": "Gør krav på", + "RELEASE": "Frigiv" + }, + "PROPERTIES": { + "TASK_NAME": "Opgave", + "THUMBNAIL": "Miniaturevisning", + "DURATION": "Varighed", + "PARENT_TASK_ID": "Id for overordnet opgave", + "NAME": "Navn", + "ASSIGNEE": "Modtager", + "ASSIGNEE_DEFAULT": "Ingen modtager", + "PRIORITY": "Prioritet", + "DUE_DATE": "Forfaldsdato", + "DUE_DATE_DEFAULT": "Ingen dato", + "STATUS": "Status", + "CATEGORY": "Kategori", + "CATEGORY_DEFAULT": "Ingen kategori", + "PARENT_NAME": "Overordnet navn", + "PARENT_NAME_DEFAULT": "Ingen overordnet", + "CREATED_BY": "Oprettet af", + "CREATED": "Oprettet", + "END_DATE": "Slutdato", + "ID": "Id", + "DESCRIPTION": "Beskrivelse", + "DESCRIPTION_DEFAULT": "Ingen beskrivelse", + "FORM_NAME": "Formularnavn", + "FORM_NAME_DEFAULT": "Ingen formular" + }, + "FORM_VALIDATION": { + "INVALID_FIELD": "Angiv en anden værdi" + } + }, + "ADF_CLOUD_PROCESS_HEADER": { + "PROPERTIES": { + "ID": "Id", + "NAME": "Navn", + "NAME_DEFAULT": "Intet navn", + "DESCRIPTION": "Beskrivelse", + "DESCRIPTION_DEFAULT": "Ingen beskrivelse", + "STATUS": "Status", + "BUSINESS_KEY": "Forretningsnøgle", + "INITIATOR": "Initiativtager", + "START_DATE": "Startdato", + "LAST_MODIFIED": "Senest ændret", + "PARENT_ID": "Overordnet-id", + "NONE": "Ingen" + } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Der er ingen tilgængelig formular", + "SUBTITLE": "Vedhæft en formular, der kan blive vist senere", + "BUTTONS": { + "COMPLETE": "Fuldført", + "CANCEL": "Annuller", + "CLAIM": "Gør krav på", + "UNCLAIM": "Frigiv" + } + } + } +} \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/de.json b/lib/process-services-cloud/src/lib/i18n/de.json index 5717d20798..d3b8f0ef2e 100644 --- a/lib/process-services-cloud/src/lib/i18n/de.json +++ b/lib/process-services-cloud/src/lib/i18n/de.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Keine Anwendungen gefunden", - "SUBTITLE": "Erstellen Sie eine neue Anwendung, die sich später leicht wiederfinden lässt" + "NO_APPS": { + "TITLE": "Keine Anwendungen gefunden", + "SUBTITLE": "Erstellen Sie eine neue Anwendung, die sich später leicht wiederfinden lässt" + }, + "ERROR": { + "TITLE": "Es ist ein Fehler aufgetreten", + "SUBTITLE": "Überprüfen Sie, ob Sie zum Zugriff auf die Anwendungen berechtigt sind" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Zugewiesener Benutzer", "CANDIDATE_GROUP": "Kandidatengruppe", "FORM": "Formular", - "DATE": "Datum auswählen" + "DATE": "Datum auswählen", + "NONE": "Keine" }, "ACTION": { "START": "Start", @@ -76,7 +83,8 @@ "PRIORITY": "Priorität", "CREATED_DATE": "Datum der Erstellung", "LAST_MODIFIED": "Zuletzt geändert", - "CREATED": "Erstellt" + "CREATED": "Erstellt", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Anwendungsname", + "TASK_ID": "Aufgaben-ID", "PROCESS_DEF_ID": "Prozessdefinitions-ID", "STATUS": "Status", "ASSIGNMENT": "Zugewiesener Benutzer", @@ -173,8 +182,8 @@ }, "ADF_CLOUD_TASK_HEADER": { "BUTTON": { - "CLAIM": "Anfordern", - "UNCLAIM": "Erneut in Warteschlange stellen" + "CLAIM": "Beanspruchen", + "RELEASE": "Anspruch aufheben" }, "PROPERTIES": { "TASK_NAME": "Aufgabe", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Name", + "NAME_DEFAULT": "Kein Name", "DESCRIPTION": "Beschreibung", "DESCRIPTION_DEFAULT": "Keine Beschreibung", "STATUS": "Status", @@ -219,5 +229,17 @@ "PARENT_ID": "Übergeordnete ID", "NONE": "Keine" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Kein Formular verfügbar", + "SUBTITLE": "Hängen Sie ein Formular an, das später angesehen werden kann", + "BUTTONS": { + "COMPLETE": "Abschließen", + "CANCEL": "Abbrechen", + "CLAIM": "Beanspruchen", + "UNCLAIM": "Anspruch aufheben" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 3aef9ccec8..201778db72 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -238,7 +238,7 @@ "COMPLETE": "COMPLETE", "CANCEL": "CANCEL", "CLAIM": "CLAIM", - "UNCLAIM": "UNCLAIM" + "UNCLAIM": "RELEASE" } } } diff --git a/lib/process-services-cloud/src/lib/i18n/es.json b/lib/process-services-cloud/src/lib/i18n/es.json index 513dd64d54..ef4e3396a9 100644 --- a/lib/process-services-cloud/src/lib/i18n/es.json +++ b/lib/process-services-cloud/src/lib/i18n/es.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "No se han encontrado aplicaciones", - "SUBTITLE": "Cree una nueva aplicación que desee encontrar fácilmente después" + "NO_APPS": { + "TITLE": "No se han encontrado aplicaciones", + "SUBTITLE": "Cree una nueva aplicación que desee encontrar fácilmente después" + }, + "ERROR": { + "TITLE": "Se ha producido un error", + "SUBTITLE": "Compruebe que dispone de permiso de acceso a las aplicaciones" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Asignado a", "CANDIDATE_GROUP": "Grupo de candidatos", "FORM": "Formulario", - "DATE": "Elegir fecha" + "DATE": "Elegir fecha", + "NONE": "Ninguno" }, "ACTION": { "START": "Comenzar", @@ -76,7 +83,8 @@ "PRIORITY": "Prioridad", "CREATED_DATE": "Fecha de creación", "LAST_MODIFIED": "Modificada por última vez", - "CREATED": "Creado" + "CREATED": "Creado", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Nombre de aplicación", + "TASK_ID": "ID de tarea", "PROCESS_DEF_ID": "ID de definición de proceso", "STATUS": "Estado", "ASSIGNMENT": "Asignado a", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Pedir", - "UNCLAIM": "Volver a poner en cola" + "RELEASE": "Liberar" }, "PROPERTIES": { "TASK_NAME": "Tarea", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Nombre", + "NAME_DEFAULT": "Sin nombre", "DESCRIPTION": "Descripción", "DESCRIPTION_DEFAULT": "Sin descripción", "STATUS": "Estado", @@ -219,5 +229,17 @@ "PARENT_ID": "ID de elemento primario", "NONE": "Ninguno" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Sin formulario disponible", + "SUBTITLE": "Adjunte un formulario que pueda verse más tarde", + "BUTTONS": { + "COMPLETE": "Completar", + "CANCEL": "Cancelar", + "CLAIM": "Pedir", + "UNCLAIM": "Liberar" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/fi.json b/lib/process-services-cloud/src/lib/i18n/fi.json new file mode 100644 index 0000000000..0a9c09ba41 --- /dev/null +++ b/lib/process-services-cloud/src/lib/i18n/fi.json @@ -0,0 +1,245 @@ +{ + "ADF_CLOUD_PROCESS_LIST": { + "MESSAGES": { + "TITLE": "Yhtään prosessia ei löydy", + "SUBTITLE": "Luo uusi prosessi, jonka löydät helposti myöhemmin", + "NONE": "Prosessiesiintymäsuodatinta ei ole valittu." + }, + "PROPERTIES": { + "NAME": "Nimi", + "CREATED": "Luotu", + "STATUS": "Tila", + "START_DATE": "Alkamispäivä", + "ID": "Tunnus", + "INITIATOR": "Käynnistäjä", + "APP_NAME": "Sovelluksen nimi", + "BUSINESS_KEY": "Liiketoiminta-avain", + "DESCRIPTION": "Kuvaus", + "LAST_MODIFIED": "Muokattu viimeksi", + "PROCESS_NAME": "Prosessin nimi", + "PARENT_TASK_ID": "Ylätason tehtävän tunnus", + "PROCESS_DEF_ID": "Prosessimääritelmätunnus", + "PROCESS_DEF_KEY": "Prosessimääritelmäavain" + }, + "ADF_CLOUD_START_PROCESS": { + "BUTTON": "Käynnistä prosessi", + "NO_PROCESS_DEFINITIONS": "Et voi käynnistää prosessia, koska prosessimääritelmiä ei ole saatavilla", + "FORM": { + "TITLE": "Käynnistä prosessi", + "LABEL": { + "TYPE": "Valitse prosessi", + "NAME": "Prosessin nimi" + }, + "TYPE_PLACEHOLDER": "Valitse yksi...", + "ACTION": { + "START": "Käynnistä prosessi", + "CANCEL": "Peruuta" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Prosessimääritelmien lataaminen ei onnistu. Tarkista, että sinulla on tarvittavat oikeudet.", + "START": "Uuden prosessiesiintymän käynnistäminen ei onnistu. Tarkista, että sinulla on tarvittavat oikeudet.", + "PROCESS_NAME_REQUIRED": "Prosessin nimi on pakollinen", + "PROCESS_DEFINITION_REQUIRED": "Prosessimääritelmä on pakollinen", + "MAXIMUM_LENGTH": "Liian pitkä: voit käyttää enintään {{characters}} merkkiä." + } + } + }, + "ADF_CLOUD_TASK_LIST": { + "APPS": { + "NO_APPS": { + "TITLE": "Yhtään sovellusta ei löydy", + "SUBTITLE": "Luo uusi sovellus, jonka löydät helposti myöhemmin" + }, + "ERROR": { + "TITLE": "Tapahtui virhe", + "SUBTITLE": "Tarkista, että sinulla on oikeus käyttää sovelluksia" + } + }, + "START_TASK": { + "FORM": { + "TITLE": "Aloita tehtävä", + "LABEL": { + "NAME": "Nimi", + "DESCRIPTION": "Kuvaus", + "ATTACHFORM": "Liitä lomake", + "ASSIGNEE": "Vastuuhenkilö", + "CANDIDATE_GROUP": "Kandidaattiryhmä", + "FORM": "Lomake", + "DATE": "Valitse päivämäärä", + "NONE": "Ei mitään" + }, + "ACTION": { + "START": "Aloita", + "CANCEL": "Peruuta" + } + } + }, + "PROPERTIES": { + "NAME": "Nimi", + "ASSIGNEE": "Vastuuhenkilö", + "ID": "Tunnus", + "STATUS": "Tila", + "PRIORITY": "Prioriteetti", + "CREATED_DATE": "Luontipäivämäärä", + "LAST_MODIFIED": "Muokattu viimeksi", + "CREATED": "Luotu", + "JSON_CELL": "Json" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Yhtään tehtävää ei löydy", + "SUBTITLE": "Luo uusi tehtävä, jonka löydät helposti myöhemmin", + "NONE": "Yhtään tehtäväluetteloa ei löydy" + } + } + }, + "ADF_CLOUD_TASK_FILTERS": { + "MY_TASKS": "Omat tehtävät", + "COMPLETED_TASKS": "Suoritetut tehtävät" + }, + "ADF_CLOUD_PROCESS_FILTERS": { + "ALL_PROCESSES": "Kaikki prosessit", + "RUNNING_PROCESSES": "Käynnissä olevat prosessit", + "COMPLETED_PROCESSES": "Suoritetut prosessit" + }, + "ADF_CLOUD_START_TASK": { + "ERROR": { + "MESSAGE": "Anna toinen arvo", + "REQUIRED": "Pakollinen kenttä", + "DATE": "Päivämäärämuoto: PP/KK/VVVV", + "MAXIMUM_LENGTH": "Liian pitkä: voit käyttää enintään {{characters}} merkkiä." + } + }, + "ADF_CLOUD_EDIT_TASK_FILTER": { + "TITLE": "Muokkaa suodatinta", + "TOOL_TIP": { + "SAVE": "Tallenna suodatin", + "SAVE_AS": "Tallenna suodatin nimellä", + "DELETE": "Poista suodatin" + }, + "LABEL": { + "APP_NAME": "Sovelluksen nimi", + "TASK_ID": "Tehtävätunnus", + "PROCESS_DEF_ID": "Prosessimääritelmätunnus", + "STATUS": "Tila", + "ASSIGNMENT": "Vastuuhenkilö", + "DIRECTION": "Suunta", + "PROCESS_INSTANCE_ID": "Prosessiesiintymätunnus", + "TASK_NAME": "Tehtävän nimi", + "PARENT_TASK_ID": "Ylätason tehtävän tunnus", + "PRIORITY": "Prioriteetti", + "STAND_ALONE": "Erillinen", + "LAST_MODIFIED_FROM": "Muokattu viimeksi kohteesta", + "LAST_MODIFIED_TO": "Muokattu viimeksi kohteeseen", + "OWNER": "Omistaja", + "DUE_DATE": "Määräpäivä", + "SORT": "Lajittele", + "START_DATE": "Alkamispäivä" + }, + "DIALOG": { + "TITLE": "Tallenna suodatin nimellä", + "SAVE": "Tallenna", + "CANCEL": "Peruuta" + } + }, + "ADF_CLOUD_EDIT_PROCESS_FILTER": { + "TITLE": "Muokkaa suodatinta", + "LABEL": { + "APP_NAME": "Sovelluksen nimi", + "PROCESS_INS_ID": "Prosessiesiintymätunnus", + "STATUS": "Tila", + "INITIATOR": "Käynnistäjä", + "ASSIGNMENT": "Vastuuhenkilö", + "SORT": "Lajittele", + "DIRECTION": "Suunta", + "PROCESS_DEF_ID": "Prosessimääritelmätunnus", + "PROCESS_DEF_KEY": "Prosessimääritelmäavain", + "LAST_MODIFIED": "Muokattu viimeksi", + "LAST_MODIFIED_DATE_FORM": "Muokattu viimeksi kohteesta", + "LAST_MODIFIED_TO": "Muokattu viimeksi kohteeseen", + "PROCESS_NAME": "Prosessin nimi" + }, + "ERROR": { + "DATE": "Päivämäärämuoto: PP/KK/VVVV" + }, + "TOOL_TIP": { + "SAVE": "Tallenna suodatin", + "SAVE_AS": "Tallenna suodatin nimellä", + "DELETE": "Poista suodatin" + }, + "DIALOG": { + "TITLE": "Tallenna suodatin nimellä", + "SAVE": "Tallenna", + "CANCEL": "Peruuta" + } + }, + "ADF_CLOUD_GROUPS": { + "SEARCH-GROUP": "Ryhmät", + "ERROR": { + "NOT_FOUND": "Nimellä {{groupName}} ei löydy ryhmää" + } + }, + "ADF_CLOUD_TASK_HEADER": { + "BUTTON": { + "CLAIM": "Varaa", + "RELEASE": "Vapauta" + }, + "PROPERTIES": { + "TASK_NAME": "Tehtävä", + "THUMBNAIL": "Pikkukuva", + "DURATION": "Kesto", + "PARENT_TASK_ID": "Ylätason tehtävän tunnus", + "NAME": "Nimi", + "ASSIGNEE": "Vastuuhenkilö", + "ASSIGNEE_DEFAULT": "Ei vastuuhenkilöä", + "PRIORITY": "Prioriteetti", + "DUE_DATE": "Määräpäivä", + "DUE_DATE_DEFAULT": "Ei päivämäärää", + "STATUS": "Tila", + "CATEGORY": "Luokka", + "CATEGORY_DEFAULT": "Ei luokkaa", + "PARENT_NAME": "Ylätason nimi", + "PARENT_NAME_DEFAULT": "Ei ylätasoa", + "CREATED_BY": "Tekijä:", + "CREATED": "Luotu", + "END_DATE": "Päättymispäivä", + "ID": "Tunnus", + "DESCRIPTION": "Kuvaus", + "DESCRIPTION_DEFAULT": "Ei kuvausta", + "FORM_NAME": "Lomakkeen nimi", + "FORM_NAME_DEFAULT": "Ei lomaketta" + }, + "FORM_VALIDATION": { + "INVALID_FIELD": "Anna toinen arvo" + } + }, + "ADF_CLOUD_PROCESS_HEADER": { + "PROPERTIES": { + "ID": "Tunnus", + "NAME": "Nimi", + "NAME_DEFAULT": "Ei nimeä", + "DESCRIPTION": "Kuvaus", + "DESCRIPTION_DEFAULT": "Ei kuvausta", + "STATUS": "Tila", + "BUSINESS_KEY": "Liiketoiminta-avain", + "INITIATOR": "Käynnistäjä", + "START_DATE": "Alkamispäivä", + "LAST_MODIFIED": "Muokattu viimeksi", + "PARENT_ID": "Ylätason tunnus", + "NONE": "Ei mitään" + } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Ei lomaketta käytettävissä", + "SUBTITLE": "Liitä lomake, jota voi tarkastella myöhemmin", + "BUTTONS": { + "COMPLETE": "Merkitse valmiiksi", + "CANCEL": "Peruuta", + "CLAIM": "Varaa", + "UNCLAIM": "Vapauta" + } + } + } +} \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/fr.json b/lib/process-services-cloud/src/lib/i18n/fr.json index 559744181e..11b51cae49 100644 --- a/lib/process-services-cloud/src/lib/i18n/fr.json +++ b/lib/process-services-cloud/src/lib/i18n/fr.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Aucune application trouvée", - "SUBTITLE": "Créer une nouvelle application à laquelle vous pourrez accéder facilement par la suite" + "NO_APPS": { + "TITLE": "Aucune application trouvée", + "SUBTITLE": "Créer une nouvelle application à laquelle vous pourrez accéder facilement par la suite" + }, + "ERROR": { + "TITLE": "Une erreur est survenue", + "SUBTITLE": "Vérifiez que vous avez les droits d'accès aux applications" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Personne assignée", "CANDIDATE_GROUP": "Groupe de candidats", "FORM": "Formulaire", - "DATE": "Choisir la date" + "DATE": "Choisir la date", + "NONE": "Aucun" }, "ACTION": { "START": "Démarrer", @@ -76,7 +83,8 @@ "PRIORITY": "Priorité", "CREATED_DATE": "Date de création", "LAST_MODIFIED": "Dernière modification", - "CREATED": "Créé" + "CREATED": "Créé", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Nom de l'application", + "TASK_ID": "ID de la tâche", "PROCESS_DEF_ID": "ID de la définition du processus", "STATUS": "Statut", "ASSIGNMENT": "Personne assignée", @@ -173,8 +182,8 @@ }, "ADF_CLOUD_TASK_HEADER": { "BUTTON": { - "CLAIM": "Se l'attribuer", - "UNCLAIM": "Replacer dans la file d'attente" + "CLAIM": "S'attribuer", + "RELEASE": "Libérer" }, "PROPERTIES": { "TASK_NAME": "Tâche", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Nom", + "NAME_DEFAULT": "Aucun nom", "DESCRIPTION": "Description", "DESCRIPTION_DEFAULT": "Aucune description", "STATUS": "Statut", @@ -219,5 +229,17 @@ "PARENT_ID": "ID parent", "NONE": "Aucune" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Aucun formulaire disponible", + "SUBTITLE": "Joindre un formulaire qui pourra être consulté ultérieurement", + "BUTTONS": { + "COMPLETE": "Terminer", + "CANCEL": "Annuler", + "CLAIM": "S'attribuer", + "UNCLAIM": "Libérer" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/it.json b/lib/process-services-cloud/src/lib/i18n/it.json index a4696b2987..fa61df399f 100644 --- a/lib/process-services-cloud/src/lib/i18n/it.json +++ b/lib/process-services-cloud/src/lib/i18n/it.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Nessuna applicazione trovata", - "SUBTITLE": "Creare una nuova applicazione per trovarla facilmente più tardi" + "NO_APPS": { + "TITLE": "Nessuna applicazione trovata", + "SUBTITLE": "Creare una nuova applicazione per trovarla facilmente più tardi" + }, + "ERROR": { + "TITLE": "Si è verificato un errore", + "SUBTITLE": "Verificare di disporre dei permessi per accedere alle app" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Assegnatario", "CANDIDATE_GROUP": "Gruppo candidati", "FORM": "Modulo", - "DATE": "Seleziona data" + "DATE": "Seleziona data", + "NONE": "Nessuno" }, "ACTION": { "START": "Avvia", @@ -76,7 +83,8 @@ "PRIORITY": "Priorità", "CREATED_DATE": "Data di creazione", "LAST_MODIFIED": "Ultima modifica", - "CREATED": "Creato" + "CREATED": "Creato", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Nome applicazione", + "TASK_ID": "ID compito", "PROCESS_DEF_ID": "ID definizione processo", "STATUS": "Stato", "ASSIGNMENT": "Assegnatario", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Richiedi", - "UNCLAIM": "Metti di nuovo in coda" + "RELEASE": "Restituisci" }, "PROPERTIES": { "TASK_NAME": "Compito", @@ -202,13 +211,14 @@ "FORM_NAME_DEFAULT": "Nessun modulo" }, "FORM_VALIDATION": { - "INVALID_FIELD": "Inserire un altro valore" + "INVALID_FIELD": "Immettere un altro valore" } }, "ADF_CLOUD_PROCESS_HEADER": { "PROPERTIES": { "ID": "ID", "NAME": "Nome", + "NAME_DEFAULT": "Nessun nome", "DESCRIPTION": "Descrizione", "DESCRIPTION_DEFAULT": "Nessuna descrizione", "STATUS": "Stato", @@ -219,5 +229,17 @@ "PARENT_ID": "ID principale", "NONE": "Nessuno" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Nessun modulo disponibile", + "SUBTITLE": "Allegare un modulo da visualizzare più tardi", + "BUTTONS": { + "COMPLETE": "Completa", + "CANCEL": "Annulla", + "CLAIM": "Richiedi", + "UNCLAIM": "Restituisci" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/ja.json b/lib/process-services-cloud/src/lib/i18n/ja.json index 113df3acd5..aeacfe3745 100644 --- a/lib/process-services-cloud/src/lib/i18n/ja.json +++ b/lib/process-services-cloud/src/lib/i18n/ja.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "アプリケーションが見つかりません", - "SUBTITLE": "後で簡単に見つけられるよう、新しいアプリケーションを作成してください" + "NO_APPS": { + "TITLE": "アプリケーションが見つかりません", + "SUBTITLE": "後で簡単に見つけられるよう、新しいアプリケーションを作成してください" + }, + "ERROR": { + "TITLE": "エラーが発生しました", + "SUBTITLE": "アプリケーションにアクセスする権限があることを確認してください" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "担当者", "CANDIDATE_GROUP": "候補グループ", "FORM": "フォーム", - "DATE": "日付の選択" + "DATE": "日付の選択", + "NONE": "なし" }, "ACTION": { "START": "開始", @@ -76,7 +83,8 @@ "PRIORITY": "優先度", "CREATED_DATE": "作成日", "LAST_MODIFIED": "最終更新日時", - "CREATED": "作成日" + "CREATED": "作成日", + "JSON_CELL": "JSON" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "アプリケーション名", + "TASK_ID": "タスク ID", "PROCESS_DEF_ID": "プロセス定義 ID", "STATUS": "ステータス", "ASSIGNMENT": "担当者", @@ -173,8 +182,8 @@ }, "ADF_CLOUD_TASK_HEADER": { "BUTTON": { - "CLAIM": "要求", - "UNCLAIM": "キューへ戻す" + "CLAIM": "担当する", + "RELEASE": "担当解除" }, "PROPERTIES": { "TASK_NAME": "タスク", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "名前", + "NAME_DEFAULT": "名前なし", "DESCRIPTION": "説明", "DESCRIPTION_DEFAULT": "説明なし", "STATUS": "ステータス", @@ -219,5 +229,17 @@ "PARENT_ID": "親 ID", "NONE": "なし" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "使用可能なフォームがありません", + "SUBTITLE": "後で表示できるフォームを添付してください", + "BUTTONS": { + "COMPLETE": "完了", + "CANCEL": "キャンセル", + "CLAIM": "担当する", + "UNCLAIM": "担当解除" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/nb.json b/lib/process-services-cloud/src/lib/i18n/nb.json index 84bd3bca29..0f85d24224 100644 --- a/lib/process-services-cloud/src/lib/i18n/nb.json +++ b/lib/process-services-cloud/src/lib/i18n/nb.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Ingen applikasjoner funnet", - "SUBTITLE": "Opprett en ny applikasjon som er lett å finne senere" + "NO_APPS": { + "TITLE": "Ingen applikasjoner funnet", + "SUBTITLE": "Opprett en ny applikasjon som er lett å finne senere" + }, + "ERROR": { + "TITLE": "Det oppstod en feil", + "SUBTITLE": "Sjekk at du har tillatelse til å gå inn i appene" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Tilordnet", "CANDIDATE_GROUP": "Kandidatgruppe", "FORM": "Skjema", - "DATE": "Velg dato" + "DATE": "Velg dato", + "NONE": "Ingen" }, "ACTION": { "START": "Start", @@ -76,7 +83,8 @@ "PRIORITY": "Prioritet", "CREATED_DATE": "Opprettelsesdato", "LAST_MODIFIED": "Sist endret", - "CREATED": "Opprettet" + "CREATED": "Opprettet", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Programnavn", + "TASK_ID": "Oppgave-ID", "PROCESS_DEF_ID": "Prosessdefinisjons-ID", "STATUS": "Status", "ASSIGNMENT": "Tilordnet", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Krev", - "UNCLAIM": "Legg tilbake i kø" + "RELEASE": "Frigi" }, "PROPERTIES": { "TASK_NAME": "Oppgave", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Navn", + "NAME_DEFAULT": "Uten navn", "DESCRIPTION": "Beskrivelse", "DESCRIPTION_DEFAULT": "Ingen beskrivelse", "STATUS": "Status", @@ -219,5 +229,17 @@ "PARENT_ID": "Overordnet ID", "NONE": "Ingen" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Skjema ikke tilgjengelig", + "SUBTITLE": "Legg til et skjema som kan vises senere", + "BUTTONS": { + "COMPLETE": "Fullfør", + "CANCEL": "Avbryt", + "CLAIM": "Krev", + "UNCLAIM": "Frigi" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/nl.json b/lib/process-services-cloud/src/lib/i18n/nl.json index df48c94202..c5a203d3da 100644 --- a/lib/process-services-cloud/src/lib/i18n/nl.json +++ b/lib/process-services-cloud/src/lib/i18n/nl.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Geen toepassingen gevonden", - "SUBTITLE": "Maak een nieuwe toepassing die u later gemakkelijk wilt kunnen vinden" + "NO_APPS": { + "TITLE": "Geen toepassingen gevonden", + "SUBTITLE": "Maak een nieuwe toepassing die u later gemakkelijk wilt kunnen vinden" + }, + "ERROR": { + "TITLE": "Er is een fout opgetreden", + "SUBTITLE": "Controleer of u machtiging hebt voor toegang tot de apps" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Toegewezen persoon", "CANDIDATE_GROUP": "Kandidaatgroep", "FORM": "Formulier", - "DATE": "Datum kiezen" + "DATE": "Datum kiezen", + "NONE": "Geen" }, "ACTION": { "START": "Start", @@ -76,7 +83,8 @@ "PRIORITY": "Prioriteit", "CREATED_DATE": "Datum gemaakt", "LAST_MODIFIED": "Laatst gewijzigd", - "CREATED": "Gemaakt" + "CREATED": "Gemaakt", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Toepassingsnaam", + "TASK_ID": "Taak-ID", "PROCESS_DEF_ID": "Procesdefinitie-id", "STATUS": "Status", "ASSIGNMENT": "Toegewezen persoon", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Claimen", - "UNCLAIM": "Opnieuw in wachtrij plaatsen" + "RELEASE": "Vrijgeven" }, "PROPERTIES": { "TASK_NAME": "Taak", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Naam", + "NAME_DEFAULT": "Geen naam", "DESCRIPTION": "Beschrijving", "DESCRIPTION_DEFAULT": "Geen beschrijving", "STATUS": "Status", @@ -219,5 +229,17 @@ "PARENT_ID": "Bovenliggende ID", "NONE": "Geen" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Geen formulier beschikbaar", + "SUBTITLE": "Voeg een formulier bij dat later kan worden weergegeven", + "BUTTONS": { + "COMPLETE": "Voltooid", + "CANCEL": "Annuleren", + "CLAIM": "Claimen", + "UNCLAIM": "Vrijgeven" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/pl.json b/lib/process-services-cloud/src/lib/i18n/pl.json new file mode 100644 index 0000000000..6bffd0922e --- /dev/null +++ b/lib/process-services-cloud/src/lib/i18n/pl.json @@ -0,0 +1,245 @@ +{ + "ADF_CLOUD_PROCESS_LIST": { + "MESSAGES": { + "TITLE": "Nie znaleziono żadnego procesu.", + "SUBTITLE": "Utwórz nowy proces, który później będzie łatwo znaleźć.", + "NONE": "Nie wybrano filtra wystąpień procesu." + }, + "PROPERTIES": { + "NAME": "Nazwa", + "CREATED": "Utworzono", + "STATUS": "Status", + "START_DATE": "Data rozpoczęcia", + "ID": "Identyfikator", + "INITIATOR": "Inicjator", + "APP_NAME": "Nazwa aplikacji", + "BUSINESS_KEY": "Klucz biznesowy", + "DESCRIPTION": "Opis", + "LAST_MODIFIED": "Ostatnia modyfikacja", + "PROCESS_NAME": "Nazwa procesu", + "PARENT_TASK_ID": "Identyfikator zadania nadrzędnego", + "PROCESS_DEF_ID": "Identyfikator definicji procesu", + "PROCESS_DEF_KEY": "Klucz definicji procesu" + }, + "ADF_CLOUD_START_PROCESS": { + "BUTTON": "Rozpocznij proces", + "NO_PROCESS_DEFINITIONS": "Nie można rozpocząć procesu, ponieważ brak dostępnych definicji procesu.", + "FORM": { + "TITLE": "Rozpocznij proces", + "LABEL": { + "TYPE": "Wybierz proces", + "NAME": "Nazwa procesu" + }, + "TYPE_PLACEHOLDER": "Wybierz jeden...", + "ACTION": { + "START": "Rozpocznij proces", + "CANCEL": "Anuluj" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Nie można wczytać definicji procesu. Sprawdź, czy masz dostęp.", + "START": "Nie można rozpocząć nowego wystąpienia procesu. Sprawdź, czy masz dostęp.", + "PROCESS_NAME_REQUIRED": "Nazwa procesu jest wymagana", + "PROCESS_DEFINITION_REQUIRED": "Definicja procesu jest wymagana", + "MAXIMUM_LENGTH": "Przekroczono długość, maksymalna długość wynosi {{characters}} znaków" + } + } + }, + "ADF_CLOUD_TASK_LIST": { + "APPS": { + "NO_APPS": { + "TITLE": "Nie znaleziono aplikacji.", + "SUBTITLE": "Utwórz nową aplikację, którą później będzie łatwo znaleźć." + }, + "ERROR": { + "TITLE": "Wystąpił błąd", + "SUBTITLE": "Sprawdź, czy masz uprawnienie dostępu do aplikacji" + } + }, + "START_TASK": { + "FORM": { + "TITLE": "Rozpocznij zadanie", + "LABEL": { + "NAME": "Nazwa", + "DESCRIPTION": "Opis", + "ATTACHFORM": "Załącz formularz", + "ASSIGNEE": "Osoba przypisana", + "CANDIDATE_GROUP": "Grupa kandydatów", + "FORM": "Formularz", + "DATE": "Wybierz datę", + "NONE": "Brak" + }, + "ACTION": { + "START": "Uruchom", + "CANCEL": "Anuluj" + } + } + }, + "PROPERTIES": { + "NAME": "Nazwa", + "ASSIGNEE": "Osoba przypisana", + "ID": "Identyfikator", + "STATUS": "Status", + "PRIORITY": "Priorytet", + "CREATED_DATE": "Data utworzenia", + "LAST_MODIFIED": "Ostatnia modyfikacja", + "CREATED": "Utworzono", + "JSON_CELL": "Json" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Nie znaleziono zadań.", + "SUBTITLE": "Utwórz nowe zadanie, które później będzie łatwo znaleźć.", + "NONE": "Nie znaleziono list zadań." + } + } + }, + "ADF_CLOUD_TASK_FILTERS": { + "MY_TASKS": "Moje zadania", + "COMPLETED_TASKS": "Ukończone zadania" + }, + "ADF_CLOUD_PROCESS_FILTERS": { + "ALL_PROCESSES": "Wszystkie procesy", + "RUNNING_PROCESSES": "Uruchomione procesy", + "COMPLETED_PROCESSES": "Zakończone procesy" + }, + "ADF_CLOUD_START_TASK": { + "ERROR": { + "MESSAGE": "Wprowadź inną wartość.", + "REQUIRED": "Pole wymagane", + "DATE": "Format daty DD/MM/RRRR", + "MAXIMUM_LENGTH": "Przekroczono długość, maksymalna długość wynosi {{characters}} znaków" + } + }, + "ADF_CLOUD_EDIT_TASK_FILTER": { + "TITLE": "Dostosuj swój filtr", + "TOOL_TIP": { + "SAVE": "Zapisz filtr", + "SAVE_AS": "Zapisz filtr jako", + "DELETE": "Usuń filtr" + }, + "LABEL": { + "APP_NAME": "Nazwa aplikacji", + "TASK_ID": "Identyfikator zadania", + "PROCESS_DEF_ID": "Identyfikator definicji procesu", + "STATUS": "Status", + "ASSIGNMENT": "Osoba przypisana", + "DIRECTION": "Kolejność", + "PROCESS_INSTANCE_ID": "Identyfikator wystąpienia procesu", + "TASK_NAME": "Nazwa zadania", + "PARENT_TASK_ID": "Identyfikator zadania nadrzędnego", + "PRIORITY": "Priorytet", + "STAND_ALONE": "Autonomiczne", + "LAST_MODIFIED_FROM": "Ostatnia modyfikacja - od", + "LAST_MODIFIED_TO": "Ostatnia modyfikacja - do", + "OWNER": "Właściciel", + "DUE_DATE": "Data ukończenia", + "SORT": "Sortuj", + "START_DATE": "Data rozpoczęcia" + }, + "DIALOG": { + "TITLE": "Zapisz filtr jako", + "SAVE": "Zapisz", + "CANCEL": "Anuluj" + } + }, + "ADF_CLOUD_EDIT_PROCESS_FILTER": { + "TITLE": "Dostosuj swój filtr", + "LABEL": { + "APP_NAME": "Nazwa aplikacji", + "PROCESS_INS_ID": "Identyfikator wystąpienia procesu", + "STATUS": "Status", + "INITIATOR": "Inicjator", + "ASSIGNMENT": "Osoba przypisana", + "SORT": "Sortuj", + "DIRECTION": "Kolejność", + "PROCESS_DEF_ID": "Identyfikator definicji procesu", + "PROCESS_DEF_KEY": "Klucz definicji procesu", + "LAST_MODIFIED": "Ostatnia modyfikacja", + "LAST_MODIFIED_DATE_FORM": "Ostatnia modyfikacja - od", + "LAST_MODIFIED_TO": "Ostatnia modyfikacja - do", + "PROCESS_NAME": "Nazwa procesu" + }, + "ERROR": { + "DATE": "Format daty DD/MM/RRRR" + }, + "TOOL_TIP": { + "SAVE": "Zapisz filtr", + "SAVE_AS": "Zapisz filtr jako", + "DELETE": "Usuń filtr" + }, + "DIALOG": { + "TITLE": "Zapisz filtr jako", + "SAVE": "Zapisz", + "CANCEL": "Anuluj" + } + }, + "ADF_CLOUD_GROUPS": { + "SEARCH-GROUP": "Grupy", + "ERROR": { + "NOT_FOUND": "Nie znaleziono grupy o nazwie {{groupName}}" + } + }, + "ADF_CLOUD_TASK_HEADER": { + "BUTTON": { + "CLAIM": "Przejmij", + "RELEASE": "Zwolnij" + }, + "PROPERTIES": { + "TASK_NAME": "Zadanie", + "THUMBNAIL": "Miniatura", + "DURATION": "Czas trwania", + "PARENT_TASK_ID": "Identyfikator zadania nadrzędnego", + "NAME": "Nazwa", + "ASSIGNEE": "Osoba przypisana", + "ASSIGNEE_DEFAULT": "Brak osoby przypisanej", + "PRIORITY": "Priorytet", + "DUE_DATE": "Data ukończenia", + "DUE_DATE_DEFAULT": "Brak daty", + "STATUS": "Status", + "CATEGORY": "Kategoria", + "CATEGORY_DEFAULT": "Brak kategorii", + "PARENT_NAME": "Nazwa obiektu nadrzędnego", + "PARENT_NAME_DEFAULT": "Brak obiektu nadrzędnego", + "CREATED_BY": "Utworzone przez", + "CREATED": "Utworzono", + "END_DATE": "Data zakończenia", + "ID": "Identyfikator", + "DESCRIPTION": "Opis", + "DESCRIPTION_DEFAULT": "Brak opisu", + "FORM_NAME": "Nazwa formularza", + "FORM_NAME_DEFAULT": "Brak formularza" + }, + "FORM_VALIDATION": { + "INVALID_FIELD": "Wprowadź inną wartość." + } + }, + "ADF_CLOUD_PROCESS_HEADER": { + "PROPERTIES": { + "ID": "Identyfikator", + "NAME": "Nazwa", + "NAME_DEFAULT": "Bez nazwy", + "DESCRIPTION": "Opis", + "DESCRIPTION_DEFAULT": "Brak opisu", + "STATUS": "Status", + "BUSINESS_KEY": "Klucz biznesowy", + "INITIATOR": "Inicjator", + "START_DATE": "Data rozpoczęcia", + "LAST_MODIFIED": "Ostatnia modyfikacja", + "PARENT_ID": "Identyfikator obiektu nadrzędnego", + "NONE": "Brak" + } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Brak dostępnego formularza", + "SUBTITLE": "Dołącz formularz do wyświetlania później", + "BUTTONS": { + "COMPLETE": "Zakończ", + "CANCEL": "Anuluj", + "CLAIM": "Przejmij", + "UNCLAIM": "Zwolnij" + } + } + } +} \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/pt-BR.json b/lib/process-services-cloud/src/lib/i18n/pt-BR.json index 06056649ae..0d0f8170dc 100644 --- a/lib/process-services-cloud/src/lib/i18n/pt-BR.json +++ b/lib/process-services-cloud/src/lib/i18n/pt-BR.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Nenhum Aplicativo Encontrado", - "SUBTITLE": "Crie um aplicativo que você possa identificar com facilidade depois" + "NO_APPS": { + "TITLE": "Nenhum Aplicativo Encontrado", + "SUBTITLE": "Crie um aplicativo que você possa identificar com facilidade depois" + }, + "ERROR": { + "TITLE": "Houve um erro", + "SUBTITLE": "Verifique se você tem permissão para acessar os aplicativos" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Destinatário", "CANDIDATE_GROUP": "Grupo de Candidato", "FORM": "Formulário", - "DATE": "Escolher Data" + "DATE": "Escolher Data", + "NONE": "Nenhum" }, "ACTION": { "START": "Iniciar", @@ -76,7 +83,8 @@ "PRIORITY": "Prioridade", "CREATED_DATE": "Data de criação", "LAST_MODIFIED": "Modificado por último", - "CREATED": "Criado" + "CREATED": "Criado", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Nome de aplicativo", + "TASK_ID": "ID de tarefa", "PROCESS_DEF_ID": "ID de Definição de Processo", "STATUS": "Status", "ASSIGNMENT": "Destinatário", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Reivindicar", - "UNCLAIM": "Recolocar na fila" + "RELEASE": "Liberar" }, "PROPERTIES": { "TASK_NAME": "Tarefa", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "Nome", + "NAME_DEFAULT": "Nenhum nome", "DESCRIPTION": "Descrição", "DESCRIPTION_DEFAULT": "Nenhuma descrição", "STATUS": "Status", @@ -219,5 +229,17 @@ "PARENT_ID": "ID primária", "NONE": "Nenhum" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Nenhum formulário disponível", + "SUBTITLE": "Anexe um formulário que possa ser visualizado mais tarde", + "BUTTONS": { + "COMPLETE": "Completar", + "CANCEL": "Cancelar", + "CLAIM": "Reivindicar", + "UNCLAIM": "Liberar" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/ru.json b/lib/process-services-cloud/src/lib/i18n/ru.json index 5e8f798e42..b3f2d4823e 100644 --- a/lib/process-services-cloud/src/lib/i18n/ru.json +++ b/lib/process-services-cloud/src/lib/i18n/ru.json @@ -17,22 +17,22 @@ "DESCRIPTION": "Описание", "LAST_MODIFIED": "Дата последнего изменения", "PROCESS_NAME": "Имя процесса", - "PARENT_TASK_ID": "Идентификатор родительской задачи", + "PARENT_TASK_ID": "Идентификатор родительского задания", "PROCESS_DEF_ID": "Идентификатор определения процесса", "PROCESS_DEF_KEY": "Ключ определения процесса" }, "ADF_CLOUD_START_PROCESS": { - "BUTTON": "Запуск процесса", + "BUTTON": "Начать процесс", "NO_PROCESS_DEFINITIONS": "Невозможно начать процесс, поскольку нет определений процесса", "FORM": { - "TITLE": "Запуск процесса", + "TITLE": "Начать процесс", "LABEL": { "TYPE": "Выбрать процесс", "NAME": "Имя процесса" }, "TYPE_PLACEHOLDER": "Выбрать элемент...", "ACTION": { - "START": "Запуск процесса", + "START": "Начать процесс", "CANCEL": "Отмена" } }, @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "Приложения не найдены", - "SUBTITLE": "Создайте новое приложение, которое вы сможете легко найти позже" + "NO_APPS": { + "TITLE": "Приложения не найдены", + "SUBTITLE": "Создайте новое приложение, которое вы сможете легко найти позже" + }, + "ERROR": { + "TITLE": "Произошла ошибка", + "SUBTITLE": "Убедитесь, что у вас есть разрешение на доступ к приложениям" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "Исполнитель", "CANDIDATE_GROUP": "Группа-кандидат", "FORM": "Форма", - "DATE": "Выбрать дату" + "DATE": "Выбрать дату", + "NONE": "Нет" }, "ACTION": { "START": "Начать", @@ -76,7 +83,8 @@ "PRIORITY": "Приоритет", "CREATED_DATE": "Дата создания", "LAST_MODIFIED": "Дата последнего изменения", - "CREATED": "Создано" + "CREATED": "Создано", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -100,7 +108,7 @@ "MESSAGE": "Введите другое значение", "REQUIRED": "Обязательное поле", "DATE": "Формат даты ДД.ММ.ГГГГ", - "MAXIMUM_LENGTH": "Превышение длины, макс. символов: {{characters}}." + "MAXIMUM_LENGTH": "Превышение длины, макс. символов: {{characters}}" } }, "ADF_CLOUD_EDIT_TASK_FILTER": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "Название приложения", + "TASK_ID": "ИД задачи", "PROCESS_DEF_ID": "Идентификатор определения процесса", "STATUS": "Статус", "ASSIGNMENT": "Исполнитель", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "Принять", - "UNCLAIM": "Повторно поставить в очередь" + "RELEASE": "Освободить" }, "PROPERTIES": { "TASK_NAME": "Задача", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "Идентификатор", "NAME": "Имя", + "NAME_DEFAULT": "Нет имени", "DESCRIPTION": "Описание", "DESCRIPTION_DEFAULT": "Нет описания", "STATUS": "Статус", @@ -219,5 +229,17 @@ "PARENT_ID": "ID родителя", "NONE": "Нет" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Нет доступных форм", + "SUBTITLE": "Прикрепите форму для дальнейшего просмотра", + "BUTTONS": { + "COMPLETE": "Завершить", + "CANCEL": "Отмена", + "CLAIM": "Принять", + "UNCLAIM": "Освободить" + } + } } } \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/sv.json b/lib/process-services-cloud/src/lib/i18n/sv.json new file mode 100644 index 0000000000..66ab0035f3 --- /dev/null +++ b/lib/process-services-cloud/src/lib/i18n/sv.json @@ -0,0 +1,245 @@ +{ + "ADF_CLOUD_PROCESS_LIST": { + "MESSAGES": { + "TITLE": "Inga processer hittades", + "SUBTITLE": "Skapa en ny proces som du enkelt hittar senare", + "NONE": "Inget processinstansfilter valt" + }, + "PROPERTIES": { + "NAME": "Namn", + "CREATED": "Skapad", + "STATUS": "Status", + "START_DATE": "Startdatum", + "ID": "ID", + "INITIATOR": "Initerare", + "APP_NAME": "Programnamn", + "BUSINESS_KEY": "Affärsnyckel", + "DESCRIPTION": "Beskrivning", + "LAST_MODIFIED": "Senast ändrad", + "PROCESS_NAME": "Processnamn", + "PARENT_TASK_ID": "Föräldrauppgifts-ID", + "PROCESS_DEF_ID": "Processdefinition", + "PROCESS_DEF_KEY": "Processdefinition" + }, + "ADF_CLOUD_START_PROCESS": { + "BUTTON": "Starta process", + "NO_PROCESS_DEFINITIONS": "Du kan inte starta en process eftersom inga processdefinitioner är tillgängliga", + "FORM": { + "TITLE": "Starta process", + "LABEL": { + "TYPE": "Välj process", + "NAME": "Processnamn" + }, + "TYPE_PLACEHOLDER": "Välj en...", + "ACTION": { + "START": "Starta process", + "CANCEL": "Avbryt" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Kunde inte läsa in processdefinitioner, kontrollera att du har åtkomst.", + "START": "Kunde inte starta ny processinstans, kontrollera att du har åtkomst.", + "PROCESS_NAME_REQUIRED": "Processnamn krävs", + "PROCESS_DEFINITION_REQUIRED": "Processdefinition krävs", + "MAXIMUM_LENGTH": "Längd överskriden, {{characters}} tecken max." + } + } + }, + "ADF_CLOUD_TASK_LIST": { + "APPS": { + "NO_APPS": { + "TITLE": "Inga program hittades", + "SUBTITLE": "Skapa ett nytt program som du enkelt hittar senare" + }, + "ERROR": { + "TITLE": "Ett fel uppstod", + "SUBTITLE": "Kontrollera att du har behörighet att öppna apparna" + } + }, + "START_TASK": { + "FORM": { + "TITLE": "Starta uppgift", + "LABEL": { + "NAME": "Namn", + "DESCRIPTION": "Beskrivning", + "ATTACHFORM": "Bifoga formulär", + "ASSIGNEE": "Tilldelad användare", + "CANDIDATE_GROUP": "Kandidatgrupp", + "FORM": "Formulär", + "DATE": "Välj datum", + "NONE": "Ingen" + }, + "ACTION": { + "START": "Starta", + "CANCEL": "Avbryt" + } + } + }, + "PROPERTIES": { + "NAME": "Namn", + "ASSIGNEE": "Tilldelad användare", + "ID": "ID", + "STATUS": "Status", + "PRIORITY": "Prioritet", + "CREATED_DATE": "Skapad datum", + "LAST_MODIFIED": "Senast ändrad", + "CREATED": "Skapad", + "JSON_CELL": "Json" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Inga uppgifter hittades", + "SUBTITLE": "Skapa en ny uppgift som du enkelt hittar senare", + "NONE": "Inga uppgiftslistor hittades" + } + } + }, + "ADF_CLOUD_TASK_FILTERS": { + "MY_TASKS": "Mina uppgifter", + "COMPLETED_TASKS": "Slutförda uppgifter" + }, + "ADF_CLOUD_PROCESS_FILTERS": { + "ALL_PROCESSES": "Alla processer", + "RUNNING_PROCESSES": "Köra processer", + "COMPLETED_PROCESSES": "Slutförda processer" + }, + "ADF_CLOUD_START_TASK": { + "ERROR": { + "MESSAGE": "Ange ett annat värde", + "REQUIRED": "Fält obligatoriskt", + "DATE": "Datumformat DD/MM/ÅÅÅÅ", + "MAXIMUM_LENGTH": "Längd överskriden, {{characters}} tecken max." + } + }, + "ADF_CLOUD_EDIT_TASK_FILTER": { + "TITLE": "Anpassa ditt filter", + "TOOL_TIP": { + "SAVE": "Spara filter", + "SAVE_AS": "Spara filter som", + "DELETE": "Radera filter" + }, + "LABEL": { + "APP_NAME": "ApplicationName", + "TASK_ID": "Uppgifts-ID", + "PROCESS_DEF_ID": "Processdefinitions-ID", + "STATUS": "Status", + "ASSIGNMENT": "Tilldelad användare", + "DIRECTION": "Riktning", + "PROCESS_INSTANCE_ID": "Processinstans-ID", + "TASK_NAME": "TaskName", + "PARENT_TASK_ID": "ParentTaskId", + "PRIORITY": "Prioritet", + "STAND_ALONE": "StandAlone", + "LAST_MODIFIED_FROM": "Senast modifierad från", + "LAST_MODIFIED_TO": "Senast modifierad till", + "OWNER": "Ägare", + "DUE_DATE": "Leveransdatum", + "SORT": "Sortera", + "START_DATE": "Startdatum" + }, + "DIALOG": { + "TITLE": "Spara filter som", + "SAVE": "Spara", + "CANCEL": "Avbryt" + } + }, + "ADF_CLOUD_EDIT_PROCESS_FILTER": { + "TITLE": "Anpassa ditt filter", + "LABEL": { + "APP_NAME": "ApplicationName", + "PROCESS_INS_ID": "Processinstans-ID", + "STATUS": "Status", + "INITIATOR": "Initerare", + "ASSIGNMENT": "Tilldelad användare", + "SORT": "Sortera", + "DIRECTION": "Riktning", + "PROCESS_DEF_ID": "Processdefinitions-ID", + "PROCESS_DEF_KEY": "Processdefinitionsnyckel", + "LAST_MODIFIED": "Senast modifierad", + "LAST_MODIFIED_DATE_FORM": "Senast modifierad från", + "LAST_MODIFIED_TO": "Senast modifierad till", + "PROCESS_NAME": "Processnamn" + }, + "ERROR": { + "DATE": "Datumformat DD/MM/ÅÅÅÅ" + }, + "TOOL_TIP": { + "SAVE": "Spara filter", + "SAVE_AS": "Spara filter som", + "DELETE": "Radera filter" + }, + "DIALOG": { + "TITLE": "Spara filter som", + "SAVE": "Spara", + "CANCEL": "Avbryt" + } + }, + "ADF_CLOUD_GROUPS": { + "SEARCH-GROUP": "Grupper", + "ERROR": { + "NOT_FOUND": "Ingen grupp med namnet {{groupName}} hittades" + } + }, + "ADF_CLOUD_TASK_HEADER": { + "BUTTON": { + "CLAIM": "Anta", + "RELEASE": "Avsäga" + }, + "PROPERTIES": { + "TASK_NAME": "Uppgift", + "THUMBNAIL": "Miniatyrbild", + "DURATION": "Varaktighet", + "PARENT_TASK_ID": "Föräldrauppgifts-ID", + "NAME": "Namn", + "ASSIGNEE": "Tilldelad användare", + "ASSIGNEE_DEFAULT": "Ingen tilldelad användare", + "PRIORITY": "Prioritet", + "DUE_DATE": "Förfallodatum", + "DUE_DATE_DEFAULT": "Inget datum", + "STATUS": "Status", + "CATEGORY": "Kategori", + "CATEGORY_DEFAULT": "Ingen kategori", + "PARENT_NAME": "Överordnad namn", + "PARENT_NAME_DEFAULT": "Ingen överordnad", + "CREATED_BY": "Skapad av", + "CREATED": "Skapad", + "END_DATE": "Slutdatum", + "ID": "ID", + "DESCRIPTION": "Beskrivning", + "DESCRIPTION_DEFAULT": "Ingen beskrivning", + "FORM_NAME": "Formulärnamn", + "FORM_NAME_DEFAULT": "Inget formulär" + }, + "FORM_VALIDATION": { + "INVALID_FIELD": "Ange ett annat värde" + } + }, + "ADF_CLOUD_PROCESS_HEADER": { + "PROPERTIES": { + "ID": "ID", + "NAME": "Namn", + "NAME_DEFAULT": "Inget namn", + "DESCRIPTION": "Beskrivning", + "DESCRIPTION_DEFAULT": "Ingen beskrivning", + "STATUS": "Status", + "BUSINESS_KEY": "Affärsnyckel", + "INITIATOR": "Initerare", + "START_DATE": "Startdatum", + "LAST_MODIFIED": "Senast ändrad", + "PARENT_ID": "Föräldra-ID", + "NONE": "Ingen" + } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "Inget formulär finns tillgängligt", + "SUBTITLE": "Bifoga ett formulär som kan visas senare", + "BUTTONS": { + "COMPLETE": "Slutför", + "CANCEL": "Avbryt", + "CLAIM": "Anta", + "UNCLAIM": "Avsäga" + } + } + } +} \ No newline at end of file diff --git a/lib/process-services-cloud/src/lib/i18n/zh-CN.json b/lib/process-services-cloud/src/lib/i18n/zh-CN.json index e365c123b3..46b7d335ea 100644 --- a/lib/process-services-cloud/src/lib/i18n/zh-CN.json +++ b/lib/process-services-cloud/src/lib/i18n/zh-CN.json @@ -47,8 +47,14 @@ }, "ADF_CLOUD_TASK_LIST": { "APPS": { - "TITLE": "找不到应用程序", - "SUBTITLE": "创建您想要今后轻松查找的新应用程序" + "NO_APPS": { + "TITLE": "找不到应用程序", + "SUBTITLE": "创建您想要今后轻松查找的新应用程序" + }, + "ERROR": { + "TITLE": "存在错误", + "SUBTITLE": "请确定您是否有访问应用程序的权限" + } }, "START_TASK": { "FORM": { @@ -60,7 +66,8 @@ "ASSIGNEE": "被指派者", "CANDIDATE_GROUP": "候选人组", "FORM": "表单", - "DATE": "选择日期" + "DATE": "选择日期", + "NONE": "无" }, "ACTION": { "START": "开始", @@ -76,7 +83,8 @@ "PRIORITY": "优先级", "CREATED_DATE": "创建日期", "LAST_MODIFIED": "最近一次修改时间", - "CREATED": "已创建" + "CREATED": "已创建", + "JSON_CELL": "Json" }, "LIST": { "MESSAGES": { @@ -112,6 +120,7 @@ }, "LABEL": { "APP_NAME": "应用程序名称", + "TASK_ID": "任务 ID", "PROCESS_DEF_ID": "流程定义 ID", "STATUS": "状态", "ASSIGNMENT": "被指派者", @@ -174,7 +183,7 @@ "ADF_CLOUD_TASK_HEADER": { "BUTTON": { "CLAIM": "申领", - "UNCLAIM": "重新排队" + "RELEASE": "释放" }, "PROPERTIES": { "TASK_NAME": "任务", @@ -209,6 +218,7 @@ "PROPERTIES": { "ID": "ID", "NAME": "名称", + "NAME_DEFAULT": "没有名称", "DESCRIPTION": "说明", "DESCRIPTION_DEFAULT": "没有描述", "STATUS": "状态", @@ -219,5 +229,17 @@ "PARENT_ID": "父 ID", "NONE": "无" } + }, + "ADF_CLOUD_TASK_FORM": { + "EMPTY_FORM": { + "TITLE": "没有可用表单", + "SUBTITLE": "附加可以稍后查看的表单", + "BUTTONS": { + "COMPLETE": "完成", + "CANCEL": "取消", + "CLAIM": "申领", + "UNCLAIM": "释放" + } + } } } \ No newline at end of file diff --git a/lib/process-services/i18n/ar.json b/lib/process-services/i18n/ar.json index 371ddac583..5cfcc112a9 100644 --- a/lib/process-services/i18n/ar.json +++ b/lib/process-services/i18n/ar.json @@ -73,7 +73,7 @@ "BUTTON": { "COMPLETE": "تم", "CLAIM": "مطالبة", - "UNCLAIM": "إعادة وضع في قائمة الانتظار", + "UNCLAIM": "تحرير", "DRAG-ATTACHMENT": "إفلات الملفات لتحميلها", "UPLOAD-ATTACHMENT": "تحميل المرفق" }, diff --git a/lib/process-services/i18n/cs.json b/lib/process-services/i18n/cs.json new file mode 100644 index 0000000000..49adbfd8e4 --- /dev/null +++ b/lib/process-services/i18n/cs.json @@ -0,0 +1,333 @@ +{ + "DIALOG": { + "SAVE_MESSAGE": "Kliknutím na tlačítko Uložit přidáte zprávu se současným nastavením do svého seznamu zpráv.", + "EXPORT_MESSAGE": "" + }, + "DATE-WIDGET": { + "START-DATE": "Datum zahájení", + "END-DATE": "Datum ukončení", + "MESSAGES": { + "START-DATE-REQUIRED": "Je třeba zadat datum zahájení", + "START-LESS-THAN-END-DATE": "Datum zahájení musí předcházet datu ukončení" + } + }, + "ADF_TASK_LIST": { + "APPS": { + "TITLE": "Nenalezeny žádné aplikace", + "SUBTITLE": "Pro lepší přehlednost vytvořte novou aplikaci", + "TASK_APP_NAME": "Aplikace úkolů" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Nenalezeny žádné úkoly", + "SUBTITLE": "Pro lepší přehlednost vytvořte nový úkol", + "NONE": "Nenalezeny žádné seznamy úkolů" + } + }, + "PROPERTIES": { + "TASK_NAME": "Úkol", + "THUMBNAIL": "Miniatura", + "DURATION": "Trvání", + "PARENT_TASK_ID": "ID nadřazeného úkolu", + "NAME": "Název", + "ASSIGNEE": "Pověřená osoba", + "ASSIGNEE_DEFAULT": "Žádná pověřená osoba", + "PRIORITY": "Priorita", + "DUE_DATE": "Termín", + "DUE_DATE_DEFAULT": "Žádné datum", + "STATUS": "Stav", + "CATEGORY": "Kategorie", + "CATEGORY_DEFAULT": "Žádná kategorie", + "PARENT_NAME": "Název nadřazené složky", + "PARENT_NAME_DEFAULT": "Žádná nadřazená složka", + "CREATED_BY": "Vytvořil(a)", + "CREATED": "Vytvořeno", + "END_DATE": "Datum ukončení", + "ID": "ID", + "DESCRIPTION": "Popis", + "DESCRIPTION_DEFAULT": "Žádný popis", + "FORM_NAME": "Název formuláře", + "FORM_NAME_DEFAULT": "Žádný formulář" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Zobrazit", + "REMOVE_CONTENT": "Odstranit", + "DOWNLOAD_CONTENT": "Stáhnout", + "DOWNLOAD_AUDIT": "Stáhnout audit" + }, + "DETAILS": { + "LABELS": { + "INFO_DRAWER_TITLE": "Aktivity", + "INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivita", + "INFO_DRAWER_TAB_DETAILS_TITLE": "Podrobnosti", + "ASSIGNEE": "Pověřená osoba", + "DUE": "Termín", + "FORM": "Formulář", + "PEOPLE": "Osoby, se kterými je tento úkol sdílený", + "COMMENTS": "Poznámky", + "CHECKLIST": "Kontrolní seznam", + "INVOLVED_PEOPLE": "Zapojené osoby", + "ADD_PEOPLE": "Přidat osoby a skupiny", + "ADD_ASSIGNEE": "Přidat novou pověřenou osobu" + }, + "BUTTON": { + "COMPLETE": "Dokončit", + "CLAIM": "Převzít", + "UNCLAIM": "Vzdát se", + "DRAG-ATTACHMENT": "Přetáhněte soubory, které chcete odeslat", + "UPLOAD-ATTACHMENT": "Odeslat přílohu" + }, + "MESSAGES": { + "NONE": "Nenalezeny žádné podrobnosti o úkolu", + "CLAIM": "Po kliknutí na tlačítko Převzít můžete začít pracovat na tomto úkolu" + }, + "FORM": { + "NONE": "Žádný formulář" + }, + "DUE": { + "NONE": "Žádný termín" + }, + "ASSIGNEE": { + "NONE": "Žádná pověřená osoba" + }, + "PEOPLE": { + "NONE": "Nikdo není zapojen" + }, + "CHECKLIST": { + "NONE": "Žádný kontrolní seznam", + "DIALOG": { + "TITLE": "Nová kontrola", + "CANCEL-BUTTON": "Zrušit", + "ADD-BUTTON": "Přidat kontrolní seznam", + "PLACEHOLDER": "Název" + } + }, + "ERROR": { + "TITLE": "Akci se nepodařilo dokončit", + "DESCRIPTION": "Zkuste to znovu nebo se ujistěte, že máte potřebná přístupová oprávnění.", + "CLOSE": "Zavřít" + } + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Nebyl vybrán žádný filtr úkolů" + } + }, + "START_TASK": { + "DEFAULT_NAME": "Můj výchozí úkol", + "BUTTON": "Vytvořit úkol", + "FORM": { + "TITLE": "Zahájit úkol", + "LABEL": { + "NONE": "Žádný", + "NAME": "Název", + "DESCRIPTION": "Popis", + "ATTACHFORM": "Připojit formulář", + "ASSIGNEE": "Pověřená osoba", + "FORM": "Formulář", + "DATE": "Zvolit datum" + }, + "ACTION": { + "START": "Spustit", + "CANCEL": "Zrušit" + }, + "ERROR": { + "REQUIRED": "Povinné pole", + "DATE": "Formát data je DD/MM/RRRR", + "MAXIMUM_LENGTH": "Přesáhli jste délku (maximálně lze zadat {{characters}} znaků).", + "MESSAGE": "Zadejte jinou hodnotu" + } + } + }, + "PEOPLE": { + "ASSIGNEE": "Pověřená osoba", + "DIALOG_CLOSE": "Zavřít", + "ADD_USER": "Přidat", + "ADD_ASSIGNEE": "Přiřadit", + "SEARCH_USER": "Hledat uživatele", + "SEARCH": { + "NO_USERS": "Nenalezen nikdo, koho by bylo možné zapojit" + } + }, + "ATTACHMENT": { + "EMPTY": { + "HEADER": "Tento seznam je prázdný", + "DRAG-AND-DROP": { + "TITLE": "Přetažením", + "SUBTITLE": "odešlete soubory" + } + }, + "EMPTY-LIST": { + "HEADER": "Nejsou k dispozici žádné soubory" + } + }, + "STANDALONE_TASK": { + "NO_FORM_MESSAGE": "Nepřipojeny žádné formuláře", + "COMPLETE_TASK_MESSAGE": "Úkol {{taskName}} dokončen", + "COMPLETE_TASK_SUB_MESSAGE": "Žádné formuláře určené k připojení" + }, + "ATTACH_FORM": { + "SELECT_FORM": "Vyberte formulář, který chcete připojit", + "REMOVE_FORM": "Odebrat formulář", + "SELECT_OPTION": "Vybrat možnost" + } + }, + "ADF_PROCESS_LIST": { + "LIST": { + "TITLE": "Nenalezeny žádné procesy", + "SUBTITLE": "Pro lepší přehlednost vytvořte nový proces", + "SUMMARY": "Nalezené instance procesu: {{total}}", + "ERROR": "Instance procesu se nepodařilo načíst. Zkuste to znovu nebo oddělení IT předejte následující zprávu: {{errorMessage}}" + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Nebyl zvolen žádný filtr instancí." + } + }, + "PROPERTIES": { + "PROCESS_NAME": "Proces", + "NAME": "Název", + "THUMBNAIL": "Miniatura", + "STATUS": "Stav", + "END_DATE": "Datum ukončení", + "END_DATE_DEFAULT": "Žádné datum", + "CATEGORY": "Kategorie", + "CATEGORY_DEFAULT": "Žádná kategorie", + "CREATED_BY": "Vytvořil(a)", + "CREATED_BY_DEFAULT": "Žádná pověřená osoba", + "CREATED": "Vytvořeno", + "BUSINESS_KEY": "Obchodní klíč", + "BUSINESS_KEY_DEFAULT": "Žádný", + "DESCRIPTION": "Popis", + "DESCRIPTION_DEFAULT": "Žádný popis", + "ID": "ID" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Zobrazit", + "REMOVE_CONTENT": "Odstranit", + "DOWNLOAD_CONTENT": "Stáhnout", + "DOWNLOAD_AUDIT": "Stáhnout audit", + "VIEW_TASK": "Zobrazit úkol" + }, + "DETAILS": { + "LABELS": { + "STARTED_BY": "Zahájil(a)", + "STARTED": "Zahájeno", + "ENDED": "Ukončeno", + "COMMENTS": "Poznámky", + "START_FORM": "Spustit formulář", + "TASKS_ACTIVE": "Aktivní úkoly", + "TASKS_COMPLETED": "Dokončené úkoly", + "TASK_SUBTITLE": "Přiřazeno: {{user}}. Vytvořeno k {{created}}" + }, + "BUTTON": { + "CANCEL": "Zrušit proces", + "CLOSE": "Zavřít", + "SHOW_DIAGRAM": "Zobrazit diagram", + "DRAG-ATTACHMENT": "Přetáhněte soubory, které chcete odeslat", + "UPLOAD-ATTACHMENT": "Odeslat přílohu" + }, + "MESSAGES": { + "NONE": "Nenalezeny žádné podrobnosti o procesu" + }, + "TASKS": { + "NO_ACTIVE": "Momentálně nejsou aktivní žádné úkoly", + "NO_COMPLETED": "Nebyly zatím dokončeny žádné úkoly", + "TASK_DETAILS": "Podrobnosti o úkolu", + "TASK_CLOSE": "Zavřít" + }, + "COMMENTS": { + "ADD": "Přidat komentář", + "HEADER": "Komentáře ({{ count }})", + "NONE": "Žádné komentáře", + "BUTTON": { + "ADD": "Přidat komentář" + }, + "ADD_DIALOG": { + "TITLE": "Nový komentář", + "LABEL": { + "MESSAGE": "Zpráva" + }, + "BUTTON": { + "ADD": "Přidat komentář", + "CANCEL": "Zrušit" + } + } + }, + "ADD_DIALOG": { + "TITLE": "Nastavit proměnnou procesu", + "LABEL": { + "NAME": "Název", + "VALUE": "Hodnota", + "SCOPE": "Rozsah" + } + }, + "EDIT_DIALOG": { + "TITLE": "Upravit proměnnou procesu" + }, + "ERROR_DIALOG": { + "TITLE": "Akci se nepodařilo dokončit", + "DESCRIPTION": "Nemáte pravděpodobně potřebná přístupová oprávněni. Obraťte se na oddělení IT." + } + }, + "START_PROCESS": { + "BUTTON": "Zahájit proces", + "NO_PROCESS_DEFINITIONS": "Proces nelze zahájit, protože nejsou k dispozici žádné definice procesu", + "FORM": { + "TITLE": "Zahájit proces", + "LABEL": { + "TYPE": "Vybrat proces", + "NAME": "Název procesu" + }, + "TYPE_PLACEHOLDER": "Vyberte...", + "ACTION": { + "START": "Zahájit proces", + "CANCEL": "Zrušit" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Definice procesu se nepodařilo načíst. Zkontrolujte svá přístupová oprávnění.", + "START": "Nepodařilo se spustit novou instanci procesu. Zkontrolujte svá přístupová oprávnění.", + "MAXIMUM_LENGTH": "Přesáhli jste délku (maximálně lze zadat {{characters}} znaků)." + } + }, + "PROCESS-ATTACHMENT": { + "EMPTY": { + "HEADER": "Tento seznam je prázdný", + "DRAG-AND-DROP": { + "TITLE": "Přetažením", + "SUBTITLE": "odešlete soubory" + } + }, + "EMPTY-LIST": { + "HEADER": "Nejsou k dispozici žádné soubory" + }, + "COLUMNS": { + "NAME": "Název", + "CREATED-ON": "Vytvořeno" + } + } + }, + "ADF_SIDEBAR_ACTION_MENU": { + "BUTTON": { + "CREATE": "Vytvořit", + "NEW_TASK": "Nový úkol", + "NEW_PROCESS": "Nový proces" + } + }, + "APP": { + "DIALOG": { + "START": "Pokračovat", + "TITLE": "Vyberte procesní aplikaci", + "LIST": "Seznam procesních aplikací", + "ERROR": "Při pokusu připojit se k aplikaci Process Services došlo k problému" + } + }, + "ATTACH-FILE": { + "ACTIONS": { + "LOGIN": "Přihlášení", + "CANCEL": "Zrušit", + "CHOOSE": "Vybrat" + } + } +} \ No newline at end of file diff --git a/lib/process-services/i18n/da.json b/lib/process-services/i18n/da.json new file mode 100644 index 0000000000..07312b7816 --- /dev/null +++ b/lib/process-services/i18n/da.json @@ -0,0 +1,333 @@ +{ + "DIALOG": { + "SAVE_MESSAGE": "Klik på Gem for at tilføje en rapport med de aktuelle indstillinger på din rapportliste.", + "EXPORT_MESSAGE": "" + }, + "DATE-WIDGET": { + "START-DATE": "Startdato", + "END-DATE": "Slutdato", + "MESSAGES": { + "START-DATE-REQUIRED": "Startdatoen er påkrævet", + "START-LESS-THAN-END-DATE": "Startdatoen skal være før slutdatoen" + } + }, + "ADF_TASK_LIST": { + "APPS": { + "TITLE": "Der blev ikke fundet nogen programmer", + "SUBTITLE": "Opret et nyt program, som skal være nemt at finde senere", + "TASK_APP_NAME": "Opgaveapp" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Der blev ikke fundet nogen opgaver", + "SUBTITLE": "Opret en ny opgave, som skal være nem at finde senere", + "NONE": "Der blev ikke fundet nogen opgavelister" + } + }, + "PROPERTIES": { + "TASK_NAME": "Opgave", + "THUMBNAIL": "Miniaturevisning", + "DURATION": "Varighed", + "PARENT_TASK_ID": "Id for overordnet opgave", + "NAME": "Navn", + "ASSIGNEE": "Modtager", + "ASSIGNEE_DEFAULT": "Ingen modtager", + "PRIORITY": "Prioritet", + "DUE_DATE": "Forfaldsdato", + "DUE_DATE_DEFAULT": "Ingen dato", + "STATUS": "Status", + "CATEGORY": "Kategori", + "CATEGORY_DEFAULT": "Ingen kategori", + "PARENT_NAME": "Overordnet navn", + "PARENT_NAME_DEFAULT": "Ingen overordnet", + "CREATED_BY": "Oprettet af", + "CREATED": "Oprettet", + "END_DATE": "Slutdato", + "ID": "Id", + "DESCRIPTION": "Beskrivelse", + "DESCRIPTION_DEFAULT": "Ingen beskrivelse", + "FORM_NAME": "Formularnavn", + "FORM_NAME_DEFAULT": "Ingen formular" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Vis", + "REMOVE_CONTENT": "Fjern", + "DOWNLOAD_CONTENT": "Download", + "DOWNLOAD_AUDIT": "Download overvågning" + }, + "DETAILS": { + "LABELS": { + "INFO_DRAWER_TITLE": "Aktiviteter", + "INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivitet", + "INFO_DRAWER_TAB_DETAILS_TITLE": "Detaljer", + "ASSIGNEE": "Modtager", + "DUE": "Forfalder", + "FORM": "Formular", + "PEOPLE": "Personer, som denne opgave er delt med", + "COMMENTS": "Kommentarer", + "CHECKLIST": "Tjekliste", + "INVOLVED_PEOPLE": "Involverede personer", + "ADD_PEOPLE": "Tilføj personer og grupper", + "ADD_ASSIGNEE": "Tilføj ny modtager" + }, + "BUTTON": { + "COMPLETE": "Fuldført", + "CLAIM": "Gør krav på", + "UNCLAIM": "Frigiv", + "DRAG-ATTACHMENT": "Slip filer for at uploade dem", + "UPLOAD-ATTACHMENT": "Upload vedhæftet fil" + }, + "MESSAGES": { + "NONE": "Der blev ikke fundet nogen opgavedetaljer", + "CLAIM": "Klik på Gør krav på for at arbejde på denne opgave" + }, + "FORM": { + "NONE": "Ingen formular" + }, + "DUE": { + "NONE": "Ingen forfaldsdato" + }, + "ASSIGNEE": { + "NONE": "Ingen modtager" + }, + "PEOPLE": { + "NONE": "Der er ingen involverede" + }, + "CHECKLIST": { + "NONE": "Ingen tjekliste", + "DIALOG": { + "TITLE": "Nyt tjek", + "CANCEL-BUTTON": "Annuller", + "ADD-BUTTON": "Tilføj kontrolliste", + "PLACEHOLDER": "Navn" + } + }, + "ERROR": { + "TITLE": "Handlingen kunne ikke fuldføres", + "DESCRIPTION": "Prøv igen, eller kontrollér, om du har adgang.", + "CLOSE": "Luk" + } + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Der er ikke valgt noget opgavefilter" + } + }, + "START_TASK": { + "DEFAULT_NAME": "Min standardopgave", + "BUTTON": "Opret opgave", + "FORM": { + "TITLE": "Start opgave", + "LABEL": { + "NONE": "Ingen", + "NAME": "Navn", + "DESCRIPTION": "Beskrivelse", + "ATTACHFORM": "Vedhæft formular", + "ASSIGNEE": "Modtager", + "FORM": "Formular", + "DATE": "Vælg dato" + }, + "ACTION": { + "START": "Start", + "CANCEL": "Annuller" + }, + "ERROR": { + "REQUIRED": "Obligatorisk felt", + "DATE": "Datoformat DD/MM/ÅÅÅÅ", + "MAXIMUM_LENGTH": "Længden er overskredet, maks. {{characters}} tegn", + "MESSAGE": "Angiv en anden værdi" + } + } + }, + "PEOPLE": { + "ASSIGNEE": "Modtager", + "DIALOG_CLOSE": "Luk", + "ADD_USER": "Tilføj", + "ADD_ASSIGNEE": "Tildel", + "SEARCH_USER": "Søg efter bruger", + "SEARCH": { + "NO_USERS": "Der blev ikke fundet nogen involverede" + } + }, + "ATTACHMENT": { + "EMPTY": { + "HEADER": "Denne liste er tom", + "DRAG-AND-DROP": { + "TITLE": "Træk og slip", + "SUBTITLE": "for at uploade filer" + } + }, + "EMPTY-LIST": { + "HEADER": "Der er ingen tilgængelige filer" + } + }, + "STANDALONE_TASK": { + "NO_FORM_MESSAGE": "Der er ikke vedhæftet en formular", + "COMPLETE_TASK_MESSAGE": "Opgaven {{taskName}} er fuldført", + "COMPLETE_TASK_SUB_MESSAGE": "Der er ikke tilføjet nogen formularer" + }, + "ATTACH_FORM": { + "SELECT_FORM": "Vælg den formular, du vil vedhæfte", + "REMOVE_FORM": "Fjern formular", + "SELECT_OPTION": "Vælg en valgmulighed" + } + }, + "ADF_PROCESS_LIST": { + "LIST": { + "TITLE": "Der blev ikke fundet nogen processer", + "SUBTITLE": "Opret en ny proces, som skal være nem at finde senere", + "SUMMARY": "{{total}} procesforekomster fundet", + "ERROR": "Procesforekomsterne kunne ikke indlæses. Prøv igen, eller giv følgende meddelelse til din it-afdeling: {{errorMessage}}" + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Der er ikke valgt et filter for procesforekomster." + } + }, + "PROPERTIES": { + "PROCESS_NAME": "Proces", + "NAME": "Navn", + "THUMBNAIL": "Miniaturevisning", + "STATUS": "Status", + "END_DATE": "Slutdato", + "END_DATE_DEFAULT": "Ingen dato", + "CATEGORY": "Kategori", + "CATEGORY_DEFAULT": "Ingen kategori", + "CREATED_BY": "Oprettet af", + "CREATED_BY_DEFAULT": "Ingen modtager", + "CREATED": "Oprettet", + "BUSINESS_KEY": "Forretningsnøgle", + "BUSINESS_KEY_DEFAULT": "Ingen", + "DESCRIPTION": "Beskrivelse", + "DESCRIPTION_DEFAULT": "Ingen beskrivelse", + "ID": "Id" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Vis", + "REMOVE_CONTENT": "Fjern", + "DOWNLOAD_CONTENT": "Download", + "DOWNLOAD_AUDIT": "Download overvågning", + "VIEW_TASK": "Vis opgave" + }, + "DETAILS": { + "LABELS": { + "STARTED_BY": "Startet af", + "STARTED": "Startet", + "ENDED": "Sluttet", + "COMMENTS": "Kommentarer", + "START_FORM": "Åbn formular", + "TASKS_ACTIVE": "Aktive opgaver", + "TASKS_COMPLETED": "Fuldførte opgaver", + "TASK_SUBTITLE": "Tildelt til {{user}}, oprettet {{created}}" + }, + "BUTTON": { + "CANCEL": "Annuller proces", + "CLOSE": "Luk", + "SHOW_DIAGRAM": "Vis diagram", + "DRAG-ATTACHMENT": "Slip filer for at uploade dem", + "UPLOAD-ATTACHMENT": "Upload vedhæftet fil" + }, + "MESSAGES": { + "NONE": "Der blev ikke fundet nogen procesdetaljer" + }, + "TASKS": { + "NO_ACTIVE": "Der er ikke nogen aktive opgaver", + "NO_COMPLETED": "Der er endnu ikke fuldført nogen opgaver", + "TASK_DETAILS": "Opgavedetaljer", + "TASK_CLOSE": "Luk" + }, + "COMMENTS": { + "ADD": "Tilføj en kommentar", + "HEADER": "Kommentarer ({{ count }})", + "NONE": "Ingen kommentarer", + "BUTTON": { + "ADD": "Tilføj en kommentar" + }, + "ADD_DIALOG": { + "TITLE": "Ny kommentar", + "LABEL": { + "MESSAGE": "Meddelelse" + }, + "BUTTON": { + "ADD": "Tilføj kommentar", + "CANCEL": "Annuller" + } + } + }, + "ADD_DIALOG": { + "TITLE": "Angiv procesvariabel", + "LABEL": { + "NAME": "Navn", + "VALUE": "Værdi", + "SCOPE": "Omfang" + } + }, + "EDIT_DIALOG": { + "TITLE": "Rediger procesvariabel" + }, + "ERROR_DIALOG": { + "TITLE": "Handlingen kunne ikke fuldføres", + "DESCRIPTION": "Du har muligvis ikke det påkrævede adgangsniveau. Kontakt din it-afdeling." + } + }, + "START_PROCESS": { + "BUTTON": "Start proces", + "NO_PROCESS_DEFINITIONS": "Du kan ikke starte en proces, da der ikke er nogen tilgængelige procesdefinitioner", + "FORM": { + "TITLE": "Start proces", + "LABEL": { + "TYPE": "Vælg proces", + "NAME": "Procesnavn" + }, + "TYPE_PLACEHOLDER": "Vælg en...", + "ACTION": { + "START": "Start proces", + "CANCEL": "Annuller" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Der kunne ikke indlæses nogen procesdefinitioner. Kontrollér, om du har adgang til dem.", + "START": "Der kunne ikke startes en ny procesforekomst. Kontrollér, om du har adgang.", + "MAXIMUM_LENGTH": "Længden er overskredet, maks. {{characters}} tegn." + } + }, + "PROCESS-ATTACHMENT": { + "EMPTY": { + "HEADER": "Denne liste er tom", + "DRAG-AND-DROP": { + "TITLE": "Træk og slip", + "SUBTITLE": "for at uploade filer" + } + }, + "EMPTY-LIST": { + "HEADER": "Der er ingen tilgængelige filer" + }, + "COLUMNS": { + "NAME": "Navn", + "CREATED-ON": "Oprettet den" + } + } + }, + "ADF_SIDEBAR_ACTION_MENU": { + "BUTTON": { + "CREATE": "Opret", + "NEW_TASK": "Ny opgave", + "NEW_PROCESS": "Ny proces" + } + }, + "APP": { + "DIALOG": { + "START": "Fortsæt", + "TITLE": "Vælg en procesapp", + "LIST": "Liste over procesapps", + "ERROR": "Der kan ikke oprettes forbindelse til Process Services" + } + }, + "ATTACH-FILE": { + "ACTIONS": { + "LOGIN": "Log ind", + "CANCEL": "Annuller", + "CHOOSE": "Vælg" + } + } +} \ No newline at end of file diff --git a/lib/process-services/i18n/de.json b/lib/process-services/i18n/de.json index 0ea7f82d8a..98e8308820 100644 --- a/lib/process-services/i18n/de.json +++ b/lib/process-services/i18n/de.json @@ -72,14 +72,14 @@ }, "BUTTON": { "COMPLETE": "Abschließen", - "CLAIM": "Anfordern", - "UNCLAIM": "Erneut in Warteschlange stellen", + "CLAIM": "Beanspruchen", + "UNCLAIM": "Anspruch aufheben", "DRAG-ATTACHMENT": "Dateien zum Hochladen ablegen", "UPLOAD-ATTACHMENT": "Anhang hochladen" }, "MESSAGES": { "NONE": "Keine Aufgabendetails gefunden", - "CLAIM": "Klicken Sie auf 'Anfordern', um diese Aufgabe zu bearbeiten" + "CLAIM": "Klicken Sie auf 'Beanspruchen', um diese Aufgabe zu bearbeiten" }, "FORM": { "NONE": "Kein Formular" diff --git a/lib/process-services/i18n/es.json b/lib/process-services/i18n/es.json index 6fcbbc5f38..b8ee619d5a 100644 --- a/lib/process-services/i18n/es.json +++ b/lib/process-services/i18n/es.json @@ -73,7 +73,7 @@ "BUTTON": { "COMPLETE": "Completar", "CLAIM": "Pedir", - "UNCLAIM": "Volver a poner en cola", + "UNCLAIM": "Liberar", "DRAG-ATTACHMENT": "Arrastrar ficheros a cargar", "UPLOAD-ATTACHMENT": "Cargar adjunto" }, diff --git a/lib/process-services/i18n/fi.json b/lib/process-services/i18n/fi.json new file mode 100644 index 0000000000..d3976d6046 --- /dev/null +++ b/lib/process-services/i18n/fi.json @@ -0,0 +1,333 @@ +{ + "DIALOG": { + "SAVE_MESSAGE": "Jos haluat tallentaa raportin nykyisillä asetuksilla raporttiluetteloosi, napsauta Tallenna.", + "EXPORT_MESSAGE": "" + }, + "DATE-WIDGET": { + "START-DATE": "Alkamispäivä", + "END-DATE": "Päättymispäivä", + "MESSAGES": { + "START-DATE-REQUIRED": "Alkamispäivä on pakollinen", + "START-LESS-THAN-END-DATE": "Alkamispäivän täytyy olla ennen päättymispäivää" + } + }, + "ADF_TASK_LIST": { + "APPS": { + "TITLE": "Yhtään sovellusta ei löydy", + "SUBTITLE": "Luo uusi sovellus, jonka löydät helposti myöhemmin", + "TASK_APP_NAME": "Tehtäväsovellus" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Yhtään tehtävää ei löydy", + "SUBTITLE": "Luo uusi tehtävä, jonka löydät helposti myöhemmin", + "NONE": "Yhtään tehtäväluetteloa ei löydy" + } + }, + "PROPERTIES": { + "TASK_NAME": "Tehtävä", + "THUMBNAIL": "Pikkukuva", + "DURATION": "Kesto", + "PARENT_TASK_ID": "Ylätason tehtävän tunnus", + "NAME": "Nimi", + "ASSIGNEE": "Vastuuhenkilö", + "ASSIGNEE_DEFAULT": "Ei vastuuhenkilöä", + "PRIORITY": "Prioriteetti", + "DUE_DATE": "Määräpäivä", + "DUE_DATE_DEFAULT": "Ei päivämäärää", + "STATUS": "Tila", + "CATEGORY": "Luokka", + "CATEGORY_DEFAULT": "Ei luokkaa", + "PARENT_NAME": "Ylätason nimi", + "PARENT_NAME_DEFAULT": "Ei ylätasoa", + "CREATED_BY": "Tekijä:", + "CREATED": "Luotu", + "END_DATE": "Päättymispäivä", + "ID": "Tunnus", + "DESCRIPTION": "Kuvaus", + "DESCRIPTION_DEFAULT": "Ei kuvausta", + "FORM_NAME": "Lomakkeen nimi", + "FORM_NAME_DEFAULT": "Ei lomaketta" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Näytä", + "REMOVE_CONTENT": "Poista", + "DOWNLOAD_CONTENT": "Lataa", + "DOWNLOAD_AUDIT": "Lataa tarkastus" + }, + "DETAILS": { + "LABELS": { + "INFO_DRAWER_TITLE": "Toiminnot", + "INFO_DRAWER_TAB_ACTIVITY_TITLE": "Toiminto", + "INFO_DRAWER_TAB_DETAILS_TITLE": "Tiedot", + "ASSIGNEE": "Vastuuhenkilö", + "DUE": "Määräpäivä", + "FORM": "Lomake", + "PEOPLE": "Käyttäjät, joille tämä tehtävä on jaettu", + "COMMENTS": "Kommentit", + "CHECKLIST": "Tarkistuslista", + "INVOLVED_PEOPLE": "Mukana olevat käyttäjät", + "ADD_PEOPLE": "Lisää ihmisiä ja ryhmiä", + "ADD_ASSIGNEE": "Lisää uusi vastuuhenkilö" + }, + "BUTTON": { + "COMPLETE": "Merkitse valmiiksi", + "CLAIM": "Varaa", + "UNCLAIM": "Vapauta", + "DRAG-ATTACHMENT": "Lataa tiedostoja pudottamalla niitä", + "UPLOAD-ATTACHMENT": "Lataa liite" + }, + "MESSAGES": { + "NONE": "Tehtävätietoja ei löydy", + "CLAIM": "Jos haluat työstää tätä tehtävää, napsauta Varaa" + }, + "FORM": { + "NONE": "Ei lomaketta" + }, + "DUE": { + "NONE": "Ei määräpäivää" + }, + "ASSIGNEE": { + "NONE": "Ei vastuuhenkilöä" + }, + "PEOPLE": { + "NONE": "Ei ketään mukana" + }, + "CHECKLIST": { + "NONE": "Ei tarkistuslistaa", + "DIALOG": { + "TITLE": "Uusi tarkistus", + "CANCEL-BUTTON": "Peruuta", + "ADD-BUTTON": "Lisää tarkistuslista", + "PLACEHOLDER": "Nimi" + } + }, + "ERROR": { + "TITLE": "Toiminnon suorittaminen ei onnistu", + "DESCRIPTION": "Yritä uudelleen tai tarkista, että sinulla on tarvittavat oikeudet.", + "CLOSE": "Sulje" + } + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Ei valittua tehtäväsuodatinta" + } + }, + "START_TASK": { + "DEFAULT_NAME": "Oma oletustehtävä", + "BUTTON": "Luo tehtävä", + "FORM": { + "TITLE": "Aloita tehtävä", + "LABEL": { + "NONE": "Ei mitään", + "NAME": "Nimi", + "DESCRIPTION": "Kuvaus", + "ATTACHFORM": "Liitä lomake", + "ASSIGNEE": "Vastuuhenkilö", + "FORM": "Lomake", + "DATE": "Valitse päivämäärä" + }, + "ACTION": { + "START": "Aloita", + "CANCEL": "Peruuta" + }, + "ERROR": { + "REQUIRED": "Pakollinen kenttä", + "DATE": "Päivämäärämuoto: PP/KK/VVVV", + "MAXIMUM_LENGTH": "Liian pitkä: voit käyttää enintään {{characters}} merkkiä.", + "MESSAGE": "Anna toinen arvo" + } + } + }, + "PEOPLE": { + "ASSIGNEE": "Vastuuhenkilö", + "DIALOG_CLOSE": "Sulje", + "ADD_USER": "Lisää", + "ADD_ASSIGNEE": "Määritä", + "SEARCH_USER": "Hae käyttäjää", + "SEARCH": { + "NO_USERS": "Ei löydy ketään mukaan lisättäväksi" + } + }, + "ATTACHMENT": { + "EMPTY": { + "HEADER": "Tämä luettelo on tyhjä", + "DRAG-AND-DROP": { + "TITLE": "Lataa tiedostoja", + "SUBTITLE": "vetämällä ja pudottamalla" + } + }, + "EMPTY-LIST": { + "HEADER": "Yhtään tiedostoa ei ole saatavilla" + } + }, + "STANDALONE_TASK": { + "NO_FORM_MESSAGE": "Ei liitettyjä lomakkeita", + "COMPLETE_TASK_MESSAGE": "Tehtävä {{taskName}} suoritettu", + "COMPLETE_TASK_SUB_MESSAGE": "Ei lisättäviä lomakkeita" + }, + "ATTACH_FORM": { + "SELECT_FORM": "Valitse liitettävä lomake", + "REMOVE_FORM": "Poista lomake", + "SELECT_OPTION": "Valitse asetus" + } + }, + "ADF_PROCESS_LIST": { + "LIST": { + "TITLE": "Yhtään prosessia ei löydy", + "SUBTITLE": "Luo uusi prosessi, jonka löydät helposti myöhemmin", + "SUMMARY": "Löytyi {{total}} prosessiesiintymää", + "ERROR": "Prosessiesiintymien lataaminen ei onnistu. Yritä uudelleen tai ilmoita seuraava virheilmoitus IT-tuelle: {{errorMessage}}" + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Prosessiesiintymäsuodatinta ei ole valittu." + } + }, + "PROPERTIES": { + "PROCESS_NAME": "Prosessi", + "NAME": "Nimi", + "THUMBNAIL": "Pikkukuva", + "STATUS": "Tila", + "END_DATE": "Päättymispäivä", + "END_DATE_DEFAULT": "Ei päivämäärää", + "CATEGORY": "Luokka", + "CATEGORY_DEFAULT": "Ei luokkaa", + "CREATED_BY": "Tekijä:", + "CREATED_BY_DEFAULT": "Ei vastuuhenkilöä", + "CREATED": "Luotu", + "BUSINESS_KEY": "Liiketoiminta-avain", + "BUSINESS_KEY_DEFAULT": "Ei mitään", + "DESCRIPTION": "Kuvaus", + "DESCRIPTION_DEFAULT": "Ei kuvausta", + "ID": "Tunnus" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Näytä", + "REMOVE_CONTENT": "Poista", + "DOWNLOAD_CONTENT": "Lataa", + "DOWNLOAD_AUDIT": "Lataa tarkastus", + "VIEW_TASK": "Näytä tehtävä" + }, + "DETAILS": { + "LABELS": { + "STARTED_BY": "Aloittaja:", + "STARTED": "Aloitettu", + "ENDED": "Lopetettu", + "COMMENTS": "Kommentit", + "START_FORM": "Aloita lomake", + "TASKS_ACTIVE": "Aktiiviset tehtävät", + "TASKS_COMPLETED": "Suoritetut tehtävät", + "TASK_SUBTITLE": "Määritetty käyttäjälle {{user}}, luotu {{created}}" + }, + "BUTTON": { + "CANCEL": "Peruuta prosessi", + "CLOSE": "Sulje", + "SHOW_DIAGRAM": "Näytä kaavio", + "DRAG-ATTACHMENT": "Lataa tiedostoja pudottamalla niitä", + "UPLOAD-ATTACHMENT": "Lataa liite" + }, + "MESSAGES": { + "NONE": "Prosessitietoja ei löydy" + }, + "TASKS": { + "NO_ACTIVE": "Ei tällä hetkellä aktiivisia tehtäviä", + "NO_COMPLETED": "Ei vielä yhtään suoritettua tehtävää", + "TASK_DETAILS": "Tehtävätiedot", + "TASK_CLOSE": "Sulje" + }, + "COMMENTS": { + "ADD": "Lisää kommentti", + "HEADER": "Kommentit ({{ count }})", + "NONE": "Ei kommentteja", + "BUTTON": { + "ADD": "Lisää kommentti" + }, + "ADD_DIALOG": { + "TITLE": "Uusi kommentti", + "LABEL": { + "MESSAGE": "Viesti" + }, + "BUTTON": { + "ADD": "Lisää kommentti", + "CANCEL": "Peruuta" + } + } + }, + "ADD_DIALOG": { + "TITLE": "Määritä prosessimuuttuja", + "LABEL": { + "NAME": "Nimi", + "VALUE": "Arvo", + "SCOPE": "Laajuus" + } + }, + "EDIT_DIALOG": { + "TITLE": "Muokkaa prosessimuuttujaa" + }, + "ERROR_DIALOG": { + "TITLE": "Toiminnon suorittaminen ei onnistu", + "DESCRIPTION": "Sinulla ei ehkä ole riittäviä oikeuksia. Tarkista asia IT-tuesta." + } + }, + "START_PROCESS": { + "BUTTON": "Käynnistä prosessi", + "NO_PROCESS_DEFINITIONS": "Et voi käynnistää prosessia, koska prosessimääritelmiä ei ole saatavilla", + "FORM": { + "TITLE": "Käynnistä prosessi", + "LABEL": { + "TYPE": "Valitse prosessi", + "NAME": "Prosessin nimi" + }, + "TYPE_PLACEHOLDER": "Valitse yksi...", + "ACTION": { + "START": "Käynnistä prosessi", + "CANCEL": "Peruuta" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Prosessimääritelmien lataaminen ei onnistu. Tarkista, että sinulla on tarvittavat oikeudet.", + "START": "Uuden prosessiesiintymän käynnistäminen ei onnistu. Tarkista, että sinulla on tarvittavat oikeudet.", + "MAXIMUM_LENGTH": "Liian pitkä: voit käyttää enintään {{characters}} merkkiä." + } + }, + "PROCESS-ATTACHMENT": { + "EMPTY": { + "HEADER": "Tämä luettelo on tyhjä", + "DRAG-AND-DROP": { + "TITLE": "Lataa tiedostoja", + "SUBTITLE": "vetämällä ja pudottamalla" + } + }, + "EMPTY-LIST": { + "HEADER": "Yhtään tiedostoa ei ole saatavilla" + }, + "COLUMNS": { + "NAME": "Nimi", + "CREATED-ON": "Luotu" + } + } + }, + "ADF_SIDEBAR_ACTION_MENU": { + "BUTTON": { + "CREATE": "Luo", + "NEW_TASK": "Uusi tehtävä", + "NEW_PROCESS": "Uusi prosessi" + } + }, + "APP": { + "DIALOG": { + "START": "Jatka", + "TITLE": "Valitse prosessisovellus", + "LIST": "Prosessisovellusluettelo", + "ERROR": "Process Services -yhteyden muodostamisessa on ongelma" + } + }, + "ATTACH-FILE": { + "ACTIONS": { + "LOGIN": "Kirjaudu sisään", + "CANCEL": "Peruuta", + "CHOOSE": "Valitse" + } + } +} \ No newline at end of file diff --git a/lib/process-services/i18n/fr.json b/lib/process-services/i18n/fr.json index 32e243390a..40ae2a1099 100644 --- a/lib/process-services/i18n/fr.json +++ b/lib/process-services/i18n/fr.json @@ -72,14 +72,14 @@ }, "BUTTON": { "COMPLETE": "Terminer", - "CLAIM": "Se l'attribuer", - "UNCLAIM": "Replacer dans la file d'attente", + "CLAIM": "S'attribuer", + "UNCLAIM": "Libérer", "DRAG-ATTACHMENT": "Déposez des fichiers pour les importer", "UPLOAD-ATTACHMENT": "Importer la pièce jointe" }, "MESSAGES": { "NONE": "Aucun détail de tâche trouvé", - "CLAIM": "Cliquez sur Se l'attribuer pour travailler sur cette tâche" + "CLAIM": "Cliquez sur S'attribuer pour travailler sur cette tâche" }, "FORM": { "NONE": "Aucun formulaire" diff --git a/lib/process-services/i18n/it.json b/lib/process-services/i18n/it.json index 85e906cc24..4337a403e1 100644 --- a/lib/process-services/i18n/it.json +++ b/lib/process-services/i18n/it.json @@ -73,13 +73,13 @@ "BUTTON": { "COMPLETE": "Completa", "CLAIM": "Richiedi", - "UNCLAIM": "Metti di nuovo in coda", + "UNCLAIM": "Restituisci", "DRAG-ATTACHMENT": "Rilascia file da caricare", "UPLOAD-ATTACHMENT": "Carica allegato" }, "MESSAGES": { "NONE": "Nessun dettaglio compito trovato", - "CLAIM": "Fai clic su Richiedi per lavorare su questo compito" + "CLAIM": "Fare clic su Richiedi per lavorare su questo compito" }, "FORM": { "NONE": "Nessun modulo" @@ -135,7 +135,7 @@ "REQUIRED": "Campo obbligatorio", "DATE": "Formato data GG/MM/AAAA", "MAXIMUM_LENGTH": "Lunghezza superata, massimo {{characters}} caratteri.", - "MESSAGE": "Inserire un altro valore" + "MESSAGE": "Immettere un altro valore" } } }, diff --git a/lib/process-services/i18n/ja.json b/lib/process-services/i18n/ja.json index 3844ad6d31..f97f7bd077 100644 --- a/lib/process-services/i18n/ja.json +++ b/lib/process-services/i18n/ja.json @@ -72,14 +72,14 @@ }, "BUTTON": { "COMPLETE": "完了", - "CLAIM": "要求", - "UNCLAIM": "キューへの再登録", + "CLAIM": "担当する", + "UNCLAIM": "担当解除", "DRAG-ATTACHMENT": "アップロードするファイルをここにドロップしてください", "UPLOAD-ATTACHMENT": "添付ファイルのアップロード" }, "MESSAGES": { "NONE": "タスクの詳細が見つかりません", - "CLAIM": "このタスクの作業を行うには、[要求] をクリックします" + "CLAIM": "このタスクの作業を行うには、[担当する] をクリックします" }, "FORM": { "NONE": "フォームなし" diff --git a/lib/process-services/i18n/nb.json b/lib/process-services/i18n/nb.json index 7f59f5e2c1..470a9fefbf 100644 --- a/lib/process-services/i18n/nb.json +++ b/lib/process-services/i18n/nb.json @@ -73,13 +73,13 @@ "BUTTON": { "COMPLETE": "Fullfør", "CLAIM": "Krev", - "UNCLAIM": "Legg tilbake i kø", + "UNCLAIM": "Frigi", "DRAG-ATTACHMENT": "Slipp filer for å laste opp", "UPLOAD-ATTACHMENT": "Last opp vedlegg" }, "MESSAGES": { "NONE": "Ingen oppgavedetaljer funnet", - "CLAIM": "Klikk på Krav for å jobbe med denne oppgaven" + "CLAIM": "Klikk på Krev for å jobbe med denne oppgaven" }, "FORM": { "NONE": "Ikke noe skjema" diff --git a/lib/process-services/i18n/nl.json b/lib/process-services/i18n/nl.json index 643e43801d..bfabbfdc3e 100644 --- a/lib/process-services/i18n/nl.json +++ b/lib/process-services/i18n/nl.json @@ -73,7 +73,7 @@ "BUTTON": { "COMPLETE": "Voltooid", "CLAIM": "Claimen", - "UNCLAIM": "Opnieuw in wachtrij plaatsen", + "UNCLAIM": "Vrijgeven", "DRAG-ATTACHMENT": "Bestanden neerzetten om te uploaden", "UPLOAD-ATTACHMENT": "Bijlage uploaden" }, diff --git a/lib/process-services/i18n/pl.json b/lib/process-services/i18n/pl.json new file mode 100644 index 0000000000..942874691d --- /dev/null +++ b/lib/process-services/i18n/pl.json @@ -0,0 +1,333 @@ +{ + "DIALOG": { + "SAVE_MESSAGE": "Kliknij Zapisz, aby do listy raportów dodać raport z bieżącymi ustawieniami.", + "EXPORT_MESSAGE": "" + }, + "DATE-WIDGET": { + "START-DATE": "Data rozpoczęcia", + "END-DATE": "Data zakończenia", + "MESSAGES": { + "START-DATE-REQUIRED": "Data rozpoczęcia jest wymagana.", + "START-LESS-THAN-END-DATE": "Data rozpoczęcia musi być wcześniejsza od daty zakończenia." + } + }, + "ADF_TASK_LIST": { + "APPS": { + "TITLE": "Nie znaleziono aplikacji.", + "SUBTITLE": "Utwórz nową aplikację, którą później będzie łatwo znaleźć.", + "TASK_APP_NAME": "Aplikacja zadań" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Nie znaleziono zadań.", + "SUBTITLE": "Utwórz nowe zadanie, które później będzie łatwo znaleźć.", + "NONE": "Nie znaleziono list zadań." + } + }, + "PROPERTIES": { + "TASK_NAME": "Zadanie", + "THUMBNAIL": "Miniatura", + "DURATION": "Czas trwania", + "PARENT_TASK_ID": "Identyfikator zadania nadrzędnego", + "NAME": "Nazwa", + "ASSIGNEE": "Osoba przypisana", + "ASSIGNEE_DEFAULT": "Brak osoby przypisanej", + "PRIORITY": "Priorytet", + "DUE_DATE": "Data ukończenia", + "DUE_DATE_DEFAULT": "Brak daty", + "STATUS": "Status", + "CATEGORY": "Kategoria", + "CATEGORY_DEFAULT": "Brak kategorii", + "PARENT_NAME": "Nazwa obiektu nadrzędnego", + "PARENT_NAME_DEFAULT": "Brak obiektu nadrzędnego", + "CREATED_BY": "Utworzone przez", + "CREATED": "Utworzono", + "END_DATE": "Data zakończenia", + "ID": "Identyfikator", + "DESCRIPTION": "Opis", + "DESCRIPTION_DEFAULT": "Brak opisu", + "FORM_NAME": "Nazwa formularza", + "FORM_NAME_DEFAULT": "Brak formularza" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Widok", + "REMOVE_CONTENT": "Usuń", + "DOWNLOAD_CONTENT": "Pobierz", + "DOWNLOAD_AUDIT": "Pobierz inspekcję" + }, + "DETAILS": { + "LABELS": { + "INFO_DRAWER_TITLE": "Aktywności", + "INFO_DRAWER_TAB_ACTIVITY_TITLE": "Działanie", + "INFO_DRAWER_TAB_DETAILS_TITLE": "Szczegóły", + "ASSIGNEE": "Osoba przypisana", + "DUE": "Termin", + "FORM": "Formularz", + "PEOPLE": "Osoby, którym udostępniono to zadanie.", + "COMMENTS": "Komentarze", + "CHECKLIST": "Lista kontrolna", + "INVOLVED_PEOPLE": "Osoby zaangażowane", + "ADD_PEOPLE": "Dodaj osoby i grupy", + "ADD_ASSIGNEE": "Dodaj nową osobę przypisaną" + }, + "BUTTON": { + "COMPLETE": "Zakończ", + "CLAIM": "Przejmij", + "UNCLAIM": "Zwolnij", + "DRAG-ATTACHMENT": "Upuść i prześlij pliki", + "UPLOAD-ATTACHMENT": "Prześlij załącznik" + }, + "MESSAGES": { + "NONE": "Nie znaleziono szczegółów zadania.", + "CLAIM": "Kliknij przycisk Przejmij, aby przystąpić do pracy nad tym zadaniem." + }, + "FORM": { + "NONE": "Brak formularza" + }, + "DUE": { + "NONE": "Bez daty ukończenia" + }, + "ASSIGNEE": { + "NONE": "Brak osoby przypisanej" + }, + "PEOPLE": { + "NONE": "Brak osób zaangażowanych" + }, + "CHECKLIST": { + "NONE": "Brak listy kontrolnej", + "DIALOG": { + "TITLE": "Nowe sprawdzenie", + "CANCEL-BUTTON": "Anuluj", + "ADD-BUTTON": "Dodaj listę kontrolną", + "PLACEHOLDER": "Nazwa" + } + }, + "ERROR": { + "TITLE": "Nie można wykonać czynności.", + "DESCRIPTION": "Spróbuj ponownie lub sprawdź, czy masz dostęp.", + "CLOSE": "Zamknij" + } + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Nie wybrano filtra zadań." + } + }, + "START_TASK": { + "DEFAULT_NAME": "Moje domyślne zadanie", + "BUTTON": "Utwórz zadanie", + "FORM": { + "TITLE": "Rozpocznij zadanie", + "LABEL": { + "NONE": "Brak", + "NAME": "Nazwa", + "DESCRIPTION": "Opis", + "ATTACHFORM": "Załącz formularz", + "ASSIGNEE": "Osoba przypisana", + "FORM": "Formularz", + "DATE": "Wybierz datę" + }, + "ACTION": { + "START": "Uruchom", + "CANCEL": "Anuluj" + }, + "ERROR": { + "REQUIRED": "Pole wymagane", + "DATE": "Format daty DD/MM/RRRR", + "MAXIMUM_LENGTH": "Przekroczono długość, maksymalna długość wynosi {{characters}} znaków", + "MESSAGE": "Wprowadź inną wartość." + } + } + }, + "PEOPLE": { + "ASSIGNEE": "Osoba przypisana", + "DIALOG_CLOSE": "Zamknij", + "ADD_USER": "Dodaj", + "ADD_ASSIGNEE": "Przypisz", + "SEARCH_USER": "Szukaj użytkownika", + "SEARCH": { + "NO_USERS": "Nie znaleziono osób do zaangażowania." + } + }, + "ATTACHMENT": { + "EMPTY": { + "HEADER": "Ta lista jest pusta.", + "DRAG-AND-DROP": { + "TITLE": "Przeciągnij i upuść", + "SUBTITLE": "aby przesłać pliki" + } + }, + "EMPTY-LIST": { + "HEADER": "Brak dostępnych plików." + } + }, + "STANDALONE_TASK": { + "NO_FORM_MESSAGE": "Nie załączono formularzy", + "COMPLETE_TASK_MESSAGE": "Zadanie {{taskName}} zostało zakończone.", + "COMPLETE_TASK_SUB_MESSAGE": "Brak formularzy do dodania." + }, + "ATTACH_FORM": { + "SELECT_FORM": "Wybierz formularz do załączenia.", + "REMOVE_FORM": "Usuń formularz", + "SELECT_OPTION": "Wybierz opcję" + } + }, + "ADF_PROCESS_LIST": { + "LIST": { + "TITLE": "Nie znaleziono żadnego procesu.", + "SUBTITLE": "Utwórz nowy proces, który później będzie łatwo znaleźć.", + "SUMMARY": "Znaleziono następującą liczbę wystąpień procesu: {{total}}.", + "ERROR": "Nie można wczytać wystąpień procesu. Spróbuj ponownie lub udostępnij zespołowi IT następujący komunikat: {{errorMessage}}." + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Nie wybrano filtra wystąpień procesu." + } + }, + "PROPERTIES": { + "PROCESS_NAME": "Proces", + "NAME": "Nazwa", + "THUMBNAIL": "Miniatura", + "STATUS": "Status", + "END_DATE": "Data zakończenia", + "END_DATE_DEFAULT": "Brak daty", + "CATEGORY": "Kategoria", + "CATEGORY_DEFAULT": "Brak kategorii", + "CREATED_BY": "Utworzone przez", + "CREATED_BY_DEFAULT": "Brak osoby przypisanej", + "CREATED": "Utworzono", + "BUSINESS_KEY": "Klucz biznesowy", + "BUSINESS_KEY_DEFAULT": "Brak", + "DESCRIPTION": "Opis", + "DESCRIPTION_DEFAULT": "Brak opisu", + "ID": "Identyfikator" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Widok", + "REMOVE_CONTENT": "Usuń", + "DOWNLOAD_CONTENT": "Pobierz", + "DOWNLOAD_AUDIT": "Pobierz inspekcję", + "VIEW_TASK": "Widok zadania" + }, + "DETAILS": { + "LABELS": { + "STARTED_BY": "Uruchomione przez", + "STARTED": "Uruchomione", + "ENDED": "Zakończone", + "COMMENTS": "Komentarze", + "START_FORM": "Uruchom formularz", + "TASKS_ACTIVE": "Aktywne zadania", + "TASKS_COMPLETED": "Ukończone zadania", + "TASK_SUBTITLE": "Przypisane do użytkownika {{user}}, utworzone {{created}}." + }, + "BUTTON": { + "CANCEL": "Anuluj proces", + "CLOSE": "Zamknij", + "SHOW_DIAGRAM": "Pokaż schemat", + "DRAG-ATTACHMENT": "Upuść i prześlij pliki", + "UPLOAD-ATTACHMENT": "Prześlij załącznik" + }, + "MESSAGES": { + "NONE": "Nie znaleziono szczegółów procesu." + }, + "TASKS": { + "NO_ACTIVE": "Brak obecnie aktywnych zadań.", + "NO_COMPLETED": "Brak ukończonych zadań.", + "TASK_DETAILS": "Szczegóły zadania", + "TASK_CLOSE": "Zamknij" + }, + "COMMENTS": { + "ADD": "Dodaj komentarz", + "HEADER": "Liczba komentarzy: ({{ count }})", + "NONE": "Brak komentarzy", + "BUTTON": { + "ADD": "Dodaj komentarz" + }, + "ADD_DIALOG": { + "TITLE": "Nowy komentarz", + "LABEL": { + "MESSAGE": "Komunikat" + }, + "BUTTON": { + "ADD": "Dodaj komentarz", + "CANCEL": "Anuluj" + } + } + }, + "ADD_DIALOG": { + "TITLE": "Ustaw zmienną procesu", + "LABEL": { + "NAME": "Nazwa", + "VALUE": "Wartość", + "SCOPE": "Zakres" + } + }, + "EDIT_DIALOG": { + "TITLE": "Edytuj zmienną procesu" + }, + "ERROR_DIALOG": { + "TITLE": "Nie można wykonać czynności.", + "DESCRIPTION": "Prawdopodobnie nie dysponujesz żądanym poziomem dostępu. Skonsultuj się z zespołem IT." + } + }, + "START_PROCESS": { + "BUTTON": "Rozpocznij proces", + "NO_PROCESS_DEFINITIONS": "Nie można rozpocząć procesu, ponieważ brak dostępnych definicji procesu.", + "FORM": { + "TITLE": "Rozpocznij proces", + "LABEL": { + "TYPE": "Wybierz proces", + "NAME": "Nazwa procesu" + }, + "TYPE_PLACEHOLDER": "Wybierz jeden...", + "ACTION": { + "START": "Rozpocznij proces", + "CANCEL": "Anuluj" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Nie można wczytać definicji procesu. Sprawdź, czy masz dostęp.", + "START": "Nie można rozpocząć nowego wystąpienia procesu. Sprawdź, czy masz dostęp.", + "MAXIMUM_LENGTH": "Przekroczono długość, maksymalna długość wynosi {{characters}} znaków" + } + }, + "PROCESS-ATTACHMENT": { + "EMPTY": { + "HEADER": "Ta lista jest pusta.", + "DRAG-AND-DROP": { + "TITLE": "Przeciągnij i upuść", + "SUBTITLE": "aby przesłać pliki" + } + }, + "EMPTY-LIST": { + "HEADER": "Brak dostępnych plików." + }, + "COLUMNS": { + "NAME": "Nazwa", + "CREATED-ON": "Data utworzenia" + } + } + }, + "ADF_SIDEBAR_ACTION_MENU": { + "BUTTON": { + "CREATE": "Utwórz", + "NEW_TASK": "Nowe zadanie", + "NEW_PROCESS": "Nowy proces" + } + }, + "APP": { + "DIALOG": { + "START": "Kontynuuj", + "TITLE": "Wybierz aplikację procesu", + "LIST": "Lista aplikacji procesu", + "ERROR": "Podczas nawiązywania połączenia z usługami procesu wystąpił problem." + } + }, + "ATTACH-FILE": { + "ACTIONS": { + "LOGIN": "Zaloguj", + "CANCEL": "Anuluj", + "CHOOSE": "Wybierz" + } + } +} \ No newline at end of file diff --git a/lib/process-services/i18n/pt-BR.json b/lib/process-services/i18n/pt-BR.json index 8b0d71f70d..ff352ad286 100644 --- a/lib/process-services/i18n/pt-BR.json +++ b/lib/process-services/i18n/pt-BR.json @@ -73,7 +73,7 @@ "BUTTON": { "COMPLETE": "Completar", "CLAIM": "Reivindicar", - "UNCLAIM": "Recolocar na fila", + "UNCLAIM": "Liberar", "DRAG-ATTACHMENT": "Solte os arquivos para carregar", "UPLOAD-ATTACHMENT": "Carregar Anexo" }, diff --git a/lib/process-services/i18n/ru.json b/lib/process-services/i18n/ru.json index 04ba38464a..46a8ce4686 100644 --- a/lib/process-services/i18n/ru.json +++ b/lib/process-services/i18n/ru.json @@ -73,13 +73,13 @@ "BUTTON": { "COMPLETE": "Завершить", "CLAIM": "Принять", - "UNCLAIM": "Повторно поставить в очередь", + "UNCLAIM": "Освободить", "DRAG-ATTACHMENT": "Перетащите файлы для загрузки", "UPLOAD-ATTACHMENT": "Загрузить вложение" }, "MESSAGES": { "NONE": "Сведений о задаче не найдено", - "CLAIM": "Чтобы приступить к работе над этой задачей, нажмите \"Я выполню это\"" + "CLAIM": "Чтобы приступить к работе над этой задачей, нажмите \"Принять\"" }, "FORM": { "NONE": "Без формы" diff --git a/lib/process-services/i18n/sv.json b/lib/process-services/i18n/sv.json new file mode 100644 index 0000000000..7033258b3b --- /dev/null +++ b/lib/process-services/i18n/sv.json @@ -0,0 +1,333 @@ +{ + "DIALOG": { + "SAVE_MESSAGE": "Klicka på Spara för att lägga till en rapport med aktuella inställningar till din rapportlista.", + "EXPORT_MESSAGE": "" + }, + "DATE-WIDGET": { + "START-DATE": "Startdatum", + "END-DATE": "Slutdatum", + "MESSAGES": { + "START-DATE-REQUIRED": "Startdatum krävs", + "START-LESS-THAN-END-DATE": "Startdatum måste ligga innan slutdatum" + } + }, + "ADF_TASK_LIST": { + "APPS": { + "TITLE": "Inga program hittades", + "SUBTITLE": "Skapa ett nytt program som du enkelt hittar senare", + "TASK_APP_NAME": "Överordnad namn" + }, + "LIST": { + "MESSAGES": { + "TITLE": "Inga uppgifter hittades", + "SUBTITLE": "Skapa en ny uppgift som du enkelt hittar senare", + "NONE": "Inga uppgiftslistor hittades" + } + }, + "PROPERTIES": { + "TASK_NAME": "Uppgift", + "THUMBNAIL": "Miniatyrbild", + "DURATION": "Varaktighet", + "PARENT_TASK_ID": "Föräldrauppgifts-ID", + "NAME": "Namn", + "ASSIGNEE": "Tilldelad användare", + "ASSIGNEE_DEFAULT": "Ingen tilldelad användare", + "PRIORITY": "Prioritet", + "DUE_DATE": "Förfallodatum", + "DUE_DATE_DEFAULT": "Inget datum", + "STATUS": "Status", + "CATEGORY": "Kategori", + "CATEGORY_DEFAULT": "Ingen kategori", + "PARENT_NAME": "Överordnad namn", + "PARENT_NAME_DEFAULT": "Ingen överordnad", + "CREATED_BY": "Skapad av", + "CREATED": "Skapad", + "END_DATE": "Slutdatum", + "ID": "ID", + "DESCRIPTION": "Beskrivning", + "DESCRIPTION_DEFAULT": "Ingen beskrivning", + "FORM_NAME": "Formulärnamn", + "FORM_NAME_DEFAULT": "Inget formulär" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Visa", + "REMOVE_CONTENT": "Ta bort", + "DOWNLOAD_CONTENT": "Ladda ner", + "DOWNLOAD_AUDIT": "Ladda ner granskning" + }, + "DETAILS": { + "LABELS": { + "INFO_DRAWER_TITLE": "Aktiviteter", + "INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivitet", + "INFO_DRAWER_TAB_DETAILS_TITLE": "Detaljer", + "ASSIGNEE": "Tilldelad användare", + "DUE": "Förfaller", + "FORM": "Formulär", + "PEOPLE": "Personer den här uppgiften delas med", + "COMMENTS": "Kommentarer", + "CHECKLIST": "Checklista", + "INVOLVED_PEOPLE": "Personer involverade", + "ADD_PEOPLE": "Lägg till personer och grupper", + "ADD_ASSIGNEE": "Lägg till ny tilldelad användare" + }, + "BUTTON": { + "COMPLETE": "Slutför", + "CLAIM": "Anta", + "UNCLAIM": "Avsäga", + "DRAG-ATTACHMENT": "Släpp filer att ladda upp", + "UPLOAD-ATTACHMENT": "Ladda upp bilaga" + }, + "MESSAGES": { + "NONE": "Inga uppgiftsdetaljer hittades", + "CLAIM": "Klicka på Anta för att arbeta på den här uppgiften" + }, + "FORM": { + "NONE": "Inget formulär" + }, + "DUE": { + "NONE": "Inget förfallodatum" + }, + "ASSIGNEE": { + "NONE": "Ingen tilldelad användare" + }, + "PEOPLE": { + "NONE": "Ingen inbjuden" + }, + "CHECKLIST": { + "NONE": "Ingen checklista", + "DIALOG": { + "TITLE": "Ny kontroll", + "CANCEL-BUTTON": "Avbryt", + "ADD-BUTTON": "Lägg till checklista", + "PLACEHOLDER": "Namn" + } + }, + "ERROR": { + "TITLE": "Kunde inte slutföra åtgärden", + "DESCRIPTION": "Försök igen eller kontrolla att du har åtkomst.", + "CLOSE": "Stäng" + } + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Inget uppgiftsfilter valt" + } + }, + "START_TASK": { + "DEFAULT_NAME": "Min standarduppgift", + "BUTTON": "Skapa uppgfit", + "FORM": { + "TITLE": "Starta uppgift", + "LABEL": { + "NONE": "Ingen", + "NAME": "Namn", + "DESCRIPTION": "Beskrivning", + "ATTACHFORM": "Bifoga formulär", + "ASSIGNEE": "Tilldelad användare", + "FORM": "Formulär", + "DATE": "Välj datum" + }, + "ACTION": { + "START": "Starta", + "CANCEL": "Avbryt" + }, + "ERROR": { + "REQUIRED": "Fält obligatoriskt", + "DATE": "Datumformat DD/MM/ÅÅÅÅ", + "MAXIMUM_LENGTH": "Längd överskriden, {{characters}} tecken max.", + "MESSAGE": "Ange ett annat värde" + } + } + }, + "PEOPLE": { + "ASSIGNEE": "Tilldelad användare", + "DIALOG_CLOSE": "Stäng", + "ADD_USER": "Lägg till", + "ADD_ASSIGNEE": "Tilldela", + "SEARCH_USER": "Sök användare", + "SEARCH": { + "NO_USERS": "Hittade ingen att involvera" + } + }, + "ATTACHMENT": { + "EMPTY": { + "HEADER": "Den här listan är tom", + "DRAG-AND-DROP": { + "TITLE": "Dra och släpp", + "SUBTITLE": "för att ladda upp filer" + } + }, + "EMPTY-LIST": { + "HEADER": "Inga filer är tillgängliga" + } + }, + "STANDALONE_TASK": { + "NO_FORM_MESSAGE": "Inga formulär bifogade", + "COMPLETE_TASK_MESSAGE": "Uppgift {{taskName}} slutförd", + "COMPLETE_TASK_SUB_MESSAGE": "Inga formulär ska läggas till" + }, + "ATTACH_FORM": { + "SELECT_FORM": "Välj formulär att bifoga", + "REMOVE_FORM": "Ta bort formulär", + "SELECT_OPTION": "Välj ett alternativ" + } + }, + "ADF_PROCESS_LIST": { + "LIST": { + "TITLE": "Inga processer hittades", + "SUBTITLE": "Skapa en ny proces som du enkelt hittar senare", + "SUMMARY": "{{total}} processinstanser hittades", + "ERROR": "Kunde inte läsa in processinstanser. Försök igen eller dela följande meddelande med din IT-avdelning: {{errorMessage}}" + }, + "FILTERS": { + "MESSAGES": { + "NONE": "Inget processinstansfilter valt" + } + }, + "PROPERTIES": { + "PROCESS_NAME": "Process", + "NAME": "Namn", + "THUMBNAIL": "Miniatyrbild", + "STATUS": "Status", + "END_DATE": "Slutdatum", + "END_DATE_DEFAULT": "Inget datum", + "CATEGORY": "Kategori", + "CATEGORY_DEFAULT": "Ingen kategori", + "CREATED_BY": "Skapad av", + "CREATED_BY_DEFAULT": "Ingen tilldelad användare", + "CREATED": "Skapad", + "BUSINESS_KEY": "Affärsnyckel", + "BUSINESS_KEY_DEFAULT": "Ingen", + "DESCRIPTION": "Beskrivning", + "DESCRIPTION_DEFAULT": "Ingen beskrivning", + "ID": "ID" + }, + "MENU_ACTIONS": { + "VIEW_CONTENT": "Visa", + "REMOVE_CONTENT": "Ta bort", + "DOWNLOAD_CONTENT": "Ladda ner", + "DOWNLOAD_AUDIT": "Ladda ner granskning", + "VIEW_TASK": "Visa uppgift" + }, + "DETAILS": { + "LABELS": { + "STARTED_BY": "Startad av", + "STARTED": "Startade", + "ENDED": "Mime-typ", + "COMMENTS": "Kommentarer", + "START_FORM": "Startformulär", + "TASKS_ACTIVE": "Aktiva uppgifter", + "TASKS_COMPLETED": "Slutförda uppgifter", + "TASK_SUBTITLE": "Tilldelad till {{user}}, skapad {{created}}" + }, + "BUTTON": { + "CANCEL": "Avbryt processen", + "CLOSE": "Stäng", + "SHOW_DIAGRAM": "Visa diagram", + "DRAG-ATTACHMENT": "Släpp filer att ladda upp", + "UPLOAD-ATTACHMENT": "Ladda upp bilaga" + }, + "MESSAGES": { + "NONE": "Inga processdetaljer hittades" + }, + "TASKS": { + "NO_ACTIVE": "Inga aktiva uppgifter för närvarande", + "NO_COMPLETED": "Inga uppgifter slutförda än", + "TASK_DETAILS": "Uppgiftsdetaljer", + "TASK_CLOSE": "Stäng" + }, + "COMMENTS": { + "ADD": "Lägg till en kommentar", + "HEADER": "Kommentarer ({{ count }})", + "NONE": "Inga kommentarer", + "BUTTON": { + "ADD": "Lägg till en kommentar" + }, + "ADD_DIALOG": { + "TITLE": "Ny kommentar", + "LABEL": { + "MESSAGE": "Meddelande" + }, + "BUTTON": { + "ADD": "Lägg till kommentar", + "CANCEL": "Avbryt" + } + } + }, + "ADD_DIALOG": { + "TITLE": "Ställ in processvariabel", + "LABEL": { + "NAME": "Namn", + "VALUE": "Värde", + "SCOPE": "Definitionsområde" + } + }, + "EDIT_DIALOG": { + "TITLE": "Redigera processvariabel" + }, + "ERROR_DIALOG": { + "TITLE": "Kunde inte slutföra åtgärden", + "DESCRIPTION": "Du kanske inte har den åtkomstnivå som krävs, kolla med din IT-avdelning." + } + }, + "START_PROCESS": { + "BUTTON": "Starta process", + "NO_PROCESS_DEFINITIONS": "Du kan inte starta en process eftersom inga processdefinitioner är tillgängliga", + "FORM": { + "TITLE": "Starta process", + "LABEL": { + "TYPE": "Välj process", + "NAME": "Processnamn" + }, + "TYPE_PLACEHOLDER": "Välj en...", + "ACTION": { + "START": "Starta process", + "CANCEL": "Avbryt" + } + }, + "ERROR": { + "LOAD_PROCESS_DEFS": "Kunde inte läsa in processdefinitioner, kontrollera att du har åtkomst.", + "START": "Kunde inte starta ny processinstans, kontrollera att du har åtkomst.", + "MAXIMUM_LENGTH": "Längd överskriden, {{characters}} tecken max." + } + }, + "PROCESS-ATTACHMENT": { + "EMPTY": { + "HEADER": "Den här listan är tom", + "DRAG-AND-DROP": { + "TITLE": "Dra och släpp", + "SUBTITLE": "för att ladda upp filer" + } + }, + "EMPTY-LIST": { + "HEADER": "Inga filer är tillgängliga" + }, + "COLUMNS": { + "NAME": "Namn", + "CREATED-ON": "Skapad den" + } + } + }, + "ADF_SIDEBAR_ACTION_MENU": { + "BUTTON": { + "CREATE": "Skapa", + "NEW_TASK": "Ny uppgift", + "NEW_PROCESS": "Ny process" + } + }, + "APP": { + "DIALOG": { + "START": "Fortsätt", + "TITLE": "Välj ett processprogram", + "LIST": "Lista över processprogram", + "ERROR": "Det är problem med att ansluta till Process Services" + } + }, + "ATTACH-FILE": { + "ACTIONS": { + "LOGIN": "Inloggning", + "CANCEL": "Avbryt", + "CHOOSE": "Välj" + } + } +} \ No newline at end of file diff --git a/lib/process-services/i18n/zh-CN.json b/lib/process-services/i18n/zh-CN.json index 80731aac25..2dc7d2ed61 100644 --- a/lib/process-services/i18n/zh-CN.json +++ b/lib/process-services/i18n/zh-CN.json @@ -73,13 +73,13 @@ "BUTTON": { "COMPLETE": "完成", "CLAIM": "申领", - "UNCLAIM": "重新排队", + "UNCLAIM": "释放", "DRAG-ATTACHMENT": "放置文件以上传", "UPLOAD-ATTACHMENT": "上传附件" }, "MESSAGES": { "NONE": "未找到任务详情", - "CLAIM": "单击声明,以处理该任务" + "CLAIM": "单击“申领”以处理此任务" }, "FORM": { "NONE": "无表单" From 0fa9b2fd6b396ee124137f836fb24fae21e41568 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 2 May 2019 10:11:47 +0100 Subject: [PATCH 191/208] Create license-info-v3.2.0.md --- docs/license-info/license-info-v3.2.0.md | 479 +++++++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 docs/license-info/license-info-v3.2.0.md diff --git a/docs/license-info/license-info-v3.2.0.md b/docs/license-info/license-info-v3.2.0.md new file mode 100644 index 0000000000..0bd168f678 --- /dev/null +++ b/docs/license-info/license-info-v3.2.0.md @@ -0,0 +1,479 @@ +--- +Title: License info, ADF v3.2.0 +--- + +# License information for ADF v3.2.0 + +This page lists all third party libraries that ADF v3.2.0 depends on. + +## Libraries + +| Name | Version | License | +| -- | -- | -- | +| [@alfresco/adf-content-services](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/adf-core](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/adf-extensions](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/adf-insights](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/adf-process-services-cloud](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/adf-process-services](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/adf-testing](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@alfresco/js-api](https://github.com/Alfresco/alfresco-js-api) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [@angular/animations](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/cdk](https://github.com/angular/material2) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/common](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/compiler](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/core](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/flex-layout](https://github.com/angular/flex-layout) | 7.0.0-beta.23 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/forms](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/http](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/material-moment-adapter](https://github.com/angular/material2) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/material](https://github.com/angular/material2) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/platform-browser](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@angular/router](https://github.com/angular/angular) | 7.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@mat-datetimepicker/moment](https://github.com/kuhnroyal/mat-datetimepicker) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@ngx-translate/core](https://github.com/ngx-translate/core) | 11.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/ast](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/floating-point-hex-parser](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/helper-api-error](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/helper-buffer](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/helper-code-frame](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/helper-fsm](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [@webassemblyjs/helper-module-context](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/helper-wasm-bytecode](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/helper-wasm-section](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/ieee754](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/leb128](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/utf8](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/wasm-edit](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/wasm-gen](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/wasm-opt](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/wasm-parser](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/wast-parser](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@webassemblyjs/wast-printer](https://github.com/xtuc/webassemblyjs) | 1.7.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [@xtuc/ieee754](https://github.com/feross/ieee754) | 1.2.0 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [@xtuc/long](https://github.com/dcodeIO/long.js) | 4.2.1 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [abbrev](https://github.com/isaacs/abbrev-js) | 1.1.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [acorn-dynamic-import](https://github.com/kesne/acorn-dynamic-import) | 4.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [acorn](https://github.com/acornjs/acorn) | 6.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [adf-monaco-extension](https://github.com/eromano/aca-monaco-extension) | 0.0.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [adf-tslint-rules](https://github.com/Alfresco/alfresco-ng2-components) | 0.0.6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [ajv-errors](https://github.com/epoberezkin/ajv-errors) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ajv-keywords](https://github.com/epoberezkin/ajv-keywords) | 3.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ajv](https://github.com/epoberezkin/ajv) | 6.10.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [alfresco-components](https://github.com/Alfresco/alfresco-ng2-components) | 3.2.0-beta6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [ansi-regex](https://github.com/chalk/ansi-regex) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ansi-styles](https://github.com/chalk/ansi-styles) | 2.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ansi-styles](https://github.com/chalk/ansi-styles) | 3.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [anymatch](https://github.com/micromatch/anymatch) | 2.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [app-root-path](https://github.com/inxilpro/node-app-root-path) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [app-root-path](https://github.com/inxilpro/node-app-root-path) | 2.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [aproba](https://github.com/iarna/aproba) | 1.2.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [are-we-there-yet](https://github.com/iarna/are-we-there-yet) | 1.1.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [argparse](https://github.com/nodeca/argparse) | 1.0.10 | [MIT](http://www.opensource.org/licenses/MIT) | +| [aria-query](https://github.com/A11yance/aria-query) | 3.0.0 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [arr-diff](https://github.com/jonschlinkert/arr-diff) | 4.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [arr-flatten](https://github.com/jonschlinkert/arr-flatten) | 1.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [arr-union](https://github.com/jonschlinkert/arr-union) | 3.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [array-unique](https://github.com/jonschlinkert/array-unique) | 0.3.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [asn1.js](https://github.com/indutny/asn1.js) | 4.10.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [assert](https://github.com/defunctzombie/commonjs-assert) | 1.4.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [assign-symbols](https://github.com/jonschlinkert/assign-symbols) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ast-types-flow](https://github.com/kyldvs/ast-types-flow) | 0.0.7 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [async-each](https://github.com/paulmillr/async-each) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [asynckit](https://github.com/alexindigo/asynckit) | 0.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [atob](git://git.coolaj86.com/coolaj86/atob.js) | 2.1.2 | ([MIT](http://www.opensource.org/licenses/MIT) OR [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0)) | +| [axobject-query](https://github.com/A11yance/axobject-query) | 2.0.2 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [babel-code-frame](https://github.com/babel/babel/tree/master/packages/babel-code-frame) | 6.26.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [balanced-match](https://github.com/juliangruber/balanced-match) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [base64-js](https://github.com/beatgammit/base64-js) | 1.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [base](https://github.com/node-base/base) | 0.11.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [big.js](https://github.com/MikeMcl/big.js) | 5.2.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [binary-extensions](https://github.com/sindresorhus/binary-extensions) | 1.13.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [bluebird](https://github.com/petkaantonov/bluebird) | 3.5.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [bn.js](https://github.com/indutny/bn.js) | 4.11.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [brace-expansion](https://github.com/juliangruber/brace-expansion) | 1.1.11 | [MIT](http://www.opensource.org/licenses/MIT) | +| [braces](https://github.com/micromatch/braces) | 2.3.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [brorand](https://github.com/indutny/brorand) | 1.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [browserify-aes](https://github.com/crypto-browserify/browserify-aes) | 1.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [browserify-cipher](https://github.com/crypto-browserify/browserify-cipher) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [browserify-des](https://github.com/crypto-browserify/browserify-des) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [browserify-rsa](https://github.com/crypto-browserify/browserify-rsa) | 4.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [browserify-sign](https://github.com/crypto-browserify/browserify-sign) | 4.0.4 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [browserify-zlib](https://github.com/devongovett/browserify-zlib) | 0.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [buffer-from](https://github.com/LinusU/buffer-from) | 1.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [buffer-xor](https://github.com/crypto-browserify/buffer-xor) | 1.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [buffer](https://github.com/feross/buffer) | 4.9.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [builtin-modules](https://github.com/sindresorhus/builtin-modules) | 1.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [builtin-status-codes](https://github.com/bendrucker/builtin-status-codes) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [cacache](https://github.com/zkat/cacache) | 11.3.2 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [cache-base](https://github.com/jonschlinkert/cache-base) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chalk](https://github.com/chalk/chalk) | 1.1.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chalk](https://github.com/chalk/chalk) | 2.4.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chart.js](https://github.com/chartjs/Chart.js) | 2.5.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chart.js](https://github.com/chartjs/Chart.js) | 2.8.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chartjs-color-string](https://github.com/chartjs/chartjs-color-string) | 0.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chartjs-color](https://github.com/chartjs/chartjs-color) | 2.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chokidar](https://github.com/paulmillr/chokidar) | 2.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [chownr](https://github.com/isaacs/chownr) | 1.1.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [chrome-trace-event](github.com:samccone/chrome-trace-event) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [cipher-base](https://github.com/crypto-browserify/cipher-base) | 1.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [class-utils](https://github.com/jonschlinkert/class-utils) | 0.3.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [classlist.js](https://github.com/eligrey/classList.js) | 1.1.20150312 | Public Domain | +| [code-point-at](https://github.com/sindresorhus/code-point-at) | 1.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [codelyzer](https://github.com/mgechev/codelyzer) | 5.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [collection-visit](https://github.com/jonschlinkert/collection-visit) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [color-convert](https://github.com/harthur/color-convert) | 0.5.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [color-convert](https://github.com/Qix-/color-convert) | 1.9.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [color-name](https://github.com/dfcreative/color-name) | 1.1.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [color-name](https://github.com/colorjs/color-name) | 1.1.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [combined-stream](https://github.com/felixge/node-combined-stream) | 1.0.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [commander](https://github.com/tj/commander.js) | 2.19.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [commondir](https://github.com/substack/node-commondir) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [component-emitter](https://github.com/component/emitter) | 1.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [concat-map](https://github.com/substack/node-concat-map) | 0.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [concat-stream](https://github.com/maxogden/concat-stream) | 1.6.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [console-browserify](https://github.com/Raynos/console-browserify) | 1.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [console-control-strings](https://github.com/iarna/console-control-strings) | 1.1.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [constants-browserify](https://github.com/juliangruber/constants-browserify) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [cookiejar](https://github.com/bmeck/node-cookiejar) | 2.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [copy-concurrently](https://github.com/npm/copy-concurrently) | 1.0.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [copy-descriptor](https://github.com/jonschlinkert/copy-descriptor) | 0.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [core-js](https://github.com/zloirock/core-js) | 2.6.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [core-util-is](https://github.com/isaacs/core-util-is) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [create-ecdh](https://github.com/crypto-browserify/createECDH) | 4.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [create-hash](https://github.com/crypto-browserify/createHash) | 1.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [create-hmac](https://github.com/crypto-browserify/createHmac) | 1.1.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [crypto-browserify](https://github.com/crypto-browserify/crypto-browserify) | 3.12.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [css-selector-tokenizer](https://github.com/css-modules/css-selector-tokenizer) | 0.7.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [css-selector-tokenizer](https://github.com/css-modules/css-selector-tokenizer) | 0.7.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [cssauron](https://github.com/chrisdickinson/cssauron) | 1.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [cssesc](https://github.com/mathiasbynens/cssesc) | 0.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [custom-event-polyfill](https://github.com/krambuhl/custom-event-polyfill) | 0.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [cyclist](https://github.com/mafintosh/cyclist) | 0.2.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [d](https://github.com/medikoo/d) | 0.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [d](https://github.com/medikoo/d) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [damerau-levenshtein](https://github.com/lzrski/node-damerau-levenshtein) | 1.0.4 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [date-now](https://github.com/Colingo/date-now) | 0.1.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [debug](https://github.com/visionmedia/debug) | 2.6.9 | [MIT](http://www.opensource.org/licenses/MIT) | +| [debug](https://github.com/visionmedia/debug) | 3.2.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) | 0.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [deep-extend](https://github.com/unclechu/node-deep-extend) | 0.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [define-property](https://github.com/jonschlinkert/define-property) | 0.2.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [define-property](https://github.com/jonschlinkert/define-property) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [define-property](https://github.com/jonschlinkert/define-property) | 2.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [delayed-stream](https://github.com/felixge/node-delayed-stream) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [delegates](https://github.com/visionmedia/node-delegates) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [des.js](https://github.com/indutny/des.js) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [detect-libc](https://github.com/lovell/detect-libc) | 1.0.3 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [diff](https://github.com/kpdecker/jsdiff) | 3.5.0 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [diffie-hellman](https://github.com/crypto-browserify/diffie-hellman) | 5.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [domain-browser](https://github.com/bevry/domain-browser) | 1.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [duplexify](https://github.com/mafintosh/duplexify) | 3.7.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [elliptic](https://github.com/indutny/elliptic) | 6.4.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [emoji-regex](https://github.com/mathiasbynens/emoji-regex) | 6.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [emojis-list](https://github.com/kikobeats/emojis-list) | 2.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [end-of-stream](https://github.com/mafintosh/end-of-stream) | 1.4.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [enhanced-resolve](https://github.com/webpack/enhanced-resolve) | 4.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [errno](https://github.com/rvagg/node-errno) | 0.1.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [es5-ext](https://github.com/medikoo/es5-ext) | 0.10.49 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [es6-iterator](https://github.com/medikoo/es6-iterator) | 2.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [es6-symbol](https://github.com/medikoo/es6-symbol) | 3.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [escape-string-regexp](https://github.com/sindresorhus/escape-string-regexp) | 1.0.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [eslint-scope](https://github.com/eslint/eslint-scope) | 4.0.3 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [esprima](https://github.com/jquery/esprima) | 4.0.1 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [esrecurse](https://github.com/estools/esrecurse) | 4.2.1 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [estraverse](https://github.com/estools/estraverse) | 4.2.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [esutils](https://github.com/estools/esutils) | 2.0.2 | [BSD](http://www.opensource.org/licenses/BSD-2-Clause) | +| [eve-raphael](https://github.com/tomasAlabes/eve) | 0.5.0 | [Apache](http://www.apache.org/licenses/LICENSE-2.0) | +| [event-emitter](https://github.com/medikoo/event-emitter) | 0.3.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [events](https://github.com/Gozala/events) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [evp_bytestokey](https://github.com/crypto-browserify/EVP_BytesToKey) | 1.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [expand-brackets](https://github.com/jonschlinkert/expand-brackets) | 2.1.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [extend-shallow](https://github.com/jonschlinkert/extend-shallow) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [extend-shallow](https://github.com/jonschlinkert/extend-shallow) | 3.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [extend](https://github.com/justmoon/node-extend) | 2.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [extend](https://github.com/justmoon/node-extend) | 3.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [extglob](https://github.com/micromatch/extglob) | 2.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [fast-deep-equal](https://github.com/epoberezkin/fast-deep-equal) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [fastparse](https://github.com/webpack/fastparse) | 1.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [figgy-pudding](https://github.com/zkat/figgy-pudding) | 3.5.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [fill-range](https://github.com/jonschlinkert/fill-range) | 4.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [find-cache-dir](https://github.com/avajs/find-cache-dir) | 2.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [find-up](https://github.com/sindresorhus/find-up) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [flush-write-stream](https://github.com/mafintosh/flush-write-stream) | 1.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [for-in](https://github.com/jonschlinkert/for-in) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [form-data](https://github.com/form-data/form-data) | 2.3.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [formidable](https://github.com/felixge/node-formidable) | 1.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [fragment-cache](https://github.com/jonschlinkert/fragment-cache) | 0.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [from2](https://github.com/hughsk/from2) | 2.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [fs-minipass](https://github.com/npm/fs-minipass) | 1.2.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [fs-write-stream-atomic](https://github.com/npm/fs-write-stream-atomic) | 1.0.10 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [fs.realpath](https://github.com/isaacs/fs.realpath) | 1.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [fsevents](https://github.com/strongloop/fsevents) | 1.2.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [gauge](https://github.com/iarna/gauge) | 2.7.4 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [get-value](https://github.com/jonschlinkert/get-value) | 2.0.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [github-slugger](https://github.com/Flet/github-slugger) | 1.2.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [glob-parent](https://github.com/es128/glob-parent) | 3.1.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [glob](https://github.com/isaacs/node-glob) | 7.1.3 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [graceful-fs](https://github.com/isaacs/node-graceful-fs) | 4.1.15 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [hammerjs](https://github.com/hammerjs/hammer.js) | 2.0.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [has-ansi](https://github.com/sindresorhus/has-ansi) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [has-flag](https://github.com/sindresorhus/has-flag) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [has-unicode](https://github.com/iarna/has-unicode) | 2.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [has-value](https://github.com/jonschlinkert/has-value) | 0.3.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [has-value](https://github.com/jonschlinkert/has-value) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [has-values](https://github.com/jonschlinkert/has-values) | 0.1.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [has-values](https://github.com/jonschlinkert/has-values) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [hash-base](https://github.com/crypto-browserify/hash-base) | 3.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [hash.js](https://github.com/indutny/hash.js) | 1.1.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [hmac-drbg](https://github.com/indutny/hmac-drbg) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [hosted-git-info](https://github.com/npm/hosted-git-info) | 2.7.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [https-browserify](https://github.com/substack/https-browserify) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [iconv-lite](https://github.com/ashtuchkin/iconv-lite) | 0.4.24 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ieee754](https://github.com/feross/ieee754) | 1.1.12 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [iferr](https://github.com/shesek/iferr) | 0.1.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ignore-walk](https://github.com/isaacs/ignore-walk) | 3.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [imurmurhash](https://github.com/jensyt/imurmurhash-js) | 0.1.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [indexof](https://github.com/component/indexof) | 0.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [inflight](https://github.com/npm/inflight) | 1.0.6 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [inherits](https://github.com/isaacs/inherits) | 2.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [inherits](https://github.com/isaacs/inherits) | 2.0.3 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [ini](https://github.com/isaacs/ini) | 1.3.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [is-accessor-descriptor](https://github.com/jonschlinkert/is-accessor-descriptor) | 0.1.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-accessor-descriptor](https://github.com/jonschlinkert/is-accessor-descriptor) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-binary-path](https://github.com/sindresorhus/is-binary-path) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-buffer](https://github.com/feross/is-buffer) | 1.1.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-data-descriptor](https://github.com/jonschlinkert/is-data-descriptor) | 0.1.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-data-descriptor](https://github.com/jonschlinkert/is-data-descriptor) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-descriptor](https://github.com/jonschlinkert/is-descriptor) | 0.1.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-descriptor](https://github.com/jonschlinkert/is-descriptor) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-extendable](https://github.com/jonschlinkert/is-extendable) | 0.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-extendable](https://github.com/jonschlinkert/is-extendable) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-extglob](https://github.com/jonschlinkert/is-extglob) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-fullwidth-code-point](https://github.com/sindresorhus/is-fullwidth-code-point) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-glob](https://github.com/jonschlinkert/is-glob) | 3.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-glob](https://github.com/jonschlinkert/is-glob) | 4.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-number](https://github.com/jonschlinkert/is-number) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-plain-object](https://github.com/jonschlinkert/is-plain-object) | 2.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [is-windows](https://github.com/jonschlinkert/is-windows) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [isarray](https://github.com/juliangruber/isarray) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [isobject](https://github.com/jonschlinkert/isobject) | 2.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [isobject](https://github.com/jonschlinkert/isobject) | 3.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [js-tokens](https://github.com/lydell/js-tokens) | 3.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [js-yaml](https://github.com/nodeca/js-yaml) | 3.12.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [jsesc](https://github.com/mathiasbynens/jsesc) | 0.5.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [json-parse-better-errors](https://github.com/zkat/json-parse-better-errors) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [json-schema-traverse](https://github.com/epoberezkin/json-schema-traverse) | 0.4.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [json5](https://github.com/json5/json5) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [kind-of](https://github.com/jonschlinkert/kind-of) | 3.2.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [kind-of](https://github.com/jonschlinkert/kind-of) | 4.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [kind-of](https://github.com/jonschlinkert/kind-of) | 5.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [kind-of](https://github.com/jonschlinkert/kind-of) | 6.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [levenshtein-edit-distance](https://github.com/wooorm/levenshtein-edit-distance) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [loader-runner](https://github.com/webpack/loader-runner) | 2.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [loader-utils](https://github.com/webpack/loader-utils) | 1.2.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [locate-path](https://github.com/sindresorhus/locate-path) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [lodash.debounce](https://github.com/lodash/lodash) | 4.0.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [lru-cache](https://github.com/isaacs/node-lru-cache) | 5.1.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [make-dir](https://github.com/sindresorhus/make-dir) | 2.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [map-cache](https://github.com/jonschlinkert/map-cache) | 0.2.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [map-visit](https://github.com/jonschlinkert/map-visit) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [md5.js](https://github.com/crypto-browserify/md5.js) | 1.3.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mdast-util-definitions](https://github.com/syntax-tree/mdast-util-definitions) | 1.2.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mdast-util-to-string](https://github.com/syntax-tree/mdast-util-to-string) | 1.0.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [memory-fs](https://github.com/webpack/memory-fs) | 0.4.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [methods](https://github.com/jshttp/methods) | 1.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [micromatch](https://github.com/micromatch/micromatch) | 3.1.10 | [MIT](http://www.opensource.org/licenses/MIT) | +| [miller-rabin](https://github.com/indutny/miller-rabin) | 4.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mime-db](https://github.com/jshttp/mime-db) | 1.38.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mime-types](https://github.com/jshttp/mime-types) | 2.1.22 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mime](https://github.com/broofa/node-mime) | 1.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [minimalistic-assert](https://github.com/calvinmetcalf/minimalistic-assert) | 1.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [minimalistic-crypto-utils](https://github.com/indutny/minimalistic-crypto-utils) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [minimatch-browser](https://github.com/isaacs/minimatch) | 1.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [minimatch](https://github.com/isaacs/minimatch) | 3.0.4 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [minimist](https://github.com/substack/minimist) | 0.0.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [minimist](https://github.com/substack/minimist) | 1.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [minipass](https://github.com/isaacs/minipass) | 2.3.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [minizlib](https://github.com/isaacs/minizlib) | 1.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mississippi](https://github.com/maxogden/mississippi) | 3.0.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [mixin-deep](https://github.com/jonschlinkert/mixin-deep) | 1.3.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [mkdirp](https://github.com/substack/node-mkdirp) | 0.5.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [moment-es6](https://github.com/Agamnentzar/moment-es6) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [moment](https://github.com/moment/moment) | 2.22.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [move-concurrently](https://github.com/npm/move-concurrently) | 1.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [ms](https://github.com/zeit/ms) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ms](https://github.com/zeit/ms) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [nan](https://github.com/nodejs/nan) | 2.13.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [nanomatch](https://github.com/micromatch/nanomatch) | 1.2.13 | [MIT](http://www.opensource.org/licenses/MIT) | +| [needle](https://github.com/tomas/needle) | 2.2.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [neo-async](https://github.com/suguru03/neo-async) | 2.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [next-tick](https://github.com/medikoo/next-tick) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ng2-charts](https://github.com/valor-software/ng2-charts) | 1.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ngx-monaco-editor](https://github.com/atularen/ngx-monaco-editor) | 7.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [node-ensure](https://github.com/bauerca/node-ensure) | 0.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [node-libs-browser](https://github.com/webpack/node-libs-browser) | 2.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) | 0.10.3 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [nopt](https://github.com/npm/nopt) | 4.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [normalize-path](https://github.com/jonschlinkert/normalize-path) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [npm-bundled](https://github.com/npm/npm-bundled) | 1.0.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [npm-packlist](https://github.com/npm/npm-packlist) | 1.2.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [npmlog](https://github.com/npm/npmlog) | 4.1.2 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [number-is-nan](https://github.com/sindresorhus/number-is-nan) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [object-assign](https://github.com/sindresorhus/object-assign) | 4.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [object-copy](https://github.com/jonschlinkert/object-copy) | 0.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [object-visit](https://github.com/jonschlinkert/object-visit) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [object.pick](https://github.com/jonschlinkert/object.pick) | 1.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [once](https://github.com/isaacs/once) | 1.4.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [os-browserify](https://github.com/CoderPuppy/os-browserify) | 0.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [os-homedir](https://github.com/sindresorhus/os-homedir) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [os-tmpdir](https://github.com/sindresorhus/os-tmpdir) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [osenv](https://github.com/npm/osenv) | 0.1.5 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [p-limit](https://github.com/sindresorhus/p-limit) | 2.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [p-locate](https://github.com/sindresorhus/p-locate) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [p-try](https://github.com/sindresorhus/p-try) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pako](https://github.com/nodeca/pako) | 1.0.10 | ([MIT](http://www.opensource.org/licenses/MIT) AND [Zlib](http://www.zlib.net/zlib_license.html)) | +| [parallel-transform](https://github.com/mafintosh/parallel-transform) | 1.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [parse-asn1](https://github.com/crypto-browserify/parse-asn1) | 5.1.4 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [parse5](https://github.com/inikulin/parse5) | 5.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pascalcase](https://github.com/jonschlinkert/pascalcase) | 0.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [path-browserify](https://github.com/substack/path-browserify) | 0.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [path-dirname](https://github.com/es128/path-dirname) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [path-exists](https://github.com/sindresorhus/path-exists) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [path-is-absolute](https://github.com/sindresorhus/path-is-absolute) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [path-parse](https://github.com/jbgutierrez/path-parse) | 1.0.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pbkdf2](https://github.com/crypto-browserify/pbkdf2) | 3.0.17 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pdfjs-dist](https://github.com/mozilla/pdfjs-dist) | 2.0.943 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [pify](https://github.com/sindresorhus/pify) | 4.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pkg-dir](https://github.com/sindresorhus/pkg-dir) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [posix-character-classes](https://github.com/jonschlinkert/posix-character-classes) | 0.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [process-nextick-args](https://github.com/calvinmetcalf/process-nextick-args) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [process](https://github.com/shtylman/node-process) | 0.11.10 | [MIT](http://www.opensource.org/licenses/MIT) | +| [promise-inflight](https://github.com/iarna/promise-inflight) | 1.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [propose](https://github.com/liushuping/propose) | 0.0.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [prr](https://github.com/rvagg/prr) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [public-encrypt](https://github.com/crypto-browserify/publicEncrypt) | 4.0.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pump](https://github.com/mafintosh/pump) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pump](https://github.com/mafintosh/pump) | 3.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [pumpify](https://github.com/mafintosh/pumpify) | 1.5.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [punycode](https://github.com/bestiejs/punycode.js) | 1.3.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [punycode](https://github.com/bestiejs/punycode.js) | 1.4.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [punycode](https://github.com/bestiejs/punycode.js) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [qs](https://github.com/ljharb/qs) | 6.7.0 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [querystring-es3](https://github.com/mike-spainhower/querystring) | 0.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [querystring](https://github.com/Gozala/querystring) | 0.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [randombytes](https://github.com/crypto-browserify/randombytes) | 2.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [randomfill](https://github.com/crypto-browserify/randomfill) | 1.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [raphael](https://github.com/DmitryBaranovskiy/raphael) | 2.2.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [rc](https://github.com/dominictarr/rc) | 1.2.8 | ([BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) OR [MIT](http://www.opensource.org/licenses/MIT) OR [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0)) | +| [readable-stream](https://github.com/nodejs/readable-stream) | 2.3.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [readdirp](https://github.com/paulmillr/readdirp) | 2.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [reflect-metadata](https://github.com/rbuckton/reflect-metadata) | 0.1.13 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [regenerate](https://github.com/mathiasbynens/regenerate) | 1.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [regex-not](https://github.com/jonschlinkert/regex-not) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [regexpu-core](https://github.com/mathiasbynens/regexpu-core) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [regjsgen](https://github.com/d10/regjsgen) | 0.2.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [regjsparser](https://github.com/jviereck/regjsparser) | 0.1.5 | [BSD](http://www.opensource.org/licenses/BSD-2-Clause) | +| [remark-validate-links](https://github.com/remarkjs/remark-validate-links) | 8.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [remove-trailing-separator](https://github.com/darsain/remove-trailing-separator) | 1.1.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [repeat-element](https://github.com/jonschlinkert/repeat-element) | 1.1.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [repeat-string](https://github.com/jonschlinkert/repeat-string) | 1.6.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [resolve-url](https://github.com/lydell/resolve-url) | 0.2.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [resolve](https://github.com/browserify/resolve) | 1.10.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [ret](https://github.com/fent/ret.js) | 0.1.15 | [MIT](http://www.opensource.org/licenses/MIT) | +| [rimraf](https://github.com/isaacs/rimraf) | 2.6.3 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [ripemd160](https://github.com/crypto-browserify/ripemd160) | 2.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [run-queue](https://github.com/iarna/run-queue) | 1.0.3 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [rxjs](https://github.com/reactivex/rxjs) | 6.4.0 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [safe-buffer](https://github.com/feross/safe-buffer) | 5.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [safe-regex](https://github.com/substack/safe-regex) | 1.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [safer-buffer](https://github.com/ChALkeR/safer-buffer) | 2.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [sax](https://github.com/isaacs/sax-js) | 1.2.4 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [schema-utils](https://github.com/webpack-contrib/schema-utils) | 0.4.7 | [MIT](http://www.opensource.org/licenses/MIT) | +| [schema-utils](https://github.com/webpack-contrib/schema-utils) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [semver-dsl](https://github.com/mgechev/semver-dsl) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [semver](https://github.com/npm/node-semver) | 5.6.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [serialize-javascript](https://github.com/yahoo/serialize-javascript) | 1.6.1 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [set-blocking](https://github.com/yargs/set-blocking) | 2.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [set-value](https://github.com/jonschlinkert/set-value) | 0.4.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [set-value](https://github.com/jonschlinkert/set-value) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [setimmediate](https://github.com/YuzuJS/setImmediate) | 1.0.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [sha.js](https://github.com/crypto-browserify/sha.js) | 2.4.11 | ([MIT](http://www.opensource.org/licenses/MIT) AND [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause)) | +| [signal-exit](https://github.com/tapjs/signal-exit) | 3.0.2 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [snapdragon-node](https://github.com/jonschlinkert/snapdragon-node) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [snapdragon-util](https://github.com/jonschlinkert/snapdragon-util) | 3.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [snapdragon](https://github.com/jonschlinkert/snapdragon) | 0.8.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [source-list-map](https://github.com/webpack/source-list-map) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [source-map-resolve](https://github.com/lydell/source-map-resolve) | 0.5.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [source-map-support](https://github.com/evanw/node-source-map-support) | 0.5.10 | [MIT](http://www.opensource.org/licenses/MIT) | +| [source-map-url](https://github.com/lydell/source-map-url) | 0.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [source-map](https://github.com/mozilla/source-map) | 0.5.6 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [source-map](https://github.com/mozilla/source-map) | 0.5.7 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [source-map](https://github.com/mozilla/source-map) | 0.6.1 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [split-string](https://github.com/jonschlinkert/split-string) | 3.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [sprintf-js](https://github.com/alexei/sprintf.js) | 1.0.3 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [sprintf-js](https://github.com/alexei/sprintf.js) | 1.1.2 | [BSD-3-Clause](http://www.opensource.org/licenses/BSD-3-Clause) | +| [ssri](https://github.com/zkat/ssri) | 6.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [static-extend](https://github.com/jonschlinkert/static-extend) | 0.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [stream-browserify](https://github.com/browserify/stream-browserify) | 2.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [stream-each](https://github.com/mafintosh/stream-each) | 1.2.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [stream-http](https://github.com/jhiesey/stream-http) | 2.8.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [stream-shift](https://github.com/mafintosh/stream-shift) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [string-width](https://github.com/sindresorhus/string-width) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [string_decoder](https://github.com/nodejs/string_decoder) | 1.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [strip-ansi](https://github.com/chalk/strip-ansi) | 3.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [strip-json-comments](https://github.com/sindresorhus/strip-json-comments) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [superagent](https://github.com/visionmedia/superagent) | 3.8.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [supports-color](https://github.com/chalk/supports-color) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [supports-color](https://github.com/chalk/supports-color) | 5.5.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [systemjs](https://github.com/systemjs/systemjs) | 0.19.27 | [MIT](http://www.opensource.org/licenses/MIT) | +| [tapable](https://github.com/webpack/tapable) | 1.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [tar](https://github.com/npm/node-tar) | 4.4.8 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [terser-webpack-plugin](https://github.com/webpack-contrib/terser-webpack-plugin) | 1.2.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [terser](https://github.com/fabiosantoscode/terser) | 3.17.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [through2](https://github.com/rvagg/through2) | 2.0.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [through](https://github.com/dominictarr/through) | 2.3.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [timers-browserify](https://github.com/jryans/timers-browserify) | 2.0.10 | [MIT](http://www.opensource.org/licenses/MIT) | +| [to-arraybuffer](https://github.com/jhiesey/to-arraybuffer) | 1.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [to-object-path](https://github.com/jonschlinkert/to-object-path) | 0.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [to-regex-range](https://github.com/micromatch/to-regex-range) | 2.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [to-regex](https://github.com/jonschlinkert/to-regex) | 3.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [tslib](https://github.com/Microsoft/tslib) | 1.9.3 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [tslint](https://github.com/palantir/tslint) | 5.9.1 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [tsutils](https://github.com/ajafff/tsutils) | 2.29.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [tty-browserify](https://github.com/substack/tty-browserify) | 0.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [typedarray](https://github.com/substack/typedarray) | 0.0.6 | [MIT](http://www.opensource.org/licenses/MIT) | +| [typescript](https://github.com/Microsoft/TypeScript) | 3.1.6 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [union-value](https://github.com/jonschlinkert/union-value) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [unique-filename](https://github.com/iarna/unique-filename) | 1.1.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [unique-slug](https://github.com/iarna/unique-slug) | 2.0.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [unist-util-is](https://github.com/syntax-tree/unist-util-is) | 2.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [unist-util-visit-parents](https://github.com/syntax-tree/unist-util-visit-parents) | 2.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [unist-util-visit](https://github.com/syntax-tree/unist-util-visit) | 1.4.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [unset-value](https://github.com/jonschlinkert/unset-value) | 1.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [upath](https://github.com/anodynos/upath) | 1.1.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [uri-js](https://github.com/garycourt/uri-js) | 4.2.2 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) | +| [urix](https://github.com/lydell/urix) | 0.1.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [url](https://github.com/defunctzombie/node-url) | 0.11.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [urljoin](https://github.com/yanni4night/urljoin) | 0.1.5 | [MIT](http://www.opensource.org/licenses/MIT) | +| [use](https://github.com/jonschlinkert/use) | 3.1.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [util-deprecate](https://github.com/TooTallNate/util-deprecate) | 1.0.2 | [MIT](http://www.opensource.org/licenses/MIT) | +| [util](https://github.com/defunctzombie/node-util) | 0.10.3 | [MIT](http://www.opensource.org/licenses/MIT) | +| [util](https://github.com/defunctzombie/node-util) | 0.11.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [vm-browserify](https://github.com/substack/vm-browserify) | 0.0.4 | [MIT](http://www.opensource.org/licenses/MIT) | +| [watchpack](https://github.com/webpack/watchpack) | 1.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [web-animations-js](https://github.com/web-animations/web-animations-js) | 2.3.1 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | +| [webpack-sources](https://github.com/webpack/webpack-sources) | 1.3.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [webpack](https://github.com/webpack/webpack) | 4.29.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [when](https://github.com/cujojs/when) | 3.7.8 | [MIT](http://www.opensource.org/licenses/MIT) | +| [wide-align](https://github.com/iarna/wide-align) | 1.1.3 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [worker-farm](https://github.com/rvagg/node-worker-farm) | 1.6.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [worker-loader](https://github.com/webpack-contrib/worker-loader) | 2.0.0 | [MIT](http://www.opensource.org/licenses/MIT) | +| [wrappy](https://github.com/npm/wrappy) | 1.0.2 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [xtend](https://github.com/Raynos/xtend) | 4.0.1 | [MIT](http://www.opensource.org/licenses/MIT) | +| [y18n](https://github.com/yargs/y18n) | 4.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [yallist](https://github.com/isaacs/yallist) | 3.0.3 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) | +| [zone.js](https://github.com/angular/zone.js) | 0.8.29 | [MIT](http://www.opensource.org/licenses/MIT) | From 3afd2b24fcee11fd2ded832edc5c83ba168714fc Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 2 May 2019 10:12:41 +0100 Subject: [PATCH 192/208] Update README.md --- docs/license-info/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/license-info/README.md b/docs/license-info/README.md index ea7fe6c384..b94cc9a9fd 100644 --- a/docs/license-info/README.md +++ b/docs/license-info/README.md @@ -7,5 +7,6 @@ Github only: true The pages linked below contain the licenses for all third party dependencies of ADF. +- [ADF v3.2](license-info-v3.2.0.md) - [ADF v3.1](license-info-v3.1.0.md) -- [ADF v3.0](license-info-v3.0.0.md) \ No newline at end of file +- [ADF v3.0](license-info-v3.0.0.md) From 6eec4858914bfa2eee4f59f2698cb37d224798ee Mon Sep 17 00:00:00 2001 From: Francesco Corti <fcorti@gmail.com> Date: Thu, 2 May 2019 11:13:28 +0200 Subject: [PATCH 193/208] [ADF-4429] Process List Cloud - Remove the pagination parameters. (#4682) --- .../components/process-list-cloud.component.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/process-services-cloud/components/process-list-cloud.component.md b/docs/process-services-cloud/components/process-list-cloud.component.md index 478daa2f00..07036c0723 100644 --- a/docs/process-services-cloud/components/process-list-cloud.component.md +++ b/docs/process-services-cloud/components/process-list-cloud.component.md @@ -172,9 +172,7 @@ The Process Instance List also supports pagination: ```html <adf-cloud-process-list - [appId]="'1'" - [page]="page" - [size]="size" + [appName]="'myApp'" #processList> </adf-cloud-process-list> <adf-pagination @@ -185,6 +183,16 @@ The Process Instance List also supports pagination: </adf-pagination> ``` +The configuration related to the pagination can be changed from the `app.config.json`, as described in the example below: + +```json +"pagination": { + "size": 20, + "supportedPageSizes": [ 5, 10, 15, 20 ] +}, + +``` + ## See also - [Data column component](../../core/components/data-column.component.md) From ad2fac15d84f341a24871899940b742fe6b093d0 Mon Sep 17 00:00:00 2001 From: Francesco Corti <fcorti@gmail.com> Date: Thu, 2 May 2019 11:14:03 +0200 Subject: [PATCH 194/208] Compatibility matrix for ADF 3.2. (#4679) --- docs/compatibility.md | 1 + docs/versionIndex.md | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/docs/compatibility.md b/docs/compatibility.md index fcae16f478..a67cdfd550 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -21,6 +21,7 @@ You can find further information about released versions of ADF in the | ADF version | Content Services | Process Services | | -- | -- | -- | +| [3.2.0](versionIndex.md#v320) | **Full test:** v6.1.0 <br/> **Smoke test:** v5.2.4 | **Full test:** v7.1.0 (latest CI pipeline build), v1.9.0 <br/>**Smoke test:** v1.8.1 | | [3.1.0](versionIndex.md#v310) | **Full test:** v6.1.0 RC7 <br/> **Smoke test:** v5.2.4 | **Full test:** v2.0.0 (latest CI pipeline build), v1.9.0 <br/>**Smoke test:** v1.8.1 | | [3.0.0](versionIndex.md#v300) | **Full test:** v6.1.0 RC7 <br/> **Smoke test:** v5.2.4 | **Full test:** v2.0.0 (latest CI pipeline build), v1.9.0 <br/>**Smoke test:** v1.8.1 | | [2.6.0](versionIndex.md#v260) | **Full test:** v6.0.0, v5.2.4 <br/> **Smoke test:** v5.2.3 | **Full test:** v1.9.0 <br/>**Smoke test:** v1.8.1, v1.7.0, v1.6.4 | diff --git a/docs/versionIndex.md b/docs/versionIndex.md index 81c929430d..8cbbe2aeb5 100644 --- a/docs/versionIndex.md +++ b/docs/versionIndex.md @@ -12,6 +12,7 @@ backend services have been tested with each released version of ADF. ## Versions +- [v3.2.0](#v320) - [v3.1.0](#v310) - [v3.0.0](#v300) - [v2.6.0](#v260) @@ -22,6 +23,19 @@ backend services have been tested with each released version of ADF. - [v2.1.0](#v210) - [v2.0.0](#v200) +## v3.2.0 + +**Release:** 2019-05-03<br/> + +<!--v320 start--> + +- Support for five new languages (Danish, Finnish, Swedish, Czech, Polish). +- Easier event handling in [DataTable](core/components/datatable.component.md) (header row action). +- Configurable [multi-value metadata separator](content-services/components/content-metadata-card.component.md). +- More process components for Activiti 7. + +<!--v320 end--> + ## v3.1.0 **Release:** 2019-03-29<br/> From 07da98e1bc23214f7f0c62f744fccfaf5d942ddb Mon Sep 17 00:00:00 2001 From: Francesco Corti <fcorti@gmail.com> Date: Thu, 2 May 2019 11:14:41 +0200 Subject: [PATCH 195/208] Release Note for ADF 3.2 (initial version) (#4617) * Release note for ADF 3.2. * Release note for ADF 3.2. --- docs/release-notes/README.md | 1 + docs/release-notes/RelNote320.md | 143 +++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 docs/release-notes/RelNote320.md diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md index e2daf1d303..12114294d4 100644 --- a/docs/release-notes/README.md +++ b/docs/release-notes/README.md @@ -9,6 +9,7 @@ The first **General available** release was v2.0.0. ## General available +- [3.2.0](RelNote320.md) - [3.1.0](RelNote310.md) - [3.0.0](RelNote300.md) - [2.6.0](RelNote260.md) diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md new file mode 100644 index 0000000000..64af33c72b --- /dev/null +++ b/docs/release-notes/RelNote320.md @@ -0,0 +1,143 @@ +--- +Title: Release notes v3.2.0 +--- + +# Alfresco Application Development Framework (ADF) version 3.2.0 Release Note + +These release notes provide information about the **3.2.0 release** of the Alfresco Application Development Framework. + +This is the latest **General Available** release of the Application Development Framework, which contains the Angular components to build a Web Application on top of the Alfresco Platform. + +The release can be found on GitHub at [this location](https://github.com/Alfresco/alfresco-ng2-components/releases/tag/3.2.0). + +See the [ADF roadmap](../roadmap.md) for details of features planned for future +versions of ADF. + +## Contents + +- [New package versions](#new-package-versions) +- [Goals for this release](#goals-for-this-release) + - [More on Activiti 7](#more-on-activiti-7) + - [Five more languages supported](#five-more-languages-supported) + - [Event handling during header row action](#event-handling-during-header-row-action) + - [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) +- [Localisation](#localisation) +- [References](#references) +- [Issues addressed](#issues-addressed) + - [Documentation](#documentation) + - [Feature](#feature) + - [Bug](#bug) + - [Task](#task) + - [Feature (Task)](#feature-task) + +## New package versions + + "@alfresco/adf-content-services" : "3.2.0" + "@alfresco/adf-process-services" : "3.2.0" + "@alfresco/adf-core" : "3.2.0" + "@alfresco/adf-insights" : "3.2.0", + "@alfresco/adf-extensions": "3.2.0" + +## Goals for this release + +This is the second minor release since ADF version 3 which was released in February 2019. + +This release goes a step further in the direction of complete support for [Activiti 7](https://www.activiti.org/), the next generation Cloud Native implementation of Activiti. Also, some enhancements have been introduced to the Metadata viewer to properly manage multi-value properties, together with the event handling during header row action, to properly manage use cases like the drag & drop feature, requested from some developers. + +We are pleased to announce that starting from ADF 3.2, five more languages are now supported, together with the other ten. The new languages are: Danish, Finnish, Swedish, Czech, Polish. + +Please report issues with this release in the [issue tracker](https://github.com/Alfresco/alfresco-ng2-components/issues/new). You can collaborate on this release or share feedback by using the discussion tools on [Gitter](http://gitter.im/Alfresco/alfresco-ng2-components). + +Below are the most important new features of this release: + +- [More on Activiti 7](#more-on-activiti-7) +- [Five more languages supported](#five-more-languages-supported) +- [Event handling during header row action](#event-handling-during-header-row-action) +- [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) + +### More on Activiti 7 + +In ADF 3.0.0 (released in February) we announced the introduction of the new `*Cloud` package. This contains a set of components to support [Activiti 7](https://www.activiti.org/), the next generation Cloud Native implementation of Activiti BPM Engine. With the ADF 3.2 release, the journey continues with more supported features, like: + +===> Please complete the description here. + +### Five more languages supported + +Starting from ADF 3.2, five more languages are now supported, together with the other ten already in the list. The new languages supported are: Danish, Finnish, Swedish, Czech, Polish. + +### Event handling during header row action + +Following some suggestions from customers and partners, we enhanced the `Datatable` to be able to manage event handling during header row action. Two more events have been added: `header-drop` raised when data is dropped on the column header and `cell-drop` raised when data is dropped on the column cell. + +For more details refer to the: +- [DataTable component](../core/components/datatable.component.md). + +### List separator configuration in multi-value metadata + +As of this version of ADF, developers can configure the list separator of multi-value properties into the metadata viewer. Since this version of ADF, to customize the separator you can set it in your `app.config.json` file inside your `content-metadata` configuration. Below an example. + +```json +"content-metadata": { + "presets": { + ... + }, + "multi-value-pipe-separator" : " - " +} +``` + +For more details refer to the: +- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) + +## Localisation + +This release includes: French, German, Italian, Spanish, Arabic, Japanese, Dutch, Norwegian (Bokmål), Russian, Danish, Finnish, Swedish, Czech, Polish, Brazilian Portuguese and Simplified Chinese versions. + +## References + +Below is a brief list of references to help you start using the new release: + +- [Getting started guides with Alfresco Application Development Framework](https://community.alfresco.com/community/application-development-framework/pages/get-started) +- [Alfresco ADF Documentation on the Builder Network](../README.md) +- [Gitter chat supporting Alfresco ADF](https://gitter.im/Alfresco/alfresco-ng2-components) +- [ADF examples on GitHub](https://github.com/Alfresco/adf-examples) +- [Official GitHub Project - alfresco-ng2-components](https://github.com/Alfresco/alfresco-ng2-components) +- [Official GitHub Project - alfresco-js-api](https://github.com/Alfresco/alfresco-js-api) +- [Official GitHub Project - generator-ng2-alfresco-app](https://github.com/Alfresco/generator-ng2-alfresco-app) + +Please refer to the [official documentation](http://docs.alfresco.com/) for further details and suggestions. + +## Issues addressed + +Below is the list of JIRA issues that were closed for this release. + +### Documentation + +===> Please complete the description here. + +### Feature + +===> Please complete the description here. + +### Epic + +===> Please complete the description here. + +### Story + +===> Please complete the description here. + +### Bug + +===> Please complete the description here. + +### Task + +===> Please complete the description here. + +### Feature (Task) + +===> Please complete the description here. + +Please refer to the [Alfresco issue tracker](https://issues.alfresco.com/jira/projects/ADF/issues/ADF-581?filter=allopenissues) for other known issues in this release. If you have any questions about the release, please contact us using [Gitter](https://gitter.im/Alfresco/alfresco-ng2-components). + +Thanks to the whole application team and the amazing Alfresco community for the hard work. From bbb28c9d687875a43efe7d3aed740d9de2020963 Mon Sep 17 00:00:00 2001 From: Francesco Corti <fcorti@gmail.com> Date: Thu, 2 May 2019 11:15:07 +0200 Subject: [PATCH 196/208] Activiti 7 and ADF tutorial review. (#4681) --- docs/tutorials/activiti-7-and-adf.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/activiti-7-and-adf.md b/docs/tutorials/activiti-7-and-adf.md index 12d8df2cb9..9b3cd3a40d 100644 --- a/docs/tutorials/activiti-7-and-adf.md +++ b/docs/tutorials/activiti-7-and-adf.md @@ -49,7 +49,7 @@ file as shown below: runtime-bundle: enabled: true service: - name: my-app/rb \\ <-- change it here! + name: rb \\ <-- change it here! ... ``` @@ -94,7 +94,7 @@ After your changes, the `app.config.json` file should look like the example belo Then, set the `alfresco-deployed-apps` property as shown below. - "alfresco-deployed-apps": [{"name":"my-app"}] + "alfresco-deployed-apps": [{"name":""}] When you are done, save the `app.config.json` file and launch the application by executing the `npm start` command. You should now be able to use your own ADF application From 9298e6762f4db418771b7aaaedc18c127805d00b Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 2 May 2019 10:16:31 +0100 Subject: [PATCH 197/208] Update package.json --- lib/testing/package.json | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/testing/package.json b/lib/testing/package.json index 3e31054c0d..15c6c98f18 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,9 +1,25 @@ { "name": "@alfresco/adf-testing", + "description": "Alfresco ADF testing page and utils", "version": "3.2.0-beta6", + "author": "Alfresco Software, Ltd.", + "repository": { + "type": "git", + "url": "https://github.com/Alfresco/alfresco-ng2-components.git" + }, + "bugs": { + "url": "https://github.com/Alfresco/alfresco-ng2-components/issues" + }, "peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0", "@alfresco/js-api": "3.2.0-beta6" - } + }, + "keywords": [ + "testing", + "alfresco-component", + "angular", + "components" + ], + "license": "Apache-2.0" } From e88e0d9b45a35e8d22630660671c2d8dd8c544f4 Mon Sep 17 00:00:00 2001 From: Maurizio Vitale <maurizio.vitale@alfresco.com> Date: Thu, 2 May 2019 14:30:38 +0200 Subject: [PATCH 198/208] [ADF-4409] ADF for Activiti Community - Be able to claim/release/complete task (#4677) * Be able to claim/release/complete task for community Be able to start a task/process Fix unsubscribe on destroy * Fix the construnctor --- ...unity-process-details-cloud.component.html | 1 + .../community-start-task-cloud.component.html | 1 + .../components/form-cloud.component.spec.ts | 5 ++- .../lib/form/models/form-cloud.model.spec.ts | 4 +- .../lib/form/services/form-cloud.service.ts | 20 ++++++---- .../form-definition-selector-cloud.service.ts | 7 ++-- .../task/directives/claim-task.directive.ts | 2 +- .../directives/complete-task.directive.ts | 2 +- .../task/directives/unclaim-task.directive.ts | 2 +- .../lib/task/services/task-cloud.service.ts | 39 +++++++++++-------- .../components/task-form-cloud.component.ts | 2 +- .../components/task-header-cloud.component.ts | 18 ++++++--- 12 files changed, 62 insertions(+), 41 deletions(-) diff --git a/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html index 6fc529df18..cc41129884 100644 --- a/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html +++ b/demo-shell/src/app/components/cloud/community/community-process-details-cloud.component.html @@ -10,6 +10,7 @@ <adf-cloud-task-list fxFlex class="adf-cloud-layout-overflow" + [appName]="''" [processInstanceId]="processInstanceId" (rowClick)="onRowClick($event)" #taskCloud> diff --git a/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html b/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html index 9975b99cc6..2a305e9ba5 100644 --- a/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html +++ b/demo-shell/src/app/components/cloud/community/community-start-task-cloud.component.html @@ -1,4 +1,5 @@ <adf-cloud-start-task + [appName]="''" (error)="openSnackMessage($event)" (success)="onStartTaskSuccess()" (cancel)="onCancelStartTask()"> diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts index 59f0ef38b0..5fd6e8079c 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -19,7 +19,8 @@ import { SimpleChange, DebugElement, CUSTOM_ELEMENTS_SCHEMA, Component } from '@ import { By } from '@angular/platform-browser'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Observable, of, throwError } from 'rxjs'; -import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService, setupTestBed } from '@alfresco/adf-core'; +import { FormFieldModel, FormFieldTypes, FormService, FormOutcomeEvent, FormOutcomeModel, LogService, WidgetVisibilityService, + setupTestBed, AppConfigService } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module'; import { FormCloudService } from '../services/form-cloud.service'; import { FormCloudComponent } from './form-cloud.component'; @@ -38,7 +39,7 @@ describe('FormCloudComponent', () => { logService = new LogService(null); visibilityService = new WidgetVisibilityService(null, logService); spyOn(visibilityService, 'refreshVisibility').and.stub(); - formCloudService = new FormCloudService(null, null, logService); + formCloudService = new FormCloudService(null, new AppConfigService(null), logService); formService = new FormService(null, null, logService); formComponent = new FormCloudComponent(formCloudService, formService, null, visibilityService); }); diff --git a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts index 7a9b1a5fdf..672d34d846 100644 --- a/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts +++ b/lib/process-services-cloud/src/lib/form/models/form-cloud.model.spec.ts @@ -17,14 +17,14 @@ import { FormCloudService } from '../services/form-cloud.service'; import { FormCloud } from './form-cloud.model'; -import { TabModel, FormFieldModel, ContainerModel, FormOutcomeModel, FormFieldTypes } from '@alfresco/adf-core'; +import { TabModel, FormFieldModel, ContainerModel, FormOutcomeModel, FormFieldTypes, AppConfigService } from '@alfresco/adf-core'; describe('FormCloud', () => { let formCloudService: FormCloudService; beforeEach(() => { - formCloudService = new FormCloudService(null, null, null); + formCloudService = new FormCloudService(null, new AppConfigService(null), null); }); it('should store original json', () => { diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts index 3396ba691c..c6e2c04466 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -23,18 +23,22 @@ import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details import { SaveFormRepresentation, CompleteFormRepresentation } from '@alfresco/js-api'; import { FormCloud } from '../models/form-cloud.model'; import { TaskVariableCloud } from '../models/task-variable-cloud.model'; +import { BaseCloudService } from '../../services/base-cloud.service'; @Injectable({ providedIn: 'root' }) -export class FormCloudService { +export class FormCloudService extends BaseCloudService { contentTypes = ['application/json']; accepts = ['application/json']; returnType = Object; constructor( private apiService: AlfrescoApiService, private appConfigService: AppConfigService, private logService: LogService - ) {} + ) { + super(); + this.contextRoot = this.appConfigService.get('bpmHost', ''); + } /** * Gets the form definition of a task. @@ -245,15 +249,15 @@ export class FormCloudService { } private buildGetTaskUrl(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/query/v1/tasks/${taskId}`; + return `${this.getBasePath(appName)}/query/v1/tasks/${taskId}`; } private buildGetFormUrl(appName: string, formId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}`; + return `${this.getBasePath(appName)}/form/v1/forms/${formId}`; } private buildSaveFormUrl(appName: string, formId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}/save`; + return `${this.getBasePath(appName)}/form/v1/forms/${formId}/save`; } private buildUploadUrl(nodeId: string): string { @@ -261,15 +265,15 @@ export class FormCloudService { } private buildSubmitFormUrl(appName: string, formId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms/${formId}/submit`; + return `${this.getBasePath(appName)}/form/v1/forms/${formId}/submit`; } private buildGetTaskVariablesUrl(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/query/v1/tasks/${taskId}/variables`; + return `${this.getBasePath(appName)}/query/v1/tasks/${taskId}/variables`; } private buildFolderTask(appName: string, taskId: string): string { - return `${this.appConfigService.get('bpmHost')}/${appName}/process-storage/v1/folders/tasks/${taskId}`; + return `${this.getBasePath(appName)}/process-storage/v1/folders/tasks/${taskId}`; } private handleError(error: any) { diff --git a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts index 03826a00f4..a5f680204e 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-definition-selector-cloud.service.ts @@ -20,13 +20,13 @@ import { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf- import { catchError, map } from 'rxjs/operators'; import { FormDefinitionSelectorCloudModel } from '../models/form-definition-selector-cloud.model'; import { from, Observable, throwError } from 'rxjs'; +import { BaseCloudService } from '../../services/base-cloud.service'; @Injectable({ providedIn: 'root' }) -export class FormDefinitionSelectorCloudService { +export class FormDefinitionSelectorCloudService extends BaseCloudService { - contextRoot: string; contentTypes = ['application/json']; accepts = ['application/json']; returnType = Object; @@ -34,6 +34,7 @@ export class FormDefinitionSelectorCloudService { constructor(private apiService: AlfrescoApiService, private appConfigService: AppConfigService, private logService: LogService) { + super(); this.contextRoot = this.appConfigService.get('bpmHost', ''); } @@ -65,7 +66,7 @@ export class FormDefinitionSelectorCloudService { } private buildGetFormsUrl(appName: string): any { - return `${this.appConfigService.get('bpmHost')}/${appName}/form/v1/forms`; + return `${this.getBasePath(appName)}/form/v1/forms`; } private handleError(error: any) { diff --git a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts b/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts index 54bbd8e46d..fe3962c89a 100644 --- a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts +++ b/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.ts @@ -67,7 +67,7 @@ export class ClaimTaskDirective implements OnInit { } isAppValid(): boolean { - return this.appName && this.appName.length > 0; + return (this.appName && this.appName.length > 0) || (this.appName === ''); } @HostListener('click') diff --git a/lib/process-services-cloud/src/lib/task/directives/complete-task.directive.ts b/lib/process-services-cloud/src/lib/task/directives/complete-task.directive.ts index 8652123ebf..094a2401fb 100644 --- a/lib/process-services-cloud/src/lib/task/directives/complete-task.directive.ts +++ b/lib/process-services-cloud/src/lib/task/directives/complete-task.directive.ts @@ -64,7 +64,7 @@ export class CompleteTaskDirective implements OnInit { } isAppValid(): boolean { - return this.appName && this.appName.length > 0; + return (this.appName && this.appName.length > 0) || (this.appName === ''); } @HostListener('click') diff --git a/lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts b/lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts index 492e372450..c152f40606 100644 --- a/lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts +++ b/lib/process-services-cloud/src/lib/task/directives/unclaim-task.directive.ts @@ -65,7 +65,7 @@ export class UnClaimTaskDirective implements OnInit { } isAppValid(): boolean { - return this.appName && this.appName.length > 0; + return (this.appName && this.appName.length > 0) || (this.appName === ''); } @HostListener('click') diff --git a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts index a6af517e40..4763ef28d3 100644 --- a/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/services/task-cloud.service.ts @@ -48,21 +48,26 @@ export class TaskCloudService extends BaseCloudService { * @returns Details of the task that was completed */ completeTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { - const queryUrl = this.buildCompleteTaskUrl(appName, taskId); - const bodyParam = { 'payloadType': 'CompleteTaskPayload' }; - const pathParams = {}, queryParams = {}, headerParams = {}, - formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; + if ((appName || appName === '') && taskId) { + const queryUrl = this.buildCompleteTaskUrl(appName, taskId); + const bodyParam = { 'payloadType': 'CompleteTaskPayload' }; + const pathParams = {}, queryParams = {}, headerParams = {}, + formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return from( - this.apiService - .getInstance() - .oauth2Auth.callCustomApi( - queryUrl, 'POST', pathParams, queryParams, - headerParams, formParams, bodyParam, - contentTypes, accepts, null, null) - ).pipe( - catchError((err) => this.handleError(err)) - ); + return from( + this.apiService + .getInstance() + .oauth2Auth.callCustomApi( + queryUrl, 'POST', pathParams, queryParams, + headerParams, formParams, bodyParam, + contentTypes, accepts, null, null) + ).pipe( + catchError((err) => this.handleError(err)) + ); + } else { + this.logService.error('AppName and TaskId are mandatory for complete a task'); + return throwError('AppName/TaskId not configured'); + } } /** @@ -102,7 +107,7 @@ export class TaskCloudService extends BaseCloudService { * @returns Details of the claimed task */ claimTask(appName: string, taskId: string, assignee: string): Observable<TaskDetailsCloudModel> { - if (appName && taskId) { + if ((appName || appName === '') && taskId) { const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/claim?assignee=${assignee}`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', @@ -129,7 +134,7 @@ export class TaskCloudService extends BaseCloudService { * @returns Details of the task that was unclaimed */ unclaimTask(appName: string, taskId: string): Observable<TaskDetailsCloudModel> { - if (appName && taskId) { + if ((appName || appName === '') && taskId) { const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}/release`; return from(this.apiService.getInstance() .oauth2Auth.callCustomApi(queryUrl, 'POST', @@ -184,7 +189,7 @@ export class TaskCloudService extends BaseCloudService { * @returns Updated task details */ updateTask(appName: string, taskId: string, updatePayload: any): Observable<TaskDetailsCloudModel> { - if (appName && taskId) { + if ((appName || appName === '') && taskId) { updatePayload.payloadType = 'UpdateTaskPayload'; const queryUrl = `${this.getBasePath(appName)}/rb/v1/tasks/${taskId}`; diff --git a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts index 962eaaca4b..5ecac0805d 100644 --- a/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-form/components/task-form-cloud.component.ts @@ -98,7 +98,7 @@ export class TaskFormCloudComponent implements OnChanges { ngOnChanges(changes: SimpleChanges) { const appName = changes['appName']; - if (appName && appName.currentValue && this.taskId) { + if (appName && (appName.currentValue || appName.currentValue === '' ) && this.taskId) { this.loadTask(); return; } diff --git a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts index 1b726e4429..6224e9bc4f 100644 --- a/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnInit, EventEmitter, Output } from '@angular/core'; +import { Component, Input, OnInit, EventEmitter, Output, OnDestroy } from '@angular/core'; import { CardViewDateItemModel, CardViewItem, @@ -29,13 +29,14 @@ import { import { TaskDetailsCloudModel, TaskStatusEnum } from '../../start-task/models/task-details-cloud.model'; import { Router } from '@angular/router'; import { TaskCloudService } from '../../services/task-cloud.service'; +import { Subscription } from 'rxjs'; @Component({ selector: 'adf-cloud-task-header', templateUrl: './task-header-cloud.component.html', styleUrls: ['./task-header-cloud.component.scss'] }) -export class TaskHeaderCloudComponent implements OnInit { +export class TaskHeaderCloudComponent implements OnInit, OnDestroy { /** (Required) The name of the application. */ @Input() @@ -58,6 +59,8 @@ export class TaskHeaderCloudComponent implements OnInit { inEdit: boolean = false; parentTaskName: string; + private subscriptions: Subscription[] = []; + constructor( private taskCloudService: TaskCloudService, private translationService: TranslationService, @@ -71,11 +74,11 @@ export class TaskHeaderCloudComponent implements OnInit { this.loadTaskDetailsById(this.appName, this.taskId); } - this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this)); + this.subscriptions.push(this.cardViewUpdateService.itemUpdated$.subscribe(this.updateTaskDetails.bind(this))); } loadTaskDetailsById(appName: string, taskId: string): any { - this.taskCloudService.getTaskById(appName, taskId).subscribe( + this.subscriptions.push(this.taskCloudService.getTaskById(appName, taskId).subscribe( (taskDetails) => { this.taskDetails = taskDetails; if (this.taskDetails.parentTaskId) { @@ -83,7 +86,7 @@ export class TaskHeaderCloudComponent implements OnInit { } else { this.refreshData(); } - }); + })); } private initDefaultProperties() { @@ -244,4 +247,9 @@ export class TaskHeaderCloudComponent implements OnInit { onCompletedTask(event: any) { this.goBack(); } + + ngOnDestroy() { + this.subscriptions.forEach((subscription) => subscription.unsubscribe()); + this.subscriptions = []; + } } From 6b1c60a5aeaa678c379a85c8136f9f315d2f9ea7 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Thu, 2 May 2019 13:54:24 +0100 Subject: [PATCH 199/208] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b18e83f1ab..9db3d1789d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ branches: only: - master - development + - /.*old-env.*/ - /.*next-release.*/ - /.*beta.*/ - /.*greenkeeper.*/ From d6719c0b579efd2c02493bc9633b4d72e169ec3f Mon Sep 17 00:00:00 2001 From: davidcanonieto <david.cano.nieto@gmail.com> Date: Thu, 2 May 2019 15:00:09 +0100 Subject: [PATCH 200/208] [ADF-4478] Fix layout container and empty template (#4683) --- .../datatable/components/datatable/datatable.component.scss | 1 + .../components/layout-container/layout-container.component.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/core/datatable/components/datatable/datatable.component.scss b/lib/core/datatable/components/datatable/datatable.component.scss index b24b0b39c7..dd873a925a 100644 --- a/lib/core/datatable/components/datatable/datatable.component.scss +++ b/lib/core/datatable/components/datatable/datatable.component.scss @@ -578,6 +578,7 @@ .adf-datatable-body { .adf-datatable-row { + height: 100%; background-color: mat-color($background, card); border: none !important; diff --git a/lib/core/layout/components/layout-container/layout-container.component.scss b/lib/core/layout/components/layout-container/layout-container.component.scss index 614ee0b5a2..f7af955fbd 100644 --- a/lib/core/layout/components/layout-container/layout-container.component.scss +++ b/lib/core/layout/components/layout-container/layout-container.component.scss @@ -14,7 +14,7 @@ } .adf-container-full-width { - width: 100%; + width: inherit; } .adf-sidenav--hidden { From 2f126fe7fd4bcb111f5aad788e01465d10c1d7d3 Mon Sep 17 00:00:00 2001 From: Denys Vuika <denys.vuika@gmail.com> Date: Thu, 2 May 2019 15:47:02 +0100 Subject: [PATCH 201/208] minor a11y fix for header --- .../components/header/header.component.html | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/core/layout/components/header/header.component.html b/lib/core/layout/components/header/header.component.html index 4119c3b223..ab869519c8 100644 --- a/lib/core/layout/components/header/header.component.html +++ b/lib/core/layout/components/header/header.component.html @@ -1,20 +1,50 @@ -<mat-toolbar color="{{color}}" [style.background-color]="color"> - <button *ngIf="showSidenavToggle && position === 'start'" id="adf-sidebar-toggle-start" data-automation-id="adf-menu-icon" - class="mat-icon-button adf-menu-icon" mat-icon-button (click)="toggleMenu()"> - <mat-icon class="mat-icon material-icon" role="img" aria-hidden="true">menu</mat-icon> +<mat-toolbar + [color]="color" + [style.background-color]="color" + role="heading" + aria-level="1"> + <button + *ngIf="showSidenavToggle && position === 'start'" + id="adf-sidebar-toggle-start" + data-automation-id="adf-menu-icon" + class="mat-icon-button adf-menu-icon" + mat-icon-button + (click)="toggleMenu()" + aria-label="Toggle Menu"> + <mat-icon + class="mat-icon material-icon" + role="img" + aria-hidden="true">menu</mat-icon> </button> <a [routerLink]="redirectUrl" title="{{ tooltip }}"> - <img src="{{logo}}" class="adf-app-logo" alt="{{ 'CORE.HEADER.LOGO_ARIA' | translate }}"/> + <img + src="{{ logo }}" + class="adf-app-logo" + alt="{{ 'CORE.HEADER.LOGO_ARIA' | translate }}" + /> </a> - <span [routerLink]="redirectUrl" fxFlex="1 1 auto" fxShow fxHide.lt-sm="true" class="adf-app-title">{{title}}</span> + <span + [routerLink]="redirectUrl" + fxFlex="1 1 auto" + fxShow + fxHide.lt-sm="true" + class="adf-app-title" + >{{ title }}</span> <ng-content></ng-content> - <button *ngIf="showSidenavToggle && position === 'end'" id="adf-sidebar-toggle-end" data-automation-id="adf-menu-icon" - class="mat-icon-button adf-menu-icon" mat-icon-button (click)="toggleMenu()"> - <mat-icon class="mat-icon material-icon" role="img" aria-hidden="true">menu</mat-icon> + <button + *ngIf="showSidenavToggle && position === 'end'" + id="adf-sidebar-toggle-end" + data-automation-id="adf-menu-icon" + class="mat-icon-button adf-menu-icon" + mat-icon-button + (click)="toggleMenu()" + aria-label="Toggle Menu"> + <mat-icon + class="mat-icon material-icon" + role="img" + aria-hidden="true">menu</mat-icon> </button> - </mat-toolbar> - From f43789b7a75ecc8b1a34545f4d17d3ae0f2870e5 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 3 May 2019 10:53:21 +0100 Subject: [PATCH 202/208] Update RelNote320.md --- docs/release-notes/RelNote320.md | 319 ++++++++++++++++++++++++++++--- 1 file changed, 293 insertions(+), 26 deletions(-) diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md index 64af33c72b..03118c2dfa 100644 --- a/docs/release-notes/RelNote320.md +++ b/docs/release-notes/RelNote320.md @@ -110,33 +110,300 @@ Please refer to the [official documentation](http://docs.alfresco.com/) for furt Below is the list of JIRA issues that were closed for this release. -### Documentation -===> Please complete the description here. - -### Feature - -===> Please complete the description here. - -### Epic - -===> Please complete the description here. - -### Story - -===> Please complete the description here. - -### Bug - -===> Please complete the description here. - -### Task - -===> Please complete the description here. - -### Feature (Task) - -===> Please complete the description here. + Release Notes - Apps Development Framework - Version 3.2.0 + +<h2> Documentation +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4356'>ADF-4356</a>] - How to build an ADF application on top of Activiti 7 Community Edition +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4391'>ADF-4391</a>] - Doc review for 3.2 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4413'>ADF-4413</a>] - Activiti 7 and ADF tutorial +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4414'>ADF-4414</a>] - Release note for version 3.2.0 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4415'>ADF-4415</a>] - Create the list of third party Open Source components for ADF 3.2 release +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4416'>ADF-4416</a>] - Create the upgrade guide from ADF 3.1 to ADF 3.2 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4417'>ADF-4417</a>] - Update the compatibility matrix for ADF 3.2 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4429'>ADF-4429</a>] - Process List Cloud - Remove the pagination parameters +</li> +</ul> + +<h2> Feature +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3794'>ADF-3794</a>] - Update individual rows without reloading DocumentList +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3887'>ADF-3887</a>] - Using multiple ADF apps from the same browser/user +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3912'>ADF-3912</a>] - Document-List is not able to retrieve the -file-plan- information from the node +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4128'>ADF-4128</a>] - Task Cloud completion/back +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4213'>ADF-4213</a>] - Event handling during header row action. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4219'>ADF-4219</a>] - List separator configuration in multi-value metadata +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4327'>ADF-4327</a>] - Confirm Dialog does not support template injection +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4328'>ADF-4328</a>] - Storage Service should stream the values when they are changed +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4340'>ADF-4340</a>] - APW - Form - Upload a file from a form +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4349'>ADF-4349</a>] - Cloud - task-form-component - Create a new component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4359'>ADF-4359</a>] - Add the possibility to chose wich panel to show first in info-drawer +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4362'>ADF-4362</a>] - No-growing cells on Datatable component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4409'>ADF-4409</a>] - Cloud - Make sure ADF is compatible with activiti 7 community and enterprise +</li> +</ul> + +<h2> Epic +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-1452'>ADF-1452</a>] - Documentation +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4246'>ADF-4246</a>] - Microsoft Internet Explorer +</li> +</ul> + +<h2> Story +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3797'>ADF-3797</a>] - Task management view - Task with Form +</li> +</ul> + +<h2> Bug +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-1954'>ADF-1954</a>] - [IE11] Breadcrumbs are not well aligned +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3228'>ADF-3228</a>] - User can access the version manager dialog for a locked file +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3678'>ADF-3678</a>] - Custom Process Filter - Different results in APS than in ADF +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3934'>ADF-3934</a>] - People Cloud Component - Remove the concept of assignee +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3969'>ADF-3969</a>] - ADF - Start Task page, fields are not properly aligned. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3983'>ADF-3983</a>] - [App List ] - Should be displayed a message to inform the user that has no application +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4043'>ADF-4043</a>] - [Demo Shell] People Cloud Component - Roles are displayed once with ' ' and once with " " +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4093'>ADF-4093</a>] - Activiti Cloud - EditProcessFilter - the status are not correct +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4096'>ADF-4096</a>] - TaskList Cloud component is missing fileName attribute +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4142'>ADF-4142</a>] - ProcessDefinitionKey is not exposed by the edit task cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4193'>ADF-4193</a>] - SearchQueryBuilderService - execute() error handling +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4198'>ADF-4198</a>] - 'Escape' key doesn't work to close the User Profile dialog. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4216'>ADF-4216</a>] - Recently uploaded files are missing 'ago' in the Created column. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4242'>ADF-4242</a>] - Inconsistent format date for process and task header components +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4250'>ADF-4250</a>] - Improve Error Component to display more accurate info about errors +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4263'>ADF-4263</a>] - [EditProcessFilterCloudComponent] Unit tests are failing. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4270'>ADF-4270</a>] - Empty value is displayed on name field when checking the details of a process without name +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4273'>ADF-4273</a>] - Decide if description field of process header cloud component needs to be removed +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4274'>ADF-4274</a>] - Group Cloud component - the group is not preselected and is still displayed in the dropdown. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4275'>ADF-4275</a>] - People Cloud Component: Preselect validation on User Id doesn't work. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4303'>ADF-4303</a>] - [Process Cloud] Start Process - Can not complete a task with the assigned user +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4307'>ADF-4307</a>] - processDefinitionKey property is not supported by sort edit task +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4321'>ADF-4321</a>] - Not able to filter by taskId in edit task filter cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4334'>ADF-4334</a>] - Editing a multi-valued content property causes it to be stored as a single value (rather than a multi-value collection) +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4339'>ADF-4339</a>] - The rows in documentList are not properly aligned on IE11 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4343'>ADF-4343</a>] - Host Settings Dialog closes on Enter key pressed +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4352'>ADF-4352</a>] - When the SSO identity service is wrongly configured no login error message is displayed +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4357'>ADF-4357</a>] - Cannot complete a task with the assigned user +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4360'>ADF-4360</a>] - Ellipsis not working on Date Cell +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4361'>ADF-4361</a>] - [Accessibility]On Login page, the user is not able to navigate using tab key +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4363'>ADF-4363</a>] - Cloud page layout broken +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4371'>ADF-4371</a>] - CLONE - [Upload new version] File is completely deleted when user cancels the upload +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4372'>ADF-4372</a>] - Json type Date Column breaks datatable layout when json is too long +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4374'>ADF-4374</a>] - Fix Sticky Header Feature in Datatable Component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4386'>ADF-4386</a>] - fix style for CopyContentDirective +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4393'>ADF-4393</a>] - TaskDetails - Remove readOnly property from TaskDetailsCloud +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4400'>ADF-4400</a>] - CLONE - Restore version does not refresh the document list +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4401'>ADF-4401</a>] - Nested 'adf-datatable-cell' items cause display & functional issues +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4403'>ADF-4403</a>] - Adf clipboard directive - It should have a default placeholder/Position +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4404'>ADF-4404</a>] - Type ahead form control does not work for URLs +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4405'>ADF-4405</a>] - Copy link to share not working +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4418'>ADF-4418</a>] - [Demo-Shell][Cloud]The task is not completed when clicking on complete button +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4420'>ADF-4420</a>] - End date is empty when task is completed on task header cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4430'>ADF-4430</a>] - The error message on metadata property with valid value is still displayed if it had once an invalid value +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4432'>ADF-4432</a>] - TaskFormCloudComponent - should be read only if the task is unclaimed +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4434'>ADF-4434</a>] - Custom Empty Content Template message is not centered. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4455'>ADF-4455</a>] - Remove whitespace in multivalue metadata fields +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4460'>ADF-4460</a>] - Can't complete task with an empty upload file widget +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4468'>ADF-4468</a>] - FormCloud - Not able to show a value of a form variable +</li> +</ul> + +<h2> Task +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3876'>ADF-3876</a>] - StartTaskCloud - Be able to start a task with a form +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-3962'>ADF-3962</a>] - [E2E] Automate tests for Content Services with SSO +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4028'>ADF-4028</a>] - Automate tests for Processlist multiselect +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4046'>ADF-4046</a>] - Automation test for copy/move file inside a folder +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4047'>ADF-4047</a>] - Automate test for dropping file in a folder +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4059'>ADF-4059</a>] - Automate test for copying/moving a node to a folder in a different page +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4191'>ADF-4191</a>] - Fix and enable the viewer tests +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4272'>ADF-4272</a>] - Datatable - Create a new directive to copy/paste cells text +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4277'>ADF-4277</a>] - Automate C305041- Should filter the People and Groups with the Application name filter. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4278'>ADF-4278</a>] - Automate C305033 - Should fetch the preselect users +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4279'>ADF-4279</a>] - AAA - LandingPage layout not aligned +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4292'>ADF-4292</a>] - Create manual test cases and automate them for new process list properties +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4295'>ADF-4295</a>] - AuthGuardSSO - Provide a way to validate the client role +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4298'>ADF-4298</a>] - Automate tests for Info Drawer +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4302'>ADF-4302</a>] - Move the cloud folder inside app-layout into components folder +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4308'>ADF-4308</a>] - Add another property on DataColumnComponent to render json data +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4310'>ADF-4310</a>] - Add manual and automated test cases for edit task filter cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4312'>ADF-4312</a>] - Update backend CS in terraform +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4320'>ADF-4320</a>] - Move cloud folder in root +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4323'>ADF-4323</a>] - Add style fixes from ACA +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4335'>ADF-4335</a>] - Update webdriver-manager before running the e2e tests inside test-e2e-lib.sh script +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4336'>ADF-4336</a>] - Move APS Cloud pages to adf-test +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4337'>ADF-4337</a>] - Automate ADF-4048 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4344'>ADF-4344</a>] - Fix cloud automated tests +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4350'>ADF-4350</a>] - Fix failing e2e tests +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4351'>ADF-4351</a>] - Change APS2 services url pattern form -service/ to /service/ +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4354'>ADF-4354</a>] - Fix failing cloud tests +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4365'>ADF-4365</a>] - [e2e] Create startTaskCloudComponent page in @adf-testing package +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4383'>ADF-4383</a>] - Update the documentation for Edit Process Filter Cloud Component. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4384'>ADF-4384</a>] - Support custom filters with Recent Files source +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4387'>ADF-4387</a>] - Configuration option to change the default image zoom +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4406'>ADF-4406</a>] - Confirm Dialog doesn't support a third extra button option to be customised +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4410'>ADF-4410</a>] - CLONE - Upload dialog - version upload +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4411'>ADF-4411</a>] - Create script to remove Alfresco dependencies +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4422'>ADF-4422</a>] - Fix Should display processes ordered by id when Id test +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4447'>ADF-4447</a>] - Automate C307975 +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4451'>ADF-4451</a>] - Automate Event handling during header row action. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4454'>ADF-4454</a>] - Map upload field to UploadCloudWidget in task cloud form +</li> +</ul> + +<h2> Feature Bug +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4311'>ADF-4311</a>] - [Process-Cloud] - Incorrect label loaded for unclaim option -> "Resqueue" should be "Release" +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4394'>ADF-4394</a>] - JSON is not supported. +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4423'>ADF-4423</a>] - Copy Content tooltip is not displayed correctly +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4433'>ADF-4433</a>] - The attached form is not displayed on a standalone task +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4437'>ADF-4437</a>] - showRefreshButton property shouldn't be part of task form cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4444'>ADF-4444</a>] - Upload Drag&Drop area is not working properly +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4445'>ADF-4445</a>] - showSaveButton property is missing from form-cloud component +</li> +</ul> + +<h2> Feature (Task) +</h2> +<ul> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4241'>ADF-4241</a>] - Automate tests for process header cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4367'>ADF-4367</a>] - Automate test for task/process date format +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4368'>ADF-4368</a>] - Add a way to pass json property to datatable +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4373'>ADF-4373</a>] - Automation test for accurate error messages +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4388'>ADF-4388</a>] - Create automated tests for Id in edit task filter cloud component +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4390'>ADF-4390</a>] - Add a way to test that the developer can use this directive by changing the data-column in demo-shell +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4396'>ADF-4396</a>] - Automation for cancelling new version upload +</li> +<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4407'>ADF-4407</a>] - Automate test for user without permission redirection +</li> +</ul> Please refer to the [Alfresco issue tracker](https://issues.alfresco.com/jira/projects/ADF/issues/ADF-581?filter=allopenissues) for other known issues in this release. If you have any questions about the release, please contact us using [Gitter](https://gitter.im/Alfresco/alfresco-ng2-components). From 676efbf2fb5f90de9caed29ce38b22e45d926e57 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 3 May 2019 10:55:53 +0100 Subject: [PATCH 203/208] Update RelNote320.md --- docs/release-notes/RelNote320.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md index 03118c2dfa..cf9b67dde5 100644 --- a/docs/release-notes/RelNote320.md +++ b/docs/release-notes/RelNote320.md @@ -170,8 +170,6 @@ Below is the list of JIRA issues that were closed for this release. <ul> <li>[<a href='https://issues.alfresco.com/jira/browse/ADF-1452'>ADF-1452</a>] - Documentation </li> -<li>[<a href='https://issues.alfresco.com/jira/browse/ADF-4246'>ADF-4246</a>] - Microsoft Internet Explorer -</li> </ul> <h2> Story From 2e439bf0769ed0cfb89412fda37854f8283bdd8f Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 3 May 2019 13:56:49 +0100 Subject: [PATCH 204/208] Update RelNote320.md --- docs/release-notes/RelNote320.md | 157 ++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md index cf9b67dde5..0f568f7345 100644 --- a/docs/release-notes/RelNote320.md +++ b/docs/release-notes/RelNote320.md @@ -20,7 +20,8 @@ versions of ADF. - [More on Activiti 7](#more-on-activiti-7) - [Five more languages supported](#five-more-languages-supported) - [Event handling during header row action](#event-handling-during-header-row-action) - - [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) + - [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) + - [Configuration option to change the dafault viewer zoom](#configuration-option-to-change-the-dafault-viewer-zoom) - [Localisation](#localisation) - [References](#references) - [Issues addressed](#issues-addressed) @@ -53,13 +54,26 @@ Below are the most important new features of this release: - [More on Activiti 7](#more-on-activiti-7) - [Five more languages supported](#five-more-languages-supported) - [Event handling during header row action](#event-handling-during-header-row-action) -- [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) +- [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) ### More on Activiti 7 In ADF 3.0.0 (released in February) we announced the introduction of the new `*Cloud` package. This contains a set of components to support [Activiti 7](https://www.activiti.org/), the next generation Cloud Native implementation of Activiti BPM Engine. With the ADF 3.2 release, the journey continues with more supported features, like: -===> Please complete the description here. +#### New permission template to app list +A new message template is now displayed when a user doesn't have permissions + +#### Cloud form definition selector component +Cloud form definition selector component is a dropdown that shows all the form present in your app: + +```html +<adf-cloud-form-definition-selector + [appName]="'simple-app'" + (selectForm)="onFormSelect($event)"> +</adf-cloud-form-definition-selector> +``` +For more details refer to the: +- [DataTable component](../process-services-cloud/components/form-definition-selector-cloud.component.md ). ### Five more languages supported @@ -84,10 +98,147 @@ As of this version of ADF, developers can configure the list separator of multi- "multi-value-pipe-separator" : " - " } ``` +For more details refer to the: +- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) + +### Option to chose which panel to show first in info drawer + +Is now possible define which aspect show expanded by default in the metadata card applying the optional property ```displayAspect``` + +![feature-1](https://user-images.githubusercontent.com/14145706/56648273-a45efd80-66a0-11e9-866b-4f13c7df4b80.gif) For more details refer to the: - [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) +### Confirm Dialog third extra button option and custom HTML message + + +Is now possible add an extra button in the Confirm Dialog + +#### Dialog inputs +| Name | Type | Default value | Description | +| ---- | ---- | ---- | ----------- | +| title | `string` | `Confirm` | It will be placed in the dialog title section. | +| yesLabel | `string` | `yes` | It will be placed first in the dialog action section | +| noLabel | `string` | `no`| It will be placed last in the dialog action section | +| thirdOptionLabel (optional) | `string` | | It is not a mandatory input. it will be rendered in between yes and no label | +| message | `string` | `Do you want to proceed?` | It will be rendered in the dialog content area | +| htmlContent | `HTML` | | It will be rendered in the dialog content area | + +![yes-all](https://user-images.githubusercontent.com/14145706/56139451-87e30700-5fb6-11e9-8121-e58008231df2.png) + +For more details refer to the: +- [Confirm Dialog](../content-services/dialogs/confirm.dialog.md) + +### Configuration option to change the default viewer zoom + +You can set a default zoom scaling value for pdf viewer by adding the following code in `app.config.json`. +Note: For the pdf viewer the value has to be within the range of 25 - 1000. + +```json + "adf-viewer": { + "pdf-viewer-scaling": 150 + } +``` + +In the same way, you can set a default zoom scaling value for the image viewer by adding the following code in `app.config.json`. + +```json + "adf-viewer": { + "image-viewer-scaling": 150 + } +``` + +By default, the viewer's zoom scaling is set to 100%. + +For more details refer to the: +- [Viewer Component](../docs/core/components/viewer.component.md) + +### Drop events for DataTable component + +#### Drop Events +Below are the four new DOM events emitted by the DataTable component. +These events bubble up the component tree and can be handled by any parent component. + +| Name | Description | +| ---- | ----------- | +| header-dragover | Raised when dragging content over the header. | +| header-drop | Raised when data is dropped on the column header. | +| cell-dragover | Raised when dragging data over the cell. | +| cell-drop | Raised when data is dropped on the column cell. | + +#### Drop Events + +All custom DOM events related to `drop` handling expose the following interface: + +```ts +export interface DataTableDropEvent { + detail: { + target: 'cell' | 'header'; + event: Event; + column: DataColumn; + row?: DataRow + }; + + preventDefault(): void; +} +``` + +Note that `event` is the original `drop` event, +and `row` is not available for Header events. + +According to the [HTML5 Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API), +you need to handle both `dragover` and `drop` events to handle the drop correctly. + +Given that DataTable raises bubbling DOM events, you can handle drop behavior from the parent elements as well: + +```html +<div + (header-dragover)="onDragOver($event)" + (header-drop)="onDrop($event)" + (cell-dragover)="onDragOver($event)" + (cell-drop)="onDrop($event)"> + + <adf-datatable [data]="data"> + </adf-datatable> +</div> +``` + +### Sidenav Layout Direction property +If you use the [Sidenav Layout component](../core/components/sidenav-layout.component.md) you can choose set the direction property in it using the property direction ans set it to **'rtl'** + + ```html +<adf-sidenav-layout + [direction]="'rtl'"> +...... +</adf-sidenav-layout> +``` + +![preview](https://user-images.githubusercontent.com/3947156/55820667-507ee100-5b04-11e9-81ee-a9951982b237.gif) + +### Custom local storages prefix property + If you are using multiple ADF apps, you might want to set the following configuration so that the apps have specific storages and are independent of others when setting and getting data from the local storage. + + In order to achieve this, you will only need to set your app identifier under the `storagePrefix` property of the app in your `app.config.json` file. + ```json +"application": { + "storagePrefix": "ADF_Identifier" +} +``` + +### Datatable Component new Json cell type +The datale is now able to render in a better way JSON text : + +Show Json formated value inside datatable component. + + ```html +<adf-datatable ...> + <data-columns> + <data-column key="entry.json" type="json" title="Json Column"></data-column> + </data-columns> +</adf-datatable> +``` + ## Localisation This release includes: French, German, Italian, Spanish, Arabic, Japanese, Dutch, Norwegian (Bokmål), Russian, Danish, Finnish, Swedish, Czech, Polish, Brazilian Portuguese and Simplified Chinese versions. From f40eb2560bada5a6c1874f7f241fe74223087e9c Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 3 May 2019 14:02:25 +0100 Subject: [PATCH 205/208] Update RelNote320.md --- docs/release-notes/RelNote320.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md index 0f568f7345..9c62a840f8 100644 --- a/docs/release-notes/RelNote320.md +++ b/docs/release-notes/RelNote320.md @@ -18,10 +18,16 @@ versions of ADF. - [New package versions](#new-package-versions) - [Goals for this release](#goals-for-this-release) - [More on Activiti 7](#more-on-activiti-7) + -[New permission template to app list](new-permission-template-to-app-list) + -[Cloud form definition selector component](cloud-form-definition-selector-component) - [Five more languages supported](#five-more-languages-supported) - - [Event handling during header row action](#event-handling-during-header-row-action) - - [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) + - [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) + - [Confirm Dialog third extra button option and custom HTML message](#confirm-dialog-third-extra-button-option-and-custom-html-message) - [Configuration option to change the dafault viewer zoom](#configuration-option-to-change-the-dafault-viewer-zoom) + - [Drop events for DataTable component](#drop-events-for-dataTable-component) + - [Sidenav Layout Direction property](#sidenav-layout-direction-property) + - [Custom local storages prefix property](#custom-local-storages-prefix-property) + - [Datatable Component new Json cell type](#datatable-component-new-json-cell-type) - [Localisation](#localisation) - [References](#references) - [Issues addressed](#issues-addressed) @@ -79,13 +85,6 @@ For more details refer to the: Starting from ADF 3.2, five more languages are now supported, together with the other ten already in the list. The new languages supported are: Danish, Finnish, Swedish, Czech, Polish. -### Event handling during header row action - -Following some suggestions from customers and partners, we enhanced the `Datatable` to be able to manage event handling during header row action. Two more events have been added: `header-drop` raised when data is dropped on the column header and `cell-drop` raised when data is dropped on the column cell. - -For more details refer to the: -- [DataTable component](../core/components/datatable.component.md). - ### List separator configuration in multi-value metadata As of this version of ADF, developers can configure the list separator of multi-value properties into the metadata viewer. Since this version of ADF, to customize the separator you can set it in your `app.config.json` file inside your `content-metadata` configuration. Below an example. From 42d02146fdaef95158e5ec985db722264c22ea08 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 3 May 2019 14:30:35 +0100 Subject: [PATCH 206/208] [ADF-3.2.0] review link doc (#4689) * review link doc --- docs/README.md | 9 +- .../components/breadcrumb.component.md | 2 +- .../content-metadata-card.component.md | 16 +- .../content-node-selector-panel.component.md | 4 +- .../components/document-list.component.md | 4 +- .../dropdown-breadcrumb.component.md | 2 +- .../components/search-filter.component.md | 6 +- .../interfaces/search-widget.interface.md | 2 +- .../models/image-resolver.model.md | 2 +- .../models/row-filter.model.md | 2 +- .../services/custom-resources.service.md | 3 +- .../services/document-actions.service.md | 8 +- .../services/document-list.service.md | 32 +- .../services/folder-actions.service.md | 8 +- .../services/search-query-builder.service.md | 8 - docs/core/components/data-column.component.md | 5 +- docs/core/components/datatable.component.md | 2 +- .../components/error-content.component.md | 2 +- docs/core/components/form-field.component.md | 4 +- .../infinite-pagination.component.md | 2 +- .../components/sidenav-layout.component.md | 2 +- docs/core/components/start-form.component.md | 3 +- docs/core/components/viewer.component.md | 4 +- docs/core/directives/clipboard.directive.md | 4 +- docs/core/services/authentication.service.md | 4 +- docs/core/services/card-item-types.service.md | 14 +- docs/core/services/form-rendering.service.md | 14 +- docs/core/services/notification.service.md | 11 +- docs/core/services/process-content.service.md | 4 +- docs/core/services/renditions.service.md | 4 +- docs/core/services/storage.service.md | 2 + .../core/services/user-preferences.service.md | 4 + docs/extensions/services/extension.service.md | 16 +- .../components/app-list-cloud.component.md | 1 - .../components/form-cloud.component.md | 2 + ...orm-definition-selector-cloud.component.md | 7 +- .../components/people-cloud.component.md | 4 +- .../process-list-cloud.component.md | 3 +- .../services/form-cloud.service.md | 7 +- .../services/process-header-cloud.service.md | 5 + .../services/process-list-cloud.service.md | 7 +- .../services/start-process-cloud.service.md | 5 + .../services/start-task-cloud.service.md | 4 + .../services/task-cloud.service.md | 5 + .../services/task-list-cloud.service.md | 5 + .../components/form.component.md | 3 +- .../components/process-filters.component.md | 2 +- .../components/start-process.component.md | 2 +- .../services/process-filter.service.md | 4 +- .../services/process.service.md | 8 +- .../services/tasklist.service.md | 6 +- docs/release-notes/RelNote161.md | 4 +- docs/release-notes/RelNote170.md | 6 +- docs/release-notes/RelNote190.md | 2 +- docs/release-notes/RelNote200.md | 18 +- docs/release-notes/RelNote210.md | 4 +- docs/release-notes/RelNote220.md | 2 +- docs/release-notes/RelNote230.md | 14 +- docs/release-notes/RelNote240.md | 2 +- docs/release-notes/RelNote250.md | 6 +- docs/release-notes/RelNote260.md | 16 +- docs/release-notes/RelNote310.md | 371 +++++++------- docs/release-notes/RelNote320.md | 88 ++-- docs/tutorials/README.md | 6 +- docs/tutorials/content-metadata-component.md | 4 +- docs/upgrade-guide/upgrade26-30.md | 462 ++++++++++-------- docs/user-guide/app-extensions.md | 2 +- docs/user-guide/internationalization.md | 4 +- docs/versionIndex.md | 15 +- 69 files changed, 736 insertions(+), 579 deletions(-) diff --git a/docs/README.md b/docs/README.md index 007acbe6fa..01c8635c68 100644 --- a/docs/README.md +++ b/docs/README.md @@ -98,7 +98,7 @@ for more information about installing and using the source code. | [Info drawer layout component](core/components/info-drawer-layout.component.md) | Displays a sidebar-style information panel. | [Source](../lib/core/info-drawer/info-drawer-layout.component.ts) | | [Info Drawer Tab component](core/components/info-drawer-tab.component.md) | Renders tabs in a Info drawer component. | [Source](../lib/core/info-drawer/info-drawer.component.ts) | | [Info Drawer component](core/components/info-drawer.component.md) | Displays a sidebar-style information panel with tabs. | [Source](../lib/core/info-drawer/info-drawer.component.ts) | -| [JsonCell component](core/components/json-cell.component.md) | Show Json formated value inside datatable component. | [Source](../lib/core/datatable/components/datatable/json-cell.component.ts) | +| [Json Cell component](core/components/json-cell.component.md) | Shows a JSON-formatted value inside a datatable component. | [Source](../lib/core/datatable/components/datatable/json-cell.component.ts) | | [Language Menu component](core/components/language-menu.component.md) | Displays all the languages that are present in "app.config.json" and the default (EN). | [Source](../lib/core/language-menu/language-menu.component.ts) | | [Login Dialog Panel component](core/components/login-dialog-panel.component.md) | Shows and manages a login dialog. | [Source](../lib/core/login/components/login-dialog-panel.component.ts) | | [Login Dialog component](core/components/login-dialog.component.md) | Allows a user to perform a login via a dialog. | [Source](../lib/core/login/components/login-dialog.component.ts) | @@ -107,7 +107,7 @@ for more information about installing and using the source code. | [Sidebar action menu component](core/components/sidebar-action-menu.component.md) | Displays a sidebar-action menu information panel. | [Source](../lib/core/layout/components/sidebar-action/sidebar-action-menu.component.ts) | | [Sidenav Layout component](core/components/sidenav-layout.component.md) | Displays the standard three-region ADF application layout. | [Source](../lib/core/layout/components/sidenav-layout/sidenav-layout.component.ts) | | [Sorting Picker Component](core/components/sorting-picker.component.md) | Selects from a set of predefined sorting definitions and directions. | [Source](../lib/core/sorting-picker/sorting-picker.component.ts) | -| [Start Form component](core/components/start-form.component.md) | Displays the Start Form for a process. | [Source](../lib/process-services/form/start-form.component.ts) | +| [Start Form component](core/components/start-form.component.md) | Displays the Start Form for a process. | [Source](../lib/core/form/components/start-form.component.ts) | | [Text Mask directive](core/components/text-mask.component.md) | Implements text field input masks. | [Source](../lib/core/form/components/widgets/text/text-mask.component.ts) | | [Toolbar Divider Component](core/components/toolbar-divider.component.md) | Divides groups of elements in a Toolbar with a visual separator. | [Source](../lib/core/toolbar/toolbar-divider.component.ts) | | [Toolbar Title Component](core/components/toolbar-title.component.md) | Supplies custom HTML to be included in a Toolbar component title. | [Source](../lib/core/toolbar/toolbar-title.component.ts) | @@ -158,11 +158,11 @@ for more information about installing and using the source code. | [Format Space pipe](core/pipes/format-space.pipe.md) | Replaces all the white space in a string with a supplied character. | [Source](../lib/core/pipes/format-space.pipe.ts) | | [Full name pipe](core/pipes/full-name.pipe.md) | Joins the first and last name properties from a UserProcessModel object into a single string. | [Source](../lib/core/pipes/full-name.pipe.ts) | | [Mime Type Icon pipe](core/pipes/mime-type-icon.pipe.md) | Retrieves an icon to represent a MIME type. | [Source](../lib/core/pipes/mime-type-icon.pipe.ts) | +| [Multi Value pipe](core/pipes/multi-value.pipe.md) | Takes an array of strings and turns it into one string where items are separated by a separator. The default separator applied to the list is ', ', however, you can set your own separator in the params of the pipe. | [Source](../lib/core/pipes/multi-value.pipe.ts) | | [Node Name Tooltip pipe](core/pipes/node-name-tooltip.pipe.md) | Formats the tooltip for a Node. | [Source](../lib/core/pipes/node-name-tooltip.pipe.ts) | | [Text Highlight pipe](core/pipes/text-highlight.pipe.md) | Adds highlighting to words or sections of text that match a search string. | [Source](../lib/core/pipes/text-highlight.pipe.ts) | | [Time Ago pipe](core/pipes/time-ago.pipe.md) | Converts a recent past date into a number of days ago. | [Source](../lib/core/pipes/time-ago.pipe.ts) | | [User Initial pipe](core/pipes/user-initial.pipe.md) | Takes the name fields of a UserProcessModel object and extracts and formats the initials. | [Source](../lib/core/pipes/user-initial.pipe.ts) | -| [Multi value pipe](core/pipes/multi-value.pipe.md) | Takes a list of values to stringify them with a custom separator. | [Source](../lib/core/pipes/multi-value.pipe.ts) | ### Services @@ -408,7 +408,9 @@ for more information about installing and using the source code. | [App List Cloud Component](process-services-cloud/components/app-list-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Shows all deployed cloud application instances. | [Source](../lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts) | | [Edit Process Filter Cloud component](process-services-cloud/components/edit-process-filter-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Shows/edits process filter details. | [Source](../lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts) | | [Edit Task Filter Cloud component](process-services-cloud/components/edit-task-filter-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Edits task filter details. | [Source](../lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filter-cloud.component.ts) | +| [Form cloud custom outcomes component](process-services-cloud/components/form-cloud-custom-outcome.component.md) | Supplies custom outcome buttons to be included in Form cloud component. | [Source](../lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts) | | [Form cloud component](process-services-cloud/components/form-cloud.component.md) | Shows a form from Process Services. | [Source](../lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts) | +| [Form definition selector Cloud componet](process-services-cloud/components/form-definition-selector-cloud.component.md) | Allows one form to be selected. | [Source](../lib/process-services-cloud/src/lib/form-definition-selector/components/form-definition-selector-cloud.component.ts) | | [Group Cloud component](process-services-cloud/components/group-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Searches Groups. | [Source](../lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts) | | [People Cloud Component](process-services-cloud/components/people-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Allows one or more users to be selected (with auto-suggestion) based on the input parameters. | [Source](../lib/process-services-cloud/src/lib/task/start-task/components/people-cloud/people-cloud.component.ts) | | [Process Filters Cloud Component](process-services-cloud/components/process-filters-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Lists all available process filters and allows to select a filter. | [Source](../lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.ts) | @@ -417,6 +419,7 @@ for more information about installing and using the source code. | [Start Process Cloud Component](process-services-cloud/components/start-process-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Starts a process. | [Source](../lib/process-services-cloud/src/lib/process/start-process/components/start-process-cloud.component.ts) | | [Start Task Cloud Component](process-services-cloud/components/start-task-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Creates/starts a new task for the specified app. | [Source](../lib/process-services-cloud/src/lib/task/start-task/components/start-task-cloud.component.ts) | | [Task Filters Cloud component](process-services-cloud/components/task-filters-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Shows all available filters. | [Source](../lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.ts) | +| [Form cloud component](process-services-cloud/components/task-form-cloud.component.md) | Shows a form for a task. | [Source](../lib/process-services-cloud/src/lib/form/components/task-form-cloud.component.ts) | | [Task Header Cloud Component](process-services-cloud/components/task-header-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Shows all the information related to a task. | [Source](../lib/process-services-cloud/src/lib/task/task-header/components/task-header-cloud.component.ts) | | [Task List Cloud component](process-services-cloud/components/task-list-cloud.component.md) ![Experimental](docassets/images/ExperimentalIcon.png) | Renders a list containing all the tasks matched by the parameters specified. | [Source](../lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.ts) | diff --git a/docs/content-services/components/breadcrumb.component.md b/docs/content-services/components/breadcrumb.component.md index 17b3f4c773..41cac36dee 100644 --- a/docs/content-services/components/breadcrumb.component.md +++ b/docs/content-services/components/breadcrumb.component.md @@ -36,7 +36,7 @@ Indicates the current position within a navigation hierarchy. | Name | Type | Description | | ---- | ---- | ----------- | -| navigate | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the user clicks on a breadcrumb. | +| navigate | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`PathElement`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/PathElement.md)`>` | Emitted when the user clicks on a breadcrumb. | ## Details diff --git a/docs/content-services/components/content-metadata-card.component.md b/docs/content-services/components/content-metadata-card.component.md index c280ae6f69..6a16df841e 100644 --- a/docs/content-services/components/content-metadata-card.component.md +++ b/docs/content-services/components/content-metadata-card.component.md @@ -11,6 +11,18 @@ Displays and edits metadata related to a node. ![Content metadata screenshot](../../docassets/images/ContentMetadata.png) +## Contents + +- [Basic Usage](#basic-usage) +- [Class members](#class-members) + - [Properties](#properties) +- [Details](#details) + - [Application config presets](#application-config-presets) + - [Layout oriented config](#layout-oriented-config) + - [Displaying all properties](#displaying-all-properties) +- [What happens when there is a whitelisted aspect in the config but the given node doesn't relate to that aspect](#what-happens-when-there-is-a-whitelisted-aspect-in-the-config-but-the-given-node-doesnt-relate-to-that-aspect) +- [Multi value card properties](#multi-value-card-properties) + ## Basic Usage ```html @@ -28,13 +40,13 @@ Displays and edits metadata related to a node. | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | +| displayAspect | `string` | null | (optional) This flag displays desired aspect when open for the first time fields. | | displayEmpty | `boolean` | false | (optional) This flag displays/hides empty metadata fields. | | multi | `boolean` | false | (optional) This flag allows the component to display more than one accordion at a time. | | node | [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) | | (required) The node entity to fetch metadata about | | preset | `string` | | (required) Name of the metadata preset, which defines aspects and their properties. | | readOnly | `boolean` | false | (optional) This flag sets the metadata in read only mode preventing changes. | | displayDefaultProperties | `boolean` | | (optional) This flag displays/hides the metadata properties. | -| displayAspect | `string` | | (optional) This flag displays the desired metadata property in the expanded card | ## Details @@ -217,7 +229,6 @@ The result of this config would be two accordion groups with the following prope | kitten:favourite-food | | kitten:recommended-food | - ### Displaying all properties You can list all the properties by simply adding the `includeAll: boolean` to your config. This config will display all the aspects and properties available for that specific file. @@ -277,6 +288,7 @@ Nothing - since this aspect is not related to the node, it will simply be ignore displayed. The aspects to be displayed are calculated as an intersection of the preset's aspects and the aspects related to the node. ## Multi value card properties + Multi value properties are displayed one after another separated by a comma. This card makes use of the [Multi Value Pipe](../../core/pipes/multi-value.pipe.ts). To customize the separator used by this card you can set it in your `app.config.json` inside your content-metadata configuration: diff --git a/docs/content-services/components/content-node-selector-panel.component.md b/docs/content-services/components/content-node-selector-panel.component.md index f8fd6191bc..6dd81efed8 100644 --- a/docs/content-services/components/content-node-selector-panel.component.md +++ b/docs/content-services/components/content-node-selector-panel.component.md @@ -34,12 +34,12 @@ Opens a [Content Node Selector](content-node-selector.component.md) in its own | currentFolderId | `string` | null | [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) ID of the folder currently listed. | | dropdownHideMyFiles | `boolean` | false | Hide the "My Files" option added to the site list by default. See the [Sites Dropdown component](sites-dropdown.component.md) for more information. | | dropdownSiteList | [`SitePaging`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/SitePaging.md) | null | Custom site for site dropdown. This is the same as the `siteList`. property of the Sites Dropdown component (see its doc page for more information). | -| imageResolver | [`ImageResolver`](../../../lib/content-services/document-list/data/image-resolver.model.ts) | null | Custom image resolver function. See the [Image Resolver Model](../models/image-resolver.model.md) page for more information. | +| imageResolver | [`ImageResolver`](../../../lib/content-services/document-list/data/image-resolver.model.ts) | null | Custom image resolver function. See the [Image Resolver Model](image-resolver.model.md) page for more information. | | isSelectionValid | [`ValidationFunction`](../../../lib/content-services/content-node-selector/content-node-selector-panel.component.ts) | defaultValidation | Function used to decide if the selected node has permission to be selected. Default value is a function that always returns true. | | pageSize | `number` | | Number of items shown per page in the list. | | where | `string` | | Custom _where_ filter function. See the [Document List component](../../content-services/components/document-list.component.md) for more information. | | excludeSiteContent | `string[]` | | Custom list of site content componentIds. Used to filter out the corresponding items from the displayed nodes | -| rowFilter | [`RowFilter`](../../../lib/content-services/document-list/data/row-filter.model.ts) | | Custom row filter function. See the [Row Filter Model](../models/row-filter.model.md) page for more information. | +| rowFilter | [`RowFilter`](../../../lib/content-services/document-list/data/row-filter.model.ts) | | Custom row filter function. See the [Row Filter Model](row-filter.model.md) page for more information. | ### Events diff --git a/docs/content-services/components/document-list.component.md b/docs/content-services/components/document-list.component.md index f8847b463a..5ffa33eec2 100644 --- a/docs/content-services/components/document-list.component.md +++ b/docs/content-services/components/document-list.component.md @@ -62,7 +62,7 @@ Displays the documents from a repository. | contextMenuActions | `boolean` | false | Toggles context menus for each row | | display | `string` | DisplayMode.List | Change the display mode of the table. Can be "list" or "gallery". | | emptyFolderImageUrl | `string` | | Custom image for empty folder. Default value: './assets/images/empty_doc_lib.svg' | -| imageResolver | `any \| null` | null | Custom function to choose image file paths to show. See the [Image Resolver Model](../models/image-resolver.model.md) page for more information. | +| imageResolver | `any \| null` | null | Custom function to choose image file paths to show. See the [Image Resolver Model](image-resolver.model.md) page for more information. | | includeFields | `string[]` | | Include additional information about the node in the server request. For example: association, isLink, isLocked and others. | | loading | `boolean` | false | Toggles the loading state and animated spinners for the component. Used in combination with `navigate=false` to perform custom navigation and loading state indication. | | locationFormat | `string` | "/" | The default route for all the location-based columns (if declared). | @@ -82,7 +82,7 @@ Displays the documents from a repository. | thumbnails | `boolean` | false | Show document thumbnails rather than icons | | where | `string` | | Filters the [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) list using the _where_ condition of the REST API (for example, isFolder=true). See the REST API documentation for more information. | | currentFolderId | `string` | | The ID of the folder node to display or a reserved string alias for special sources | -| rowFilter | [`RowFilter`](../../../lib/content-services/document-list/data/row-filter.model.ts) | | Custom function to choose whether to show or hide rows. See the [Row Filter Model](../models/row-filter.model.md) page for more information. | +| rowFilter | [`RowFilter`](../../../lib/content-services/document-list/data/row-filter.model.ts) | | Custom function to choose whether to show or hide rows. See the [Row Filter Model](row-filter.model.md) page for more information. | ### Events diff --git a/docs/content-services/components/dropdown-breadcrumb.component.md b/docs/content-services/components/dropdown-breadcrumb.component.md index 315069123f..15b160b34b 100644 --- a/docs/content-services/components/dropdown-breadcrumb.component.md +++ b/docs/content-services/components/dropdown-breadcrumb.component.md @@ -37,7 +37,7 @@ Indicates the current position within a navigation hierarchy using a dropdown me | Name | Type | Description | | ---- | ---- | ----------- | -| navigate | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the user clicks on a breadcrumb. | +| navigate | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`PathElement`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/PathElement.md)`>` | Emitted when the user clicks on a breadcrumb. | ## Details diff --git a/docs/content-services/components/search-filter.component.md b/docs/content-services/components/search-filter.component.md index be4e7445a3..8d53ab733e 100644 --- a/docs/content-services/components/search-filter.component.md +++ b/docs/content-services/components/search-filter.component.md @@ -19,8 +19,8 @@ Represents a main container component for custom search and faceted search setti - [Categories and widgets](#categories-and-widgets) - [Facet Fields](#facet-fields) - [Facet Queries](#facet-queries) - - [Highlight](#highlight) - [Facet Intervals](#facet-intervals) + - [Highlight](#highlight) - [See also](#see-also) ## Basic usage @@ -451,7 +451,6 @@ An example query for search highlighting could look like this: } } } - ``` The example above changes the highlighting prefix and postfix from the default to '¿?' for all @@ -479,7 +478,8 @@ then be added in each node entry response. An example partial response is shown } ] }, - ``` +``` + ## See also - [Search Query Builder service](../services/search-query-builder.service.md) diff --git a/docs/content-services/interfaces/search-widget.interface.md b/docs/content-services/interfaces/search-widget.interface.md index 9775c479a4..28ed0b48ed 100644 --- a/docs/content-services/interfaces/search-widget.interface.md +++ b/docs/content-services/interfaces/search-widget.interface.md @@ -36,7 +36,7 @@ export interface SearchWidget { | ---- | ---- | ------------- | ----------- | | id | `string` | | Unique identifying value for the widget | | settings | [`SearchWidgetSettings`](../../../lib/content-services/search/search-widget-settings.interface.ts) | | Settings for component properties | -| context | [`SearchQueryBuilderService`](../services/search-query-builder.service.md) | | Instance of the [Search Query Builder service](../services/search-query-builder.service.md) to process the query | +| context | [`SearchQueryBuilderService`](../../content-services/services/search-query-builder.service.md) | | Instance of the [Search Query Builder service](../services/search-query-builder.service.md) to process the query | ## Details diff --git a/docs/content-services/models/image-resolver.model.md b/docs/content-services/models/image-resolver.model.md index 154f77b0ee..1ea0d8592f 100644 --- a/docs/content-services/models/image-resolver.model.md +++ b/docs/content-services/models/image-resolver.model.md @@ -11,7 +11,7 @@ Defines the Image Resolver function used by the [Document List Component](../com ## Definitions -- `type` **ImageResolver** = (row: [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts), column: [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts)) => `string` +- `type` **[ImageResolver](../../../lib/content-services/document-list/data/image-resolver.model.ts)** = (row: [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts), column: [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts)) => `string` - _row:_ [`DataRow`](../../../lib/core/datatable/data/data-row.model.ts) - Data that defines the row - _column:_ [`DataColumn`](../../../lib/core/datatable/data/data-column.model.ts) - Data that defines the column - **Returns** File path for the image diff --git a/docs/content-services/models/row-filter.model.md b/docs/content-services/models/row-filter.model.md index 9107ff37d5..894c8c4530 100644 --- a/docs/content-services/models/row-filter.model.md +++ b/docs/content-services/models/row-filter.model.md @@ -11,7 +11,7 @@ Defines the Row Filter function used by the [Document List Component](../compone ## Definitions -- `type` **RowFilter** = (value: [`ShareDataRow`](../../../lib/content-services/document-list/data/share-data-row.model.ts), index: `number`, array: [`ShareDataRow`](../../../lib/content-services/document-list/data/share-data-row.model.ts)`[]`) => any +- `type` **[RowFilter](../../../lib/content-services/document-list/data/row-filter.model.ts)** = (value: [`ShareDataRow`](../../../lib/content-services/document-list/data/share-data-row.model.ts), index: `number`, array: [`ShareDataRow`](../../../lib/content-services/document-list/data/share-data-row.model.ts)`[]`) => any - _value:_ [`ShareDataRow`](../../../lib/content-services/document-list/data/share-data-row.model.ts) - Data that defines the row - _index:_ `number` - Index of the row within the list - _array:_ [`ShareDataRow`](../../../lib/content-services/document-list/data/share-data-row.model.ts)`[]` - The full set of rows for the list diff --git a/docs/content-services/services/custom-resources.service.md b/docs/content-services/services/custom-resources.service.md index a969fd6898..4041a54945 100644 --- a/docs/content-services/services/custom-resources.service.md +++ b/docs/content-services/services/custom-resources.service.md @@ -23,10 +23,11 @@ Manages Document List information that is specific to a user. - _node:_ `any` - [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) object - _nodeId:_ `string` - ID of the node object - **Returns** `string` - ID value -- **getRecentFiles**(personId: `string`, pagination: [`PaginationModel`](../../../lib/core/models/pagination.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/NodePaging.md)`>`<br/> +- **getRecentFiles**(personId: `string`, pagination: [`PaginationModel`](../../../lib/core/models/pagination.model.ts), filters?: `string[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/NodePaging.md)`>`<br/> Gets files recently accessed by a user. - _personId:_ `string` - ID of the user - _pagination:_ [`PaginationModel`](../../../lib/core/models/pagination.model.ts) - Specifies how to paginate the results + - _filters:_ `string[]` - (Optional) Specifies additional filters to apply (joined with **AND**) - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/NodePaging.md)`>` - List of nodes for the recently used files - **hasCorrespondingNodeIds**(nodeId: `string`): `boolean`<br/> Does the well-known alias have a corresponding node ID? diff --git a/docs/content-services/services/document-actions.service.md b/docs/content-services/services/document-actions.service.md index 7fb31d2ba2..5a6001abc3 100644 --- a/docs/content-services/services/document-actions.service.md +++ b/docs/content-services/services/document-actions.service.md @@ -17,14 +17,14 @@ Implements the document menu actions for the [Document List component](../compon Checks if actions can be executed for an item. - _nodeEntry:_ [`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md) - Item to receive an action - **Returns** `boolean` - True if the action can be executed on this item, false otherwise -- **getHandler**(key: `string`): `ContentActionHandler`<br/> +- **getHandler**(key: `string`): [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts)<br/> Gets the handler for an action. - _key:_ `string` - Identifier of the action - - **Returns** `ContentActionHandler` - The handler for the action -- **setHandler**(key: `string`, handler: `ContentActionHandler`): `boolean`<br/> + - **Returns** [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts) - The handler for the action +- **setHandler**(key: `string`, handler: [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts)): `boolean`<br/> Sets a new handler for an action. - _key:_ `string` - Identifier of the action - - _handler:_ `ContentActionHandler` - Handler for the action + - _handler:_ [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts) - Handler for the action - **Returns** `boolean` - False if the key was an empty/null string, true otherwise ## Details diff --git a/docs/content-services/services/document-list.service.md b/docs/content-services/services/document-list.service.md index 9daf4d3ef4..139b0795ea 100644 --- a/docs/content-services/services/document-list.service.md +++ b/docs/content-services/services/document-list.service.md @@ -13,22 +13,15 @@ Implements node operations used by the [Document List component](../components/d ### Methods -- **copyNode**(nodeId: `string`, targetParentId: `string`): `any`<br/> +- **copyNode**(nodeId: `string`, targetParentId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>`<br/> Copy a node to destination node - _nodeId:_ `string` - The id of the node to be copied - _targetParentId:_ `string` - The id of the folder where the node will be copied - - **Returns** `any` - [NodeEntry](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md) for the copied node + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>` - NodeEntry for the copied node - **deleteNode**(nodeId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Deletes a node. - _nodeId:_ `string` - ID of the node to delete - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Empty response when the operation is complete -- **getDefaultMimeTypeIcon**(): `string`<br/> - Gets a default icon for MIME types with no specific icon. - - **Returns** `string` - Path to the icon file -- **getDocumentThumbnailUrl**(node: [`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)): `string`<br/> - Get thumbnail URL for the given document node. - - _node:_ [`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md) - [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) to get URL for. - - **Returns** `string` - Thumbnail URL string - **getFolder**(folder: `string`, opts?: `any`, includeFields: `string[]` = `[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/NodePaging.md)`>`<br/> Gets the folder node with the specified relative name path below the root node. - _folder:_ `string` - Path to folder. @@ -40,20 +33,29 @@ Implements node operations used by the [Document List component](../components/d - _nodeId:_ `string` - ID of the folder node - _includeFields:_ `string[]` - Extra information to include (available options are "aspectNames", "isLink" and "association") - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>` - Details of the folder -- **getMimeTypeIcon**(mimeType: `string`): `string`<br/> - Gets the icon that represents a MIME type. - - _mimeType:_ `string` - MIME type to get the icon for - - **Returns** `string` - Path to the icon file - **getNode**(nodeId: `string`, includeFields: `string[]` = `[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>`<br/> Gets a node via its node ID. - _nodeId:_ `string` - ID of the target node - _includeFields:_ `string[]` - Extra information to include (available options are "aspectNames", "isLink" and "association") - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>` - Details of the folder -- **moveNode**(nodeId: `string`, targetParentId: `string`): `any`<br/> +- **isCustomSourceService**(nodeId: `any`): `boolean`<br/> + + - _nodeId:_ `any` - + - **Returns** `boolean` - + +- **loadFolderByNodeId**(nodeId: `string`, pagination: [`PaginationModel`](../../../lib/core/models/pagination.model.ts), includeFields: `string[]`, where?: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`DocumentLoaderNode`](../../../lib/content-services/document-list/models/document-folder.model.ts)`>`<br/> + + - _nodeId:_ `string` - + - _pagination:_ [`PaginationModel`](../../../lib/core/models/pagination.model.ts) - + - _includeFields:_ `string[]` - + - _where:_ `string` - (Optional) + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`DocumentLoaderNode`](../../../lib/content-services/document-list/models/document-folder.model.ts)`>` - + +- **moveNode**(nodeId: `string`, targetParentId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>`<br/> Moves a node to destination node. - _nodeId:_ `string` - The id of the node to be moved - _targetParentId:_ `string` - The id of the folder where the node will be moved - - **Returns** `any` - [NodeEntry](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md) for the moved node + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md)`>` - NodeEntry for the moved node ## Details diff --git a/docs/content-services/services/folder-actions.service.md b/docs/content-services/services/folder-actions.service.md index fc508d6817..2c1697bfbc 100644 --- a/docs/content-services/services/folder-actions.service.md +++ b/docs/content-services/services/folder-actions.service.md @@ -17,14 +17,14 @@ Implements the folder menu actions for the [Document List component](../componen Checks if an action is available for a particular item. - _nodeEntry:_ [`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md) - Item to check - **Returns** `boolean` - True if the action is available, false otherwise -- **getHandler**(key: `string`): `ContentActionHandler`<br/> +- **getHandler**(key: `string`): [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts)<br/> Gets the handler function for an action. - _key:_ `string` - Identifier for the action - - **Returns** `ContentActionHandler` - The handler function -- **setHandler**(key: `string`, handler: `ContentActionHandler`): `boolean`<br/> + - **Returns** [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts) - The handler function +- **setHandler**(key: `string`, handler: [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts)): `boolean`<br/> Sets a new handler function for an action. - _key:_ `string` - Identifier for the action - - _handler:_ `ContentActionHandler` - The new handler function + - _handler:_ [`ContentActionHandler`](../../../lib/content-services/document-list/models/content-action.model.ts) - The new handler function - **Returns** `boolean` - True if the key was a valid action identifier, false otherwise ## Details diff --git a/docs/content-services/services/search-query-builder.service.md b/docs/content-services/services/search-query-builder.service.md index 8b04806a22..ac180cf915 100644 --- a/docs/content-services/services/search-query-builder.service.md +++ b/docs/content-services/services/search-query-builder.service.md @@ -11,14 +11,6 @@ Stores information from all the custom search and faceted search widgets, compil ## Class members -### Events - -| Name | Type | Details | -| --- | --- | --- | -| updated | QueryBody | Raised when query gets updated but before query is executed | -| executed | ResultSetPaging | Raised when query gets executed and results are available | -| error | any | Raised when search api emits internal error | - ### Methods - **addFilterQuery**(query: `string`)<br/> diff --git a/docs/core/components/data-column.component.md b/docs/core/components/data-column.component.md index e8c197b8dc..8d845e8ff2 100644 --- a/docs/core/components/data-column.component.md +++ b/docs/core/components/data-column.component.md @@ -20,7 +20,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo - [Custom tooltips](#custom-tooltips) - [Column Template](#column-template) - [Styling Techniques](#styling-techniques) - - [Using the `copyContent` option](#using-the-copycontent-option) + - [Using the copyContent option](#using-the-copycontent-option) - [See also](#see-also) ## Basic Usage @@ -303,7 +303,7 @@ Now you can declare columns and assign the `desktop-only` class where needed: ### Using the `copyContent` option When the `copyContent` property is true, a -Clipboard directive +[Clipboard directive](../../core/directives/clipboard.directive.md) is added to each cell in the column. This lets the user copy the cell content to the clipboard with a mouse click. @@ -328,6 +328,7 @@ HTML `<data-column>` element example: </data-columns> </adf-tasklist> ``` + ## See also - [Document list component](../../content-services/components/document-list.component.md) diff --git a/docs/core/components/datatable.component.md b/docs/core/components/datatable.component.md index 45f125f9a5..8def0c4c8b 100644 --- a/docs/core/components/datatable.component.md +++ b/docs/core/components/datatable.component.md @@ -311,7 +311,7 @@ while the data for the table is loading: } ``` -###Styling transcluded content +\###Styling transcluded content When adding your custom templates you can style them as you like. However, for an out of the box experience, if you want to apply datatable styles to your column you will need to follow this structure: diff --git a/docs/core/components/error-content.component.md b/docs/core/components/error-content.component.md index 08e89eb195..79b32f4789 100644 --- a/docs/core/components/error-content.component.md +++ b/docs/core/components/error-content.component.md @@ -23,7 +23,7 @@ this.router.navigate(['/error', errorCode]); | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| errorCode | `string` | "UNKNOWN" | Error code associated with this error. | +| errorCode | `string` | | Error code associated with this error. | | returnButtonUrl | `string` | "/" | Target URL for the return button. | | secondaryButtonUrl | `string` | "report-issue" | Target URL for the secondary button. | diff --git a/docs/core/components/form-field.component.md b/docs/core/components/form-field.component.md index 8c1b96959d..8416db91b0 100644 --- a/docs/core/components/form-field.component.md +++ b/docs/core/components/form-field.component.md @@ -38,8 +38,8 @@ uses `<adf-form-field>` components to render the form fields. Forms defined in APS have the following default mappings for the form fields: -| _APS [Form](../../../lib/process-services/task-list/models/form.model.ts) Designer_ Widget | Field Type | Component Type | -| ------------------------------------------------------------------------------------------ | ---------- | -------------- | +| _APS [`Form`](../../../lib/process-services/task-list/models/form.model.ts) Designer_ Widget | Field Type | Component Type | +| -------------------------------------------------------------------------------------------- | ---------- | -------------- | | Text | text | [`TextWidgetComponent`](../../../lib/core/form/components/widgets/text/text.widget.ts) | | Multi-line text | multi-line-text | [`MultilineTextWidgetComponentComponent`](../../../lib/core/form/components/widgets/multiline-text/multiline-text.widget.ts) | | Number | integer | [`NumberWidgetComponent`](../../../lib/core/form/components/widgets/number/number.widget.ts) | diff --git a/docs/core/components/infinite-pagination.component.md b/docs/core/components/infinite-pagination.component.md index 790ed345fb..0ea6844b7a 100644 --- a/docs/core/components/infinite-pagination.component.md +++ b/docs/core/components/infinite-pagination.component.md @@ -40,7 +40,7 @@ Adds "infinite" pagination to the component it is used with. | ---- | ---- | ------------- | ----------- | | isLoading | `boolean` | false | Is a new page loading? | | pageSize | `number` | | Number of items that are added with each "load more" event. | -| target | | | Component that provides custom pagination support. | +| target | [`PaginatedComponent`](../../../lib/core/pagination/paginated-component.interface.ts) | | Component that provides custom pagination support. | ### Events diff --git a/docs/core/components/sidenav-layout.component.md b/docs/core/components/sidenav-layout.component.md index 9909512001..b5a0b87028 100644 --- a/docs/core/components/sidenav-layout.component.md +++ b/docs/core/components/sidenav-layout.component.md @@ -69,13 +69,13 @@ sub-components (note the use of `<ng-template>` in the sub-components' body sect | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | +| direction | `string` | "ltr" | The direction of the layout. 'ltr' or 'rtl' | | expandedSidenav | `boolean` | true | Should the navigation region be expanded initially? | | hideSidenav | `boolean` | false | Toggles showing/hiding the navigation region. | | position | `string` | "start" | The side that the drawer is attached to. Possible values are 'start' and 'end'. | | sidenavMax | `number` | | Maximum size of the navigation region. | | sidenavMin | `number` | | Minimum size of the navigation region. | | stepOver | `number` | | Screen size at which display switches from small screen to large screen configuration. | -| direction | `string` | `ltr` | The direction of the layout. 'ltr' or 'rtl' | ### Events diff --git a/docs/core/components/start-form.component.md b/docs/core/components/start-form.component.md index 75c5488137..d31a41c4fc 100644 --- a/docs/core/components/start-form.component.md +++ b/docs/core/components/start-form.component.md @@ -5,7 +5,7 @@ Status: Active Last reviewed: 2018-06-08 --- -# [Start Form component](../../../lib/core/form/components/start-form.component.ts "Defined in start-form.component.ts") +# [Start Form component](../../../lib/process-services/form/start-form.component.ts "Defined in start-form.component.ts") Displays the Start [`Form`](../../../lib/process-services/task-list/models/form.model.ts) for a process. @@ -42,7 +42,6 @@ Displays the Start [`Form`](../../../lib/process-services/task-list/models/form. | readOnlyForm | `boolean` | false | Is the form read-only (ie, can't be edited)? | | saveMetadata | `boolean` | false | Toggle saving of form metadata. | | showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | -| showDebugButton | `boolean` | false | Toggle debug options. | | showOutcomeButtons | `boolean` | true | Should form outcome buttons be shown? | | showRefreshButton | `boolean` | true | Should the refresh button be shown? | | showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. | diff --git a/docs/core/components/viewer.component.md b/docs/core/components/viewer.component.md index a2a23ea68d..3d917e4c7c 100644 --- a/docs/core/components/viewer.component.md +++ b/docs/core/components/viewer.component.md @@ -24,7 +24,7 @@ See it live: [Viewer Quickstart](https://embed.plnkr.co/iTuG1lFIXfsP95l6bDW6/) - [Custom file parameters](#custom-file-parameters) - [Supported file formats](#supported-file-formats) - [Content Renditions](#content-renditions) - - [Configuring PDF.js library](#configuring-pdf-js-library) + - [Configuring PDF.js library](#configuring-pdfjs-library) - [Extending the Viewer](#extending-the-viewer) - [Custom layout](#custom-layout) - [Printing](#printing) @@ -475,7 +475,7 @@ Note: For the pdf viewer the value has to be within the range of 25 - 1000. "adf-viewer": { "pdf-viewer-scaling": 150 } - + In the same way you can set a default zoom scaling value for the image viewer by adding the following code in `app.config.json`. "adf-viewer": { diff --git a/docs/core/directives/clipboard.directive.md b/docs/core/directives/clipboard.directive.md index 7d586277af..0a29f4839f 100644 --- a/docs/core/directives/clipboard.directive.md +++ b/docs/core/directives/clipboard.directive.md @@ -27,8 +27,8 @@ Copies text to the clipboard. | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| adf-clipboard | `string` | | Translation key or message for the tooltip. | -| clipboard-notification | `string` | | Translation key or message for snackbar notification. | +| message | `string` | | Translation key or message for snackbar notification. | +| placeholder | `string` | | Translation key or message for the tooltip. | | target | [`HTMLInputElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement)` \| `[`HTMLTextAreaElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement) | | Reference to the HTML element containing the text to copy. | ## Details diff --git a/docs/core/services/authentication.service.md b/docs/core/services/authentication.service.md index 17e244bdbf..7e18bb6ab8 100644 --- a/docs/core/services/authentication.service.md +++ b/docs/core/services/authentication.service.md @@ -81,9 +81,9 @@ Provides authentication to ACS and APS. - _password:_ `string` - Password for the login - _rememberMe:_ `boolean` - Stores the user's login details if true - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<Function>` - Object with auth type ("ECM", "BPM" or "ALL") and auth ticket -- **logout**(): `any`<br/> +- **logout**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Logs the user out. - - **Returns** `any` - Response event called when logout is complete + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Response event called when logout is complete - **setRedirect**(url: [`RedirectionModel`](../../../lib/core/models/redirection.model.ts))<br/> Sets the URL to redirect to after login. - _url:_ [`RedirectionModel`](../../../lib/core/models/redirection.model.ts) - URL to redirect to diff --git a/docs/core/services/card-item-types.service.md b/docs/core/services/card-item-types.service.md index 3aba8f86f6..8da233dd35 100644 --- a/docs/core/services/card-item-types.service.md +++ b/docs/core/services/card-item-types.service.md @@ -13,27 +13,27 @@ Maps type names to field component types for the [Card View component](../compon ### Methods -- **getComponentTypeResolver**(type: `string`, defaultValue: `Type<__type>` = `this.defaultValue`): `DynamicComponentResolveFunction`<br/> - Gets the currently active DynamicComponentResolveFunction for a field type. +- **getComponentTypeResolver**(type: `string`, defaultValue: `Type<__type>` = `this.defaultValue`): [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts)<br/> + Gets the currently active [DynamicComponentResolveFunction](../../../lib/core/services/dynamic-component-mapper.service.ts) for a field type. - _type:_ `string` - The type whose resolver you want - _defaultValue:_ `Type<__type>` - Default type returned for types that are not yet mapped - - **Returns** `DynamicComponentResolveFunction` - Resolver function + - **Returns** [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts) - Resolver function - **resolveComponentType**(model: [`DynamicComponentModel`](../../../lib/core/services/dynamic-component-mapper.service.ts), defaultValue: `Type<__type>` = `this.defaultValue`): `Type<__type>`<br/> Finds the component type that is needed to render a form field. - _model:_ [`DynamicComponentModel`](../../../lib/core/services/dynamic-component-mapper.service.ts) - [Form](../../../lib/process-services/task-list/models/form.model.ts) field model for the field to render - _defaultValue:_ `Type<__type>` - Default type returned for field types that are not yet mapped. - **Returns** `Type<__type>` - Component type -- **setComponentTypeResolver**(type: `string`, resolver: `DynamicComponentResolveFunction`, override: `boolean` = `true`)<br/> - Sets or optionally replaces a DynamicComponentResolveFunction for a field type. +- **setComponentTypeResolver**(type: `string`, resolver: [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts), override: `boolean` = `true`)<br/> + Sets or optionally replaces a [DynamicComponentResolveFunction](../../../lib/core/services/dynamic-component-mapper.service.ts) for a field type. - _type:_ `string` - The type whose resolver you want to set - - _resolver:_ `DynamicComponentResolveFunction` - The new resolver function + - _resolver:_ [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts) - The new resolver function - _override:_ `boolean` - The new resolver will only replace an existing one if this parameter is true ## Details The [Card View component](../components/card-view.component.md) uses this service to find the component type that is required to display a particular field type (text, date, etc). The service -maps a type name string to a corresponding `DynamicComponentResolveFunction` that takes a +maps a type name string to a corresponding [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts) that takes a model object as a parameter and returns the component type needed to display that model. The default mapping is shown below: diff --git a/docs/core/services/form-rendering.service.md b/docs/core/services/form-rendering.service.md index 1551307936..011b850746 100644 --- a/docs/core/services/form-rendering.service.md +++ b/docs/core/services/form-rendering.service.md @@ -13,20 +13,20 @@ Maps a form field type string onto the corresponding form [widget component](../ ### Methods -- **getComponentTypeResolver**(type: `string`, defaultValue: `Type<__type>` = `this.defaultValue`): `DynamicComponentResolveFunction`<br/> - Gets the currently active DynamicComponentResolveFunction for a field type. +- **getComponentTypeResolver**(type: `string`, defaultValue: `Type<__type>` = `this.defaultValue`): [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts)<br/> + Gets the currently active [DynamicComponentResolveFunction](../../../lib/core/services/dynamic-component-mapper.service.ts) for a field type. - _type:_ `string` - The type whose resolver you want - _defaultValue:_ `Type<__type>` - Default type returned for types that are not yet mapped - - **Returns** `DynamicComponentResolveFunction` - Resolver function + - **Returns** [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts) - Resolver function - **resolveComponentType**(model: [`DynamicComponentModel`](../../../lib/core/services/dynamic-component-mapper.service.ts), defaultValue: `Type<__type>` = `this.defaultValue`): `Type<__type>`<br/> Finds the component type that is needed to render a form field. - _model:_ [`DynamicComponentModel`](../../../lib/core/services/dynamic-component-mapper.service.ts) - [Form](../../../lib/process-services/task-list/models/form.model.ts) field model for the field to render - _defaultValue:_ `Type<__type>` - Default type returned for field types that are not yet mapped. - **Returns** `Type<__type>` - Component type -- **setComponentTypeResolver**(type: `string`, resolver: `DynamicComponentResolveFunction`, override: `boolean` = `true`)<br/> - Sets or optionally replaces a DynamicComponentResolveFunction for a field type. +- **setComponentTypeResolver**(type: `string`, resolver: [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts), override: `boolean` = `true`)<br/> + Sets or optionally replaces a [DynamicComponentResolveFunction](../../../lib/core/services/dynamic-component-mapper.service.ts) for a field type. - _type:_ `string` - The type whose resolver you want to set - - _resolver:_ `DynamicComponentResolveFunction` - The new resolver function + - _resolver:_ [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts) - The new resolver function - _override:_ `boolean` - The new resolver will only replace an existing one if this parameter is true ## Details @@ -34,7 +34,7 @@ Maps a form field type string onto the corresponding form [widget component](../ The [`Form`](../../../lib/process-services/task-list/models/form.model.ts) Field component uses this service to choose which widget to use to render an instance of a form field. The [`Form`](../../../lib/process-services/task-list/models/form.model.ts) Field model stores the field type name as a string (see the table below). The [`Form`](../../../lib/process-services/task-list/models/form.model.ts) Rendering service maintains a mapping between each type name and -a corresponding `DynamicComponentResolveFunction`. The function takes a [`FormFieldModel`](../../core/models/form-field.model.md) object as its argument and +a corresponding [`DynamicComponentResolveFunction`](../../../lib/core/services/dynamic-component-mapper.service.ts). The function takes a [`FormFieldModel`](../../core/models/form-field.model.md) object as its argument and uses the data from the object to determine which widget should be used to render the field. In some cases, the field type string alone is enough to determine the widget type and so the function diff --git a/docs/core/services/notification.service.md b/docs/core/services/notification.service.md index 676af8ef51..28a729fd8e 100644 --- a/docs/core/services/notification.service.md +++ b/docs/core/services/notification.service.md @@ -17,16 +17,16 @@ Shows a notification message with optional feedback. - **dismissSnackMessageAction**()<br/> dismiss the notification snackbar -- **openSnackMessage**(message: `string`, config: `number|MatSnackBarConfig` = [`NotificationService`](../../core/services/notification.service.md)`.DEFAULT_DURATION_MESSAGE`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`<any>`<br/> +- **openSnackMessage**(message: `string`, config?: `number|MatSnackBarConfig`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`<any>`<br/> Opens a SnackBar notification to show a message. - _message:_ `string` - The message (or resource key) to show. - - _config:_ `number|MatSnackBarConfig` - Time before notification disappears after being shown or MatSnackBarConfig object + - _config:_ `number|MatSnackBarConfig` - (Optional) Time before notification disappears after being shown or MatSnackBarConfig object - **Returns** [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`<any>` - Information/control object for the SnackBar -- **openSnackMessageAction**(message: `string`, action: `string`, config: `number|MatSnackBarConfig` = [`NotificationService`](../../core/services/notification.service.md)`.DEFAULT_DURATION_MESSAGE`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`<any>`<br/> +- **openSnackMessageAction**(message: `string`, action: `string`, config?: `number|MatSnackBarConfig`): [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`<any>`<br/> Opens a SnackBar notification with a message and a response button. - _message:_ `string` - The message (or resource key) to show. - _action:_ `string` - Caption for the response button - - _config:_ `number|MatSnackBarConfig` - Time before notification disappears after being shown or MatSnackBarConfig object + - _config:_ `number|MatSnackBarConfig` - (Optional) Time before notification disappears after being shown or MatSnackBarConfig object - **Returns** [`MatSnackBarRef`](https://material.angular.io/components/snack-bar/overview)`<any>` - Information/control object for the SnackBar ## Details @@ -93,11 +93,10 @@ export class MyComponent implements OnInit { } } ``` + The default message duration is 5000 ms that is used only if you don't pass a custom duration in the parameters of openSnackMessageAction/openSnackMessage methods. You can also change the default 5000 ms adding the following configuration in the app.config.json: ```json - "notificationDefaultDuration" : "7000" - ``` diff --git a/docs/core/services/process-content.service.md b/docs/core/services/process-content.service.md index 06da886eb9..df09795d8d 100644 --- a/docs/core/services/process-content.service.md +++ b/docs/core/services/process-content.service.md @@ -18,12 +18,12 @@ Manipulates content related to a Process Instance or Task Instance in APS. - _content:_ `any` - File to associate - _opts:_ `any` - (Optional) Options supported by JS-API - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Details of created content -- **createTaskRelatedContent**(taskId: `string`, file: `any`, opts?: `any`): `any`<br/> +- **createTaskRelatedContent**(taskId: `string`, file: `any`, opts?: `any`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Associates an uploaded file with a task instance. - _taskId:_ `string` - ID of the target task - _file:_ `any` - File to associate - _opts:_ `any` - (Optional) Options supported by JS-API - - **Returns** `any` - Details of created content + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Details of created content - **createTemporaryRawRelatedContent**(file: `any`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`RelatedContentRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-activiti-rest-api/docs/RelatedContentRepresentation.md)`>`<br/> Create temporary related content from an uploaded file. - _file:_ `any` - File to use for content diff --git a/docs/core/services/renditions.service.md b/docs/core/services/renditions.service.md index 3da126c3f3..f3f4220c86 100644 --- a/docs/core/services/renditions.service.md +++ b/docs/core/services/renditions.service.md @@ -13,13 +13,13 @@ Manages prearranged conversions of content to different formats. ### Methods -- **convert**(nodeId: `string`, encoding: `string`, pollingInterval: `number` = `1000`, retries: `number` = `5`): [`Observable`](http://reactivex.io/documentation/observable.html)`<Object>`<br/> +- **convert**(nodeId: `string`, encoding: `string`, pollingInterval: `number` = `1000`, retries: `number` = `5`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`RenditionEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/RenditionEntry.md)`>`<br/> Repeatedly attempts to create a rendition, through to success or failure. - _nodeId:_ `string` - ID of the target node - _encoding:_ `string` - Name of the rendition encoding - _pollingInterval:_ `number` - Time interval (in milliseconds) between checks for completion - _retries:_ `number` - Number of attempts to make before declaring failure - - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<Object>` - True if the rendition was created, false otherwise + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`RenditionEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/RenditionEntry.md)`>` - True if the rendition was created, false otherwise - **createRendition**(nodeId: `string`, encoding: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<__type>`<br/> Creates a rendition for a node. - _nodeId:_ `string` - ID of the target node diff --git a/docs/core/services/storage.service.md b/docs/core/services/storage.service.md index 1b904d49c4..9fd0101998 100644 --- a/docs/core/services/storage.service.md +++ b/docs/core/services/storage.service.md @@ -15,6 +15,8 @@ Stores items in the form of key-value pairs. - **clear**()<br/> Removes all currently stored items. +- **getAppPrefix**()<br/> + Sets the prefix that is used for the local storage of the app It assigns the string that is defined i the app config, empty prefix otherwise. - **getItem**(key: `string`): `string|null`<br/> Gets an item. - _key:_ `string` - Key to identify the item diff --git a/docs/core/services/user-preferences.service.md b/docs/core/services/user-preferences.service.md index 78e5deac19..ea39b6cc93 100644 --- a/docs/core/services/user-preferences.service.md +++ b/docs/core/services/user-preferences.service.md @@ -43,6 +43,10 @@ Stores preferences for the app and for individual components. - **setStoragePrefix**(value: `string`)<br/> Sets the active storage prefix for preferences. - _value:_ `string` - Name of the prefix +- **setWithoutStore**(property: `string`, value: `any`)<br/> + Sets a preference property. + - _property:_ `string` - Name of the property + - _value:_ `any` - New value for the property ## Details diff --git a/docs/extensions/services/extension.service.md b/docs/extensions/services/extension.service.md index f3904f526e..53a41f2782 100644 --- a/docs/extensions/services/extension.service.md +++ b/docs/extensions/services/extension.service.md @@ -13,10 +13,10 @@ Manages and runs basic extension functionality. ### Methods -- **evaluateRule**(ruleId: `string`, context: [`RuleContext`](../../../lib/extensions/src/lib/config/rule.extensions.ts)): `boolean`<br/> +- **evaluateRule**(ruleId: `string`, context?: [`RuleContext`](../../../lib/extensions/src/lib/config/rule.extensions.ts)): `boolean`<br/> Evaluates a rule. - _ruleId:_ `string` - ID of the rule to evaluate - - _context:_ [`RuleContext`](../../../lib/extensions/src/lib/config/rule.extensions.ts) - Parameter object for the evaluator with details of app state + - _context:_ [`RuleContext`](../../../lib/extensions/src/lib/config/rule.extensions.ts) - (Optional) (optional) Custom rule execution context. - **Returns** `boolean` - True if the rule passed, false otherwise - **getActionById**(id: `string`): [`ActionRef`](../../../lib/extensions/src/lib/config/action.extensions.ts)<br/> Retrieves an action using its ID value. @@ -30,10 +30,16 @@ Manages and runs basic extension functionality. Retrieves a registered [extension component](../../../lib/extensions/src/lib/services/component-register.service.ts) using its ID value. - _id:_ `string` - The ID value to look for - **Returns** `Type<>` - The component or null if not found -- **getEvaluator**(key: `string`): `RuleEvaluator`<br/> - Retrieves a RuleEvaluator function using its key name. +- **getElements**(key: `string`, fallback: `Array<>` = `[]`): `Array<>`<br/> + + - _key:_ `string` - + - _fallback:_ `Array<>` - + - **Returns** `Array<>` - + +- **getEvaluator**(key: `string`): [`RuleEvaluator`](../../../lib/extensions/src/lib/config/rule.extensions.ts)<br/> + Retrieves a [RuleEvaluator](../../../lib/extensions/src/lib/config/rule.extensions.ts) function using its key name. - _key:_ `string` - Key name to look for - - **Returns** `RuleEvaluator` - RuleEvaluator or null if not found + - **Returns** [`RuleEvaluator`](../../../lib/extensions/src/lib/config/rule.extensions.ts) - [RuleEvaluator](../../../lib/extensions/src/lib/config/rule.extensions.ts) or null if not found - **getFeature**(key: `string`): `any[]`<br/> Gets features by key. - _key:_ `string` - Key string, using dot notation diff --git a/docs/process-services-cloud/components/app-list-cloud.component.md b/docs/process-services-cloud/components/app-list-cloud.component.md index 234585d6a8..490ae0f84d 100644 --- a/docs/process-services-cloud/components/app-list-cloud.component.md +++ b/docs/process-services-cloud/components/app-list-cloud.component.md @@ -41,7 +41,6 @@ For example : "alfresco-deployed-apps" : [{"name": "simple-app"}] ``` - ## Class members ### Properties diff --git a/docs/process-services-cloud/components/form-cloud.component.md b/docs/process-services-cloud/components/form-cloud.component.md index 3b75144917..8736b93555 100644 --- a/docs/process-services-cloud/components/form-cloud.component.md +++ b/docs/process-services-cloud/components/form-cloud.component.md @@ -12,6 +12,7 @@ Shows a [`form`](../../../lib/process-services-cloud/src/lib/form/models/form-cl ## Contents - [Basic Usage](#basic-usage) + - [Custom form outcomes template](#custom-form-outcomes-template) - [Empty form template](#empty-form-template) - [Class members](#class-members) - [Properties](#properties) @@ -98,6 +99,7 @@ The template defined inside `empty-form` will be shown when no form definition i | error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when any error occurs. | | executeOutcome | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormOutcomeEvent`](../../../lib/core/form/components/widgets/core/form-outcome-event.model.ts)`>` | Emitted when any outcome is executed. Default behaviour can be prevented via `event.preventDefault()`. | | formCompleted | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is submitted with the `Complete` outcome. | +| formContentClicked | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | | | formDataRefreshed | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when form values are refreshed due to a data property change. | | formError | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormFieldModel`](../../core/models/form-field.model.md)`[]>` | Emitted when the supplied form values have a validation error. | | formLoaded | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`FormCloud`](../../../lib/process-services-cloud/src/lib/form/models/form-cloud.model.ts)`>` | Emitted when the form is loaded or reloaded. | diff --git a/docs/process-services-cloud/components/form-definition-selector-cloud.component.md b/docs/process-services-cloud/components/form-definition-selector-cloud.component.md index c4ee8d865a..2da112cdc3 100644 --- a/docs/process-services-cloud/components/form-definition-selector-cloud.component.md +++ b/docs/process-services-cloud/components/form-definition-selector-cloud.component.md @@ -1,5 +1,4 @@ - -# [Form Definition Selector Cloud](../../../lib/process-services-cloud/src/lib/form-definition-selector/components/form-definition-selector-cloud.component.ts "Defined in form-definition-selector-cloud.component.ts") +# [Form Definition Selector Cloud](../../../lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts "Defined in form-definition-selector-cloud.component.ts") Allows one form to be selected. @@ -18,10 +17,10 @@ Allows one form to be selected. | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| appName | `string` | | (**required**) Name of the application. If specified, this shows the users who have access to the app. +| appName | `string` | | Name of the application. If specified, this shows the users who have access to the app. | ### Events | Name | Type | Description | | ---- | ---- | ----------- | -| selectForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`string`](../../../lib/core/userinfo/models/identity-user.model.ts)`>` | Emitted when a form is selected. | +| selectForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when a form is selected. | diff --git a/docs/process-services-cloud/components/people-cloud.component.md b/docs/process-services-cloud/components/people-cloud.component.md index f42dce375f..da3cc9df6b 100644 --- a/docs/process-services-cloud/components/people-cloud.component.md +++ b/docs/process-services-cloud/components/people-cloud.component.md @@ -28,8 +28,8 @@ Allows one or more users to be selected (with auto-suggestion) based on the inpu | mode | `string` | | User selection mode (single/multiple). | | preSelectUsers | [`IdentityUserModel`](../../../lib/core/userinfo/models/identity-user.model.ts)`[]` | | Array of users to be pre-selected. All users in the array are pre-selected in multi selection mode, but only the first user is pre-selected in single selection mode. Mandatory properties are: id, email, username | | roles | `string[]` | | Role names of the users to be listed. | -| validate | `Boolean` | false | This flag enables the validation on the preSelectUsers passed as input. In case the flag is true the components call the identity service to verify the validity of the information passed as input. Otherwise, no check will be done. | -| title | `string` | | Translation key for the input placeholder | +| title | `string` | | Placeholder translation key | +| validate | `Boolean` | false | This flag enables the validation on the preSelectUsers passed as input. In case the flag is true the components call the [identity service](../../../lib/testing/src/lib/core/actions/identity/identity.service.ts) to verify the validity of the information passed as input. Otherwise, no check will be done. | ### Events diff --git a/docs/process-services-cloud/components/process-list-cloud.component.md b/docs/process-services-cloud/components/process-list-cloud.component.md index 07036c0723..5b12220bed 100644 --- a/docs/process-services-cloud/components/process-list-cloud.component.md +++ b/docs/process-services-cloud/components/process-list-cloud.component.md @@ -50,7 +50,7 @@ when the process list is empty: | Name | Type | Default value | Description | | ---- | ---- | ------------- | ----------- | -| appName | `string` | "" | The name of the application. | +| appName | `string` | | The name of the application. | | businessKey | `string` | "" | Filter the processes to display only the ones with this businessKey value. | | id | `string` | "" | Filter the processes to display only the ones with this ID. | | initiator | `string` | "" | Name of the initiator of the process. | @@ -190,7 +190,6 @@ The configuration related to the pagination can be changed from the `app.config. "size": 20, "supportedPageSizes": [ 5, 10, 15, 20 ] }, - ``` ## See also diff --git a/docs/process-services-cloud/services/form-cloud.service.md b/docs/process-services-cloud/services/form-cloud.service.md index aeca24c579..0c06cef312 100644 --- a/docs/process-services-cloud/services/form-cloud.service.md +++ b/docs/process-services-cloud/services/form-cloud.service.md @@ -40,6 +40,11 @@ class MyComponent { - _nodeId:_ `any` - - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - + - **getForm**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Gets a form definition. - _appName:_ `string` - Name of the app @@ -82,4 +87,4 @@ class MyComponent { ## See also -- [Form cloud component](../components/form-cloud.component.md) +- [Form cloud component](../components/form-cloud.component.md) diff --git a/docs/process-services-cloud/services/process-header-cloud.service.md b/docs/process-services-cloud/services/process-header-cloud.service.md index 381fc9a2ae..bdabe7fdeb 100644 --- a/docs/process-services-cloud/services/process-header-cloud.service.md +++ b/docs/process-services-cloud/services/process-header-cloud.service.md @@ -13,6 +13,11 @@ Manages cloud process instances. ### Methods +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - + - **getProcessInstanceById**(appName: `string`, processInstanceId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceCloud`](../../../lib/process-services-cloud/src/lib/process/start-process/models/process-instance-cloud.model.ts)`>`<br/> Gets details of a process instance. - _appName:_ `string` - Name of the app diff --git a/docs/process-services-cloud/services/process-list-cloud.service.md b/docs/process-services-cloud/services/process-list-cloud.service.md index dc0261825d..30d836300b 100644 --- a/docs/process-services-cloud/services/process-list-cloud.service.md +++ b/docs/process-services-cloud/services/process-list-cloud.service.md @@ -13,6 +13,11 @@ Searches processes. ### Methods +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - + - **getProcessByRequest**(requestNode: [`ProcessQueryCloudRequestModel`](../../../lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Finds a process using an object with optional query properties. - _requestNode:_ [`ProcessQueryCloudRequestModel`](../../../lib/process-services-cloud/src/lib/process/process-list/models/process-cloud-query-request.model.ts) - Query object @@ -36,4 +41,4 @@ For example : ## See also -- [App list cloud component](../components/app-list-cloud.component.md) +- [App list cloud component](../components/app-list-cloud.component.md) diff --git a/docs/process-services-cloud/services/start-process-cloud.service.md b/docs/process-services-cloud/services/start-process-cloud.service.md index fa3c19b55e..466a9017b8 100644 --- a/docs/process-services-cloud/services/start-process-cloud.service.md +++ b/docs/process-services-cloud/services/start-process-cloud.service.md @@ -13,6 +13,11 @@ Gets process definitions and starts processes. ### Methods +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - + - **getProcessDefinitions**(appName: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessDefinitionCloud`](../../../lib/process-services-cloud/src/lib/process/start-process/models/process-definition-cloud.model.ts)`[]>`<br/> Gets the process definitions associated with an app. - _appName:_ `string` - Name of the target app diff --git a/docs/process-services-cloud/services/start-task-cloud.service.md b/docs/process-services-cloud/services/start-task-cloud.service.md index d9aa6f3a35..05632e5dab 100644 --- a/docs/process-services-cloud/services/start-task-cloud.service.md +++ b/docs/process-services-cloud/services/start-task-cloud.service.md @@ -17,6 +17,10 @@ Starts standalone tasks. Creates a new standalone task. - _taskDetails:_ [`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts) - Details of the task to create - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>` - Details of the newly created task +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - ## Details diff --git a/docs/process-services-cloud/services/task-cloud.service.md b/docs/process-services-cloud/services/task-cloud.service.md index 23ff3ae9dc..8589f850a3 100644 --- a/docs/process-services-cloud/services/task-cloud.service.md +++ b/docs/process-services-cloud/services/task-cloud.service.md @@ -36,6 +36,11 @@ Manages task cloud. - _appName:_ `string` - Name of the app - _taskId:_ `string` - ID of the task to complete - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>` - Details of the task that was completed +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - + - **getTaskById**(appName: `string`, taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsCloudModel`](../../../lib/process-services-cloud/src/lib/task/start-task/models/task-details-cloud.model.ts)`>`<br/> Gets details of a task. - _appName:_ `string` - Name of the app diff --git a/docs/process-services-cloud/services/task-list-cloud.service.md b/docs/process-services-cloud/services/task-list-cloud.service.md index 36ab32c940..9151185ceb 100644 --- a/docs/process-services-cloud/services/task-list-cloud.service.md +++ b/docs/process-services-cloud/services/task-list-cloud.service.md @@ -13,6 +13,11 @@ Searches tasks. ### Methods +- **getBasePath**(appName: `string`): `string`<br/> + + - _appName:_ `string` - + - **Returns** `string` - + - **getTaskByRequest**(requestNode: [`TaskQueryCloudRequestModel`](../../../lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Finds a task using an object with optional query properties. - _requestNode:_ [`TaskQueryCloudRequestModel`](../../../lib/process-services-cloud/src/lib/task/task-list/models/filter-cloud-model.ts) - Query object diff --git a/docs/process-services/components/form.component.md b/docs/process-services/components/form.component.md index 351371144c..281684db21 100644 --- a/docs/process-services/components/form.component.md +++ b/docs/process-services/components/form.component.md @@ -7,7 +7,7 @@ Last reviewed: 2019-01-16 # [Form component](../../../lib/process-services/form/form.component.ts "Defined in form.component.ts") -Shows a [`Form`](../../../lib/core/form/components/widgets/core/form.model.ts) from APS +Shows a [`Form`](../../../lib/process-services/task-list/models/form.model.ts) from APS (See it live: [Form Quickstart](https://embed.plnkr.co/YSLXTqb3DtMhVJSqXKkE/)) @@ -67,7 +67,6 @@ Any content in the body of `<adf-form>` will be shown when no form definition is | readOnly | `boolean` | false | Toggle readonly state of the form. Forces all form widgets to render as readonly if enabled. | | saveMetadata | `boolean` | false | Toggle saving of form metadata. | | showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. | -| showDebugButton | `boolean` | false | Toggle debug options. | | showRefreshButton | `boolean` | true | Toggle rendering of the `Refresh` button. | | showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. | | showTitle | `boolean` | true | Toggle rendering of the form title. | diff --git a/docs/process-services/components/process-filters.component.md b/docs/process-services/components/process-filters.component.md index 09f63642ee..6f35ad45b1 100644 --- a/docs/process-services/components/process-filters.component.md +++ b/docs/process-services/components/process-filters.component.md @@ -17,7 +17,7 @@ Collection of criteria used to filter process instances, which may be customized - [Events](#events) - [Details](#details) - [How filter the activiti process filters](#how-filter-the-activiti-process-filters) - - [`FilterParamsModel`](../../../lib/process-services/task-list/models/filter.model.ts) + - [FilterParamsModel](#filterparamsmodel) - [See also](#see-also) ## Basic Usage diff --git a/docs/process-services/components/start-process.component.md b/docs/process-services/components/start-process.component.md index fb1e5cee29..7b3eed1271 100644 --- a/docs/process-services/components/start-process.component.md +++ b/docs/process-services/components/start-process.component.md @@ -44,7 +44,7 @@ Starts a process. | processFilterSelector | `boolean` | true | (optional) Parameter to enable selection of process when filtering. | | showSelectProcessDropdown | `boolean` | true | Hide or show the process selection dropdown. | | values | [`FormValues`](../../../lib/core/form/components/widgets/core/form-values.ts) | | Parameter to pass form field values in the start form if one is associated. | -| variables | [`ProcessInstanceVariable`](../../../lib/process-services/process-list/models/process-instance-variable.model.ts)`[]` | | Variables in the input to the process [RestVariable](https://github.com/Alfresco/alfresco-js-api/tree/master/src/alfresco-activiti-rest-api/docs/RestVariable.md). | +| variables | [`ProcessInstanceVariable`](../../../lib/process-services/process-list/models/process-instance-variable.model.ts)`[]` | | Variables in the input to the process [`RestVariable`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/RestVariable.md). | ### Events diff --git a/docs/process-services/services/process-filter.service.md b/docs/process-services/services/process-filter.service.md index a77588b9e7..6cb6c30fa5 100644 --- a/docs/process-services/services/process-filter.service.md +++ b/docs/process-services/services/process-filter.service.md @@ -17,10 +17,10 @@ Manage Process Filters, which are pre-configured Process Instance queries. Adds a filter. - _filter:_ [`FilterProcessRepresentationModel`](../../../lib/process-services/process-list/models/filter-process.model.ts) - The filter to add - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`FilterProcessRepresentationModel`](../../../lib/process-services/process-list/models/filter-process.model.ts)`>` - The filter just added -- **callApiProcessFilters**(appId?: `number`): `any`<br/> +- **callApiProcessFilters**(appId?: `number`): [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`ResultListDataRepresentationUserProcessInstanceFilterRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/ResultListDataRepresentation%C2%ABUserProcessInstanceFilterRepresentation%C2%BB.md)`>`<br/> Calls `getUserProcessInstanceFilters` from the Alfresco JS API. - _appId:_ `number` - (Optional) ID of the target app - - **Returns** `any` - List of filter details + - **Returns** [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)`<`[`ResultListDataRepresentationUserProcessInstanceFilterRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/ResultListDataRepresentation%C2%ABUserProcessInstanceFilterRepresentation%C2%BB.md)`>` - List of filter details - **createDefaultFilters**(appId: `number`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`FilterProcessRepresentationModel`](../../../lib/process-services/process-list/models/filter-process.model.ts)`[]>`<br/> Creates and returns the default filters for an app. - _appId:_ `number` - ID of the target app diff --git a/docs/process-services/services/process.service.md b/docs/process-services/services/process.service.md index 644c1e6c5c..d95a63c6d1 100644 --- a/docs/process-services/services/process.service.md +++ b/docs/process-services/services/process.service.md @@ -17,10 +17,10 @@ Manages process instances, process variables, and process audit Log. Cancels a process instance. - _processInstanceId:_ `string` - ID of process to cancel - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<void>` - Null response notifying when the operation is complete -- **createOrUpdateProcessInstanceVariables**(processInstanceId: `string`, variables: `RestVariable[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceVariable`](../../../lib/process-services/process-list/models/process-instance-variable.model.ts)`[]>`<br/> +- **createOrUpdateProcessInstanceVariables**(processInstanceId: `string`, variables: [`RestVariable`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/RestVariable.md)`[]`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceVariable`](../../../lib/process-services/process-list/models/process-instance-variable.model.ts)`[]>`<br/> Creates or updates variables for a process instance. - _processInstanceId:_ `string` - ID of the target process - - _variables:_ `RestVariable[]` - Variables to update + - _variables:_ [`RestVariable`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/RestVariable.md)`[]` - Variables to update - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceVariable`](../../../lib/process-services/process-list/models/process-instance-variable.model.ts)`[]>` - Array of instance variable info - **deleteProcessInstanceVariable**(processInstanceId: `string`, variableName: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<void>`<br/> Deletes a variable for a process instance. @@ -39,10 +39,10 @@ Manages process instances, process variables, and process audit Log. Gets Process Instance metadata. - _processInstanceId:_ `string` - ID of the target process - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstance`](../../../lib/process-services/process-list/models/process-instance.model.ts)`>` - Metadata for the instance -- **getProcessDefinitions**(appId?: `number`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessDefinitionRepresentation`](../../../lib/process-services/process-list/models/process-definition.model.ts)`[]>`<br/> +- **getProcessDefinitions**(appId?: `number`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessDefinitionRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/ProcessDefinitionRepresentation.md)`[]>`<br/> Gets process definitions associated with an app. - _appId:_ `number` - (Optional) ID of a target app - - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessDefinitionRepresentation`](../../../lib/process-services/process-list/models/process-definition.model.ts)`[]>` - Array of process definitions + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessDefinitionRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/ProcessDefinitionRepresentation.md)`[]>` - Array of process definitions - **getProcessInstanceVariables**(processInstanceId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`ProcessInstanceVariable`](../../../lib/process-services/process-list/models/process-instance-variable.model.ts)`[]>`<br/> Gets the variables for a process instance. - _processInstanceId:_ `string` - ID of the target process diff --git a/docs/process-services/services/tasklist.service.md b/docs/process-services/services/tasklist.service.md index da5d24525c..fe3b84a713 100644 --- a/docs/process-services/services/tasklist.service.md +++ b/docs/process-services/services/tasklist.service.md @@ -36,10 +36,10 @@ Manages Task Instances. Claims a task for the current user. - _taskId:_ `string` - ID of the task to claim - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsModel`](../../../lib/process-services/task-list/models/task-details.model.ts)`>` - Details of the claimed task -- **completeTask**(taskId: `string`): `any`<br/> +- **completeTask**(taskId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Gives completed status to a task. - _taskId:_ `string` - ID of the target task - - **Returns** `any` - Null response notifying when the operation is complete + - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Null response notifying when the operation is complete - **createNewTask**(task: [`TaskDetailsModel`](../../../lib/process-services/task-list/models/task-details.model.ts)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsModel`](../../../lib/process-services/task-list/models/task-details.model.ts)`>`<br/> Creates a new standalone task. - _task:_ [`TaskDetailsModel`](../../../lib/process-services/task-list/models/task-details.model.ts) - Details of the new task @@ -110,7 +110,7 @@ Manages Task Instances. - **updateTask**(taskId: `any`, updated: `any`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsModel`](../../../lib/process-services/task-list/models/task-details.model.ts)`>`<br/> Updates the details (name, description, due date) for a task. - _taskId:_ `any` - ID of the task to update - - _updated:_ `any` - Data to update the task (as a `TaskUpdateRepresentation` instance). + - _updated:_ `any` - Data to update the task (as a [`TaskUpdateRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/TaskUpdateRepresentation.md) instance). - **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TaskDetailsModel`](../../../lib/process-services/task-list/models/task-details.model.ts)`>` - Updated task details ## Details diff --git a/docs/release-notes/RelNote161.md b/docs/release-notes/RelNote161.md index 6e43800c37..495e8d9944 100644 --- a/docs/release-notes/RelNote161.md +++ b/docs/release-notes/RelNote161.md @@ -422,8 +422,8 @@ Below you can find a detailed list of tickets addressed in the new release. For - \[[ADF-810](https://issues.alfresco.com/jira/browse/ADF-810)] - Radio button list is selecting the first value behind the scenes when nothing is selected - 1963 Github - \[[ADF-833](https://issues.alfresco.com/jira/browse/ADF-833)] - Data table - single and double click - \[[ADF-842](https://issues.alfresco.com/jira/browse/ADF-842)] - Error is received in console log when a form is completed -- \[[ADF-883](https://issues.alfresco.com/jira/browse/ADF-883)] - [`UserInfo`](../../lib/content-services/document-list/models/document-library.model.ts) - Build errors -- \[[ADF-884](https://issues.alfresco.com/jira/browse/ADF-884)] - [`FormComponent`](../core/components/form.component.md) - Compilation error +- \[[ADF-883](https://issues.alfresco.com/jira/browse/ADF-883)] - [`UserInfo`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/UserInfo.md) - Build errors +- \[[ADF-884](https://issues.alfresco.com/jira/browse/ADF-884)] - [`FormComponent`](../process-services/components/form.component.md) - Compilation error - \[[ADF-893](https://issues.alfresco.com/jira/browse/ADF-893)] - Create Attachment Task/Process - Compilation error - \[[ADF-897](https://issues.alfresco.com/jira/browse/ADF-897)] - ActivitiPeopleList - use the prexif adf - \[[ADF-906](https://issues.alfresco.com/jira/browse/ADF-906)] - data property on activiti-form component do not react on changes - 2007 Github diff --git a/docs/release-notes/RelNote170.md b/docs/release-notes/RelNote170.md index 272311d50a..337110e61a 100644 --- a/docs/release-notes/RelNote170.md +++ b/docs/release-notes/RelNote170.md @@ -246,8 +246,8 @@ Two new methods has been added into the alfresco-js-api to support retrieve the | API | Name | HTTP method | URL | Description | | --- | ---- | ----------- | --- | ----------- | -| _ActivitiPublicRestApi.TaskApi_ | [**getTaskAuditJson**](https://github.com/Alfresco/alfresco-js-api/blob/a82ce3bbe56cb0944f8771d14193704b571adf96/src/alfresco-activiti-rest-api/docs/TaskApi.md#getTaskAuditJson) | **GET** | /api/enterprise/tasks/{taskId}/audit | Retrieve audit infromation in json format | -| _ActivitiPublicRestApi.TaskApi_ | [**getTaskAuditPdf**](https://github.com/Alfresco/alfresco-js-api/blob/a82ce3bbe56cb0944f8771d14193704b571adf96/src/alfresco-activiti-rest-api/docs/TaskApi.md#getTaskAuditPdf) | **GET** | /app/rest/tasks/{taskId}/audit | Retrieve the task audit infromation in pdf format | +| _ActivitiPublicRestApi.[TaskApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api-legacy/activiti-rest-api/docs/TaskApi.md)_ | [**getTaskAuditJson**](https://github.com/Alfresco/alfresco-js-api/blob/a82ce3bbe56cb0944f8771d14193704b571adf96/src/alfresco-activiti-rest-api/docs/TaskApi.md#getTaskAuditJson) | **GET** | /api/enterprise/tasks/{taskId}/audit | Retrieve audit infromation in json format | +| _ActivitiPublicRestApi.[TaskApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api-legacy/activiti-rest-api/docs/TaskApi.md)_ | [**getTaskAuditPdf**](https://github.com/Alfresco/alfresco-js-api/blob/a82ce3bbe56cb0944f8771d14193704b571adf96/src/alfresco-activiti-rest-api/docs/TaskApi.md#getTaskAuditPdf) | **GET** | /app/rest/tasks/{taskId}/audit | Retrieve the task audit infromation in pdf format | For further details about those endepoints please refer to the [official documentation](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-activiti-rest-api/docs/TaskApi.md) @@ -343,7 +343,7 @@ Release Notes - Apps Development Framework - Version 1.7. - \[[ADF-819](https://issues.alfresco.com/jira/browse/ADF-819)] - Snackbar does not appear when uploading files via DnD - \[[ADF-923](https://issues.alfresco.com/jira/browse/ADF-923)] - Involved user should not be able to see 'Complete' button as active in a task. - \[[ADF-939](https://issues.alfresco.com/jira/browse/ADF-939)] - [Login] Sign in button does not stay at the bottom -- \[[ADF-943](https://issues.alfresco.com/jira/browse/ADF-943)] - APS ContentApi is not present on index.d.ts and SitesApi is not complete +- \[[ADF-943](https://issues.alfresco.com/jira/browse/ADF-943)] - APS [ContentApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/api/content.api.ts) is not present on index.d.ts and [SitesApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/api/sites.api.ts) is not complete - \[[ADF-945](https://issues.alfresco.com/jira/browse/ADF-945)] - 'Undefined' is displayed in 'attach file' widget after restore. - \[[ADF-950](https://issues.alfresco.com/jira/browse/ADF-950)] - when the [`Form`](../../lib/process-services/task-list/models/form.model.ts) in readonly mode you can edit the date - \[[ADF-957](https://issues.alfresco.com/jira/browse/ADF-957)] - Duplicate Rest calls are made for fields where Rest end points are given diff --git a/docs/release-notes/RelNote190.md b/docs/release-notes/RelNote190.md index 6889541ad8..7daf7ca80b 100644 --- a/docs/release-notes/RelNote190.md +++ b/docs/release-notes/RelNote190.md @@ -350,7 +350,7 @@ Release Notes - Apps Development Framework - Version 1.9. - \[[ADF-1249](https://issues.alfresco.com/jira/browse/ADF-1249)] - Remove mdl from ng2-activiti-diagrams - \[[ADF-1250](https://issues.alfresco.com/jira/browse/ADF-1250)] - Remove mdl from ng2-activiti-analytics - \[[ADF-1251](https://issues.alfresco.com/jira/browse/ADF-1251)] - Remove mdl from demo shell -- \[[ADF-1492](https://issues.alfresco.com/jira/browse/ADF-1492)] - Document List - Export [`ContentNodeSelectorComponent`](../content-services/components/content-node-selector.component.md) and [ContentNodeSelectorComponentData](../../lib/content-services/content-node-selector/content-node-selector.component-data.interface.ts) +- \[[ADF-1492](https://issues.alfresco.com/jira/browse/ADF-1492)] - Document List - Export [`ContentNodeSelectorComponent`](../content-services/components/content-node-selector.component.md) and [`ContentNodeSelectorComponentData`](../../lib/content-services/content-node-selector/content-node-selector.component-data.interface.ts) - \[[ADF-1496](https://issues.alfresco.com/jira/browse/ADF-1496)] - Remove "Disable upload button when user has no permissions" switch. - \[[ADF-1504](https://issues.alfresco.com/jira/browse/ADF-1504)] - Rename UserInfoComponentModule to [`UserInfoModule`](../../lib/core/userinfo/userinfo.module.ts) - \[[ADF-1515](https://issues.alfresco.com/jira/browse/ADF-1515)] - Internationalization - ADF strings review diff --git a/docs/release-notes/RelNote200.md b/docs/release-notes/RelNote200.md index 26ba665fe2..a82a38475d 100644 --- a/docs/release-notes/RelNote200.md +++ b/docs/release-notes/RelNote200.md @@ -232,7 +232,7 @@ For more details please refer to [Upload button documentation](../content-servic ### 8. Register Alfresco file type icons within the mat-icon -All the ADF MIME type icons are now registered into the [MatIconRegistry](https://material.angular.io/components/icon/api). This improvement allows you to use all the icons through the mat-icon tag: +All the ADF MIME type icons are now registered into the [`MatIconRegistry`](https://material.angular.io/components/icon/api). This improvement allows you to use all the icons through the mat-icon tag: ![](images/Untitled.gif) @@ -256,7 +256,7 @@ The [log service](../core/services/log.service.md) provides 6 level of logs: TRA ### 10. Favorite node directive -The [NodeFavoriteDirective](../core/directives/node-favorite.directive.md) instance can be bound to a button to retrieve and manage a favorites node list: +The [`NodeFavoriteDirective`](../core/directives/node-favorite.directive.md) instance can be bound to a button to retrieve and manage a favorites node list: <button mat-icon-button #favorite="adfFavorite" @@ -485,7 +485,7 @@ The **extension-viewer** tag (used to extend the viewer behavior to open extensi | Properties | Description | | ---------- | ----------- | -| showNotificationBar | Deprecated in 1.6.0 you can use [`UploadService`](../core/services/upload.service.md) events and [NotificationService](../core/services/notification.service.md) api instead. | +| showNotificationBar | Deprecated in 1.6.0 you can use [`UploadService`](../core/services/upload.service.md) events and [`NotificationService`](../core/services/notification.service.md) api instead. | | currentFolderPath | Deprecated in 1.6.0, this property is not used for couple of releases already. Use rootFolderId instead. | | disableWithNoPermission | Deprecated in 1.8.0, use the button with combination of adf-node-permission directive | @@ -584,7 +584,7 @@ Release Notes - Apps Development Framework - Version 2.0. - \[[ADF-1633](https://issues.alfresco.com/jira/browse/ADF-1633)] - [Login] redirect to original path upon successful login - \[[ADF-1694](https://issues.alfresco.com/jira/browse/ADF-1694)] - Date-picker i18n support - \[[ADF-1723](https://issues.alfresco.com/jira/browse/ADF-1723)] - [Service][logservice](../core/log.service.md) configuration -- \[[ADF-1729](https://issues.alfresco.com/jira/browse/ADF-1729)] - [Directive] Mark [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) as Favorite Directive +- \[[ADF-1729](https://issues.alfresco.com/jira/browse/ADF-1729)] - [Directive] Mark [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) as Favorite Directive - \[[ADF-1745](https://issues.alfresco.com/jira/browse/ADF-1745)] - [Directive] Delete multiple nodes directive - \[[ADF-1749](https://issues.alfresco.com/jira/browse/ADF-1749)] - [Task List][process list] - Customizable template using the app.config.json - \[[ADF-1750](https://issues.alfresco.com/jira/browse/ADF-1750)] - [Viewer] Content projection for "Open With" and "More actions" @@ -596,7 +596,7 @@ Release Notes - Apps Development Framework - Version 2.0. - \[[ADF-1840](https://issues.alfresco.com/jira/browse/ADF-1840)] - [Document List] Create a generic permission denied page - \[[ADF-1841](https://issues.alfresco.com/jira/browse/ADF-1841)] - [Metadata] Default metadata Nodes property editing - \[[ADF-1906](https://issues.alfresco.com/jira/browse/ADF-1906)] - [Accordion Menu] Tooltip configuration -- \[[ADF-1918](https://issues.alfresco.com/jira/browse/ADF-1918)] - [Search] Use the new Search api service for the [search component](../content-services/components/search.component.md) +- \[[ADF-1918](https://issues.alfresco.com/jira/browse/ADF-1918)] - [Search] Use the new Search [api service](../../lib/testing/src/lib/core/actions/api.service.ts) for the [search component](../content-services/components/search.component.md) ### Documentation @@ -701,7 +701,7 @@ Release Notes - Apps Development Framework - Version 2.0. - \[[ADF-1710](https://issues.alfresco.com/jira/browse/ADF-1710)] - An error is logged into the console when using data widget - \[[ADF-1711](https://issues.alfresco.com/jira/browse/ADF-1711)] - The adf-task-attachment-list component displays drag-and-drop area that is not working - \[[ADF-1712](https://issues.alfresco.com/jira/browse/ADF-1712)] - The adf-task-header component displays a Requeue button for none pooled tasks -- \[[ADF-1716](https://issues.alfresco.com/jira/browse/ADF-1716)] - Process List - processDefinitionKey is not part of the ProcessInstanceQueryRepresentation +- \[[ADF-1716](https://issues.alfresco.com/jira/browse/ADF-1716)] - Process List - processDefinitionKey is not part of the [ProcessInstanceQueryRepresentation](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/activiti-rest-api/docs/ProcessInstanceQueryRepresentation.md) - \[[ADF-1718](https://issues.alfresco.com/jira/browse/ADF-1718)] - [`Pagination`](../../lib/content-services/document-list/models/document-library.model.ts) should not be displayed on Search Results page when there are no results - \[[ADF-1720](https://issues.alfresco.com/jira/browse/ADF-1720)] - Date-time picker is not working properly with other Date Display Format than default - \[[ADF-1722](https://issues.alfresco.com/jira/browse/ADF-1722)] - [object Object] appears in People control when selecting the same name @@ -738,7 +738,7 @@ Release Notes - Apps Development Framework - Version 2.0. - \[[ADF-1824](https://issues.alfresco.com/jira/browse/ADF-1824)] - Moment js security issue - \[[ADF-1825](https://issues.alfresco.com/jira/browse/ADF-1825)] - [`Form`](../../lib/process-services/task-list/models/form.model.ts) field in start task no aligned - \[[ADF-1827](https://issues.alfresco.com/jira/browse/ADF-1827)] - 'Object Object' displayed on search results page -- \[[ADF-1829](https://issues.alfresco.com/jira/browse/ADF-1829)] - PeopleApi - getSiteMembership wrong returned type +- \[[ADF-1829](https://issues.alfresco.com/jira/browse/ADF-1829)] - [PeopleApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/api/people.api.ts) - getSiteMembership wrong returned type - \[[ADF-1830](https://issues.alfresco.com/jira/browse/ADF-1830)] - Cannot access processes or reports - \[[ADF-1832](https://issues.alfresco.com/jira/browse/ADF-1832)] - [Document List] IE 11 erro on click - \[[ADF-1835](https://issues.alfresco.com/jira/browse/ADF-1835)] - The pagination on search results page is not working properly @@ -746,7 +746,7 @@ Release Notes - Apps Development Framework - Version 2.0. - \[[ADF-1839](https://issues.alfresco.com/jira/browse/ADF-1839)] - Login does not switch user preferences - \[[ADF-1856](https://issues.alfresco.com/jira/browse/ADF-1856)] - Document List - location fails for a user that has granular permissions - \[[ADF-1859](https://issues.alfresco.com/jira/browse/ADF-1859)] - The [document list component](../content-services/components/document-list.component.md) no longer exports [`ShareDataRow`](../../lib/content-services/document-list/data/share-data-row.model.ts) -- \[[ADF-1860](https://issues.alfresco.com/jira/browse/ADF-1860)] - NodesApi.getNodeChildren has wrong return type +- \[[ADF-1860](https://issues.alfresco.com/jira/browse/ADF-1860)] - [NodesApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/api/nodes.api.ts).getNodeChildren has wrong return type - \[[ADF-1861](https://issues.alfresco.com/jira/browse/ADF-1861)] - Line breaks not displayed in "Display Text" widget in forms - \[[ADF-1862](https://issues.alfresco.com/jira/browse/ADF-1862)] - Adf toolbar should get the background color from the theme - \[[ADF-1865](https://issues.alfresco.com/jira/browse/ADF-1865)] - [Document List] "Empty View" does not wrap long text @@ -782,7 +782,7 @@ Release Notes - Apps Development Framework - Version 2.0. - \[[ADF-1951](https://issues.alfresco.com/jira/browse/ADF-1951)] - Date widget doesn't display the correct date. - \[[ADF-1956](https://issues.alfresco.com/jira/browse/ADF-1956)] - Date widget with advanced properties does not display value. - \[[ADF-1962](https://issues.alfresco.com/jira/browse/ADF-1962)] - getContentThumbnailUrl returns file data instead or URL -- \[[ADF-1963](https://issues.alfresco.com/jira/browse/ADF-1963)] - ContentApi is missing the preview rendition API +- \[[ADF-1963](https://issues.alfresco.com/jira/browse/ADF-1963)] - [ContentApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/api/content.api.ts) is missing the preview rendition API - \[[ADF-1964](https://issues.alfresco.com/jira/browse/ADF-1964)] - [Demo Shell] Max size filter is not switched off. - \[[ADF-1965](https://issues.alfresco.com/jira/browse/ADF-1965)] - 'Upload file' button is enabled if user does not have permission to upload a file/folder - \[[ADF-1966](https://issues.alfresco.com/jira/browse/ADF-1966)] - Wrong sort on Document List diff --git a/docs/release-notes/RelNote210.md b/docs/release-notes/RelNote210.md index 2b1d82fba8..8637ec4336 100644 --- a/docs/release-notes/RelNote210.md +++ b/docs/release-notes/RelNote210.md @@ -365,7 +365,7 @@ Release Notes - Apps Development Framework - Version 2.1. - \[[ADF-1752](https://issues.alfresco.com/jira/browse/ADF-1752)] - allowInfoDrawer property does not disable the feature when showInfoDrawer is set to true - \[[ADF-1882](https://issues.alfresco.com/jira/browse/ADF-1882)] - Preview uploaded content in APS fails in form -- \[[ADF-1888](https://issues.alfresco.com/jira/browse/ADF-1888)] - [ExternalContent](../../lib/core/form/components/widgets/core/external-content.ts) is not exported in ActivitiFormModule +- \[[ADF-1888](https://issues.alfresco.com/jira/browse/ADF-1888)] - [`ExternalContent`](../../lib/core/form/components/widgets/core/external-content.ts) is not exported in ActivitiFormModule - \[[ADF-1889](https://issues.alfresco.com/jira/browse/ADF-1889)] - Viewer does not render PDF renditions unless urlFile ends with .pdf - \[[ADF-1926](https://issues.alfresco.com/jira/browse/ADF-1926)] - [`Form`](../../lib/process-services/task-list/models/form.model.ts) is not exported from ActivitiTaskListModule - \[[ADF-1959](https://issues.alfresco.com/jira/browse/ADF-1959)] - Apps with description appear with larger size on the Processes Services page @@ -407,7 +407,7 @@ Release Notes - Apps Development Framework - Version 2.1. - \[[ADF-2209](https://issues.alfresco.com/jira/browse/ADF-2209)] - The 'Complete' button of a task that has a form is not properly field with colour when hover - \[[ADF-2210](https://issues.alfresco.com/jira/browse/ADF-2210)] - Dynamic Table title is not aligned properly - \[[ADF-2213](https://issues.alfresco.com/jira/browse/ADF-2213)] - Amount Widget is not aligned -- \[[ADF-2221](https://issues.alfresco.com/jira/browse/ADF-2221)] - Search fails on Content [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector +- \[[ADF-2221](https://issues.alfresco.com/jira/browse/ADF-2221)] - Search fails on Content [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector - \[[ADF-2222](https://issues.alfresco.com/jira/browse/ADF-2222)] - The user profile window is not visible when only Content Services is enabled ### New Feature diff --git a/docs/release-notes/RelNote220.md b/docs/release-notes/RelNote220.md index 6c4d56e8af..e90c03281d 100644 --- a/docs/release-notes/RelNote220.md +++ b/docs/release-notes/RelNote220.md @@ -384,7 +384,7 @@ Release Notes - Apps Development Framework - Version 2.2. - \[[ADF-2163](https://issues.alfresco.com/jira/browse/ADF-2163)] - content-action target folder and file option - \[[ADF-2298](https://issues.alfresco.com/jira/browse/ADF-2298)] - Process Header - Make it customizable from config file - \[[ADF-2300](https://issues.alfresco.com/jira/browse/ADF-2300)] - [Upload Widget] Actions menu is needed -- \[[ADF-2304](https://issues.alfresco.com/jira/browse/ADF-2304)] - Add option to Content [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector to transform the breadcrumb folder node +- \[[ADF-2304](https://issues.alfresco.com/jira/browse/ADF-2304)] - Add option to Content [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector to transform the breadcrumb folder node - \[[ADF-2322](https://issues.alfresco.com/jira/browse/ADF-2322)] - [Document List] Gallery view - \[[ADF-2340](https://issues.alfresco.com/jira/browse/ADF-2340)] - [Delete directive] delete permanent form trashcan - \[[ADF-2352](https://issues.alfresco.com/jira/browse/ADF-2352)] - It should be possible to project toolbar buttons for the Viewer diff --git a/docs/release-notes/RelNote230.md b/docs/release-notes/RelNote230.md index 38aee3eecb..56fb9dfb24 100644 --- a/docs/release-notes/RelNote230.md +++ b/docs/release-notes/RelNote230.md @@ -63,7 +63,7 @@ Below are the most important new features of this release: - Inherit permission button - Share File - Lock File -- Comment a [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) +- Comment a [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) - Inherit Permission Button - [Permission List Component](../content-services/components/permission-list.component.md) - [Sidenav Layout Component](../core/components/sidenav-layout.component.md) @@ -316,7 +316,7 @@ Release Notes - Apps Development Framework - Version 2.3.0 - \[[ADF-2368](https://issues.alfresco.com/jira/browse/ADF-2368)] - Manage file version is updating wrong files. - \[[ADF-2373](https://issues.alfresco.com/jira/browse/ADF-2373)] - User should be able to see just the sites in which is member in SiteList drop-down - \[[ADF-2393](https://issues.alfresco.com/jira/browse/ADF-2393)] - Error when deleting a folder when Infinite scrolling is enabled and all items are loaded -- \[[ADF-2397](https://issues.alfresco.com/jira/browse/ADF-2397)] - Sometimes Load more on Content [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector does not load next page of results +- \[[ADF-2397](https://issues.alfresco.com/jira/browse/ADF-2397)] - Sometimes Load more on Content [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector does not load next page of results - \[[ADF-2414](https://issues.alfresco.com/jira/browse/ADF-2414)] - Translation missing for warning message on Login Page - \[[ADF-2421](https://issues.alfresco.com/jira/browse/ADF-2421)] - CLONE - Unable to copy / move a file from Recent or Favorites when user has only granular permissions on the file - \[[ADF-2428](https://issues.alfresco.com/jira/browse/ADF-2428)] - \[Demo shell Unable to view document metadata from document list view @@ -324,12 +324,12 @@ Release Notes - Apps Development Framework - Version 2.3.0 - \[[ADF-2442](https://issues.alfresco.com/jira/browse/ADF-2442)] - [Search Service](../../lib/core/services/search.service.ts) has wrong types for the 'search' API - \[[ADF-2443](https://issues.alfresco.com/jira/browse/ADF-2443)] - Typo in the UserPreferences service - \[[ADF-2444](https://issues.alfresco.com/jira/browse/ADF-2444)] - CLONE - Incorrect Items per page values on all lists after upgrade to ADF 2.2.0 -- \[[ADF-2448](https://issues.alfresco.com/jira/browse/ADF-2448)] - Wrong type definition for RequestPagination +- \[[ADF-2448](https://issues.alfresco.com/jira/browse/ADF-2448)] - Wrong type definition for [RequestPagination](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/search-rest-api/docs/RequestPagination.md) - \[[ADF-2450](https://issues.alfresco.com/jira/browse/ADF-2450)] - Search api type definition is not defined - \[[ADF-2454](https://issues.alfresco.com/jira/browse/ADF-2454)] - Login dialog icon and header text not centered correctly - \[[ADF-2455](https://issues.alfresco.com/jira/browse/ADF-2455)] - Document List does not render thumbnails - \[[ADF-2461](https://issues.alfresco.com/jira/browse/ADF-2461)] - Pdf viewer worker are not unregistered -- \[[ADF-2465](https://issues.alfresco.com/jira/browse/ADF-2465)] - Sometimes, navigating using the breadcrumb opens another folder instead of the clicked one - after search performed on the Content [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector +- \[[ADF-2465](https://issues.alfresco.com/jira/browse/ADF-2465)] - Sometimes, navigating using the breadcrumb opens another folder instead of the clicked one - after search performed on the Content [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Selector - \[[ADF-2468](https://issues.alfresco.com/jira/browse/ADF-2468)] - Error message displayed in console when navigating to tag page - \[[ADF-2470](https://issues.alfresco.com/jira/browse/ADF-2470)] - Search API implementation is incomplete - \[[ADF-2480](https://issues.alfresco.com/jira/browse/ADF-2480)] - Document List is not refreshed after deleting a file @@ -349,10 +349,10 @@ Release Notes - Apps Development Framework - Version 2.3.0 - \[[ADF-2604](https://issues.alfresco.com/jira/browse/ADF-2604)] - Incorrect definitions for Enums - \[[ADF-2607](https://issues.alfresco.com/jira/browse/ADF-2607)] - Task [`Form`](../../lib/process-services/task-list/models/form.model.ts) - Number Widget placeholder no longer displayed - \[[ADF-2624](https://issues.alfresco.com/jira/browse/ADF-2624)] - All metadata card component children display parent info drawer tooltip -- \[[ADF-2625](https://issues.alfresco.com/jira/browse/ADF-2625)] - [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) name not updated when changing its value in metadata component +- \[[ADF-2625](https://issues.alfresco.com/jira/browse/ADF-2625)] - [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) name not updated when changing its value in metadata component - \[[ADF-2628](https://issues.alfresco.com/jira/browse/ADF-2628)] - Metadata editors miss tooltips - \[[ADF-2630](https://issues.alfresco.com/jira/browse/ADF-2630)] - demo shell: tabs of the info drawer are not translated -- \[[ADF-2634](https://issues.alfresco.com/jira/browse/ADF-2634)] - [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Version List actions are not localised +- \[[ADF-2634](https://issues.alfresco.com/jira/browse/ADF-2634)] - [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Version List actions are not localised - \[[ADF-2636](https://issues.alfresco.com/jira/browse/ADF-2636)] - Console gives an error when trying to load ADF on safari - \[[ADF-2660](https://issues.alfresco.com/jira/browse/ADF-2660)] - ADF [Process Service](../process-services/services/process.service.md) lib is not importing the content dependency - \[[ADF-2662](https://issues.alfresco.com/jira/browse/ADF-2662)] - [Settings Component] Still able to sign in when changing APS or ACS URLS to invalid URL @@ -397,7 +397,7 @@ Release Notes - Apps Development Framework - Version 2.3.0 - \[[ADF-2394](https://issues.alfresco.com/jira/browse/ADF-2394)] - Process List Component - Should expose the mutiSelect property - \[[ADF-2405](https://issues.alfresco.com/jira/browse/ADF-2405)] - [Process Service](../process-services/services/process.service.md) - Add a new method to get all process definition versions - \[[ADF-2412](https://issues.alfresco.com/jira/browse/ADF-2412)] - Task List - refactoring -- \[[ADF-2417](https://issues.alfresco.com/jira/browse/ADF-2417)] - Remove the default [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) ID from tag page in demo-shell +- \[[ADF-2417](https://issues.alfresco.com/jira/browse/ADF-2417)] - Remove the default [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) ID from tag page in demo-shell - \[[ADF-2424](https://issues.alfresco.com/jira/browse/ADF-2424)] - Docker file size decreasing - \[[ADF-2462](https://issues.alfresco.com/jira/browse/ADF-2462)] - Automatic PR script after any beta release - \[[ADF-2471](https://issues.alfresco.com/jira/browse/ADF-2471)] - Create smoke tests to cover Colour change component diff --git a/docs/release-notes/RelNote240.md b/docs/release-notes/RelNote240.md index 51692f51d9..e8f053acbe 100644 --- a/docs/release-notes/RelNote240.md +++ b/docs/release-notes/RelNote240.md @@ -314,7 +314,7 @@ Release Notes - Apps Development Framework - Version 2.4.0 - \[[ADF-2726](https://issues.alfresco.com/jira/browse/ADF-2726)] - Not able to view a file from the attach file widget. - \[[ADF-2739](https://issues.alfresco.com/jira/browse/ADF-2739)] - Breadcrumb issue if the folder name is too big. - \[[ADF-2760](https://issues.alfresco.com/jira/browse/ADF-2760)] - Background colour for document lists is not white -- \[[ADF-2766](https://issues.alfresco.com/jira/browse/ADF-2766)] - Download [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Directive does not work with Shared Links +- \[[ADF-2766](https://issues.alfresco.com/jira/browse/ADF-2766)] - Download [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Directive does not work with Shared Links - \[[ADF-2767](https://issues.alfresco.com/jira/browse/ADF-2767)] - Side nav is not responsive - \[[ADF-2771](https://issues.alfresco.com/jira/browse/ADF-2771)] - [Sidebar action menu component](../core/components/sidebar-action-menu.component.md) - UX review - \[[ADF-2772](https://issues.alfresco.com/jira/browse/ADF-2772)] - Sidenav Layout - UX review diff --git a/docs/release-notes/RelNote250.md b/docs/release-notes/RelNote250.md index d575047822..d047cd68c4 100644 --- a/docs/release-notes/RelNote250.md +++ b/docs/release-notes/RelNote250.md @@ -139,7 +139,7 @@ For more information about this component please refer to the ### NotificationService customizability improvement -The [NotificationService](../core/services/notification.service.md) now exposes a new input parameter to allow a full customization of the notification message: +The [`NotificationService`](../core/services/notification.service.md) now exposes a new input parameter to allow a full customization of the notification message: - Direction : Text layout direction for the snack bar. - Duration : The length of time in milliseconds to wait before automatically dismissing the snack bar. @@ -338,7 +338,7 @@ Release Notes - Apps Development Framework - Version 2.5.0 ] - CLONE - Thumbs.db files are uploading with a folder upload - \[ [ADF-3289](https://issues.alfresco.com/jira/browse/ADF-3289) - ] - AppsDefinitionApi contains two methods with same name and different firms + ] - [AppsDefinitionApi](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api-legacy/activiti-rest-api/src/api/AppsDefinitionApi.ts) contains two methods with same name and different firms - \[ [ADF-3292](https://issues.alfresco.com/jira/browse/ADF-3292) ] - CLONE - Filter category should be deselected when user makes a new search query @@ -374,7 +374,7 @@ Release Notes - Apps Development Framework - Version 2.5.0 ] - Refresh button is not displayed on the form - \[ [ADF-3383](https://issues.alfresco.com/jira/browse/ADF-3383) - ] - Incorrect datatype for password in PersonBodyCreate in index.d.ts + ] - Incorrect datatype for password in [PersonBodyCreate](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/model/personBodyCreate.ts) in index.d.ts - \[ [ADF-3386](https://issues.alfresco.com/jira/browse/ADF-3386) ] - Task Filters accordion is not expanding / collapsing diff --git a/docs/release-notes/RelNote260.md b/docs/release-notes/RelNote260.md index 7b77c28adf..0d9f671497 100644 --- a/docs/release-notes/RelNote260.md +++ b/docs/release-notes/RelNote260.md @@ -99,7 +99,7 @@ The **DocumentList Component** can now show different icons for **Smart Folders* ### Tag node list component has a configurable delete button for tag -A configurable delete button has been added to the **Tag [Node](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) List Component** to let you show it only when user has permissions. +A configurable delete button has been added to the **Tag [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) List Component** to let you show it only when user has permissions. <adf-tag-node-list [showDelete]="showDelete" [nodeId]="nodeId"></adf-tag-node-list> @@ -107,7 +107,7 @@ A configurable delete button has been added to the **Tag [Node](https://github.c ### Validation summary support for form component -The **[Form](../../lib/process-services/task-list/models/form.model.ts) Component** will now use the **formError** event to send a validation summary for all the fields with errors. This will be useful particularly with big forms for showing which fields are in error without scrolling the whole form by creating a summary. +The **[`Form`](../../lib/process-services/task-list/models/form.model.ts) Component** will now use the **formError** event to send a validation summary for all the fields with errors. This will be useful particularly with big forms for showing which fields are in error without scrolling the whole form by creating a summary. <div class="form-container"> <adf-form @@ -176,10 +176,10 @@ Release Notes - Apps Development Framework - Version 2.6. ### Feature -- \[[ADF-584](https://issues.alfresco.com/jira/browse/ADF-584)] - Validation summary support for [Form](../../lib/process-services/task-list/models/form.model.ts) component +- \[[ADF-584](https://issues.alfresco.com/jira/browse/ADF-584)] - Validation summary support for [`Form`](../../lib/process-services/task-list/models/form.model.ts) component - \[[ADF-2640](https://issues.alfresco.com/jira/browse/ADF-2640)] - adf-tag-node-list with remove option configurable - \[[ADF-2921](https://issues.alfresco.com/jira/browse/ADF-2921)] - Icons for smart folders, links and folders with rules -- \[[ADF-3308](https://issues.alfresco.com/jira/browse/ADF-3308)] - [ProcessList](../../lib/process-services/mock/process/process.model.mock.ts) Component - Provide a way to filter the list by fields +- \[[ADF-3308](https://issues.alfresco.com/jira/browse/ADF-3308)] - [`ProcessList`](../../lib/process-services/mock/process/process.model.mock.ts) Component - Provide a way to filter the list by fields - \[[ADF-3352](https://issues.alfresco.com/jira/browse/ADF-3352)] - [Viewer Component](../core/components/viewer.component.md) - Allow multiple side bar - \[[ADF-3382](https://issues.alfresco.com/jira/browse/ADF-3382)] - Start a Process - Change the process definition from a dropdown to autocomplete - \[[ADF-3397](https://issues.alfresco.com/jira/browse/ADF-3397)] - Task Filter - Doesn't show the right icon @@ -189,10 +189,10 @@ Release Notes - Apps Development Framework - Version 2.6. - \[[ADF-3443](https://issues.alfresco.com/jira/browse/ADF-3443)] - Move print from ACA to ADF - \[[ADF-3499](https://issues.alfresco.com/jira/browse/ADF-3499)] - ACS APS Integration - Not able to upload a file in case the user has more than one alfresco repositories - \[[ADF-3507](https://issues.alfresco.com/jira/browse/ADF-3507)] - Show more/fewer tags buttons in [Tag List Component](../content-services/components/tag-list.component.md) -- \[[ADF-3512](https://issues.alfresco.com/jira/browse/ADF-3512)] - [SidenavLayoutComponent](../core/components/sidenav-layout.component.md) option to show the sidebar on the right +- \[[ADF-3512](https://issues.alfresco.com/jira/browse/ADF-3512)] - [`SidenavLayoutComponent`](../core/components/sidenav-layout.component.md) option to show the sidebar on the right - \[[ADF-3553](https://issues.alfresco.com/jira/browse/ADF-3553)] - Cache management for application configuration file - \[[ADF-3570](https://issues.alfresco.com/jira/browse/ADF-3570)] - Migration to APS2 - Add a interceptor to be able to use APS2 API -- \[[ADF-3607](https://issues.alfresco.com/jira/browse/ADF-3607)] - [Demo shell] JSON Editor in [Form](../../lib/process-services/task-list/models/form.model.ts) Page +- \[[ADF-3607](https://issues.alfresco.com/jira/browse/ADF-3607)] - [Demo shell] JSON Editor in [`Form`](../../lib/process-services/task-list/models/form.model.ts) Page ### Bug @@ -262,7 +262,7 @@ Release Notes - Apps Development Framework - Version 2.6. ### Feature Bug -- \[[ADF-3413](https://issues.alfresco.com/jira/browse/ADF-3413)] - [Form](../../lib/process-services/task-list/models/form.model.ts) name still displayed after removing form +- \[[ADF-3413](https://issues.alfresco.com/jira/browse/ADF-3413)] - [`Form`](../../lib/process-services/task-list/models/form.model.ts) name still displayed after removing form - \[[ADF-3567](https://issues.alfresco.com/jira/browse/ADF-3567)] - The default items per page value is not displayed - \[[ADF-3571](https://issues.alfresco.com/jira/browse/ADF-3571)] - Due After field not working as expected - \[[ADF-3573](https://issues.alfresco.com/jira/browse/ADF-3573)] - Showing NaN-20 of 20 is displayed instead of 20 @@ -294,6 +294,6 @@ Release Notes - Apps Development Framework - Version 2.6. - \[[ADF-3563](https://issues.alfresco.com/jira/browse/ADF-3563)] - Automated test for Show More/Less button in Search Filters - \[[ADF-3594](https://issues.alfresco.com/jira/browse/ADF-3594)] - Create automated test for Show more/ less button on Tag component. - \[[ADF-3596](https://issues.alfresco.com/jira/browse/ADF-3596)] - Automated tests for start a process -- \[[ADF-3597](https://issues.alfresco.com/jira/browse/ADF-3597)] - Create automated test to cover Error Log on [Form](../../lib/process-services/task-list/models/form.model.ts) component +- \[[ADF-3597](https://issues.alfresco.com/jira/browse/ADF-3597)] - Create automated test to cover Error Log on [`Form`](../../lib/process-services/task-list/models/form.model.ts) component Please refer to [the Alfresco issue tracker](https://issues.alfresco.com/jira/projects/ADF/issues/ADF-581?filter=allopenissues) for other known issues in this release. If you have any questions about the release, please contact us using [gitter](https://gitter.im/Alfresco/alfresco-ng2-components). diff --git a/docs/release-notes/RelNote310.md b/docs/release-notes/RelNote310.md index 3cee8b8638..301303437e 100644 --- a/docs/release-notes/RelNote310.md +++ b/docs/release-notes/RelNote310.md @@ -21,13 +21,18 @@ versions of ADF. - [Enhanced DocumentList](#enhanced-documentlist) - [Enhanced Metadata viewer](#enhanced-metadata-viewer) - [Search pattern highlight](#search-pattern-highlight) + - [Facet Intervals](#facet-intervals) + - [SSO Role AuthGuard](#sso-role-authguard) - [Improved accessibility](#improved-accessibility) - [Arabic and RTL languages support](#arabic-and-rtl-languages-support) + - [ADF Testing pacakge](#adf-testing-pacakge) - [Localisation](#localisation) - [References](#references) - [Issues addressed](#issues-addressed) - [Documentation](#documentation) - [Feature](#feature) + - [Epic](#epic) + - [Story](#story) - [Bug](#bug) - [Task](#task) - [Feature (Task)](#feature-task) @@ -70,16 +75,18 @@ Below are the most important new features of this release: In ADF 3.0.0 (released in February) we announced the introduction of the new `*Cloud` package. This contains a set of components to support [Activiti 7](https://www.activiti.org/), the next generation Cloud Native implementation of Activiti BPM Engine. With the ADF 3.1 release, the journey continues with more supported features, like: -#### Claim a task +#### Claim a task ```html <button adf-claim-task [appName]="appName" [taskId]="taskId" (success)="onTaskClaimed()">Complete</button> ``` For more details refer to the : -- [Claim task directive](../process-services-cloud/directives/claim-task.directive.md) + +- [Claim task directive](../process-services-cloud/directives/claim-task.directive.md) #### EditTaskComponent allows sorting and actions customization + You can supply various _filter properties_ to edit that will determine which tasks are found by a filter. @@ -88,9 +95,11 @@ displayed in the editor. However, you can also choose which sort properties to show using the `sortProperties` array. For more details refer to the : -- [Edit Task Filter Cloud component](../process-services-cloud/components/edit-task-filter-cloud.component.md) + +- [Edit Task Filter Cloud component](../process-services-cloud/components/edit-task-filter-cloud.component.md) #### EditProcessComponent allow sorting and actions customization + You can supply various _filter properties_ to edit that will determine which tasks are found by a filter. @@ -99,15 +108,18 @@ displayed in the editor. However, you can also choose which properties to show using the `filterProperties` array. For more details refer to the : -- [Edit Process Filter Cloud component](../process-services-cloud/components/edit-process-filter-cloud.component.md) - + +- [Edit Process Filter Cloud component](../process-services-cloud/components/edit-process-filter-cloud.component.md) + #### Complete task directive ```html <button adf-cloud-complete-task [appName]="appName" [taskId]="taskId" (success)="onTaskCompleted()">Complete</button> ``` + For more details refer to the : -- [Complete task directive](../process-services-cloud/directives/complete-task.directive.md) + +- [Complete task directive](../process-services-cloud/directives/complete-task.directive.md) ### Enhanced DocumentList @@ -132,8 +144,9 @@ First, set the `stickyHeader` property of your datatable to `true`: ``` For more details refer to the : -- [Document List Component](../content-services/components/document-list.component.md) -- [DataTable component](../core/components/datatable.component.md) + +- [Document List Component](../content-services/components/document-list.component.md) +- [DataTable component](../core/components/datatable.component.md) ### Enhanced Metadata viewer @@ -165,7 +178,8 @@ Futhermore, you can also exclude specific aspects by adding the `exclude` proper ``` For more details refer to the : -- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) + +- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) ### Search pattern highlight @@ -195,17 +209,15 @@ An example query for search highlighting could look like this: } } } - ``` - The example above changes the highlighting prefix and postfix from the default to '¿?' for all fields except the "description" field, which uses '()' instead. The highlight information will then be added in each node entry response. For more details refer to the : -- [Search Filter component highlight](../content-services/components/search-filter.component.md#highlight) +- [Search Filter component highlight](../content-services/components/search-filter.component.md#highlight) ### Facet Intervals @@ -263,8 +275,8 @@ by its `label`. The code snippet just above will result in the following display ![Facet Intervals](../docassets/images/search-facet-intervals.png) For more details refer to the : -- [Facet intervals section of the Search Filter Component docs](../content-services/components/search-filter.component.md#facet-intervals) +- [Facet intervals section of the Search Filter Component docs](../content-services/components/search-filter.component.md#facet-intervals) ### SSO Role AuthGuard @@ -287,7 +299,8 @@ const appRoutes: Routes = [ ``` For more details refer to the : -- [Facet intervals](../core/services/auth-guard-sso-role.service.md) + +- [Facet intervals](../core/services/auth-guard-sso-role.service.md) ### Improved accessibility @@ -326,345 +339,345 @@ Please refer to the [official documentation](http://docs.alfresco.com/) for furt ## Issues addressed Below is the list of JIRA issues that were closed for this release. - + ### Documentation -- [ADF-271](https://issues.alfresco.com/jira/browse/ADF-271) - ADD all valid fields that the tasklist can display - 1643 Github +- [ADF-271](https://issues.alfresco.com/jira/browse/ADF-271) - ADD all valid fields that the tasklist can display - 1643 Github -- [ADF-449](https://issues.alfresco.com/jira/browse/ADF-449) - Missing documentation for content-action in Data table +- [ADF-449](https://issues.alfresco.com/jira/browse/ADF-449) - Missing documentation for content-action in Data table -- [ADF-588](https://issues.alfresco.com/jira/browse/ADF-588) - tasks/processes - more documentation about the available fields +- [ADF-588](https://issues.alfresco.com/jira/browse/ADF-588) - tasks/processes - more documentation about the available fields -- [ADF-3040](https://issues.alfresco.com/jira/browse/ADF-3040) - Markdown templates sometimes add whitespace incorrectly +- [ADF-3040](https://issues.alfresco.com/jira/browse/ADF-3040) - Markdown templates sometimes add whitespace incorrectly -- [ADF-4008](https://issues.alfresco.com/jira/browse/ADF-4008) - Add the documentation for the default columns available in adf-process-list-cloud +- [ADF-4008](https://issues.alfresco.com/jira/browse/ADF-4008) - Add the documentation for the default columns available in adf-process-list-cloud -- [ADF-4146](https://issues.alfresco.com/jira/browse/ADF-4146) - How to migrate an application from ADF 2.6 to ADF 3.0 +- [ADF-4146](https://issues.alfresco.com/jira/browse/ADF-4146) - How to migrate an application from ADF 2.6 to ADF 3.0 -- [ADF-4152](https://issues.alfresco.com/jira/browse/ADF-4152) - Add subfolders to docs library folders to represent class types +- [ADF-4152](https://issues.alfresco.com/jira/browse/ADF-4152) - Add subfolders to docs library folders to represent class types -- [ADF-4160](https://issues.alfresco.com/jira/browse/ADF-4160) - Clarify the behaviour of the InfoDrawer configuration for default * +- [ADF-4160](https://issues.alfresco.com/jira/browse/ADF-4160) - Clarify the behaviour of the InfoDrawer configuration for default \* -- [ADF-4189](https://issues.alfresco.com/jira/browse/ADF-4189) - Improve `allowDropFiles` prop description for Document List docs +- [ADF-4189](https://issues.alfresco.com/jira/browse/ADF-4189) - Improve `allowDropFiles` prop description for Document List docs -- [ADF-4190](https://issues.alfresco.com/jira/browse/ADF-4190) - Fix source file paths generated by auto-linking tools +- [ADF-4190](https://issues.alfresco.com/jira/browse/ADF-4190) - Fix source file paths generated by auto-linking tools -- [ADF-4228](https://issues.alfresco.com/jira/browse/ADF-4228) - Tutorial on how to switch an ADF app to be able to support RTL languages +- [ADF-4228](https://issues.alfresco.com/jira/browse/ADF-4228) - Tutorial on how to switch an ADF app to be able to support RTL languages -- [ADF-4239](https://issues.alfresco.com/jira/browse/ADF-4239) - Update introduction text +- [ADF-4239](https://issues.alfresco.com/jira/browse/ADF-4239) - Update introduction text -- [ADF-4249](https://issues.alfresco.com/jira/browse/ADF-4249) - Doc review for 3.1 +- [ADF-4249](https://issues.alfresco.com/jira/browse/ADF-4249) - Doc review for 3.1 -- [ADF-4260](https://issues.alfresco.com/jira/browse/ADF-4260) - How to migrate an application from ADF 3.0 to ADF 3.1 +- [ADF-4260](https://issues.alfresco.com/jira/browse/ADF-4260) - How to migrate an application from ADF 3.0 to ADF 3.1 -- [ADF-4262](https://issues.alfresco.com/jira/browse/ADF-4262) - Release note for version 3.1.0 +- [ADF-4262](https://issues.alfresco.com/jira/browse/ADF-4262) - Release note for version 3.1.0 -- [ADF-4285](https://issues.alfresco.com/jira/browse/ADF-4285) - The documentation of content metadata component is misleading +- [ADF-4285](https://issues.alfresco.com/jira/browse/ADF-4285) - The documentation of [content metadata component](../../lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts) is misleading -- [ADF-4294](https://issues.alfresco.com/jira/browse/ADF-4294) - Creating the list of third party Open Source for ADF 3.1 (to be done as last task) +- [ADF-4294](https://issues.alfresco.com/jira/browse/ADF-4294) - Creating the list of third party Open Source for ADF 3.1 (to be done as last task) -- [ADF-4300](https://issues.alfresco.com/jira/browse/ADF-4300) - Add the sort properties for edit task cloud component +- [ADF-4300](https://issues.alfresco.com/jira/browse/ADF-4300) - Add the sort properties for edit task cloud component ### Feature -- [ADF-3497](https://issues.alfresco.com/jira/browse/ADF-3497) - Facet intervals on search filter +- [ADF-3497](https://issues.alfresco.com/jira/browse/ADF-3497) - Facet intervals on search filter -- [ADF-3677](https://issues.alfresco.com/jira/browse/ADF-3677) - SearchQueryBuilderService to support highlight +- [ADF-3677](https://issues.alfresco.com/jira/browse/ADF-3677) - [SearchQueryBuilderService](../content-services/services/search-query-builder.service.md) to support highlight -- [ADF-3735](https://issues.alfresco.com/jira/browse/ADF-3735) - SSO Login Error for login component +- [ADF-3735](https://issues.alfresco.com/jira/browse/ADF-3735) - SSO Login Error for [login component](../core/components/login.component.md) -- [ADF-3798](https://issues.alfresco.com/jira/browse/ADF-3798) - [Demo Shell] [APS2] Show Task list related to a Process +- [ADF-3798](https://issues.alfresco.com/jira/browse/ADF-3798) - [Demo Shell][aps2] Show Task list related to a Process -- [ADF-4003](https://issues.alfresco.com/jira/browse/ADF-4003) - Add roles filtering to PeopleCloudComponent +- [ADF-4003](https://issues.alfresco.com/jira/browse/ADF-4003) - Add roles filtering to [PeopleCloudComponent](../process-services-cloud/components/people-cloud.component.md) -- [ADF-4078](https://issues.alfresco.com/jira/browse/ADF-4078) - Fixed headers in the document list +- [ADF-4078](https://issues.alfresco.com/jira/browse/ADF-4078) - Fixed headers in the document list -- [ADF-4099](https://issues.alfresco.com/jira/browse/ADF-4099) - The metadata group is always showed even though the properties are not there +- [ADF-4099](https://issues.alfresco.com/jira/browse/ADF-4099) - The metadata group is always showed even though the properties are not there -- [ADF-4122](https://issues.alfresco.com/jira/browse/ADF-4122) - Sticky header on DataTable +- [ADF-4122](https://issues.alfresco.com/jira/browse/ADF-4122) - Sticky header on DataTable -- [ADF-4125](https://issues.alfresco.com/jira/browse/ADF-4125) - Simplify extension load in extension module +- [ADF-4125](https://issues.alfresco.com/jira/browse/ADF-4125) - Simplify extension load in extension module -- [ADF-4127](https://issues.alfresco.com/jira/browse/ADF-4127) - Claim a task on the new generation of BPM engines +- [ADF-4127](https://issues.alfresco.com/jira/browse/ADF-4127) - Claim a task on the new generation of BPM engines -- [ADF-4128](https://issues.alfresco.com/jira/browse/ADF-4128) - Task Cloud completion/back +- [ADF-4128](https://issues.alfresco.com/jira/browse/ADF-4128) - Task Cloud completion/back -- [ADF-4162](https://issues.alfresco.com/jira/browse/ADF-4162) - Adding the "includeAll" type of object to the presets configurations of the InforDrawer +- [ADF-4162](https://issues.alfresco.com/jira/browse/ADF-4162) - Adding the "includeAll" type of object to the presets configurations of the InforDrawer -- [ADF-4221](https://issues.alfresco.com/jira/browse/ADF-4221) - Avoiding to show a group of metadata, if any of the properties are empty +- [ADF-4221](https://issues.alfresco.com/jira/browse/ADF-4221) - Avoiding to show a group of metadata, if any of the properties are empty -- [ADF-4225](https://issues.alfresco.com/jira/browse/ADF-4225) - Viewer extension accept multiple file type +- [ADF-4225](https://issues.alfresco.com/jira/browse/ADF-4225) - Viewer extension accept multiple file type -- [ADF-4267](https://issues.alfresco.com/jira/browse/ADF-4267) - Sticky header on Document List +- [ADF-4267](https://issues.alfresco.com/jira/browse/ADF-4267) - Sticky header on Document List ### Epic -- [ADF-9](https://issues.alfresco.com/jira/browse/ADF-9) - Document list feature +- [ADF-9](https://issues.alfresco.com/jira/browse/ADF-9) - Document list feature -- [ADF-14](https://issues.alfresco.com/jira/browse/ADF-14) - Destination picker (copy/move) +- [ADF-14](https://issues.alfresco.com/jira/browse/ADF-14) - Destination picker (copy/move) -- [ADF-262](https://issues.alfresco.com/jira/browse/ADF-262) - File viewer +- [ADF-262](https://issues.alfresco.com/jira/browse/ADF-262) - File viewer -- [ADF-1452](https://issues.alfresco.com/jira/browse/ADF-1452) - Documentation +- [ADF-1452](https://issues.alfresco.com/jira/browse/ADF-1452) - Documentation -- [ADF-1463](https://issues.alfresco.com/jira/browse/ADF-1463) - Adding of automated tests +- [ADF-1463](https://issues.alfresco.com/jira/browse/ADF-1463) - Adding of automated tests -- [ADF-3296](https://issues.alfresco.com/jira/browse/ADF-3296) - APS 2.x & Activiti 7 compatibility +- [ADF-3296](https://issues.alfresco.com/jira/browse/ADF-3296) - APS 2.x & Activiti 7 compatibility -- [ADF-3349](https://issues.alfresco.com/jira/browse/ADF-3349) - Activiti 7+ support +- [ADF-3349](https://issues.alfresco.com/jira/browse/ADF-3349) - Activiti 7+ support -- [ADF-3741](https://issues.alfresco.com/jira/browse/ADF-3741) - Support for Activiti version 7 (and APS 2), maintaining the backward compatibility with APS 1.x. +- [ADF-3741](https://issues.alfresco.com/jira/browse/ADF-3741) - Support for Activiti version 7 (and APS 2), maintaining the backward compatibility with APS 1.x. -- [ADF-3742](https://issues.alfresco.com/jira/browse/ADF-3742) - Extensibility of ADF applications +- [ADF-3742](https://issues.alfresco.com/jira/browse/ADF-3742) - Extensibility of ADF applications -- [ADF-3857](https://issues.alfresco.com/jira/browse/ADF-3857) - Accessibility +- [ADF-3857](https://issues.alfresco.com/jira/browse/ADF-3857) - Accessibility -- [ADF-4246](https://issues.alfresco.com/jira/browse/ADF-4246) - Testing Microsoft Internet Explorer +- [ADF-4246](https://issues.alfresco.com/jira/browse/ADF-4246) - Testing Microsoft Internet Explorer ### Story -- [ADF-2129](https://issues.alfresco.com/jira/browse/ADF-2129) - Results highlighting (P2) +- [ADF-2129](https://issues.alfresco.com/jira/browse/ADF-2129) - Results highlighting (P2) + +- [ADF-3472](https://issues.alfresco.com/jira/browse/ADF-3472) - Whitelisting metadata by default with the ability to hide some of them by configuration + -- [ADF-3472](https://issues.alfresco.com/jira/browse/ADF-3472) - Whitelisting metadata by default with the ability to hide some of them by configuration - ### Bug -- [ADF-1713](https://issues.alfresco.com/jira/browse/ADF-1713) - Small adjustments for Task and Process for consistency - Demo Shell +- [ADF-1713](https://issues.alfresco.com/jira/browse/ADF-1713) - Small adjustments for Task and Process for consistency - Demo Shell -- [ADF-1954](https://issues.alfresco.com/jira/browse/ADF-1954) - [IE11] Breadcrumbs are not well aligned +- [ADF-1954](https://issues.alfresco.com/jira/browse/ADF-1954) - [IE11] Breadcrumbs are not well aligned -- [ADF-2971](https://issues.alfresco.com/jira/browse/ADF-2971) - Mandatory search config +- [ADF-2971](https://issues.alfresco.com/jira/browse/ADF-2971) - Mandatory search config -- [ADF-3401](https://issues.alfresco.com/jira/browse/ADF-3401) - The filter facets are not reseted when user makes a new search query +- [ADF-3401](https://issues.alfresco.com/jira/browse/ADF-3401) - The filter facets are not reseted when user makes a new search query -- [ADF-3444](https://issues.alfresco.com/jira/browse/ADF-3444) - Site list displays only a certain number of sites. +- [ADF-3444](https://issues.alfresco.com/jira/browse/ADF-3444) - Site list displays only a certain number of sites. -- [ADF-3604](https://issues.alfresco.com/jira/browse/ADF-3604) - 'Sign in' and copyrights is displayed on login dialog from 'Attach Folder' from Share. +- [ADF-3604](https://issues.alfresco.com/jira/browse/ADF-3604) - 'Sign in' and copyrights is displayed on login dialog from 'Attach Folder' from Share. -- [ADF-3678](https://issues.alfresco.com/jira/browse/ADF-3678) - Custom Process Filter - Different results in APS than in ADF +- [ADF-3678](https://issues.alfresco.com/jira/browse/ADF-3678) - Custom Process Filter - Different results in APS than in ADF -- [ADF-3843](https://issues.alfresco.com/jira/browse/ADF-3843) - Is not possible to change theInfinite pagination pageSize +- [ADF-3843](https://issues.alfresco.com/jira/browse/ADF-3843) - Is not possible to change theInfinite pagination pageSize -- [ADF-3861](https://issues.alfresco.com/jira/browse/ADF-3861) - [508 compliance] Multi-select, hamburger menu (row-based action menu) should be 508 compliant +- [ADF-3861](https://issues.alfresco.com/jira/browse/ADF-3861) - [508 compliance] Multi-select, hamburger menu (row-based action menu) should be 508 compliant -- [ADF-3862](https://issues.alfresco.com/jira/browse/ADF-3862) - [508 compliance] Documents and images should be readable +- [ADF-3862](https://issues.alfresco.com/jira/browse/ADF-3862) - [508 compliance] Documents and images should be readable -- [ADF-3863](https://issues.alfresco.com/jira/browse/ADF-3863) - [508 compliance] The user should be informed of what the label is that he/she is selecting +- [ADF-3863](https://issues.alfresco.com/jira/browse/ADF-3863) - [508 compliance] The user should be informed of what the label is that he/she is selecting -- [ADF-3878](https://issues.alfresco.com/jira/browse/ADF-3878) - Created date value of Column column should be in upper case +- [ADF-3878](https://issues.alfresco.com/jira/browse/ADF-3878) - Created date value of Column column should be in upper case -- [ADF-3934](https://issues.alfresco.com/jira/browse/ADF-3934) - People Cloud Component - Remove the concept of assignee +- [ADF-3934](https://issues.alfresco.com/jira/browse/ADF-3934) - [People Cloud Component](../process-services-cloud/components/people-cloud.component.md) - Remove the concept of assignee -- [ADF-3979](https://issues.alfresco.com/jira/browse/ADF-3979) - GroupCloudComponent should be able to detect "preSelectGroups" input changes +- [ADF-3979](https://issues.alfresco.com/jira/browse/ADF-3979) - [GroupCloudComponent](../process-services-cloud/components/group-cloud.component.md) should be able to detect "preSelectGroups" input changes -- [ADF-3989](https://issues.alfresco.com/jira/browse/ADF-3989) - The list of apps in 'appName' filter is duplicated after switching between saved filters +- [ADF-3989](https://issues.alfresco.com/jira/browse/ADF-3989) - The list of apps in 'appName' filter is duplicated after switching between saved filters -- [ADF-3995](https://issues.alfresco.com/jira/browse/ADF-3995) - 'ProcessInstanceId' value is not displayed into a saved filter +- [ADF-3995](https://issues.alfresco.com/jira/browse/ADF-3995) - 'ProcessInstanceId' value is not displayed into a saved filter -- [ADF-4023](https://issues.alfresco.com/jira/browse/ADF-4023) - [Demo-shell] Pagination layout is broken in Process List Cloud +- [ADF-4023](https://issues.alfresco.com/jira/browse/ADF-4023) - [Demo-shell] Pagination layout is broken in Process List Cloud -- [ADF-4058](https://issues.alfresco.com/jira/browse/ADF-4058) - Process Cloud - 502 Bad Gateway when try to create an task or an process +- [ADF-4058](https://issues.alfresco.com/jira/browse/ADF-4058) - Process Cloud - 502 Bad Gateway when try to create an task or an process -- [ADF-4065](https://issues.alfresco.com/jira/browse/ADF-4065) - The input field to add comments is visible when permission is denied. +- [ADF-4065](https://issues.alfresco.com/jira/browse/ADF-4065) - The input field to add comments is visible when permission is denied. -- [ADF-4068](https://issues.alfresco.com/jira/browse/ADF-4068) - Tasks - Able to add a description with spaces +- [ADF-4068](https://issues.alfresco.com/jira/browse/ADF-4068) - Tasks - Able to add a description with spaces -- [ADF-4076](https://issues.alfresco.com/jira/browse/ADF-4076) - Error when accessing Active Task after closing process diagram +- [ADF-4076](https://issues.alfresco.com/jira/browse/ADF-4076) - Error when accessing Active Task after closing process diagram -- [ADF-4097](https://issues.alfresco.com/jira/browse/ADF-4097) - [Demo shell] Add comment button not displayed in Comment section +- [ADF-4097](https://issues.alfresco.com/jira/browse/ADF-4097) - [Demo shell] Add comment button not displayed in Comment section -- [ADF-4143](https://issues.alfresco.com/jira/browse/ADF-4143) - LastModifiedFrom and LastModifiedTo fields of edit task filter cloud component validations are wrong +- [ADF-4143](https://issues.alfresco.com/jira/browse/ADF-4143) - LastModifiedFrom and LastModifiedTo fields of [edit task filter cloud component](../process-services-cloud/components/edit-task-filter-cloud.component.md) validations are wrong -- [ADF-4148](https://issues.alfresco.com/jira/browse/ADF-4148) - [kerberos] Text Viewer Component not passing the withCredentials parameter +- [ADF-4148](https://issues.alfresco.com/jira/browse/ADF-4148) - [kerberos] Text [Viewer Component](../core/components/viewer.component.md) not passing the withCredentials parameter -- [ADF-4153](https://issues.alfresco.com/jira/browse/ADF-4153) - Unable to open the Task Details page. +- [ADF-4153](https://issues.alfresco.com/jira/browse/ADF-4153) - Unable to open the Task Details page. -- [ADF-4154](https://issues.alfresco.com/jira/browse/ADF-4154) - Unit tests failing after upgrade to ADF 3.1.0-beta3 +- [ADF-4154](https://issues.alfresco.com/jira/browse/ADF-4154) - Unit tests failing after upgrade to ADF 3.1.0-beta3 -- [ADF-4156](https://issues.alfresco.com/jira/browse/ADF-4156) - Regression in TaskListComponent Caused by in-place Date Formatting +- [ADF-4156](https://issues.alfresco.com/jira/browse/ADF-4156) - Regression in [TaskListComponent](../process-services/components/task-list.component.md) Caused by in-place Date Formatting -- [ADF-4165](https://issues.alfresco.com/jira/browse/ADF-4165) - ADF 3.0 Not able to login with implicitFlow false +- [ADF-4165](https://issues.alfresco.com/jira/browse/ADF-4165) - ADF 3.0 Not able to login with implicitFlow false -- [ADF-4179](https://issues.alfresco.com/jira/browse/ADF-4179) - adf- prefix missing - style not applied to facet-buttons +- [ADF-4179](https://issues.alfresco.com/jira/browse/ADF-4179) - adf- prefix missing - style not applied to facet-buttons -- [ADF-4183](https://issues.alfresco.com/jira/browse/ADF-4183) - Login dialog does not redirect correctly after page reload +- [ADF-4183](https://issues.alfresco.com/jira/browse/ADF-4183) - Login dialog does not redirect correctly after page reload -- [ADF-4196](https://issues.alfresco.com/jira/browse/ADF-4196) - Datatable component not always selects the row after click +- [ADF-4196](https://issues.alfresco.com/jira/browse/ADF-4196) - Datatable component not always selects the row after click -- [ADF-4199](https://issues.alfresco.com/jira/browse/ADF-4199) - The 'Locally set' permission label is not displayed properly in the UI screen. +- [ADF-4199](https://issues.alfresco.com/jira/browse/ADF-4199) - The 'Locally set' permission label is not displayed properly in the UI screen. -- [ADF-4202](https://issues.alfresco.com/jira/browse/ADF-4202) - Not able to start a standalone task using start task cloud component +- [ADF-4202](https://issues.alfresco.com/jira/browse/ADF-4202) - Not able to start a standalone task using [start task cloud component](../process-services-cloud/components/start-task-cloud.component.md) -- [ADF-4205](https://issues.alfresco.com/jira/browse/ADF-4205) - Error in console when User tries to add user or group to permissions. +- [ADF-4205](https://issues.alfresco.com/jira/browse/ADF-4205) - Error in console when User tries to add user or group to permissions. -- [ADF-4215](https://issues.alfresco.com/jira/browse/ADF-4215) - Locale doesn't change when a user changes the browser locale +- [ADF-4215](https://issues.alfresco.com/jira/browse/ADF-4215) - Locale doesn't change when a user changes the browser locale -- [ADF-4220](https://issues.alfresco.com/jira/browse/ADF-4220) - [SSO] Not able to login with implicitFlow false after changing the config +- [ADF-4220](https://issues.alfresco.com/jira/browse/ADF-4220) - [SSO] Not able to login with implicitFlow false after changing the config -- [ADF-4229](https://issues.alfresco.com/jira/browse/ADF-4229) - Big space issue in case of RTL ADF application +- [ADF-4229](https://issues.alfresco.com/jira/browse/ADF-4229) - Big space issue in case of RTL ADF application -- [ADF-4230](https://issues.alfresco.com/jira/browse/ADF-4230) - Pagination arrows in the wrong order, in case or RTL ADF application +- [ADF-4230](https://issues.alfresco.com/jira/browse/ADF-4230) - Pagination arrows in the wrong order, in case or RTL ADF application -- [ADF-4281](https://issues.alfresco.com/jira/browse/ADF-4281) - Completed processes default filters is not doing the correct call +- [ADF-4281](https://issues.alfresco.com/jira/browse/ADF-4281) - Completed processes default filters is not doing the correct call -- [ADF-4282](https://issues.alfresco.com/jira/browse/ADF-4282) - The name of the content is not well aligned in documentList on small devices +- [ADF-4282](https://issues.alfresco.com/jira/browse/ADF-4282) - The name of the content is not well aligned in documentList on small devices -- [ADF-4287](https://issues.alfresco.com/jira/browse/ADF-4287) - The alignment in datatable is wrong +- [ADF-4287](https://issues.alfresco.com/jira/browse/ADF-4287) - The alignment in datatable is wrong -- [ADF-4301](https://issues.alfresco.com/jira/browse/ADF-4301) - [Accessibility] Not able to navigate through tasks in task list using tab +- [ADF-4301](https://issues.alfresco.com/jira/browse/ADF-4301) - [Accessibility] Not able to navigate through tasks in task list using tab -- [ADF-4305](https://issues.alfresco.com/jira/browse/ADF-4305) - DocumentList - CardViewMode - Field values missing in the display. +- [ADF-4305](https://issues.alfresco.com/jira/browse/ADF-4305) - DocumentList - CardViewMode - Field values missing in the display. -- [ADF-4313](https://issues.alfresco.com/jira/browse/ADF-4313) - [Demo shell] Form field looks like an editable field in task header after task was completed +- [ADF-4313](https://issues.alfresco.com/jira/browse/ADF-4313) - [Demo shell] [Form](../../lib/process-services/task-list/models/form.model.ts) field looks like an editable field in task header after task was completed -- [ADF-4316](https://issues.alfresco.com/jira/browse/ADF-4316) - People component table is not well aligned +- [ADF-4316](https://issues.alfresco.com/jira/browse/ADF-4316) - [People component](../process-services/components/people.component.md) table is not well aligned -- [ADF-4318](https://issues.alfresco.com/jira/browse/ADF-4318) - Process definition is not automatically selected if the app contains more than one +- [ADF-4318](https://issues.alfresco.com/jira/browse/ADF-4318) - Process definition is not automatically selected if the app contains more than one ### Task -- [ADF-3873](https://issues.alfresco.com/jira/browse/ADF-3873) - Create automated tests for edit process filters +- [ADF-3873](https://issues.alfresco.com/jira/browse/ADF-3873) - Create automated tests for edit process filters -- [ADF-3888](https://issues.alfresco.com/jira/browse/ADF-3888) - Implement automated tests for all the properties of task list and edit task filters components +- [ADF-3888](https://issues.alfresco.com/jira/browse/ADF-3888) - Implement automated tests for all the properties of task list and edit task filters components -- [ADF-3976](https://issues.alfresco.com/jira/browse/ADF-3976) - EditTaskComponent - Be able to customise the sorting and actions +- [ADF-3976](https://issues.alfresco.com/jira/browse/ADF-3976) - EditTaskComponent - Be able to customise the sorting and actions -- [ADF-3977](https://issues.alfresco.com/jira/browse/ADF-3977) - EditProcessComponent - Be able to change the sort and actions +- [ADF-3977](https://issues.alfresco.com/jira/browse/ADF-3977) - EditProcessComponent - Be able to change the sort and actions -- [ADF-3978](https://issues.alfresco.com/jira/browse/ADF-3978) - Travis on dev branch - should not run the jobs Create docker pr Deploy docker pr +- [ADF-3978](https://issues.alfresco.com/jira/browse/ADF-3978) - Travis on dev branch - should not run the jobs Create docker pr Deploy docker pr -- [ADF-3981](https://issues.alfresco.com/jira/browse/ADF-3981) - Automate Login Component manual test C291854 +- [ADF-3981](https://issues.alfresco.com/jira/browse/ADF-3981) - Automate [Login Component](../core/components/login.component.md) manual test C291854 -- [ADF-3986](https://issues.alfresco.com/jira/browse/ADF-3986) - [ProcessListCloudComponent] Be able to filter process with all possible params +- [ADF-3986](https://issues.alfresco.com/jira/browse/ADF-3986) - [ProcessListCloudComponent] Be able to filter process with all possible params -- [ADF-4004](https://issues.alfresco.com/jira/browse/ADF-4004) - Automate attach file test case +- [ADF-4004](https://issues.alfresco.com/jira/browse/ADF-4004) - Automate attach file test case -- [ADF-4012](https://issues.alfresco.com/jira/browse/ADF-4012) - Automate ADF-3872 - to be able to set default columns in adf-process-list-cloud +- [ADF-4012](https://issues.alfresco.com/jira/browse/ADF-4012) - Automate ADF-3872 - to be able to set default columns in adf-process-list-cloud -- [ADF-4015](https://issues.alfresco.com/jira/browse/ADF-4015) - automate ADF-3982 - Should be able to filter tasks with all possible params +- [ADF-4015](https://issues.alfresco.com/jira/browse/ADF-4015) - automate ADF-3982 - Should be able to filter tasks with all possible params -- [ADF-4045](https://issues.alfresco.com/jira/browse/ADF-4045) - Automate test infinite pagination delete +- [ADF-4045](https://issues.alfresco.com/jira/browse/ADF-4045) - Automate test infinite pagination delete -- [ADF-4048](https://issues.alfresco.com/jira/browse/ADF-4048) - PeopleCloud - Improve the preselectUsers +- [ADF-4048](https://issues.alfresco.com/jira/browse/ADF-4048) - PeopleCloud - Improve the preselectUsers -- [ADF-4061](https://issues.alfresco.com/jira/browse/ADF-4061) - Automate test for navigating to a non empty folder in >= 2nd page +- [ADF-4061](https://issues.alfresco.com/jira/browse/ADF-4061) - Automate test for navigating to a non empty folder in >= 2nd page -- [ADF-4064](https://issues.alfresco.com/jira/browse/ADF-4064) - Remove multiple elements locators +- [ADF-4064](https://issues.alfresco.com/jira/browse/ADF-4064) - Remove multiple elements locators -- [ADF-4067](https://issues.alfresco.com/jira/browse/ADF-4067) - [APS2] Application Name input should have the same name in all components +- [ADF-4067](https://issues.alfresco.com/jira/browse/ADF-4067) - [APS2] Application Name input should have the same name in all components -- [ADF-4083](https://issues.alfresco.com/jira/browse/ADF-4083) - Parse 'escaped' empty spaced labels inside facetFields or facetIntervals +- [ADF-4083](https://issues.alfresco.com/jira/browse/ADF-4083) - Parse 'escaped' empty spaced labels inside facetFields or facetIntervals -- [ADF-4089](https://issues.alfresco.com/jira/browse/ADF-4089) - contentListPage refactoring +- [ADF-4089](https://issues.alfresco.com/jira/browse/ADF-4089) - contentListPage refactoring -- [ADF-4094](https://issues.alfresco.com/jira/browse/ADF-4094) - Automate Permissions Component +- [ADF-4094](https://issues.alfresco.com/jira/browse/ADF-4094) - Automate Permissions Component -- [ADF-4121](https://issues.alfresco.com/jira/browse/ADF-4121) - Fixing failing e2e tests +- [ADF-4121](https://issues.alfresco.com/jira/browse/ADF-4121) - Fixing failing e2e tests -- [ADF-4123](https://issues.alfresco.com/jira/browse/ADF-4123) - Process Cloud Instance Details Header component +- [ADF-4123](https://issues.alfresco.com/jira/browse/ADF-4123) - Process Cloud Instance Details Header component -- [ADF-4124](https://issues.alfresco.com/jira/browse/ADF-4124) - [Demo Shell] TaskListCloud with the filter on a Process instance +- [ADF-4124](https://issues.alfresco.com/jira/browse/ADF-4124) - [Demo Shell] TaskListCloud with the filter on a Process instance -- [ADF-4132](https://issues.alfresco.com/jira/browse/ADF-4132) - [Artificial Intelligence] Smart viewer for ADF recognising entities +- [ADF-4132](https://issues.alfresco.com/jira/browse/ADF-4132) - [Artificial Intelligence] Smart viewer for ADF recognising entities -- [ADF-4145](https://issues.alfresco.com/jira/browse/ADF-4145) - [Artificial Intelligence] Transformation Services added to the ACS instance in the ADF development pipeline +- [ADF-4145](https://issues.alfresco.com/jira/browse/ADF-4145) - [Artificial Intelligence] Transformation Services added to the ACS instance in the ADF development pipeline -- [ADF-4147](https://issues.alfresco.com/jira/browse/ADF-4147) - Add a way to test selectionMode on demo-shell for task list cloud component +- [ADF-4147](https://issues.alfresco.com/jira/browse/ADF-4147) - Add a way to test selectionMode on demo-shell for [task list cloud component](../process-services-cloud/components/task-list-cloud.component.md) -- [ADF-4149](https://issues.alfresco.com/jira/browse/ADF-4149) - e2e tests - Move the pages from the e2e folder to the adf-testing +- [ADF-4149](https://issues.alfresco.com/jira/browse/ADF-4149) - e2e tests - Move the pages from the e2e folder to the adf-testing -- [ADF-4155](https://issues.alfresco.com/jira/browse/ADF-4155) - AppList - be able to show the list of apps even in case the deployment service is missing +- [ADF-4155](https://issues.alfresco.com/jira/browse/ADF-4155) - AppList - be able to show the list of apps even in case the deployment service is missing -- [ADF-4158](https://issues.alfresco.com/jira/browse/ADF-4158) - No Alfresco-supplied docker image should run as root +- [ADF-4158](https://issues.alfresco.com/jira/browse/ADF-4158) - No Alfresco-supplied docker image should run as root -- [ADF-4159](https://issues.alfresco.com/jira/browse/ADF-4159) - DemoShell add nested-menu +- [ADF-4159](https://issues.alfresco.com/jira/browse/ADF-4159) - DemoShell add nested-menu -- [ADF-4184](https://issues.alfresco.com/jira/browse/ADF-4184) - Add Arabic i18n support +- [ADF-4184](https://issues.alfresco.com/jira/browse/ADF-4184) - Add Arabic i18n support -- [ADF-4192](https://issues.alfresco.com/jira/browse/ADF-4192) - Remove spinner check from editTaskFilter tests +- [ADF-4192](https://issues.alfresco.com/jira/browse/ADF-4192) - Remove spinner check from editTaskFilter tests -- [ADF-4195](https://issues.alfresco.com/jira/browse/ADF-4195) - Automate tests for SSO login with implicitFlow false +- [ADF-4195](https://issues.alfresco.com/jira/browse/ADF-4195) - Automate tests for SSO login with implicitFlow false -- [ADF-4201](https://issues.alfresco.com/jira/browse/ADF-4201) - About component improvements +- [ADF-4201](https://issues.alfresco.com/jira/browse/ADF-4201) - [About component](../core/components/about.component.md) improvements -- [ADF-4208](https://issues.alfresco.com/jira/browse/ADF-4208) - [E2E] Make the pipeline green again ! +- [ADF-4208](https://issues.alfresco.com/jira/browse/ADF-4208) - [E2E] Make the pipeline green again ! -- [ADF-4217](https://issues.alfresco.com/jira/browse/ADF-4217) - [Yeoman generator] Remove APS2 and leave Activiti only. +- [ADF-4217](https://issues.alfresco.com/jira/browse/ADF-4217) - [Yeoman generator] Remove APS2 and leave Activiti only. -- [ADF-4222](https://issues.alfresco.com/jira/browse/ADF-4222) - Fix the compilation errors on the Development branch, so that this can be added to the rules. +- [ADF-4222](https://issues.alfresco.com/jira/browse/ADF-4222) - Fix the compilation errors on the Development branch, so that this can be added to the rules. -- [ADF-4223](https://issues.alfresco.com/jira/browse/ADF-4223) - Export folder-name dialog validators +- [ADF-4223](https://issues.alfresco.com/jira/browse/ADF-4223) - Export folder-name dialog validators -- [ADF-4233](https://issues.alfresco.com/jira/browse/ADF-4233) - DemoShell - Change nested menu layout +- [ADF-4233](https://issues.alfresco.com/jira/browse/ADF-4233) - DemoShell - Change nested menu layout ### Feature (Task) -- [ADF-3945](https://issues.alfresco.com/jira/browse/ADF-3945) - Provide a way to change the infinite pagination pageSize +- [ADF-3945](https://issues.alfresco.com/jira/browse/ADF-3945) - Provide a way to change the infinite pagination pageSize -- [ADF-4038](https://issues.alfresco.com/jira/browse/ADF-4038) - Add appName filter parameter for people/group demo component +- [ADF-4038](https://issues.alfresco.com/jira/browse/ADF-4038) - Add appName filter parameter for people/group demo component -- [ADF-4095](https://issues.alfresco.com/jira/browse/ADF-4095) - Automate C268974 - Inherit Permission +- [ADF-4095](https://issues.alfresco.com/jira/browse/ADF-4095) - Automate C268974 - Inherit Permission -- [ADF-4100](https://issues.alfresco.com/jira/browse/ADF-4100) - Automate C274691 Dropdown menu +- [ADF-4100](https://issues.alfresco.com/jira/browse/ADF-4100) - Automate C274691 Dropdown menu -- [ADF-4101](https://issues.alfresco.com/jira/browse/ADF-4101) - Automate C276978 - Add user +- [ADF-4101](https://issues.alfresco.com/jira/browse/ADF-4101) - Automate C276978 - Add user -- [ADF-4102](https://issues.alfresco.com/jira/browse/ADF-4102) - Automate - C276980 - Duplicate user/group +- [ADF-4102](https://issues.alfresco.com/jira/browse/ADF-4102) - Automate - C276980 - Duplicate user/group -- [ADF-4103](https://issues.alfresco.com/jira/browse/ADF-4103) - Automate - C276982 - Remove User/Group +- [ADF-4103](https://issues.alfresco.com/jira/browse/ADF-4103) - Automate - C276982 - Remove User/Group -- [ADF-4104](https://issues.alfresco.com/jira/browse/ADF-4104) - Automate - C277014 - Role - Dropdown +- [ADF-4104](https://issues.alfresco.com/jira/browse/ADF-4104) - Automate - C277014 - Role - Dropdown -- [ADF-4105](https://issues.alfresco.com/jira/browse/ADF-4105) - Automate C277002 - Role - Site Dropdown +- [ADF-4105](https://issues.alfresco.com/jira/browse/ADF-4105) - Automate C277002 - Role - Site Dropdown -- [ADF-4106](https://issues.alfresco.com/jira/browse/ADF-4106) - Automate C276993 - Role - Consumer +- [ADF-4106](https://issues.alfresco.com/jira/browse/ADF-4106) - Automate C276993 - Role - Consumer -- [ADF-4107](https://issues.alfresco.com/jira/browse/ADF-4107) - Automate C276994 - Role - Site Consumer +- [ADF-4107](https://issues.alfresco.com/jira/browse/ADF-4107) - Automate C276994 - Role - Site Consumer -- [ADF-4108](https://issues.alfresco.com/jira/browse/ADF-4108) - Automate - C276996 - Role - Contributor +- [ADF-4108](https://issues.alfresco.com/jira/browse/ADF-4108) - Automate - C276996 - Role - Contributor -- [ADF-4109](https://issues.alfresco.com/jira/browse/ADF-4109) - Automate C276997 - Role - Site Contributor +- [ADF-4109](https://issues.alfresco.com/jira/browse/ADF-4109) - Automate C276997 - Role - Site Contributor -- [ADF-4110](https://issues.alfresco.com/jira/browse/ADF-4110) - Automate - C277000 - Role - Editor +- [ADF-4110](https://issues.alfresco.com/jira/browse/ADF-4110) - Automate - C277000 - Role - Editor -- [ADF-4111](https://issues.alfresco.com/jira/browse/ADF-4111) - Automate C277003 - Role - Collaborator +- [ADF-4111](https://issues.alfresco.com/jira/browse/ADF-4111) - Automate C277003 - Role - Collaborator -- [ADF-4112](https://issues.alfresco.com/jira/browse/ADF-4112) - Automate C277005 Role - Site Collaborator +- [ADF-4112](https://issues.alfresco.com/jira/browse/ADF-4112) - Automate C277005 Role - Site Collaborator -- [ADF-4113](https://issues.alfresco.com/jira/browse/ADF-4113) - Automate C277004 Role - Coordinator +- [ADF-4113](https://issues.alfresco.com/jira/browse/ADF-4113) - Automate C277004 Role - Coordinator -- [ADF-4114](https://issues.alfresco.com/jira/browse/ADF-4114) - Automate - C277006 Role - Site Manager +- [ADF-4114](https://issues.alfresco.com/jira/browse/ADF-4114) - Automate - C277006 Role - Site Manager -- [ADF-4115](https://issues.alfresco.com/jira/browse/ADF-4115) - Automate C277100 - EVERYONE group +- [ADF-4115](https://issues.alfresco.com/jira/browse/ADF-4115) - Automate C277100 - EVERYONE group -- [ADF-4116](https://issues.alfresco.com/jira/browse/ADF-4116) - Automate C277118 - Site Consumer - Add new version +- [ADF-4116](https://issues.alfresco.com/jira/browse/ADF-4116) - Automate C277118 - Site Consumer - Add new version -- [ADF-4117](https://issues.alfresco.com/jira/browse/ADF-4117) - Automate C279881 - No permissions +- [ADF-4117](https://issues.alfresco.com/jira/browse/ADF-4117) - Automate C279881 - No permissions -- [ADF-4120](https://issues.alfresco.com/jira/browse/ADF-4120) - automate ADF-3989 - The list of apps in 'appName' filter is duplicated after switching between saved filters +- [ADF-4120](https://issues.alfresco.com/jira/browse/ADF-4120) - automate ADF-3989 - The list of apps in 'appName' filter is duplicated after switching between saved filters -- [ADF-4126](https://issues.alfresco.com/jira/browse/ADF-4126) - Automate ADF-4003 - Add roles filtering to PeopleCloudComponent +- [ADF-4126](https://issues.alfresco.com/jira/browse/ADF-4126) - Automate ADF-4003 - Add roles filtering to [PeopleCloudComponent](../process-services-cloud/components/people-cloud.component.md) -- [ADF-4129](https://issues.alfresco.com/jira/browse/ADF-4129) - Automate ADF-4066 - Task doesn't have an assignee when the assignee is empty from Start Task form +- [ADF-4129](https://issues.alfresco.com/jira/browse/ADF-4129) - Automate ADF-4066 - Task doesn't have an assignee when the assignee is empty from Start Task form -- [ADF-4151](https://issues.alfresco.com/jira/browse/ADF-4151) - Automation test for code editor displayed when opening a .js file +- [ADF-4151](https://issues.alfresco.com/jira/browse/ADF-4151) - Automation test for code editor displayed when opening a .js file -- [ADF-4166](https://issues.alfresco.com/jira/browse/ADF-4166) - Move apps-section-cloud.e2e.ts to adf-testing +- [ADF-4166](https://issues.alfresco.com/jira/browse/ADF-4166) - Move apps-section-cloud.e2e.ts to adf-testing -- [ADF-4197](https://issues.alfresco.com/jira/browse/ADF-4197) - Automation test for redirection after page reload +- [ADF-4197](https://issues.alfresco.com/jira/browse/ADF-4197) - Automation test for redirection after page reload -- [ADF-4209](https://issues.alfresco.com/jira/browse/ADF-4209) - [E2E] Fix Core tests +- [ADF-4209](https://issues.alfresco.com/jira/browse/ADF-4209) - [E2E] Fix Core tests -- [ADF-4210](https://issues.alfresco.com/jira/browse/ADF-4210) - [E2E] Fix Content-services and Search tests +- [ADF-4210](https://issues.alfresco.com/jira/browse/ADF-4210) - [E2E] Fix Content-services and Search tests -- [ADF-4211](https://issues.alfresco.com/jira/browse/ADF-4211) - Fix process-services-cloud tests +- [ADF-4211](https://issues.alfresco.com/jira/browse/ADF-4211) - Fix process-services-cloud tests -- [ADF-4218](https://issues.alfresco.com/jira/browse/ADF-4218) - [E2E] Fix Insight tests +- [ADF-4218](https://issues.alfresco.com/jira/browse/ADF-4218) - [E2E] Fix Insight tests -- [ADF-4226](https://issues.alfresco.com/jira/browse/ADF-4226) - Implement automated test for infinitePagination - -- [ADF-4244](https://issues.alfresco.com/jira/browse/ADF-4244) - Fix search tests +- [ADF-4226](https://issues.alfresco.com/jira/browse/ADF-4226) - Implement automated test for infinitePagination +- [ADF-4244](https://issues.alfresco.com/jira/browse/ADF-4244) - Fix search tests Please refer to the [Alfresco issue tracker](https://issues.alfresco.com/jira/projects/ADF/issues/ADF-581?filter=allopenissues) for other known issues in this release. If you have any questions about the release, please contact us using [Gitter](https://gitter.im/Alfresco/alfresco-ng2-components). diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md index 9c62a840f8..c464189552 100644 --- a/docs/release-notes/RelNote320.md +++ b/docs/release-notes/RelNote320.md @@ -18,24 +18,18 @@ versions of ADF. - [New package versions](#new-package-versions) - [Goals for this release](#goals-for-this-release) - [More on Activiti 7](#more-on-activiti-7) - -[New permission template to app list](new-permission-template-to-app-list) - -[Cloud form definition selector component](cloud-form-definition-selector-component) - [Five more languages supported](#five-more-languages-supported) - [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) - - [Confirm Dialog third extra button option and custom HTML message](#confirm-dialog-third-extra-button-option-and-custom-html-message) - - [Configuration option to change the dafault viewer zoom](#configuration-option-to-change-the-dafault-viewer-zoom) - - [Drop events for DataTable component](#drop-events-for-dataTable-component) + - [Option to chose which panel to show first in info drawer](#option-to-chose-which-panel-to-show-first-in-info-drawer) + - [Confirm Dialog third extra button option and custom HTML message](#confirm-dialog-third-extra-button-option-and--custom-html-message) + - [Configuration option to change the default viewer zoom](#configuration-option-to-change-the-default-viewer-zoom) + - [Drop events for DataTable component](#drop-events-for-datatable-component) - [Sidenav Layout Direction property](#sidenav-layout-direction-property) - [Custom local storages prefix property](#custom-local-storages-prefix-property) - - [Datatable Component new Json cell type](#datatable-component-new-json-cell-type) + - [Datatable Component new Json cell type](#datatable-component-new--json-cell-type) - [Localisation](#localisation) - [References](#references) - [Issues addressed](#issues-addressed) - - [Documentation](#documentation) - - [Feature](#feature) - - [Bug](#bug) - - [Task](#task) - - [Feature (Task)](#feature-task) ## New package versions @@ -60,16 +54,18 @@ Below are the most important new features of this release: - [More on Activiti 7](#more-on-activiti-7) - [Five more languages supported](#five-more-languages-supported) - [Event handling during header row action](#event-handling-during-header-row-action) -- [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) +- [List separator configuration in multi-value metadata](#list-separator-configuration-in-multi-value-metadata) ### More on Activiti 7 In ADF 3.0.0 (released in February) we announced the introduction of the new `*Cloud` package. This contains a set of components to support [Activiti 7](https://www.activiti.org/), the next generation Cloud Native implementation of Activiti BPM Engine. With the ADF 3.2 release, the journey continues with more supported features, like: #### New permission template to app list + A new message template is now displayed when a user doesn't have permissions #### Cloud form definition selector component + Cloud form definition selector component is a dropdown that shows all the form present in your app: ```html @@ -78,8 +74,10 @@ Cloud form definition selector component is a dropdown that shows all the form p (selectForm)="onFormSelect($event)"> </adf-cloud-form-definition-selector> ``` + For more details refer to the: -- [DataTable component](../process-services-cloud/components/form-definition-selector-cloud.component.md ). + +- [DataTable component](../process-services-cloud/components/form-definition-selector-cloud.component.md). ### Five more languages supported @@ -97,37 +95,41 @@ As of this version of ADF, developers can configure the list separator of multi- "multi-value-pipe-separator" : " - " } ``` + For more details refer to the: -- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) + +- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) ### Option to chose which panel to show first in info drawer -Is now possible define which aspect show expanded by default in the metadata card applying the optional property ```displayAspect``` +Is now possible define which aspect show expanded by default in the metadata card applying the optional property `displayAspect` ![feature-1](https://user-images.githubusercontent.com/14145706/56648273-a45efd80-66a0-11e9-866b-4f13c7df4b80.gif) For more details refer to the: -- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) -### Confirm Dialog third extra button option and custom HTML message +- [Content Metadata Card component](../content-services/components/content-metadata-card.component.md) +### Confirm Dialog third extra button option and custom HTML message Is now possible add an extra button in the Confirm Dialog #### Dialog inputs -| Name | Type | Default value | Description | -| ---- | ---- | ---- | ----------- | -| title | `string` | `Confirm` | It will be placed in the dialog title section. | + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| title | `string` | `Confirm` | It will be placed in the dialog title section. | | yesLabel | `string` | `yes` | It will be placed first in the dialog action section | -| noLabel | `string` | `no`| It will be placed last in the dialog action section | -| thirdOptionLabel (optional) | `string` | | It is not a mandatory input. it will be rendered in between yes and no label | +| noLabel | `string` | `no` | It will be placed last in the dialog action section | +| thirdOptionLabel (optional) | `string` | | It is not a mandatory input. it will be rendered in between yes and no label | | message | `string` | `Do you want to proceed?` | It will be rendered in the dialog content area | -| htmlContent | `HTML` | | It will be rendered in the dialog content area | +| htmlContent | `HTML` | | It will be rendered in the dialog content area | ![yes-all](https://user-images.githubusercontent.com/14145706/56139451-87e30700-5fb6-11e9-8121-e58008231df2.png) - + For more details refer to the: -- [Confirm Dialog](../content-services/dialogs/confirm.dialog.md) + +- [Confirm Dialog](../content-services/dialogs/confirm.dialog.md) ### Configuration option to change the default viewer zoom @@ -146,16 +148,18 @@ In the same way, you can set a default zoom scaling value for the image viewer b "adf-viewer": { "image-viewer-scaling": 150 } -``` +``` By default, the viewer's zoom scaling is set to 100%. For more details refer to the: -- [Viewer Component](../docs/core/components/viewer.component.md) -### Drop events for DataTable component +- [Viewer Component](../docs/core/components/viewer.component.md) + +### Drop events for DataTable component #### Drop Events + Below are the four new DOM events emitted by the DataTable component. These events bubble up the component tree and can be handled by any parent component. @@ -203,38 +207,42 @@ Given that DataTable raises bubbling DOM events, you can handle drop behavior fr </div> ``` -### Sidenav Layout Direction property +### Sidenav Layout Direction property + If you use the [Sidenav Layout component](../core/components/sidenav-layout.component.md) you can choose set the direction property in it using the property direction ans set it to **'rtl'** - ```html +```html <adf-sidenav-layout - [direction]="'rtl'"> + [direction]="'rtl'"> ...... </adf-sidenav-layout> ``` ![preview](https://user-images.githubusercontent.com/3947156/55820667-507ee100-5b04-11e9-81ee-a9951982b237.gif) -### Custom local storages prefix property +### Custom local storages prefix property + If you are using multiple ADF apps, you might want to set the following configuration so that the apps have specific storages and are independent of others when setting and getting data from the local storage. In order to achieve this, you will only need to set your app identifier under the `storagePrefix` property of the app in your `app.config.json` file. - ```json + +```json "application": { - "storagePrefix": "ADF_Identifier" + "storagePrefix": "ADF_Identifier" } ``` -### Datatable Component new Json cell type +### Datatable Component new Json cell type + The datale is now able to render in a better way JSON text : Show Json formated value inside datatable component. - ```html +```html <adf-datatable ...> - <data-columns> - <data-column key="entry.json" type="json" title="Json Column"></data-column> - </data-columns> + <data-columns> + <data-column key="entry.json" type="json" title="Json Column"></data-column> + </data-columns> </adf-datatable> ``` @@ -259,10 +267,10 @@ Please refer to the [official documentation](http://docs.alfresco.com/) for furt ## Issues addressed Below is the list of JIRA issues that were closed for this release. - Release Notes - Apps Development Framework - Version 3.2.0 + <h2> Documentation </h2> <ul> diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index 818adbef2d..fd191e8235 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -6,17 +6,17 @@ Github only: true # Tutorials | Name | Level | Abstract | -| -- | -- | -- | +| ---- | ----- | -------- | | [**Creating your first ADF application**](creating-your-first-adf-application.md) | Basic | This tutorial shows you how to set up your development environment and create an ADF application. | | [**Creating your ADF application using Yeoman**](creating-the-app-using-yeoman.md) | Basic | In this tutorial you are going to see how to create an ADF application from scratch, using the [Yeoman scaffolding tool](http://yeoman.io/). | | [**Creating your Alfresco JavaScript application**](creating-javascript-app-using-alfresco-js-api.md) | Basic | In this tutorial you will learn how to create an application in JavaScript from scratch to interact with Alfresco. | | [**Adding a new component**](new-component.md) | Basic | In this tutorial, you will learn how to create a component using [Angular CLI](https://cli.angular.io/) within an existing application. | | [**Adding a new view**](new-view.md) | Beginner | In this tutorial you will learn how to create a new view in your application and how to access it using a defined endpoint. | | [**Using ADF Components**](using-components.md) | Basic | In this tutorial you will learn how to extend, use and configure ADF Components. | -| [**Basic theming**](basic-theming.md) | Beginner | In this tutorial you will see how to theme an ADF app by modifying the CSS. | +| [**Basic theming**](basic-theming.md) | Beginner | In this tutorial you will see how to theme an ADF app by modifying the CSS. | | [**Customizing the Login component**](customising-login.md) | Intermediate | In this tutorial you will learn how to customize the [Login component](../core/components/login.component.md) following the technical documentation. | | [**Working with a Data Table**](working-with-data-table.md) | Intermediate | In this tutorial you will learn how to populate a DataTable component. | | [**Working with the Nodes API Service**](working-with-nodes-api-service.md) | Intermediate | In this tutorial you will learn how to use the [`NodesApiService`](../core/services/nodes-api.service.md). | | [**Working with Nodes using the JS API**](working-with-nodes-js-api.md) | Intermediate | In this tutorial you will learn how to use the [`AlfrescoCoreRestApi`](https://github.com/Alfresco/alfresco-js-api/tree/master/src/alfresco-core-rest-api). | -| [**Content metadata component**](content-metadata-component.md) | Advanced | In this tutorial you will learn how to work with the [`ContentMetadataComponent`](../content-services/components/content-metadata-card.component.md). | +| [**Content metadata component**](content-metadata-component.md) | Advanced | In this tutorial you will learn how to work with the [`ContentMetadataComponent`](../../lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts). | | [**Building an ADF application on top of Activiti Cloud 7.0.0 GA Community Edition**](activiti-7-and-adf.md) | Intermediate | This tutorial shows how to configure an ADF app to connect to Activiti Cloud 7. | diff --git a/docs/tutorials/content-metadata-component.md b/docs/tutorials/content-metadata-component.md index 58d1b7eff8..27e064f376 100644 --- a/docs/tutorials/content-metadata-component.md +++ b/docs/tutorials/content-metadata-component.md @@ -5,13 +5,13 @@ Level: Advanced # Content metadata component -In this tutorial you will learn how to work with the [`ContentMetadataComponent`](../content-services/components/content-metadata-card.component.md). +In this tutorial you will learn how to work with the [`ContentMetadataComponent`](../../lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts). This component is used to render the standard and custom metadata of generic content item (called a _node_) stored in Alfresco Content Services. With the usual approach "learning by doing", you will see here some practical examples you might find useful in your own applicatioin. As a starting point, we will use and customize the [Alfresco Content App](https://github.com/Alfresco/alfresco-content-app). ## About the `ContentMetadataComponent` -As described in the [`ContentMetadataComponent`](../content-services/components/content-metadata-card.component.md) documentation, the `adf-content-metadata-card` tag has some useful attributes, included the `preset` attribute, which is used to point to a collection of aspects/properties to render. +As described in the [`ContentMetadataComponent`](../../lib/content-services/content-metadata/components/content-metadata/content-metadata.component.ts) documentation, the `adf-content-metadata-card` tag has some useful attributes, included the `preset` attribute, which is used to point to a collection of aspects/properties to render. Below, you can see the `preset` value requesting to render all the available aspects/properties: diff --git a/docs/upgrade-guide/upgrade26-30.md b/docs/upgrade-guide/upgrade26-30.md index 56d6495c2e..2a83068aea 100644 --- a/docs/upgrade-guide/upgrade26-30.md +++ b/docs/upgrade-guide/upgrade26-30.md @@ -17,6 +17,27 @@ you need to take into account as well as the usual library updates. After updati the libraries, check the other sections to see if any of the changes affect your project. +## Contents + +- [Library updates](#library-updates) + - [Automatic update using the Yeoman Generator](#automatic-update-using-the-yeoman-generator) + - [Manual update](#manual-update) +- [Breaking changes](#breaking-changes) +- [JS-API changes](#js-api-changes) +- [Permissions vs Allowable Operations](#permissions-vs-allowable-operations) +- [Deprecated items](#deprecated-items) +- [Relocated classes](#relocated-classes) +- [Renamed items](#renamed-items) + - [Classes](#classes) + - [Properties and methods](#properties-and-methods) + - [Component selectors](#component-selectors) +- [CSS classes with "adf-" prefix added](#css-classes-with-adf--prefix-added) + - [Content services CSS classes](#content-services-css-classes) + - [Core CSS classes](#core-css-classes) + - [Insights CSS classes](#insights-css-classes) + - [Process services cloud CSS classes](#process-services-cloud-css-classes) + - [Process services CSS classes](#process-services-css-classes) + ## Library updates ### Automatic update using the Yeoman Generator @@ -62,6 +83,7 @@ After starting the app, if everything is working fine, that's all and you don't ### Manual update 1. Update the `package.json` file with the latest library versions: + ```json "dependencies": { ... @@ -83,7 +105,7 @@ After starting the app, if everything is working fine, that's all and you don't ## Breaking changes The ADF project follows the [semver](https://semver.org/) conventions and so we -only make breaking changes (ie, not backward-compatible) in *major* versions. +only make breaking changes (ie, not backward-compatible) in _major_ versions. ADF 3.0 is the first major version since general availability so a number of deprecated items have been removed and also some existing items have been renamed. The sections below explain how to adapt your project to the changes @@ -92,12 +114,12 @@ in 3.0. See also our document for more information about the changes and links to the associated pull requests. -- [JS-API changes](#js-api-changes) -- [Permissions vs Allowable Operations](#permissions-vs-allowable-operations) -- [Deprecated items](#deprecated-items) -- [Relocated classes](#relocated-classes) -- [Renamed items](#renamed-items) -- [CSS classes with "adf-" prefix added](#css-classes-with-adf--prefix-added) +- [JS-API changes](#js-api-changes) +- [Permissions vs Allowable Operations](#permissions-vs-allowable-operations) +- [Deprecated items](#deprecated-items) +- [Relocated classes](#relocated-classes) +- [Renamed items](#renamed-items) +- [CSS classes with "adf-" prefix added](#css-classes-with-adf--prefix-added) ## JS-API changes @@ -169,7 +191,7 @@ Related to this issue is the `hasPermission` method of the made redundant by [`ContentService`](../core/services/content.service.md)`.hasAllowableOperations` and has now been removed. -Also, the former Node Permission Directive has now been renamed as the +Also, the former [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Permission Directive has now been renamed as the [Check Allowable Operation directive](../core/directives/check-allowable-operation.directive.md) to better reflect its true behavior. You should therefore replace existing references to `adf-node-permission` with `adf-check-allowable-operation`. @@ -197,6 +219,7 @@ update your code to use the suggested fix for each item that affects your projec - The `sidebarTemplate` input has now been split into `sidebarLeftTemplate` and `sidebarRightTemplate`. - The `sidebarPosition` input has been removed (the other new inputs render it obsolete). + - The `createFolder` event of the [`UploadBase`](../../lib/content-services/upload/components/base-upload/upload-base.ts) class (emitted when a folder was created) has been removed. You should modify your code to use the `success` event instead. - [Login component](../core/components/login.component.md): Two inputs have been removed: `disableCsrf` and `providers`. Set the @@ -216,18 +239,18 @@ update your code to use the suggested fix for each item that affects your projec your document list as the `target`. - The `folderNode` input has been removed. Use the `currentFolderId` and `node` inputs instead. + - The `SettingsService` class has been removed. Access the equivalent properties with the [App config service](../core/services/app-config.service.md) - [Form service](../core/services/form.service.md): the `addFieldsToAForm` method has been removed. - ## Relocated classes The following classes have been moved from their original libraries to the Core library. You should modify your code to import these classes from `@alfresco/adf-core`. -- [`DownloadZipDialogComponent`](../core/dialogs/download-zip.dialog.md) (formerly Content Services) +- [`DownloadZipDialogComponent`](../../lib/core/dialogs/download-zip.dialog.ts) (formerly Content Services) - [`NodeDownloadDirective`](../core/directives/node-download.directive.md) (formerly Content Services) - [`CommentsModule`](../../lib/core/comments/comments.module.ts) (formerly Process Services) - [`CommentListComponent`](../core/components/comment-list.component.md) (formerly Process Services) @@ -247,9 +270,9 @@ you should replace them with the new ones. ### Properties and methods -- `<adf-form>`: The `onError` event has now been renamed as `error`. -- `<adf-viewer>`: The `fileNodeId` input that supplies the [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Id of the file to -load has been renamed as `nodeId`. +- `<adf-form>`: The `onError` event has now been renamed as `error`. +- `<adf-viewer>`: The `fileNodeId` input that supplies the [`Node`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/Node.md) Id of the file to + load has been renamed as `nodeId`. - `<adf-upload-drag-area>`: The `parentId` input has been renamed as `rootFolderId`. ### Component selectors @@ -274,302 +297,357 @@ they are defined. The new form of the name (ie, with the `adf-` prefix added) is listed but there are a few exceptions where the names were also altered in other ways. These changes are noted with an arrow "->". -- [Content services CSS classes](#content-services-css-classes) -- [Core CSS classes](#core-css-classes) -- [Insights CSS classes](#insights-css-classes) -- [Process services cloud CSS classes](#process-services-cloud-css-classes) -- [Process services CSS classes](#process-services-css-classes) +- [Content services CSS classes](#content-services-css-classes) +- [Core CSS classes](#core-css-classes) +- [Insights CSS classes](#insights-css-classes) +- [Process services cloud CSS classes](#process-services-cloud-css-classes) +- [Process services CSS classes](#process-services-css-classes) ### Content services CSS classes #### [../../lib/content-services/breadcrumb/breadcrumb.component.scss](../../lib/content-services/breadcrumb/breadcrumb.component.scss) -- `adf-isRoot` -- `adf-focus` -- `adf-active` + +- `adf-isRoot` +- `adf-focus` +- `adf-active` #### [../../lib/content-services/content-node-selector/content-node-selector-panel.component.scss](../../lib/content-services/content-node-selector/content-node-selector-panel.component.scss) -- `adf-search-results-label` -- `adf-dropdown-breadcrumb-item-chevron` + +- `adf-search-results-label` +- `adf-dropdown-breadcrumb-item-chevron` #### [../../lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.scss](../../lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.scss) -- `adf-choose-action` + +- `adf-choose-action` #### [../../lib/content-services/content-node-selector/content-node-selector.component.scss](../../lib/content-services/content-node-selector/content-node-selector.component.scss) -- `adf-choose-action` + +- `adf-choose-action` #### [../../lib/content-services/content-node-share/content-node-share.dialog.scss](../../lib/content-services/content-node-share/content-node-share.dialog.scss) -- `adf-input-action` -- `adf-full-width` + +- `adf-input-action` +- `adf-full-width` #### [../../lib/core/dialogs/download-zip.dialog.scss](../../lib/core/dialogs/download-zip.dialog.scss) -- `adf-spacer` + +- `adf-spacer` #### [../../lib/content-services/document-list/components/document-list.component.scss](../../lib/content-services/document-list/components/document-list.component.scss) -- `adf-document-list_empty_template` -- `adf-document-list__this-space-is-empty` -- `adf-document-list__drag-drop` -- `adf-document-list__any-files-here-to-add` -- `adf-document-list__empty_doc_lib` -- `adf-cell-container` -- `adf-cell-value` + +- `adf-document-list_empty_template` +- `adf-document-list__this-space-is-empty` +- `adf-document-list__drag-drop` +- `adf-document-list__any-files-here-to-add` +- `adf-document-list__empty_doc_lib` +- `adf-cell-container` +- `adf-cell-value` #### [../../lib/content-services/search/components/search-check-list/search-check-list.component.scss](../../lib/content-services/search/components/search-check-list/search-check-list.component.scss) -- `adf-facet-filter` -- `adf-facet-name` + +- `adf-facet-filter` +- `adf-facet-name` #### [../../lib/content-services/search/components/search-control.component.scss](../../lib/content-services/search/components/search-control.component.scss) -- `adf-highlight` + +- `adf-highlight` #### [../../lib/content-services/search/components/search-filter/search-filter.component.scss](../../lib/content-services/search/components/search-filter/search-filter.component.scss) -- `adf-checklist` -- `adf-facet-label` -- `adf-facet-result-filter` -- `adf-facet-buttons` + +- `adf-checklist` +- `adf-facet-label` +- `adf-facet-result-filter` +- `adf-facet-buttons` #### [../../lib/content-services/search/components/search-radio/search-radio.component.scss](../../lib/content-services/search/components/search-radio/search-radio.component.scss) -- `adf-facet-filter` -- `adf-filter-label` + +- `adf-facet-filter` +- `adf-filter-label` #### [../../lib/content-services/site-dropdown/sites-dropdown.component.scss](../../lib/content-services/site-dropdown/sites-dropdown.component.scss) -- `adf-full-width` + +- `adf-full-width` #### [../../lib/content-services/upload/components/file-uploading-dialog.component.scss](../../lib/content-services/upload/components/file-uploading-dialog.component.scss) -- `adf-upload-dialog` -- `adf-upload-dialog__content` + +- `adf-upload-dialog` +- `adf-upload-dialog__content` #### [../../lib/content-services/version-manager/version-manager.component.scss](../../lib/content-services/version-manager/version-manager.component.scss) -- `adf-upload-new-version` + +- `adf-upload-new-version` ### Core CSS classes #### [../../lib/core/about/about.component.scss](../../lib/core/about/about.component.scss) -- `adf-about-container` + +- `adf-about-container` #### [../../lib/core/buttons-menu/buttons-menu.component.scss](../../lib/core/buttons-menu/buttons-menu.component.scss) -- `adf-material-icons` + +- `adf-material-icons` #### [../../lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.scss](../../lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.scss) -- `adf-card-view` + +- `adf-card-view` #### [../../lib/core/comments/comment-list.component.scss](../../lib/core/comments/comment-list.component.scss) -- `adf-is-selected` + +- `adf-is-selected` #### [../../lib/core/datatable/components/datatable/datatable.component.scss](../../lib/core/datatable/components/datatable/datatable.component.scss) -- `adf-is-selected` -- `alfresco-datatable__actions-cell` -> `adf-datatable__actions-cell` -- `adf-image-table-cell` -- `adf-cell-container` -- `adf-no-select` -- `adf-sortable` -- `adf-cell-value` -- `adf-full-width` -- `adf-ellipsis-cell` -- `adf-sr-only` -- `adf-hidden` -- `adf-desktop-only` + +- `adf-is-selected` +- `alfresco-datatable__actions-cell` -> `adf-datatable__actions-cell` +- `adf-image-table-cell` +- `adf-cell-container` +- `adf-no-select` +- `adf-sortable` +- `adf-cell-value` +- `adf-full-width` +- `adf-ellipsis-cell` +- `adf-sr-only` +- `adf-hidden` +- `adf-desktop-only` #### [../../lib/core/form/components/form.component.scss](../../lib/core/form/components/form.component.scss) -- `adf-debug-toggle-text` -- `adf-invalid-color` + +- `adf-debug-toggle-text` +- `adf-invalid-color` #### [../../lib/core/form/components/widgets/container/container.widget.scss](../../lib/core/form/components/widgets/container/container.widget.scss) -- `adf-hidden` -- `adf-container-widget__header-text` -- `adf-collapsible` -- `adf-grid-list` -- `adf-grid-list-item` + +- `adf-hidden` +- `adf-container-widget__header-text` +- `adf-collapsible` +- `adf-grid-list` +- `adf-grid-list-item` #### [../../lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.scss](../../lib/core/form/components/widgets/dynamic-table/dynamic-table.widget.scss) -- `adf-is-selected` -- `adf-no-select` -- `adf-sortable` -- `adf-full-width` + +- `adf-is-selected` +- `adf-no-select` +- `adf-sortable` +- `adf-full-width` #### [../../lib/core/layout/components/layout-container/layout-container.component.scss](../../lib/core/layout/components/layout-container/layout-container.component.scss) -- `adf-sidenav--hidden` + +- `adf-sidenav--hidden` #### [../../lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss](../../lib/core/layout/components/sidenav-layout/sidenav-layout.component.scss) -- `adf-sidenav-layout` -- `adf-layout__content` + +- `adf-sidenav-layout` +- `adf-layout__content` #### [../../lib/core/login/components/login-dialog-panel.component.scss](../../lib/core/login/components/login-dialog-panel.component.scss) -- `adf-copyright` + +- `adf-copyright` #### [../../lib/core/login/components/login.component.scss](../../lib/core/login/components/login.component.scss) -- `adf-ie11FixerParent` -- `adf-ie11FixerChild` -- `adf-show` -- `adf-hide` -- `adf-icon-inline` -- `adf-error-icon` -- `adf-isChecking` -- `adf-isWelcome` -- `adf-welcome-icon` -- `adf-login-checking-spinner` -- `adf-is-active` -- `adf-copyright` -- `adf-login-rememberme` -> - `adf-login-remember-me` + +- `adf-ie11FixerParent` +- `adf-ie11FixerChild` +- `adf-show` +- `adf-hide` +- `adf-icon-inline` +- `adf-error-icon` +- `adf-isChecking` +- `adf-isWelcome` +- `adf-welcome-icon` +- `adf-login-checking-spinner` +- `adf-is-active` +- `adf-copyright` +- `adf-login-rememberme` -> - `adf-login-remember-me` #### [../../lib/core/settings/host-settings.component.scss](../../lib/core/settings/host-settings.component.scss) -- `adf-full-width` + +- `adf-full-width` #### [../../lib/core/viewer/components/imgViewer.component.scss](../../lib/core/viewer/components/imgViewer.component.scss) -- `adf-image-container` + +- `adf-image-container` #### [../../lib/core/viewer/components/pdfViewer-thumbnails.component.scss](../../lib/core/viewer/components/pdfViewer-thumbnails.component.scss) -- `adf-pdf-thumbnails` + +- `adf-pdf-thumbnails` #### [../../lib/core/viewer/components/pdfViewer.component.scss](../../lib/core/viewer/components/pdfViewer.component.scss) -- `adf-loader-container` -- `adf-thumbnails-template` -- `adf-loader-item` + +- `adf-loader-container` +- `adf-thumbnails-template` +- `adf-loader-item` #### [../../lib/core/viewer/components/pdfViewerHost.component.scss](../../lib/core/viewer/components/pdfViewerHost.component.scss) -- `adf-highlight` -- `adf-begin` -- `adf-end` -- `adf-middle` -- `adf-selected` -- `adf-endOfContent` -- `adf-active` -- `adf-annotationLayer` -- `adf-linkAnnotation` -- `adf-textAnnotation` -- `adf-popupWrapper` -- `adf-popup` -- `adf-highlightAnnotation` -- `adf-underlineAnnotation` -- `adf-squigglyAnnotation` -- `adf-strikeoutAnnotation` -- `adf-fileAttachmentAnnotation` -- `adf-pdfViewer` -- `adf-page` -- `adf-loadingIcon` -- `adf-removePageBorders` -- `adf-hidden` -- `adf-viewer-pdf-viewer` + +- `adf-highlight` +- `adf-begin` +- `adf-end` +- `adf-middle` +- `adf-selected` +- `adf-endOfContent` +- `adf-active` +- `adf-annotationLayer` +- `adf-linkAnnotation` +- `adf-textAnnotation` +- `adf-popupWrapper` +- `adf-popup` +- `adf-highlightAnnotation` +- `adf-underlineAnnotation` +- `adf-squigglyAnnotation` +- `adf-strikeoutAnnotation` +- `adf-fileAttachmentAnnotation` +- `adf-pdfViewer` +- `adf-page` +- `adf-loadingIcon` +- `adf-removePageBorders` +- `adf-hidden` +- `adf-viewer-pdf-viewer` #### [../../lib/core/viewer/components/viewer.component.scss](../../lib/core/viewer/components/viewer.component.scss) -- `adf-full-screen` -- `adf-info-drawer-content` + +- `adf-full-screen` +- `adf-info-drawer-content` ### Insights CSS classes #### [../../lib/insights/analytics-process/components/analytics-generator.component.scss](../../lib/insights/analytics-process/components/analytics-generator.component.scss) -- `adf-chart` -- `adf-analytics-row__entry` -- `adf-report-icons` -- `adf-full-width` -- `adf-partial-width` -- `adf-clear-both` + +- `adf-chart` +- `adf-analytics-row__entry` +- `adf-report-icons` +- `adf-full-width` +- `adf-partial-width` +- `adf-clear-both` #### [../../lib/insights/analytics-process/components/analytics-report-list.component.scss](../../lib/insights/analytics-process/components/analytics-report-list.component.scss) -- `adf-activiti-filters__entry` -- `adf-activiti-filters__entry-icon` -- `adf-activiti-filters__label` -- `adf-active` -- `adf-application-title` + +- `adf-activiti-filters__entry` +- `adf-activiti-filters__entry-icon` +- `adf-activiti-filters__label` +- `adf-active` +- `adf-application-title` #### [../../lib/insights/analytics-process/components/analytics-report-parameters.component.scss](../../lib/insights/analytics-process/components/analytics-report-parameters.component.scss) -- `adf-dropdown-widget` -- `adf-dropdown-widget__select` -- `adf-dropdown-widget__invalid` -- `adf-dropdown-widget__label` -- `adf-is-hide` -- `adf-report-container-setting` -- `adf-option_button_details` -- `adf-export-message` -- `adf-save-export-input` -- `adf-delete-parameter` -- `adf-hide` + +- `adf-dropdown-widget` +- `adf-dropdown-widget__select` +- `adf-dropdown-widget__invalid` +- `adf-dropdown-widget__label` +- `adf-is-hide` +- `adf-report-container-setting` +- `adf-option_button_details` +- `adf-export-message` +- `adf-save-export-input` +- `adf-delete-parameter` +- `adf-hide` #### [../../lib/insights/analytics-process/components/analytics.component.scss](../../lib/insights/analytics-process/components/analytics.component.scss) -- `adf-chart` + +- `adf-chart` #### [../../lib/insights/analytics-process/components/widgets/duration/duration.widget.scss](../../lib/insights/analytics-process/components/widgets/duration/duration.widget.scss) -- `adf-dropdown-container` + +- `adf-dropdown-container` #### [../../lib/insights/diagram/components/tooltip/diagram-tooltip.component.scss](../../lib/insights/diagram/components/tooltip/diagram-tooltip.component.scss) -- `adf-is-active` + +- `adf-is-active` ### Process services cloud CSS classes #### [../../lib/process-services-cloud/src/lib/app/components/app-details-cloud.component.scss](../../lib/process-services-cloud/src/lib/app/components/app-details-cloud.component.scss) -- `adf-line-clamp` + +- `adf-line-clamp` #### [../../lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.scss](../../lib/process-services-cloud/src/lib/process/process-filters/components/process-filters-cloud.component.scss) -- `adf-active` + +- `adf-active` #### [../../lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.scss](../../lib/process-services-cloud/src/lib/process/process-list/components/process-list-cloud.component.scss) -- `adf-no-content-message` + +- `adf-no-content-message` #### [../../lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.scss](../../lib/process-services-cloud/src/lib/task/task-filters/components/task-filters-cloud.component.scss) -- `adf-active` + +- `adf-active` ### Process services CSS classes #### [../../lib/process-services/app-list/apps-list.component.scss](../../lib/process-services/app-list/apps-list.component.scss) -- `adf-line-clamp` + +- `adf-line-clamp` #### [../../lib/process-services/attachment/process-attachment-list.component.scss](../../lib/process-services/attachment/process-attachment-list.component.scss) -- `adf-data-cell` + +- `adf-data-cell` #### [../../lib/process-services/attachment/task-attachment-list.component.scss](../../lib/process-services/attachment/task-attachment-list.component.scss) -- `adf-data-cell` + +- `adf-data-cell` #### [../../lib/process-services/content-widget/attach-file-widget-dialog.component.scss](../../lib/process-services/content-widget/attach-file-widget-dialog.component.scss) -- `adf-choose-action` + +- `adf-choose-action` #### [../../lib/process-services/people/components/people-search-field/people-search-field.component.scss](../../lib/process-services/people/components/people-search-field/people-search-field.component.scss) -- `adf-search-text-container` -- `adf-search-list-container` -- `adf-people-pic` -- `adf-people-img` + +- `adf-search-text-container` +- `adf-search-list-container` +- `adf-people-pic` +- `adf-people-img` #### [../../lib/process-services/people/components/people-search/people-search.component.scss](../../lib/process-services/people/components/people-search/people-search.component.scss) -- `adf-activiti-label` -- `adf-fix-element-user-list` -- `adf-search-text-header` -- `adf-search-list-action-container` + +- `adf-activiti-label` +- `adf-fix-element-user-list` +- `adf-search-text-header` +- `adf-search-list-action-container` #### [../../lib/process-services/people/components/people/people.component.scss](../../lib/process-services/people/components/people/people.component.scss) -- `adf-assignment-header` -- `adf-assignment-count` -- `adf-add-people` -- `adf-assignment-top-container` -- `adf-assignment-top-container-content` -- `adf-assignment-container` -- `adf-assignment-list-container` -- `adf-cell-container` -- `adf-people-email` -- `adf-people-img` + +- `adf-assignment-header` +- `adf-assignment-count` +- `adf-add-people` +- `adf-assignment-top-container` +- `adf-assignment-top-container-content` +- `adf-assignment-container` +- `adf-assignment-list-container` +- `adf-cell-container` +- `adf-people-email` +- `adf-people-img` #### [../../lib/process-services/process-comments/process-comments.component.scss](../../lib/process-services/process-comments/process-comments.component.scss) -- `adf-activiti-label` -- `adf-icon` -- `adf-list-wrap` -- `adf-hide-long-names` + +- `adf-activiti-label` +- `adf-icon` +- `adf-list-wrap` +- `adf-hide-long-names` #### [../../lib/process-services/process-list/components/process-filters.component.scss](../../lib/process-services/process-list/components/process-filters.component.scss) -- `adf-active` + +- `adf-active` #### [../../lib/process-services/task-list/components/checklist.component.scss](../../lib/process-services/task-list/components/checklist.component.scss) -- `adf-activiti-label` -- `adf-checklist-menu-container` -- `adf-checklist-none-message` -- `activiti-label` -> `adfactiviti-label` + +- `adf-activiti-label` +- `adf-checklist-menu-container` +- `adf-checklist-none-message` +- `activiti-label` -> `adfactiviti-label` #### [../../lib/process-services/task-list/components/start-task.component.scss](../../lib/process-services/task-list/components/start-task.component.scss) -- `adf-people-widget-content` + +- `adf-people-widget-content` #### [../../lib/process-services/task-list/components/task-details.component.scss](../../lib/process-services/task-list/components/task-details.component.scss) -- `adf-error-dialog` -- `adf-activiti-task-details__header` -- `adf-activiti-task-details__action-button` -- `adf-assignment-container` -- `adf-task-header` -- `adf-assign-edit-view` -- `adf-property` + +- `adf-error-dialog` +- `adf-activiti-task-details__header` +- `adf-activiti-task-details__action-button` +- `adf-assignment-container` +- `adf-task-header` +- `adf-assign-edit-view` +- `adf-property` #### [../../lib/process-services/task-list/components/task-filters.component.scss](../../lib/process-services/task-list/components/task-filters.component.scss) -- `adf-active` + +- `adf-active` diff --git a/docs/user-guide/app-extensions.md b/docs/user-guide/app-extensions.md index 4d08ef0df0..540883edb8 100644 --- a/docs/user-guide/app-extensions.md +++ b/docs/user-guide/app-extensions.md @@ -203,7 +203,7 @@ The simplest type of rule is configured as shown below: ] ``` -The `type` is the ID of a `RuleEvaluator` function that has been registered using +The `type` is the ID of a [`RuleEvaluator`](../../lib/extensions/src/lib/config/rule.extensions.ts) function that has been registered using the `setEvaluators` method of the [Extension service](../extensions/services/extension.service.md). The evaluator is a boolean function that represents whether a certain condition is true or false (eg, whether an item is selected, whether the user diff --git a/docs/user-guide/internationalization.md b/docs/user-guide/internationalization.md index 00d764b4b9..f918fcc2c1 100644 --- a/docs/user-guide/internationalization.md +++ b/docs/user-guide/internationalization.md @@ -71,7 +71,7 @@ below: ``` The hierarchical structure is referred to in the UI using the familiar "dot" -notation (so `FORM.START_FORM.TITLE` would be the key for the "Start Form" +notation (so `FORM.START_FORM.TITLE` would be the key for the "Start [Form"](../../lib/process-services/task-list/models/form.model.ts) string here). This is useful for grouping related messages and providing singular and plural versions, among other things. @@ -144,7 +144,7 @@ Using [`TranslationService`](../core/services/translation.service.md)`.get` is s convenient to add translation keys directly into your page's HTML. Use the `translate` pipe to convert a key in the page directly to the corresponding text. For example, the following will display the -"Start Form" text as above but without any code or variables in the +"Start [Form"](../../lib/process-services/task-list/models/form.model.ts) text as above but without any code or variables in the component's `.ts` file: <!-- {% raw %} --> diff --git a/docs/versionIndex.md b/docs/versionIndex.md index 8cbbe2aeb5..9332f594a9 100644 --- a/docs/versionIndex.md +++ b/docs/versionIndex.md @@ -29,10 +29,13 @@ backend services have been tested with each released version of ADF. <!--v320 start--> -- Support for five new languages (Danish, Finnish, Swedish, Czech, Polish). -- Easier event handling in [DataTable](core/components/datatable.component.md) (header row action). -- Configurable [multi-value metadata separator](content-services/components/content-metadata-card.component.md). -- More process components for Activiti 7. +- [Clipboard directive](core/directives/clipboard.directive.md) +- [Clipboard service](core/services/clipboard.service.md) +- [Form cloud custom outcome component](process-services-cloud/components/form-cloud-custom-outcome.component.md) +- [Form cloud component](process-services-cloud/components/form-cloud.component.md) +- [Form cloud service](process-services-cloud/services/form-cloud.service.md) +- [Json cell component](core/components/json-cell.component.md) +- [Task form cloud component](process-services-cloud/components/task-form-cloud.component.md) <!--v320 end--> @@ -295,11 +298,12 @@ backend services have been tested with each released version of ADF. - [Folder actions service](content-services/services/folder-actions.service.md) - [Folder create directive](content-services/directives/folder-create.directive.md) - [Folder edit directive](content-services/directives/folder-edit.directive.md) +- [Form definition selector cloud component](process-services-cloud/components/form-definition-selector-cloud.component.md) - [Form field component](core/components/form-field.component.md) - [Form field model](core/models/form-field.model.md) - [Form list component](core/components/form-list.component.md) - [Form rendering service](core/services/form-rendering.service.md) -- [Form component](core/components/form.component.md) +- [Form component](process-services/components/form.component.md) - [Form service](core/services/form.service.md) - [Highlight transform service](core/services/highlight-transform.service.md) - [Highlight directive](core/directives/highlight.directive.md) @@ -314,6 +318,7 @@ backend services have been tested with each released version of ADF. - [Login component](core/components/login.component.md) - [Logout directive](core/directives/logout.directive.md) - [Mime type icon pipe](core/pipes/mime-type-icon.pipe.md) +- [Multi value pipe](core/pipes/multi-value.pipe.md) - [Node delete directive](core/directives/node-delete.directive.md) - [Node favorite directive](core/directives/node-favorite.directive.md) - [Node name tooltip pipe](core/pipes/node-name-tooltip.pipe.md) From 4cfc54ad60680500665e35d0f317611345260ca6 Mon Sep 17 00:00:00 2001 From: Maurizio Vitale <maurizio.vitale@alfresco.com> Date: Fri, 3 May 2019 16:24:47 +0200 Subject: [PATCH 207/208] Improve the release note with activiti features (#4692) --- docs/release-notes/RelNote320.md | 51 ++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/RelNote320.md b/docs/release-notes/RelNote320.md index c464189552..9820210c18 100644 --- a/docs/release-notes/RelNote320.md +++ b/docs/release-notes/RelNote320.md @@ -60,13 +60,55 @@ Below are the most important new features of this release: In ADF 3.0.0 (released in February) we announced the introduction of the new `*Cloud` package. This contains a set of components to support [Activiti 7](https://www.activiti.org/), the next generation Cloud Native implementation of Activiti BPM Engine. With the ADF 3.2 release, the journey continues with more supported features, like: +#### Task Form component + +This component is responsible to show the form renderer in case the task has a form attached or the standard standalone card with the Claim/Release/Complete buttons. + +```html +<adf-cloud-task-form + [appName]="appName" + [taskId]="taskId"> +</adf-cloud-task-form> +``` + +For more details refer to the: + +- [TaskFormCloudComponent](../process-services-cloud/components/task-form-cloud.component). + +#### Form Cloud + +This component is responsible to render the form cloud definition attached to the task. + +```html +<adf-cloud-form + [appName]="appName" + [taskId]="taskId"> +</adf-cloud-form> +``` + +In case the form has an upload widget and the alfresco content has been configured*, the attached file will be stored into the alfresco repositoty. + +Note*: +Don't forget to set the `providers` property to `ALL` and `ecmHost` value in the `app.config.json`. +e.g. + +```json +"ecmHost": "http://alfrescocontent.example.com", +"bpmHost": "http://alfrescoaps2.example.com", +"providers": "ALL" +``` + +For more details refer to the: + +- [FormCloudComponent](../process-services-cloud/components/form-cloud.component.md). + #### New permission template to app list A new message template is now displayed when a user doesn't have permissions #### Cloud form definition selector component -Cloud form definition selector component is a dropdown that shows all the form present in your app: +Cloud form definition selector component is a dropdown that shows all the form present in your app. ```html <adf-cloud-form-definition-selector @@ -77,7 +119,12 @@ Cloud form definition selector component is a dropdown that shows all the form p For more details refer to the: -- [DataTable component](../process-services-cloud/components/form-definition-selector-cloud.component.md). +- [FormDefinitionSelectorCloudComponent](../process-services-cloud/components/form-definition-selector-cloud.component.md). + +#### Start a standalone task with a form + +The start task cloud is now using the `cloud-form-definition-selector` that allows the user to attach a form to a task + ### Five more languages supported From 5d49b494fad7d9689072233ebea5ac26ee911560 Mon Sep 17 00:00:00 2001 From: Eugenio Romano <eromano@users.noreply.github.com> Date: Fri, 3 May 2019 17:07:05 +0100 Subject: [PATCH 208/208] bump 3.2.0 (#4690) --- demo-shell/package.json | 2 +- lib/content-services/package.json | 6 +++--- lib/core/package.json | 4 ++-- lib/extensions/package.json | 4 ++-- lib/insights/package.json | 8 ++++---- lib/process-services-cloud/package.json | 6 +++--- lib/process-services/package.json | 8 ++++---- lib/testing/package.json | 4 ++-- package.json | 18 +++++++++--------- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/demo-shell/package.json b/demo-shell/package.json index 5d02f1bdb3..b15d0a7be0 100644 --- a/demo-shell/package.json +++ b/demo-shell/package.json @@ -1,7 +1,7 @@ { "name": "Alfresco-ADF-Angular-Demo", "description": "Demo shell for Alfresco Angular components", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "repository": { "type": "git", diff --git a/lib/content-services/package.json b/lib/content-services/package.json index 71e865ec22..f899a8b19f 100644 --- a/lib/content-services/package.json +++ b/lib/content-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-content-services", "description": "Alfresco ADF content services", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-content-services.js", "repository": { @@ -25,9 +25,9 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.2.0-beta6", + "@alfresco/js-api": "3.2.0", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta6", + "@alfresco/adf-core": "3.2.0", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/core/package.json b/lib/core/package.json index 5f3557ba12..552d68e9b0 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-core", "description": "Alfresco ADF core", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-core.js", "repository": { @@ -27,7 +27,7 @@ "@angular/router": ">=7.0.3", "@mat-datetimepicker/core": ">=2.0.1", "@mat-datetimepicker/moment": ">=2.0.1", - "@alfresco/js-api": "3.2.0-beta6", + "@alfresco/js-api": "3.2.0", "rxjs": ">=6.2.2", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", diff --git a/lib/extensions/package.json b/lib/extensions/package.json index f56a2efe6a..b146d74983 100644 --- a/lib/extensions/package.json +++ b/lib/extensions/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-extensions", "description": "Provides extensibility support for ADF applications.", - "version": "3.2.0-beta6", + "version": "3.2.0", "license": "Apache-2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-extensions.js", @@ -16,7 +16,7 @@ "@angular/common": ">=7.0.3", "@angular/core": ">=7.0.3", "@angular/http": ">=7.0.3", - "@alfresco/js-api": "3.2.0-beta6" + "@alfresco/js-api": "3.2.0" }, "keywords": [ "extensions", diff --git a/lib/insights/package.json b/lib/insights/package.json index 379cd10b76..9ee0078781 100644 --- a/lib/insights/package.json +++ b/lib/insights/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-insights", "description": "Alfresco ADF insights", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-insights.js", "repository": { @@ -25,10 +25,10 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.2.0-beta6", + "@alfresco/js-api": "3.2.0", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta6", - "@alfresco/adf-content-services": "3.2.0-beta6", + "@alfresco/adf-core": "3.2.0", + "@alfresco/adf-content-services": "3.2.0", "@ngx-translate/core": ">=11.0.0", "chart.js": ">=2.5.0", "core-js": ">=2.5.4", diff --git a/lib/process-services-cloud/package.json b/lib/process-services-cloud/package.json index 0d25e5dbe9..7fc2ba6240 100644 --- a/lib/process-services-cloud/package.json +++ b/lib/process-services-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services-cloud", "description": "Alfresco ADF process services cloud", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services-cloud.js", "repository": { @@ -25,9 +25,9 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.2.0-beta6", + "@alfresco/js-api": "3.2.0", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta6", + "@alfresco/adf-core": "3.2.0", "@ngx-translate/core": ">=11.0.0", "hammerjs": ">=2.0.8", "moment": ">=2.22.2", diff --git a/lib/process-services/package.json b/lib/process-services/package.json index 8b0073757d..4b5fd19d6a 100644 --- a/lib/process-services/package.json +++ b/lib/process-services/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-process-services", "description": "Alfresco ADF process services", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "main": "bundles/adf-process-services.js", "repository": { @@ -25,10 +25,10 @@ "@angular/platform-browser": ">=7.0.3", "@angular/platform-browser-dynamic": ">=7.0.3", "@angular/router": ">=7.0.3", - "@alfresco/js-api": "3.2.0-beta6", + "@alfresco/js-api": "3.2.0", "rxjs": ">=6.2.2", - "@alfresco/adf-core": "3.2.0-beta6", - "@alfresco/adf-content-services": "3.2.0-beta6", + "@alfresco/adf-core": "3.2.0", + "@alfresco/adf-content-services": "3.2.0", "@ngx-translate/core": ">=11.0.0", "core-js": ">=2.5.4", "hammerjs": ">=2.0.8", diff --git a/lib/testing/package.json b/lib/testing/package.json index 15c6c98f18..61a260f524 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,7 +1,7 @@ { "name": "@alfresco/adf-testing", "description": "Alfresco ADF testing page and utils", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "repository": { "type": "git", @@ -13,7 +13,7 @@ "peerDependencies": { "@angular/common": "^7.1.0", "@angular/core": "^7.1.0", - "@alfresco/js-api": "3.2.0-beta6" + "@alfresco/js-api": "3.2.0" }, "keywords": [ "testing", diff --git a/package.json b/package.json index 932571adcd..228b1753de 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "alfresco-components", "description": "Alfresco Angular components", - "version": "3.2.0-beta6", + "version": "3.2.0", "author": "Alfresco Software, Ltd.", "main": "./index.js", "scripts": { @@ -55,14 +55,14 @@ "process services-cloud" ], "dependencies": { - "@alfresco/adf-content-services": "3.2.0-beta6", - "@alfresco/adf-core": "3.2.0-beta6", - "@alfresco/adf-extensions": "3.2.0-beta6", - "@alfresco/adf-insights": "3.2.0-beta6", - "@alfresco/adf-process-services": "3.2.0-beta6", - "@alfresco/adf-process-services-cloud": "3.2.0-beta6", - "@alfresco/adf-testing": "3.2.0-beta6", - "@alfresco/js-api": "3.2.0-beta6", + "@alfresco/adf-content-services": "3.2.0", + "@alfresco/adf-core": "3.2.0", + "@alfresco/adf-extensions": "3.2.0", + "@alfresco/adf-insights": "3.2.0", + "@alfresco/adf-process-services": "3.2.0", + "@alfresco/adf-process-services-cloud": "3.2.0", + "@alfresco/adf-testing": "3.2.0", + "@alfresco/js-api": "3.2.0", "@angular/animations": "7.0.3", "@angular/cdk": "7.0.3", "@angular/common": "7.0.3",