[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 319e1830fec774b4a7d8e3662d80ca2a8a56f196.

* 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 80d971f7abbaf3fdd66f6731e6a84ffe23900c56.

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

This reverts commit 821d9e1864b48bb2723b51347e133346cc311e5d.

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

This reverts commit 378c6c2000fe1319b2043ca3e4652e12737e30d8.

* Revert "Fixed most of unit tests failing"

This reverts commit 44948e0a2888f3f62c93d5ee439eeccf849cf9b2.

* 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 7cfb5ea64a0bd3b9d462b4bd18c57abd0251d9df.

* 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 58951a77b859eab4f01ae44a27c2d6505fcd66b2.

* 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 a520ba3595bb8deb1f5727e6abfd5a75bd4c83a1.

* 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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
536 changed files with 18952 additions and 32894 deletions

View File

@ -1,5 +1,6 @@
module.exports = {
root: true,
ignorePatterns: [
'projects/**/*',
'**/node_modules/**/*',
@ -10,7 +11,9 @@ module.exports = {
'**/scripts',
'**/docs'
],
plugins: ['@nrwl/nx'],
overrides: [
{
files: ['*.ts'],
@ -196,5 +199,7 @@ module.exports = {
extends: ['plugin:@angular-eslint/template/process-inline-templates'],
excludedFiles: ['*.spec.ts']
}
]
],
extends: ['plugin:storybook/recommended']
};

3
.eslintrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": ["./.eslintrc.js"]
}

1
.gitignore vendored
View File

@ -35,3 +35,4 @@ licenses.txt
.DS_Store
.angular
NX
.nx

2
.nvmrc
View File

@ -1 +1 @@
18.18.2
18.20.3

View File

@ -1,7 +1,10 @@
module.exports = {
framework: {
name: '@storybook/angular',
options: {}
},
staticDirs: [{ from: '../../../demo-shell/src/app.config.json', to: 'app.config.json' }],
docs: {},
stories: [],
addons: ['@storybook/addon-essentials'],
framework: '@storybook/angular',
staticDirs: [ { from: '../../../demo-shell/src/app.config.json', to: 'app.config.json' } ],
core: { builder: 'webpack5' }
addons: []
};

View File

@ -2,3 +2,4 @@ export const parameters = {
docs: { inlineStories: true },
controls: { expanded: true }
};
export const tags = ['autodocs'];

View File

@ -31,5 +31,6 @@
"postcss",
"scss"
],
"editor.guides.indentation": true
"editor.guides.indentation": true,
"typescript.tsdk": "node_modules/typescript/lib"
}

View File

@ -20,7 +20,8 @@
"zen-observable",
"subscriptions-transport-ws",
"d",
"chart.js"
"chart.js",
"cropperjs"
],
"outputPath": "dist/demo-shell",
"index": "demo-shell/src/index.html",
@ -283,7 +284,7 @@
]
},
"test": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": ["TS_NODE_PROJECT=lib/js-api/test/tsconfig.json mocha --full-trace --config lib/js-api/.mocharc.json"]
}
@ -297,7 +298,7 @@
}
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
],
@ -434,7 +435,7 @@
}
},
"license": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -444,7 +445,7 @@
}
},
"pretheme": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -454,9 +455,9 @@
}
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
"build", "pretheme"
],
"options": {
"cwd": "dist/libs/core",
@ -570,7 +571,7 @@
}
},
"stylelint": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -641,7 +642,7 @@
}
},
"stylelint": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -783,7 +784,7 @@
}
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
],
@ -844,7 +845,7 @@
}
},
"stylelint": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -854,7 +855,7 @@
}
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
],
@ -944,12 +945,6 @@
"main": "lib/testing/index.ts",
"generatePackageJson" : true,
"tsConfig": "lib/testing/tsconfig.lib.prod.json",
"additionalEntryPoints": [
{
"entryName": "shared",
"entryPath": "/lib/testing/src/lib/shared/index.ts"
}
],
"stylePreprocessorOptions": {
"includePaths": [
"lib", "lib/core/src/lib"
@ -977,7 +972,7 @@
}
},
"bundle": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -990,7 +985,7 @@
]
},
"copyToNodeModules": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -1006,7 +1001,7 @@
]
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
],
@ -1072,7 +1067,7 @@
}
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
],
@ -1113,7 +1108,7 @@
"defaultConfiguration": "production"
},
"bundle": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -1126,7 +1121,7 @@
]
},
"copyToNodeModules": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"options": {
"commands": [
{
@ -1151,7 +1146,7 @@
}
},
"npm-publish": {
"executor": "nx:run-commands",
"builder": "nx:run-commands",
"dependsOn": [
"build"
],

201
demo-shell/project.json Normal file
View File

@ -0,0 +1,201 @@
{
"name": "demoshell",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "demo-shell/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"minimatch",
"minimatch-browser",
"superagent",
"event-emitter",
"brace-expansion",
"zen-observable",
"subscriptions-transport-ws",
"d",
"chart.js",
"cropperjs"
],
"outputPath": "dist/demo-shell",
"index": "demo-shell/src/index.html",
"main": "demo-shell/src/main.ts",
"tsConfig": "tsconfig.dev.json",
"polyfills": "demo-shell/src/polyfills.ts",
"stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"]
},
"assets": [
"demo-shell/src/assets",
"demo-shell/src/favicon-96x96.png",
"demo-shell/src/app.config.json",
{
"glob": "**/*",
"input": "demo-shell/src/assets",
"output": "/assets"
},
{
"glob": "app.config.json",
"input": "demo-shell/src",
"output": "/"
},
{
"glob": "**/*",
"input": "demo-shell/resources",
"output": "/resources"
},
{
"glob": "**/*",
"input": "lib/core/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/process-services/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/process-services-cloud/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/content-services/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/core/src/lib/i18n",
"output": "/assets/adf-core/i18n"
},
{
"glob": "**/*",
"input": "lib/content-services/src/lib/i18n",
"output": "/assets/adf-content-services/i18n"
},
{
"glob": "**/*",
"input": "lib/process-services/src/lib/i18n",
"output": "/assets/adf-process-services/i18n"
},
{
"glob": "**/*",
"input": "lib/process-services-cloud/src/lib/i18n",
"output": "/assets/adf-process-services-cloud/i18n"
},
{
"glob": "**/*",
"input": "lib/insights/src/lib/i18n",
"output": "/assets/adf-insights/i18n"
},
{
"glob": "pdf.worker.min.js",
"input": "node_modules/pdfjs-dist/build",
"output": "/"
},
{
"glob": "**/*",
"input": "node_modules/monaco-editor",
"output": "/assets/monaco/"
}
],
"styles": [
"demo-shell/src/styles.scss",
"demo-shell/src/custom-style-dev.scss",
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"scripts": ["node_modules/pdfjs-dist/build/pdf.js", "node_modules/pdfjs-dist/web/pdf_viewer.js", "node_modules/raphael/raphael.min.js"],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": false,
"sourceMap": true,
"optimization": false,
"namedChunks": true
},
"configurations": {
"production": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "12kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"buildOptimizer": true,
"verbose": false,
"fileReplacements": [
{
"replace": "demo-shell/src/environments/environment.ts",
"with": "demo-shell/src/environments/environment.prod.ts"
}
]
},
"canary": {
"fileReplacements": [
{
"replace": "demo-shell/src/environments/environment.ts",
"with": "demo-shell/src/environments/environment.canary.ts"
}
]
},
"e2e": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"buildOptimizer": true,
"verbose": false,
"fileReplacements": [
{
"replace": "demo-shell/src/environments/environment.ts",
"with": "demo-shell/src/environments/environment.e2e.ts"
}
]
}
},
"defaultConfiguration": ""
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "demoshell:build",
"host": "0.0.0.0",
"port": 3000,
"proxyConfig": "demo-shell/proxy.conf.js",
"disableHostCheck": true
},
"configurations": {
"production": {
"browserTarget": "demoshell:build:production"
},
"canary": {
"browserTarget": "demoshell:build:canary"
},
"e2e": {
"browserTarget": "demoshell:build:e2e"
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": ["demo-shell/**/*.ts", "demo-shell/**/*.html"]
}
}
}
}

View File

@ -622,7 +622,7 @@
"unit": "Byte",
"field": "cm:content.size",
"min": 0,
"max": 18,
"max": 4000,
"step": 1,
"thumbLabel": true
}

View File

@ -76,7 +76,7 @@ import { CoreAutomationService } from '../testing/automation.service';
BrowserModule,
environment.e2e ? NoopAnimationsModule : BrowserAnimationsModule,
ReactiveFormsModule,
RouterModule.forRoot(appRoutes, { useHash: true, relativeLinkResolution: 'legacy' }),
RouterModule.forRoot(appRoutes, { useHash: true }),
AuthModule.forRoot({ useHash: true }),
FormsModule,
HttpClientModule,

View File

@ -1,3 +1,5 @@
@import 'styles/mat-selectors';
.app-form-container {
padding: 10px;
}
@ -31,7 +33,7 @@
}
.app-form-editor-buttons {
& > .mat-raised-button {
& > #{$mat-raised-button} {
margin-right: 5px;
}
}

View File

@ -40,7 +40,7 @@
<mat-menu #menu="matMenu" id="user-profile-lists" [xPosition]="menuPositionX" [yPosition]="menuPositionY"
[overlapTrigger]="false" class="adf-userinfo-menu">
<mat-card *ngIf="mode === userInfoMode.CONTENT" class="adf-userinfo-card adf-content-userinfo-card">
<mat-card appearance="outlined" *ngIf="mode === userInfoMode.CONTENT" class="adf-userinfo-card adf-content-userinfo-card">
<mat-card-header class="adf-userinfo-card-header"
[style.background-image]="'url(' + ecmBackgroundImage + ')'">
<div *ngIf="ecmUser.avatarId; else initialTemplate"
@ -53,7 +53,7 @@
[outerHTML]="ecmUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
</ng-template>
<div class="mat-title" id="ecm-username">{{ecmUser | fullName}}</div>
<div class="mat-headline-6" id="ecm-username">{{ecmUser | fullName}}</div>
</mat-card-header>
<mat-card-content>
<div class="adf-userinfo-supporting-text">
@ -73,7 +73,7 @@
</div>
</mat-card-content>
</mat-card>
<mat-card *ngIf="mode === userInfoMode.CONTENT_SSO" class="adf-userinfo-card adf-content-userinfo-card">
<mat-card appearance="outlined" *ngIf="mode === userInfoMode.CONTENT_SSO" class="adf-userinfo-card adf-content-userinfo-card">
<mat-card-header class="adf-userinfo-card-header"
[style.background-image]="'url(' + bpmBackgroundImage + ')'">
<div *ngIf="ecmUser.avatarId; else initialTemplate"
@ -85,7 +85,7 @@
<div
[outerHTML]="identityUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
</ng-template>
<div class="mat-title" id="identity-username">{{identityUser | fullName}}</div>
<div class="mat-headline-6" id="identity-username">{{identityUser | fullName}}</div>
</mat-card-header>
<mat-card-content>
<div class="adf-userinfo-supporting-text">

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { CoreTestingModule, IdentityUserModel, InitialUsernamePipe, UserInfoMode } from '@alfresco/adf-core';
import { IdentityUserModel, InitialUsernamePipe, UserInfoMode } from '@alfresco/adf-core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatMenuModule } from '@angular/material/menu';
import { By, DomSanitizer } from '@angular/platform-browser';
@ -119,7 +119,7 @@ describe('ContentUserInfoComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, ContentTestingModule, MatMenuModule]
imports: [ContentTestingModule, MatMenuModule]
});
fixture = TestBed.createComponent(ContentUserInfoComponent);
component = fixture.componentInstance;

View File

@ -41,7 +41,7 @@
class="adf-userinfo-tab" [class.adf-hide-tab]="!ecmUser">
<mat-tab label="{{ 'USER_PROFILE.TAB.CS' | translate }}" role="dialog"
*ngIf="mode===userInfoMode.ALL">
<mat-card class="adf-userinfo-card" *ngIf="ecmUser">
<mat-card appearance="outlined" class="adf-userinfo-card" *ngIf="ecmUser">
<mat-card-header class="adf-userinfo-card-header"
[style.background-image]="'url(' + ecmBackgroundImage + ')'">
<div *ngIf="ecmUser.avatarId; else initialTemplate"
@ -54,7 +54,7 @@
[outerHTML]="ecmUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
</ng-template>
<div class="mat-title" id="ecm-username">{{ecmUser | fullName}}</div>
<div class="mat-headline-6" id="ecm-username">{{ecmUser | fullName}}</div>
</mat-card-header>
<mat-card-content>
<div class="adf-userinfo-supporting-text">
@ -75,7 +75,7 @@
</mat-tab>
<mat-tab id="bpm-panel" label="{{ 'USER_PROFILE.TAB.PS' | translate }}" role="dialog"
*ngIf="mode===userInfoMode.PROCESS || mode===userInfoMode.ALL">
<mat-card class="adf-userinfo-card">
<mat-card appearance="outlined" class="adf-userinfo-card">
<mat-card-header class="adf-userinfo-card-header"
[style.background-image]="'url(' + bpmBackgroundImage + ')'">
<img *ngIf="bpmUser.pictureId; else initialTemplate"
@ -85,7 +85,7 @@
<div
[outerHTML]="bpmUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
</ng-template>
<div class="mat-title" id="bpm-username">{{bpmUser | fullName}}</div>
<div class="mat-headline-6" id="bpm-username">{{bpmUser | fullName}}</div>
</mat-card-header>
<mat-card-content>
<div class="adf-userinfo-supporting-text">

View File

@ -1,4 +1,5 @@
@import 'styles/flex';
@import 'styles/mat-selectors';
.adf {
&-userinfo-container {
@ -49,7 +50,7 @@
display: inline-block;
}
&-userinfo-menu_button.mat-button {
&-userinfo-menu_button#{$mat-button} {
margin-right: 0;
border-radius: 90%;
padding: 0;
@ -57,13 +58,13 @@
height: 40px;
}
&-userinfo-tab .mat-tab-header {
&-userinfo-tab #{$mat-tab-header} {
align-self: center;
width: 100%;
min-width: 250px;
}
&-userinfo-tab .mat-tab-label {
&-userinfo-tab #{$mat-tab-label-text} {
flex: auto;
font-weight: 500;
font-size: var(--theme-body-1-font-size);
@ -81,7 +82,7 @@
box-sizing: border-box;
}
&-userinfo-card.mat-card {
&-userinfo-card#{$mat-card} {
padding: 0;
}
@ -160,7 +161,7 @@
}
@media only screen and (min-device-width: 480px) {
.mat-menu-panel.adf-userinfo-menu {
#{$mat-menu-panel}.adf-userinfo-menu {
max-height: 450px;
min-width: 450px;
overflow: auto;
@ -168,6 +169,6 @@
}
}
.mat-menu-panel.adf-userinfo-menu .mat-menu-content {
#{$mat-menu-panel}.adf-userinfo-menu #{$mat-menu-content} {
padding: 0;
}

View File

@ -1,3 +1,5 @@
@import 'styles/mat-selectors';
.app-cloud-layout-overflow {
overflow: auto;
}

View File

@ -43,11 +43,11 @@
<button mat-raised-button (click)="addAction()">Add</button>
</form>
<div *ngIf="actions.length > 0">
<mat-chip-list>
<mat-chip *ngFor="let action of actions" [removable]="true">
<mat-chip-listbox>
<mat-chip-option *ngFor="let action of actions" [removable]="true">
{{action.title}}
<mat-icon matChipRemove (click)="removeAction(action)">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</mat-chip-option>
</mat-chip-listbox>
</div>
</div>

View File

@ -1,6 +1,7 @@
@use '@angular/material' as mat;
@import '../../lib/core/src/lib/styles/index';
@import '../../lib/core/src/lib/styles/typography';
@include mat.all-component-typographies;
@include mat.core;
$primary: mat.define-palette($alfresco-accent-orange);
@ -19,19 +20,3 @@ $theme: mat.define-light-theme(
@include mat.all-component-themes($theme);
@include alfresco-material-theme($theme);
$typography: map-get($theme, typography);
body,
html {
margin: 0;
height: 100%;
overflow: hidden;
font-size: mat.font-size($typography, body-1);
font-family: mat.font-family($typography);
line-height: mat.line-height($typography, body-1);
}
body {
overflow: auto;
}

View File

@ -1,6 +1,7 @@
@use '@angular/material' as mat;
@import '~@alfresco/adf-core/theming';
@include mat.core($alfresco-typography);
@include mat.all-component-typographies($alfresco-typography);
@include mat.core;
$primary: mat.define-palette($alfresco-accent-orange);
$accent: mat.define-palette($alfresco-accent-purple);
@ -16,17 +17,3 @@ $theme: mat.define-light-theme(
@include mat.all-component-themes($theme);
@include alfresco-material-theme($theme);
body,
html {
margin: 0;
height: 100%;
overflow: hidden;
font-size: mat.font-size($alfresco-typography, body-1);
font-family: mat.font-family($alfresco-typography);
line-height: mat.line-height($alfresco-typography, body-1);
}
body {
overflow: auto;
}

View File

@ -150,6 +150,7 @@ A collection of Angular components for generic use.
| Name | Description | Source link |
| ---- | ----------- | ----------- |
| [Confirm dialog component](core/dialogs/confirm.dialog.md) | Requests a yes/no choice from the user. | [Source](../lib/core/src/lib/dialogs/confirm-dialog/confirm.dialog.ts) |
| [Edit JSON Dialog](core/dialogs/edit-json.dialog.md) | Allows a user to preview or edit a JSON content in a dialog. | [Source](../lib/testing/src/lib/core/dialog/edit-json-dialog.ts) |
| [Unsaved Changes Dialog](core/dialogs/unsaved-changes-dialog.component.md) | Dialog which informs about unsaved changes. Allows discard them and proceed or close dialog and stop proceeding. | [Source](../lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes-dialog.component.ts) |
@ -348,7 +349,6 @@ for more information about installing and using the source code.
| Name | Description | Source link |
| ---- | ----------- | ----------- |
| [Dialog component](content-services/dialogs/dialog.md) | Dialog styled wrapper. | [Source](../lib/content-services/src/lib/dialogs/dialog/dialog.component.ts) |
| [Confirm dialog component](content-services/dialogs/confirm.dialog.md) | Requests a yes/no choice from the user. | [Source](../lib/content-services/src/lib/dialogs/confirm.dialog.ts) |
| [Library dialog component](content-services/dialogs/library.dialog.md) | Creates a new Content Services document library/site. | [Source](../lib/content-services/src/lib/dialogs/library/library.dialog.ts) |
### Interfaces

View File

@ -96,7 +96,7 @@ However, you can use a more complex template if necessary:
class="adf-search-autocomplete-item"
(click)="elementClicked(item)"
(keyup.enter)="elementClicked(item)">
<mat-icon mat-list-icon>
<mat-icon matListItemLine>
<img [src]="getMimeTypeIcon(item)" />
</mat-icon>
<h4 mat-line id="result_name_{{idx}}"

View File

@ -27,7 +27,7 @@ Displays a input text that supports autocompletion
### Properties
| Name | Type | Default value | Description |
| ---- | ---- | ------------- | ----------- |
|--------------------| ---- | ------------- |--------------------------------------------------------------------------------------------|
| autocomplete | `boolean` | false | Toggles auto-completion of the search input field. |
| collapseOnBlur | `boolean` | true | Toggles whether to collapse the search on blur. |
| collapseOnSubmit | `boolean` | true | Collapse search bar on submit. |
@ -39,6 +39,7 @@ Displays a input text that supports autocompletion
| inputType | `string` | "text" | Type of the input field to render, e.g. "search" or "text" (default). |
| liveSearchEnabled | `boolean` | true | Toggles "find-as-you-type" suggestions for possible matches. |
| placeholder | `string` | "" | Placeholder text to show in the input field |
| label | `string` | "" | Label text to show over the input field |
| searchAutocomplete | `any` | false | Trigger autocomplete results on input change. |
| searchTerm | `string` | "" | Search term preselected |
| showClearButton | `boolean` | false | Toggles whether to show a clear button that closes the search |

View File

@ -5,7 +5,7 @@ Status: Active
Last reviewed: 2019-01-22
---
# [Confirm dialog component](../../../lib/content-services/src/lib/dialogs/confirm.dialog.ts "Defined in confirm.dialog.ts")
# [Confirm dialog component](../../../lib/core/src/lib/dialogs/confirm-dialog/confirm.dialog.ts "Defined in confirm.dialog.ts")
Requests a yes/no choice from the user.

View File

@ -175,7 +175,7 @@ Is now possible add an extra button in the Confirm Dialog
For more details refer to the:
- [Confirm Dialog](../content-services/dialogs/confirm.dialog.md)
- [Confirm Dialog](../core/dialogs/confirm.dialog.md)
### Configuration option to change the default viewer zoom

View File

@ -441,7 +441,7 @@ backend services have been tested with each released version of ADF.
<!--v230 start-->
- [Comment content service](core/services/comment-content.service.md)
- [Confirm dialog](content-services/dialogs/confirm.dialog.md)
- [Confirm dialog](core/dialogs/confirm.dialog.md)
- [Content node share directive](content-services/directives/content-node-share.directive.md)
- [Custom resources service](content-services/services/custom-resources.service.md)
- [Inherited button directive](content-services/directives/inherited-button.directive.md)

View File

@ -16,4 +16,4 @@
*/
export * from './components';
export * from './stories/base.stories';
export * from './stories/base-stories';

View File

@ -24,7 +24,7 @@ interface NavigationParameters {
moduleNames: string[];
componentName: string;
story: string;
};
}
export class BaseStories extends PlaywrightBase {
private libraryName: string;
@ -34,15 +34,13 @@ export class BaseStories extends PlaywrightBase {
this.libraryName = libraryName;
}
private buildStoryId({ moduleNames, componentName, story }: NavigationParameters): string{
private buildStoryId({ moduleNames, componentName, story }: NavigationParameters): string {
const moduleNamesConcatenated = moduleNames.reduce((module, submodule) => module + '-' + submodule);
return this.libraryName + '-' + moduleNamesConcatenated + '-' + componentName + '--' + story;
}
async navigateTo(navigationParameters: NavigationParameters): Promise<void> {
await this.page.goto(`/iframe.html?args=&viewMode=story&id=${this.buildStoryId(navigationParameters)}`, {
waitUntil: 'networkidle',
timeout: timeouts.large
});
await this.page.goto(`/iframe.html?viewMode=story&id=${this.buildStoryId(navigationParameters)}`);
await this.page.waitForSelector('storybook-root', { timeout: timeouts.large });
}
}

View File

@ -15,7 +15,15 @@
* limitations under the License.
*/
import { createApiService, CheckboxPage, LoginPage, UploadActions, UserModel, UsersActions, ViewerPage } from '@alfresco/adf-testing';
import { createApiService,
CheckboxPage,
LoginPage,
UploadActions,
UserModel,
UsersActions,
ViewerPage,
TogglePage
} from '@alfresco/adf-testing';
import { MetadataViewPage } from '../../core/pages/metadata-view.page';
import { FileModel } from '../../models/ACS/file.model';
import { browser } from 'protractor';
@ -37,6 +45,7 @@ describe('CardView Component - properties', () => {
const viewerPage = new ViewerPage();
const metadataViewPage = new MetadataViewPage();
const contentServicesPage = new ContentServicesPage();
const togglePage = new TogglePage();
let acsUser: UserModel;
@ -127,13 +136,13 @@ describe('CardView Component - properties', () => {
await viewerPage.checkInfoSideBarIsDisplayed();
await metadataViewPage.clickOnPropertiesTab();
await CheckboxPage.uncheck(metadataViewPage.defaultPropertiesSwitch);
await togglePage.disableToggle(metadataViewPage.defaultPropertiesSwitch);
await metadataViewPage.checkMetadataGroupIsNotPresent('properties');
await metadataViewPage.checkMetadataGroupIsPresent('Versionable');
await metadataViewPage.checkMetadataGroupIsExpand('Versionable');
await CheckboxPage.check(metadataViewPage.defaultPropertiesSwitch);
await togglePage.enableToggle(metadataViewPage.defaultPropertiesSwitch);
await metadataViewPage.checkMetadataGroupIsPresent('properties');
await metadataViewPage.checkMetadataGroupIsExpand('properties');
@ -145,7 +154,11 @@ describe('CardView Component - properties', () => {
await viewerPage.checkInfoSideBarIsDisplayed();
await metadataViewPage.clickOnPropertiesTab();
await CheckboxPage.uncheck(metadataViewPage.defaultPropertiesSwitch);
await metadataViewPage.checkMetadataGroupIsPresent('properties');
await togglePage.disableToggle(metadataViewPage.defaultPropertiesSwitch);
await metadataViewPage.checkMetadataGroupIsNotPresent('properties');
});
it('[C307975] Should be able to choose which aspect to show expanded in the info-drawer', async () => {

View File

@ -38,11 +38,12 @@ export class MetadataViewPage {
multiSwitch = $(`#adf-metadata-multi`);
defaultPropertiesSwitch = $('#adf-metadata-default-properties');
closeButton = element(by.cssContainingText(`button${materialLocators.Button.class} span`, 'Close'));
displayAspect = $(`input[data-placeholder='Display Aspect']`);
applyAspect = element(by.cssContainingText(`button span${materialLocators.Button.wrapper}`, 'Apply Aspect'));
displayAspect = $(`input[placeholder='Display Aspect']`);
applyAspect = element(by.cssContainingText(`button span${materialLocators.Button.label}`, 'Apply Aspect'));
saveMetadataButton = $(`[data-automation-id='save-metadata']`);
saveGeneralMetadataButton = $(`[data-automation-id='save-general-info-metadata']`);
resetMetadataButton = $(`[data-automation-id='reset-metadata']`);
informationButton = $(`button[data-automation-id='meta-data-card-toggle-expand']`);
private getMetadataGroupLocator = async (groupName: string): Promise<ElementFinder> =>
$(`[data-automation-id="adf-metadata-group-${groupName}"]`);
@ -113,12 +114,7 @@ export class MetadataViewPage {
}
async clickOnPropertiesTab(): Promise<void> {
const propertiesTab = element(
by.cssContainingText(
`.adf-info-drawer-layout-content div${materialLocators.Tab.labels.class} div ${materialLocators.Tab.label.content.class}`,
`Properties`
)
);
const propertiesTab = element(by.cssContainingText(`.adf-info-drawer-layout-content ${materialLocators.Tab.labels.class}`, `Properties`));
await BrowserActions.click(propertiesTab);
}
@ -274,4 +270,12 @@ export class MetadataViewPage {
async clickSaveGeneralMetadata(): Promise<void> {
await BrowserActions.click(this.saveGeneralMetadataButton);
}
async informationButtonIsDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsClickable(this.informationButton);
}
async informationButtonIsNotDisplayed(): Promise<void> {
await BrowserVisibility.waitUntilElementIsNotVisible(this.informationButton);
}
}

View File

@ -18,12 +18,17 @@
import { FormCloudComponentPage, LoginPage, ProcessCloudWidgetPage } from '@alfresco/adf-testing';
import { NavigationBarPage } from '../../core/pages/navigation-bar.page';
import { tabFieldValueVisibilityJson, tabVarValueVisibilityJson, tabVarFieldVisibilityJson,
tabFieldFieldVisibilityJson, tabFieldVarVisibilityJson, tabVarVarVisibilityJson,
tabNextOperatorsVisibilityJson } from '../../resources/forms/tab-visibility-conditions';
import {
tabFieldValueVisibilityJson,
tabVarValueVisibilityJson,
tabVarFieldVisibilityJson,
tabFieldFieldVisibilityJson,
tabFieldVarVisibilityJson,
tabVarVarVisibilityJson,
tabNextOperatorsVisibilityJson
} from '../../resources/forms/tab-visibility-conditions';
describe('Visibility conditions on tabs - cloud', () => {
const loginSSOPage = new LoginPage();
const navigationBarPage = new NavigationBarPage();
const formCloudDemoPage = new FormCloudComponentPage();

View File

@ -21,7 +21,7 @@ import { ProcessServicesPage } from '../pages/process-services.page';
import { ChecklistDialog } from '../pages/dialog/create-checklist-dialog.page';
import { NavigationBarPage } from '../../core/pages/navigation-bar.page';
import { browser } from 'protractor';
import CONSTANTS = require('../../util/constants');
import * as CONSTANTS from '../../util/constants';
describe('Checklist component', () => {
const app = browser.params.resources.Files.SIMPLE_APP_WITH_USER_FORM;
@ -75,7 +75,8 @@ describe('Checklist component', () => {
await taskPage.tasksListPage().checkContentIsDisplayed(tasks[0]);
await taskPage.tasksListPage().selectRow(tasks[0]);
await (await taskPage.clickOnAddChecklistButton()).clickCreateChecklistButton();
await taskPage.clickOnAddChecklistButton();
await checklistDialog.clickCreateChecklistButton();
await taskPage.checkChecklistDialogIsNotDisplayed();
await taskPage.checkNoChecklistIsDisplayed();
expect(await taskPage.getNumberOfChecklists()).toEqual('0');

View File

@ -20,7 +20,7 @@ import { TasksPage } from './../pages/tasks.page';
import { NavigationBarPage } from '../../core/pages/navigation-bar.page';
import { ProcessServicesPage } from './../pages/process-services.page';
import { browser } from 'protractor';
import CONSTANTS = require('../../util/constants');
import * as CONSTANTS from '../../util/constants';
describe('People component', () => {
const app = browser.params.resources.Files.SIMPLE_APP_WITH_USER_FORM;

View File

@ -21,8 +21,8 @@ import { BrowserVisibility, BrowserActions } from '@alfresco/adf-testing';
export class ChecklistDialog {
nameField = $('input[data-automation-id="checklist-name"]');
addChecklistButton = $('button[id="add-check"] span');
closeButton = $('button[id="close-check-dialog"] span');
addChecklistButton = $('button[id="add-check"]');
closeButton = $('button[id="close-check-dialog"]');
dialogTitle = $('#add-checklist-title');
async addName(name: string): Promise<void> {
@ -42,7 +42,7 @@ export class ChecklistDialog {
}
async getNameFieldPlaceholder(): Promise<string> {
return BrowserActions.getAttribute(this.nameField, 'data-placeholder');
return BrowserActions.getAttribute(this.nameField, 'placeholder');
}
async checkCancelButtonIsEnabled(): Promise<void> {

View File

@ -58,7 +58,7 @@ export class StartTaskDialogPage {
}
async getAssignee(): Promise<string> {
return BrowserActions.getAttribute(this.assignee, 'data-placeholder');
return BrowserActions.getAttribute(this.assignee, 'placeholder');
}
async selectForm(form): Promise<void> {

View File

@ -20,19 +20,19 @@ import { element, by, browser } from 'protractor';
export class ProcessServiceTabBarPage {
tasksButton = element.all(by.cssContainingText(`div[class*="${materialLocators.Tab.label.root}"] ${materialLocators.Tab.labels.class} div`, 'Tasks')).first();
processButton = element.all(by.cssContainingText(`div[class*="${materialLocators.Tab.label.root}"] ${materialLocators.Tab.labels.class} div`, 'Process')).first();
reportsButton = element.all(by.cssContainingText(`div[class*="${materialLocators.Tab.label.root}"] ${materialLocators.Tab.labels.class} div`, 'Reports')).first();
reportsButtonSelected = element.all(by.cssContainingText(`div[class*="${materialLocators.Tab.label.root}"] ${materialLocators.Tab.labels.class} div[aria-selected="true"]`, 'Reports')).first();
tasksButton = element.all(by.cssContainingText(`div${materialLocators.Tab.labels.container.class} ${materialLocators.Tab.labels.class}`, 'Tasks')).first();
processButton = element.all(by.cssContainingText(`div${materialLocators.Tab.labels.container.class} ${materialLocators.Tab.labels.class}`, 'Process')).first();
reportsButton = element.all(by.cssContainingText(`div${materialLocators.Tab.labels.container.class} ${materialLocators.Tab.labels.class}`, 'Reports')).first();
reportsButtonSelected = element.all(by.cssContainingText(`div${materialLocators.Tab.labels.container.class} ${materialLocators.Tab.labels.class} div[aria-selected="true"]`, 'Reports')).first();
async clickTasksButton(): Promise<void> {
await BrowserActions.click(this.tasksButton);
await browser.sleep(500);
await browser.sleep(100);
}
async clickProcessButton(): Promise<void> {
await BrowserActions.click(this.processButton);
await browser.sleep(500);
await browser.sleep(100);
}
async clickReportsButton(): Promise<void> {

View File

@ -180,7 +180,7 @@ export class TaskDetailsPage {
}
async getDescriptionPlaceholder(): Promise<string> {
return BrowserActions.getAttribute(this.descriptionField, 'data-placeholder');
return BrowserActions.getAttribute(this.descriptionField, 'placeholder');
}
getDueDate(): Promise<string> {
@ -310,7 +310,7 @@ export class TaskDetailsPage {
}
async getInvolvePeoplePlaceholder(): Promise<string> {
return BrowserActions.getAttribute(this.addPeopleField, 'data-placeholder');
return BrowserActions.getAttribute(this.addPeopleField, 'placeholder');
}
async checkCancelButtonIsEnabled(): Promise<void> {

View File

@ -21,6 +21,8 @@ import { browser, $, $$ } from 'protractor';
export class TasksListPage {
taskList = $('adf-tasklist');
selectedTab = $('[data-automation-id="navigation-bar"] .mdc-tab--active .mdc-tab__text-label');
taskTab = $$('[data-automation-id="navigation-bar"] .mdc-tab__text-label').first();
noTasksFound = $$('.adf-empty-content__title').first();
dataTable = new DataTableComponentPage(this.taskList);
@ -61,4 +63,11 @@ export class TasksListPage {
return BrowserActions.getText(this.noTasksFound);
}
async selectTaskTab() {
const currentTab = await BrowserActions.getText(this.selectedTab);
if(currentTab && currentTab.toLowerCase().trim() !== 'tasks') {
await BrowserActions.click(this.taskTab);
}
}
}

View File

@ -27,13 +27,13 @@ import { BrowserActions, BrowserVisibility, FormFields, materialLocators } from
export class TasksPage {
createButton = $('button[data-automation-id="create-button"');
addChecklistButton = $('button[class*="adf-add-to-checklist-button"]');
rowByRowName = by.xpath(`ancestor::${materialLocators.Chip.root}`);
rowByRowName = by.xpath(`ancestor::${materialLocators.Chip.list.option.class}`);
checklistContainer = $('div[class*="checklist-menu"]');
taskTitle = '.adf-activiti-task-details__header span';
completeButtonNoForm = $('#adf-no-form-complete-button');
checklistDialog = $('#checklist-dialog');
checklistNoMessage = $('#checklist-none-message');
numberOfChecklists = $(`[data-automation-id="checklist-label"] ${materialLocators.Chip.root}`);
numberOfChecklists = $(`[data-automation-id="checklist-label"] ${materialLocators.Chip.list.option.value}`);
async createNewTask(): Promise<StartTaskDialogPage> {
await this.clickOnCreateButton();
@ -82,7 +82,7 @@ export class TasksPage {
}
getRowsName(name: string) {
return this.checklistContainer.element(by.cssContainingText('span', name));
return this.checklistContainer.element(by.cssContainingText(`span${materialLocators.Chip.list.option.value}`, name));
}
getChecklistByName(name: string) {

View File

@ -95,6 +95,7 @@ describe('Task Filters Sorting', () => {
await userFiltersUtil.createUserTaskFilter(newFilter);
await browser.refresh();
await tasksListPage.selectTaskTab();
await taskFiltersDemoPage.customTaskFilter(newFilter.name).clickTaskFilter();
expect(await tasksListPage.getDataTable().contentInPosition(1)).toBe(tasks[2].name);

View File

@ -18,7 +18,7 @@
import { createApiService, ApplicationsUtil, LoginPage, ProcessUtil, UsersActions, Widget, UserModel } from '@alfresco/adf-testing';
import { TasksPage } from '../pages/tasks.page';
import { browser } from 'protractor';
import CONSTANTS = require('../../util/constants');
import * as CONSTANTS from '../../util/constants';
import { ProcessServicesPage } from '../pages/process-services.page';
import { AppDefinitionRepresentation, ProcessInstanceRepresentation } from '@alfresco/js-api';
@ -65,6 +65,12 @@ describe('Checkbox Widget', () => {
await usersActions.deleteTenant(processUserModel.tenantId);
});
it('[C272812] Should be able to set visibility settings for Checkbox widget', async () => {
await widget.checkboxWidget().isCheckboxHidden(app.FIELD.checkbox_field_id);
await taskPage.formFields().setValueInInputById(app.FIELD.number_input_id, '2');
await widget.checkboxWidget().isCheckboxDisplayed(app.FIELD.checkbox_field_id);
});
it('[C268554] Should be able to set general settings for Checkbox widget ', async () => {
await taskPage.formFields().setValueInInputById(app.FIELD.number_input_id, '2');
expect(await widget.checkboxWidget().getCheckboxLabel()).toContain(app.FIELD.checkbox_label);
@ -72,10 +78,4 @@ describe('Checkbox Widget', () => {
await widget.checkboxWidget().clickCheckboxInput(app.FIELD.checkbox_input_id);
expect(await taskPage.formFields().isCompleteFormButtonEnabled()).toEqual(true);
});
it('[C272812] Should be able to set visibility settings for Checkbox widget', async () => {
await widget.checkboxWidget().isCheckboxHidden(app.FIELD.checkbox_field_id);
await taskPage.formFields().setValueInInputById(app.FIELD.number_input_id, '2');
await widget.checkboxWidget().isCheckboxDisplayed(app.FIELD.checkbox_field_id);
});
});

View File

@ -32,10 +32,14 @@ const createField = (id = 'TextTwo', name = 'TextTwo') => ({
}
});
const createFieldDefinition = (id = 'dcde7e13-2444-48bc-ab30-32902cea549e', tabName = '71da814d-5580-4f1f-972a-8089253aeded', fields = {
const createFieldDefinition = (
id = 'dcde7e13-2444-48bc-ab30-32902cea549e',
tabName = '71da814d-5580-4f1f-972a-8089253aeded',
fields = {
1: [createField()],
2: []
}) => ({
}
) => ({
id,
name: 'Label',
type: 'container',
@ -57,7 +61,14 @@ const fieldDefinition3 = createFieldDefinition('df452297-d0e8-4406-b9d3-10842033
const fieldsDefinitions1 = [fieldDefinition1, fieldDefinition2];
const fieldsDefinitions2 = [fieldDefinition1, fieldDefinition3];
const createVisibilityCondition = (leftType = 'field', leftValue = 'TextOne', nextCondition?: any, rightValue = 'showTab', rightType = 'value', operator = '==') => ({
const createVisibilityCondition = (
leftType = 'field',
leftValue = 'TextOne',
nextCondition?: any,
rightValue = 'showTab',
rightType = 'value',
operator = '=='
) => ({
leftType,
leftValue,
operator,
@ -67,16 +78,19 @@ const createVisibilityCondition = (leftType = 'field', leftValue = 'TextOne', ne
nextCondition
});
const createTab = (id = '71da814d-5580-4f1f-972a-8089253aeded', title = 'tabBasicFieldValue', visibilityCondition = createVisibilityCondition('field', 'TextOne', null)) => ({
const createTab = (
id = '71da814d-5580-4f1f-972a-8089253aeded',
title = 'tabBasicFieldValue',
visibilityCondition = createVisibilityCondition('field', 'TextOne', null)
) => ({
id,
title,
visibilityCondition
});
const createTabVisibilityJson = (tabs = [
createTab(),
createTab('442eea0b-65f9-484e-b37f-f5a91d5e1f21', 'tabWithFields', null)
], fields = [
const createTabVisibilityJson = (
tabs = [createTab(), createTab('442eea0b-65f9-484e-b37f-f5a91d5e1f21', 'tabWithFields', null)],
fields = [
createFieldDefinition(),
createFieldDefinition('df452297-d0e8-4406-b9d3-10842033549d', '442eea0b-65f9-484e-b37f-f5a91d5e1f21', {
1: [
@ -99,7 +113,9 @@ const createTabVisibilityJson = (tabs = [
],
2: []
})
], variables = []) => ({
],
variables = []
) => ({
formRepresentation: {
id: 'form-3aff57d3-62af-4adf-9b14-1d8f44a28077',
name: 'tabvisibility',
@ -118,70 +134,86 @@ const createTabVisibilityJson = (tabs = [
export const tabFieldValueVisibilityJson = createTabVisibilityJson();
export const tabVarValueVisibilityJson = createTabVisibilityJson([
createTab('71da814d-5580-4f1f-972a-8089253aeded', 'tabBasicVarValue', createVisibilityCondition('variable', 'stringVar'))
], [fieldDefinition1], [
export const tabVarValueVisibilityJson = createTabVisibilityJson(
[createTab('71da814d-5580-4f1f-972a-8089253aeded', 'tabBasicVarValue', createVisibilityCondition('variable', 'stringVar'))],
[fieldDefinition1],
[
{
id: '803269e6-a568-40e2-aec3-75ad2f411688',
name: 'stringVar',
type: 'string',
value: 'showTab'
}
]);
]
);
export const tabVarFieldVisibilityJson = createTabVisibilityJson([
export const tabVarFieldVisibilityJson = createTabVisibilityJson(
[
createTab(
'71da814d-5580-4f1f-972a-8089253aeded',
'tabBasicVarField',
createVisibilityCondition('variable', 'stringVar', undefined, 'TextOne', 'field')
),
createTab('0e538a28-f8d6-4cb8-ae93-dbfb2efdf3b1', 'tabWithFields', null)
], fieldsDefinitions1, [
],
fieldsDefinitions1,
[
{
id: '803269e6-a568-40e2-aec3-75ad2f411688',
name: 'stringVar',
type: 'string',
value: 'showTab'
}
]);
]
);
export const tabFieldFieldVisibilityJson = createTabVisibilityJson([
export const tabFieldFieldVisibilityJson = createTabVisibilityJson(
[
createTab(
'71da814d-5580-4f1f-972a-8089253aeded',
'tabBasicFieldField',
createVisibilityCondition('field', 'TextThree', undefined, 'TextOne', 'field')
),
createTab('442eea0b-65f9-484e-b37f-f5a91d5e1f21', 'tabWithFields', null)
], fieldsDefinitions2);
],
fieldsDefinitions2
);
export const tabFieldVarVisibilityJson = createTabVisibilityJson([
export const tabFieldVarVisibilityJson = createTabVisibilityJson(
[
createTab(
'71da814d-5580-4f1f-972a-8089253aeded',
'tabBasicVarField',
createVisibilityCondition('field', 'TextOne', undefined, 'stringVar', 'variable')
),
createTab('0e538a28-f8d6-4cb8-ae93-dbfb2efdf3b1', 'tabWithFields', null)
], fieldsDefinitions1, [
],
fieldsDefinitions1,
[
{
id: '803269e6-a568-40e2-aec3-75ad2f411688',
name: 'stringVar',
type: 'string',
value: 'showTab'
}
]);
]
);
export const tabVarVarVisibilityJson = createTabVisibilityJson([
export const tabVarVarVisibilityJson = createTabVisibilityJson(
[
createTab(
'ef512cb3-0c41-4d12-84ef-a7ef8f0b111a',
'tabBasicVarVar',
createVisibilityCondition('variable', 'showTabOne', undefined, 'showTabTwo', 'variable')
)
], [
],
[
createFieldDefinition('6eeb9e54-e51d-44f3-9557-503308f07361', 'ef512cb3-0c41-4d12-84ef-a7ef8f0b111a', {
1: [createField('TextOne', 'TextOne')],
2: []
})
], [
],
[
{
id: 'b116df99-f6b5-45f8-b48c-15b74f7f1c92',
name: 'showTabOne',
@ -194,13 +226,17 @@ export const tabVarVarVisibilityJson = createTabVisibilityJson([
type: 'string',
value: 'showTab'
}
]);
]
);
export const tabNextOperatorsVisibilityJson = createTabVisibilityJson([
export const tabNextOperatorsVisibilityJson = createTabVisibilityJson(
[
createTab(
'71da814d-5580-4f1f-972a-8089253aeded',
'tabNextOperators',
createVisibilityCondition('field', 'TextOne', createVisibilityCondition('field', 'TextThree', null, 'showTab', 'value', '!='))
),
createTab('442eea0b-65f9-484e-b37f-f5a91d5e1f21', 'tabWithFields', null)
], fieldsDefinitions2);
],
fieldsDefinitions2
);

View File

@ -318,6 +318,7 @@ describe('Search Number Range Filter', () => {
expect(await sizeRangeFilter.getFromNumber()).toEqual('');
expect(await sizeRangeFilter.getToNumber()).toEqual('');
await dataTable.waitTillContentLoaded();
const resultsSize = (await dataTable.geCellElementDetail('Size')) as ElementFinder[];
for (const currentResult of resultsSize) {
const currentSize = await BrowserActions.getAttribute(currentResult, 'title');

View File

@ -99,7 +99,7 @@ describe('Search Slider Filter', () => {
});
it('[C276972] Should be keep value when Search Size Slider is collapsed', async () => {
const size = 5;
const size = 10;
await searchFilters.checkSizeSliderFilterIsDisplayed();
await searchFilters.clickSizeSliderFilterHeader();
@ -107,9 +107,9 @@ describe('Search Slider Filter', () => {
await sizeSliderFilter.setValue(size);
await searchFilters.clickSizeSliderFilterHeader();
await searchFilters.checkSizeSliderFilterIsCollapsed();
await searchFilters.checkSizeSliderFilterIsDisplayed();
await searchFilters.clickSizeSliderFilterHeader();
await searchFilters.checkSizeSliderFilterIsExpanded();
await searchFilters.checkSizeSliderFilterIsDisplayed();
expect(await sizeSliderFilter.getValue()).toEqual(`${size}`);
});

View File

@ -23,7 +23,7 @@ export class SearchBarPage {
searchBar = $(`adf-search-control input`);
searchBarExpanded = TestElement.byCss(`adf-search-control ${materialLocators.Form.field.root}[class*="${materialLocators.Focused.root}"] input`);
noResultMessage = $(`p[class*='adf-search-fixed-text']`);
rowsAuthor = `${materialLocators.List.text.class} p[class*='adf-search-fixed-text']`;
rowsAuthor = `${materialLocators.List.content.class} p[class*='adf-search-fixed-text']`;
completeName = `h4[class*='adf-search-fixed-text']`;
highlightName = `.adf-highlight`;
searchBarPage = $(`${materialLocators.List.root}[id='autocomplete-search-result-list']`);

View File

@ -199,7 +199,7 @@ describe('Search Filters', () => {
it('[C287796] Should be able to display the correct bucket number after selecting a filter', async () => {
await BrowserActions.getUrl(`${browser.baseUrl}/search;q=*`);
await searchFiltersPage.fileTypeCheckListFiltersPage().clickCheckListOption('PNG Image');
await searchFiltersPage.fileTypeCheckListFiltersPage().clickCheckListOption('PNG');
const bucketNumberForFilter = await searchFiltersPage.fileTypeCheckListFiltersPage().getBucketNumberOfFilterType(filter.type);
const resultFileNames: any = await contentList.getAllRowsColumnValues('Display name');

View File

@ -4,12 +4,12 @@
"version": "6.9.0",
"author": "Hyland Software, Inc. and its affiliates",
"bin": {
"adf-cli": "./bin/adf-cli",
"adf": "./bin/adf-cli"
"adf-cli": "bin/adf-cli",
"adf": "bin/adf-cli"
},
"repository": {
"type": "git",
"url": "https://github.com/Alfresco/alfresco-ng2-components.git"
"url": "git+https://github.com/Alfresco/alfresco-ng2-components.git"
},
"bugs": {
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"

70
lib/cli/project.json Normal file
View File

@ -0,0 +1,70 @@
{
"name": "cli",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "lib/cli",
"projectType": "library",
"prefix": "adf",
"targets": {
"build": {
"executor": "nx:run-commands",
"options": {
"command": "cd lib/cli && npm i && npm run dist",
"stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"]
}
},
"configurations": {
"production": {
"tsConfig": "lib/cli/tsconfig.json"
}
},
"defaultConfiguration": "production"
},
"bundle": {
"executor": "nx:run-commands",
"options": {
"commands": [
{
"command": "echo cli bundle created"
}
]
},
"dependsOn": ["copyToNodeModules"]
},
"copyToNodeModules": {
"executor": "nx:run-commands",
"options": {
"commands": [
{
"command": "rm -rf ./node_modules/@alfresco/adf-cli/ && mkdir -p ./node_modules/@alfresco/adf-cli/ && cp -R ./dist/libs/cli/* ./node_modules/@alfresco/adf-cli/"
}
]
},
"dependsOn": [
{
"projects": "self",
"target": "build"
}
]
},
"lint": {
"executor": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": ["lib/cli/**/*.ts", "lib/cli/**/*.html"]
}
},
"npm-publish": {
"executor": "nx:run-commands",
"dependsOn": ["build"],
"options": {
"cwd": "dist/libs/cli",
"commands": [
{
"command": "npm publish --tag {args.tag}",
"forwardAllArgs": true
}
]
}
}
}
}

View File

@ -1,9 +1,27 @@
const rootMain = require('../../../.storybook/main');
var rootPath = require('../../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
stories: [...rootMain.stories, '../**/*.stories.@(js|jsx|ts|tsx)'],
staticDirs: [...rootMain.staticDirs, { from: __dirname + '/../src/lib/i18n', to: 'assets/adf-content-services/i18n' }],
addons: [...rootMain.addons]
rootMain: rootPath,
stories: [...rootPath.stories, '../**/*.stories.@(js|jsx|ts|tsx)'],
staticDirs: [
...rootPath.staticDirs,
{ from: __dirname + '/../src/lib/i18n', to: 'assets/adf-core/i18n' },
{ from: __dirname + '/../src/lib/assets/images', to: 'assets/images' }
],
addons: ['@storybook/addon-essentials', ...rootPath.addons],
framework: {
name: '@storybook/angular',
options: {}
},
docs: {
autodocs: true
},
core: {
builder: '@storybook/builder-webpack5'
}
};

View File

@ -1,6 +1,6 @@
import { addons } from '@storybook/addons';
import { addons } from '@storybook/manager-api';
import alfrescoTheme from '../../../.storybook/alfrescoTheme';
addons.setConfig({
theme: alfrescoTheme,
theme: alfrescoTheme
});

View File

@ -0,0 +1,111 @@
{
"name": "content-services",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "lib/content-services/src",
"projectType": "library",
"prefix": "adf",
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "lib/content-services/tsconfig.lib.json",
"project": "lib/content-services/ng-package.json"
},
"configurations": {
"production": {
"project": "lib/content-services/ng-package.json",
"tsConfig": "lib/content-services/tsconfig.lib.prod.json"
}
},
"defaultConfiguration": "production"
},
"test": {
"executor": "@angular-devkit/build-angular:karma",
"options": {
"main": "lib/content-services/src/test.ts",
"tsConfig": "lib/content-services/tsconfig.spec.json",
"karmaConfig": "lib/content-services/karma.conf.js",
"sourceMap": true,
"codeCoverage": true,
"stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"]
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": ["lib/content-services/**/*.ts", "lib/content-services/**/*.html"]
}
},
"storybook": {
"executor": "@storybook/angular:start-storybook",
"options": {
"port": 4400,
"browserTarget": "content-services:storybook",
"configDir": "lib/content-services/.storybook",
"compodoc": false,
"styles": [
"demo-shell/src/styles.scss",
"demo-shell/src/custom-style-dev.scss",
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"]
}
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-storybook": {
"executor": "@storybook/angular:build-storybook",
"options": {
"browserTarget": "content-services:build-storybook",
"configDir": "lib/content-services/.storybook",
"outputDir": "dist/storybook/content-services",
"compodoc": false,
"styles": [
"demo-shell/src/styles.scss",
"demo-shell/src/custom-style-dev.scss",
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"]
}
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"stylelint": {
"executor": "nx:run-commands",
"options": {
"commands": [
{
"command": "npx stylelint lib/content-services/**/*.scss --config stylelint-config.json"
}
]
}
},
"npm-publish": {
"executor": "nx:run-commands",
"dependsOn": ["build"],
"options": {
"cwd": "dist/libs/content-services",
"commands": [
{
"command": "npm publish --tag {args.tag}",
"forwardAllArgs": true
}
]
}
}
}
}

View File

@ -1,3 +1,13 @@
@import 'styles/mat-selectors';
adf-aspect-list-dialog {
display: block;
#{$mat-expansion-panel-body} {
margin-top: -2px;
}
}
.adf {
&-aspect-list-dialog-title {
font-size: large;
@ -13,21 +23,34 @@
&-aspect-list-dialog-information {
display: flex;
justify-content: space-between;
padding-left: 5px;
padding-right: 5px;
padding-bottom: 4px;
padding-left: 4px;
padding-right: 4px;
font-size: small;
}
&-aspect-list-dialog {
justify-content: space-between;
padding-left: 4px;
padding-right: 4px;
padding-top: 0;
#{$mat-dialog-content} {
padding: 0;
}
&::before {
display: none;
}
}
&-aspect-dialog-content {
padding-top: 3px;
margin-bottom: 8px;
.adf-aspect-property-table {
.adf-aspect-property-table-cell {
font-size: smaller;
color: var(--adf-theme-foreground-text-color-087);
}
.adf-aspect-property-table-column {

View File

@ -27,6 +27,7 @@ import { AspectEntry, Node } from '@alfresco/js-api';
import { NodesApiService } from '../common/services/nodes-api.service';
import { By } from '@angular/platform-browser';
import { AspectListComponent } from './aspect-list.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
const aspectListMock: AspectEntry[] = [
{
@ -113,7 +114,7 @@ describe('AspectListDialogComponent', () => {
excludedAspects: []
};
await TestBed.configureTestingModule({
imports: [ContentTestingModule, MatDialogModule],
imports: [HttpClientTestingModule, ContentTestingModule, MatDialogModule],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: data },
{

View File

@ -1,3 +1,4 @@
@import 'styles/mat-selectors';
$dialog-title-height: 100px;
$dialog-information-height: 44px;
$dialog-buttons-height: 68px;
@ -30,6 +31,7 @@ $dialog-list-height: calc(65vh - ($dialog-title-height + $dialog-information-hei
}
.adf-aspect-list-element-title {
font-size: smaller;
display: flex;
align-items: center;
}
@ -37,8 +39,14 @@ $dialog-list-height: calc(65vh - ($dialog-title-height + $dialog-information-hei
.adf-accordion-aspect-list-expansion-panel {
margin: 0;
#{$mat-checkbox-background} {
height: 16px;
width: 16px;
}
&-header {
font-size: smaller;
padding-left: 12px;
}
&-header-title {
@ -59,17 +67,28 @@ $dialog-list-height: calc(65vh - ($dialog-title-height + $dialog-information-hei
&-aspect-property-table {
width: 100%;
.adf-aspect-property-table-column-name,
.adf-aspect-property-table-column-title,
.adf-aspect-property-table-column-data-type {
font-size: 12px;
color: var(--adf-theme-foreground-text-color-054);
}
.adf-aspect-property-table-column {
&-name {
width: 15%;
padding-left: 24px;
padding-right: 0;
}
&-title {
width: 65%;
padding: 0;
}
&-data-type {
width: 20%;
padding-right: 24px;
padding-left: 10px;
}
}

View File

@ -16,31 +16,29 @@
*/
import { TestBed } from '@angular/core/testing';
import { AlfrescoApiService, CoreTestingModule } from '@alfresco/adf-core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { AspectListService } from './aspect-list.service';
import { AspectPaging, AspectsApi, AspectEntry } from '@alfresco/js-api';
import { HttpClientTestingModule } from '@angular/common/http/testing';
const stdAspect1: AspectEntry = { entry: { id: 'std:standardAspectOne', description: 'Standard Aspect One', title: 'StandardAspectOne' } };
const stdAspect2: AspectEntry = { entry: { id: 'std:standardAspectTwo', description: 'Standard Aspect Two', title: 'StandardAspectTwo' } };
const stdAspect3: AspectEntry = { entry: { id: 'std:standardAspectThree', description: 'Standard Aspect Three', title: 'StandardAspectThree' } };
const standardAspectPagingMock: AspectPaging = { list: { entries: [ stdAspect1, stdAspect2, stdAspect3 ] } };
const standardAspectPagingMock: AspectPaging = { list: { entries: [stdAspect1, stdAspect2, stdAspect3] } };
const cstAspect1: AspectEntry = { entry: { id: 'cst:customAspectOne', description: 'Custom Aspect One', title: 'CustomAspectOne' } };
const cstAspect2: AspectEntry = { entry: { id: 'cst:customAspectTwo', description: 'Custom Aspect Two', title: 'CustomAspectTwo' } };
const cstAspect3: AspectEntry = { entry: { id: 'cst:customAspectThree', description: 'Custom Aspect Three', title: 'CustomAspectThree' } };
const customAspectPagingMock: AspectPaging = { list: { entries: [ cstAspect1, cstAspect2, cstAspect3 ] } };
const customAspectPagingMock: AspectPaging = { list: { entries: [cstAspect1, cstAspect2, cstAspect3] } };
describe('AspectListService', () => {
let aspectListService: AspectListService;
let apiService: AlfrescoApiService;
let aspectsApi: AspectsApi;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CoreTestingModule
]
imports: [HttpClientTestingModule]
});
aspectListService = TestBed.inject(AspectListService);

View File

@ -18,6 +18,7 @@
<mat-select
#dropdown
*ngIf="hasPreviousNodes()"
panelClass="adf-breadcrumb-dropdown-panel"
class="adf-dropdown-breadcrumb-path-select"
tabindex="-1"
role="button"

View File

@ -1,3 +1,5 @@
@import 'styles/mat-selectors';
$dropdown-horizontal-offset: 30px;
.adf {
@ -47,7 +49,6 @@ $dropdown-horizontal-offset: 30px;
width: 0;
height: 0;
overflow: hidden;
margin-top: 35px;
&-select {
width: 0;
@ -64,8 +65,6 @@ $dropdown-horizontal-offset: 30px;
}
&-dropdown-breadcrumb-path-option.adf-dropdown-breadcrumb-path-option-node {
height: 28px;
line-height: 28px;
padding: 0 12px;
font-size: var(--theme-caption-font-size);
}
@ -98,3 +97,7 @@ $dropdown-horizontal-offset: 30px;
margin-right: $dropdown-horizontal-offset;
}
}
#{$cdk-overlay-pane}:has(>.adf-breadcrumb-dropdown-panel){
min-width: fit-content;
}

View File

@ -1,8 +1,6 @@
<div class="adf-categories-management">
<div *ngIf="categoryNameControlVisible" class="adf-category-name-field">
<input #categoryNameInput
matInput
autocomplete="off"
[formControl]="categoryNameControl"
(keyup.enter)="addCategory()"
placeholder="{{'CATEGORIES_MANAGEMENT.CATEGORIES_SEARCH_PLACEHOLDER' | translate }}"
@ -10,7 +8,7 @@
/>
<mat-error *ngIf="categoryNameControl.invalid">{{ categoryNameErrorMessageKey | translate }}</mat-error>
</div>
<div class="adf-categories-list" [class.adf-categories-list-fixed]="!categoryNameControlVisible">
<div class="adf-categories-list" *ngIf="categories?.length > 0" [class.adf-categories-list-fixed]="!categoryNameControlVisible">
<span
*ngFor="let category of categories"
[class.adf-categories-padded]="!isCRUDMode"

View File

@ -1,17 +1,27 @@
.adf-categories-management {
padding-top: 12px;
@import 'styles/mat-selectors';
.adf-categories-management {
.adf-category-name-field {
justify-content: space-between;
width: 100%;
color: var(--adf-metadata-property-panel-text-color);
background: var(--adf-metadata-buttons-background-color);
height: 32px;
border-radius: 12px;
align-items: center;
display: flex;
flex-direction: column;
margin-right: 12px;
input {
background: var(--adf-metadata-buttons-background-color);
border-radius: 12px;
padding: 7px 8px;
border: none;
outline: none;
font: inherit;
color: currentcolor;
margin: 0;
vertical-align: bottom;
text-align: inherit;
box-sizing: content-box;
}
#{$mat-form-field-error} {
padding-top: 5px;
}
}
@ -46,7 +56,7 @@
background-color: inherit;
color: inherit;
&:hover {
&:not(#{$mat-list-item-disabled}):hover {
cursor: pointer;
background: var(--adf-theme-mat-grey-color-a200);
}
@ -68,9 +78,15 @@
}
.adf-existing-categories-panel {
min-height: 22vh;
.adf-create-category-label {
color: var(--theme-primary-color);
cursor: pointer;
overflow-wrap: anywhere;
}
#{$mat-list-item-disabled} #{$mat-list-item-primary-text} {
opacity: 1;
}
}

View File

@ -49,11 +49,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<void>();
private _categoryNameControl = new FormControl<string>(
'',
[
this.validateIfNotAlreadyAdded.bind(this),
this.validateEmptyCategory,
Validators.required
],
[this.validateIfNotAlreadyAdded.bind(this), this.validateEmptyCategory, Validators.required],
this.validateIfNotAlreadyCreated.bind(this)
);
private _existingCategories: Category[];
@ -150,9 +146,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
)
.subscribe((name: string) => this.onNameControlValueChange(name));
this.categoryNameControl.statusChanges
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => this.setCategoryNameControlErrorMessageKey());
this.categoryNameControl.statusChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.setCategoryNameControlErrorMessageKey());
this.setCategoryNameControlErrorMessageKey();
@ -164,9 +158,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
this._categoryNameControl.removeValidators(Validators.required);
this.categories.forEach((category) => this.initialCategories.push(category));
if (this.classifiableChanged) {
this.classifiableChanged
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => {
this.classifiableChanged.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
this.categories = [];
this.categoryNameControlVisible = false;
this.categoryNameControlVisibleChange.emit(false);
@ -237,12 +229,14 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
* @param category - selection list change containing selected category
*/
addCategoryToAssign(category: Category) {
if (!(this.isCRUDMode || (!this.multiSelect && this.categories.length > 0))) {
const selectedCategory: Category = category;
this.categories.push(selectedCategory);
this._existingCategories.splice(this._existingCategories.indexOf(selectedCategory), 1);
this.categoryNameControl.updateValueAndValidity();
this.categoriesChange.emit(this.categories);
}
}
/**
* Removes the category from categories list and adds it to existing categories list in ASSIGN mode.
@ -275,7 +269,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
}
private searchForExistingCategories(searchTerm: string) {
this.categoryService.searchCategories(searchTerm, 0 , this.existingCategoriesListLimit).subscribe((existingCategoriesResult) => {
this.categoryService.searchCategories(searchTerm, 0, this.existingCategoriesListLimit).subscribe((existingCategoriesResult) => {
this._existingCategories = existingCategoriesResult.list.entries.map((rowEntry) => {
const existingCat = new Category();
existingCat.id = rowEntry.entry.id;
@ -283,7 +277,9 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
existingCat.name = path ? `${path}/${rowEntry.entry.name}` : rowEntry.entry.name;
return existingCat;
});
this._existingCategories = this._existingCategories.filter((existingCat) => this.categories.find((category) => existingCat.id === category.id) === undefined);
this._existingCategories = this._existingCategories.filter(
(existingCat) => this.categories.find((category) => existingCat.id === category.id) === undefined
);
this.sortCategoriesList(this._existingCategories);
this._existingCategoriesLoading = false;
this._typing = false;
@ -294,7 +290,9 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
private getChildrenCategories(searchTerm: string) {
this.categoryService.getSubcategories(this.parentId).subscribe((childrenCategories) => {
this._existingCategories = childrenCategories.list.entries.map((categoryEntry) => categoryEntry.entry);
this._existingCategories = this._existingCategories.filter((existingCat) => existingCat.name.toLowerCase().includes(searchTerm.toLowerCase()));
this._existingCategories = this._existingCategories.filter((existingCat) =>
existingCat.name.toLowerCase().includes(searchTerm.toLowerCase())
);
this.sortCategoriesList(this._existingCategories);
this._existingCategoriesLoading = false;
this._typing = false;
@ -310,9 +308,11 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
private validateIfNotAlreadyCreated(nameControl: FormControl<string>): Observable<CategoryNameControlErrors | null> {
return this.existingCategoryLoaded$.pipe(
map<void, CategoryNameControlErrors | null>(() => this.existingCategories.some((category) => this.compareCategories(category, nameControl.value)) && this.isCRUDMode
map<void, CategoryNameControlErrors | null>(() =>
this.existingCategories.some((category) => this.compareCategories(category, nameControl.value)) && this.isCRUDMode
? { duplicatedExistingCategory: true }
: null),
: null
),
first()
);
}
@ -322,9 +322,7 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy {
}
private validateEmptyCategory(categoryNameControl: FormControl<string>): CategoryNameControlErrors | null {
return categoryNameControl.value.length && !categoryNameControl.value.trim()
? { emptyCategory: true }
: null;
return categoryNameControl.value.length && !categoryNameControl.value.trim() ? { emptyCategory: true } : null;
}
private setCategoryNameControlErrorMessageKey() {

View File

@ -15,7 +15,6 @@
* limitations under the License.
*/
import { CoreTestingModule } from '@alfresco/adf-core';
import { fakeAsync, TestBed } from '@angular/core/testing';
import { CategoryService } from '../services/category.service';
import { CategoryNode, CategoryTreeDatasourceService } from '@alfresco/adf-content-services';
@ -30,12 +29,7 @@ describe('CategoryTreeDatasourceService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CoreTestingModule
],
providers: [
{ provide: CategoryService, useClass: CategoryServiceMock }
]
providers: [CategoryTreeDatasourceService, { provide: CategoryService, useClass: CategoryServiceMock }]
});
categoryTreeDatasourceService = TestBed.inject(CategoryTreeDatasourceService);
@ -44,7 +38,7 @@ describe('CategoryTreeDatasourceService', () => {
it('should get root level categories', fakeAsync(() => {
spyOn(categoryTreeDatasourceService, 'getParentNode').and.returnValue(undefined);
categoryTreeDatasourceService.getSubNodes(null, 0 , 100).subscribe((treeResponse: TreeResponse<CategoryNode>) => {
categoryTreeDatasourceService.getSubNodes(null, 0, 100).subscribe((treeResponse: TreeResponse<CategoryNode>) => {
expect(treeResponse.entries.length).toBe(1);
expect(treeResponse.entries[0].level).toBe(0);
expect(treeResponse.entries[0].nodeType).toBe(TreeNodeType.RegularNode);
@ -62,7 +56,7 @@ describe('CategoryTreeDatasourceService', () => {
nodeType: TreeNodeType.RegularNode
};
spyOn(categoryTreeDatasourceService, 'getParentNode').and.returnValue(parentNode);
categoryTreeDatasourceService.getSubNodes(parentNode.id, 0 , 100).subscribe((treeResponse: TreeResponse<CategoryNode>) => {
categoryTreeDatasourceService.getSubNodes(parentNode.id, 0, 100).subscribe((treeResponse: TreeResponse<CategoryNode>) => {
expect(treeResponse.entries.length).toBe(2);
expect(treeResponse.entries[0].parentId).toBe(parentNode.id);
expect(treeResponse.entries[0].level).toBe(1);
@ -84,7 +78,8 @@ describe('CategoryTreeDatasourceService', () => {
});
it('should call getCategory for every instance if value of name parameter is defined', (done) => {
spyOn(categoryService, 'getCategory').and.returnValues(of({
spyOn(categoryService, 'getCategory').and.returnValues(
of({
entry: {
name: 'name',
id: 'some id 1',
@ -97,10 +92,9 @@ describe('CategoryTreeDatasourceService', () => {
id: 'some id 2',
hasChildren: false
}
}));
categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name')
.subscribe(() => {
})
);
categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name').subscribe(() => {
expect(categoryService.getCategory).toHaveBeenCalledWith('some id 1');
expect(categoryService.getCategory).toHaveBeenCalledWith('some id 2');
done();
@ -108,7 +102,8 @@ describe('CategoryTreeDatasourceService', () => {
});
it('should return observable which emits correct categories', (done) => {
spyOn(categoryService, 'getCategory').and.returnValues(of({
spyOn(categoryService, 'getCategory').and.returnValues(
of({
entry: {
name: 'some name',
id: 'some id 1',
@ -121,14 +116,15 @@ describe('CategoryTreeDatasourceService', () => {
id: 'some id 2',
hasChildren: false
}
}));
categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name')
.subscribe((response) => {
})
);
categoryTreeDatasourceService.getSubNodes('id', undefined, undefined, 'name').subscribe((response) => {
const pagination = new Pagination();
pagination.count = 2;
expect(response).toEqual({
pagination,
entries: [{
entries: [
{
id: 'some id 1',
nodeName: 'some name',
parentId: 'parent id 1',
@ -136,7 +132,8 @@ describe('CategoryTreeDatasourceService', () => {
nodeType: TreeNodeType.RegularNode,
hasChildren: true,
isLoading: false
}, {
},
{
id: 'some id 2',
nodeName: 'Language/some other name',
parentId: 'parent id 2',
@ -144,7 +141,8 @@ describe('CategoryTreeDatasourceService', () => {
nodeType: TreeNodeType.RegularNode,
hasChildren: false,
isLoading: false
}]
}
]
});
done();
});

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { AppConfigService, CoreTestingModule, UserPreferencesService } from '@alfresco/adf-core';
import { AppConfigService, TranslationMock, TranslationService, UserPreferencesService } from '@alfresco/adf-core';
import {
CategoryBody,
CategoryEntry,
@ -29,6 +29,8 @@ import {
} from '@alfresco/js-api';
import { fakeAsync, TestBed } from '@angular/core/testing';
import { CategoryService } from './category.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TranslateModule } from '@ngx-translate/core';
describe('CategoryService', () => {
let categoryService: CategoryService;
@ -44,7 +46,8 @@ describe('CategoryService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule]
imports: [HttpClientTestingModule, TranslateModule.forRoot()],
providers: [CategoryService, UserPreferencesService, { provide: TranslationService, useClass: TranslationMock }]
});
categoryService = TestBed.inject(CategoryService);

View File

@ -17,8 +17,10 @@
import { TestBed } from '@angular/core/testing';
import { ContentService } from './content.service';
import { AppConfigService, AuthenticationService, StorageService, CoreTestingModule } from '@alfresco/adf-core';
import { AppConfigService, AuthenticationService, RedirectAuthService, StorageService } from '@alfresco/adf-core';
import { Node, PermissionsInfo } from '@alfresco/js-api';
import { EMPTY, of } from 'rxjs';
import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('ContentService', () => {
let contentService: ContentService;
@ -27,7 +29,8 @@ describe('ContentService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule]
imports: [HttpClientTestingModule],
providers: [ContentService, AuthenticationService, { provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }]
});
authService = TestBed.inject(AuthenticationService);
contentService = TestBed.inject(ContentService);

View File

@ -16,10 +16,12 @@
*/
import { fakeEcmUser } from '../mocks/ecm-user.service.mock';
import { AlfrescoApiService, AlfrescoApiServiceMock, CoreTestingModule } from '@alfresco/adf-core';
import { AlfrescoApiService, AlfrescoApiServiceMock, RedirectAuthService } from '@alfresco/adf-core';
import { PeopleContentQueryRequestModel, PeopleContentService } from './people-content.service';
import { TestBed } from '@angular/core/testing';
import { PersonPaging } from '@alfresco/js-api';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { EMPTY, of } from 'rxjs';
export const fakeEcmUser2 = {
id: 'another-fake-id',
@ -66,8 +68,12 @@ describe('PeopleContentService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule],
providers: [{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }]
imports: [HttpClientTestingModule],
providers: [
PeopleContentService,
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }
]
});
peopleContentService = TestBed.inject(PeopleContentService);

View File

@ -257,17 +257,14 @@ export class RenditionService {
printFile(url: string, type: string): void {
const pwa = window.open(url, RenditionService.TARGET);
if (pwa) {
// Because of the way chrome focus and close image window vs. pdf preview window
pwa.onload = () => {
pwa.print();
if (type === RenditionService.ContentGroup.IMAGE) {
pwa.onfocus = () => {
// Because of the way chrome focus and close image window vs. pdf preview window
setTimeout(() => {
pwa.close();
}, 500);
};
}
pwa.onload = () => {
pwa.print();
};
}
}

View File

@ -17,12 +17,13 @@
import { EventEmitter } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { AppConfigService, CoreTestingModule } from '@alfresco/adf-core';
import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigModule, AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core';
import { UploadService } from './upload.service';
import { RepositoryInfo } from '@alfresco/js-api';
import { BehaviorSubject } from 'rxjs';
import { DiscoveryApiService } from '../../common/services/discovery-api.service';
import { FileModel, FileUploadStatus } from '../../common/models/file.model';
import { HttpClientTestingModule } from '@angular/common/http/testing';
declare let jasmine: any;
@ -35,8 +36,11 @@ describe('UploadService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule],
imports: [AppConfigModule, HttpClientTestingModule],
providers: [
UploadService,
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: AppConfigService, useClass: AppConfigServiceMock },
{
provide: DiscoveryApiService,
useValue: {
@ -281,9 +285,7 @@ describe('UploadService', () => {
service.cancelUpload(...file);
const request = jasmine.Ajax.requests.mostRecent();
expect(request.url).toBe(
'http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/fakeId/content?include=allowableOperations'
);
expect(request.url).toContain('ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/fakeId/content?include=allowableOperations');
expect(request.method).toBe('PUT');
jasmine.Ajax.requests.mostRecent().respondWith({
@ -338,8 +340,8 @@ describe('UploadService', () => {
service.uploadFilesInTheQueue(emitter);
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.url).toContain(
'/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/123/children?autoRename=true&include=allowableOperations'
);
expect(request.method).toBe('POST');

View File

@ -1,4 +1,4 @@
<mat-card *ngIf="node" class="adf-content-metadata-card-view">
<mat-card appearance="outlined" *ngIf="node" class="adf-content-metadata-card-view">
<mat-card-content class="adf-content-metadata-card-view-content">
<adf-content-metadata
[displayDefaultProperties]="displayDefaultProperties"

View File

@ -20,12 +20,23 @@ import { By } from '@angular/platform-browser';
import { Node } from '@alfresco/js-api';
import { ContentMetadataCardComponent } from './content-metadata-card.component';
import { ContentMetadataComponent } from '../content-metadata/content-metadata.component';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { SimpleChange } from '@angular/core';
import { APP_INITIALIZER, SimpleChange } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { NodeAspectService } from '../../../aspect-list/services/node-aspect.service';
import { ContentMetadataService } from '../../services/content-metadata.service';
import { AllowableOperationsEnum } from '../../../common/models/allowable-operations.enum';
import { of } from 'rxjs';
import { AlfrescoApiService, AlfrescoApiServiceMock, AuthModule, PipeModule, TranslationMock, TranslationService } from '@alfresco/adf-core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { versionCompatibilityFactory } from '../../../version-compatibility/version-compatibility-factory';
import { VersionCompatibilityService } from '../../../version-compatibility';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { CategoryService } from '../../../category';
import { TagService } from '../../../tag';
import { PropertyDescriptorsService } from '../../public-api';
describe('ContentMetadataCardComponent', () => {
let component: ContentMetadataCardComponent;
@ -34,15 +45,40 @@ describe('ContentMetadataCardComponent', () => {
let node: Node;
const preset = 'custom-preset';
let nodeAspectService: NodeAspectService = null;
let tagService: TagService = null;
let categoryService: CategoryService = null;
let propertyDescriptorsService: PropertyDescriptorsService = null;
const getToggleEditButton = () => fixture.debugElement.query(By.css('[data-automation-id="meta-data-card-toggle-edit"]'));
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
imports: [
TranslateModule.forRoot(),
NoopAnimationsModule,
AuthModule.forRoot({ useHash: true }),
HttpClientModule,
MatDialogModule,
PipeModule,
MatSnackBarModule,
MatTooltipModule
],
providers: [
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: TranslationService, useClass: TranslationMock },
{
provide: APP_INITIALIZER,
useFactory: versionCompatibilityFactory,
deps: [ VersionCompatibilityService ],
multi: true
}
]
});
fixture = TestBed.createComponent(ContentMetadataCardComponent);
contentMetadataService = TestBed.inject(ContentMetadataService);
tagService = TestBed.inject(TagService);
categoryService = TestBed.inject(CategoryService);
propertyDescriptorsService = TestBed.inject(PropertyDescriptorsService);
component = fixture.componentInstance;
node = {
aspectNames: [],
@ -59,6 +95,9 @@ describe('ContentMetadataCardComponent', () => {
component.editAspectSupported = true;
nodeAspectService = TestBed.inject(NodeAspectService);
spyOn(contentMetadataService, 'getContentTypeProperty').and.returnValue(of([]));
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of());
spyOn(categoryService, 'getCategoryLinksForNode').and.returnValue(of());
spyOn(propertyDescriptorsService, 'load').and.returnValue(of());
fixture.detectChanges();
});

View File

@ -100,7 +100,9 @@
</adf-content-metadata-header>
</mat-expansion-panel-header>
<div *ngIf="currentPanel.panelTitle === DefaultPanels.TAGS && !editing" class="adf-metadata-properties-tags">
<span *ngFor="let tag of tags" class="adf-metadata-properties-tag">{{ tag }}</span>
<mat-chip-set>
<mat-chip *ngFor="let tag of tags" [disableRipple]="true" class="metadata-properties-tag-chip" data-automation-id="metadata-properties-tag-chip">{{ tag }}</mat-chip>
</mat-chip-set>
</div>
<div *ngIf="showEmptyTagMessage" class="adf-metadata-no-item-added">
{{ 'METADATA.BASIC.NO_TAGS_ADDED' | translate }}

View File

@ -1,3 +1,5 @@
@import 'styles/mat-selectors';
$panel-properties-height: 56px !default;
.adf {
@ -8,9 +10,24 @@ $panel-properties-height: 56px !default;
border-radius: 12px;
margin: 12px;
adf-card-view-textitem {
#{$mat-form-field-subscript-wrapper} {
display: none;
}
#{$mat-form-field-infix} {
padding-bottom: 0;
}
}
.adf-property-list .adf-property .adf-property-field {
.adf-property-value:not(.adf-card-view-selectitem .adf-property-value) {
margin-top: 20px;
margin-top: 10px;
height: 32px;
&:is(textarea) {
padding-top: 6px;
}
}
label {
@ -30,28 +47,36 @@ $panel-properties-height: 56px !default;
}
}
#{$mat-expansion-panel-body} {
padding-top: 16px;
input {
border-color: transparent;
width: 100%;
&:focus-visible {
outline: none;
}
}
}
.adf-edit-icon-buttons {
color: var(--adf-theme-foreground-text-color-054);
}
.adf-metadata-properties-tag {
min-height: 32px;
display: inline-flex;
align-items: center;
border-radius: 16px;
width: fit-content;
#{$mat-chip} {
background: var(--adf-metadata-buttons-background-color);
margin-top: 12px;
padding: 6px 12px;
justify-content: center;
margin-left: 8px;
padding: 6px;
&.metadata-properties-tag-chip {
overflow-wrap: anywhere;
}
}
.adf-metadata-no-item-added {
word-break: break-all;
font-size: 15px;
padding: 16px 0 0 12px;
padding: 0 0 0 12px;
}
&-tags {

View File

@ -16,15 +16,25 @@
*/
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { DebugElement, SimpleChange } from '@angular/core';
import { SimpleChange } from '@angular/core';
import { By } from '@angular/platform-browser';
import { Category, CategoryPaging, ClassesApi, Node, Tag, TagBody, TagEntry, TagPaging, TagPagingList } from '@alfresco/js-api';
import { ContentMetadataComponent } from './content-metadata.component';
import { ContentMetadataService } from '../../services/content-metadata.service';
import { AppConfigService, CardViewBaseItemModel, CardViewComponent, NotificationService, UpdateNotification } from '@alfresco/adf-core';
import {
AppConfigService,
AuthModule,
CardViewBaseItemModel,
CardViewComponent,
NotificationService,
PipeModule,
TranslationMock,
TranslationService,
UpdateNotification
} from '@alfresco/adf-core';
import { NodesApiService } from '../../../common/services/nodes-api.service';
import { EMPTY, of, throwError } from 'rxjs';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { CardViewContentUpdateService } from '../../../common/services/card-view-content-update.service';
import { PropertyGroup } from '../../interfaces/property-group.interface';
import { PropertyDescriptorsService } from '../../services/property-descriptors.service';
@ -37,6 +47,14 @@ import {
TagService
} from '@alfresco/adf-content-services';
import { MatExpansionPanel } from '@angular/material/expansion';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness } from '@angular/material/chips/testing';
describe('ContentMetadataComponent', () => {
let component: ContentMetadataComponent;
@ -50,6 +68,7 @@ describe('ContentMetadataComponent', () => {
let categoryService: CategoryService;
let getClassSpy: jasmine.Spy;
let notificationService: NotificationService;
let getGroupedPropertiesSpy: jasmine.Spy;
const preset = 'custom-preset';
@ -72,7 +91,16 @@ describe('ContentMetadataComponent', () => {
const category2 = new Category({ id: 'test2', name: 'testCat2' });
const categoryPagingResponse: CategoryPaging = { list: { pagination: {}, entries: [{ entry: category1 }, { entry: category2 }] } };
const findTagElements = (): DebugElement[] => fixture.debugElement.queryAll(By.css('.adf-metadata-properties .adf-metadata-properties-tag'));
const findTagElements = async (): Promise<string[]> => {
const matChipHarnessList = await TestbedHarnessEnvironment.loader(fixture).getAllHarnesses(
MatChipHarness.with({ selector: '[data-automation-id="metadata-properties-tag-chip"]' })
);
const tags = [];
for (const matChip of matChipHarnessList) {
tags.push(await matChip.getText());
}
return tags;
};
const findCancelButton = (): HTMLButtonElement => fixture.debugElement.query(By.css('[data-automation-id=reset-metadata]')).nativeElement;
const findCancelTagsButton = (): HTMLButtonElement =>
@ -158,8 +186,19 @@ describe('ContentMetadataComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule],
imports: [
TranslateModule.forRoot(),
NoopAnimationsModule,
AuthModule.forRoot({ useHash: true }),
HttpClientModule,
MatDialogModule,
MatSnackBarModule,
MatProgressBarModule,
MatTooltipModule,
PipeModule
],
providers: [
{ provide: TranslationService, useClass: TranslationMock },
{
provide: TagService,
useValue: {
@ -210,6 +249,7 @@ describe('ContentMetadataComponent', () => {
component.node = node;
component.preset = preset;
spyOn(contentMetadataService, 'getContentTypeProperty').and.returnValue(of([]));
getGroupedPropertiesSpy = spyOn(contentMetadataService, 'getGroupedProperties');
getClassSpy = spyOn(classesApi, 'getClass');
fixture.detectChanges();
});
@ -231,6 +271,7 @@ describe('ContentMetadataComponent', () => {
describe('Folder', () => {
it('should show the folder node', (done) => {
component.expanded = false;
getGroupedPropertiesSpy.and.returnValue(of([]));
fixture.detectChanges();
component.basicProperties$.subscribe(() => {
@ -258,7 +299,7 @@ describe('ContentMetadataComponent', () => {
it('nodeAspectUpdate', fakeAsync(() => {
const fakeNode = { id: 'fake-minimal-node', aspectNames: ['ft:a', 'ft:b', 'ft:c'], name: 'fake-node' } as Node;
spyOn(contentMetadataService, 'getGroupedProperties').and.stub();
getGroupedPropertiesSpy.and.stub();
spyOn(contentMetadataService, 'getBasicProperties').and.stub();
updateService.updateNodeAspect(fakeNode);
@ -268,7 +309,7 @@ describe('ContentMetadataComponent', () => {
}));
it('should save changedProperties on save click', fakeAsync(() => {
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@ -350,6 +391,8 @@ describe('ContentMetadataComponent', () => {
it('should throw error on unsuccessful save', fakeAsync(() => {
component.readOnly = false;
const property = { key: 'properties.property-key', value: 'original-value' } as CardViewBaseItemModel;
spyOn(nodesApiService, 'updateNode').and.returnValue(throwError(new Error('My bad')));
updateService.update(property, 'updated-value');
tick(600);
@ -359,8 +402,6 @@ describe('ContentMetadataComponent', () => {
sub.unsubscribe();
});
spyOn(nodesApiService, 'updateNode').and.returnValue(throwError(new Error('My bad')));
fixture.detectChanges();
toggleEditModeForGeneralInfo();
fixture.whenStable().then(() => clickOnGeneralInfoSave());
@ -456,7 +497,7 @@ describe('ContentMetadataComponent', () => {
beforeEach(() => {
showErrorSpy = spyOn(notificationService, 'showError').and.stub();
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@ -612,7 +653,7 @@ describe('ContentMetadataComponent', () => {
});
it('should reset group edit ability on reset click', () => {
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@ -684,7 +725,7 @@ describe('ContentMetadataComponent', () => {
});
it('should load the group properties on node change', () => {
spyOn(contentMetadataService, 'getGroupedProperties');
getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@ -708,7 +749,7 @@ describe('ContentMetadataComponent', () => {
}
];
component.preset = presetConfig;
spyOn(contentMetadataService, 'getGroupedProperties');
getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@ -719,7 +760,7 @@ describe('ContentMetadataComponent', () => {
const expectedProperties = [];
component.expanded = true;
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of([{ properties: expectedProperties } as any]));
getGroupedPropertiesSpy.and.returnValue(of([{ properties: expectedProperties } as any]));
spyOn(component, 'showGroup').and.returnValue(true);
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@ -733,7 +774,7 @@ describe('ContentMetadataComponent', () => {
component.expanded = true;
component.displayEmpty = false;
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of([{ properties: [] } as any]));
getGroupedPropertiesSpy.and.returnValue(of([{ properties: [] } as any]));
spyOn(component, 'showGroup').and.returnValue(true);
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@ -744,7 +785,7 @@ describe('ContentMetadataComponent', () => {
});
it('should hide card views group when the grouped properties are empty', async () => {
spyOn(contentMetadataService, 'getGroupedProperties').and.stub();
getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@ -757,7 +798,7 @@ describe('ContentMetadataComponent', () => {
it('should display card views group when there is at least one property that is not empty', async () => {
component.expanded = true;
spyOn(contentMetadataService, 'getGroupedProperties').and.stub();
getGroupedPropertiesSpy.and.stub();
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
@ -779,7 +820,7 @@ describe('ContentMetadataComponent', () => {
});
it('should reload properties for group panel on cancel', () => {
const getGroupedPropertiesSpy = spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(
getGroupedPropertiesSpy.and.returnValue(
of([
{
editable: true,
@ -947,6 +988,7 @@ describe('ContentMetadataComponent', () => {
component.expanded = true;
component.preset = 'default';
getGroupedPropertiesSpy.and.callThrough();
});
it('should show Versionable with given content-metadata config', async () => {
@ -1200,32 +1242,32 @@ describe('ContentMetadataComponent', () => {
component.displayTags = true;
});
it('should render tags after loading tags in ngOnInit', () => {
it('should render tags after loading tags in ngOnInit', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnInit();
fixture.detectChanges();
expandTagsPanel();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(2);
expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag);
expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag);
expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagService.getTagsByNodeId).toHaveBeenCalledWith(node.id);
});
it('should not render tags after loading tags in ngOnInit if displayTags is false', () => {
it('should not render tags after loading tags in ngOnInit if displayTags is false', async () => {
component.displayTags = false;
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnInit();
fixture.detectChanges();
expandTagsPanel();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
it('should render tags after loading tags in ngOnChanges', () => {
it('should render tags after loading tags in ngOnChanges', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({
@ -1234,14 +1276,14 @@ describe('ContentMetadataComponent', () => {
fixture.detectChanges();
expandTagsPanel();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(2);
expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag);
expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag);
expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagService.getTagsByNodeId).toHaveBeenCalledWith(node.id);
});
it('should not render tags after loading tags in ngOnChanges if displayTags is false', () => {
it('should not render tags after loading tags in ngOnChanges if displayTags is false', async () => {
component.displayTags = false;
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({
@ -1250,23 +1292,23 @@ describe('ContentMetadataComponent', () => {
expandTagsPanel();
fixture.detectChanges();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
it('should not render tags after loading tags in ngOnChanges if node is not changed', () => {
it('should not render tags after loading tags in ngOnChanges if node is not changed', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({});
expandTagsPanel();
fixture.detectChanges();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
it('should not render tags after loading tags in ngOnChanges if node is changed first time', () => {
it('should not render tags after loading tags in ngOnChanges if node is changed first time', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnChanges({
node: new SimpleChange(undefined, node, true)
@ -1274,12 +1316,12 @@ describe('ContentMetadataComponent', () => {
expandTagsPanel();
fixture.detectChanges();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(0);
expect(tagService.getTagsByNodeId).not.toHaveBeenCalled();
});
it('should render tags after loading tags after clicking on Cancel button', fakeAsync(() => {
it('should render tags after loading tags after clicking on Cancel button', fakeAsync(async () => {
component.readOnly = false;
fixture.detectChanges();
toggleEditModeForTags();
@ -1293,14 +1335,14 @@ describe('ContentMetadataComponent', () => {
fixture.detectChanges();
expandTagsPanel();
const tagElements = findTagElements();
const tagElements = await findTagElements();
expect(tagElements).toHaveSize(2);
expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag);
expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag);
expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag);
expect(tagService.getTagsByNodeId).toHaveBeenCalledOnceWith(node.id);
}));
it('should be hidden when editable is true', () => {
it('should be hidden when editable is true', async () => {
spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging));
component.ngOnInit();
component.readOnly = false;
@ -1308,7 +1350,7 @@ describe('ContentMetadataComponent', () => {
toggleEditModeForTags();
fixture.detectChanges();
expect(findTagElements()).toHaveSize(0);
expect(await findTagElements()).toHaveSize(0);
});
});

View File

@ -33,15 +33,17 @@ describe('PropertyDescriptorLoaderService', () => {
classesApi = service['classesApi'];
});
it('should load the groups passed by paramter', () => {
spyOn(classesApi, 'getClass');
service.load(['exif:exif', 'cm:content', 'custom:custom']).subscribe(() => {});
it('should load the groups passed by paramter', (done) => {
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve({}));
service.load(['exif:exif', 'cm:content', 'custom:custom'])
.subscribe(() => {
expect(classesApi.getClass).toHaveBeenCalledTimes(3);
expect(classesApi.getClass).toHaveBeenCalledWith('exif_exif');
expect(classesApi.getClass).toHaveBeenCalledWith('cm_content');
expect(classesApi.getClass).toHaveBeenCalledWith('custom_custom');
done();
});
});
it('should merge the forked values', (done) => {

View File

@ -1,10 +1,14 @@
<div class="adf-content-node-selector-content">
<mat-form-field floatPlaceholder="never" class="adf-content-node-selector-content-input" *ngIf="showSearch">
<mat-form-field floatPlaceholder="never"
appearance="fill"
class="adf-content-node-selector-content-input"
subscriptSizing="dynamic"
*ngIf="showSearch">
<mat-label>{{ 'NODE_SELECTOR.SEARCH' | translate }}</mat-label>
<input matInput
id="searchInput"
[formControl]="searchInput"
type="text"
placeholder="{{'NODE_SELECTOR.SEARCH' | translate}}"
[value]="searchTerm"
adf-auto-focus
data-automation-id="content-node-selector-search-input">

View File

@ -1,3 +1,5 @@
@import 'styles/mat-selectors';
/* stylelint-disable no-descending-specificity */
$content-node-selector-thumbnail-width: 35px !default;
$content-node-selector-thumbnail-max-width: 40px !default;
@ -13,6 +15,12 @@ h2.adf-search-results-label {
color: var(--adf-theme-foreground-text-color-087);
}
#{$mdc-dialog} {
#{$mat-dialog-surface}:is(div) {
padding-bottom: 0;
}
}
.adf-content-node-selector-panel {
.adf-toolbar .adf-toolbar-container.adf-toolbar-container-row {
max-height: 48px;
@ -28,38 +36,69 @@ h2.adf-search-results-label {
}
&-document-list-container {
margin-top: 16px;
width: 100%;
}
&-content {
#{$mat-input-element} {
&:focus::placeholder {
color: var(--theme-primary-color);
}
}
#{$mat-form-field-wrapper} {
#{$mat-form-field-flex} {
align-items: center;
#{$mat-form-field-infix} {
padding-bottom: 0;
}
}
}
.adf-sites-dropdown-form-field {
label {
&#{$mat-form-field-label} {
top: 32px;
}
}
}
#{$mat-form-field-subscript-wrapper} {
height: 16px;
}
padding-top: 0;
&-input {
width: 100%;
margin-bottom: 8px;
&-icon {
.adf-content-node-selector-content-input-icon {
color: var(--adf-theme-foreground-icon-color-054);
cursor: pointer;
padding: 0 0 8px;
width: 1em;
height: 1em;
font-size: 20px;
&:hover {
color: var(--adf-theme-foreground-base-color);
}
}
#{$mat-form-field-subscript-wrapper} {
display: none;
}
}
.adf-site-dropdown-container {
.adf-sites-dropdown-form-field {
display: block;
margin-bottom: 15px;
}
}
.adf-site-dropdown-list-element {
.adf-sites-dropdown-form-field {
width: 100%;
margin-bottom: 0;
.adf-sites-dropdown-select-trigger {
font-size: var(--theme-body-1-font-size);
}
}
}
@ -85,6 +124,7 @@ h2.adf-search-results-label {
}
}
&-content-list,
&-list {
height: 40vh;
overflow: auto;
@ -105,6 +145,10 @@ h2.adf-search-results-label {
.adf-datatable-list {
border: none;
.adf-name-location-cell-location {
display: none;
}
.adf-datatable-selected {
height: 100%;
width: 100%;
@ -130,8 +174,9 @@ h2.adf-search-results-label {
flex: 1 0 95px;
}
.adf-name-location-cell-location {
display: none;
.adf-no-content-container.adf-datatable-cell {
text-align: center;
border: none;
}
&.adf-content-selector-visibility-cell {
@ -169,10 +214,8 @@ h2.adf-search-results-label {
.adf-datatable-list .adf-datatable-body .adf-datatable-row {
min-height: 65px;
.adf-datatable-cell {
.adf-name-location-cell-location {
padding: 0 10px;
display: block;
@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
padding-top: 15px;
}
.adf-name-location-cell-name {
@ -193,6 +236,4 @@ h2.adf-search-results-label {
}
}
}
}
}
}

View File

@ -1,3 +1,5 @@
@import 'styles/mat-selectors';
adf-content-node-selector {
.adf-upload-dialog {
box-shadow: none;
@ -40,6 +42,23 @@ adf-content-node-selector {
}
.adf-content-node-selector-dialog {
#{$mat-form-field} {
width: 100%;
}
.adf-dropdown-breadcrumb-icon {
color: var(--adf-theme-foreground-base-color-045);
}
#{$mat-dialog-title} {
margin-bottom: 0;
padding: 0;
&::before {
display: none;
}
}
.adf-content-node-selector-dialog-title {
font-size: var(--theme-title-font-size);
font-weight: 600;
@ -48,6 +67,7 @@ adf-content-node-selector {
line-height: 1.6;
letter-spacing: -0.5px;
color: var(--adf-theme-foreground-text-color-087);
margin-bottom: 20px;
h2 {
margin: unset;
@ -57,7 +77,8 @@ adf-content-node-selector {
.adf-content-node-selector-dialog-actions {
padding: 8px;
height: 61px;
height: 77px;
background-color: var(--theme-background-color);
display: flex;
flex-direction: row;
justify-content: space-between;

View File

@ -148,13 +148,13 @@ describe('ContentNodeSelectorComponent', () => {
it('should pass through the injected currentFolderId to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
expect(documentList).not.toBeNull();
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', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
expect(documentList).not.toBeNull();
expect(documentList).not.toBeNull('Document list should be shown');
expect(
documentList.componentInstance.rowFilter({
node: {
@ -178,69 +178,66 @@ describe('ContentNodeSelectorComponent', () => {
it('should pass through the injected imageResolver to the documentList', () => {
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
expect(documentList).not.toBeNull();
expect(documentList).not.toBeNull('Document list should be shown');
expect(documentList.componentInstance.imageResolver).toBe(data.imageResolver);
});
});
describe('Cancel button', () => {
const getCancelButton = () => fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
it('should not be shown if dialogRef is NOT injected', () => {
const closeButton = fixture.debugElement.query(By.css('[content-node-selector-actions-cancel]'));
expect(closeButton).toBeNull();
});
it('should close the dialog', () => {
let cancelButton = getCancelButton();
let cancelButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
cancelButton.triggerEventHandler('click', {});
expect(dialog.close).toHaveBeenCalled();
fixture.detectChanges();
cancelButton = getCancelButton();
cancelButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-cancel"]'));
expect(cancelButton).not.toBeNull();
});
});
describe('Action button for the chosen node', () => {
const getActionButton = () =>
fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'))?.nativeElement as HTMLButtonElement;
it('should be disabled by default', () => {
fixture.detectChanges();
const actionButton = getActionButton();
expect(actionButton.disabled).toBeTruthy();
const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButton.nativeElement.disabled).toBeTruthy();
});
it('should be enabled when a node is chosen', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
const actionButton = getActionButton();
expect(actionButton.disabled).toBeFalsy();
const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButton.nativeElement.disabled).toBeFalsy();
});
it('should be disabled when no node chosen', () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
const actionButtonWithNodeSelected = getActionButton();
expect(actionButtonWithNodeSelected.disabled).toBe(false);
const actionButtonWithNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButtonWithNodeSelected.nativeElement.disabled).toBe(false);
component.onSelect([]);
fixture.detectChanges();
const actionButtonWithoutNodeSelected = getActionButton();
expect(actionButtonWithoutNodeSelected.disabled).toBe(true);
const actionButtonWithoutNodeSelected = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
expect(actionButtonWithoutNodeSelected.nativeElement.disabled).toBe(true);
});
it('should close the dialog when action button is clicked', () => {
it('should close the dialog when action button is clicked', async () => {
component.onSelect([new Node({ id: 'fake' })]);
fixture.detectChanges();
const actionButton = getActionButton();
actionButton.click();
const actionButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-actions-choose"]'));
await actionButton.nativeElement.click();
expect(dialog.close).toHaveBeenCalled();
});
@ -260,8 +257,6 @@ describe('ContentNodeSelectorComponent', () => {
});
describe('Upload button', () => {
const getUploadButton = () => fixture.debugElement.query(By.css('adf-upload-button button'))?.nativeElement as HTMLButtonElement;
it('Should not be able to upload a file whilst a search is still running', async () => {
enableLocalUpload();
fixture.detectChanges();
@ -308,10 +303,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
const adfUploadButton = getUploadButton();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.disabled).toBe(true);
expect(adfUploadButton.nativeElement.disabled).toBe(true);
});
it('should be able to enable UploadButton if showingSearch set to false', async () => {
@ -320,10 +315,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
const adfUploadButton = getUploadButton();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.disabled).toBe(false);
expect(adfUploadButton.nativeElement.disabled).toBe(false);
});
it('should be able to show warning message while searching', async () => {
@ -359,10 +354,10 @@ describe('ContentNodeSelectorComponent', () => {
component.onTabSelectionChange(1);
fixture.detectChanges();
const adfUploadButton = getUploadButton();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.disabled).toBe(true);
expect(adfUploadButton.nativeElement.disabled).toBe(true);
});
it('should be able to enable UploadButton if user has allowable operations', async () => {
@ -370,10 +365,10 @@ describe('ContentNodeSelectorComponent', () => {
component.hasAllowableOperations = true;
fixture.detectChanges();
const adfUploadButton = getUploadButton();
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button button'));
expect(adfUploadButton).not.toBeNull();
expect(adfUploadButton.disabled).toBe(false);
expect(adfUploadButton.nativeElement.disabled).toBe(false);
});
it('should not be able to show warning message if user has allowable operations', async () => {
@ -448,8 +443,6 @@ describe('ContentNodeSelectorComponent', () => {
});
describe('Drag and drop area', () => {
const getEmptyList = () => fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
it('should uploadStarted be false by default', () => {
expect(component.uploadStarted).toBe(false);
});
@ -467,8 +460,7 @@ describe('ContentNodeSelectorComponent', () => {
fixture.detectChanges();
await fixture.whenRenderingDone();
const emptyListTemplate = getEmptyList();
const emptyListTemplate = fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
const dragAndDropArea = fixture.debugElement.query(By.css('.adf-upload-drag-area'));
expect(emptyListTemplate).not.toBeNull();
@ -482,15 +474,13 @@ describe('ContentNodeSelectorComponent', () => {
component.uploadStarted = true;
fixture.detectChanges();
await fixture.whenRenderingDone();
const emptyListTemplate = fixture.nativeElement.querySelector('[data-automation-id="adf-empty-list"]');
const emptyListTemplate = getEmptyList();
expect(emptyListTemplate).toBeNull();
});
});
describe('Selected nodes counter', () => {
const getNodeCounter = () => fixture.debugElement.nativeElement.querySelector('adf-node-counter');
it('should getSelectedCount return 0 by default', () => {
expect(component.getSelectedCount()).toBe(0);
});
@ -504,19 +494,19 @@ describe('ContentNodeSelectorComponent', () => {
it('should show the counter depending on the action', () => {
component.action = NodeAction.ATTACH;
fixture.detectChanges();
expect(getNodeCounter()).not.toBe(null);
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).not.toBe(null);
component.action = NodeAction.CHOOSE;
fixture.detectChanges();
expect(getNodeCounter()).not.toBe(null);
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).not.toBe(null);
component.action = NodeAction.COPY;
fixture.detectChanges();
expect(getNodeCounter()).toBe(null);
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).toBe(null);
component.action = NodeAction.MOVE;
fixture.detectChanges();
expect(getNodeCounter()).toBe(null);
expect(fixture.debugElement.nativeElement.querySelector('adf-node-counter')).toBe(null);
});
});
});

View File

@ -1,14 +1,16 @@
<div id="site-dropdown-container" class="adf-site-dropdown-container">
<mat-form-field class="adf-sites-dropdown-form-field">
<mat-form-field class="adf-sites-dropdown-form-field" appearance="fill" subscriptSizing="dynamic">
<mat-label>{{ 'NODE_SELECTOR.LOCATION' | translate }}</mat-label>
<mat-select
adf-infinite-select-scroll
(scrollEnd)="loadAllOnScroll()"
#siteSelect
data-automation-id="site-my-files-option"
class="adf-site-dropdown-list-element"
id="site-dropdown"
placeholder="{{placeholder | translate}}"
[(value)]="selected"
placeholder="{{placeholder | translate}}"
(selectionChange)="selectedSite($event)">
<mat-select-trigger class="adf-sites-dropdown-select-trigger">
{{ selected?.entry.title | translate}}

View File

@ -66,6 +66,10 @@ describe('DropdownSitesComponent', () => {
});
});
afterEach(() => {
fixture.destroy();
});
describe('Rendering tests', () => {
describe('Infinite Loading', () => {
beforeEach(() => {

View File

@ -1,6 +1,6 @@
<div class="adf-share-link__dialog-content">
<div class="adf-share-link__dialog-container">
<div class="adf-share-link--row">
<div class="adf-share-link--header adf-share-link--row">
<div
data-automation-id="adf-share-dialog-title"
class="adf-share-link__title adf-share-link__label adf-share-link__heading"
@ -10,10 +10,10 @@
</div>
<mat-icon mat-dialog-close class="adf-share-link__close adf-share-link__icon">close</mat-icon>
</div>
<mat-dialog-content>
<mat-dialog-content class="adf-share-link--dialog-content">
<hr class="adf-share-link__separation-line" />
<form [formGroup]="form" class="adf-share-link__form">
<div class="adf-share-link--row">
<div class="adf-share-link--row adf-share-link--row-sharable">
<mat-icon class="adf-share-link__icon">timer</mat-icon>
<div class="adf-share-link__label adf-sharable-link">{{ 'SHARE.LINK-EXPIRY-DATE' | translate }}
</div>
@ -31,7 +31,7 @@
[style.display]="isExpiryDateToggleChecked ? 'block' : 'none'"
data-automation-id="adf-slide-toggle-checked"
class="adf-share-link__date-time-container">
<mat-form-field class="adf-full-width" floatLabel="never" data-automation-id="adf-content-share-expiration-field">
<mat-form-field class="adf-full-width" subscriptSizing="dynamic" data-automation-id="adf-content-share-expiration-field">
<mat-label>{{ 'SHARE.EXPIRATION-PLACEHOLDER' | translate }}</mat-label>
<mat-datepicker-toggle
[disabled]="time.disabled"
@ -47,7 +47,6 @@
class="adf-share-link__input"
#datePickerInput
matInput
placeholder="{{ 'SHARE.EXPIRATION-PLACEHOLDER' | translate }}"
[attr.aria-label]="'SHARE.EXPIRATION-LABEL' | translate"
[min]="minDate"
formControlName="time"
@ -60,10 +59,11 @@
</mat-form-field>
</div>
<p class="adf-share-link__info adf-share-link__para">{{ 'SHARE.SHARE-LINK' | translate }}</p>
<div class="adf-share-link--row">
<div class="adf-share-link--row adf-share-link--sharable-container">
<mat-slide-toggle
color="primary"
data-automation-id="adf-share-toggle"
class="adf-share-link--row__slide-toggle"
aria-label="{{ 'SHARE.TITLE' | translate }}"
[checked]="isFileShared"
[disabled]="!canUpdate || isDisabled"
@ -73,8 +73,9 @@
</div>
</div>
<mat-form-field
class="adf-full-width"
floatLabel="never"
subscriptSizing="dynamic"
floatLabel="always"
class="adf-full-width adf-share-link__form--field"
data-automation-id="adf-content-share-public-link-field"
[ngClass]="isLinkWithExpiryDate? 'adf-share-link__border-color' : ''">
<input
@ -88,7 +89,7 @@
formControlName="sharedUrl"
readonly="readonly">
<mat-icon
class="adf-input-action adf-share-link__icon"
class="adf-input-action adf-share-link__icon adf-share-link__copy-icon"
role="button"
matSuffix
[clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate"

View File

@ -1,5 +1,11 @@
@import 'styles/mat-selectors';
.adf-share-link-dialog {
.adf-share-link {
#{$mat-form-field-flex} {
height: 48px;
}
&__dialog-content {
display: flex;
flex-direction: column;
@ -8,7 +14,6 @@
&__dialog-container {
background-color: var(--theme-card-background-color);
border-radius: 16px;
padding: 16px 24px;
}
&__label,
@ -29,6 +34,16 @@
&__form {
padding-top: 8px;
#{$mat-form-field-infix}:has(.adf-share-link__input) {
border-top: 0.9375em solid transparent;
border-bottom: 0.9375em solid transparent;
height: 16px;
}
&--field {
padding-bottom: 16px;
}
}
&__public-content {
@ -48,6 +63,23 @@
flex-wrap: wrap;
align-items: center;
margin: 8px 0;
&-sharable {
margin-bottom: 0;
}
}
&--sharable-container {
margin-bottom: 0;
}
&--header {
padding: 16px 24px 0;
}
&--dialog-content {
padding-top: 0;
padding-bottom: 0;
}
&__input {
@ -66,6 +98,8 @@
&__icon {
color: var(--adf-theme-foreground-icon-color-054);
padding-bottom: 0;
padding-right: 0;
}
&__para {
@ -78,12 +112,24 @@
font-size: var(--theme-subheading-2-font-size);
}
&__copy-icon {
padding-top: 18px;
font-size: 22px;
}
&__calender-icon {
font-size: 18px;
top: 12px;
position: relative;
right: -6px;
svg {
height: 18px;
width: 18px;
}
}
&__date-time-container {
padding-bottom: 8px;
padding-bottom: 20px;
}
&__border-color {
@ -98,15 +144,17 @@
.adf-full-width {
width: 100%;
border-radius: 6px;
margin-top: -6px;
}
.adf-sharable-link {
margin-top: 2px;
margin-left: 8px;
}
.adf-share-link__actions {
justify-content: flex-end;
padding: 0;
padding: 8px 24px 32px 0;
margin: 8px 0 0;
& > button {

View File

@ -297,7 +297,7 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('[data-automation-id="adf-content-share-expiration-field"]')).componentInstance.floatLabel).toBe(
'never'
'auto'
);
});
@ -309,7 +309,7 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('[data-automation-id="adf-content-share-public-link-field"]')).componentInstance.floatLabel).toBe(
'never'
'always'
);
});

View File

@ -23,7 +23,7 @@ import { Subject } from 'rxjs';
import { ContentService } from '../common/services/content.service';
import { SharedLinksApiService } from './services/shared-links-api.service';
import { SharedLinkBodyCreate } from '@alfresco/js-api';
import { ConfirmDialogComponent } from '../dialogs/confirm.dialog';
import { ConfirmDialogComponent } from '@alfresco/adf-core';
import { ContentNodeShareSettings } from './content-node-share.settings';
import { RenditionService } from '../common/services/rendition.service';
import { format, add, endOfDay, isBefore } from 'date-fns';

View File

@ -15,18 +15,18 @@
* limitations under the License.
*/
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { TypeEntry } from '@alfresco/js-api';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { of, Subject } from 'rxjs';
import { ContentTestingModule } from '../testing/content.testing.module';
import { ContentTypeDialogComponent } from './content-type-dialog.component';
import { ContentTypeService } from './content-type.service';
import { ContentTypeDialogComponentData } from './content-type-metadata.interface';
import { TypeEntry } from '@alfresco/js-api';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatExpansionPanelHarness } from '@angular/material/expansion/testing';
import { MatTableHarness } from '@angular/material/table/testing';
import { ContentTypeService } from './content-type.service';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
const elementCustom: TypeEntry = {
entry: {

View File

@ -19,9 +19,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CategorySelectorDialogComponent, CategorySelectorDialogOptions } from './category-selector.dialog';
import { Subject } from 'rxjs';
import { Category } from '@alfresco/js-api';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { CoreTestingModule } from '@alfresco/adf-core';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import { AppConfigService, AppConfigServiceMock, TranslationMock, TranslationService } from '@alfresco/adf-core';
import { CategoriesManagementComponent } from '../category';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { MatFormFieldModule } from '@angular/material/form-field';
describe('Category selector dialog component', () => {
let fixture: ComponentFixture<CategorySelectorDialogComponent>;
@ -36,7 +40,10 @@ describe('Category selector dialog component', () => {
select: new Subject<Category[]>()
};
const categories: Category[] = [{id: 'id1', name: 'cat1'}, {id: 'id2', name: 'cat3'}];
const categories: Category[] = [
{ id: 'id1', name: 'cat1' },
{ id: 'id2', name: 'cat3' }
];
const setCategories = () => {
component.categories = categories;
@ -45,11 +52,14 @@ describe('Category selector dialog component', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule],
imports: [MatFormFieldModule, TranslateModule.forRoot(), MatDialogModule, HttpClientTestingModule],
providers: [
{ provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: MatDialogRef, useValue: dialogRef },
{ provide: MAT_DIALOG_DATA, useValue: options }
]
{ provide: MAT_DIALOG_DATA, useValue: options },
{ provide: TranslationService, useClass: TranslationMock }
],
declarations: [CategoriesManagementComponent, CategorySelectorDialogComponent]
});
dialogRef.close.calls.reset();
fixture = TestBed.createComponent(CategorySelectorDialogComponent);

View File

@ -1,18 +0,0 @@
<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" class="adf-confirm-dialog-button" mat-button color="primary" data-automation-id="adf-confirm-dialog-confirmation"
[mat-dialog-close]="true">{{ yesLabel | translate }}</button>
<button id="adf-confirm-all" class="adf-confirm-dialog-button" mat-button *ngIf="thirdOptionLabel" [mat-dialog-close]="thirdOptionLabel" data-automation-id="adf-confirm-dialog-confirm-all">{{ thirdOptionLabel | translate }}</button>
<button id="adf-confirm-cancel" class="adf-confirm-dialog-button" mat-button [mat-dialog-close]="false" data-automation-id="adf-confirm-dialog-reject"
cdkFocusInitial>{{ noLabel | translate }}</button>
</mat-dialog-actions>

View File

@ -23,7 +23,6 @@ import { CoreModule } from '@alfresco/adf-core';
import { MaterialModule } from '../material.module';
import { FolderDialogComponent } from './folder.dialog';
import { NodeLockDialogComponent } from './node-lock.dialog';
import { ConfirmDialogComponent } from './confirm.dialog';
import { MatDatetimepickerModule } from '@mat-datetimepicker/core';
import { LibraryDialogComponent } from './library/library.dialog';
import { ContentDirectiveModule } from '../directives';
@ -46,14 +45,12 @@ import { CategoriesModule } from '../category';
declarations: [
FolderDialogComponent,
NodeLockDialogComponent,
ConfirmDialogComponent,
LibraryDialogComponent,
CategorySelectorDialogComponent
],
exports: [
FolderDialogComponent,
NodeLockDialogComponent,
ConfirmDialogComponent,
LibraryDialogComponent,
CategorySelectorDialogComponent
]

View File

@ -16,11 +16,14 @@
*/
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import { DownloadZipDialogComponent } from './download-zip.dialog';
import { CoreTestingModule } from '@alfresco/adf-core';
import { DownloadZipService } from './services/download-zip.service';
import { Observable } from 'rxjs';
import { EMPTY, Observable, of } from 'rxjs';
import { AlfrescoApiService, AlfrescoApiServiceMock, RedirectAuthService, TranslationMock, TranslationService } from '@alfresco/adf-core';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TranslateModule } from '@ngx-translate/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
describe('DownloadZipDialogComponent', () => {
let fixture: ComponentFixture<DownloadZipDialogComponent>;
@ -37,10 +40,14 @@ describe('DownloadZipDialogComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule],
imports: [HttpClientTestingModule, TranslateModule.forRoot(), MatDialogModule, NoopAnimationsModule],
providers: [
DownloadZipService,
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: TranslationService, useClass: TranslationMock },
{ provide: MatDialogRef, useValue: dialogRef },
{ provide: MAT_DIALOG_DATA, useValue: dataMock }
{ provide: MAT_DIALOG_DATA, useValue: dataMock },
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }
]
});
dialogRef.close.calls.reset();

View File

@ -15,30 +15,26 @@
* limitations under the License.
*/
import { Meta, moduleMetadata, Story } from '@storybook/angular';
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button';
import { DownloadZipDialogStorybookComponent } from './download-zip.dialog.stories.component';
import {
AlfrescoApiServiceMock,
ContentApiMock,
DownloadZipMockService,
NodesApiMock
} from './mock/download-zip-service.mock';
import { DownloadZipDialogModule } from './download-zip.dialog.module';
import { AlfrescoApiServiceMock, ContentApiMock, DownloadZipMockService, NodesApiMock } from './mock/download-zip-service.mock';
import { DownloadZipService } from './services/download-zip.service';
import { ContentService } from '../../common/services/content.service';
import { NodesApiService } from '../../common/services/nodes-api.service';
import { MatDialogModule } from '@angular/material/dialog';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { importProvidersFrom } from '@angular/core';
import { CoreStoryModule } from '../../../../../core/src/public-api';
export default {
component: DownloadZipDialogStorybookComponent,
title: 'Core/Dialog/Download ZIP Dialog',
decorators: [
moduleMetadata({
imports: [
DownloadZipDialogModule,
MatButtonModule
],
declarations: [DownloadZipDialogStorybookComponent],
imports: [MatButtonModule, MatDialogModule, HttpClientTestingModule],
providers: [
{
provide: AlfrescoApiService,
@ -57,6 +53,9 @@ export default {
useClass: NodesApiMock
}
]
}),
applicationConfig({
providers: [importProvidersFrom(CoreStoryModule)]
})
],
argTypes: {
@ -68,16 +67,19 @@ export default {
category: 'Story controls',
type: {
summary: 'boolean'
},
defaultValue: {
summary: 'false'
}
}
}
},
defaultValue: false
args: {
showLoading: false
}
}
} as Meta;
} as Meta<DownloadZipDialogStorybookComponent>;
export const downloadZIPDialog: Story<DownloadZipDialogStorybookComponent> = (
args: DownloadZipDialogStorybookComponent
) => ({
export const DownloadZIPDialog: StoryFn<DownloadZipDialogStorybookComponent> = (args) => ({
props: args
});
downloadZIPDialog.parameters = { layout: 'centered' };
DownloadZIPDialog.parameters = { layout: 'centered' };

View File

@ -2,12 +2,12 @@
{{ (editing ? editTitle : createTitle) | translate }}
</h2>
<mat-dialog-content>
<mat-dialog-content class="adf-folder-dialog-content">
<form [formGroup]="form" (submit)="submit()">
<mat-form-field class="adf-full-width">
<mat-label>{{ 'CORE.FOLDER_DIALOG.FOLDER_NAME.LABEL' | translate }}</mat-label>
<input
id="adf-folder-name-input"
placeholder="{{ 'CORE.FOLDER_DIALOG.FOLDER_NAME.LABEL' | translate }}"
[attr.aria-label]="'CORE.FOLDER_DIALOG.FOLDER_NAME.LABEL' | translate"
matInput
required
@ -27,20 +27,20 @@
</mat-form-field>
<mat-form-field class="adf-full-width">
<mat-label>{{ 'CORE.FOLDER_DIALOG.FOLDER_TITLE.LABEL' | translate }}</mat-label>
<input
id="adf-folder-title-input"
matInput
placeholder="{{ 'CORE.FOLDER_DIALOG.FOLDER_TITLE.LABEL' | translate }}"
[attr.aria-label]="'CORE.FOLDER_DIALOG.FOLDER_TITLE.LABEL' | translate"
[formControlName]="'title'"
/>
</mat-form-field>
<mat-form-field class="adf-full-width">
<mat-label>{{ 'CORE.FOLDER_DIALOG.FOLDER_DESCRIPTION.LABEL' | translate }}</mat-label>
<textarea
id="adf-folder-description-input"
matInput
placeholder="{{ 'CORE.FOLDER_DIALOG.FOLDER_DESCRIPTION.LABEL' | translate }}"
[attr.aria-label]="'CORE.FOLDER_DIALOG.FOLDER_DESCRIPTION.LABEL' | translate"
rows="4"
[formControlName]="'description'">

View File

@ -1,3 +1,33 @@
@import 'styles/mat-selectors';
.adf-folder-dialog {
.adf-folder-dialog-content {
padding: 0;
overflow: unset;
#{$mat-form-field-infix} {
padding-bottom: 3.5px;
}
#{$mat-form-field-hide-placeholder} {
#{$mat-floating-label} {
padding-top: 11px;
}
}
#{$mat-form-field-hint-wrapper} {
padding-left: 0;
margin-left: -2px;
color: var(--adf-theme-foreground-secondary-text-color);
font-size: 10.5px;
}
}
.adf-folder-dialog-title {
display: inline-flex;
}
}
.adf-fill-remaining-space {
flex: 1 1 auto;
}

View File

@ -37,7 +37,7 @@ describe('FolderDialogComponent', () => {
let createFolderSpy: jasmine.Spy;
const updateNode$ = new BehaviorSubject(null);
const createFolderNode$ = new BehaviorSubject(null);
let createFolderNode$ = null;
beforeEach(() => {
TestBed.configureTestingModule({
@ -48,6 +48,7 @@ describe('FolderDialogComponent', () => {
fixture = TestBed.createComponent(FolderDialogComponent);
component = fixture.componentInstance;
nodesApi = TestBed.inject(NodesApiService);
createFolderNode$ = new BehaviorSubject(null);
createFolderSpy = spyOn(nodesApi, 'createFolder').and.returnValue(createFolderNode$);
updateNodeSpy = spyOn(nodesApi, 'updateNode').and.returnValue(updateNode$);
@ -273,8 +274,13 @@ describe('FolderDialogComponent', () => {
});
describe('Error events', () => {
let errorSubscriber = null;
afterEach(() => {
createFolderNode$.next(null);
if (errorSubscriber) {
errorSubscriber.complete();
}
});
it('should raise error for 409', (done) => {
@ -283,7 +289,7 @@ describe('FolderDialogComponent', () => {
};
createFolderNode$.error(error);
component.error.subscribe((message) => {
errorSubscriber = component.error.subscribe((message) => {
expect(message).toBe('CORE.MESSAGES.ERRORS.EXISTENT_FOLDER');
done();
});
@ -300,7 +306,7 @@ describe('FolderDialogComponent', () => {
};
createFolderNode$.error(error);
component.error.subscribe((message) => {
errorSubscriber = component.error.subscribe((message) => {
expect(message).toBe('CORE.MESSAGES.ERRORS.GENERIC');
done();
});

View File

@ -31,7 +31,8 @@ import { forbidEndingDot, forbidOnlySpaces, forbidSpecialCharacters } from './fo
selector: 'adf-folder-dialog',
templateUrl: './folder.dialog.html',
styleUrls: ['./folder.dialog.scss'],
encapsulation: ViewEncapsulation.None
encapsulation: ViewEncapsulation.None,
host: { class: 'adf-folder-dialog' }
})
export class FolderDialogComponent implements OnInit {
/**

View File

@ -1,10 +1,10 @@
<h2 mat-dialog-title>{{ createTitle | translate }}</h2>
<mat-dialog-content>
<mat-dialog-content class="adf-library-dialog-content">
<form novalidate [formGroup]="form" (submit)="submit()">
<mat-form-field class="adf-library-dialog-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}</mat-label>
<input
placeholder="{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}"
required
matInput
formControlName="title"
@ -29,9 +29,9 @@
</mat-form-field>
<mat-form-field class="adf-library-dialog-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.SITE_ID' | translate }}</mat-label>
<input
required
placeholder="{{ 'LIBRARY.DIALOG.FORM.SITE_ID' | translate }}"
matInput
formControlName="id"
autocomplete="off"
@ -46,10 +46,10 @@
</mat-error>
</mat-form-field>
<mat-form-field class="adf-library-dialog-form-field">
<mat-form-field class="adf-library-dialog-form-field adf-library-dialog-form-field-description">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.DESCRIPTION' | translate }}</mat-label>
<textarea
matInput
placeholder="{{ 'LIBRARY.DIALOG.FORM.DESCRIPTION' | translate }}"
rows="3"
formControlName="description"
></textarea>

View File

@ -1,8 +1,15 @@
@import 'styles/mat-selectors';
.adf-library-dialog {
.adf-library-dialog-content {
padding: 0;
overflow: unset;
}
.adf-library-dialog-radio-group {
display: flex;
flex-direction: column;
margin: 0 0 20px;
margin: 0;
}
.adf-library-dialog-radio-group .adf-library-dialog-radio-group-button {
@ -11,8 +18,48 @@
.adf-library-dialog-form-field {
width: 100%;
padding-top: 9.5px;
&:first-of-type {
padding-top: 13.5px;
}
&:last-of-type {
padding-top: 4.5px;
}
#{$mat-floating-label} {
-webkit-font-smoothing: subpixel-antialiased;
}
&#{$mat-form-field-hide-placeholder} {
#{$mat-floating-label} {
padding-top: 11px;
}
}
&-description {
&#{$mat-form-field-hide-placeholder} {
#{$mat-floating-label} {
padding-top: 20px;
}
}
}
#{$mat-form-field-infix} {
padding-bottom: 3.5px;
}
#{$mat-form-field-error-wrapper} {
margin-left: -2px;
font-size: 10.5px;
-webkit-font-smoothing: subpixel-antialiased;
#{$mat-form-field-error} {
height: 13.125px;
}
}
}
.adf-action-buttons {
display: flex;
@ -21,6 +68,10 @@
.adf-action-button {
text-transform: uppercase;
span {
font-weight: 500;
}
}
}
}

View File

@ -17,7 +17,6 @@
export * from './folder.dialog';
export * from './node-lock.dialog';
export * from './confirm.dialog';
export * from './category-selector.dialog';
export * from './dialog.module';

View File

@ -16,11 +16,14 @@
*/
import { ChangeDetectorRef, Component, ElementRef, SimpleChange } from '@angular/core';
import { CoreTestingModule } from '@alfresco/adf-core';
import { ContentService } from '../common/services/content.service';
import { CheckAllowableOperationDirective } from './check-allowable-operation.directive';
import { TestBed } from '@angular/core/testing';
import { NodeAllowableOperationSubject } from '../interfaces/node-allowable-operation-subject.interface';
import { ContentDirectiveModule } from './content-directive.module';
import { RedirectAuthService } from '@alfresco/adf-core';
import { EMPTY, of } from 'rxjs';
import { HttpClientTestingModule } from '@angular/common/http/testing';
@Component({
selector: 'adf-text-subject',
@ -35,7 +38,8 @@ describe('CheckAllowableOperationDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule]
imports: [ContentDirectiveModule, HttpClientTestingModule],
providers: [{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }]
});
changeDetectorMock = { detectChanges: () => {} } as ChangeDetectorRef;
});

View File

@ -18,8 +18,8 @@
import { Component, ViewChild } from '@angular/core';
import { LibraryFavoriteDirective } from './library-favorite.directive';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { CoreTestingModule } from '@alfresco/adf-core';
import { LibraryEntity } from '../interfaces/library-entity.interface';
import { HttpClientTestingModule } from '@angular/common/http/testing';
@Component({
standalone: true,
@ -41,7 +41,7 @@ describe('LibraryFavoriteDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, LibraryFavoriteDirective, TestComponent]
imports: [HttpClientTestingModule, TestComponent, LibraryFavoriteDirective]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;

View File

@ -17,11 +17,12 @@
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { LibraryMembershipDirective } from './library-membership.directive';
import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
import { SimpleChange } from '@angular/core';
import { of, throwError, Subject } from 'rxjs';
import { AlfrescoApiService, CoreModule, CoreTestingModule } from '@alfresco/adf-core';
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-core';
import { ContentDirectiveModule } from './content-directive.module';
import { SitesService } from '../common/services/sites.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
describe('LibraryMembershipDirective', () => {
let alfrescoApiService: AlfrescoApiService;
@ -37,8 +38,8 @@ describe('LibraryMembershipDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentDirectiveModule, CoreModule.forRoot(), CoreTestingModule],
schemas: [NO_ERRORS_SCHEMA]
imports: [HttpClientTestingModule, ContentDirectiveModule],
providers: [SitesService, { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }]
});
testSiteEntry = {

View File

@ -19,8 +19,11 @@ import { Component, DebugElement, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NodeDeleteDirective } from './node-delete.directive';
import { CoreTestingModule } from '@alfresco/adf-core';
import { ContentDirectiveModule } from './content-directive.module';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TranslateModule } from '@ngx-translate/core';
import { RedirectAuthService, TranslationMock, TranslationService } from '@alfresco/adf-core';
import { EMPTY, of } from 'rxjs';
@Component({
template: `<div id="delete-component" [adf-delete]="selection" (delete)="onDelete()"></div>`
@ -76,7 +79,11 @@ describe('NodeDeleteDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CoreTestingModule, ContentDirectiveModule],
imports: [ContentDirectiveModule, HttpClientTestingModule, TranslateModule.forRoot()],
providers: [
{ provide: TranslationService, useClass: TranslationMock },
{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, onTokenReceived: of() } }
],
declarations: [TestComponent, TestWithPermissionsComponent, TestDeletePermanentComponent]
});
fixture = TestBed.createComponent(TestComponent);

Some files were not shown because too many files have changed in this diff Show More