[AAE-19177] - Migration to NG15 - this one for real 👯 (#9088)

* Fixed linting

* Fixed storybook with migration to WP5

* Fixed core unit test and excluded instable ones

* Rebased with the latest develop

* Fixed most of unit tests failing

* Fixed prod build

* Fixed linting and js-api tests

* Fixed unit tests

* Fixed last unit tests

* Fixed js-api build

* Attempt to fix the e2e run'

* Fixing e2e part 2

* Fixing styles not migrated by material

* Fixed unit test failing

* E2E - fixing

* Fixing unit after rebase

* Fixing e2e - part III

* Rebase went little bit wrong -II

* Rebase went little bit wrong -III

* Fixing e2e - changing toggles

* Fixed code flow switch setting

* wrong xdescribe

* fixig e2es

* fixig e2es - task and version

* readded missing dep

* Fixed slider search e2es

* rebased and fixed the wrong directive for matList'

* fixed unit test problem and some other e2e

* Fixed search e2es

* Rebased to latest

* Fixed the last e2es?

* reverted broken rebase

* Fixed unit tests after rebase

* Fixed unit tests after rebase

* Honestly i'm going on just for the challenge now'

* Readded method removed

* Fixed pointless e2e

* Fixed unit test

* [AAE-18267] change unit test setup for auth service (#9216)

* [AAE-18267] change unit test setup for auth service

* [AAE-18267] remove exclude

* [AAE-18267] removed CoreTestingModule from imports

* unit test fixes for migration (#9217)

* reenabled excluded test in TagNodeList

* fixed tests for UploadApi in js-api

* Fixed a dependency problem

* remaining unit test fixes for the Angular 15 update (#9218)

* removing excludes from working tests

* test fixes for CategoriesManagementComponent

* [ci:force] reenabling tests / fixes

* fixes in process-services-cloud

* change html element type

* fix selector in StartProcessComponent

* Revert "Fixed a dependency problem"

This reverts commit 319e1830fe.

* Rebased to latest

* Fixed PR after huge rebase -_-

* Fixed lint files and exclude some needing migration

* Fixed package.json

* Fixed dependency to allow greater versions

* Rebased to the latest

* [affected:*][ci:force] Fixing rebase

* [affected:*][ci:force] Fixing rebase

* [affected:*][ci:force] Fixing rebase

* [affected:*][ci:force] Wrong setting page

* [affected:*][ci:force] Upgrading material selector class

* [affected:*][ci:force] Fixed lint

* [affected:*][ci:force] Fixed lint

* [affected:*][ci:force] Fixed e2e with new notation

* [affected:*][ci:force] Fixed e2e with new notation

* [affected:*][ci:force] Fixed e2e with new notation

* [affected:*][ci:force] [AAE-21070] Fix e2e Content: Components - C587084 - fix class selectors

* [affected:*][ci:force] Fixed lint after error on important

* Improvement/AAE-19176-reapply-selector-changes (#9424)

* AAE-19510 remove selector variable

* AAE-19510 poc for card view using variable selectors

* AAE-19176 rename mat selectors file

* AAE-19176 add missing style imports

* AAE-19176 remove remaining mat selectors

* AAE-19176 replaced todo material selectors with variables

* AAE-19176 changes made in meantime

* AAE-19176 conflict fixes

* [AAE-21083] Fix e2e Content: Metadata - C245652 - fix tab active selector

* Fix selector after merging https://github.com/Alfresco/alfresco-ng2-components/pull/9424, .mat-content-actions was replaced by .adf-start-process-content-actions

* Fix lint issue

* [AAE-21083] Fix e2e Content: Metadata - C280560 - fix slide toggle click, in v15 toggle is handled with a button instead of input

* [affected:*][ci:force] Fixed check on expansion panel filter

* [affected:*][ci:force] Fixed check on expansion panel filter

* [affected:*][ci:force] Fixed other e2es

* [affected:*][ci:force] Fixing e2e - the long painful journey

* [affected:*][ci:force] Fixing e2e - the long painful journey - part II

* [AAE-21084] Fix e2e Content: Upload and Versioning - C279992 - fix enable togle selector

* [AAE-21085] Fix e2e Search - revert to previous version, text should be written without pressing eneter to show the autocomplete list items

* [AAE-21085] Fix e2e Search - add content selector that wrap text

* [affected:*][ci:force] Fixing e2e - the lord of E2E

* [AAE-21089] Fix e2e Search - fix checkbox selector

* [affected:*][ci:force] Fixing e2e - the lord of E2E

* [affected:*][ci:force] Fixing e2e - the return of the fail

* [affected:*][ci:force] Fixing e2e - the return of the fail

* [affected:*][ci:force] Fixing e2e - the eternal fail

* [affected:*][ci:force] Remove fit

* [affected:*][ci:force] Fixing e2e - fixing the last ones

* [affected:*][ci:force] attempt to fix mat-selectors importing

* [affected:*][ci:force] Fixing the styles - check

* [affected:*][ci:force] Added pretheme for core as it is mandatory when publishing and rebuilding

* [affected:*][ci:force] - REBASED

* [ACS-7359] - Angular 15 - Edit aspects modal [ACA] (#9488)

* [affected:*][ci:force] - REBASED

* [affected:*][ci:force] - REBASED

* [affected:*][ci:force] - Rebased and added an extra fix for after

* [affected:*][ci:force] - Funny imports

* [ACS-7373] ng15 permissions page fixes

* [ACS-7373] mat-icon-buttons

* [ACS-7452] - Small screen notification banner [ACS-7418] About page (#9507)

* [ACS-7413] Dialog height and spacing issues (#9515)

* [ACS-7446] - Upload progress box issues

* [ACS-7414] - Manage versions dialog

* [ACS-7375] - Share link dialog issues

* Fixed errors on unit and lint

* Re Enabling unit test removed

* Fixing unit test after last rebase + lint

* Fixing unit test after last rebase + lint

* Fixing unit test after last rebase + lint

* [ACS-7419] Fix broken styling of notifications

* [ACS-7419] Fix broken styling of notifications, apply pr remarks

* [ACS-7419] Fix broken styling of notifications, apply pr remarks

* [ACS-7419] Fix broken styling of notifications, apply pr remarks

* Extra parentesys lint

* [ACS-7528] - Notification and user icons are a bit different (#9540)

* [ACS-7532] - Click on chip in search gives redundant icon (#9544)

* [ACS-7530] - Notifications popup looks a bit differently (#9543)

* [ACS-7414] - manage versions dialog (#9545)

* [ACS-7535][ACS-7537][ACS-7536][ACA] Move/Copy dialogs, Share dialog, Aspects dialog (#9553)

* AAE-21697 Fix people form widget style (#9555)

* [affected:*][ci:force] - Rebased

* [affected:*][ci:force] - Fixed problem after rebase

* [ACS-7519] - Login page (#9565)

* [ACS-7331] - View details sidebar (#9455)

* [ACS-7542] - Upload new version dialog (#9572)

* [ACS-7542] - Upload new version dialog

* [ACS-7542] - Upload new version dialog

* [ACS-7575] create library dialog fixes (#9574)

* [ACS-7534] create/edit folder dialog fixes (#9575)

* Rebased ADF Migration PR

* Rebased ADF Migration PR

* Sync lock

* [ACS-7681] Bell icon not aligned [ACS-7571] Comments [ACS-7563] Add permission dialog (#9594)

* [ACS-7554] Fix tags in column display (#9597)

* Fixed unit test

* AAE-21256 Fix form widget styles (#9599)

* [ACS-7555] column filters (#9576)

* Changed ng version before material migration

* migration for material'

* Upgrading NX and start fixing styles

* Make all the part build

* Fixed core unit test and excluded instable ones

* Fixed most of unit tests failing

* Fixed unit tests

* Fixed last unit tests

* fixed unit test problem and some other e2e

* Fixed unit tests after rebase

* [AAE-18267] change unit test setup for auth service (#9216)

* [AAE-18267] change unit test setup for auth service

* [AAE-18267] remove exclude

* [AAE-18267] removed CoreTestingModule from imports

* remaining unit test fixes for the Angular 15 update (#9218)

* removing excludes from working tests

* test fixes for CategoriesManagementComponent

* [ci:force] reenabling tests / fixes

* fixes in process-services-cloud

* change html element type

* fix selector in StartProcessComponent

* Fixing unit test after last rebase + lint

* ACS-7555 Fixed styles for node type filters

* ACS-7555 Removed redundant padding

* ACS-7555 Outlined input for text filter

* ACS-7555 Resolved conflicts

---------

Co-authored-by: Vito Albano <vito.albano@hyland.com>
Co-authored-by: Wojciech Duda <69160975+wojd0@users.noreply.github.com>

* AAE-21393 Fix amount form widget style (#9601)

* AAE-21392 Fix dropdown form widget style (#9605)

* [ACS-7582] Upload dialog button display fix (#9603)

* [ACS-7531] - Search page (#9606)

* rebased to last develop

* Fixed SonarCloud complaints

* Fixed SonarCloud complaints

* Fixing some sonarcloud comments

* [ACS-7572] link rules dialog fixes (#9607)

* AAE-21703 Fix group widget style (#9612)

* AAE-21703 Fix group form widget style

* AAE-21703 Improve tests

* [ACS-7533] - Advanced search chips dropdowns (#9618)

* [ACS-7560] undo deletion notification (#9632)

* ACS-7560 Fixed margin around snackbar and size of x icon

* ACS-7560 Fixed styles for info snackbar

* Rebased to the latest develop

* Rebased to the latest

* Skipped failing unit tests

* Updated today date selector

* rebased

* Fixed process unit test fail

* fix folder-edit license headers

* fix FolderEditDirective unit tests

* AAE-21937 Fix context menu list component (#9658)

* Fixed broken unit test after rebase

* ACS-7561 - permissions page (#9675)

* Trying to fix the long failing e2ea

* Missed import

* Fixed changed unit test

* Fixed property e2e

* Updated calendar selector

* [ACS-7768] unify inputs and selects across the app (#9687)

* Changed ng version before material migration

* migration for material'

* Fixed most of unit tests failing

* [affected:*][ci:force] Fixing rebase

* [affected:*][ci:force] attempt to fix mat-selectors importing

* [affected:*][ci:force] Fixing the styles - check

* AAE-21392 Fix dropdown form widget style (#9605)

* ACS-7768 Applied new styles for inputs

* ACS-7768 Align icon

* ACS-7768 Input colors based on input state

* ACS-7768 Corrected spaces

* ACS-7768 Styles for selectboxes

* ACS-7768 Fixed label jumping on hovering

* ACS-7768 Style inputs for add permission panel, user role column and comments, styles for inputs without label

* ACS-7768 Style inputs in search filters

* ACS-7768 Set appearance for inputs globally to outline

* ACS-7768 Style inputs for share dialog and login page

* ACS-7768 Style inputs in properties panel

* ACS-7768 Fixed white background when disabled field

* ACS-7768 Moved setting outline appearance for inputs to ACA, fix issue for inputs in permission container

* Revert "[affected:*][ci:force] Fixing the styles - check"

This reverts commit 80d971f7ab.

* Revert "[affected:*][ci:force] attempt to fix mat-selectors importing"

This reverts commit 821d9e1864.

* Revert "[affected:*][ci:force] Fixing rebase"

This reverts commit 378c6c2000.

* Revert "Fixed most of unit tests failing"

This reverts commit 44948e0a28.

* ACS-7768 Reverted unwanted changes

---------

Co-authored-by: Vito Albano <vito.albano@hyland.com>
Co-authored-by: Diogo Bastos <50139916+DiogoABastos@users.noreply.github.com>

* [ACS-7768] unify inputs and selects across the app - revert (#9699)

* Revert "[ACS-7768] unify inputs and selects across the app (#9687)"

This reverts commit 7cfb5ea64a.

* ACS-7768 Little correction

* [ACS-7998] - Add permissions input (#9704)

* [ACS-8004] Fix inputs for move folder (#9707)

* [ACS-7999] Fix inputs for edit and create folder (#9713)

* ACS-7999 Fix inputs for edit and create folder

* ACS-7999 Fix jumping dialog when focus field

* [ACS-7982] ACC - fix categories tree (#9715)

* Fixed after rebase

* Fixed package-lock

* Fixed after rebase

* Fixed unit test for process

* AAE-22783 Fix form elements label style (#9725)

* [ACS-8021] Inputs for comments (#9722)

* [ACS-8008] - Inputs for properties panel "General info" (#9744)

* [ACS-8052] Inputs for general info for libraries (#9745)

* [ACS-7983] Fixed security controls dialog (#9747)

* [ACS-8026] Fixed task form rendering (#9742)

* [ACS-8026] Fixed Task form rendering

* [ACS-8026] Fixed task form rendering

* [ACS-8042] Fixed styles for inputs in library creation (#9751)

* Added missing import for uppercase pipe (#9748)

* Recreated package-lock

* Fixed package and e2e with tabs that now are capital letters?

* Fixed package json

* Removed wrong version on core package

* Ehi Js-Api should be 7.8 NOT 7.9

* These dependencies will kill me

* [ACS-7981] UI fixes for create categories dialog (#9754)

* [ACS-7981] Fixed UI for create categories dialog

* [ACS-7981] Adding mat selectors for create categories dialog

* [ACS-7981] Create category dialog no longer allows ability to add existing categories

* [ACS-7974] Adding material selectors for assign security marks dialog (#9755)

* [ACS-7974] Fixed UI for assign security controls to user dialog

* [ACS-7974] Removing unneeded mat selector

* [ACS-8069] Updated error-content.component.html to be aligned with the new mat typography classes in angular material v15 (#9762)

* Added missing mat selector for mat-list-item-disabled (#9763)

* Fixed process unit test after huge rebase

* [ACS-8066] Style inputs for link rule dialog (#9773)

* Insight material module has been removed

* [ACS-7973] [ACC] header layout (#9782)

* [ACS-8096] Print button in the viewer does not open the print window (#9776) (#9778)

* [ACS-8066] Fixed unit tests (#9783)

* [ACS-8092] [ACA] testing angular 15 notifications bell is much smaller and is further from the profile page 2 (#9786)

* AAE 22837 Move confirm to core (#9750)

* confirm dialog is used in many places and should be part of the core

* fix

* Update confirm.dialog.spec.ts

* Update public-api.ts

* Fixed imports for confirm dialog unit tests

* Fixed linting for packages

* Removed -mdc as it's wrong for mat calendar

* [ACS-8098] [ACA] Testing Angular 15 - Move Popup placeholder missing (#9796)

* [ACS-7944] [ADW] Start process page (#9802)

* [ACS-8157] Used mat chip set instead of mat chip listbox for dynamic chip list to hide tick icon for chips (#9803)

* Fixed issue on focus mat calendar

* [ACS-7980] fix style (#9798)

* [ACS-7979] Fixed UI for create tags dialog (#9793)

* [ACS-7979] Fixed UI for create tags dialog. Minor UI fixes of create categories dialog as well

* [ACS-7979] Fixed unit tests

* [ACS-7979] Replaced dependency of CoreModule from tag.module.ts with TranslateModule and DynamicChipListModule

* [ACS-8158] Fixed spacing of tags in ACA (#9808)

* [ACS-8158] Fixed spacing of tags in ACA

* [ACS-8158] Fixed unit tests

* AAE-22965 fix datepicker focused element selector (#9814)

* [ACS-8212] Fixed alignment issue of filters button in sidenav (#9828)

* [ACS-8191] Added missing mat selectors for ACA. Updated mat selector name (#9809)

* [ACS-8191] Updated mat selector names

* [ACS-8191] Added missing mat selectors for ACA. Updated mat-selector names

* [ACS-8196] fix style for pagination (#9810)

* Removing implicitFlow in favor of codeFlow

* [ACS-8230] Fixed UI for snackbars with long text content and action buttons (#9830)

* [ACS-8231] [ADW] Processes button styling on hover- edit summary (#9833)

[ADW] Processes button styling on hover

* Revert "Removing implicitFlow in favor of codeFlow"

This reverts commit 58951a77b8.

* Fixed unit test after rebase

* Fixing unit test

* Disabled failing unit from content

* AAE-23287 migrate to storybook 8 (#9867)

* Fixed core unit test and excluded instable ones

* AAE-23287 migrate to storybook 8

---------

Co-authored-by: Vito Albano <vito.albano@hyland.com>

* Fixed unit and lint

* Fixing unit test and lint issues after merging with storybook latest

* Storybook still not working though

* Fixed missing locator for content e2e

* fix storybook exceeding timeout

* Fixed wrong package version

* AAE-23478 replace nav-list with action-list (#9875)

* [ACS-8272] [ADW] Testing Angular 15 - Misplaced buttons Cancel and Start process (#9869)

* [ACS-8273] [ADW] Testing Angular 15 - Process' tab names are uppercased (#9870)

* [ACS-8274] angular 15 description field in info drawer is truncated and scrollable (#9878)

* [ACS-8275] - [ACA] Testing Angular 15 - Tags are not displayed correctly (#9872)

* Fixing e2e tab label

* AAE-22858 Fix date button style (#9892)

* AAE-23556 Fix search text input component styles (#9895)

* Fixing unit test an builds

* Fixing style

* [ACS-8260] add user dialog misplaced search icon and space issue (#9897)

* [ACS-8275] [ACA] Angular 15 tags are not displayed correctly (#9896)

* [ACS-8322] Testing Angular 15 - Info Drawer - General info - Missing … (#9901)

* [ACS-8322] Testing Angular 15 - Info Drawer - General info - Missing arrow in Content type selector

* [ACS-8322] Testing Angular 15 - Info Drawer - General info - Missing arrow in Content type selector

* [AAE-23622] fixed buttons and chips (#9913)

* Aae 23572 recreate js api lib into a proper nx workspace lib bis (#9917)

* back to mocha, working in future node versions

* update package-lock

* change bundle to build

* update node to 18.20.3 [ci:force]

* fix e2es [ci:force]

* bring bundle back to fix e2e [ci:force]

* patch in legacy builds

* Updated package-lock

* Updated executor to new @nx

* Revert "Updated executor to new @nx"

This reverts commit a520ba3595.

* Improved ts config reverted changes on @nrwl

---------

Co-authored-by: Wojciech Duda <69160975+wojd0@users.noreply.github.com>

* Fixing target name for publishing js-api as it's not happening anymore

* fixed js-api publish command

* JS-api wasn't building correctly on publish

* Fixed naming for tests tab

* Fixed tabs name missed

* AAE-23704 Fixed outcome buttons text alignment (#9933)

* Thanks tooltip change

* Removing FIT :O

* Fixing build broken

* [ACS-8275] Testing Angular 15 - Tags are not displayed correctly (#9940)

* [ACS-8253] viewer file name change position on navigation (#9900)

* AAE-23783 Fixed feature flags dialog styles (#9945)

* Added styles include path to feature flags lib

* Fixed js-api version

---------

Co-authored-by: Wojciech Duda <69160975+wojd0@users.noreply.github.com>
Co-authored-by: Amedeo Lepore <amedeo.lepore85@gmail.com>
Co-authored-by: Amedeo Lepore <amedeo.lepore@hyland.com>
Co-authored-by: jacekpluta <73617938+jacekpluta@users.noreply.github.com>
Co-authored-by: Mykyta Maliarchuk <maliarchuk99@gmail.com>
Co-authored-by: tomson <tomasz.nastaly@hyland.com>
Co-authored-by: DominikIwanek <dominik.iwanek@hyland.com>
Co-authored-by: Jacek Pluta <jacek.pluta@hyland.com>
Co-authored-by: dominikiwanekhyland <141320833+dominikiwanekhyland@users.noreply.github.com>
Co-authored-by: Diogo Bastos <50139916+DiogoABastos@users.noreply.github.com>
Co-authored-by: Mykyta Maliarchuk <84377976+nikita-web-ua@users.noreply.github.com>
Co-authored-by: AleksanderSklorz <115619721+AleksanderSklorz@users.noreply.github.com>
Co-authored-by: Ehsan Rezaei <ehsan.rezaei@hyland.com>
Co-authored-by: swapnil-verma-gl <92505353+swapnil-verma-gl@users.noreply.github.com>
Co-authored-by: Eugenio Romano <eromano@users.noreply.github.com>
Co-authored-by: tamaragruszka <156320606+tamaragruszka@users.noreply.github.com>
Co-authored-by: tomasz hanaj <12088991+tomaszhanaj@users.noreply.github.com>
This commit is contained in:
Vito Albano
2024-07-19 09:27:15 +01:00
committed by GitHub
parent eda03ed525
commit 68ab2c67fd
536 changed files with 18952 additions and 32894 deletions

View File

@@ -1,6 +1,7 @@
<div class="adf-app-listgrid">
<div class="adf-app-listgrid-item">
<mat-card
appearance="outlined"
tabindex="0"
role="button"
class="adf-app-listgrid-item-card"

View File

@@ -15,24 +15,27 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { AppDetailsCloudComponent } from './app-details-cloud.component';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { AppListCloudModule } from '../app-list-cloud.module';
import { fakeApplicationInstance } from '../mock/app-model.mock';
import { importProvidersFrom } from '@angular/core';
export default {
component: AppDetailsCloudComponent,
title: 'Process Services Cloud/App List Cloud/App Details Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, AppListCloudModule]
imports: [AppListCloudModule]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
applicationInstance: {
control: 'object',
defaultValue: fakeApplicationInstance[0],
table: {
type: { summary: 'ApplicationInstanceModel' }
}
@@ -42,11 +45,14 @@ export default {
description: 'Emitted when an app entry is clicked.',
table: { category: 'Actions' }
}
},
args: {
applicationInstance: fakeApplicationInstance[0]
}
} as Meta;
} as Meta<AppDetailsCloudComponent>;
const template: Story<AppDetailsCloudComponent> = (args: AppDetailsCloudComponent) => ({
const template: StoryFn<AppDetailsCloudComponent> = (args) => ({
props: args
});
export const appDetailsCloud = template.bind({});
export const AppDetailsCloud = template.bind({});

View File

@@ -15,24 +15,27 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { AppListCloudModule } from '../app-list-cloud.module';
import { AppListCloudComponent } from './app-list-cloud.component';
import { importProvidersFrom } from '@angular/core';
export default {
component: AppListCloudComponent,
title: 'Process Services Cloud/App List Cloud/App List Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, AppListCloudModule]
imports: [AppListCloudModule]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
layoutType: {
control: 'radio',
options: ['GRID', 'LIST'],
defaultValue: 'GRID',
description: 'Defines the layout of the apps.',
table: {
type: { summary: 'string' },
@@ -44,11 +47,14 @@ export default {
description: 'Emitted when an app entry is clicked.',
table: { category: 'Actions' }
}
},
args: {
layoutType: 'GRID'
}
} as Meta;
} as Meta<AppListCloudComponent>;
const template: Story<AppListCloudComponent> = (args) => ({
const template: StoryFn<AppListCloudComponent> = (args) => ({
props: args
});
export const appListCloud = template.bind({});
export const AppListCloud = template.bind({});

View File

@@ -1,5 +1,6 @@
<mat-form-field [floatLabel]="'auto'" [attr.data-automation-id]="processFilterProperty.key">
<mat-form-field floatLabel="auto" [attr.data-automation-id]="processFilterProperty.key">
<mat-label>{{ processFilterProperty.label | translate }}</mat-label>
<mat-select
placeholder="{{ processFilterProperty.label | translate }}"
[value]="type"
@@ -12,7 +13,7 @@
</mat-form-field>
<ng-container *ngIf="isDateRangeType()">
<mat-form-field [floatLabel]="'auto'" class="adf-cloud-date-range-picker">
<mat-form-field floatLabel="auto" class="adf-cloud-date-range-picker">
<mat-label>{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.DATE_RANGE_TITLE' | translate }}</mat-label>
<mat-date-range-input [formGroup]="dateRangeForm" [rangePicker]="picker">
<input matStartDate formControlName="from" placeholder="{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.LABEL.START_DATE' | translate }}">

View File

@@ -15,24 +15,27 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { mockFilterProperty } from '../mock/date-range-filter.mock';
import { ProcessCommonModule } from '../process-common.module';
import { DateRangeFilterComponent } from './date-range-filter.component';
import { importProvidersFrom } from '@angular/core';
export default {
component: DateRangeFilterComponent,
title: 'Process Services Cloud/Process Common/Date Range Filter',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, ProcessCommonModule]
imports: [ProcessCommonModule]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
processFilterProperty: {
control: 'object',
defaultValue: mockFilterProperty,
table: {
type: { summary: 'ApplicationInstanceModel' }
}
@@ -51,11 +54,14 @@ export default {
action: 'dateTypeChange',
table: { category: 'Actions' }
}
},
args: {
processFilterProperty: mockFilterProperty
}
} as Meta;
} as Meta<DateRangeFilterComponent>;
const template: Story<DateRangeFilterComponent> = (args: DateRangeFilterComponent) => ({
const template: StoryFn<DateRangeFilterComponent> = (args) => ({
props: args
});
export const dateRangeFilter = template.bind({});
export const DateRangeFilter = template.bind({});

View File

@@ -26,7 +26,6 @@ export const mockFilterProperty = {
_startTo: new Date().toISOString()
},
type: 'dateRange',
options: null,
attributes: {
dateType: 'createdDateType',
from: '_startFrom',

View File

@@ -31,7 +31,7 @@
</button>
</adf-toolbar>
<mat-card [class.adf-cloud-form-content-card]="displayMode === 'fullScreen'">
<mat-card appearance="outlined" [class.adf-cloud-form-content-card]="displayMode === 'fullScreen'">
<div class="adf-cloud-form-content-card-container">
<mat-card-header *ngIf="showTitle || showRefreshButton || showValidationIcon">
<mat-card-title>
@@ -69,7 +69,7 @@
>
</adf-form-renderer>
</mat-card-content>
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions">
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions" align="end">
<ng-content select="adf-cloud-form-custom-outcomes"></ng-content>
<ng-container *ngFor="let outcome of form.outcomes">
<button

View File

@@ -1,5 +1,8 @@
@import 'styles/mat-selectors';
/* cspell: disable-next-line */
/* stylelint-disable scss/at-extend-no-missing-placeholder */
.adf-full-screen {
width: 100%;
height: 100%;
@@ -31,8 +34,7 @@
}
&-toolbar {
/* stylelint-disable-next-line selector-class-pattern */
.mat-toolbar {
#{$mat-toolbar} {
background-color: var(--adf-theme-background-card-color-087);
}
}
@@ -74,15 +76,10 @@
flex-direction: column;
height: 100%;
mat-card-content {
#{$mat-card-content} {
height: 100%;
overflow: hidden auto;
}
mat-card-actions {
display: flex;
justify-content: flex-end;
}
}
}

View File

@@ -32,7 +32,8 @@ import {
UploadWidgetContentLinkModel,
WidgetVisibilityService,
provideTranslations,
AuthModule
AuthModule,
FormFieldEvent
} from '@alfresco/adf-core';
import { Node } from '@alfresco/js-api';
import { ESCAPE } from '@angular/cdk/keycodes';
@@ -46,7 +47,6 @@ import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable, of, throwError } from 'rxjs';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { FormCloudModule } from '../form-cloud.module';
import {
cloudFormMock,
@@ -65,6 +65,7 @@ import { ProcessServicesCloudModule } from '../../process-services-cloud.module'
import { MatButtonHarness } from '@angular/material/button/testing';
import { FormCloudDisplayMode } from '../../services/form-fields.interfaces';
import { CloudFormRenderingService } from './cloud-form-rendering.service';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
const mockOauth2Auth: any = {
@@ -1633,7 +1634,7 @@ describe('retrieve metadata on submit', () => {
it('should enable save button when form field value changed', () => {
formComponent.disableSaveButton = true;
formService.formFieldValueChanged.next();
formService.formFieldValueChanged.next({} as FormFieldEvent);
expect(formComponent.disableSaveButton).toBeFalse();
});

View File

@@ -31,17 +31,17 @@ import {
FormModel,
ContentLinkModel,
UploadWidgetContentLinkModel,
FormEvent
FormEvent,
ConfirmDialogComponent
} from '@alfresco/adf-core';
import { FormCloudService } from '../services/form-cloud.service';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmDialogComponent } from '@alfresco/adf-content-services';
import { v4 as uuidGeneration } from 'uuid';
import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../services/form-fields.interfaces';
import { DisplayModeService } from '../public-api';
import { FormCloudSpinnerService } from '../services/spinner/form-cloud-spinner.service';
import { DisplayModeService } from '../services/display-mode.service';
@Component({
selector: 'adf-cloud-form',

View File

@@ -15,28 +15,29 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { FormCloudModule } from '../form-cloud.module';
import { FormDefinitionSelectorCloudComponent } from './form-definition-selector-cloud.component';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { FormDefinitionSelectorCloudService } from '../services/form-definition-selector-cloud.service';
import { FormDefinitionSelectorCloudServiceMock } from '../mocks/form-definition-selector-cloud.service.mock';
import { importProvidersFrom } from '@angular/core';
export default {
component: FormDefinitionSelectorCloudComponent,
title: 'Process Services Cloud/Form Cloud/Form Definition Selector Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, FormCloudModule],
providers: [
{ provide: FormDefinitionSelectorCloudService, useClass: FormDefinitionSelectorCloudServiceMock }
]
imports: [FormCloudModule],
providers: [{ provide: FormDefinitionSelectorCloudService, useClass: FormDefinitionSelectorCloudServiceMock }]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
appName: {
control: 'text',
defaultValue: '',
description: 'Name of the application. If specified, this shows the users who have access to the app.',
table: {
type: { summary: 'string' },
@@ -48,11 +49,14 @@ export default {
description: 'Emitted when a form is selected.',
table: { category: 'Actions' }
}
},
args: {
appName: ''
}
} as Meta;
} as Meta<FormDefinitionSelectorCloudComponent>;
const template: Story<FormDefinitionSelectorCloudComponent> = (args: FormDefinitionSelectorCloudComponent) => ({
const template: StoryFn<FormDefinitionSelectorCloudComponent> = (args) => ({
props: args
});
export const formDefinitionSelectorCloud = template.bind({});
export const FormDefinitionSelectorCloud = template.bind({});

View File

@@ -79,9 +79,7 @@
cursor: pointer;
}
.adf-file {
margin-bottom: 0;
}
margin-bottom: 0;
}
&-attach-selected-file-row {

View File

@@ -2,17 +2,17 @@
<table mat-table [dataSource]="uploadedFiles" class="adf-properties-table adf-file-properties-table mat-elevation-z0" *ngIf="hasFile">
<ng-container matColumnDef="icon">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell class="adf-file-properties-table-cell" *matCellDef="let element">
<mat-icon mat-list-icon class="adf-datatable-selected"
*ngIf="selectedNode && element.id === selectedNode.id" (click)="onRowClicked(element)">
<td class="adf-file-properties-table-cell" mat-cell *matCellDef="let element">
<mat-icon matListItemLine class="adf-datatable-selected"
*ngIf="selectedNode && element.id === selectedNode.id" (click)="onRowClicked(element)">
check_circle
</mat-icon>
<img mat-list-icon class="adf-attach-widget__icon"
*ngIf="!selectedNode || element.id !== selectedNode.id" [id]="'file-'+element?.id+'-icon'"
(click)="onRowClicked(element)"
(keyup.enter)="onRowClicked(element)"
[src]="element.content ? getIcon(element.content.mimeType) : getIcon(element['mimeType'])"
[alt]="mimeTypeIcon" role="button" tabindex="0" />
<img matListItemLine class="adf-attach-widget__icon"
*ngIf="!selectedNode || element.id !== selectedNode.id" [id]="'file-'+element?.id+'-icon'"
(click)="onRowClicked(element)"
(keyup.enter)="onRowClicked(element)"
[src]="element.content ? getIcon(element.content.mimeType) : getIcon(element['mimeType'])"
[alt]="mimeTypeIcon" role="button" tabindex="0" />
</td>
</ng-container>

View File

@@ -6,7 +6,7 @@
<div>
<mat-list *ngIf="hasFile">
<mat-list-item class="adf-upload-files-row" *ngFor="let file of uploadedFiles">
<img mat-list-icon class="adf-upload-widget__icon" [id]="'file-'+file.id+'-icon'"
<img matListItemLine class="adf-upload-widget__icon" [id]="'file-'+file.id+'-icon'"
[src]="getIcon(file.content.mimeType)" [alt]="mimeTypeIcon" (click)="fileClicked(file)"
(keyup.enter)="fileClicked(file)" role="button" tabindex="0" />
<span class="adf-upload-widget__button" matLine id="{{'file-'+file.id}}" (click)="fileClicked(file)" (keyup.enter)="fileClicked(file)"

View File

@@ -1,7 +1,10 @@
/* stylelint-disable selector-class-pattern */
@import 'styles/mat-selectors';
.adf {
// eslint-disable-selector-class-pattern
&-date-widget {
/* stylelint-disable-next-line */
.mat-form-field-suffix {
#{$mat-form-field-suffix} {
top: 26px;
}
@@ -11,14 +14,11 @@
}
&-left-label-input-datepicker {
/* stylelint-disable-next-line */
.mat-form-field-suffix {
#{$mat-form-field-suffix} {
top: 0;
}
/* stylelint-disable-next-line */
.mat-form-field-infix {
#{$mat-form--text-field-infix} {
width: 100%;
}
}

View File

@@ -1,8 +1,7 @@
<div class="adf-dropdown-widget {{field.className}}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels">
<div>
<label class="adf-label" [class.adf-left-label]="field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk"
*ngIf="isRequired()">*</span></label>
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</div>
<div>
<adf-cloud-group [mode]="mode"
@@ -16,6 +15,7 @@
[preSelectGroups]="preSelectGroup"
(blur)="markAsTouched()"
[attr.title]="field.tooltip">
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id" label>{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</adf-cloud-group>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired() && isTouched()"

View File

@@ -1,24 +1,26 @@
<div class="adf-dropdown-widget {{field.className}}"
[class.adf-invalid]="!field.isValid && isTouched()" [class.adf-readonly]="field.readOnly" [class.adf-left-label-input-container]="field.leftLabels">
<div>
<label class="adf-label" [class.adf-left-label]="field.leftLabels" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<div *ngIf="field.leftLabels">
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</div>
<div>
<adf-cloud-people
[preSelectUsers]="preSelectUsers"
[appName]="appName"
[title]="title"
[readOnly]="field.readOnly"
[validate]="validate"
[searchUserCtrl]="search"
[required]="isRequired()"
(changedUsers)="onChangedUser($event)"
[roles]="roles"
[mode]="mode"
[groupsRestriction]="groupsRestriction"
(blur)="markAsTouched()"
[attr.title]="field.tooltip">
</adf-cloud-people>
[preSelectUsers]="preSelectUsers"
[appName]="appName"
[title]="title"
[readOnly]="field.readOnly"
[validate]="validate"
[searchUserCtrl]="search"
[required]="isRequired()"
(changedUsers)="onChangedUser($event)"
[roles]="roles"
[mode]="mode"
[groupsRestriction]="groupsRestriction"
(blur)="markAsTouched()"
[attr.title]="field.tooltip"
>
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id" label>{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
</adf-cloud-people>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired() && isTouched()"
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>

View File

@@ -1,9 +1,8 @@
<form>
<mat-form-field floatLabel="auto" class="adf-cloud-group" [class.adf-invalid]="hasError() && isDirty()">
<mat-label *ngIf="!isReadonly()" id="adf-group-cloud-title-id" class="adf-cloud-group-title"
[ngClass]="{'adf-cloud-group-title--focus': isFocused}">{{ (title || 'ADF_CLOUD_GROUPS.SEARCH-GROUP') | translate }}</mat-label>
<mat-chip-list #groupChipList [disabled]="isReadonly() || isValidationLoading()" data-automation-id="adf-cloud-group-chip-list">
<mat-chip
<mat-form-field class="adf-cloud-group" [class.adf-invalid]="hasError() && isDirty()">
<ng-content select="[label]"></ng-content>
<mat-chip-grid #groupChipList [disabled]="isReadonly() || isValidationLoading()" data-automation-id="adf-cloud-group-chip-list">
<mat-chip-row
*ngFor="let group of selectedGroups"
[removable]="!(group.readonly)"
[attr.data-automation-id]="'adf-cloud-group-chip-' + group.name"
@@ -15,17 +14,18 @@
matChipRemove [attr.data-automation-id]="'adf-cloud-group-chip-remove-icon-' + group.name">
cancel
</mat-icon>
</mat-chip>
<input *ngIf="!isReadonly()" matInput
</mat-chip-row>
<input [disabled]="isReadonly()" matInput
[formControl]="searchGroupsControl"
[matAutocomplete]="auto"
[matChipInputFor]="groupChipList"
[placeholder]="title | translate"
[required]="required"
(focus)="setFocus(true)"
(blur)="setFocus(false); markAsTouched()"
class="adf-group-input"
data-automation-id="adf-cloud-group-search-input" #groupInput>
</mat-chip-list>
</mat-chip-grid>
<mat-autocomplete
autoActiveFirstOption

View File

@@ -18,7 +18,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of } from 'rxjs';
import { ProcessServiceCloudTestingModule } from './../../testing/process-service-cloud.testing.module';
import { GroupCloudModule } from '../group-cloud.module';
import { GroupCloudComponent } from './group-cloud.component';
import { CoreTestingModule } from '@alfresco/adf-core';
@@ -27,7 +26,7 @@ import { IdentityGroupService } from '../services/identity-group.service';
import { mockFoodGroups, mockMeatChicken, mockVegetableAubergine } from '../mock/group-cloud.mock';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness, MatChipListHarness } from '@angular/material/chips/testing';
import { MatChipGridHarness, MatChipHarness } from '@angular/material/chips/testing';
import { MatIconHarness } from '@angular/material/icon/testing';
import { MatInputHarness } from '@angular/material/input/testing';
@@ -73,7 +72,7 @@ describe('GroupCloudComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, ProcessServiceCloudTestingModule, GroupCloudModule]
imports: [CoreTestingModule, GroupCloudModule]
});
fixture = TestBed.createComponent(GroupCloudComponent);
component = fixture.componentInstance;
@@ -83,13 +82,22 @@ describe('GroupCloudComponent', () => {
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should populate placeholder when title is present', () => {
it('should populate placeholder when title is present', async () => {
component.title = 'TITLE_KEY';
fixture.detectChanges();
const matLabel = element.querySelector<HTMLInputElement>('#adf-group-cloud-title-id');
expect(matLabel.textContent).toEqual('TITLE_KEY');
const inputElement = await loader.getHarness(MatInputHarness.with({ selector: '[data-automation-id="adf-cloud-group-search-input"]' }));
expect(await inputElement.getPlaceholder()).toEqual('TITLE_KEY');
});
it('should not populate placeholder when title is not present', async () => {
fixture.detectChanges();
const inputElement = await loader.getHarness(MatInputHarness.with({ selector: '[data-automation-id="adf-cloud-group-search-input"]' }));
expect(await inputElement.getPlaceholder()).toEqual('');
});
describe('Search group', () => {
@@ -350,7 +358,7 @@ describe('GroupCloudComponent', () => {
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(1);
const chipList = await loader.getHarness(MatChipListHarness);
const chipList = await loader.getHarness(MatChipGridHarness);
expect(await chipList.isDisabled()).toBe(true);
});
@@ -365,7 +373,7 @@ describe('GroupCloudComponent', () => {
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
const chipList = await loader.getHarness(MatChipListHarness);
const chipList = await loader.getHarness(MatChipGridHarness);
expect(await chipList.isDisabled()).toBe(true);
});
});

View File

@@ -15,29 +15,25 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { GroupCloudModule } from '../group-cloud.module';
import { GroupCloudComponent } from './group-cloud.component';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { IdentityGroupService } from '../services/identity-group.service';
import {
IdentityGroupServiceMock,
mockFoodGroups,
mockMeatChicken,
mockVegetableAubergine
} from '../mock/group-cloud.mock';
import { FormControl } from '@angular/forms';
const defaultFormControl = new FormControl({ value: '', disabled: false });
import { IdentityGroupServiceMock, mockFoodGroups, mockMeatChicken, mockVegetableAubergine } from '../mock/group-cloud.mock';
import { importProvidersFrom } from '@angular/core';
export default {
component: GroupCloudComponent,
title: 'Process Services Cloud/Group Cloud/Group Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, GroupCloudModule],
imports: [GroupCloudModule]
}),
applicationConfig({
providers: [
{ provide: IdentityGroupService, useClass: IdentityGroupServiceMock }
{ provide: IdentityGroupService, useClass: IdentityGroupServiceMock },
importProvidersFrom(ProcessServicesCloudStoryModule)
]
})
],
@@ -45,7 +41,6 @@ export default {
appName: {
control: 'text',
description: 'Name of the application. If specified this shows the groups who have access to the app.',
defaultValue: 'app',
table: {
type: { summary: 'string' }
}
@@ -53,7 +48,6 @@ export default {
title: {
control: 'text',
description: 'Title of the field.',
defaultValue: 'Groups',
table: {
type: { summary: 'string' }
}
@@ -62,7 +56,6 @@ export default {
control: 'radio',
options: ['single', 'multiple'],
description: 'Group selection mode.',
defaultValue: 'single',
table: {
type: { summary: 'ComponentSelectionMode' },
defaultValue: { summary: 'single' }
@@ -70,8 +63,8 @@ export default {
},
preSelectGroups: {
control: 'object',
description: 'Array of groups to be pre-selected. This pre-selects all groups in multi selection mode and only the first group of the array in single selection mode.',
defaultValue: [],
description:
'Array of groups to be pre-selected. This pre-selects all groups in multi selection mode and only the first group of the array in single selection mode.',
table: {
type: { summary: 'IdentityGroupModel[]' },
defaultValue: { summary: '[]' }
@@ -79,10 +72,10 @@ export default {
},
validate: {
control: 'boolean',
description: 'This flag enables the validation on the preSelectGroups passed as input.\n\n'+
'In case the flag is true the components call the identity service to verify the validity of the information passed as input.\n\n'+
'Otherwise, no check will be done.',
defaultValue: false,
description:
'This flag enables the validation on the preSelectGroups passed as input.\n\n' +
'In case the flag is true the components call the identity service to verify the validity of the information passed as input.\n\n' +
'Otherwise, no check will be done.',
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' }
@@ -91,7 +84,6 @@ export default {
readOnly: {
control: 'boolean',
description: 'Show the info in readonly mode.',
defaultValue: false,
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' }
@@ -100,7 +92,6 @@ export default {
required: {
control: 'boolean',
description: 'Mark this field as required.',
defaultValue: false,
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' }
@@ -109,7 +100,6 @@ export default {
groupChipsCtrl: {
control: 'object',
description: 'FormControl to list of group.',
mapping: { default: defaultFormControl },
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
@@ -119,7 +109,6 @@ export default {
searchGroupsControl: {
control: 'object',
description: 'FormControl to search the group.',
mapping: { default: defaultFormControl },
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
@@ -129,7 +118,6 @@ export default {
roles: {
control: 'object',
description: 'Role names of the groups to be listed.',
defaultValue: [],
table: {
type: { summary: 'string[]' },
defaultValue: { summary: '[]' }
@@ -155,38 +143,41 @@ export default {
description: 'Emitted when an warning occurs.',
table: { category: 'Actions' }
}
},
args: {
appName: 'app',
title: 'Groups',
mode: 'single',
preSelectGroups: [],
validate: false,
readOnly: false,
required: false,
roles: []
}
} as Meta;
} as Meta<GroupCloudComponent>;
const template: Story<GroupCloudComponent> = (args: GroupCloudComponent) => ({
const template: StoryFn<GroupCloudComponent> = (args) => ({
props: args
});
export const defaultGroupCloud = template.bind({});
defaultGroupCloud.args = {
groupChipsCtrl: 'default',
searchGroupsControl: 'default'
};
export const DefaultGroupCloud = template.bind({});
export const validPreselectedGroups = template.bind({});
validPreselectedGroups.args = {
...defaultGroupCloud.args,
export const ValidPreselectedGroups = template.bind({});
ValidPreselectedGroups.args = {
validate: true,
mode: 'multiple',
preSelectGroups: mockFoodGroups
};
export const mandatoryPreselectedGroups = template.bind({});
mandatoryPreselectedGroups.args = {
...defaultGroupCloud.args,
export const MandatoryPreselectedGroups = template.bind({});
MandatoryPreselectedGroups.args = {
validate: true,
mode: 'multiple',
preSelectGroups: [mockVegetableAubergine, { ...mockMeatChicken, readonly: true }]
};
export const invalidPreselectedGroups = template.bind({});
invalidPreselectedGroups.args = {
...defaultGroupCloud.args,
export const InvalidPreselectedGroups = template.bind({});
InvalidPreselectedGroups.args = {
validate: true,
mode: 'multiple',
preSelectGroups: [{ id: 'invalid-group', name: 'Invalid Group' }]

View File

@@ -16,7 +16,7 @@
*/
import { TestBed } from '@angular/core/testing';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { IdentityGroupService } from './identity-group.service';
import {
mockHttpErrorResponse,
@@ -26,6 +26,7 @@ import {
} from '../mock/identity-group.service.mock';
import { mockFoodGroups } from '../mock/group-cloud.mock';
import { AdfHttpClient } from '@alfresco/adf-core/api';
import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('IdentityGroupService', () => {
let service: IdentityGroupService;
@@ -34,7 +35,8 @@ describe('IdentityGroupService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule]
imports: [TranslateModule.forRoot(), HttpClientTestingModule],
providers: [IdentityGroupService]
});
service = TestBed.inject(IdentityGroupService);
adfHttpClient = TestBed.inject(AdfHttpClient);

View File

@@ -21,7 +21,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatNativeDateModule, MatOptionModule, MatRippleModule } from '@angular/material/core';
import { MatNativeDateModule, MatRippleModule, MatOptionModule } from '@angular/material/core';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';

View File

@@ -1,9 +1,8 @@
<form>
<mat-form-field floatLabel="auto" class="adf-people-cloud" [class.adf-invalid]="hasError() && isDirty()">
<mat-label *ngIf="!isReadonly()" id="adf-people-cloud-title-id" class="adf-people-cloud-title"
[ngClass]="{'adf-people-cloud-title--focus': isFocused}">{{ title | translate }}</mat-label>
<mat-chip-list #userMultipleChipList [disabled]="isReadonly() || isValidationLoading()" data-automation-id="adf-cloud-people-chip-list">
<mat-chip
<mat-form-field [floatLabel]="'auto'" class="adf-people-cloud" [class.adf-invalid]="hasError() && isDirty()">
<ng-content select="[label]"></ng-content>
<mat-chip-grid #userMultipleChipList [disabled]="isReadonly() || isValidationLoading()" data-automation-id="adf-cloud-people-chip-list">
<mat-chip-row
*ngFor="let user of selectedUsers"
[removable]="!(user.readonly)"
[attr.data-automation-id]="'adf-people-cloud-chip-' + user.username"
@@ -16,17 +15,19 @@
[attr.data-automation-id]="'adf-people-cloud-chip-remove-icon-' + user.username">
cancel
</mat-icon>
</mat-chip>
<input *ngIf="!isReadonly()" matInput
</mat-chip-row>
<input [disabled]="isReadonly()" matInput
#chipInput
[formControl]="searchUserCtrl"
[matAutocomplete]="auto"
[matChipInputFor]="userMultipleChipList"
[placeholder]="title | translate"
[required]="required"
(focus)="setFocus(true)"
(blur)="setFocus(false); markAsTouched()"
class="adf-cloud-input"
data-automation-id="adf-people-cloud-search-input" #userInput>
</mat-chip-list>
</mat-chip-grid>
<mat-autocomplete autoActiveFirstOption class="adf-people-cloud-list"
#auto="matAutocomplete"

View File

@@ -28,7 +28,7 @@ import { IDENTITY_USER_SERVICE_TOKEN } from '../services/identity-user-service.t
import { mockFoodUsers, mockKielbasaSausage, mockShepherdsPie, mockYorkshirePudding, mockPreselectedFoodUsers } from '../mock/people-cloud.mock';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness, MatChipListHarness } from '@angular/material/chips/testing';
import { MatChipGridHarness, MatChipHarness } from '@angular/material/chips/testing';
import { MatInputHarness } from '@angular/material/input/testing';
describe('PeopleCloudComponent', () => {
@@ -96,17 +96,17 @@ describe('PeopleCloudComponent', () => {
component.title = 'TITLE_KEY';
fixture.detectChanges();
const matLabel = element.querySelector<HTMLInputElement>('#adf-people-cloud-title-id');
const inputElement = element.querySelector<HTMLInputElement>('[data-automation-id="adf-people-cloud-search-input"]');
expect(matLabel.textContent).toEqual('TITLE_KEY');
expect(inputElement.placeholder).toEqual('TITLE_KEY');
});
it('should not populate placeholder when title is not present', () => {
fixture.detectChanges();
const matLabel = element.querySelector<HTMLInputElement>('#adf-people-cloud-title-id');
const inputElement = element.querySelector<HTMLInputElement>('[data-automation-id="adf-people-cloud-search-input"]');
expect(matLabel.textContent).toEqual('');
expect(inputElement.placeholder).toEqual('');
});
describe('Search user', () => {
@@ -406,7 +406,7 @@ describe('PeopleCloudComponent', () => {
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(1);
const chipList = await loader.getHarness(MatChipListHarness);
const chipList = await loader.getHarness(MatChipGridHarness);
expect(await chipList.isDisabled()).toBe(true);
});
@@ -421,7 +421,7 @@ describe('PeopleCloudComponent', () => {
const chips = await loader.getAllHarnesses(MatChipHarness);
expect(chips.length).toBe(2);
const chipList = await loader.getHarness(MatChipListHarness);
const chipList = await loader.getHarness(MatChipGridHarness);
expect(await chipList.isDisabled()).toBe(true);
});
});

View File

@@ -15,30 +15,25 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { PeopleCloudComponent } from './people-cloud.component';
import { PeopleCloudModule } from '../people-cloud.module';
import { ProcessServicesCloudStoryModule } from '../../testing/process-services-cloud-story.module';
import { IdentityUserService } from '../services/identity-user.service';
import {
IdentityUserServiceMock,
mockFoodUsers,
mockKielbasaSausage,
mockShepherdsPie,
mockYorkshirePudding
} from '../mock/people-cloud.mock';
import { FormControl } from '@angular/forms';
const defaultFormControl = new FormControl({ value: '', disabled: false });
import { IdentityUserServiceMock, mockFoodUsers, mockKielbasaSausage, mockShepherdsPie, mockYorkshirePudding } from '../mock/people-cloud.mock';
import { importProvidersFrom } from '@angular/core';
export default {
component: PeopleCloudComponent,
title: 'Process Services Cloud/People Cloud/People Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, PeopleCloudModule],
imports: [PeopleCloudModule]
}),
applicationConfig({
providers: [
{ provide: IdentityUserService, useClass: IdentityUserServiceMock }
{ provide: IdentityUserService, useClass: IdentityUserServiceMock },
importProvidersFrom(ProcessServicesCloudStoryModule)
]
})
],
@@ -46,7 +41,6 @@ export default {
appName: {
control: 'text',
description: 'Name of the application. If specified, this shows the users who have access to the app.',
defaultValue: 'app',
table: {
type: { summary: 'string' }
}
@@ -55,7 +49,6 @@ export default {
control: 'radio',
options: ['single', 'multiple'],
description: 'User selection mode.',
defaultValue: 'single',
table: {
type: { summary: 'ComponentSelectionMode' },
defaultValue: { summary: 'single' }
@@ -64,7 +57,6 @@ export default {
roles: {
control: 'object',
description: 'Role names of the users to be listed.',
defaultValue: [],
table: {
type: { summary: 'string[]' },
defaultValue: { summary: '[]' }
@@ -72,10 +64,10 @@ export default {
},
validate: {
control: 'boolean',
description: 'This flag enables the validation on the preSelectUsers passed as input.\n\n'+
'In case the flag is true the components call the identity service to verify the validity of the information passed as input.\n\n'+
'Otherwise, no check will be done.',
defaultValue: false,
description:
'This flag enables the validation on the preSelectUsers passed as input.\n\n' +
'In case the flag is true the components call the identity service to verify the validity of the information passed as input.\n\n' +
'Otherwise, no check will be done.',
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' }
@@ -84,7 +76,6 @@ export default {
readOnly: {
control: 'boolean',
description: 'Show the info in readonly mode.',
defaultValue: false,
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' }
@@ -93,7 +84,6 @@ export default {
required: {
control: 'boolean',
description: 'Mark this field as required.',
defaultValue: false,
table: {
type: { summary: 'boolean' },
defaultValue: { summary: 'false' }
@@ -101,8 +91,8 @@ export default {
},
preSelectUsers: {
control: 'object',
description: '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',
defaultValue: [],
description:
'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',
table: {
type: { summary: 'IdentityUserModel[]' },
defaultValue: { summary: '[]' }
@@ -111,7 +101,6 @@ export default {
excludedUsers: {
control: 'object',
description: 'Array of users to be excluded. Mandatory properties are: id, email, username',
defaultValue: [],
table: {
type: { summary: 'IdentityUserModel[]' },
defaultValue: { summary: '[]' }
@@ -120,7 +109,6 @@ export default {
groupsRestriction: {
control: 'object',
description: 'Array of groups to restrict user searches. Mandatory property is group name',
defaultValue: [],
table: {
type: { summary: 'string[]' },
defaultValue: { summary: '[]' }
@@ -129,7 +117,6 @@ export default {
userChipsCtrl: {
control: 'object',
description: 'FormControl to list of users.',
mapping: { default: defaultFormControl },
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
@@ -139,7 +126,6 @@ export default {
searchUserCtrl: {
control: 'object',
description: 'FormControl to search the user.',
mapping: { default: defaultFormControl },
table: {
type: { summary: 'FormControl' },
defaultValue: { summary: 'new FormControl({ value: \'\', disabled: false })' },
@@ -173,60 +159,58 @@ export default {
description: 'Emitted when an warning occurs.',
table: { category: 'Actions' }
}
},
args: {
appName: 'app',
mode: 'single',
roles: [],
validate: false,
readOnly: false,
required: false,
preSelectUsers: [],
excludedUsers: [],
groupsRestriction: []
}
} as Meta;
} as Meta<PeopleCloudComponent>;
const template: Story<PeopleCloudComponent> = (args: PeopleCloudComponent) => ({
const template: StoryFn<PeopleCloudComponent> = args => ({
props: args
});
export const defaultPeopleCloud = template.bind({});
defaultPeopleCloud.args = {
userChipsCtrl: 'default',
searchUserCtrl: 'default'
};
export const DefaultPeopleCloud = template.bind({});
export const validPreselectedUsers = template.bind({});
validPreselectedUsers.args = {
...defaultPeopleCloud.args,
export const ValidPreselectedUsers = template.bind({});
ValidPreselectedUsers.args = {
validate: true,
mode: 'multiple',
preSelectUsers: mockFoodUsers
};
export const mandatoryPreselectedUsers = template.bind({});
mandatoryPreselectedUsers.args = {
...defaultPeopleCloud.args,
export const MandatoryPreselectedUsers = template.bind({});
MandatoryPreselectedUsers.args = {
validate: true,
mode: 'multiple',
preSelectUsers: [{ ...mockKielbasaSausage, readonly: true }, mockShepherdsPie]
};
export const invalidPreselectedUsers = template.bind({});
invalidPreselectedUsers.args = {
...defaultPeopleCloud.args,
export const InvalidPreselectedUsers = template.bind({});
InvalidPreselectedUsers.args = {
validate: true,
mode: 'multiple',
preSelectUsers: [{ id: 'invalid-user', username: 'Invalid User', firstName: 'Invalid', lastName: 'User', email: 'invalid@xyz.com' }]
};
export const excludedUsers = template.bind({});
excludedUsers.args = {
...defaultPeopleCloud.args,
excludedUsers: [
mockKielbasaSausage,
mockYorkshirePudding
]
export const ExcludedUsers = template.bind({});
ExcludedUsers.args = {
excludedUsers: [mockKielbasaSausage, mockYorkshirePudding]
};
export const noUsers = template.bind({});
noUsers.args = {
...defaultPeopleCloud.args,
export const NoUsers = template.bind({});
NoUsers.args = {
excludedUsers: mockFoodUsers
};
export const invalidOrEmptyAppName = template.bind({});
invalidOrEmptyAppName.args = {
...defaultPeopleCloud.args,
export const InvalidOrEmptyAppName = template.bind({});
InvalidOrEmptyAppName.args = {
appName: null
};

View File

@@ -2,7 +2,7 @@
<span mat-dialog-title id="adf-process-filter-dialog-title">
{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.DIALOG.TITLE' | translate}}
</span>
<mat-card class="adf-process-filter-dialog-card">
<mat-card appearance="outlined" class="adf-process-filter-dialog-card">
<mat-card-content class="adf-process-filter-dialog-card-content">
<form [formGroup]="filterForm">
<mat-form-field class="adf-process-filter-name" [floatLabel]="'auto'">

View File

@@ -1,6 +1,4 @@
<mat-nav-list class="adf-process-filters" *ngIf="filters$ | async as filterList; else loading">
<mat-action-list class="adf-process-filters" *ngIf="filters$ | async as filterList; else loading">
<button
*ngFor="let filter of filterList"
mat-list-item
@@ -23,7 +21,7 @@
</span>
</div>
</button>
</mat-nav-list>
</mat-action-list>
<ng-template #loading>
<ng-container>
<div class="adf-app-list-spinner">

View File

@@ -1,4 +1,4 @@
<mat-card *ngIf="processInstanceDetails" class="adf-process-header-cloud-card">
<mat-card appearance="outlined" *ngIf="processInstanceDetails" class="adf-process-header-cloud-card">
<mat-card-content>
<adf-card-view [properties]="properties"></adf-card-view>
</mat-card-content>

View File

@@ -15,20 +15,23 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessHeaderCloudModule } from '../process-header-cloud.module';
import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module';
import { ProcessHeaderCloudComponent } from './process-header-cloud.component';
import { ProcessCloudServiceMock } from '../../mock/process-cloud.service.mock';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { importProvidersFrom } from '@angular/core';
export default {
component: ProcessHeaderCloudComponent,
title: 'Process Services Cloud/Process Cloud/Process Header Cloud/Process Header Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, ProcessHeaderCloudModule],
providers: [{ provide: ProcessCloudService, useClass: ProcessCloudServiceMock }]
imports: [ProcessHeaderCloudModule]
}),
applicationConfig({
providers: [{ provide: ProcessCloudService, useClass: ProcessCloudServiceMock }, importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
@@ -49,32 +52,32 @@ export default {
}
}
}
} as Meta;
} as Meta<ProcessHeaderCloudComponent>;
const template: Story<ProcessHeaderCloudComponent> = (args: ProcessHeaderCloudComponent) => ({
const template: StoryFn<ProcessHeaderCloudComponent> = (args) => ({
props: args
});
export const defaultProcessHeaderCloud = template.bind({});
defaultProcessHeaderCloud.args = {
export const DefaultProcessHeaderCloud = template.bind({});
DefaultProcessHeaderCloud.args = {
appName: 'app',
processInstanceId: 'mock-process-id'
};
export const noParentAndBusinessAndName = template.bind({});
noParentAndBusinessAndName.args = {
export const NoParentAndBusinessAndName = template.bind({});
NoParentAndBusinessAndName.args = {
appName: 'app-placeholders',
processInstanceId: 'mock-process-id'
};
export const invalidOrMissingAppName = template.bind({});
invalidOrMissingAppName.args = {
export const InvalidOrMissingAppName = template.bind({});
InvalidOrMissingAppName.args = {
appName: undefined,
processInstanceId: 'mock-process-id'
};
export const invalidOrMissingProcessInstanceID = template.bind({});
invalidOrMissingProcessInstanceID.args = {
export const InvalidOrMissingProcessInstanceID = template.bind({});
InvalidOrMissingProcessInstanceID.args = {
appName: 'app',
processInstanceId: undefined
};

View File

@@ -15,8 +15,15 @@
* limitations under the License.
*/
import { Component, Input, OnChanges, OnInit, OnDestroy, EventEmitter, ViewEncapsulation } from '@angular/core';
import { CardViewItem, CardViewTextItemModel, TranslationService, AppConfigService, CardViewDateItemModel, CardViewBaseItemModel } from '@alfresco/adf-core';
import { Component, Input, OnChanges, OnInit, OnDestroy, EventEmitter, ViewEncapsulation, Output } from '@angular/core';
import {
CardViewItem,
CardViewTextItemModel,
TranslationService,
AppConfigService,
CardViewDateItemModel,
CardViewBaseItemModel
} from '@alfresco/adf-core';
import { ProcessInstanceCloud } from '../../start-process/models/process-instance-cloud.model';
import { ProcessCloudService } from '../../services/process-cloud.service';
import { takeUntil } from 'rxjs/operators';
@@ -30,7 +37,6 @@ import { Subject } from 'rxjs';
host: { class: 'adf-cloud-process-header' }
})
export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy {
/** (Required) The name of the application. */
@Input()
appName: string = '';
@@ -39,29 +45,28 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
@Input()
processInstanceId: string;
/** Gets emitted each time a new process instance details are loaded. */
@Output()
loaded = new EventEmitter<ProcessInstanceCloud>();
processInstanceDetails: ProcessInstanceCloud;
properties: CardViewItem[];
dateFormat: string;
dateLocale: string;
/** Gets emitted each time a new process instance details are loaded. */
loaded = new EventEmitter<ProcessInstanceCloud>();
private onDestroy$ = new Subject<boolean>();
constructor(
private processCloudService: ProcessCloudService,
private translationService: TranslationService,
private appConfig: AppConfigService) {
}
private appConfig: AppConfigService
) {}
ngOnInit() {
this.dateFormat = this.appConfig.get('adf-cloud-process-header.defaultDateFormat');
this.dateLocale = this.appConfig.get('dateValues.defaultDateLocale');
this.processCloudService.dataChangesDetected
.pipe(takeUntil(this.onDestroy$))
.subscribe((processDetails) => this.onLoaded(processDetails));
this.processCloudService.dataChangesDetected.pipe(takeUntil(this.onDestroy$)).subscribe((processDetails) => this.onLoaded(processDetails));
}
ngOnChanges() {
@@ -71,9 +76,7 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
}
private loadProcessInstanceDetails(appName: string, processInstanceId: string) {
this.processCloudService
.getProcessInstanceById(appName, processInstanceId)
.subscribe((result) => this.onLoaded(result));
this.processCloudService.getProcessInstanceById(appName, processInstanceId).subscribe((result) => this.onLoaded(result));
}
private onLoaded(processInstanceDetails: ProcessInstanceCloud) {
@@ -96,61 +99,53 @@ export class ProcessHeaderCloudComponent implements OnChanges, OnInit, OnDestroy
private initDefaultProperties(): any[] {
return [
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.ID',
value: this.processInstanceDetails.id,
key: 'id'
}),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME',
value: this.processInstanceDetails.name,
key: 'name',
default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME_DEFAULT')
}),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.STATUS',
value: this.processInstanceDetails.status,
key: 'status'
}),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.INITIATOR',
value: this.processInstanceDetails.initiator,
key: 'initiator'
}),
new CardViewDateItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.START_DATE',
value: this.processInstanceDetails.startDate,
key: 'startDate',
format: this.dateFormat,
locale: this.dateLocale
}),
new CardViewDateItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.LAST_MODIFIED',
value: this.processInstanceDetails.lastModified,
key: 'lastModified',
format: this.dateFormat,
locale: this.dateLocale
}),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.PARENT_ID',
value: this.processInstanceDetails.parentId,
key: 'parentId',
default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE')
}),
new CardViewTextItemModel(
{
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.BUSINESS_KEY',
value: this.processInstanceDetails.businessKey,
key: 'businessKey',
default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE')
})
new CardViewTextItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.ID',
value: this.processInstanceDetails.id,
key: 'id'
}),
new CardViewTextItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME',
value: this.processInstanceDetails.name,
key: 'name',
default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NAME_DEFAULT')
}),
new CardViewTextItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.STATUS',
value: this.processInstanceDetails.status,
key: 'status'
}),
new CardViewTextItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.INITIATOR',
value: this.processInstanceDetails.initiator,
key: 'initiator'
}),
new CardViewDateItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.START_DATE',
value: this.processInstanceDetails.startDate,
key: 'startDate',
format: this.dateFormat,
locale: this.dateLocale
}),
new CardViewDateItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.LAST_MODIFIED',
value: this.processInstanceDetails.lastModified,
key: 'lastModified',
format: this.dateFormat,
locale: this.dateLocale
}),
new CardViewTextItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.PARENT_ID',
value: this.processInstanceDetails.parentId,
key: 'parentId',
default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE')
}),
new CardViewTextItemModel({
label: 'ADF_CLOUD_PROCESS_HEADER.PROPERTIES.BUSINESS_KEY',
value: this.processInstanceDetails.businessKey,
key: 'businessKey',
default: this.translationService.instant('ADF_CLOUD_PROCESS_HEADER.PROPERTIES.NONE')
})
];
}

View File

@@ -1,7 +1,4 @@
<mat-card
*ngIf="(loading$ | async) === false; else spinner"
class="adf-start-process"
>
<mat-card appearance="outlined" class="adf-start-process" *ngIf="(loading$ | async) === false; else spinner">
<mat-card-content>

View File

@@ -25,7 +25,7 @@ import { StartProcessCloudComponent } from './start-process-cloud.component';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatOptionModule, MatRippleModule, MatCommonModule } from '@angular/material/core';
import { MatRippleModule, MatCommonModule, MatOptionModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';

View File

@@ -18,7 +18,6 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RichTextEditorComponent } from './rich-text-editor.component';
describe('RichTextEditorComponent', () => {
@@ -56,9 +55,7 @@ describe('RichTextEditorComponent', () => {
await TestBed.configureTestingModule({
declarations: [RichTextEditorComponent]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RichTextEditorComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;

View File

@@ -16,16 +16,20 @@
*/
import { RichTextEditorModule } from './rich-text-editor.module';
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../testing/process-services-cloud-story.module';
import { RichTextEditorComponent } from './rich-text-editor.component';
import { importProvidersFrom } from '@angular/core';
export default {
component: RichTextEditorComponent,
title: 'Process Services Cloud/Rich Text Editor',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, RichTextEditorModule]
imports: [RichTextEditorModule]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
@@ -37,9 +41,9 @@ export default {
}
}
}
} as Meta;
} as Meta<RichTextEditorComponent>;
const template: Story<RichTextEditorComponent> = (args: RichTextEditorComponent) => ({
const template: StoryFn<RichTextEditorComponent> = (args) => ({
props: args,
template: `
<adf-cloud-rich-text-editor [data]=data #editor>
@@ -50,8 +54,8 @@ const template: Story<RichTextEditorComponent> = (args: RichTextEditorComponent)
`
});
export const defaultRichTextEditor = template.bind({});
defaultRichTextEditor.args = {
export const DefaultRichTextEditor = template.bind({});
DefaultRichTextEditor.args = {
data: {
time: 1550476186479,
blocks: [

View File

@@ -1,4 +1,4 @@
<mat-card>
<mat-card appearance="outlined">
<mat-card-header class="adf-cloud-start-task-heading">
<mat-card-title class="adf-cloud-start-task-heading-title">{{'ADF_CLOUD_TASK_LIST.START_TASK.FORM.TITLE' | translate}}</mat-card-title>
</mat-card-header>

View File

@@ -1,5 +1,4 @@
<mat-nav-list class="adf-task-filters" *ngIf="filters$ | async as filterList; else loading">
<mat-action-list class="adf-task-filters" *ngIf="filters$ | async as filterList; else loading">
<button
*ngFor="let filter of filterList"
mat-list-item
@@ -7,8 +6,7 @@
[attr.aria-label]="filter.name | translate"
[id]="filter.id"
[attr.data-automation-id]="filter.key + '_filter'"
[class.adf-active]="currentFilter === filter"
>
[class.adf-active]="currentFilter === filter">
<div class="adf-task-filters__entry">
<div class="adf-task-filters__entry-label">
<adf-icon data-automation-id="adf-filter-icon"
@@ -27,7 +25,7 @@
</span>
</div>
</button>
</mat-nav-list>
</mat-action-list>
<ng-template #loading>
<ng-container>
<div class="adf-app-list-spinner">

View File

@@ -2,7 +2,7 @@
<span mat-dialog-title id="adf-task-filter-dialog-title">
{{ 'ADF_CLOUD_EDIT_TASK_FILTER.DIALOG.TITLE' | translate}}
</span>
<mat-card class="adf-task-filter-dialog-card">
<mat-card appearance="outlined" class="adf-task-filter-dialog-card">
<mat-card-content class="adf-task-filter-dialog-card-content">
<form [formGroup]="filterForm">
<mat-form-field class="adf-task-filter-name" [floatLabel]="'auto'">

View File

@@ -27,7 +27,7 @@
</adf-cloud-form>
<ng-template #withoutForm>
<mat-card class="adf-task-form-container">
<mat-card appearance="outlined" class="adf-task-form-container">
<mat-card-header *ngIf="showTitle">
<mat-card-title>
<h4>
@@ -44,7 +44,7 @@
[subtitle]="'ADF_CLOUD_TASK_FORM.EMPTY_FORM.SUBTITLE'">
</adf-empty-content>
</mat-card-content>
<mat-card-actions class="adf-task-form-actions">
<mat-card-actions class="adf-task-form-actions" align="end">
<ng-template [ngTemplateOutlet]="taskFormCloudButtons">
</ng-template>
<button mat-button *ngIf="canCompleteTask()" adf-cloud-complete-task [appName]="appName"

View File

@@ -1,24 +1,30 @@
@import 'styles/mat-selectors';
.adf-task-form-cloud-container {
.adf-task-form {
&-container {
overflow: hidden;
.adf-task-form-actions:has(button) {
float: right;
padding-bottom: 25px;
padding-right: 25px;
& .adf-task-form-actions-button {
.adf-task-form-actions-button {
height: 36px;
border-radius: 5px;
}
span {
width: 58px;
height: 20px;
opacity: 0.54;
font-size: var(--theme-body-2-font-size);
font-weight: bold;
}
#{$mat-button} {
height: 36px;
border-radius: 5px;
width: auto;
padding: 0 16px;
margin: 0 8px;
white-space: nowrap;
}
#{$mat-button-label} {
min-width: 58px;
}
}
}

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { FormCloudService } from '../../../form/public-api';
import { TaskCloudService } from '../../services/task-cloud.service';
import { TaskFormModule } from '../task-form.module';
@@ -23,17 +23,23 @@ import { TaskFormCloudComponent } from './task-form-cloud.component';
import { TaskCloudServiceMock } from '../../mock/task-cloud.service.mock';
import { FormCloudServiceMock } from '../../../form/mocks/form-cloud.service.mock';
import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module';
import { importProvidersFrom } from '@angular/core';
export default {
component: TaskFormCloudComponent,
title: 'Process Services Cloud/Task Cloud/Task Form/Task Form Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, TaskFormModule],
imports: [TaskFormModule],
providers: [
{ provide: TaskCloudService, useClass: TaskCloudServiceMock },
{ provide: FormCloudService, useClass: FormCloudServiceMock }
]
}),
applicationConfig({
providers: [
importProvidersFrom(ProcessServicesCloudStoryModule)
]
})
],
argTypes: {
@@ -148,26 +154,26 @@ export default {
table: { category: 'Actions' }
}
}
} as Meta;
} as Meta<TaskFormCloudComponent>;
const template: Story<TaskFormCloudComponent> = (args: TaskFormCloudComponent) => ({
const template: StoryFn<TaskFormCloudComponent> = (args) => ({
props: args
});
export const defaultTaskFormCloud = template.bind({});
defaultTaskFormCloud.args = {
export const DefaultTaskFormCloud = template.bind({});
DefaultTaskFormCloud.args = {
appName: 'app',
taskId: 'mock-task-with-form'
};
export const invalidOrMissingApp = template.bind({});
invalidOrMissingApp.args = {
...defaultTaskFormCloud.args,
export const InvalidOrMissingApp = template.bind({});
InvalidOrMissingApp.args = {
...DefaultTaskFormCloud.args,
appName: undefined
};
export const invalidOrMissingTaskId = template.bind({});
invalidOrMissingTaskId.args = {
...defaultTaskFormCloud.args,
export const InvalidOrMissingTaskId = template.bind({});
InvalidOrMissingTaskId.args = {
...DefaultTaskFormCloud.args,
taskId: undefined
};

View File

@@ -1,7 +1,7 @@
<h3 *ngIf="showTitle" class="adf-task-title">{{ taskDetails?.name }}</h3>
<div class="adf-task-header-container">
<mat-card *ngIf="isTaskValid()" class="adf-card-container">
<mat-card appearance="outlined" *ngIf="isTaskValid()" class="adf-card-container">
<mat-card-content>
<adf-card-view
*ngIf="!isLoading; else loadingTemplate"

View File

@@ -413,11 +413,11 @@ describe('TaskHeaderCloudComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const candidateGroup1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup1"] span');
const candidateGroup2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup2"] span');
const candidateGroup1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup1"]');
const candidateGroup2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockgroup2"]');
expect(getCandidateGroupsSpy).toHaveBeenCalled();
expect(candidateGroup1.innerText).toBe('mockgroup1');
expect(candidateGroup2.innerText).toBe('mockgroup2');
expect(candidateGroup1.innerText).toContain('mockgroup1');
expect(candidateGroup2.innerText).toContain('mockgroup2');
});
it('should display candidate user', async () => {
@@ -425,11 +425,11 @@ describe('TaskHeaderCloudComponent', () => {
fixture.detectChanges();
await fixture.whenStable();
const candidateUser1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser1"] span');
const candidateUser2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser2"] span');
const candidateUser1 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser1"]');
const candidateUser2 = fixture.nativeElement.querySelector('[data-automation-id="card-arrayitem-chip-mockuser2"]');
expect(getCandidateUsersSpy).toHaveBeenCalled();
expect(candidateUser1.innerText).toBe('mockuser1');
expect(candidateUser2.innerText).toBe('mockuser2');
expect(candidateUser1.innerText).toContain('mockuser1');
expect(candidateUser2.innerText).toContain('mockuser2');
});
it('should display placeholder if no candidate groups', async () => {

View File

@@ -15,22 +15,24 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { TaskHeaderCloudModule } from '../task-header-cloud.module';
import { TaskHeaderCloudComponent } from './task-header-cloud.component';
import { TaskCloudService } from '../../services/task-cloud.service';
import { TaskCloudServiceMock } from '../../mock/task-cloud.service.mock';
import { ProcessServicesCloudStoryModule } from '../../../testing/process-services-cloud-story.module';
import { importProvidersFrom } from '@angular/core';
export default {
component: TaskHeaderCloudComponent,
title: 'Process Services Cloud/Task Cloud/Task Header Cloud/Task Header Cloud',
decorators: [
moduleMetadata({
imports: [ProcessServicesCloudStoryModule, TaskHeaderCloudModule],
providers: [
{ provide: TaskCloudService, useClass: TaskCloudServiceMock }
]
imports: [TaskHeaderCloudModule],
providers: [{ provide: TaskCloudService, useClass: TaskCloudServiceMock }]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
@@ -75,62 +77,62 @@ export default {
table: { category: 'Actions' }
}
}
} as Meta;
} as Meta<TaskHeaderCloudComponent>;
const template: Story<TaskHeaderCloudComponent> = (args: TaskHeaderCloudComponent) => ({
const template: StoryFn<TaskHeaderCloudComponent> = (args) => ({
props: args
});
export const assignedAndEditable = template.bind({});
assignedAndEditable.args = {
export const AssignedAndEditable = template.bind({});
AssignedAndEditable.args = {
appName: 'app',
taskId: 'mock-assigned-task'
};
export const completedAndReadonly = template.bind({});
completedAndReadonly.args = {
...assignedAndEditable.args,
export const CompletedAndReadonly = template.bind({});
CompletedAndReadonly.args = {
...AssignedAndEditable.args,
taskId: 'mock-completed-task'
};
export const suspended = template.bind({});
suspended.args = {
...assignedAndEditable.args,
export const Suspended = template.bind({});
Suspended.args = {
...AssignedAndEditable.args,
taskId: 'mock-suspended-task'
};
export const withParentId = template.bind({});
withParentId.args = {
...assignedAndEditable.args,
export const WithParentId = template.bind({});
WithParentId.args = {
...AssignedAndEditable.args,
taskId: 'mock-parent-task-id'
};
export const withoutAssignee = template.bind({});
withoutAssignee.args = {
...assignedAndEditable.args,
export const WithoutAssignee = template.bind({});
WithoutAssignee.args = {
...AssignedAndEditable.args,
taskId: 'mock-created-task'
};
export const notClaimableByUser = template.bind({});
notClaimableByUser.args = {
...assignedAndEditable.args,
export const NotClaimableByUser = template.bind({});
NotClaimableByUser.args = {
...AssignedAndEditable.args,
taskId: 'mock-no-candidate-users'
};
export const taskNotClaimableByGroupUser = template.bind({});
taskNotClaimableByGroupUser.args = {
...assignedAndEditable.args,
export const TaskNotClaimableByGroupUser = template.bind({});
TaskNotClaimableByGroupUser.args = {
...AssignedAndEditable.args,
taskId: 'mock-no-candidate-groups'
};
export const invalidForMissingApp = template.bind({});
invalidForMissingApp.args = {
...assignedAndEditable.args,
export const InvalidForMissingApp = template.bind({});
InvalidForMissingApp.args = {
...AssignedAndEditable.args,
appName: undefined
};
export const invalidForMissingTaskId = template.bind({});
invalidForMissingTaskId.args = {
...assignedAndEditable.args,
export const InvalidForMissingTaskId = template.bind({});
InvalidForMissingTaskId.args = {
...AssignedAndEditable.args,
taskId: undefined
};

View File

@@ -17,20 +17,20 @@
import { NgModule } from '@angular/core';
import { AuthModule, CoreModule, provideTranslations } from '@alfresco/adf-core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule } from '@ngx-translate/core';
import { ProcessServicesCloudModule } from '../process-services-cloud.module';
import { provideAnimations } from '@angular/platform-browser/animations';
@NgModule({
imports: [
AuthModule.forRoot(),
BrowserAnimationsModule,
TranslateModule.forRoot(),
CoreModule.forRoot(),
ProcessServicesCloudModule.forRoot()
],
providers: [
provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud')
provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud'),
provideAnimations()
]
})
export class ProcessServicesCloudStoryModule { }

View File

@@ -20,21 +20,9 @@
import 'zone.js';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), {
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: true }
}
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);
});