mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-16 18:13:06 +00:00
Compare commits
196
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bfbeb13b2 | ||
|
|
40df22b576 | ||
|
|
3287263794 | ||
|
|
06d8f48862 | ||
|
|
dc92a9551e | ||
|
|
f8d39aa10b | ||
|
|
da6de234d7 | ||
|
|
3cc39bd650 | ||
|
|
150e073952 | ||
|
|
5625cf72d6 | ||
|
|
f379d99474 | ||
|
|
f317374a2e | ||
|
|
a9efe36e5f | ||
|
|
6bece85060 | ||
|
|
c5f3008301 | ||
|
|
514754d0eb | ||
|
|
57090bd76e | ||
|
|
0f911b1259 | ||
|
|
91447f8646 | ||
|
|
533bf89b18 | ||
|
|
81658d0588 | ||
|
|
f5f7c04a85 | ||
|
|
3d07d7e942 | ||
|
|
2009a4ec27 | ||
|
|
dbdc402756 | ||
|
|
f63f0a85c0 | ||
|
|
44a6a02ce3 | ||
|
|
3031ec1f66 | ||
|
|
e87c33dcae | ||
|
|
5aa73344c4 | ||
|
|
82ad2b40e6 | ||
|
|
fdd6b4988d | ||
|
|
c68f638992 | ||
|
|
eff64284e9 | ||
|
|
9a6cd813de | ||
|
|
03f67c861f | ||
|
|
58a25fe19e | ||
|
|
2f5139df73 | ||
|
|
9fd304b66d | ||
|
|
3b05504e65 | ||
|
|
fbc647459f | ||
|
|
97b563e967 | ||
|
|
ad41c0eae2 | ||
|
|
c957beff7c | ||
|
|
c09c4d5f53 | ||
|
|
70277b4ea0 | ||
|
|
5f76d8efad | ||
|
|
dec8fcfb91 | ||
|
|
2ebe4ccfb0 | ||
|
|
9af4b7a4b6 | ||
|
|
a748541ca0 | ||
|
|
ac3c30480b | ||
|
|
002c5b4bf7 | ||
|
|
2f4dad1636 | ||
|
|
d298d92214 | ||
|
|
b7d687f3d2 | ||
|
|
c2c3bff7bb | ||
|
|
c2f4597309 | ||
|
|
0d670dd333 | ||
|
|
54f20b7b6e | ||
|
|
d85a261720 | ||
|
|
b61912e3eb | ||
|
|
ea58a5d794 | ||
|
|
e11aa6ddf3 | ||
|
|
61e1395bfa | ||
|
|
43622266ce | ||
|
|
38d98200a6 | ||
|
|
e28e924b87 | ||
|
|
3180ca8e9d | ||
|
|
c2add07426 | ||
|
|
2a4f341dbd | ||
|
|
ab67ba3414 | ||
|
|
c4f276e228 | ||
|
|
f7d26d904f | ||
|
|
e85a27e05b | ||
|
|
4acda3b09b | ||
|
|
4feba2f304 | ||
|
|
a4f5cfc964 | ||
|
|
e78c590323 | ||
|
|
71d518539d | ||
|
|
86093adf18 | ||
|
|
59b148ea03 | ||
|
|
82b9b18891 | ||
|
|
5016eff847 | ||
|
|
6ab54be7d0 | ||
|
|
2d68cf9916 | ||
|
|
42a1ddf540 | ||
|
|
8c9f6a0828 | ||
|
|
160b12993f | ||
|
|
f152953cc9 | ||
|
|
e202c693c1 | ||
|
|
1c8af0467e | ||
|
|
1685ee4c8b | ||
|
|
983d505309 | ||
|
|
81a0ee0963 | ||
|
|
b1f9f32e3f | ||
|
|
718df62173 | ||
|
|
022f75efe1 | ||
|
|
56047699a5 | ||
|
|
9196932e06 | ||
|
|
fa5277e1b7 | ||
|
|
472ca5a20e | ||
|
|
e1d56be29c | ||
|
|
9b17f50401 | ||
|
|
9fc7c22e18 | ||
|
|
c6b3f74350 | ||
|
|
07d0b278ed | ||
|
|
0e6ef311ac | ||
|
|
010ea60e9b | ||
|
|
72555b7326 | ||
|
|
5a8088a5ec | ||
|
|
dfc65ae45c | ||
|
|
cef71a2d71 | ||
|
|
124fd66965 | ||
|
|
0335a32a3a | ||
|
|
8ebb67d1cf | ||
|
|
84d32157ad | ||
|
|
816601fcec | ||
|
|
cb5831450e | ||
|
|
b8d228d409 | ||
|
|
970cd7d6e5 | ||
|
|
74437a01c0 | ||
|
|
685ac09387 | ||
|
|
d11fbf4b5e | ||
|
|
afb22c2cd6 | ||
|
|
24cb259f99 | ||
|
|
56092ff2c1 | ||
|
|
33ca9313be | ||
|
|
8b553bb00f | ||
|
|
25ecfcf5e1 | ||
|
|
3356dab434 | ||
|
|
dffa37f182 | ||
|
|
622dcafbc4 | ||
|
|
29d341cc3b | ||
|
|
b6ea1e056e | ||
|
|
40ff0d56af | ||
|
|
6b9d3d2104 | ||
|
|
fb72ccffcc | ||
|
|
84fcc48c1a | ||
|
|
731443ca1c | ||
|
|
91d6b80965 | ||
|
|
ef29bafc75 | ||
|
|
591934db0e | ||
|
|
4964ae94c5 | ||
|
|
2b08e0c1d0 | ||
|
|
1b212e8805 | ||
|
|
d230176e7f | ||
|
|
d49575ba03 | ||
|
|
1c8181fca8 | ||
|
|
4f2b5329c6 | ||
|
|
a347b20f20 | ||
|
|
b400757ad1 | ||
|
|
10afe75e94 | ||
|
|
196b60a7d9 | ||
|
|
82f96d9510 | ||
|
|
3a1020ea7b | ||
|
|
7bdbf6194e | ||
|
|
36b4c34008 | ||
|
|
7206a6322d | ||
|
|
fd29e953d6 | ||
|
|
c8c1ae7838 | ||
|
|
3b5e98b182 | ||
|
|
09c35ea903 | ||
|
|
923feccdb9 | ||
|
|
e7024d1970 | ||
|
|
a72726427b | ||
|
|
054ecf3dcb | ||
|
|
8c51e783e5 | ||
|
|
fd88e1014c | ||
|
|
2ec227c331 | ||
|
|
2235c6b09e | ||
|
|
dfa6db447f | ||
|
|
e7bba32679 | ||
|
|
ea81fcd6ad | ||
|
|
f1fea0a70b | ||
|
|
0564e67ba6 | ||
|
|
3ac2a91ea0 | ||
|
|
88b857a8fe | ||
|
|
51c55674b4 | ||
|
|
93c872b65d | ||
|
|
195194fb15 | ||
|
|
49375181e4 | ||
|
|
aae4efdd92 | ||
|
|
a4e62974ea | ||
|
|
81fed833f5 | ||
|
|
609144551c | ||
|
|
5bc4c02a94 | ||
|
|
04d488b8ea | ||
|
|
dabab63f78 | ||
|
|
b277a29f32 | ||
|
|
bdeb8a8e51 | ||
|
|
9c0313a00c | ||
|
|
2200135b82 | ||
|
|
a141d19629 | ||
|
|
15ed9a5f81 | ||
|
|
f205cbc33c |
@@ -1,21 +0,0 @@
|
||||
.git
|
||||
.github
|
||||
.vscode
|
||||
assets
|
||||
coverage
|
||||
docs
|
||||
e2e
|
||||
e2e-output
|
||||
node_modules
|
||||
scripts
|
||||
src
|
||||
lib
|
||||
tools
|
||||
/angular.json
|
||||
/desktop.ini
|
||||
/cspell.json
|
||||
/CODE_OF_CONDUCT.md
|
||||
/.stylelintignore
|
||||
/ALFRESCOCORS.md
|
||||
/CONTRIBUTING.md
|
||||
/BROWSER-SUPPORT.md
|
||||
@@ -9,5 +9,4 @@ scripts
|
||||
/angular.json
|
||||
docs/**/*.md
|
||||
lib/js-api/docs/**/*.md
|
||||
.storybook
|
||||
webpack.config.js
|
||||
|
||||
+2
-13
@@ -1,16 +1,7 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
ignorePatterns: [
|
||||
'projects/**/*',
|
||||
'**/node_modules/**/*',
|
||||
'lib/cli/node_modules/**/*',
|
||||
'**/node_modules',
|
||||
'**/docker',
|
||||
'**/assets',
|
||||
'**/scripts',
|
||||
'**/docs'
|
||||
],
|
||||
ignorePatterns: ['projects/**/*', '**/node_modules/**/*', 'lib/cli/node_modules/**/*', '**/node_modules', '**/assets', '**/scripts', '**/docs'],
|
||||
|
||||
plugins: ['@nx'],
|
||||
|
||||
@@ -216,7 +207,5 @@ module.exports = {
|
||||
'comma-dangle': ['error', 'never']
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
extends: ['plugin:storybook/recommended']
|
||||
]
|
||||
};
|
||||
|
||||
@@ -9,12 +9,6 @@ inputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Before install
|
||||
if: ${{ ! env.ACT }}
|
||||
shell: bash
|
||||
run: |
|
||||
pip install --user --quiet awscli
|
||||
|
||||
- name: base vars
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -51,11 +45,13 @@ runs:
|
||||
- name: RELEASE on master/develop patch branch
|
||||
if: ${{ env.BREAK_ACTION == false && github.event.pull_request.merged }}
|
||||
shell: bash
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run: |
|
||||
if [[ "${{ github.ref_name }}" =~ ^master(-patch.*)?$ ]]; then
|
||||
if [[ "$REF_NAME" =~ ^master(-patch.*)?$ ]]; then
|
||||
# into master(-patch*)
|
||||
echo "Setting up CI flags for Push on master patch"
|
||||
elif [[ "${{ github.ref_name }}" =~ ^develop-patch.*$ ]]; then
|
||||
elif [[ "$REF_NAME" =~ ^develop-patch.*$ ]]; then
|
||||
# into develop-patch*
|
||||
echo "Setting up CI flags for Push develop patch"
|
||||
else
|
||||
|
||||
@@ -3,17 +3,33 @@ description: "Download build artifacts"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: download and extract artifacts from s3
|
||||
shell: bash
|
||||
env:
|
||||
REMOTE_PATH: "alfresco-ng2-components/build-cache/${{ github.run_id }}"
|
||||
run: |
|
||||
packages=( dist nxcache node_modules )
|
||||
for i in "${packages[@]}"; do
|
||||
time aws s3 cp --no-progress s3://${S3_BUILD_BUCKET_SHORT_NAME}/${REMOTE_PATH}/$i.tar.gz $i.tar.gz
|
||||
du -h $i.tar.gz
|
||||
time tar xzf $i.tar.gz
|
||||
done
|
||||
- name: Restore dist from cache
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: dist
|
||||
key: dist-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
dist-${{ github.run_id }}-
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Restore nxcache from cache
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: nxcache
|
||||
key: nxcache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
nxcache-${{ github.run_id }}-
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
node-modules-${{ github.run_id }}-
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: show files
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -24,4 +40,4 @@ runs:
|
||||
echo "====NXCACHE===="
|
||||
find nxcache -maxdepth 1 -type d
|
||||
echo "====ADF===="
|
||||
find node_modules/@alfresco/ -maxdepth 1 -type d
|
||||
find node_modules/@alfresco/ -maxdepth 1 -type d
|
||||
|
||||
@@ -20,8 +20,10 @@ runs:
|
||||
- name: set dryrun flag to TRUE
|
||||
shell: bash
|
||||
id: dryrun
|
||||
env:
|
||||
DRY_RUN_FLAG: ${{ inputs.dry-run-flag }}
|
||||
run: |
|
||||
if [[ '${{ inputs.dry-run-flag }}' == 'true' ]]; then
|
||||
if [[ '$DRY_RUN_FLAG' == 'true' ]]; then
|
||||
echo "dryrun=--dryrun" >> $GITHUB_OUTPUT;
|
||||
echo "enabling dryrun"
|
||||
else
|
||||
|
||||
@@ -5,22 +5,27 @@ inputs:
|
||||
branch_name:
|
||||
description: "override GITHUB_REF_NAME"
|
||||
required: false
|
||||
default: $GITHUB_REF_NAME
|
||||
default: ${{ github.ref_name }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
steps:
|
||||
- name: load "NPM TAG"
|
||||
id: set-npm-tag
|
||||
uses: ./.github/actions/set-npm-tag
|
||||
with:
|
||||
branch_name: ${{ inputs.branch_name }}
|
||||
- name: check npm bundle
|
||||
shell: bash
|
||||
id: sha_out
|
||||
env:
|
||||
TAG_NPM: ${{ steps.set-npm-tag.outputs.npm-tag }}
|
||||
run: |
|
||||
if [[ -z $TAG_NPM ]]; then
|
||||
echo "TAG_NPM not set, aborting"
|
||||
exit 1
|
||||
fi
|
||||
./scripts/github/build/npm-check-bundles.sh
|
||||
ADF_VERSION=$(npm view @alfresco/adf-core@${TAG_NPM} version)
|
||||
echo "check bundle on TAG_NPM='${TAG_NPM}' and ADF_VERSION='${ADF_VERSION}'"
|
||||
./scripts/github/build/npm-check-bundles.sh -v ${ADF_VERSION}
|
||||
|
||||
@@ -2,36 +2,44 @@ name: "set npm tag"
|
||||
description: "se NPM tag"
|
||||
|
||||
inputs:
|
||||
event_name:
|
||||
description: "override github.event_name"
|
||||
required: false
|
||||
default: ${{ github.event_name }}
|
||||
branch_name:
|
||||
description: "override GITHUB_REF_NAME"
|
||||
required: false
|
||||
default: $GITHUB_REF_NAME
|
||||
default: ${{ github.ref_name }}
|
||||
|
||||
outputs:
|
||||
npm-tag:
|
||||
description: "NPM tag"
|
||||
value: ${{ steps.set-npm-tag.outputs.npm-tag }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
|
||||
- name: set TAG_NPM
|
||||
id: set-npm-tag
|
||||
shell: bash
|
||||
env:
|
||||
BRANCH_NAME: ${{ inputs.branch_name }}
|
||||
run: |
|
||||
TAG_NPM="alpha"
|
||||
VERSION_IN_PACKAGE_JSON=$(node -p "require('./package.json')".version)
|
||||
echo "version in package.json=${VERSION_IN_PACKAGE_JSON}"
|
||||
if [[ ${{ inputs.branch_name }} =~ ^master(-patch.*)?$ ]]; then
|
||||
# Pre-release versions
|
||||
if [[ $VERSION_IN_PACKAGE_JSON =~ ^[0-9]*\.[0-9]*\.[0-9]*-A\.[0-9]*$ ]];
|
||||
then
|
||||
TAG_NPM=next
|
||||
# Stable major versions
|
||||
else
|
||||
TAG_NPM=latest
|
||||
fi
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
TAG_NPM="branch"
|
||||
else
|
||||
TAG_NPM="alpha"
|
||||
VERSION_IN_PACKAGE_JSON=$(node -p "require('./package.json')".version)
|
||||
echo "version in package.json=${VERSION_IN_PACKAGE_JSON}"
|
||||
if [[ $BRANCH_NAME =~ ^master(-patch.*)?$ ]]; then
|
||||
# Pre-release versions
|
||||
if [[ $VERSION_IN_PACKAGE_JSON =~ ^[0-9]*\.[0-9]*\.[0-9]*-A\.[0-9]*$ ]]; then
|
||||
TAG_NPM=next
|
||||
# Stable major versions
|
||||
else
|
||||
TAG_NPM=latest
|
||||
fi
|
||||
fi
|
||||
if [[ $BRANCH_NAME =~ ^develop(-patch.*)?$ ]]; then
|
||||
TAG_NPM=alpha
|
||||
fi
|
||||
fi
|
||||
if [[ ${{ inputs.branch_name }} =~ ^develop(-patch.*)?$ ]]; then
|
||||
TAG_NPM=alpha
|
||||
fi
|
||||
echo "TAG_NPM=${TAG_NPM}" >> $GITHUB_ENV
|
||||
echo "npm-tag=$TAG_NPM" >> $GITHUB_OUTPUT
|
||||
echo "Computed tag: $TAG_NPM"
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
name: 'Setup'
|
||||
description: 'Initialize cache, env var load'
|
||||
inputs:
|
||||
enable-cache:
|
||||
description: 'enable caching'
|
||||
required: false
|
||||
type: boolean
|
||||
default: 'true'
|
||||
enable-node-modules-cache:
|
||||
description: 'enable caching for node modules'
|
||||
required: false
|
||||
@@ -16,22 +11,26 @@ inputs:
|
||||
required: false
|
||||
type: boolean
|
||||
default: 'false'
|
||||
outputs:
|
||||
npm-tag:
|
||||
description: 'NPM tag'
|
||||
value: ${{ steps.set-npm-tag.outputs.npm-tag }}
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: install NPM
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: get latest tag sha
|
||||
id: tag-sha
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@a32503e10c10dc999ffcdfa8bc8c5e705cf36928 # v8.31.0
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@7eb56e49e47d11547d61c3c68826022db830fc15 # v10.1.0
|
||||
# CACHE
|
||||
- name: Node Modules cache
|
||||
id: node-modules-cache
|
||||
if: ${{ inputs.enable-node-modules-cache == 'true' }}
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
env:
|
||||
cache-name: node-modules-cache
|
||||
with:
|
||||
@@ -42,15 +41,8 @@ runs:
|
||||
node_modules-${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
node_modules-${{ runner.os }}-build-
|
||||
node_modules-${{ runner.os }}-
|
||||
- name: pip cache
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
if: ${{ inputs.enable-cache == 'true' }}
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-
|
||||
restore-keys: |
|
||||
${{ runner.os }}
|
||||
- name: load "NPM TAG"
|
||||
id: set-npm-tag
|
||||
uses: ./.github/actions/set-npm-tag
|
||||
- name: before install script
|
||||
uses: ./.github/actions/before-install
|
||||
|
||||
@@ -4,16 +4,22 @@ description: "Upload build artifacts"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: tar and upload artifacts
|
||||
shell: bash
|
||||
env:
|
||||
REMOTE_PATH: "alfresco-ng2-components/build-cache/${{ github.run_id }}"
|
||||
run: |
|
||||
packages=( dist nxcache node_modules )
|
||||
for i in "${packages[@]}"; do
|
||||
time tar czf $i.tar.gz $i
|
||||
du -h $i.tar.gz
|
||||
time aws s3 cp --no-progress $i.tar.gz "s3://${S3_BUILD_BUCKET_SHORT_NAME}/${REMOTE_PATH}/$i.tar.gz"
|
||||
done
|
||||
- name: Save dist to cache
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: dist
|
||||
key: dist-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
- name: Save nxcache to cache
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: nxcache
|
||||
key: nxcache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
- name: Save node_modules to cache
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.5
|
||||
uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # v3.29.5
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
with:
|
||||
languages: javascript
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.5
|
||||
uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 # v3.29.5
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -53,4 +53,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.5
|
||||
uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # v3.29.5
|
||||
|
||||
@@ -13,34 +13,16 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- master-patch-*
|
||||
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_BRANCH: ${{ github.ref_name }}
|
||||
GH_BUILD_DIR: ${{ github.workspace }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
BUILD_ID: ${{ github.run_id }}
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
NPM_REGISTRY_ADDRESS: ${{ secrets.NPM_REGISTRY_ADDRESS }}
|
||||
NPM_REGISTRY_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
|
||||
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
REDIRECT_URI: /
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -59,17 +41,18 @@ jobs:
|
||||
GITHUB_TOKEN: $BOT_GITHUB_TOKEN
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- id: set-dryrun
|
||||
uses: ./.github/actions/enable-dryrun
|
||||
with:
|
||||
dry-run-flag: ${{ inputs.dry-run-flag }}
|
||||
- name: install NPM
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
- name: "Release tag"
|
||||
env:
|
||||
DRYRUN_FLAG: ${{ steps.set-dryrun.outputs.dryrun }}
|
||||
run: |
|
||||
git fetch --all --quiet
|
||||
BRANCH=${GITHUB_REF##*/} ./scripts/github/release/git-tag.sh ${{ steps.set-dryrun.outputs.dryrun }}
|
||||
|
||||
BRANCH=${GITHUB_REF##*/} ./scripts/github/release/git-tag.sh $DRYRUN_FLAG
|
||||
|
||||
@@ -9,14 +9,17 @@ jobs:
|
||||
if: github.event.registry_package.package_type == 'npm' && github.event.registry_package.name == 'adf-core'
|
||||
steps:
|
||||
- name: Dispatch event to monorepo
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
PACKAGE_NAME: ${{ github.event.registry_package.name }}
|
||||
PACKAGE_VERSION: ${{ github.event.registry_package.package_version.name }}
|
||||
with:
|
||||
github-token: ${{ secrets.PAT_WRITE_PKG }}
|
||||
retries: 3
|
||||
script: |
|
||||
const payload = {
|
||||
package_name: "${{ github.event.registry_package.name }}",
|
||||
package_version: "${{ github.event.registry_package.package_version.name }}"
|
||||
package_name: process.env.PACKAGE_NAME,
|
||||
package_version: process.env.PACKAGE_VERSION
|
||||
};
|
||||
|
||||
await github.rest.repos.createDispatchEvent({
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
name: Pull Translations from Crowdin
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
- cron: "0 7-17 * * 1-5"
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
pull-from-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: Pull translations from Crowdin
|
||||
uses: crowdin/github-action@590c05e09a29f392b203faf4d6aa8e0cd32c7835 # v2.9.1
|
||||
uses: crowdin/github-action@08713f00a50548bfe39b37e8f44afb53e7a802d4 # v2.12.0
|
||||
with:
|
||||
upload_sources: false
|
||||
download_translations: true
|
||||
|
||||
@@ -33,38 +33,20 @@ concurrency:
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_BRANCH: ${{ github.ref_name }}
|
||||
GH_BUILD_DIR: ${{ github.workspace }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
BUILD_ID: ${{ github.run_id }}
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
REDIRECT_URI: /
|
||||
|
||||
jobs:
|
||||
pre-checks:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
|
||||
- name: Ensure SHA pinned actions
|
||||
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@fc87bb5b5a97953d987372e74478de634726b3e5 # v3.0.25
|
||||
uses: hyland/github-actions-ensure-sha-pinned-actions@22ca7a8cf33e873ba1d6fbcd2b71fa0ec5006b17 # v1.1.0
|
||||
|
||||
- name: Check package-lock.json version
|
||||
run: |
|
||||
@@ -79,20 +61,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get branch name
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@a32503e10c10dc999ffcdfa8bc8c5e705cf36928 # v8.31.0
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@7eb56e49e47d11547d61c3c68826022db830fc15 # v10.1.0
|
||||
|
||||
- name: Save commit message
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@a32503e10c10dc999ffcdfa8bc8c5e705cf36928 # v8.31.0
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@7eb56e49e47d11547d61c3c68826022db830fc15 # v10.1.0
|
||||
|
||||
- name: ci:force flag parser
|
||||
shell: bash
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.actor }}" == "dependabot[bot]" ]; then
|
||||
if [ "$EVENT_NAME" == "schedule" ] || [ "$ACTOR" == "dependabot[bot]" ]; then
|
||||
echo -e "\033[32mci:force check can be skipped\033[0m"
|
||||
skip_check="true"
|
||||
elif [[ "$COMMIT_MESSAGE" == *"[ci:force]"* ]]; then
|
||||
@@ -109,16 +94,21 @@ jobs:
|
||||
|
||||
- name: show pr number
|
||||
shell: bash
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.action.outputs.number }}
|
||||
run: |
|
||||
echo "PR: ${{ steps.action.outputs.number }}"
|
||||
echo "PR: $PR_NUMBER"
|
||||
|
||||
- name: check if pr is approved
|
||||
env:
|
||||
DEVEL_FLAG: ${{ inputs.devel }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
skip_check: "false"
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
PR_NUMBER: ${{ steps.action.outputs.number }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.actor }}" == "dependabot[bot]" ]; then
|
||||
if [ "$EVENT_NAME" == "schedule" ] || [ "$ACTOR" == "dependabot[bot]" ]; then
|
||||
echo -e "\033[32mci:force check can be skipped\033[0m"
|
||||
skip_check="true"
|
||||
elif [[ "$COMMIT_MESSAGE" == *"[ci:force]"* ]]; then
|
||||
@@ -126,11 +116,11 @@ jobs:
|
||||
skip_check="true"
|
||||
fi
|
||||
|
||||
if [ "${{ github.actor }}" == "dependabot[bot]" ] || [ "${{ github.actor }}" == "alfresco-build" ]; then
|
||||
echo -e "\033[32mCommit by ${{ github.actor }}. No need for approval.\033[0m"
|
||||
if [ "$ACTOR" == "dependabot[bot]" ] || [ "$ACTOR" == "alfresco-build" ]; then
|
||||
echo -e "\033[32mCommit by $ACTOR. No need for approval.\033[0m"
|
||||
skip_check="true"
|
||||
fi
|
||||
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
if [ "$EVENT_NAME" == "schedule" ] || [ "$EVENT_NAME" == "workflow_dispatch" ]; then
|
||||
echo -e "\033[32mSchedule event\033[0m"
|
||||
skip_check="true"
|
||||
fi
|
||||
@@ -142,7 +132,7 @@ jobs:
|
||||
|
||||
if [ "$skip_check" == "false" ]; then
|
||||
echo "Checking PR approval"
|
||||
prNumber=${{ steps.action.outputs.number }}
|
||||
prNumber=$PR_NUMBER
|
||||
echo "PR: $prNumber"
|
||||
checkApproval=$(gh api /repos/$GITHUB_REPOSITORY/pulls/$prNumber/reviews | jq '.[] | select(.state == "APPROVED") | .user.login')
|
||||
if [[ $checkApproval ]]; then
|
||||
@@ -161,15 +151,15 @@ jobs:
|
||||
needs: [check-if-pr-is-approved, pre-checks]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all tags and branches
|
||||
- uses: ./.github/actions/setup
|
||||
- name: install
|
||||
run: |
|
||||
npm ci
|
||||
npx nx run js-api:bundle
|
||||
npx nx run cli:bundle
|
||||
npm run bundle:js-api
|
||||
npm run bundle:cli
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
unit-tests:
|
||||
@@ -196,14 +186,16 @@ jobs:
|
||||
exclude: "insights,core,extensions,content-services,process-services$,eslint-plugin-eslint-angular,js-api"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all tags and branches
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- name: Run unit tests
|
||||
env:
|
||||
EXCLUDE_PATTERN: ${{ matrix.unit-tests.exclude }}
|
||||
run: |
|
||||
/usr/bin/xvfb-run --auto-servernum npx nx affected:test $NX_CALCULATION_FLAGS --exclude=${{ matrix.unit-tests.exclude }}
|
||||
/usr/bin/xvfb-run --auto-servernum npm run test:affected -- $NX_CALCULATION_FLAGS --exclude=$EXCLUDE_PATTERN
|
||||
|
||||
lint:
|
||||
# long timeout required when cache has to be recreated
|
||||
@@ -213,12 +205,12 @@ jobs:
|
||||
needs: [setup]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all tags and branches
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- run: npx nx affected --target=lint $NX_CALCULATION_FLAGS
|
||||
- run: npm run lint:affected -- $NX_CALCULATION_FLAGS
|
||||
|
||||
build-libs:
|
||||
# long timeout required when cache has to be recreated
|
||||
@@ -228,13 +220,12 @@ jobs:
|
||||
needs: [setup]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all tags and branches
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npx nx affected:build $NX_CALCULATION_FLAGS --prod
|
||||
- run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npx nx affected --target=build-storybook $NX_CALCULATION_FLAGS --configuration=ci
|
||||
- run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npm run build:affected -- $NX_CALCULATION_FLAGS --prod
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
PR-forbidden-labels:
|
||||
@@ -243,12 +234,12 @@ jobs:
|
||||
steps:
|
||||
- id: checkoutRepo
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: PR contains forbidden labels
|
||||
id: pr-forbidden
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: |
|
||||
const issueHasLabels = require('./scripts/github/update/check-issue-has-label.js');
|
||||
@@ -260,9 +251,12 @@ jobs:
|
||||
core.setFailed('The PR contains a forbidden label! You are not allowed to merge until the label is there.');
|
||||
}
|
||||
- name: Check value after
|
||||
env:
|
||||
STEP_RESULT: ${{ toJson(steps.pr-forbidden.*.result) }}
|
||||
HAS_FAILURE: ${{ contains(toJson(steps.pr-forbidden.*.result), 'failure') }}
|
||||
run: |
|
||||
echo "result ${{ toJson(steps.pr-forbidden.*.result) }}" && echo "result ${{ steps.pr-forbidden.*.result }}"
|
||||
echo "result ${{ contains(toJson(steps.pr-forbidden.*.result), 'failure') }}"
|
||||
echo "Step result: $STEP_RESULT"
|
||||
echo "Has failure: $HAS_FAILURE"
|
||||
|
||||
finalize:
|
||||
if: ${{ always() }}
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Automatic Rebase
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
name: Release lib on branch
|
||||
run-name: Release lib on branch ${{ github.ref_name }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry-run-flag:
|
||||
description: 'enable dry-run on artifact push'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_BRANCH: ${{ github.ref_name }}
|
||||
GH_BUILD_DIR: ${{ github.workspace }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
BUILD_ID: ${{ github.run_id }}
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
REDIRECT_URI: /
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
timeout-minutes: 20
|
||||
name: "Setup"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: set TAG_NPM BRANCH
|
||||
shell: bash
|
||||
run: |
|
||||
TAG_NPM="branch"
|
||||
echo "Set TAG with name: ${TAG_NPM}"
|
||||
echo "TAG_NPM=${TAG_NPM}" >> $GITHUB_ENV
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: false
|
||||
enable-node-modules-cache: false
|
||||
- name: install
|
||||
run: |
|
||||
npm ci
|
||||
npx nx run js-api:bundle
|
||||
npx nx run cli:bundle
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
release-npm:
|
||||
needs: [setup]
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: false
|
||||
enable-node-modules-cache: false
|
||||
- id: set-dryrun
|
||||
uses: ./.github/actions/enable-dryrun
|
||||
with:
|
||||
dry-run-flag: ${{ inputs.dry-run-flag }}
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- name: Set libraries versions
|
||||
run: |
|
||||
set -u;
|
||||
./scripts/update-version.sh -gnu || exit 1;
|
||||
- name: Set migrations
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const setMigrations = require('./scripts/github/release/set-migrations.js');
|
||||
setMigrations();
|
||||
- name: Build libraries
|
||||
run: |
|
||||
npx nx run-many --target=build --prod --skip-nx-cache
|
||||
npx nx run-many --target=build-schematics
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
name: release libraries GH registry
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
scope: '@alfresco'
|
||||
- run: npx nx run-many --target=npm-publish --tag=branch|| exit 1
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.PAT_WRITE_PKG }}
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
name: release libraries Npm registry
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://${{ vars.NPM_REGISTRY_ADDRESS }}'
|
||||
scope: '@alfresco'
|
||||
- run: npx nx run-many --target=npm-publish --tag=branch || exit 1
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
|
||||
|
||||
npm-check-bundle:
|
||||
needs: [release-npm]
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: ./.github/actions/npm-check-bundle
|
||||
@@ -8,6 +8,13 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry-run-flag:
|
||||
description: 'enable dry-run on artifact push'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
@@ -16,6 +23,10 @@ on:
|
||||
- develop-patch*
|
||||
- master-patch*
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
@@ -23,99 +34,51 @@ concurrency:
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_BRANCH: ${{ github.ref_name }}
|
||||
GH_BUILD_DIR: ${{ github.workspace }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
BUILD_ID: ${{ github.run_id }}
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
REDIRECT_URI: /
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
timeout-minutes: 20
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*' || github.event_name == 'workflow_dispatch'
|
||||
name: "Setup"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: false
|
||||
enable-node-modules-cache: false
|
||||
- name: install
|
||||
run: |
|
||||
npm ci
|
||||
npx nx run js-api:bundle
|
||||
npx nx run cli:bundle
|
||||
npm run bundle:js-api
|
||||
npm run bundle:cli
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
release-storybook:
|
||||
needs: [setup]
|
||||
timeout-minutes: 15
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- run: git fetch --all
|
||||
- id: set-dryrun
|
||||
uses: ./.github/actions/enable-dryrun
|
||||
with:
|
||||
dry-run-flag: ${{ inputs.dry-run-flag }}
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: false
|
||||
enable-node-modules-cache: false
|
||||
act: ${{ inputs.dry-run-flag }}
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- name: release Storybook docker
|
||||
run: |
|
||||
npx nx run stories:build-storybook --configuration ci
|
||||
. ./scripts/github/release/docker-tag.sh
|
||||
./scripts/github/release/release-storybook-docker.sh ${{ steps.set-dryrun.outputs.dryrun }}
|
||||
|
||||
release-npm:
|
||||
needs: [setup]
|
||||
outputs:
|
||||
release_version: ${{ steps.set-version.outputs.release_version }}
|
||||
timeout-minutes: 30
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*' || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write # Required for OIDC
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/setup
|
||||
- id: setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: false
|
||||
enable-node-modules-cache: false
|
||||
- id: set-dryrun
|
||||
uses: ./.github/actions/enable-dryrun
|
||||
@@ -128,43 +91,42 @@ jobs:
|
||||
set -u;
|
||||
./scripts/github/build/bumpversion.sh
|
||||
- name: Set migrations
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: |
|
||||
const setMigrations = require('./scripts/github/release/set-migrations.js');
|
||||
setMigrations();
|
||||
- name: build libraries
|
||||
run: |
|
||||
npx nx run-many -t build --prod --skip-nx-cache
|
||||
npx nx run-many -t build-schematics
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
npm run build:libs
|
||||
npm run build:schematics
|
||||
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
name: release libraries GH registry
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
scope: '@alfresco'
|
||||
- run: npx nx run-many -t npm-publish --tag=$TAG_NPM || exit 1
|
||||
- run: npm run publish -- --tag=${{ steps.setup.outputs.npm-tag }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.PAT_WRITE_PKG }}
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
name: release libraries Npm registry
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://${{ vars.NPM_REGISTRY_ADDRESS }}'
|
||||
scope: '@alfresco'
|
||||
- run: npx nx run-many -t npm-publish --tag=$TAG_NPM || exit 1
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
|
||||
- run: npm run publish -- --tag=${{ steps.setup.outputs.npm-tag }}
|
||||
|
||||
create-git-tag:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup, release-npm]
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
name: Create github tag
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: './.github/actions/create-git-tag'
|
||||
@@ -177,7 +139,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- name: HxP upstream invoke
|
||||
uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7 # v4.0.0
|
||||
with:
|
||||
@@ -194,16 +156,16 @@ jobs:
|
||||
npm-check-bundle:
|
||||
needs: [release-npm]
|
||||
timeout-minutes: 15
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*' || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
- uses: ./.github/actions/npm-check-bundle
|
||||
|
||||
push-translation-keys-to-crowdin:
|
||||
name: Push translations keys to Crowdin
|
||||
if: ${{ github.ref == 'refs/heads/develop' }}
|
||||
if: github.ref_name == 'develop' && github.event_name != 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup]
|
||||
permissions:
|
||||
@@ -212,10 +174,10 @@ jobs:
|
||||
actions: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||
|
||||
- name: Push Source Files to Crowdin
|
||||
uses: crowdin/github-action@590c05e09a29f392b203faf4d6aa8e0cd32c7835 # v2.9.1
|
||||
uses: crowdin/github-action@08713f00a50548bfe39b37e8f44afb53e7a802d4 # v2.12.0
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_sources_args: --delete-obsolete
|
||||
@@ -223,15 +185,15 @@ jobs:
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TRANSLATIONS_TOKEN }}
|
||||
|
||||
finalize:
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
name: Final Results
|
||||
needs: [release-storybook, release-npm, npm-check-bundle]
|
||||
steps:
|
||||
- name: Check job execution status
|
||||
if: >-
|
||||
${{
|
||||
contains(needs.*.result, 'failure')
|
||||
|| contains(needs.*.result, 'cancelled')
|
||||
}}
|
||||
run: exit 1
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
name: Final Results
|
||||
needs: [release-npm, npm-check-bundle]
|
||||
steps:
|
||||
- name: Check job execution status
|
||||
if: >-
|
||||
${{
|
||||
contains(needs.*.result, 'failure')
|
||||
|| contains(needs.*.result, 'cancelled')
|
||||
}}
|
||||
run: exit 1
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
export NODE_OPTIONS=--max_old_space_size=8192
|
||||
npx lint-staged
|
||||
lint-staged
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { create } from '@storybook/theming';
|
||||
import alfrescoLogo from '../lib/core/src/lib/assets/images/alfresco-logo.svg';
|
||||
|
||||
export default create({
|
||||
base: 'light',
|
||||
brandTitle: 'Hyland | Alfresco Storybook App',
|
||||
brandUrl: 'https://www.alfresco.com/',
|
||||
brandImage: alfrescoLogo,
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
module.exports = {
|
||||
framework: {
|
||||
name: '@storybook/angular',
|
||||
options: {}
|
||||
},
|
||||
staticDirs: [],
|
||||
docs: {},
|
||||
stories: [],
|
||||
addons: ['@chromatic-com/storybook']
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
export const parameters = {
|
||||
docs: { inlineStories: true },
|
||||
controls: { expanded: true }
|
||||
};
|
||||
export const tags = ['autodocs', 'autodocs', 'autodocs'];
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"exclude": [
|
||||
"../**/*.spec.js",
|
||||
"../**/*.spec.ts",
|
||||
"../**/*.spec.tsx",
|
||||
"../**/*.spec.jsx"
|
||||
],
|
||||
"include": ["../**/*"]
|
||||
}
|
||||
Vendored
-17
@@ -1,17 +0,0 @@
|
||||
specFile=$1;
|
||||
configFile=$2;
|
||||
|
||||
findconfig() {
|
||||
if [ -f "$1" ]; then
|
||||
printf '%s\n' "${PWD%/}/$1"
|
||||
elif [ "$PWD" = / ]; then
|
||||
false
|
||||
else
|
||||
(cd .. && findconfig $1)
|
||||
fi
|
||||
}
|
||||
|
||||
DIR=$(dirname "$specFile")
|
||||
cd $DIR
|
||||
configFile=`findconfig "$configFile"`;
|
||||
echo "$configFile";
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"lucono.karma-test-explorer"
|
||||
]
|
||||
}
|
||||
Vendored
-27
@@ -1,27 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "e2e",
|
||||
"program": "${workspaceFolder}/node_modules/protractor/bin/protractor",
|
||||
"args": [
|
||||
"./e2e/protractor.conf.js",
|
||||
"--specs=${file}"
|
||||
],
|
||||
"envFile": "${workspaceFolder}/.env",
|
||||
"console": "integratedTerminal",
|
||||
"sourceMaps": true,
|
||||
"smartStep": true,
|
||||
"skipFiles": [
|
||||
"${workspaceFolder}/node_modules/**/*.js",
|
||||
"<node_internals>/**/*.js"
|
||||
],
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
-1
@@ -5,7 +5,6 @@
|
||||
"**/.svn": true,
|
||||
"**/.hg": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/coverage": true,
|
||||
"**/.happypack": true
|
||||
},
|
||||
"markdownlint.config": {
|
||||
|
||||
Vendored
@@ -103,8 +103,6 @@ Create a file next to the project's `package.json`, call it `proxy.conf.json` an
|
||||
|
||||
Note that if you are running the App, Content Service or Process Service on different ports, you should change the ports accordingly in your local configuration.
|
||||
|
||||
For further details about how to configure a webpack proxy please refer to the [official documentation](https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md).
|
||||
|
||||
|
||||
## Configure nginx proxy
|
||||
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
# 1. Generate licenses
|
||||
|
||||
FROM node:18.16-alpine3.17 AS builder
|
||||
WORKDIR /usr/src/alfresco
|
||||
COPY package.json package.json
|
||||
|
||||
# 2. Generate image
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:1.21-alpine
|
||||
|
||||
USER root
|
||||
RUN apk update && apk upgrade
|
||||
USER 101
|
||||
|
||||
ARG PROJECT_NAME
|
||||
|
||||
COPY docker/default.conf.template /etc/nginx/templates/
|
||||
|
||||
COPY dist/$PROJECT_NAME /usr/share/nginx/html/
|
||||
COPY dist/$PROJECT_NAME/app.config.json /etc/nginx/templates/app.config.json.template
|
||||
|
||||
USER root
|
||||
RUN chmod a+w -R /etc/nginx/conf.d
|
||||
USER 101
|
||||
|
||||
ENV BASE_PATH=/
|
||||
ENV NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d
|
||||
@@ -35,7 +35,6 @@ ADF Libraries list:
|
||||
- [Insights](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/insights)
|
||||
- [Process Service Cloud](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/process-services-cloud)
|
||||
- [Process service](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/process-services)
|
||||
- [Stories](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/stories)
|
||||
|
||||
## Browser Support
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@
|
||||
"mouseenter",
|
||||
"multiselect",
|
||||
"mysites",
|
||||
"nginx",
|
||||
"numbervisibilityprocess",
|
||||
"OAUTHCONFIG",
|
||||
"oidc",
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
rewrite ^([^.]*[^/])$ $1/ permanent;
|
||||
absolute_redirect off;
|
||||
|
||||
location ${BASE_PATH} {
|
||||
set $EVAL_BASE_PATH "${BASE_PATH}";
|
||||
if ($EVAL_BASE_PATH = "/") {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
index index.html index.htm;
|
||||
alias /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
location ~ /app.config.json {
|
||||
alias ${NGINX_ENVSUBST_OUTPUT_DIR}/app.config.json;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
||||
@@ -113,7 +113,6 @@ A collection of Angular components for generic use.
|
||||
| [Json Cell component](core/components/json-cell.component.md) | Shows a JSON-formatted value inside a datatable component. | [Source](../lib/core/src/lib/datatable/components/json-cell/json-cell.component.ts) |
|
||||
| [Language Menu component](core/components/language-menu.component.md) | Displays all the languages that are present in "app.config.json" and the default (EN). | [Source](../lib/core/src/lib/language-menu/language-menu.component.ts) |
|
||||
| [Login Dialog Panel component](core/components/login-dialog-panel.component.md) | Shows and manages a login dialog. | [Source](../lib/core/src/lib/login/components/login-dialog-panel.component.ts) |
|
||||
| [Login Dialog component](core/components/login-dialog.component.md) | Allows a user to perform a login via a dialog. | [Source](../lib/core/src/lib/login/components/login-dialog.component.ts) |
|
||||
| [Login component](core/components/login.component.md) | Authenticates to Alfresco Content Services and Alfresco Process Services. | [Source](../lib/core/src/lib/login/components/login.component.ts) |
|
||||
| [Notification History component](core/components/notification-history.component.md)  | This component is in the current status just an experimental component. The main purpose of the Notification history component is list all the notification received in the current session. They will disappear from the list after the refresh. | [Source](../lib/core/src/lib/notifications/components/notification-history.component.ts) | |
|
||||
| [Pagination Component](core/components/pagination.component.md) | Adds pagination to the component it is used with. | [Source](../lib/core/src/lib/pagination/pagination.component.ts) |
|
||||
@@ -222,7 +221,6 @@ A collection of Angular components for generic use.
|
||||
| [Identity user service](core/services/identity-user.service.md) | Gets OAuth2 personal details and roles for users and performs CRUD operations on identity users. | [Source](../lib/process-services-cloud/src/lib/people/services/identity-user.service.ts) |
|
||||
| [JWT helper service](core/services/jwt-helper.service.md) | Decodes a JSON Web Token (JWT) to a JavaScript object. | [Source](../lib/core/src/lib/auth/services/jwt-helper.service.ts) |
|
||||
| [Log Service](core/services/log.service.md) | Provides log functionality. | [Source](../lib/core/src/lib/common/services/log.service.ts) |
|
||||
| [Login Dialog service](core/services/login-dialog.service.md) | Manages login dialogs. | [Source](../lib/core/src/lib/services/login-dialog.service.ts) |
|
||||
| [Nodes Api service](core/services/nodes-api.service.md) | Accesses and manipulates ACS document nodes using their node IDs. | [Source](../lib/content-services/src/lib/common/services/nodes-api.service.ts) |
|
||||
| [Notification Service](core/services/notification.service.md) | Shows a notification message with optional feedback. | [Source](../lib/core/src/lib/notifications/services/notification.service.ts) |
|
||||
| [Page Title service](core/services/page-title.service.md) | Sets the page title. | [Source](../lib/core/src/lib/common/services/page-title.service.ts) |
|
||||
@@ -472,12 +470,10 @@ for more information about installing and using the source code.
|
||||
|
||||
| Name | Description | Source link |
|
||||
| ---- | ----------- | ----------- |
|
||||
| [App List Cloud Component](process-services-cloud/components/app-list-cloud.component.md)  | Shows all deployed cloud application instances. | [Source](../lib/process-services-cloud/src/lib/app/components/app-list-cloud.component.ts) |
|
||||
| [Edit Process Filter Cloud component](process-services-cloud/components/edit-process-filter-cloud.component.md)  | Shows/edits process filter details. | [Source](../lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter/edit-process-filter-cloud.component.ts) |
|
||||
| [Edit Task Filter Cloud component](process-services-cloud/components/edit-task-filter-cloud.component.md)  | Edits task filter details. | [Source](../lib/process-services-cloud/src/lib/task/task-filters/components/edit-task-filters/edit-task-filter-cloud.component.ts) |
|
||||
| [Form cloud custom outcomes component](process-services-cloud/components/form-cloud-custom-outcome.component.md) | Supplies custom outcome buttons to be included in Form cloud component. | [Source](../lib/process-services-cloud/src/lib/form/components/form-cloud-custom-outcomes.component.ts) |
|
||||
| [Form cloud component](process-services-cloud/components/form-cloud.component.md) | Shows a form from Process Services. | [Source](../lib/process-services-cloud/src/lib/form/components/form-cloud.component.ts) |
|
||||
| [Form Definition Selector Cloud](process-services-cloud/components/form-definition-selector-cloud.component.md) | Allows one form to be selected from a dropdown list. For forms to be displayed in this component they will need to be compatible with standAlone tasks. | [Source](../lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts) |
|
||||
| [Group Cloud component](process-services-cloud/components/group-cloud.component.md)  | Searches Groups. | [Source](../lib/process-services-cloud/src/lib/group/components/group-cloud.component.ts) |
|
||||
| [](process-services-cloud/components/people-cloud.component.md) | Title: People Cloud Component | |
|
||||
|
||||
|
||||
@@ -25,12 +25,13 @@ before that release, please ensure that your component configuration is updated
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
|--------------|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| field | string | Field to apply the query to. Required value |
|
||||
| maxDate | string | A fixed date (default format: dd-MMM-yy) or the string `"today"` that will set the maximum searchable date. Default is today. |
|
||||
| dateFormat | string | Date format. Dates used by the datepicker are Javascript Date objects, using [date-fns](https://date-fns.org/v2.30.0/docs/format) for formatting, so you can use any date format supported by the library. Default is 'dd-MMM-yy (sample date - 07-Jun-23) |
|
||||
| initialValue | SearchDateRange | Initial value for the component |
|
||||
| Name | Type | Description |
|
||||
|--------------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| field | string | Field to apply the query to. Required value |
|
||||
| maxDate | string | A fixed date (default format: dd-MMM-yy) or the string `"today"` that will set the maximum searchable date. Default is today. |
|
||||
| dateFormat | string | Date format. Dates used by the datepicker are Javascript Date objects, using [date-fns](https://date-fns.org/v2.30.0/docs/format) for formatting, so you can use any date format supported by the library. Default is 'dd-MMM-yy (sample date - 07-Jun-23) |
|
||||
| initialValue | SearchDateRange | Initial value for the component |
|
||||
| onReset$ | [`Observable`](http://reactivex.io/documentation/observable.html)`<void>` | Reset event observable |
|
||||
|
||||
### Events
|
||||
|
||||
|
||||
@@ -16,12 +16,3 @@ Shows and manages a login dialog.
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| success | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<`[`LoginSuccessEvent`](../../../lib/core/src/lib/login/models/login-success.event.ts)`>` | Emitted when the login succeeds. |
|
||||
|
||||
## Details
|
||||
|
||||
This component has similar features to the [Login Dialog component](login-dialog.component.md)
|
||||
but it also creates and manages the dialog for you.
|
||||
|
||||
## See also
|
||||
|
||||
- [Login Dialog component](login-dialog.component.md)
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
---
|
||||
Title: Login Dialog component
|
||||
Added: v2.6.0
|
||||
Status: Active
|
||||
Last reviewed: 2018-10-02
|
||||
---
|
||||
|
||||
# [Login Dialog component](../../../lib/core/src/lib/login/components/login-dialog.component.ts "Defined in login-dialog.component.ts")
|
||||
|
||||
Allows a user to perform a login via a dialog.
|
||||
|
||||
## Details
|
||||
|
||||
The [Login Dialog component](login-dialog.component.md) allows you to perform a login via a dialog.
|
||||
|
||||
### Showing the dialog
|
||||
|
||||
Unlike most components, the [Login Dialog Component](login-dialog.component.md) is typically shown in a dialog box
|
||||
rather than the main page and you are responsible for opening the dialog yourself. You can use the
|
||||
[Angular Material Dialog](https://material.angular.io/components/dialog/overview) for this,
|
||||
as shown in the usage example. ADF provides the [`LoginDialogComponentData`](../../../lib/core/src/lib/login/components/login-dialog-component-data.interface.ts) interface
|
||||
to work with the Dialog's
|
||||
[data option](https://material.angular.io/components/dialog/overview#sharing-data-with-the-dialog-component-):
|
||||
|
||||
```ts
|
||||
export interface LoginDialogComponentData {
|
||||
title: string;
|
||||
actionName?: string;
|
||||
logged: Subject<any>;
|
||||
}
|
||||
```
|
||||
|
||||
The properties are described in the table below:
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| title | `string` | "" | Dialog title |
|
||||
| actionName | `string` | "" | Text to appear on the dialog's main action button ("Login", "Access", etc) |
|
||||
| logged | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | | Event emitted when the login succeeds. |
|
||||
|
||||
If you don't want to manage the dialog yourself then it is easier to use the
|
||||
[Login Dialog Panel component](login-dialog-panel.component.md), or the
|
||||
methods of the [Login Dialog service](../services/login-dialog.service.md), which create
|
||||
the dialog for you.
|
||||
|
||||
### Usage example
|
||||
|
||||
```ts
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { LoginDialogComponentData, LoginDialogComponent} from '@adf/core'
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
...
|
||||
|
||||
constructor(dialog: MatDialog ... ) {}
|
||||
|
||||
openLoginDialog() {
|
||||
data: LoginDialogComponentData = {
|
||||
title: "Perform a Login",
|
||||
actionName: "Access",
|
||||
logged: new Subject<any>()
|
||||
};
|
||||
|
||||
this.dialog.open(
|
||||
LoginDialogComponent,
|
||||
{
|
||||
data, panelClass: 'adf-login-dialog',
|
||||
width: '630px'
|
||||
}
|
||||
);
|
||||
|
||||
data.logged.subscribe(() => {
|
||||
// Action after being logged in...
|
||||
},
|
||||
(error)=>{
|
||||
//your error handling
|
||||
},
|
||||
()=>{
|
||||
//action called when an action or cancel is clicked on the dialog
|
||||
this.dialog.closeAll();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
All the results will be streamed to the logged [subject](http://reactivex.io/rxjs/manual/overview.html#subject) present in the [`LoginDialogComponentData`](../../../lib/core/src/lib/login/components/login-dialog-component-data.interface.ts) object passed to the dialog.
|
||||
When the dialog action is selected by clicking, the `data.logged` stream will be completed.
|
||||
|
||||
## See also
|
||||
|
||||
- [Login component](login.component.md)
|
||||
@@ -196,7 +196,6 @@ You can access an external provider to get an auth token for a user:
|
||||
"oauth2" : {
|
||||
"host": "http://myhost.com",
|
||||
"clientId": "my-client-id",
|
||||
"secret": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -294,7 +293,6 @@ enabled the setting in `app.config.json`) then the [login component](login.compo
|
||||
"host": "<AUTH-SERVER>/auth/realms/alfresco",
|
||||
"clientId": "activiti",
|
||||
"scope": "openid",
|
||||
"secret": "",
|
||||
"implicitFlow": true,
|
||||
"silentLogin": false,
|
||||
"redirectUri": "/",
|
||||
@@ -324,7 +322,6 @@ You can also enable automatic redirection to the OAuth provider using the follow
|
||||
"host": "<AUTH-SERVER>/auth/realms/alfresco",
|
||||
"clientId": "alfresco",
|
||||
"scope": "openid",
|
||||
"secret": "",
|
||||
"implicitFlow": true,
|
||||
"silentLogin": true,
|
||||
"redirectSilentIframeUri": "/assets/silent-refresh.html",
|
||||
|
||||
@@ -43,6 +43,7 @@ Contains the value and metadata for a field of a [`Form`](../../../lib/process-s
|
||||
| displayText | string | | Displayed text for Hyperlink widgets |
|
||||
| isVisible | boolean | true | Is the field shown on the form? |
|
||||
| visibilityCondition | [`WidgetVisibilityModel`](../../../lib/core/src/lib/form/models/widget-visibility.model.ts) | null | Defines a expression that determines whether the field is visible or not, based on its logical relation to values in other fields |
|
||||
| checkParentVisibilityForValidation | boolean | false | When enabled (and `FormModel.enableParentVisibilityCheck` is true), validation will be skipped if the field's parent container/group/section is hidden, even if the field itself is visible. |
|
||||
| enableFractions | boolean | false | Are numeric values allowed to contain a decimal point? |
|
||||
| currency | string | null | Currency symbol for Amount widgets |
|
||||
| dateDisplayFormat | string | | Date/time display format template |
|
||||
|
||||
@@ -41,6 +41,7 @@ Contains the value and metadata for a form.
|
||||
|isValid | true||is form valid|
|
||||
|processVariables| ProcessVariableModel[] | []|process variables|
|
||||
|variables| FormVariableModel[] | []|variables|
|
||||
|enableParentVisibilityCheck| boolean | false|Enables checking parent container/group/section visibility for validation. When enabled, fields with `checkParentVisibilityForValidation: true` will skip validation if their parent is hidden.|
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -112,3 +113,5 @@ Contains the value and metadata for a form.
|
||||
Changes variable value
|
||||
- `loadInjectedFieldValidators(injectedFieldValidators: FormFieldValidator[]): void`
|
||||
Checks it there are any injectedValidators and adds them to the array of field validators.
|
||||
- `isFieldOrParentHidden(field: FormFieldModel): boolean`
|
||||
Checks if a field or any of its parent containers/groups/sections is hidden. Returns true if the field should skip validation. Only checks parent visibility if `enableParentVisibilityCheck` is true and the field has `checkParentVisibilityForValidation` set to true.
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
Title: Login Dialog service
|
||||
Added: v2.6.0
|
||||
Status: Active
|
||||
Last reviewed: 2019-02-08
|
||||
---
|
||||
|
||||
# [Login Dialog service](../../../lib/core/src/lib/services/login-dialog.service.ts "Defined in login-dialog.service.ts")
|
||||
|
||||
Manages login dialogs.
|
||||
|
||||
## Methods
|
||||
|
||||
- **openLogin**(actionName: `string`, title: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<string>`<br/>
|
||||
Opens a login dialog.
|
||||
- _actionName:_ `string` - Text to show in the main action button
|
||||
- _title:_ `string` - Title for the login dialog
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<string>` - Confirmation of login from the dialog
|
||||
- **close**(): `<void>`<br/>
|
||||
Closes the currently open login dialog.
|
||||
|
||||
## Details
|
||||
|
||||
Use the methods of this service to manage login dialogs from code. As an alternative, you may
|
||||
find it easier to use the [Login dialog component](../components/login-dialog.component.md) to display the
|
||||
dialog directly from HTML.
|
||||
|
||||
## See also
|
||||
|
||||
- [Login dialog component](../components/login-dialog.component.md)
|
||||
- [Login component](../components/login.component.md)
|
||||
@@ -2,10 +2,10 @@
|
||||
Title: User Preferences Service
|
||||
Added: v2.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2019-01-16
|
||||
Last reviewed: 2025-11-20
|
||||
---
|
||||
|
||||
# [User Preferences Service](../../../lib/core/src/lib/common/services/user-preferences.service.ts "Defined in user-preferences.service.ts")
|
||||
# User Preferences Service
|
||||
|
||||
Stores preferences for the app and for individual components.
|
||||
|
||||
@@ -32,10 +32,10 @@ Stores preferences for the app and for individual components.
|
||||
Check if an item is present in the storage
|
||||
- _property:_ `string` - Name of the property
|
||||
- **Returns** `boolean` - True if the item is present, false otherwise
|
||||
- **select**(property: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
|
||||
- **select**(property: `string`): `Observable<any>`<br/>
|
||||
Sets up a callback to notify when a property has changed.
|
||||
- _property:_ `string` - The property to watch
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Notification callback
|
||||
- **Returns** `Observable<any>` - Notification callback
|
||||
- **set**(property: `string`, value: `any`)<br/>
|
||||
Sets a preference property.
|
||||
- _property:_ `string` - Name of the property
|
||||
@@ -65,13 +65,13 @@ class AppComponent {
|
||||
|
||||
onLoggedIn() {
|
||||
this.userPreferences.setStoragePrefix(
|
||||
this.authService.getEcmUsername()
|
||||
this.authService.getUsername()
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As soon as you assign the storage prefix, all settings that you get or set via the [`UserPreferencesService`](../../core/services/user-preferences.service.md) will be saved to a dedicated profile.
|
||||
As soon as you assign the storage prefix, all settings that you get or set via the `UserPreferencesService` will be saved to a dedicated profile.
|
||||
|
||||
You can import the service into your controller and use its APIs as shown below:
|
||||
|
||||
@@ -96,7 +96,7 @@ The service also provides quick access to a set of the "known" properties used a
|
||||
| ---- | ---- | ----------- |
|
||||
| authType | `string` | Authorization type (can be "ECM", "BPM" or "ALL"). |
|
||||
| disableCSRF | `boolean` | Prevents the CSRF Token from being submitted if true. Only valid for Process Services. |
|
||||
| paginationSize | `number` | [`Pagination`](../../../lib/content-services/document-list/models/document-library.model.ts) size. |
|
||||
| paginationSize | `number` | `Pagination` size. |
|
||||
| locale | `string` | Current locale setting. |
|
||||
|
||||
## User Preference onChange Stream
|
||||
@@ -112,7 +112,13 @@ whole set of user properties. This is useful when a component needs to react to
|
||||
```
|
||||
|
||||
You can also use the `select` method to get notification when a particular property is changed.
|
||||
A set of basic properties is added into the enumeration [`UserPreferenceValues`](lib/core/src/lib/services/user-preferences.service.ts) which gives you the key value to access the standard user preference service properties : **PaginationSize**, **DisableCSRF**, **Locale**, **SupportedPageSizes** and **ExpandedSideNavStatus**.
|
||||
A set of basic properties is added into the enumeration `UserPreferenceValues` which gives you the key value to access the standard user preference service properties:
|
||||
|
||||
- `PaginationSize`
|
||||
- `DisableCSRF`
|
||||
- `Locale`
|
||||
- `SupportedPageSizes`
|
||||
- `ExpandedSideNavStatus`
|
||||
|
||||
```ts
|
||||
userPreferences.disableCSRF = true;
|
||||
@@ -120,3 +126,58 @@ A set of basic properties is added into the enumeration [`UserPreferenceValues`]
|
||||
console.log(CSRFflag); //this will be true;
|
||||
});
|
||||
```
|
||||
|
||||
### Convenience Observables and Signals
|
||||
|
||||
For commonly accessed preferences like `locale`, the service provides both observables and signals that simplify access patterns.
|
||||
|
||||
#### Using Signals (Recommended - No Subscription Needed!)
|
||||
|
||||
Signals automatically handle cleanup and don't require manual unsubscription:
|
||||
|
||||
```ts
|
||||
export class MyComponent {
|
||||
private userPreferences = inject(UserPreferencesService);
|
||||
|
||||
// Signal - automatically reactive, no subscription needed!
|
||||
currentLocale = this.userPreferences.localeSignal;
|
||||
|
||||
// Use in template or computed values
|
||||
displayText = computed(() => `Current locale: ${this.currentLocale()}`);
|
||||
}
|
||||
```
|
||||
|
||||
Available signals:
|
||||
|
||||
- `localeSignal` - Current locale value
|
||||
- `paginationSizeSignal` - Current pagination size
|
||||
- `supportedPageSizesSignal` - Supported page sizes array
|
||||
|
||||
**Benefits of signals:**
|
||||
|
||||
- ✅ No manual subscription/unsubscription needed
|
||||
- ✅ Automatic cleanup when component is destroyed
|
||||
- ✅ Better performance with fine-grained reactivity
|
||||
- ✅ Simpler code - just read the value with `()`
|
||||
|
||||
#### Using Observables (For Advanced Cases)
|
||||
|
||||
If you need RxJS operators or imperative subscriptions:
|
||||
|
||||
```ts
|
||||
constructor(private userPreferences: UserPreferencesService) {
|
||||
// Observable - requires takeUntilDestroyed() to prevent memory leaks
|
||||
this.userPreferences.locale$
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe(locale => {
|
||||
this.currentLocale = locale;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Available observables:
|
||||
- `locale$` - Observable for locale changes
|
||||
- `paginationSize$` - Observable for pagination size changes
|
||||
- `supportedPageSizes$` - Observable for supported page sizes changes
|
||||
|
||||
**Note:** When subscribing to observables from a singleton service in a component, always use `takeUntilDestroyed()` or `takeUntil()` to prevent memory leaks.
|
||||
|
||||
@@ -58,3 +58,5 @@ The pages linked below contain the licenses for all third party dependencies of
|
||||
- [ADF 8.0.0](license-info-8.0.0.md)
|
||||
- [ADF 8.1.0](license-info-8.1.0.md)
|
||||
- [ADF 8.1.1](license-info-8.1.1.md)
|
||||
- [ADF 8.2.0](license-info-8.2.0.md)
|
||||
- [ADF 8.2.1](license-info-8.2.1.md)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
Title: License info, alfresco-ng2-components 8.2.0
|
||||
---
|
||||
|
||||
# License information for alfresco-ng2-components 8.2.0
|
||||
|
||||
This page lists all third party libraries the project depends on.
|
||||
|
||||
## Libraries
|
||||
|
||||
| Name | Version | License |
|
||||
| --- | --- | --- |
|
||||
| [@angular/animations](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/cdk](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/common](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/compiler](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/core](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/forms](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/material-date-fns-adapter](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/material](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/platform-browser](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/router](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@apollo/client](https://github.com/apollographql/apollo-client) | 3.13.1 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@cspell/eslint-plugin](https://github.com/streetsidesoftware/cspell) | 8.16.1 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker) | 15.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| @ngx-translate/core | 16.0.4 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@nx/webpack](https://github.com/nrwl/nx) | 20.8.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [angular-oauth2-oidc-jwks](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [apollo-angular](https://github.com/kamilkisiela/apollo-angular) | 10.0.3 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [chart.js](https://github.com/chartjs/Chart.js) | 4.4.4 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [cropperjs](https://github.com/fengyuanchen/cropperjs) | 1.6.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [date-fns](https://github.com/date-fns/date-fns) | 2.30.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [dotenv-expand](https://github.com/motdotla/dotenv-expand) | 11.0.7 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
|
||||
| dotenv-expand | 5.1.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
|
||||
| editorjs-html | 4.0.5 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [eventemitter3](https://github.com/primus/eventemitter3) | 4.0.7 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [eventemitter3](https://github.com/primus/eventemitter3) | 5.0.1 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [graphql-ws](https://github.com/enisdenjo/graphql-ws) | 6.0.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [material-icons](https://github.com/marella/material-icons) | 1.13.14 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [minimatch-browser](https://github.com/isaacs/minimatch) | 1.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) |
|
||||
| [ng2-charts](https://github.com/valor-software/ng2-charts) | 4.1.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) |
|
||||
| [node-fetch](https://github.com/node-fetch/node-fetch) | 3.3.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [pdfjs-dist](https://github.com/mozilla/pdf.js) | 5.1.91 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [raphael](https://github.com/DmitryBaranovskiy/raphael) | 2.3.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [rxjs](https://github.com/reactivex/rxjs) | 7.8.2 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [superagent](https://github.com/ladjs/superagent) | 9.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [tslib](https://github.com/Microsoft/tslib) | 2.8.1 | [0BSD](http://landley.net/toybox/license.html) |
|
||||
| [zone.js](https://github.com/angular/angular) | 0.15.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
Title: License info, alfresco-ng2-components 8.2.1
|
||||
---
|
||||
|
||||
# License information for alfresco-ng2-components 8.2.1
|
||||
|
||||
This page lists all third party libraries the project depends on.
|
||||
|
||||
## Libraries
|
||||
|
||||
| Name | Version | License |
|
||||
| --- | --- | --- |
|
||||
| [@angular/animations](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/cdk](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/common](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/compiler](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/core](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/forms](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/material-date-fns-adapter](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/material](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/platform-browser](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/router](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@apollo/client](https://github.com/apollographql/apollo-client) | 3.13.1 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@cspell/eslint-plugin](https://github.com/streetsidesoftware/cspell) | 8.16.1 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker) | 15.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| @ngx-translate/core | 16.0.4 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@nx/webpack](https://github.com/nrwl/nx) | 20.8.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [angular-oauth2-oidc-jwks](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [apollo-angular](https://github.com/kamilkisiela/apollo-angular) | 10.0.3 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [chart.js](https://github.com/chartjs/Chart.js) | 4.4.4 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [cropperjs](https://github.com/fengyuanchen/cropperjs) | 1.6.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [date-fns](https://github.com/date-fns/date-fns) | 2.30.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [dotenv-expand](https://github.com/motdotla/dotenv-expand) | 11.0.7 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
|
||||
| dotenv-expand | 5.1.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
|
||||
| editorjs-html | 4.0.5 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [eventemitter3](https://github.com/primus/eventemitter3) | 4.0.7 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [eventemitter3](https://github.com/primus/eventemitter3) | 5.0.1 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [graphql-ws](https://github.com/enisdenjo/graphql-ws) | 6.0.6 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [material-icons](https://github.com/marella/material-icons) | 1.13.14 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [minimatch-browser](https://github.com/isaacs/minimatch) | 1.0.0 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) |
|
||||
| [ng2-charts](https://github.com/valor-software/ng2-charts) | 4.1.1 | [ISC](https://www.isc.org/downloads/software-support-policy/isc-license/) |
|
||||
| [node-fetch](https://github.com/node-fetch/node-fetch) | 3.3.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [pdfjs-dist](https://github.com/mozilla/pdf.js) | 5.1.91 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [raphael](https://github.com/DmitryBaranovskiy/raphael) | 2.3.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [rxjs](https://github.com/reactivex/rxjs) | 7.8.2 | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [superagent](https://github.com/ladjs/superagent) | 9.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [tslib](https://github.com/Microsoft/tslib) | 2.8.1 | [0BSD](http://landley.net/toybox/license.html) |
|
||||
| [zone.js](https://github.com/angular/angular) | 0.15.0 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
Title: App List Cloud Component
|
||||
Added: v3.0.0
|
||||
Status: Experimental
|
||||
Last reviewed: 2025-01-03
|
||||
---
|
||||
|
||||
# App List Cloud Component
|
||||
|
||||
`standalone`, `component`
|
||||
|
||||
Shows all deployed cloud application instances.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-cloud-app-list [layoutType]="'GRID'" />
|
||||
```
|
||||
|
||||
### [Transclusions](../../user-guide/transclusion.md)
|
||||
|
||||
You can show custom content when there are no apps available by supplying an
|
||||
`<adf-custom-empty-content>` section:
|
||||
|
||||
```html
|
||||
<adf-cloud-app-list [layoutType]="'GRID'">
|
||||
<adf-custom-empty-content>
|
||||
No Apps present
|
||||
</adf-custom-empty-content>
|
||||
</adf-cloud-app-list>
|
||||
```
|
||||
|
||||
## Activiti 7
|
||||
|
||||
If you are generating a project for Activiti 7, you must add the list of apps you want to use in **app.config.json** .
|
||||
|
||||
For example :
|
||||
|
||||
```json
|
||||
{
|
||||
"alfresco-deployed-apps": [
|
||||
{
|
||||
"name": "simple-app"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
|------------|----------|---------------|--------------------------------------------------------------------------------------------------|
|
||||
| layoutType | `string` | LAYOUT_GRID | (**required**) Defines the layout of the apps. There are two possible values, "GRID" and "LIST". |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
|----------|------------------------------------------|---------------------------------------|
|
||||
| appClick | `EventEmitter<ApplicationInstanceModel>` | Emitted when an app entry is clicked. |
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
Title: Form Definition Selector Cloud
|
||||
Added: v3.3.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# [Form Definition Selector Cloud](../../../lib/process-services-cloud/src/lib/form/components/form-definition-selector-cloud.component.ts "Defined in form-definition-selector-cloud.component.ts")
|
||||
|
||||
Allows one form to be selected from a dropdown list. For forms to be displayed in this component they will need to be compatible with standAlone tasks.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-cloud-form-definition-selector
|
||||
[appName]="'simple-app'"
|
||||
(selectForm)="onFormSelect($event)">
|
||||
</adf-cloud-form-definition-selector>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| appName | `string` | "" | Name of the application. If specified, this shows the users who have access to the app. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| selectForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when a form is selected. |
|
||||
@@ -44,7 +44,3 @@ For example :
|
||||
```json
|
||||
"alfresco-deployed-apps" : [{"name": "simple-app"}]
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [App list cloud component](../components/app-list-cloud.component.md)
|
||||
|
||||
@@ -9,6 +9,8 @@ The first **General Availability** release was v2.0.0.
|
||||
|
||||
## General Availability
|
||||
|
||||
- [8.2.1](RelNote-8.2.1.md)
|
||||
- [8.2.0](RelNote-8.2.0.md)
|
||||
- [8.1.1](RelNote-8.1.1.md)
|
||||
- [8.1.0](RelNote-8.1.0.md)
|
||||
- [8.0.0](RelNote-8.0.0.md)
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
Title: Changelog for alfresco-ng2-components v8.2.0
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
- [2ebe4ccfb0](https://github.com/Alfresco/alfresco-ng2-components/commit/2ebe4ccfb0) AAE-39923 Placeholder transformed with currency based on locale (#11342)
|
||||
- [9af4b7a4b6](https://github.com/Alfresco/alfresco-ng2-components/commit/9af4b7a4b6) [MNT-25412] Chip autocomplete set input value when preselected options change (#11350)
|
||||
- [a748541ca0](https://github.com/Alfresco/alfresco-ng2-components/commit/a748541ca0) AAE-39988 Fix dropdown conditional functionality (#11343)
|
||||
- [ac3c30480b](https://github.com/Alfresco/alfresco-ng2-components/commit/ac3c30480b) AAE-39949 Fix error while deleting empty row in repeatable section (#11346)
|
||||
- [002c5b4bf7](https://github.com/Alfresco/alfresco-ng2-components/commit/002c5b4bf7) [MNT-25423] Prevent minimizing menu again when previous and current route contain minimize URL (#11345)
|
||||
- [d298d92214](https://github.com/Alfresco/alfresco-ng2-components/commit/d298d92214) [ACS-10592] Remove 'secret' field from OAUTH config across ADF/ACA/ADW (#11332)
|
||||
- [b7d687f3d2](https://github.com/Alfresco/alfresco-ng2-components/commit/b7d687f3d2) Adds quickRunDeployment property (#11340)
|
||||
- [c2c3bff7bb](https://github.com/Alfresco/alfresco-ng2-components/commit/c2c3bff7bb) [AAE-39926] added missing locale param (#11341)
|
||||
- [c2f4597309](https://github.com/Alfresco/alfresco-ng2-components/commit/c2f4597309) [MNT-25412] Proper date filter clean up after reset event (#11317)
|
||||
- [0d670dd333](https://github.com/Alfresco/alfresco-ng2-components/commit/0d670dd333) AAE-27107 Improve repeatable section widget (#11336)
|
||||
- [d85a261720](https://github.com/Alfresco/alfresco-ng2-components/commit/d85a261720) [ACS-10199] Add visible focus to the details tabs (#11335)
|
||||
- [b61912e3eb](https://github.com/Alfresco/alfresco-ng2-components/commit/b61912e3eb) [ACS-10300] a11y Fix: visible and accessible Group label is missing (#11330)
|
||||
- [ea58a5d794](https://github.com/Alfresco/alfresco-ng2-components/commit/ea58a5d794) [ACS-10310] Fix a11y - Screen reader announces column header as undefined (#11328)
|
||||
- [e11aa6ddf3](https://github.com/Alfresco/alfresco-ng2-components/commit/e11aa6ddf3) AAE-38748 Fix ComputeTitle undefined error in upstream (#11334)
|
||||
- [61e1395bfa](https://github.com/Alfresco/alfresco-ng2-components/commit/61e1395bfa) [ACS-10263] sr personal files mark all as read button incorrectly grouped as notification list (#11331)
|
||||
- [43622266ce](https://github.com/Alfresco/alfresco-ng2-components/commit/43622266ce) AAE-21565 Replace deprecated @import with @use in all scss files (#11273)
|
||||
- [38d98200a6](https://github.com/Alfresco/alfresco-ng2-components/commit/38d98200a6) [ACS-10196] other a11y all libraries error message not provided for name and library id fields (#11311)
|
||||
- [e28e924b87](https://github.com/Alfresco/alfresco-ng2-components/commit/e28e924b87) AAE-38748 Change clipboard directive to be a tooltip (#11293)
|
||||
- [3180ca8e9d](https://github.com/Alfresco/alfresco-ng2-components/commit/3180ca8e9d) AAE-37713 Amount locale display v.2 (#11319)
|
||||
- [c2add07426](https://github.com/Alfresco/alfresco-ng2-components/commit/c2add07426) [ACS-9166]: Recreating PR changes for support legacy config based saved searches (#11329)
|
||||
- [ab67ba3414](https://github.com/Alfresco/alfresco-ng2-components/commit/ab67ba3414) AAE-39155 Implement button widget on ADF (#11324)
|
||||
- [c4f276e228](https://github.com/Alfresco/alfresco-ng2-components/commit/c4f276e228) AAE-39612 Registering click event on form widget twice (#11323)
|
||||
- [f7d26d904f](https://github.com/Alfresco/alfresco-ng2-components/commit/f7d26d904f) AAE-27107 Create repeatable section widget (#11290)
|
||||
- [e85a27e05b](https://github.com/Alfresco/alfresco-ng2-components/commit/e85a27e05b) Revert "[ACS-10083] Filter not behaving correctly in file and site (#… (#11327)
|
||||
- [4acda3b09b](https://github.com/Alfresco/alfresco-ng2-components/commit/4acda3b09b) [MNT-25413] ADW - First login after a clear cache does not show the s… (#11318)
|
||||
- [4feba2f304](https://github.com/Alfresco/alfresco-ng2-components/commit/4feba2f304) [ACS-10332] Search: Editable Combobox Without Autocomplete Does Not D… (#11310)
|
||||
- [a4f5cfc964](https://github.com/Alfresco/alfresco-ng2-components/commit/a4f5cfc964) AAE-39560: security fixes (#11315)
|
||||
- [86093adf18](https://github.com/Alfresco/alfresco-ng2-components/commit/86093adf18) Revert "AAE-37713 Amount locale display (#11285)" (#11312)
|
||||
- [59b148ea03](https://github.com/Alfresco/alfresco-ng2-components/commit/59b148ea03) AAE-37713 Amount locale display (#11285)
|
||||
- [82b9b18891](https://github.com/Alfresco/alfresco-ng2-components/commit/82b9b18891) [ACS-10518]: Search input keyboard navigation accessibility fixes (#11270)
|
||||
- [5016eff847](https://github.com/Alfresco/alfresco-ng2-components/commit/5016eff847) [ACS-10083] Filter not behaving correctly in file and site (#11237)
|
||||
- [6ab54be7d0](https://github.com/Alfresco/alfresco-ng2-components/commit/6ab54be7d0) [ACS-10324]: checkbox enter key handling (#11271)
|
||||
- [2d68cf9916](https://github.com/Alfresco/alfresco-ng2-components/commit/2d68cf9916) [AAE-39261] Fix Portuguese date format to display dd/mm/yyyy (#11303)
|
||||
- [42a1ddf540](https://github.com/Alfresco/alfresco-ng2-components/commit/42a1ddf540) [ACS-10178] Remove deprecated ADF components (#11221)
|
||||
- [8c9f6a0828](https://github.com/Alfresco/alfresco-ng2-components/commit/8c9f6a0828) AAE-39318 Break dependency on AWS S3 (#11300)
|
||||
- [160b12993f](https://github.com/Alfresco/alfresco-ng2-components/commit/160b12993f) [ACS-10271][ACS-10236] a11y - Search filters have no visible labels (#11302)
|
||||
- [f152953cc9](https://github.com/Alfresco/alfresco-ng2-components/commit/f152953cc9) [ACS-10333] Personal files: New File Title Not Announced by Screen Readers After Upload (#11298)
|
||||
- [e202c693c1](https://github.com/Alfresco/alfresco-ng2-components/commit/e202c693c1) AAE-39314 Break dependencies on the "commander" lib in the CLI (#11299)
|
||||
- [1c8af0467e](https://github.com/Alfresco/alfresco-ng2-components/commit/1c8af0467e) [ACS-9980] Add SSO integration API (#11297)
|
||||
- [1685ee4c8b](https://github.com/Alfresco/alfresco-ng2-components/commit/1685ee4c8b) AAE-39268 Remove jasmine-marbles dependency and related test code from form-rules.model.spec.ts (#11296)
|
||||
- [983d505309](https://github.com/Alfresco/alfresco-ng2-components/commit/983d505309) HXIDP-5126 Fix adf-cloud-task-screen re-initialization on completing (#11291)
|
||||
- [81a0ee0963](https://github.com/Alfresco/alfresco-ng2-components/commit/81a0ee0963) AAE-39263 Remove Playwright dependencies (#11294)
|
||||
- [b1f9f32e3f](https://github.com/Alfresco/alfresco-ng2-components/commit/b1f9f32e3f) Remove .dockerignore file to clean up unused configurations.
|
||||
- [718df62173](https://github.com/Alfresco/alfresco-ng2-components/commit/718df62173) Remove nginx configuration file and update cspell dictionary to exclude 'nginx'
|
||||
- [e1d56be29c](https://github.com/Alfresco/alfresco-ng2-components/commit/e1d56be29c) [ACS-10325] a11y SR: Metadata edit button announced twice (#11275)
|
||||
- [9b17f50401](https://github.com/Alfresco/alfresco-ng2-components/commit/9b17f50401) [ACS-10319] SR: Personal files: Focus returns to input field instead of remaining on Copy link button (#11272)
|
||||
- [9fc7c22e18](https://github.com/Alfresco/alfresco-ng2-components/commit/9fc7c22e18) [ACS-10318] Fixed screen reader for date format in share dialog (#11274)
|
||||
- [72555b7326](https://github.com/Alfresco/alfresco-ng2-components/commit/72555b7326) AAE-37097 Cleanup unused Docker layer (#11269)
|
||||
- [5a8088a5ec](https://github.com/Alfresco/alfresco-ng2-components/commit/5a8088a5ec) [ACS-10321] SR: Personal Files:When navigating the breadcrumb with arrow keys, a button announced as 'dropdown' (#11262)
|
||||
- [dfc65ae45c](https://github.com/Alfresco/alfresco-ng2-components/commit/dfc65ae45c) AAE-38919 There is no deployment update without closing the panel (#11263)
|
||||
- [cef71a2d71](https://github.com/Alfresco/alfresco-ng2-components/commit/cef71a2d71) [ACS-10275] a11y - Notification & Filter indicators not announced by screen readers (#11267)
|
||||
- [124fd66965](https://github.com/Alfresco/alfresco-ng2-components/commit/124fd66965) AAE-38328 Support screens on start process event (#11261)
|
||||
- [0335a32a3a](https://github.com/Alfresco/alfresco-ng2-components/commit/0335a32a3a) [ACS-10334] Changed translations for save and cancel icons for image rotation and crop (#11258)
|
||||
- [8ebb67d1cf](https://github.com/Alfresco/alfresco-ng2-components/commit/8ebb67d1cf) Adds lastModifiedAt to application instance (#11257)
|
||||
- [84d32157ad](https://github.com/Alfresco/alfresco-ng2-components/commit/84d32157ad) [ACS-10165] filter out inaccessible locations from autocomplete (#11240)
|
||||
- [816601fcec](https://github.com/Alfresco/alfresco-ng2-components/commit/816601fcec) AAE-38420 Allow any string in QueryParams include param (#11252)
|
||||
- [cb5831450e](https://github.com/Alfresco/alfresco-ng2-components/commit/cb5831450e) [ACS-10327] Other A11y: Personal files: Duplicate Labels and Repeated Text in Personal Files Page (#11250)
|
||||
- [b8d228d409](https://github.com/Alfresco/alfresco-ng2-components/commit/b8d228d409) [ACS-10328] SR: Personal files: Add permission title is not descriptive. (#11249)
|
||||
- [970cd7d6e5](https://github.com/Alfresco/alfresco-ng2-components/commit/970cd7d6e5) [ACS-10238] sr personal files close button lacks appropriate label (#11248)
|
||||
- [74437a01c0](https://github.com/Alfresco/alfresco-ng2-components/commit/74437a01c0) [ACS-10336] Tags in Tag Column Not Announced by Screen Readers (#11247)
|
||||
- [56092ff2c1](https://github.com/Alfresco/alfresco-ng2-components/commit/56092ff2c1) [ACS-10189] Remove old api docs generators from ADF (#11224)
|
||||
- [33ca9313be](https://github.com/Alfresco/alfresco-ng2-components/commit/33ca9313be) [ACS-10384] after recent changes search query builder can t process non latin characters (#11241)
|
||||
- [8b553bb00f](https://github.com/Alfresco/alfresco-ng2-components/commit/8b553bb00f) [ACS-10145] Corrected font size and alignment for date field in metadata properties panel (#11228)
|
||||
- [25ecfcf5e1](https://github.com/Alfresco/alfresco-ng2-components/commit/25ecfcf5e1) [ACS-10296] Upload new version button made accessible with keyboard (#11242)
|
||||
- [3356dab434](https://github.com/Alfresco/alfresco-ng2-components/commit/3356dab434) [AAE-38312] fix start process error translation string (#11239)
|
||||
- [dffa37f182](https://github.com/Alfresco/alfresco-ng2-components/commit/dffa37f182) [MNT-25336] ADW can't start a Microsoft 365 session when using Basic … (#11238)
|
||||
- [622dcafbc4](https://github.com/Alfresco/alfresco-ng2-components/commit/622dcafbc4) AAE-38524 remove adf-core-theme (#11235)
|
||||
- [29d341cc3b](https://github.com/Alfresco/alfresco-ng2-components/commit/29d341cc3b) [AAE-37563] Removed some CSS that was causing forms not to expand fully in the container (#11227)
|
||||
- [b6ea1e056e](https://github.com/Alfresco/alfresco-ng2-components/commit/b6ea1e056e) AAE-38456 Reloading start process form (#11226)
|
||||
- [40ff0d56af](https://github.com/Alfresco/alfresco-ng2-components/commit/40ff0d56af) [AAE-37563] Fix for extra padding on top of fullscreen toolbar (#11225)
|
||||
- [6b9d3d2104](https://github.com/Alfresco/alfresco-ng2-components/commit/6b9d3d2104) AAE-38287 Cannot select dropdown options when selection type is multiple (#11220)
|
||||
- [fb72ccffcc](https://github.com/Alfresco/alfresco-ng2-components/commit/fb72ccffcc) [ACS-9725] Fix preview for files attached to tasks with display value form field (#11219)
|
||||
- [84fcc48c1a](https://github.com/Alfresco/alfresco-ng2-components/commit/84fcc48c1a) [ACS-10145] Fix truncated text in details info drawer (#11209)
|
||||
- [731443ca1c](https://github.com/Alfresco/alfresco-ng2-components/commit/731443ca1c) Fixed js-api dep for superagent (#11212)
|
||||
- [91d6b80965](https://github.com/Alfresco/alfresco-ng2-components/commit/91d6b80965) Revert "AAE-30882 Replace superagent (#11134)" (#11210)
|
||||
- [ef29bafc75](https://github.com/Alfresco/alfresco-ng2-components/commit/ef29bafc75) [AAE-37563] Added grey background to fullscreen and standalone fullscreen forms (#11208)
|
||||
- [591934db0e](https://github.com/Alfresco/alfresco-ng2-components/commit/591934db0e) [ACS-10117] Deprecate ADF Storybook and custom Docker builds (#11207)
|
||||
- [4964ae94c5](https://github.com/Alfresco/alfresco-ng2-components/commit/4964ae94c5) AAE-0000 Trigger alpha build (#11206)
|
||||
- [2b08e0c1d0](https://github.com/Alfresco/alfresco-ng2-components/commit/2b08e0c1d0) AAE-38287 Cannot select dropdown options when selection type is multiple (#11204)
|
||||
- [1b212e8805](https://github.com/Alfresco/alfresco-ng2-components/commit/1b212e8805) AAE-38063 Default buttons are temporarily visible before the custom buttons in workspace (#11198)
|
||||
- [d230176e7f](https://github.com/Alfresco/alfresco-ng2-components/commit/d230176e7f) AAE 38257 fixing js-api deps and bump some security versions (#11203)
|
||||
- [d49575ba03](https://github.com/Alfresco/alfresco-ng2-components/commit/d49575ba03) [MNT-24388] fix location search facet (#11171)
|
||||
- [1c8181fca8](https://github.com/Alfresco/alfresco-ng2-components/commit/1c8181fca8) [ACS-10100][Security] Remove npx usage from CI/CD and shell scripts to mitigate supply chain risks (#11201)
|
||||
- [4f2b5329c6](https://github.com/Alfresco/alfresco-ng2-components/commit/4f2b5329c6) [AAE-30882] - removing ts-morph added back again on rebase (#11199)
|
||||
- [a347b20f20](https://github.com/Alfresco/alfresco-ng2-components/commit/a347b20f20) AAE-30882 Replace superagent (#11134)
|
||||
- [b400757ad1](https://github.com/Alfresco/alfresco-ng2-components/commit/b400757ad1) AAE-30878 Migrating from event-emitter to eventemitter3 (#11187)
|
||||
- [10afe75e94](https://github.com/Alfresco/alfresco-ng2-components/commit/10afe75e94) [ACS-10100][Security] Remove npx usage from CI/CD and shell scripts to mitigate supply chain risks. [ACS-10117] Deprecate ADF Storybook and custom Docker builds (#11197)
|
||||
- [196b60a7d9](https://github.com/Alfresco/alfresco-ng2-components/commit/196b60a7d9) AAE-22072 Update of a simpleapp (#11160)
|
||||
- [82f96d9510](https://github.com/Alfresco/alfresco-ng2-components/commit/82f96d9510) AAE-36335 Handle custom redirects (#11167)
|
||||
- [36b4c34008](https://github.com/Alfresco/alfresco-ng2-components/commit/36b4c34008) [ACS-10126] remove ts morph dependency from the adf core lib (#11190)
|
||||
- [7206a6322d](https://github.com/Alfresco/alfresco-ng2-components/commit/7206a6322d) Revert "AAE-37847 Create Git tag at the end of release branch process when on patch PR (#11162)" (#11188)
|
||||
- [fd29e953d6](https://github.com/Alfresco/alfresco-ng2-components/commit/fd29e953d6) Revert "AAE-30878 Migrating from event-emitter to eventemitter3 which is … (#11116)" (#11186)
|
||||
- [c8c1ae7838](https://github.com/Alfresco/alfresco-ng2-components/commit/c8c1ae7838) [ACA] Label position problem in some perform actions like 'send-email' (#11185)
|
||||
- [3b5e98b182](https://github.com/Alfresco/alfresco-ng2-components/commit/3b5e98b182) [MNT-25285] Unable to change version preview from within the preview … (#11165)
|
||||
- [09c35ea903](https://github.com/Alfresco/alfresco-ng2-components/commit/09c35ea903) AAE-37573 Add editorjs-html to process-services-cloud dependencies (#11183)
|
||||
- [923feccdb9](https://github.com/Alfresco/alfresco-ng2-components/commit/923feccdb9) [MNT-25274] Fixed issue while uploading files with multi-valued properties (#11182)
|
||||
- [dfa6db447f](https://github.com/Alfresco/alfresco-ng2-components/commit/dfa6db447f) AAE-37996 Updated Docker secrets (#11170)
|
||||
- [e7bba32679](https://github.com/Alfresco/alfresco-ng2-components/commit/e7bba32679) AAE-37368 Applying new tasks and process count APIs (#11119)
|
||||
- [ea81fcd6ad](https://github.com/Alfresco/alfresco-ng2-components/commit/ea81fcd6ad) AAE-37907 Move editorjs-html to dependencies (#11169)
|
||||
- [f1fea0a70b](https://github.com/Alfresco/alfresco-ng2-components/commit/f1fea0a70b) AAE-37906 Extract rich text parsing service (#11164)
|
||||
- [0564e67ba6](https://github.com/Alfresco/alfresco-ng2-components/commit/0564e67ba6) AAE-37923 - npm-check-bundle should take the released version to be sure to check the correct package on patch release (#11168)
|
||||
- [88b857a8fe](https://github.com/Alfresco/alfresco-ng2-components/commit/88b857a8fe) bump @nx/workspace from 20.8.0 to 20.8.2 (#11163)
|
||||
- [51c55674b4](https://github.com/Alfresco/alfresco-ng2-components/commit/51c55674b4) AAE-35340 Replace deprecated toPromise() usages with firstValueFrom / lastValueFrom (#11161)
|
||||
- [49375181e4](https://github.com/Alfresco/alfresco-ng2-components/commit/49375181e4) AAE-30878 Migrating from event-emitter to eventemitter3 which is … (#11116)
|
||||
- [aae4efdd92](https://github.com/Alfresco/alfresco-ng2-components/commit/aae4efdd92) AAE-30058 Integer form field should not allow more than 10 digits (#11146)
|
||||
- [a4e62974ea](https://github.com/Alfresco/alfresco-ng2-components/commit/a4e62974ea) AAE-37847 Create Git tag at the end of release branch process when on patch PR (#11162)
|
||||
- [81fed833f5](https://github.com/Alfresco/alfresco-ng2-components/commit/81fed833f5) AAE-35842 Admin - filter out form specific processes (in Process Instances tab) (#11131)
|
||||
- [609144551c](https://github.com/Alfresco/alfresco-ng2-components/commit/609144551c) AAE-34139 Switch Yes and No button places and change focus from No to Yes. (#11148)
|
||||
- [5bc4c02a94](https://github.com/Alfresco/alfresco-ng2-components/commit/5bc4c02a94) AAE-35385 Improve releasing-patches guide (#11149)
|
||||
- [04d488b8ea](https://github.com/Alfresco/alfresco-ng2-components/commit/04d488b8ea) [ACS-9768] remove deprecated methods from auth related components (#11031)
|
||||
- [dabab63f78](https://github.com/Alfresco/alfresco-ng2-components/commit/dabab63f78) Fix Post release version bump to align with ACA (#11153)
|
||||
- [b277a29f32](https://github.com/Alfresco/alfresco-ng2-components/commit/b277a29f32) [ACS-4593] Fixed issue with too long notification text in snackbar (#11152)
|
||||
- [bdeb8a8e51](https://github.com/Alfresco/alfresco-ng2-components/commit/bdeb8a8e51) [ACS-10101] Reduce cron job execution window (#11151)
|
||||
- [f205cbc33c](https://github.com/Alfresco/alfresco-ng2-components/commit/f205cbc33c) Post release version bump (#11147)
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
Title: Changelog for alfresco-ng2-components v8.2.1
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
- [97b563e967](https://github.com/Alfresco/alfresco-ng2-components/commit/97b563e967) AAE-39940 Localisation fixes (#11359)
|
||||
- [ad41c0eae2](https://github.com/Alfresco/alfresco-ng2-components/commit/ad41c0eae2) fix create git tag (#11357)
|
||||
- [5f76d8efad](https://github.com/Alfresco/alfresco-ng2-components/commit/5f76d8efad) AAE-40082 Use new action to check sha on github actions (#11356)
|
||||
@@ -33,7 +33,7 @@ OAuth2 is a protocol that allows the application to authorize operations without
|
||||
|
||||
silentLogin: Enables silent authentication.
|
||||
|
||||
secret: The application's secret, used for secure authentication.
|
||||
secret: Deprecated and removed. The application's secret, used for secure authentication.
|
||||
|
||||
redirectUri: Where to redirect after a successful login.
|
||||
|
||||
@@ -86,7 +86,6 @@ OAuth2 is a protocol that allows the application to authorize operations without
|
||||
"oauth2": {
|
||||
"host": "https://your-idp.auth0.com",
|
||||
"clientId": "",
|
||||
"secret": "",
|
||||
"scope": "openid profile email offline_access",
|
||||
"implicitFlow": false,
|
||||
"codeFlow": true,
|
||||
@@ -112,7 +111,6 @@ OAuth2 is a protocol that allows the application to authorize operations without
|
||||
"oauth2": {
|
||||
"host": "https://cognito-idp.your-idp-url",
|
||||
"clientId": "",
|
||||
"secret": "",
|
||||
"scope": "openid profile email",
|
||||
"implicitFlow": false,
|
||||
"codeFlow": true,
|
||||
@@ -144,23 +142,4 @@ To address this, include the following script tag within the <head> section of y
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
# Docker Environment Variables
|
||||
These settings can be customized in a Docker environment using the following environment variables:
|
||||
|
||||
APP_CONFIG_OAUTH2_HOST
|
||||
APP_CONFIG_OAUTH2_CLIENTID
|
||||
APP_CONFIG_OAUTH2_CLIENT_SECRET
|
||||
APP_CONFIG_OAUTH2_IMPLICIT_FLOW
|
||||
APP_CONFIG_OAUTH2_CODE_FLOW
|
||||
APP_CONFIG_OAUTH2_AUDIENCE
|
||||
APP_CONFIG_OAUTH2_SCOPE
|
||||
APP_CONFIG_OAUTH2_LOGOUT_URL
|
||||
APP_CONFIG_OAUTH2_LOGOUT_PARAMETERS
|
||||
APP_CONFIG_OAUTH2_SILENT_LOGIN
|
||||
APP_CONFIG_OAUTH2_REDIRECT_SILENT_IFRAME_URI
|
||||
APP_CONFIG_OAUTH2_REDIRECT_LOGIN
|
||||
APP_CONFIG_OAUTH2_REDIRECT_LOGOUT
|
||||
|
||||
Adjust the above examples according to your specific environment and authentication provider settings. These configurations ensure that the application can securely authenticate users through OAuth2, aligning with the current best practices in web application security.
|
||||
|
||||
@@ -19,14 +19,24 @@
|
||||
|
||||
4. Apply and commit your fix to **develop-patch-VERSION** branch.
|
||||
|
||||
5. Run [release.sh](../../scripts/release.sh) script with proper patch version:
|
||||
5. Increment the version in the package.json with the following command where `-v` refers to the ADF version and `-vj` to the new js-api version.
|
||||
The js-api must have a major version that is one higher than the other packages. For example, if adf-core is at version `4.11.1`, then js-api should be at version `5.11.1`
|
||||
|
||||
```bash
|
||||
./scripts/update-version.sh -v X.X.X -vj X.X.X
|
||||
|
||||
# e.g. ./scripts/update-version.sh -v 4.1.11 -vj 5.1.11
|
||||
```
|
||||
6. The `"@alfresco/js-api"` dependency in the `lib/cli/package.json` has to remain unchanged
|
||||
|
||||
7. Run [release.sh](../../scripts/release.sh) script with proper patch version:
|
||||
|
||||
```bash
|
||||
scripts/release.sh -v VERSION
|
||||
|
||||
# e.g. scripts/release.sh -v 4.11.1
|
||||
```
|
||||
6. Push your changes and run all tests:
|
||||
8. Push your changes and run all tests:
|
||||
|
||||
```bash
|
||||
git push -u origin develop-patch-VERSION
|
||||
@@ -39,28 +49,28 @@
|
||||
git push
|
||||
```
|
||||
|
||||
7. Verify if tests are green and if everything looks fine, you can proceed further.
|
||||
9. Verify if tests are green and if everything looks fine, you can proceed further.
|
||||
|
||||
8. Create new branch from **master** and call it **master-patch-VERSION** (e.g. master-patch-4.11.1):
|
||||
10. Create new branch from **master** and call it **master-patch-VERSION** (e.g. master-patch-4.11.1):
|
||||
|
||||
```bash
|
||||
git checkout master
|
||||
git checkout -b master-patch-VERSION
|
||||
```
|
||||
|
||||
9. Merge **develop-patch-VERSION** into **master-patch-VERSION**:
|
||||
11. Merge **develop-patch-VERSION** into **master-patch-VERSION**:
|
||||
|
||||
```bash
|
||||
git checkout master-patch-VERSION
|
||||
git merge develop-patch-VERSION
|
||||
```
|
||||
|
||||
10. Push **master-patch-VERSION** branch:
|
||||
12. Push **master-patch-VERSION** branch:
|
||||
|
||||
```bash
|
||||
git push -u origin master-patch-VERSION
|
||||
```
|
||||
|
||||
11. Verify if build is green and check if proper [tag](https://github.com/Alfresco/alfresco-ng2-components/tags) was created.
|
||||
13. Verify if build is green and check if proper [tag](https://github.com/Alfresco/alfresco-ng2-components/tags) was created.
|
||||
|
||||
12. After all is done, you can **cherry-pick** your fix to develop.
|
||||
14. After all is done, you can **cherry-pick** your fix to develop.
|
||||
|
||||
+33
-69
@@ -32,79 +32,30 @@ an [online palette design tool](http://mcg.mbitson.com/).
|
||||
See the [Material Design Style page](https://material.io/guidelines/style/color.html#) for
|
||||
more information about color concepts.
|
||||
|
||||
## Defining a custom theme
|
||||
## Using Angular Material theming
|
||||
|
||||
When you want more customization than a pre-built theme offers, you can create your own theme file. You only need to include the packages you actually use in your application.
|
||||
ADF is based on Angular Material library, which offers solutions for theming your application with either:
|
||||
- Material Design 2 https://material.angular.dev/guide/material-2-theming
|
||||
- Material Design 3 https://material.angular.dev/guide/theming
|
||||
|
||||
```scss
|
||||
/*
|
||||
* Include only packages that you are using (and core by default)
|
||||
*/
|
||||
@use '@angular/material' as mat;
|
||||
@import '~@angular/material/theming';
|
||||
@import '~@alfresco/adf-core/theming';
|
||||
If you already setup Angular Material theming in the application you use ADF in, there is no need for taking additional steps to theme ADF components - colors, typography and other parts of the theme will be taken from your setup.
|
||||
|
||||
@include mat.core();
|
||||
## Customizing deprecated theme variables
|
||||
|
||||
$primary: mat.define-palette($alfresco-accent-orange);
|
||||
$accent: mat.define-palette($alfresco-accent-purple);
|
||||
$warn: mat.define-palette($alfresco-warn);
|
||||
$theme: mat.define-light-theme((
|
||||
color: (
|
||||
primary: $primary,
|
||||
accent: $accent,
|
||||
warn: $warn,
|
||||
),
|
||||
typography: $alfresco-typography
|
||||
));
|
||||
Currently we have an amount of custom variables around components to mange libraries look and feel consistently and globally.
|
||||
|
||||
@include angular-material-theme($theme);
|
||||
@include alfresco-material-theme($theme);
|
||||
```
|
||||
While they are getting deprecated to be replaced with [Angular Material system variables](https://material.angular.dev/guide/system-variables), for seamless integration with Angular Material's theming, you can provide values for those variables inside the `:root` element.
|
||||
|
||||
### Multiple themes
|
||||
|
||||
You can create multiple themes for your application:
|
||||
|
||||
#### Example of defining multiple themes
|
||||
|
||||
```scss
|
||||
@import '~@angular/material/theming';
|
||||
@import '~@alfresco/adf-core/theming';
|
||||
|
||||
@include mat-core($alfresco-typography);
|
||||
|
||||
$primary: mat.define-palette($alfresco-accent-orange);
|
||||
$accent: mat.define-palette($alfresco-accent-purple);
|
||||
$warn: mat.define-palette($alfresco-warn);
|
||||
$theme: mat.define-light-theme((
|
||||
color: (
|
||||
primary: $primary,
|
||||
accent: $accent,
|
||||
warn: $warn,
|
||||
),
|
||||
typography: $alfresco-typography
|
||||
));
|
||||
|
||||
$dark-theme: mat.define-dark-theme((
|
||||
color: (
|
||||
primary: $primary,
|
||||
accent: $accent,
|
||||
warn: $warn,
|
||||
),
|
||||
typography: $alfresco-typography
|
||||
));
|
||||
|
||||
@include alfresco-material-theme($theme);
|
||||
...like above
|
||||
|
||||
.adf-dark-theme {
|
||||
@include alfresco-material-theme($dark-theme);
|
||||
...like above
|
||||
For example:
|
||||
```css
|
||||
:root {
|
||||
--theme-primary-color: --mat-sys-primary;
|
||||
--theme-accent-color: --mat-sys-tertiary;
|
||||
}
|
||||
```
|
||||
Any component with the `add-dark-theme` class will use the dark theme, while other components will fall back to the default.
|
||||
**No new variables should be added to the project**
|
||||
|
||||
[Reference list of overridable variables](https://github.com/Alfresco/alfresco-ng2-components/blob/29d341cc3b6a0842a776464027dcb1154875a8f0/lib/core/src/lib/styles/_index.scss#L25)
|
||||
|
||||
## Default reusable class
|
||||
|
||||
@@ -132,13 +83,13 @@ Avoid adding css variables with custom values, values should come from the theme
|
||||
--new-variable: mat.get-color-from-palette($primary, 50), // good
|
||||
```
|
||||
|
||||
When styling components try to use theme related variables (colors, typography):
|
||||
```
|
||||
When styling components use Angular Material system variables (colors, typography, elevation):
|
||||
```scss
|
||||
.my-class {
|
||||
color:darkgrey; // bad
|
||||
color:var(--theme-primary-color); // good
|
||||
color:var(--mat-sys-primary); // good
|
||||
font-size:23px; // bad
|
||||
font-size:var(--theme-typography-body-1-font-size); // good
|
||||
font:var(--mat-sys-body-small); // good
|
||||
background:yellow; // bad
|
||||
background:var(--my-component-nr-200-background-color); // bad
|
||||
background:var(--theme-primary-color-50); // good
|
||||
@@ -148,7 +99,7 @@ When styling components try to use theme related variables (colors, typography):
|
||||
When using library like Angular Material try to follow patterns from this library.
|
||||
It helps to style components built with this library (just apply theme instead of custom styling).
|
||||
For example when creating input:
|
||||
```
|
||||
```html
|
||||
// bad
|
||||
<div class="my-custom-input">
|
||||
<div class="my-custom-label"></div>
|
||||
@@ -166,3 +117,16 @@ For example when creating input:
|
||||
<mat-error></mat-error>
|
||||
</mat-form-field>
|
||||
```
|
||||
|
||||
Avoid customizing Angular Material's internal selectors:
|
||||
|
||||
```scss
|
||||
// bad - targeting internal Angular Material selectors
|
||||
.mat-mdc-form-field .mdc-text-field__input {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.mat-mdc-button .mdc-button__label {
|
||||
font-weight: bold;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -395,8 +395,6 @@ backend services have been tested with each released version of ADF.
|
||||
<!--v260 start-->
|
||||
|
||||
- [Login dialog panel component](core/components/login-dialog-panel.component.md)
|
||||
- [Login dialog component](core/components/login-dialog.component.md)
|
||||
- [Login dialog service](core/services/login-dialog.service.md)
|
||||
|
||||
<!--v260 end-->
|
||||
|
||||
|
||||
@@ -55,3 +55,5 @@ The pages linked below contain the audit for all third party dependencies of ADF
|
||||
- [ADF 8.0.0](audit-info-8.0.0.md)
|
||||
- [ADF 8.1.0](audit-info-8.1.0.md)
|
||||
- [ADF 8.1.1](audit-info-8.1.1.md)
|
||||
- [ADF 8.2.0](audit-info-8.2.0.md)
|
||||
- [ADF 8.2.1](audit-info-8.2.1.md)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
Title: Audit info, alfresco-ng2-components 8.2.0
|
||||
---
|
||||
|
||||
# Audit information for alfresco-ng2-components 8.2.0
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: 0
|
||||
- High risk: 3
|
||||
- Moderate risk: 1
|
||||
- Low risk: 0
|
||||
|
||||
Dependencies analyzed:
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
|high | @nx/webpack | "<=0.0.0-pr-32023-55176ba || 19.8.11 - 19.8.15 || 20.0.8 - 21.3.3 || 21.4.0-beta.0 - 21.4.0-canary.20250815-18ba315" |
|
||||
|high | glob | "10.3.7 - 11.0.3" |
|
||||
|moderate | js-yaml | "<3.14.2 || >=4.0.0 <4.1.1" |
|
||||
|high | stylus | ">=0.64.0" |
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
Title: Audit info, alfresco-ng2-components 8.2.1
|
||||
---
|
||||
|
||||
# Audit information for alfresco-ng2-components 8.2.1
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: 0
|
||||
- High risk: 1
|
||||
- Moderate risk: 0
|
||||
- Low risk: 0
|
||||
|
||||
Dependencies analyzed:
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
|high | glob | "10.2.0 - 10.4.5" |
|
||||
|
||||
|
||||
Binary file not shown.
@@ -7,7 +7,6 @@ coverage
|
||||
dist
|
||||
|
||||
content-services/**/*.js
|
||||
!content-services/.storybook/*.js
|
||||
!content-services/karma.conf.js
|
||||
content-services/**/*.js.map
|
||||
content-services/**/*.d.ts
|
||||
@@ -18,7 +17,6 @@ process-services/**/*.js.map
|
||||
process-services/**/*.d.ts
|
||||
|
||||
core/**/*.js
|
||||
!core/.storybook/*.js
|
||||
!core/karma.conf.js
|
||||
core/**/*.js.map
|
||||
core/**/*.d.ts
|
||||
@@ -29,7 +27,6 @@ insights/**/*.js.map
|
||||
insights/**/*.d.ts
|
||||
|
||||
process-services-cloud/**/*.js
|
||||
!process-services-cloud/.storybook/*.js
|
||||
!process-services-cloud/karma.conf.js
|
||||
process-services-cloud/**/*.js.map
|
||||
process-services-cloud/**/*.d.ts
|
||||
|
||||
+45
-43
@@ -18,12 +18,24 @@ adf-cli <command> --help
|
||||
|
||||
## Developing
|
||||
|
||||
Link the project as a global tool
|
||||
### Quick Setup
|
||||
|
||||
Link the project as a global tool (builds and links in one command):
|
||||
|
||||
```bash
|
||||
npm link
|
||||
npm run link
|
||||
```
|
||||
|
||||
This will build the CLI and make the `adf-cli` command available globally on your system.
|
||||
|
||||
When you're done developing:
|
||||
|
||||
```bash
|
||||
npm run unlink
|
||||
```
|
||||
|
||||
### Development Mode
|
||||
|
||||
Build the tool in the **develop** mode (automatically watches for changes and rebuilds the commands):
|
||||
|
||||
```bash
|
||||
@@ -38,18 +50,32 @@ DEVELOP=true adf-cli <command>
|
||||
|
||||
In develop mode, the CLI takes the prebuilt scripts from the dist folder.
|
||||
|
||||
### Manual Workflow
|
||||
|
||||
If you need more control, you can manually build and link:
|
||||
|
||||
```bash
|
||||
# Build the CLI
|
||||
npm run build
|
||||
|
||||
# Or build with full distribution (includes copying resources)
|
||||
npm run dist
|
||||
|
||||
# Link from the dist directory
|
||||
cd ../../dist/libs/cli && npm link
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
| **Commands** |**Description** |
|
||||
| --- | --- |
|
||||
| changelog | Generate changelog report for two branches of git repository |
|
||||
| check-cs-env | Check cs env is up |
|
||||
| check-plugin-env | Check plugin status |
|
||||
| docker | Build and publish a docker image or create additional tag link |
|
||||
| init-aae-env | Init env |
|
||||
| init-aps-env | Init aps |
|
||||
| licenses | Create a 3th party license file |
|
||||
| audit | Check the security risk dependency in your package.json |
|
||||
| **Commands** | **Description** |
|
||||
|------------------|----------------------------------------------------------------|
|
||||
| changelog | Generate changelog report for two branches of git repository |
|
||||
| check-cs-env | Check cs env is up |
|
||||
| check-plugin-env | Check plugin status |
|
||||
| init-aae-env | Init env |
|
||||
| init-aps-env | Init aps |
|
||||
| licenses | Create a 3th party license file |
|
||||
| audit | Check the security risk dependency in your package.json |
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -128,29 +154,6 @@ npm install
|
||||
adf-cli audit
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
The command provides 2 targets 'Publish' (default value) and 'Link'
|
||||
|
||||
Publish target
|
||||
Move in the folder where you have your `Dockerfile` and run the command:
|
||||
|
||||
```bash
|
||||
adf-cli docker --target "publish" --dockerRepo "${docker_repository}" --dockerTags "${TAGS}"
|
||||
```
|
||||
|
||||
If you want to specify a different docker registry you can run
|
||||
```bash
|
||||
--loginCheck --loginUsername "username" --loginPassword "password" --loginRepo "quay.io"--dockerRepo "${docker_repository}" --dockerTags "${TAGS}"
|
||||
```
|
||||
|
||||
Link target
|
||||
In case you don't need to publish a new image but you would like to create a link to an already existing image (sourceTag) you can use the link target.
|
||||
|
||||
```bash
|
||||
adf-cli docker --target "link" --dockerRepo "${docker_repository}" --dockerTags "${TAGS}" --sourceTag "develop"
|
||||
```
|
||||
|
||||
### Initialize activiti cloud env
|
||||
|
||||
The following command is in charge of Initializing the activiti cloud env with the default apps:
|
||||
@@ -167,14 +170,13 @@ adf-cli init-aae-env --host "gateway_env" --oauth "identity_env" --identityHost
|
||||
If you want to add a new app the schema needs to be:
|
||||
|
||||
```text
|
||||
TEST_APP: {
|
||||
name: 'testapp',
|
||||
file_location: 'https://github.com/Alfresco/alfresco-ng2-components/blob/branch/e2e/resources/testapp.zip?raw=true',
|
||||
security: [
|
||||
{'role': 'APS_ADMIN', 'groups': ['myadmingroup'], 'users': ['myadminuser']},
|
||||
{'role': 'APS_USER', 'groups': ['myusergroup'], 'users': ['myuser']
|
||||
}]
|
||||
},
|
||||
TEST_APP: {
|
||||
name: 'testapp',
|
||||
file_location: 'https://github.com/Alfresco/alfresco-ng2-components/blob/branch/e2e/resources/testapp.zip?raw=true',
|
||||
security:[
|
||||
{'role': 'APS_ADMIN', groups': ['myadmingroup'], 'users': ['myadminuser']},
|
||||
{'role': 'APS_USER', 'groups': ['myusergroup'], 'users': ['myuser']}]
|
||||
},
|
||||
```
|
||||
|
||||
### Checks plugin status
|
||||
|
||||
+15
-3
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
const minimist = require('minimist');
|
||||
const { parseArgs } = require('node:util');
|
||||
const { resolve, join } = require('node:path');
|
||||
const { readFileSync, existsSync } = require('node:fs');
|
||||
const { argv, exit, env, cwd } = require('node:process');
|
||||
@@ -10,10 +10,22 @@ function printHelp() {
|
||||
console.log(`${name} v${version}`);
|
||||
}
|
||||
|
||||
const args = minimist(argv.slice(2), {
|
||||
boolean: ['verbose']
|
||||
const { values, positionals } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
verbose: {
|
||||
type: 'boolean'
|
||||
}
|
||||
},
|
||||
allowPositionals: true,
|
||||
strict: false
|
||||
});
|
||||
|
||||
const args = {
|
||||
...values,
|
||||
_: positionals
|
||||
};
|
||||
|
||||
if (args._.length === 0) {
|
||||
printHelp();
|
||||
exit(1);
|
||||
|
||||
Generated
+393
-508
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-cli",
|
||||
"description": "Alfresco ADF cli and utils",
|
||||
"version": "8.1.1",
|
||||
"version": "8.3.0",
|
||||
"author": "Hyland Software, Inc. and its affiliates",
|
||||
"bin": {
|
||||
"adf-cli": "bin/adf-cli",
|
||||
@@ -17,16 +17,15 @@
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"develop": "tsc -p tsconfig.json --watch",
|
||||
"dist": "rm -rf ../../dist/libs/cli && npm run build && cp -R ./bin ../../dist/libs/cli && cp -R ./resources ../../dist/libs/cli && cp -R ./templates ../../dist/libs/cli && cp ./package.json ../../dist/libs/cli"
|
||||
"dist": "rm -rf ../../dist/libs/cli && npm run build && cp -R ./bin ../../dist/libs/cli && cp -R ./resources ../../dist/libs/cli && cp -R ./templates ../../dist/libs/cli && cp ./package.json ../../dist/libs/cli",
|
||||
"link": "npm run dist && cd ../../dist/libs/cli && npm link",
|
||||
"unlink": "cd ../../dist/libs/cli && npm unlink"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alfresco/js-api": ">=9.1.0",
|
||||
"commander": "^6.2.1",
|
||||
"ejs": "^3.1.9",
|
||||
"@alfresco/js-api": ">=9.2.0",
|
||||
"ejs": "^3.1.10",
|
||||
"license-checker": "^25.0.1",
|
||||
"node-fetch": "^2.7.0",
|
||||
"rxjs": "7.8.2",
|
||||
"shelljs": "^0.8.3",
|
||||
"spdx-license-list": "^5.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
@@ -36,7 +35,6 @@
|
||||
"devDependencies": {
|
||||
"@types/ejs": "^3.1.2",
|
||||
"@types/node": "^20.1.7",
|
||||
"@types/shelljs": "^0.8.12",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
||||
|
||||
+70
-15
@@ -17,14 +17,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as shell from 'shelljs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import * as ejs from 'ejs';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { argv, exit } from 'node:process';
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
import { parseArgs } from 'node:util';
|
||||
|
||||
interface AuditCommandArgs {
|
||||
package?: string;
|
||||
@@ -39,19 +37,39 @@ interface AuditCommandArgs {
|
||||
* @returns void
|
||||
*/
|
||||
export default function main(_args: string[], workingDir: string) {
|
||||
program
|
||||
.description('Generate an audit report')
|
||||
.usage('audit [options]')
|
||||
.option('-p, --package <path>', 'Path to package file (default: package.json in working directory)')
|
||||
.option('-d, --outDir <dir>', 'Ouput directory (default: working directory)')
|
||||
.parse(argv);
|
||||
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
program.outputHelp();
|
||||
console.log(`
|
||||
Usage: audit [options]
|
||||
|
||||
Generate an audit report
|
||||
|
||||
Options:
|
||||
-p, --package <path> Path to package file (default: package.json in working directory)
|
||||
-d, --outDir <dir> Output directory (default: working directory)
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const options: AuditCommandArgs = program.opts();
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
package: {
|
||||
type: 'string',
|
||||
short: 'p'
|
||||
},
|
||||
outDir: {
|
||||
type: 'string',
|
||||
short: 'd'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const options: AuditCommandArgs = {
|
||||
package: values.package as string | undefined,
|
||||
outDir: values.outDir as string | undefined
|
||||
};
|
||||
|
||||
let packagePath = path.resolve(workingDir, 'package.json');
|
||||
|
||||
@@ -75,8 +93,45 @@ export default function main(_args: string[], workingDir: string) {
|
||||
console.log(`Running audit on ${packagePath}`);
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath).toString());
|
||||
const cmd = 'npm audit --json --prod';
|
||||
const jsonAudit = JSON.parse(shell.exec(cmd, { silent: true }));
|
||||
|
||||
// Run in the directory containing the package.json
|
||||
const packageDir = path.dirname(packagePath);
|
||||
|
||||
// Use spawnSync with array arguments for safer command execution (prevents shell injection)
|
||||
// Cross-platform: npm is available on PATH on all platforms (Windows, macOS, Linux)
|
||||
const result = spawnSync('npm', ['audit', '--json', '--prod'], {
|
||||
cwd: packageDir,
|
||||
encoding: 'utf-8',
|
||||
// shell: false is the default and more secure (no shell interpretation)
|
||||
shell: false,
|
||||
// Set maxBuffer to handle large audit outputs
|
||||
maxBuffer: 10 * 1024 * 1024 // 10MB
|
||||
});
|
||||
|
||||
let jsonAudit;
|
||||
|
||||
// npm audit returns non-zero exit code when vulnerabilities are found
|
||||
// We still want to parse the JSON output in this case
|
||||
if (result.error) {
|
||||
console.error('Failed to run npm audit:', result.error.message);
|
||||
reject(result.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const auditOutput = result.stdout;
|
||||
if (!auditOutput) {
|
||||
console.error('npm audit produced no output');
|
||||
reject(new Error('npm audit produced no output'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
jsonAudit = JSON.parse(auditOutput);
|
||||
} catch (parseError) {
|
||||
console.error('Failed to parse npm audit output');
|
||||
reject(parseError);
|
||||
return;
|
||||
}
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
|
||||
+101
-31
@@ -20,15 +20,13 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import { argv, exit } from 'node:process';
|
||||
import * as shell from 'shelljs';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import * as path from 'path';
|
||||
import { Command } from 'commander';
|
||||
import { logger } from './logger';
|
||||
import * as fs from 'fs';
|
||||
import * as ejs from 'ejs';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
interface Commit {
|
||||
hash: string;
|
||||
author: string;
|
||||
@@ -67,10 +65,22 @@ interface DiffOptions {
|
||||
* @returns URL pointing to the git remote
|
||||
*/
|
||||
function getRemote(workingDir: string): string {
|
||||
const command = 'git config --get remote.origin.url';
|
||||
const remote = shell.exec(command, { cwd: workingDir, silent: true }).toString();
|
||||
// Use spawnSync with array arguments for safer command execution (prevents shell injection)
|
||||
const result = spawnSync('git', ['config', '--get', 'remote.origin.url'], {
|
||||
cwd: workingDir,
|
||||
encoding: 'utf-8',
|
||||
shell: false
|
||||
});
|
||||
|
||||
return remote.trim();
|
||||
if (result.error) {
|
||||
throw new Error(`Failed to get git remote: ${result.error.message}`);
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`git config command failed with exit code ${result.status}: ${result.stderr}`);
|
||||
}
|
||||
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,14 +99,14 @@ function getCommits(options: DiffOptions): Array<Commit> {
|
||||
authorFilter = `bot|Alfresco Build User`;
|
||||
}
|
||||
|
||||
// Build git command arguments array for safe execution (prevents shell injection)
|
||||
const args = [
|
||||
`git`,
|
||||
`log`,
|
||||
'log',
|
||||
options.range,
|
||||
`--no-merges`,
|
||||
`--first-parent`,
|
||||
'--no-merges',
|
||||
'--first-parent',
|
||||
// this format is needed to allow parsing all characters in the commit message and safely convert to JSON
|
||||
`--format="{ ^@^hash^@^: ^@^%h^@^, ^@^author^@^: ^@^%an^@^, ^@^author_email^@^: ^@^%ae^@^, ^@^date^@^: ^@^%ad^@^, ^@^subject^@^: ^@^%s^@^ }"`
|
||||
'--format={ ^@^hash^@^: ^@^%h^@^, ^@^author^@^: ^@^%an^@^, ^@^author_email^@^: ^@^%ae^@^, ^@^date^@^: ^@^%ad^@^, ^@^subject^@^: ^@^%s^@^ }'
|
||||
];
|
||||
|
||||
if (options.max !== undefined) {
|
||||
@@ -107,9 +117,23 @@ function getCommits(options: DiffOptions): Array<Commit> {
|
||||
args.push(`--skip=${options.skip}`);
|
||||
}
|
||||
|
||||
const command = args.join(' ');
|
||||
// Use spawnSync with array arguments for safer command execution
|
||||
const result = spawnSync('git', args, {
|
||||
cwd: options.dir,
|
||||
encoding: 'utf-8',
|
||||
shell: false,
|
||||
maxBuffer: 10 * 1024 * 1024 // 10MB to handle large git logs
|
||||
});
|
||||
|
||||
let log = shell.exec(command, { cwd: options.dir, silent: true }).toString();
|
||||
if (result.error) {
|
||||
throw new Error(`Failed to get git commits: ${result.error.message}`);
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`git log command failed with exit code ${result.status}: ${result.stderr}`);
|
||||
}
|
||||
|
||||
let log = result.stdout;
|
||||
|
||||
// https://stackoverflow.com/a/13928240/14644447
|
||||
log = JSON.stringify(log.trim()).slice(1, -1).replace(/\^@\^/gm, '"');
|
||||
@@ -151,28 +175,74 @@ function commitAuthorAllowed(commit: Commit, authorFilter: string): boolean {
|
||||
* @returns void
|
||||
*/
|
||||
export default function main(_args: string[], workingDir: string) {
|
||||
program
|
||||
.description('Generate changelog report for two branches of git repository')
|
||||
.version('0.0.1', '-v, --version')
|
||||
.usage('changelog [options]')
|
||||
.option('-r, --range <range>', 'Commit range, e.g. origin/master..develop', 'origin/master..develop')
|
||||
.option('-d, --dir <dir>', 'Working directory (default: working directory)')
|
||||
.option('-m, --max <number>', 'Limit the number of commits to output')
|
||||
.option('-o, --output <dir>', 'Output directory, will use console output if not defined')
|
||||
.option('--skip <number>', 'Skip number commits before starting to show the commit output')
|
||||
.option('-f, --format <format>', 'Output format (md, html)', 'md')
|
||||
.option('-e --exclude <string>', 'Exclude authors from the output, comma-delimited list')
|
||||
.parse(argv);
|
||||
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
program.outputHelp();
|
||||
console.log(`
|
||||
Usage: changelog [options]
|
||||
|
||||
Generate changelog report for two branches of git repository
|
||||
|
||||
Options:
|
||||
-v, --version Output the version number
|
||||
-r, --range <range> Commit range, e.g. origin/master..develop (default: "origin/master..develop")
|
||||
-d, --dir <dir> Working directory (default: working directory)
|
||||
-m, --max <number> Limit the number of commits to output
|
||||
-o, --output <dir> Output directory, will use console output if not defined
|
||||
--skip <number> Skip number commits before starting to show the commit output
|
||||
-f, --format <format> Output format (md, html) (default: "md")
|
||||
-e, --exclude <string> Exclude authors from the output, comma-delimited list
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const options = program.opts();
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.0.1');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const dir = path.resolve(options.dir || workingDir);
|
||||
const { range, skip, max, format, output, exclude } = options;
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
range: {
|
||||
type: 'string',
|
||||
short: 'r',
|
||||
default: 'origin/master..develop'
|
||||
},
|
||||
dir: {
|
||||
type: 'string',
|
||||
short: 'd'
|
||||
},
|
||||
max: {
|
||||
type: 'string',
|
||||
short: 'm'
|
||||
},
|
||||
output: {
|
||||
type: 'string',
|
||||
short: 'o'
|
||||
},
|
||||
skip: {
|
||||
type: 'string'
|
||||
},
|
||||
format: {
|
||||
type: 'string',
|
||||
short: 'f',
|
||||
default: 'md'
|
||||
},
|
||||
exclude: {
|
||||
type: 'string',
|
||||
short: 'e'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const dir = path.resolve((values.dir as string) || workingDir);
|
||||
const range = values.range as string;
|
||||
const skip = values.skip ? parseInt(values.skip as string, 10) : undefined;
|
||||
const max = values.max ? parseInt(values.max as string, 10) : undefined;
|
||||
const format = values.format as string;
|
||||
const output = values.output as string | undefined;
|
||||
const exclude = values.exclude as string | undefined;
|
||||
|
||||
const remote = getRemote(dir);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { AlfrescoApi /*, NodesApi, UploadApi*/ } from '@alfresco/js-api';
|
||||
import { argv, exit } from 'node:process';
|
||||
import { Command } from 'commander';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { logger } from './logger';
|
||||
|
||||
interface CheckCsEnvArgs {
|
||||
@@ -27,8 +27,6 @@ interface CheckCsEnvArgs {
|
||||
time?: number;
|
||||
retry?: number;
|
||||
}
|
||||
|
||||
const program = new Command();
|
||||
const MAX_RETRY = 3;
|
||||
const TIMEOUT = 20000;
|
||||
|
||||
@@ -39,18 +37,63 @@ let alfrescoJsApi: AlfrescoApi;
|
||||
* Check CS environment command
|
||||
*/
|
||||
export default async function main() {
|
||||
program
|
||||
.version('0.1.0')
|
||||
.description('Check Content service is up ')
|
||||
.usage('check-cs-env [options]')
|
||||
.option('--host [type]', 'Remote environment host adf.lab.com ')
|
||||
.option('-p, --password [type]', 'password ')
|
||||
.option('-u, --username [type]', 'username ')
|
||||
.option('-t, --time [type]', 'time ')
|
||||
.option('-r, --retry [type]', 'retry ')
|
||||
.parse(argv);
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
console.log(`
|
||||
Usage: check-cs-env [options]
|
||||
|
||||
Check Content service is up
|
||||
|
||||
Options:
|
||||
-v, --version Output the version number
|
||||
--host <host> Remote environment host adf.lab.com
|
||||
-p, --password <pass> Password
|
||||
-u, --username <user> Username
|
||||
-t, --time <ms> Time in milliseconds
|
||||
-r, --retry <num> Retry count
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
host: {
|
||||
type: 'string'
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
short: 'p'
|
||||
},
|
||||
username: {
|
||||
type: 'string',
|
||||
short: 'u'
|
||||
},
|
||||
time: {
|
||||
type: 'string',
|
||||
short: 't'
|
||||
},
|
||||
retry: {
|
||||
type: 'string',
|
||||
short: 'r'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const opts: CheckCsEnvArgs = {
|
||||
host: values.host as string | undefined,
|
||||
username: values.username as string | undefined,
|
||||
password: values.password as string | undefined,
|
||||
time: values.time ? parseInt(values.time as string, 10) : undefined,
|
||||
retry: values.retry ? parseInt(values.retry as string, 10) : undefined
|
||||
};
|
||||
|
||||
const opts = program.opts();
|
||||
await checkEnv(opts);
|
||||
// TODO: https://alfresco.atlassian.net/browse/ACS-5873
|
||||
// await checkDiskSpaceFullEnv();
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { argv } from 'node:process';
|
||||
import { argv, exit } from 'node:process';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { CheckEnv } from './plugins/check-env';
|
||||
import { Command } from 'commander';
|
||||
import { ProcessServiceCheckPlugin } from './plugins/process-service-check-plugin';
|
||||
import { ProcessAutomationCheckPlugin } from './plugins/process-automation-check-plugin';
|
||||
import { GovernanceCheckPlugin } from './plugins/governance-check-plugin';
|
||||
|
||||
const program = new Command();
|
||||
let pluginEnv: CheckEnv;
|
||||
|
||||
interface CheckPluginArgs {
|
||||
@@ -39,18 +38,74 @@ interface CheckPluginArgs {
|
||||
* Check environment plugin
|
||||
*/
|
||||
export default async function main() {
|
||||
program
|
||||
.version('0.1.0')
|
||||
.option('--host [type]', 'Remote environment host')
|
||||
.option('--pluginName [type]', 'pluginName')
|
||||
.option('--clientId [type]', 'sso client', 'alfresco')
|
||||
.option('--appName [type]', 'appName ', 'Deployed appName on activiti-cloud')
|
||||
.option('-p, --password [type]', 'password ')
|
||||
.option('-u, --username [type]', 'username ')
|
||||
.option('--ui, --uiName [type]', 'uiName', 'Deployed app UI type on activiti-cloud')
|
||||
.parse(argv);
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
console.log(`
|
||||
Usage: check-plugin-env [options]
|
||||
|
||||
const options = program.opts();
|
||||
Check plugin status
|
||||
|
||||
Options:
|
||||
-v, --version Output the version number
|
||||
--host <host> Remote environment host
|
||||
--pluginName <name> Plugin name (processService, processAutomation, governance)
|
||||
--clientId <id> SSO client (default: "alfresco")
|
||||
--appName <name> Deployed appName on activiti-cloud
|
||||
-p, --password <pass> Password
|
||||
-u, --username <user> Username
|
||||
--ui, --uiName <name> Deployed app UI type on activiti-cloud
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
host: {
|
||||
type: 'string'
|
||||
},
|
||||
pluginName: {
|
||||
type: 'string'
|
||||
},
|
||||
clientId: {
|
||||
type: 'string',
|
||||
default: 'alfresco'
|
||||
},
|
||||
appName: {
|
||||
type: 'string'
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
short: 'p'
|
||||
},
|
||||
username: {
|
||||
type: 'string',
|
||||
short: 'u'
|
||||
},
|
||||
ui: {
|
||||
type: 'string'
|
||||
},
|
||||
uiName: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const options: CheckPluginArgs = {
|
||||
host: values.host as string | undefined,
|
||||
pluginName: values.pluginName as 'processService' | 'processAutomation' | 'governance' | undefined,
|
||||
clientId: values.clientId as string | undefined,
|
||||
appName: values.appName as string | undefined,
|
||||
username: values.username as string | undefined,
|
||||
password: values.password as string | undefined,
|
||||
uiName: (values.ui || values.uiName) as string | undefined
|
||||
};
|
||||
|
||||
pluginEnv = new CheckEnv(options.host, options.username, options.password, options.clientId);
|
||||
await pluginEnv.checkEnv();
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { argv, exit } from 'node:process';
|
||||
import { exec } from './exec';
|
||||
import { Command } from 'commander';
|
||||
import { logger } from './logger';
|
||||
import { resolve } from 'path';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
enum TARGETS {
|
||||
publish = 'publish',
|
||||
link = 'link'
|
||||
}
|
||||
|
||||
const DOCKER_FILENAME = 'Dockerfile';
|
||||
export interface PublishArgs {
|
||||
tag?: string;
|
||||
dryrun?: boolean;
|
||||
verbose?: boolean;
|
||||
loginCheck?: boolean;
|
||||
loginUsername?: string;
|
||||
loginPassword?: string;
|
||||
loginRepo?: string;
|
||||
dockerRepo?: string;
|
||||
buildArgs?: string[];
|
||||
dockerTags?: string;
|
||||
pathProject: string;
|
||||
fileName: string;
|
||||
sourceTag?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a login
|
||||
*
|
||||
* @param args arguments
|
||||
*/
|
||||
function login(args: PublishArgs) {
|
||||
logger.info(`Perform docker login...${args.loginRepo}`);
|
||||
const loginDockerRes = exec('docker', ['login', `-u=${args.loginUsername}`, `-p=${args.loginPassword}`, `${args.loginRepo}`]);
|
||||
logger.info(loginDockerRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Docker image
|
||||
*
|
||||
* @param args command arguments
|
||||
* @param tag tag
|
||||
*/
|
||||
function buildImage(args: PublishArgs, tag: string) {
|
||||
logger.info(`Perform docker build...${args.dockerRepo}:${tag}`);
|
||||
|
||||
const buildArgs = [];
|
||||
|
||||
if (typeof args.buildArgs === 'string') {
|
||||
buildArgs.push(`--build-arg=${args.buildArgs}`);
|
||||
} else {
|
||||
args.buildArgs.forEach((envVar) => {
|
||||
buildArgs.push(`--build-arg=${envVar}`);
|
||||
});
|
||||
}
|
||||
if (args.verbose) {
|
||||
logger.info(`Dry-run Perform docker build -t=${args.dockerRepo}:${tag} ${buildArgs} -f=${args.fileName} ${args.pathProject}`);
|
||||
}
|
||||
const response = exec('docker', ['build', `-t=${args.dockerRepo}:${tag}`, ...buildArgs, `-f=${args.fileName}`, args.pathProject], {});
|
||||
logger.info(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag Docker image
|
||||
*
|
||||
* @param args command arguments
|
||||
* @param imageTag image tag
|
||||
* @param newTag new image tag
|
||||
*/
|
||||
function tagImage(args: PublishArgs, imageTag: string, newTag: string) {
|
||||
logger.info(`Perform docker tag... ${args.dockerRepo}:${imageTag} on ${args.dockerRepo}:${newTag}`);
|
||||
const response = exec('docker', ['tag', `${args.dockerRepo}:${imageTag}`, `${args.dockerRepo}:${newTag}`], {});
|
||||
logger.info(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull Docker image
|
||||
*
|
||||
* @param dockerRepo repository
|
||||
* @param sourceTag tag
|
||||
*/
|
||||
function pullImage(dockerRepo: string, sourceTag: string) {
|
||||
logger.info(`Perform docker pull... ${dockerRepo}:${sourceTag}`);
|
||||
const response = exec('docker', ['pull', `${dockerRepo}:${sourceTag}`], {});
|
||||
logger.info(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push Docker image
|
||||
*
|
||||
* @param args command arguments
|
||||
* @param tag tag
|
||||
*/
|
||||
function pushImage(args: PublishArgs, tag: string) {
|
||||
if (args.dryrun) {
|
||||
logger.info(`Dry-run Perform docker push... ${args.dockerRepo}:${tag}`);
|
||||
} else {
|
||||
logger.info(`Perform docker push... ${args.dockerRepo}:${tag}`);
|
||||
const response = exec('docker', ['push', `${args.dockerRepo}:${tag}`], {});
|
||||
logger.info(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean Docker image
|
||||
*
|
||||
* @param args command arguments
|
||||
* @param tag tag
|
||||
*/
|
||||
function cleanImage(args: PublishArgs, tag: string) {
|
||||
logger.info(`Perform docker clean on tag:${tag}...`);
|
||||
const response = exec('docker', ['rmi', `-f`, `${args.dockerRepo}:${tag}`], {});
|
||||
logger.info(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish to Docker command
|
||||
*
|
||||
* @param args command arguments
|
||||
*/
|
||||
export default function main(args: PublishArgs) {
|
||||
program
|
||||
.version('0.1.0')
|
||||
.description(
|
||||
'Move in the folder where you have your Dockerfile and run the command:\n\n' +
|
||||
'adf-cli docker-publish --dockerRepo "${docker_repository}" --dockerTags "${TAGS}"'
|
||||
)
|
||||
.option('--loginRepo [type]', 'URL registry')
|
||||
.option('--loginPassword [type]', ' password')
|
||||
.option('--loginUsername [type]', ' username')
|
||||
.option('--dryrun [type]', 'dryrun')
|
||||
.option('--verbose [type]', 'verbose')
|
||||
.option('--loginCheck [type]', 'perform login')
|
||||
.option('--pathProject [type]', 'the path build context')
|
||||
.option('--sourceTag [type]', 'sourceTag')
|
||||
.option('--buildArgs [type...]', 'buildArgs')
|
||||
.option('--fileName [type...]', 'Docker file name', DOCKER_FILENAME)
|
||||
.option('--target [type]', 'target: publish or link', TARGETS.publish)
|
||||
.requiredOption('--dockerRepo [type]', 'docker repo')
|
||||
.requiredOption('--dockerTags [type]', ' tags')
|
||||
.parse(argv);
|
||||
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
program.outputHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Object.values(TARGETS).includes(program.opts().target)) {
|
||||
logger.error(`error: invalid --target value. It can be ${Object.values(TARGETS)}`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (program.opts().target === TARGETS.publish && args.buildArgs === undefined) {
|
||||
logger.error(`error: required option --buildArgs [type] in case the target is ${TARGETS.publish}`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (program.opts().target === TARGETS.link && args.sourceTag === undefined) {
|
||||
logger.error(`error: required option --sourceTag [type] in case the target is ${TARGETS.link}`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (args.pathProject === undefined) {
|
||||
args.pathProject = resolve('./');
|
||||
}
|
||||
|
||||
if (args.fileName === undefined) {
|
||||
args.fileName = DOCKER_FILENAME;
|
||||
}
|
||||
|
||||
if (args.loginCheck === true) {
|
||||
login(args);
|
||||
}
|
||||
|
||||
let mainTag: string;
|
||||
if (args.dockerTags !== '') {
|
||||
args.dockerTags.split(',').forEach((tag, index) => {
|
||||
if (tag) {
|
||||
logger.info(`Analyzing tag:${tag} ... for target ${program.opts().target}`);
|
||||
if (program.opts().target === TARGETS.publish) {
|
||||
if (index === 0) {
|
||||
logger.info(`Build only once`);
|
||||
mainTag = tag;
|
||||
buildImage(args, mainTag);
|
||||
}
|
||||
} else {
|
||||
mainTag = args.sourceTag;
|
||||
pullImage(args.dockerRepo, mainTag);
|
||||
}
|
||||
tagImage(args, mainTag, tag);
|
||||
pushImage(args, tag);
|
||||
}
|
||||
});
|
||||
cleanImage(args, mainTag);
|
||||
} else {
|
||||
logger.error(`dockerTags cannot be empty ...`);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'child_process';
|
||||
import { logger } from './logger';
|
||||
|
||||
export interface ExecOptions {
|
||||
cwd?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec function
|
||||
*
|
||||
* @param command command to execute
|
||||
* @param args command arguments
|
||||
* @param opts optional settings
|
||||
* @returns void function
|
||||
*/
|
||||
export function exec(command: string, args?: string[], opts?: ExecOptions) {
|
||||
if (process.platform.startsWith('win')) {
|
||||
args.unshift('/c', command);
|
||||
command = 'cmd.exe';
|
||||
}
|
||||
|
||||
const { status, error, stderr, stdout } = spawnSync(command, args, { ...opts });
|
||||
|
||||
if (status !== 0) {
|
||||
|
||||
if (args) {
|
||||
logger.error(`Command failed: ${command} ${args.map((x) => JSON.stringify(x)).join(', ')}`);
|
||||
} else {
|
||||
logger.error(`Command failed ${command}`);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
logger.error('Error: ' + (error ? error.message : 'undefined'));
|
||||
} else {
|
||||
logger.error(`STDERR:\n${stderr}`);
|
||||
}
|
||||
throw error;
|
||||
} else {
|
||||
return stdout.toString();
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,6 @@ export * from './audit';
|
||||
export * from './changelog';
|
||||
export * from './check-cs-env';
|
||||
export * from './check-plugin-env';
|
||||
export * from './docker';
|
||||
export * from './exec';
|
||||
export * from './init-aae-env';
|
||||
export * from './init-acs-env';
|
||||
export * from './init-aps-env';
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Command } from 'commander';
|
||||
import { parseArgs } from 'node:util';
|
||||
import fetch from 'node-fetch';
|
||||
import * as fs from 'fs';
|
||||
import { logger } from './logger';
|
||||
import { AlfrescoApi, AlfrescoApiConfig } from '@alfresco/js-api';
|
||||
import { argv, exit } from 'node:process';
|
||||
|
||||
const program = new Command();
|
||||
const ACTIVITI_CLOUD_APPS = require('./resources').ACTIVITI_CLOUD_APPS;
|
||||
|
||||
let alfrescoJsApiModeler: AlfrescoApi;
|
||||
@@ -40,7 +38,6 @@ export interface ConfigArgs {
|
||||
oauth: string;
|
||||
tokenEndpoint: string;
|
||||
clientId: string;
|
||||
secret: string;
|
||||
scope: string;
|
||||
host: string;
|
||||
tag: string;
|
||||
@@ -452,7 +449,6 @@ function getAlfrescoJsApiInstance(configArgs: ConfigArgs): AlfrescoApi {
|
||||
tokenUrl: `${ssoHost}/${configArgs.tokenEndpoint}`,
|
||||
clientId: `${configArgs.clientId}`,
|
||||
scope: `${configArgs.scope}`,
|
||||
secret: `${configArgs.secret}`,
|
||||
implicitFlow: false,
|
||||
silentLogin: false,
|
||||
redirectUri: '/'
|
||||
@@ -730,32 +726,98 @@ async function sleep(time: number) {
|
||||
* Init AAE environment command
|
||||
*/
|
||||
export default async function main() {
|
||||
program
|
||||
.version('0.1.0')
|
||||
.description(
|
||||
'The following command is in charge of Initializing the activiti cloud env with the default apps' +
|
||||
'adf-cli init-aae-env --host "gateway_env" --modelerUsername "modelerusername" --modelerPassword "modelerpassword" --devopsUsername "devevopsusername" --devopsPassword "devopspassword"'
|
||||
)
|
||||
.option('-h, --host [type]', 'Host gateway')
|
||||
.option('--oauth [type]', 'SSO host')
|
||||
.option('--clientId [type]', 'sso client')
|
||||
.option('--secret [type]', 'sso secret', '')
|
||||
.option('--scope [type]', 'sso scope', 'openid')
|
||||
.option('--tokenEndpoint [type]', 'discovery token Endpoint', 'auth/realms/${clientId}/protocol/openid-connect/token')
|
||||
.option('--modelerUsername [type]', 'username of a user with role ACTIVIT_MODELER')
|
||||
.option('--modelerPassword [type]', 'modeler password')
|
||||
.option('--devopsUsername [type]', 'username of a user with role ACTIVIT_DEVOPS')
|
||||
.option('--devopsPassword [type]', 'devops password')
|
||||
.option('--tag [type]', 'tag name of the codebase')
|
||||
.option('--envs [type...]', 'environment ids of the envs where to deploy the app')
|
||||
.parse(argv);
|
||||
if (argv.includes('--help')) {
|
||||
console.log(`
|
||||
Usage: init-aae-env [options]
|
||||
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
program.outputHelp();
|
||||
Initialize the activiti cloud env with the default apps
|
||||
|
||||
Example:
|
||||
adf-cli init-aae-env --host "gateway_env" --modelerUsername "modelerusername" \\
|
||||
--modelerPassword "modelerpassword" --devopsUsername "devopsusername" \\
|
||||
--devopsPassword "devopspassword"
|
||||
|
||||
Options:
|
||||
-v, --version Output the version number
|
||||
-h, --host <host> Host gateway
|
||||
--oauth <host> SSO host
|
||||
--clientId <id> SSO client
|
||||
--secret <secret> SSO secret (default: "")
|
||||
--scope <scope> SSO scope (default: "openid")
|
||||
--tokenEndpoint <endpoint> Discovery token endpoint (default: "auth/realms/\${clientId}/protocol/openid-connect/token")
|
||||
--modelerUsername <username> Username of a user with role ACTIVIT_MODELER
|
||||
--modelerPassword <password> Modeler password
|
||||
--devopsUsername <username> Username of a user with role ACTIVIT_DEVOPS
|
||||
--devopsPassword <password> Devops password
|
||||
--tag <tag> Tag name of the codebase
|
||||
--envs <envs...> Environment ids of the envs where to deploy the app
|
||||
--help Display help for command
|
||||
`);
|
||||
return;
|
||||
}
|
||||
|
||||
const options = initializeDefaultToken(program.opts() as ConfigArgs);
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
host: {
|
||||
type: 'string',
|
||||
short: 'h'
|
||||
},
|
||||
oauth: {
|
||||
type: 'string'
|
||||
},
|
||||
clientId: {
|
||||
type: 'string'
|
||||
},
|
||||
scope: {
|
||||
type: 'string',
|
||||
default: 'openid'
|
||||
},
|
||||
tokenEndpoint: {
|
||||
type: 'string',
|
||||
default: 'auth/realms/${clientId}/protocol/openid-connect/token'
|
||||
},
|
||||
modelerUsername: {
|
||||
type: 'string'
|
||||
},
|
||||
modelerPassword: {
|
||||
type: 'string'
|
||||
},
|
||||
devopsUsername: {
|
||||
type: 'string'
|
||||
},
|
||||
devopsPassword: {
|
||||
type: 'string'
|
||||
},
|
||||
tag: {
|
||||
type: 'string'
|
||||
},
|
||||
envs: {
|
||||
type: 'string',
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const options = initializeDefaultToken({
|
||||
host: values.host as string,
|
||||
oauth: values.oauth as string,
|
||||
clientId: values.clientId as string,
|
||||
scope: values.scope as string,
|
||||
tokenEndpoint: values.tokenEndpoint as string,
|
||||
modelerUsername: values.modelerUsername as string,
|
||||
modelerPassword: values.modelerPassword as string,
|
||||
devopsUsername: values.devopsUsername as string,
|
||||
devopsPassword: values.devopsPassword as string,
|
||||
tag: values.tag as string,
|
||||
envs: (values.envs as string[]) || []
|
||||
} as ConfigArgs);
|
||||
|
||||
args = {
|
||||
host: options.host,
|
||||
@@ -767,7 +829,6 @@ export default async function main() {
|
||||
oauth: options.oauth,
|
||||
tokenEndpoint: options.tokenEndpoint,
|
||||
scope: options.scope,
|
||||
secret: options.secret,
|
||||
tag: options.tag,
|
||||
envs: options.envs
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { AlfrescoApi, SharedlinksApi, FavoritesApi, NodesApi, UploadApi, NodeEntry } from '@alfresco/js-api';
|
||||
import { exit, argv } from 'node:process';
|
||||
import { Command } from 'commander';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { createReadStream } from 'fs';
|
||||
import * as path from 'path';
|
||||
import { logger } from './logger';
|
||||
@@ -28,8 +28,6 @@ interface InitAcsEnvArgs {
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
const program = new Command();
|
||||
const MAX_RETRY = 10;
|
||||
let counter = 0;
|
||||
const TIMEOUT = 6000;
|
||||
@@ -41,15 +39,57 @@ let alfrescoJsApi: AlfrescoApi;
|
||||
* Init ACS environment command
|
||||
*/
|
||||
export default async function main() {
|
||||
program
|
||||
.version('0.1.0')
|
||||
.option('--host [type]', 'Remote environment host')
|
||||
.option('--clientId [type]', 'sso client', 'alfresco')
|
||||
.option('-p, --password [type]', 'password ')
|
||||
.option('-u, --username [type]', 'username ')
|
||||
.parse(argv);
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
console.log(`
|
||||
Usage: init-acs-env [options]
|
||||
|
||||
Initialize ACS environment
|
||||
|
||||
Options:
|
||||
-v, --version Output the version number
|
||||
--host <host> Remote environment host
|
||||
--clientId <id> SSO client (default: "alfresco")
|
||||
-p, --password <pass> Password
|
||||
-u, --username <user> Username
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
host: {
|
||||
type: 'string'
|
||||
},
|
||||
clientId: {
|
||||
type: 'string',
|
||||
default: 'alfresco'
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
short: 'p'
|
||||
},
|
||||
username: {
|
||||
type: 'string',
|
||||
short: 'u'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const opts: InitAcsEnvArgs = {
|
||||
host: values.host as string | undefined,
|
||||
clientId: values.clientId as string | undefined,
|
||||
username: values.username as string | undefined,
|
||||
password: values.password as string | undefined
|
||||
};
|
||||
|
||||
const opts = program.opts();
|
||||
await checkEnv(opts);
|
||||
|
||||
logger.info(`***** Step initialize ACS *****`);
|
||||
|
||||
@@ -26,12 +26,11 @@ import {
|
||||
AppDefinitionUpdateResultRepresentation
|
||||
} from '@alfresco/js-api';
|
||||
import { argv, exit } from 'node:process';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { createReadStream } from 'node:fs';
|
||||
import { Command } from 'commander';
|
||||
import * as path from 'path';
|
||||
import { logger } from './logger';
|
||||
import { throwError } from 'rxjs';
|
||||
|
||||
interface InitApsEnvArgs {
|
||||
host?: string;
|
||||
@@ -40,8 +39,6 @@ interface InitApsEnvArgs {
|
||||
password?: string;
|
||||
license?: string;
|
||||
}
|
||||
|
||||
const program = new Command();
|
||||
const MAX_RETRY = 10;
|
||||
let counter = 0;
|
||||
const TIMEOUT = 6000;
|
||||
@@ -56,16 +53,62 @@ let alfrescoJsApi: AlfrescoApi;
|
||||
* Init APS command
|
||||
*/
|
||||
export default async function main() {
|
||||
program
|
||||
.version('0.1.0')
|
||||
.option('--host [type]', 'Remote environment host')
|
||||
.option('--clientId [type]', 'sso client', 'alfresco')
|
||||
.option('-p, --password [type]', 'password ')
|
||||
.option('-u, --username [type]', 'username ')
|
||||
.option('--license [type]', 'APS license S3 path ')
|
||||
.parse(argv);
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
console.log(`
|
||||
Usage: init-aps-env [options]
|
||||
|
||||
Initialize APS environment
|
||||
|
||||
Options:
|
||||
-v, --version Output the version number
|
||||
--host <host> Remote environment host
|
||||
--clientId <id> SSO client (default: "alfresco")
|
||||
-p, --password <pass> Password
|
||||
-u, --username <user> Username
|
||||
--license <path> APS license S3 path
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
host: {
|
||||
type: 'string'
|
||||
},
|
||||
clientId: {
|
||||
type: 'string',
|
||||
default: 'alfresco'
|
||||
},
|
||||
password: {
|
||||
type: 'string',
|
||||
short: 'p'
|
||||
},
|
||||
username: {
|
||||
type: 'string',
|
||||
short: 'u'
|
||||
},
|
||||
license: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const opts: InitApsEnvArgs = {
|
||||
host: values.host as string | undefined,
|
||||
clientId: values.clientId as string | undefined,
|
||||
username: values.username as string | undefined,
|
||||
password: values.password as string | undefined,
|
||||
license: values.license as string | undefined
|
||||
};
|
||||
|
||||
const opts = program.opts();
|
||||
await checkEnv(opts);
|
||||
|
||||
logger.info(`***** Step 1 - Check License *****`);
|
||||
@@ -207,9 +250,9 @@ async function hasDefaultTenant(tenantId: number, tenantName: string): Promise<b
|
||||
logger.info(`Aps: has default tenantId: ${tenantId} and name ${tenantName}`);
|
||||
return true;
|
||||
} else {
|
||||
logger.info(`Wrong configuration. Another tenant has been created with id ${tenant.id} and name ${tenant.name}`);
|
||||
throwError(`Wrong configuration. Another tenant has been created with id ${tenant.id} and name ${tenant.name}`);
|
||||
return false;
|
||||
const errorMessage = `Wrong configuration. Another tenant has been created with id ${tenant.id} and name ${tenant.name}`;
|
||||
logger.error(errorMessage);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+31
-12
@@ -18,14 +18,12 @@
|
||||
*/
|
||||
|
||||
import { argv, exit } from 'node:process';
|
||||
import { parseArgs } from 'node:util';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as checker from 'license-checker';
|
||||
import * as licenseList from 'spdx-license-list';
|
||||
import * as ejs from 'ejs';
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
interface LicensesCommandArgs {
|
||||
package?: string;
|
||||
@@ -103,19 +101,40 @@ function getPackageFile(packagePath: string): PackageInfo {
|
||||
* @returns void function
|
||||
*/
|
||||
export default function main(_args: string[], workingDir: string) {
|
||||
program
|
||||
.description('Generate a licences report')
|
||||
.usage('licenses [options]')
|
||||
.option('-p, --package <path>', 'Path to package file (default: package.json in working directory)')
|
||||
.option('-d, --outDir <dir>', 'Ouput directory (default: working directory)')
|
||||
.parse(argv);
|
||||
|
||||
if (argv.includes('-h') || argv.includes('--help')) {
|
||||
program.outputHelp();
|
||||
console.log(`
|
||||
Usage: licenses [options]
|
||||
|
||||
Generate a licenses report
|
||||
|
||||
Options:
|
||||
-p, --package <path> Path to package file (default: package.json in working directory)
|
||||
-d, --outDir <dir> Output directory (default: working directory)
|
||||
-h, --help Display help for command
|
||||
`);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const options: LicensesCommandArgs = program.opts();
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
package: {
|
||||
type: 'string',
|
||||
short: 'p'
|
||||
},
|
||||
outDir: {
|
||||
type: 'string',
|
||||
short: 'd'
|
||||
}
|
||||
},
|
||||
allowPositionals: true
|
||||
});
|
||||
|
||||
const options: LicensesCommandArgs = {
|
||||
package: values.package as string | undefined,
|
||||
outDir: values.outDir as string | undefined
|
||||
};
|
||||
|
||||
let packagePath = path.resolve(workingDir, 'package.json');
|
||||
|
||||
if (options.package) {
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
.storybook
|
||||
coverage
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
var rootPath = require('../../../.storybook/main');
|
||||
|
||||
module.exports = {
|
||||
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: {}
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
import { addons } from '@storybook/manager-api';
|
||||
import alfrescoTheme from '../../../.storybook/alfrescoTheme';
|
||||
|
||||
addons.setConfig({
|
||||
theme: alfrescoTheme
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
export const parameters = {
|
||||
docs: { inlineStories: true },
|
||||
controls: { expanded: true }
|
||||
};
|
||||
export const tags = ['autodocs', 'autodocs'];
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true
|
||||
|
||||
},
|
||||
|
||||
"exclude": ["../**/*.spec.ts" ],
|
||||
"include": ["../src/**/*", "*.js"]
|
||||
}
|
||||
@@ -9,7 +9,6 @@ Contains a variety of components, directives and services used throughout ADF
|
||||
- [Documentation](#documentation)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Install](#install)
|
||||
- [Storybook](#storybook)
|
||||
- [License](#license)
|
||||
|
||||
<!-- tocstop -->
|
||||
@@ -34,21 +33,6 @@ necessary configuration, see this [page](https://github.com/Alfresco/alfresco-ng
|
||||
npm install @alfresco/adf-content-services
|
||||
```
|
||||
|
||||
## Storybook
|
||||
|
||||
In case you would like to aggregate all the stories from content services library use
|
||||
|
||||
```
|
||||
nx run content-services:storybook
|
||||
```
|
||||
And navigate to `http://localhost:4400/`.
|
||||
|
||||
To create a Storybook content services library build use
|
||||
|
||||
```
|
||||
nx run content-services:build-storybook
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[Apache Version 2.0](https://github.com/Alfresco/alfresco-ng2-components/blob/master/LICENSE)
|
||||
|
||||
@@ -66,9 +66,9 @@ module.exports = function (config) {
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
dir: join(__dirname, './coverage/content-services'),
|
||||
dir: join(__dirname, '../../coverage/content-services'),
|
||||
subdir: '.',
|
||||
reporters: [{ type: 'html' }, { type: 'text-summary' }],
|
||||
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
|
||||
check: {
|
||||
global: {
|
||||
statements: 75,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-content-services",
|
||||
"description": "Alfresco ADF content services",
|
||||
"version": "8.1.1",
|
||||
"version": "8.3.0",
|
||||
"author": "Hyland Software, Inc. and its affiliates",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,9 +21,9 @@
|
||||
"@angular/platform-browser": ">=14.1.3",
|
||||
"@angular/platform-browser-dynamic": ">=14.1.3",
|
||||
"@angular/router": ">=14.1.3",
|
||||
"@alfresco/js-api": ">=9.1.1",
|
||||
"@alfresco/js-api": ">=9.2.1",
|
||||
"@ngx-translate/core": ">=16.0.0",
|
||||
"@alfresco/adf-core": ">=8.1.1"
|
||||
"@alfresco/adf-core": ">=8.2.1"
|
||||
},
|
||||
"keywords": [
|
||||
"content-services",
|
||||
|
||||
@@ -38,48 +38,12 @@
|
||||
"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": ["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": ["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"
|
||||
"command": "stylelint lib/content-services/**/*.scss --config stylelint-config.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
</mat-panel-title>
|
||||
<mat-panel-description
|
||||
class="adf-accordion-aspect-list-expansion-panel-header-description"
|
||||
aria-hidden="true"
|
||||
[id]="'aspect-list-'+colIndex+'-title'"
|
||||
[title]="getTitle(aspect)">
|
||||
{{getTitle(aspect)}}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
[tabindex]="hasPreviousNodes() ? 0 : -1"
|
||||
class="adf-dropdown-breadcrumb-trigger"
|
||||
(click)="open()"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate"
|
||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.DROPDOWN' | translate:{ folderName: currentNode?.name }"
|
||||
[attr.aria-haspopup]="hasPreviousNodes() ? 'true' : null"
|
||||
[attr.aria-expanded]="dropdown?.panelOpen || false"
|
||||
data-automation-id="dropdown-breadcrumb-trigger">
|
||||
<mat-icon class="adf-dropdown-breadcrumb-icon" [class.adf-isRoot]="!hasPreviousNodes()">folder</mat-icon>
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { SavedSearch } from './saved-search.interface';
|
||||
|
||||
/**
|
||||
* Contract that describes the public API for saved searches strategy.
|
||||
* Implemented by both the new and legacy SavedSearches services so callers
|
||||
* can depend on the same shape.
|
||||
*/
|
||||
export interface SavedSearchStrategy {
|
||||
savedSearches$: Observable<SavedSearch[]>;
|
||||
|
||||
init(): void;
|
||||
|
||||
/**
|
||||
* Gets a list of saved searches by user.
|
||||
*
|
||||
* @returns SavedSearch list containing user saved searches
|
||||
*/
|
||||
getSavedSearches(): Observable<SavedSearch[]>;
|
||||
|
||||
/**
|
||||
* Saves a new search into state and updates state. If there are less than 5 searches,
|
||||
* it will be pushed on first place, if more it will be pushed to 6th place.
|
||||
*
|
||||
* @param newSaveSearch object { name: string, description: string, encodedUrl: string }
|
||||
* @returns NodeEntry
|
||||
*/
|
||||
saveSearch(newSaveSearch: Pick<SavedSearch, 'name' | 'description' | 'encodedUrl'>): Observable<NodeEntry>;
|
||||
|
||||
/**
|
||||
* Replace Save Search with new one and also updates the state.
|
||||
*
|
||||
* @param updatedSavedSearch - updated Save Search
|
||||
* @returns NodeEntry
|
||||
*/
|
||||
editSavedSearch(updatedSavedSearch: SavedSearch): Observable<NodeEntry>;
|
||||
|
||||
/**
|
||||
* Deletes Save Search and update state.
|
||||
*
|
||||
* @param deletedSavedSearch - Save Search to delete
|
||||
* @returns NodeEntry
|
||||
*/
|
||||
deleteSavedSearch(deletedSavedSearch: SavedSearch): Observable<NodeEntry>;
|
||||
|
||||
/**
|
||||
* Reorders saved search place
|
||||
*
|
||||
* @param previousIndex - previous index of saved search
|
||||
* @param currentIndex - new index of saved search
|
||||
*/
|
||||
changeOrder(previousIndex: number, currentIndex: number): void;
|
||||
}
|
||||
@@ -25,6 +25,8 @@ export * from './services/discovery-api.service';
|
||||
export * from './services/people-content.service';
|
||||
export * from './services/content.service';
|
||||
export * from './services/saved-searches.service';
|
||||
export * from './services/saved-searches-legacy.service';
|
||||
export * from './services/saved-searches-base.service';
|
||||
|
||||
export * from './events/file.event';
|
||||
|
||||
@@ -38,4 +40,5 @@ export * from './models/allowable-operations.enum';
|
||||
|
||||
export * from './interfaces/search-configuration.interface';
|
||||
export * from './interfaces/saved-search.interface';
|
||||
export * from './interfaces/saved-searches-strategy.interface';
|
||||
export * from './mocks/ecm-user.service.mock';
|
||||
|
||||
@@ -38,11 +38,14 @@ export class DiscoveryApiService {
|
||||
*/
|
||||
ecmProductInfo$ = new Subject<RepositoryInfo>();
|
||||
|
||||
constructor(private authenticationService: AuthenticationService, private alfrescoApiService: AlfrescoApiService) {
|
||||
constructor(
|
||||
private readonly authenticationService: AuthenticationService,
|
||||
private readonly alfrescoApiService: AlfrescoApiService
|
||||
) {
|
||||
this.authenticationService.onLogin.subscribe(() => {
|
||||
this.alfrescoApiService.alfrescoApiInitialized
|
||||
.pipe(
|
||||
filter(() => this.authenticationService.isEcmLoggedIn()),
|
||||
filter(() => this.authenticationService.isLoggedIn()),
|
||||
take(1),
|
||||
switchMap(() => this.getEcmProductInfo())
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ import { PeopleContentQueryRequestModel, PeopleContentService } from './people-c
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { PersonPaging } from '@alfresco/js-api';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { EMPTY, of } from 'rxjs';
|
||||
import { EMPTY, firstValueFrom, of } from 'rxjs';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
import { AlfrescoApiServiceMock } from '../../mock';
|
||||
|
||||
@@ -83,14 +83,14 @@ describe('PeopleContentService', () => {
|
||||
|
||||
it('should be able to fetch person details based on id', async () => {
|
||||
spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(Promise.resolve({ entry: fakeEcmUser } as any));
|
||||
const person = await peopleContentService.getPerson('fake-id').toPromise();
|
||||
const person = await firstValueFrom(peopleContentService.getPerson('fake-id'));
|
||||
expect(person.id).toEqual('fake-id');
|
||||
expect(person.email).toEqual('fakeEcm@ecmUser.com');
|
||||
});
|
||||
|
||||
it('should be able to list people', async () => {
|
||||
spyOn(peopleContentService.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
|
||||
const response = await peopleContentService.listPeople().toPromise();
|
||||
const response = await firstValueFrom(peopleContentService.listPeople());
|
||||
const people = response.entries;
|
||||
const pagination = response.pagination;
|
||||
|
||||
@@ -112,7 +112,7 @@ describe('PeopleContentService', () => {
|
||||
};
|
||||
const expectedValue = { skipCount: 10, maxItems: 20, orderBy: ['firstName ASC'] } as any;
|
||||
|
||||
await peopleContentService.listPeople(requestQueryParams).toPromise();
|
||||
await firstValueFrom(peopleContentService.listPeople(requestQueryParams));
|
||||
|
||||
expect(listPeopleSpy).toHaveBeenCalledWith(expectedValue);
|
||||
});
|
||||
@@ -122,14 +122,14 @@ describe('PeopleContentService', () => {
|
||||
const requestQueryParams: PeopleContentQueryRequestModel = { skipCount: 10, maxItems: 20, sorting: undefined };
|
||||
const expectedValue = { skipCount: 10, maxItems: 20 };
|
||||
|
||||
await peopleContentService.listPeople(requestQueryParams).toPromise();
|
||||
await firstValueFrom(peopleContentService.listPeople(requestQueryParams));
|
||||
|
||||
expect(listPeopleSpy).toHaveBeenCalledWith(expectedValue);
|
||||
});
|
||||
|
||||
it('should be able to create new person', async () => {
|
||||
spyOn(peopleContentService.peopleApi, 'createPerson').and.returnValue(Promise.resolve({ entry: fakeEcmUser } as any));
|
||||
const newUser = await peopleContentService.createPerson(createNewPersonMock).toPromise();
|
||||
const newUser = await firstValueFrom(peopleContentService.createPerson(createNewPersonMock));
|
||||
expect(newUser.id).toEqual('fake-id');
|
||||
expect(newUser.email).toEqual('fakeEcm@ecmUser.com');
|
||||
});
|
||||
@@ -150,12 +150,12 @@ describe('PeopleContentService', () => {
|
||||
Promise.resolve({ entry: fakeEcmAdminUser } as any)
|
||||
);
|
||||
|
||||
const user = await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
const user = await firstValueFrom(peopleContentService.getCurrentUserInfo());
|
||||
expect(user.id).toEqual('fake-id');
|
||||
expect(peopleContentService.isCurrentUserAdmin()).toBe(true);
|
||||
expect(getCurrentPersonSpy.calls.count()).toEqual(1);
|
||||
|
||||
await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
await firstValueFrom(peopleContentService.getCurrentUserInfo());
|
||||
|
||||
expect(peopleContentService.isCurrentUserAdmin()).toBe(true);
|
||||
expect(getCurrentPersonSpy.calls.count()).toEqual(1);
|
||||
@@ -165,13 +165,13 @@ describe('PeopleContentService', () => {
|
||||
const getCurrentPersonSpy = spyOn(peopleContentService.peopleApi, 'getPerson').and.returnValue(
|
||||
Promise.resolve({ entry: fakeEcmAdminUser } as any)
|
||||
);
|
||||
await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
await firstValueFrom(peopleContentService.getCurrentUserInfo());
|
||||
|
||||
getCurrentPersonSpy.and.returnValue(Promise.resolve({ entry: fakeEcmUser2 } as any));
|
||||
await peopleContentService.getPerson('fake-id').toPromise();
|
||||
await firstValueFrom(peopleContentService.getPerson('fake-id'));
|
||||
|
||||
expect(getCurrentPersonSpy.calls.count()).toEqual(2);
|
||||
const currentUser = await peopleContentService.getCurrentUserInfo().toPromise();
|
||||
const currentUser = await firstValueFrom(peopleContentService.getCurrentUserInfo());
|
||||
expect(peopleContentService.isCurrentUserAdmin()).toBe(true);
|
||||
expect(currentUser.id).toEqual(fakeEcmAdminUser.id);
|
||||
expect(currentUser.id).not.toEqual(fakeEcmUser2.id);
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
import { AlfrescoApiServiceMock } from '../../mock';
|
||||
import { MockSavedSearchesService } from '../../mock/saved-searches-derived.mock';
|
||||
import { SavedSearch } from '../interfaces/saved-search.interface';
|
||||
import { Subject } from 'rxjs';
|
||||
import { AuthenticationService } from '@alfresco/adf-core';
|
||||
|
||||
describe('SavedSearchesBaseService', () => {
|
||||
let service: MockSavedSearchesService;
|
||||
|
||||
const SAVED_SEARCHES_CONTENT: SavedSearch[] = [
|
||||
{ name: 'Search 1', description: 'Description 1', encodedUrl: 'url1', order: 0 },
|
||||
{ name: 'Search 2', description: 'Description 2', encodedUrl: 'url2', order: 1 }
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
||||
{ provide: AuthenticationService, useValue: { getUsername: () => {}, onLogin: new Subject() } },
|
||||
MockSavedSearchesService
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(MockSavedSearchesService);
|
||||
});
|
||||
|
||||
it('should emit loaded data in savedSearches$ on init', (done) => {
|
||||
service.savedSearches$.subscribe((value) => {
|
||||
expect(value).toEqual(SAVED_SEARCHES_CONTENT);
|
||||
done();
|
||||
});
|
||||
service.mockFetch(SAVED_SEARCHES_CONTENT);
|
||||
service.init();
|
||||
});
|
||||
|
||||
it('should emit updated searches with correct order if total of saved searches is less than limit (5)', (done) => {
|
||||
service.mockFetch(SAVED_SEARCHES_CONTENT);
|
||||
const newSearch = { name: 'new-search' } as SavedSearch;
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
const args = (service.updateSpy as jasmine.Spy).calls.mostRecent().args[0];
|
||||
|
||||
expect(args.length).toBe(1 + SAVED_SEARCHES_CONTENT.length);
|
||||
|
||||
expect(args[0]).toEqual({ ...newSearch, order: 0 });
|
||||
|
||||
service.savedSearches$.subscribe((savedSearches) => {
|
||||
expect(savedSearches).toEqual(args);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit updated searches with correct order if total of saved searches is more than limit (5)', (done) => {
|
||||
const moreSavedSearches = [...SAVED_SEARCHES_CONTENT, ...SAVED_SEARCHES_CONTENT, ...SAVED_SEARCHES_CONTENT];
|
||||
service.mockFetch(moreSavedSearches);
|
||||
const newSearch = { name: 'new-search' } as SavedSearch;
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
const args = (service.updateSpy as jasmine.Spy).calls.mostRecent().args[0];
|
||||
|
||||
expect(args.length).toBe(1 + moreSavedSearches.length);
|
||||
|
||||
expect(args[5]).toEqual({ ...newSearch, order: 5 });
|
||||
|
||||
service.savedSearches$.subscribe((savedSearches) => {
|
||||
expect(savedSearches).toEqual(args);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should edit a search and emit updated saved searches', (done) => {
|
||||
service.mockFetch(SAVED_SEARCHES_CONTENT);
|
||||
service.init();
|
||||
const updatedSearch = { name: 'updated-search', order: 0 } as SavedSearch;
|
||||
service.editSavedSearch(updatedSearch).subscribe(() => {
|
||||
const args = (service.updateSpy as jasmine.Spy).calls.mostRecent().args[0];
|
||||
expect(args[0]).toEqual(updatedSearch);
|
||||
|
||||
service.savedSearches$.subscribe((savedSearches) => {
|
||||
expect(savedSearches[0]).toEqual(updatedSearch);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete a search and emit updated saved searches', (done) => {
|
||||
service.mockFetch(SAVED_SEARCHES_CONTENT);
|
||||
service.init();
|
||||
const searchToDelete = { name: 'Search 1', order: 0 } as SavedSearch;
|
||||
service.deleteSavedSearch(searchToDelete).subscribe(() => {
|
||||
const args = (service.updateSpy as jasmine.Spy).calls.mostRecent().args[0];
|
||||
expect(args.find((savedSearch: SavedSearch) => savedSearch.name === 'Search 1')).toBeUndefined();
|
||||
|
||||
service.savedSearches$.subscribe((savedSearches) => {
|
||||
expect(savedSearches.length).toBe(1);
|
||||
expect(savedSearches[0].name).toBe('Search 2');
|
||||
expect(savedSearches[0].order).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should change order of saved searches and emit updated saved searches', (done) => {
|
||||
const updatedOrder: SavedSearch[] = [
|
||||
{ ...SAVED_SEARCHES_CONTENT[1], order: 0 },
|
||||
{ ...SAVED_SEARCHES_CONTENT[0], order: 1 }
|
||||
];
|
||||
service.mockFetch(SAVED_SEARCHES_CONTENT);
|
||||
service.init();
|
||||
service.changeOrder(1, 0);
|
||||
|
||||
service.savedSearches$.subscribe((savedSearches) => {
|
||||
expect(service.updateSpy).toHaveBeenCalledWith(updatedOrder);
|
||||
|
||||
expect(savedSearches.length).toBe(SAVED_SEARCHES_CONTENT.length);
|
||||
expect(savedSearches[0]).toEqual(updatedOrder[0]);
|
||||
expect(savedSearches[1]).toEqual(updatedOrder[1]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,151 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SavedSearchStrategy } from '../interfaces/saved-searches-strategy.interface';
|
||||
import { AuthenticationService } from '@alfresco/adf-core';
|
||||
import { ReplaySubject, Observable, catchError, switchMap, take, tap, throwError, map } from 'rxjs';
|
||||
import { NodeEntry, NodesApi } from '@alfresco/js-api';
|
||||
import { SavedSearch } from '../interfaces/saved-search.interface';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
|
||||
@Injectable()
|
||||
export abstract class SavedSearchesBaseService implements SavedSearchStrategy {
|
||||
private _nodesApi: NodesApi;
|
||||
|
||||
private static readonly SAVE_MODE_THRESHOLD = 5;
|
||||
|
||||
protected readonly _savedSearches$ = new ReplaySubject<SavedSearch[]>(1);
|
||||
readonly savedSearches$: Observable<SavedSearch[]> = this._savedSearches$.asObservable();
|
||||
|
||||
get nodesApi(): NodesApi {
|
||||
this._nodesApi = this._nodesApi ?? new NodesApi(this.apiService.getInstance());
|
||||
return this._nodesApi;
|
||||
}
|
||||
|
||||
protected constructor(
|
||||
protected readonly apiService: AlfrescoApiService,
|
||||
protected readonly authService: AuthenticationService
|
||||
) {}
|
||||
|
||||
protected abstract fetchAllSavedSearches(): Observable<SavedSearch[]>;
|
||||
protected abstract updateSavedSearches(searches: SavedSearch[]): Observable<NodeEntry>;
|
||||
|
||||
init(): void {
|
||||
this.fetchSavedSearches();
|
||||
}
|
||||
|
||||
getSavedSearches(): Observable<SavedSearch[]> {
|
||||
return this.fetchAllSavedSearches();
|
||||
}
|
||||
|
||||
saveSearch(newSaveSearch: Pick<SavedSearch, 'name' | 'description' | 'encodedUrl'>): Observable<NodeEntry> {
|
||||
const limit = SavedSearchesBaseService.SAVE_MODE_THRESHOLD;
|
||||
return this.fetchAllSavedSearches().pipe(
|
||||
take(1),
|
||||
switchMap((savedSearches) => {
|
||||
let updatedSavedSearches: SavedSearch[] = [];
|
||||
|
||||
if (savedSearches.length < limit) {
|
||||
updatedSavedSearches = [{ ...newSaveSearch, order: 0 }, ...savedSearches];
|
||||
} else {
|
||||
const upToLimitSearches = savedSearches.slice(0, limit);
|
||||
const restSearches = savedSearches.slice(limit);
|
||||
updatedSavedSearches = [...upToLimitSearches, { ...newSaveSearch, order: limit }, ...restSearches];
|
||||
}
|
||||
|
||||
updatedSavedSearches = updatedSavedSearches.map((search, index) => ({ ...search, order: index }));
|
||||
|
||||
return this.updateSavedSearches(updatedSavedSearches).pipe(tap(() => this._savedSearches$.next(updatedSavedSearches)));
|
||||
}),
|
||||
catchError((error) => {
|
||||
console.error('Error saving new search:', error);
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
editSavedSearch(updatedSavedSearch: SavedSearch): Observable<NodeEntry> {
|
||||
let previousSavedSearches: SavedSearch[];
|
||||
return this.savedSearches$.pipe(
|
||||
take(1),
|
||||
map((savedSearches) => {
|
||||
previousSavedSearches = [...savedSearches];
|
||||
return savedSearches.map((search) => (search.order === updatedSavedSearch.order ? updatedSavedSearch : search));
|
||||
}),
|
||||
tap((updatedSearches) => {
|
||||
this._savedSearches$.next(updatedSearches);
|
||||
}),
|
||||
switchMap((updatedSearches) => this.updateSavedSearches(updatedSearches)),
|
||||
catchError((error) => {
|
||||
this._savedSearches$.next(previousSavedSearches);
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
deleteSavedSearch(deletedSavedSearch: SavedSearch): Observable<NodeEntry> {
|
||||
let previousSavedSearchesOrder: SavedSearch[];
|
||||
return this.savedSearches$.pipe(
|
||||
take(1),
|
||||
map((savedSearches) => {
|
||||
previousSavedSearchesOrder = [...savedSearches];
|
||||
const updatedSearches = savedSearches.filter((search) => search.order !== deletedSavedSearch.order);
|
||||
return updatedSearches.map((search, index) => ({ ...search, order: index }));
|
||||
}),
|
||||
tap((updatedSearches: SavedSearch[]) => {
|
||||
this._savedSearches$.next(updatedSearches);
|
||||
}),
|
||||
switchMap((updatedSearches: SavedSearch[]) => this.updateSavedSearches(updatedSearches)),
|
||||
catchError((error) => {
|
||||
this._savedSearches$.next(previousSavedSearchesOrder);
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
changeOrder(previousIndex: number, currentIndex: number): void {
|
||||
let previousSavedSearchesOrder: SavedSearch[];
|
||||
this.savedSearches$
|
||||
.pipe(
|
||||
take(1),
|
||||
map((savedSearches) => {
|
||||
previousSavedSearchesOrder = [...savedSearches];
|
||||
const [movedSearch] = savedSearches.splice(previousIndex, 1);
|
||||
savedSearches.splice(currentIndex, 0, movedSearch);
|
||||
return savedSearches.map((search, index) => ({ ...search, order: index }));
|
||||
}),
|
||||
tap((savedSearches: SavedSearch[]) => this._savedSearches$.next(savedSearches)),
|
||||
switchMap((updatedSearches: SavedSearch[]) => this.updateSavedSearches(updatedSearches)),
|
||||
catchError((error) => {
|
||||
this._savedSearches$.next(previousSavedSearchesOrder);
|
||||
return throwError(() => error);
|
||||
})
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
protected resetSavedSearchesStream(): void {
|
||||
this._savedSearches$.next([]);
|
||||
}
|
||||
|
||||
private fetchSavedSearches(): void {
|
||||
this.getSavedSearches()
|
||||
.pipe(take(1))
|
||||
.subscribe((searches) => this._savedSearches$.next(searches));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { AlfrescoApiServiceMock } from '../../mock';
|
||||
import { AuthenticationService } from '@alfresco/adf-core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { SavedSearchesLegacyService } from './saved-searches-legacy.service';
|
||||
|
||||
describe('SavedSearchesLegacyService', () => {
|
||||
let service: SavedSearchesLegacyService;
|
||||
let authService: AuthenticationService;
|
||||
let testUserName: string;
|
||||
let getNodeContentSpy: jasmine.Spy<(nodeId: string) => Promise<Blob>>;
|
||||
|
||||
const testNodeId = 'test-node-id';
|
||||
const SAVED_SEARCHES_NODE_ID = 'saved-searches-node-id__';
|
||||
const SAVED_SEARCHES_CONTENT = JSON.stringify([
|
||||
{ name: 'Search 1', description: 'Description 1', encodedUrl: 'url1', order: 0 },
|
||||
{ name: 'Search 2', description: 'Description 2', encodedUrl: 'url2', order: 1 }
|
||||
]);
|
||||
|
||||
/**
|
||||
* Creates a stub with Promise returning a Blob
|
||||
*
|
||||
* @returns Promise with Blob
|
||||
*/
|
||||
function createBlob(): Promise<Blob> {
|
||||
return Promise.resolve(new Blob([SAVED_SEARCHES_CONTENT]));
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
testUserName = 'test-user';
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
||||
{ provide: AuthenticationService, useValue: { getUsername: () => {}, onLogin: new Subject() } },
|
||||
SavedSearchesLegacyService
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(SavedSearchesLegacyService);
|
||||
authService = TestBed.inject(AuthenticationService);
|
||||
spyOn(service.nodesApi, 'getNode').and.callFake(() => Promise.resolve({ entry: { id: testNodeId } } as NodeEntry));
|
||||
spyOn(service.nodesApi, 'createNode').and.callFake(() => Promise.resolve({ entry: { id: 'new-node-id' } }));
|
||||
spyOn(service.nodesApi, 'updateNodeContent').and.callFake(() => Promise.resolve({ entry: {} } as NodeEntry));
|
||||
getNodeContentSpy = spyOn(service.nodesApi, 'getNodeContent').and.callFake(() => createBlob());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
localStorage.removeItem(SAVED_SEARCHES_NODE_ID + testUserName);
|
||||
});
|
||||
|
||||
it('should retrieve saved searches from the config.json file', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => testNodeId);
|
||||
service.init();
|
||||
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith(SAVED_SEARCHES_NODE_ID + testUserName);
|
||||
expect(getNodeContentSpy).toHaveBeenCalledWith(testNodeId);
|
||||
expect(searches.length).toBe(2);
|
||||
expect(searches[0].name).toBe('Search 1');
|
||||
expect(searches[1].name).toBe('Search 2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should create config.json file if it does not exist', (done) => {
|
||||
const error: Error = { name: 'test', message: '{ "error": { "statusCode": 404 } }' };
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
service.nodesApi.getNode = jasmine.createSpy().and.returnValue(Promise.reject(error));
|
||||
getNodeContentSpy.and.callFake(() => Promise.resolve(new Blob([''])));
|
||||
service.init();
|
||||
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(service.nodesApi.getNode).toHaveBeenCalledWith('-my-', { relativePath: 'config.json' });
|
||||
expect(service.nodesApi.createNode).toHaveBeenCalledWith('-my-', jasmine.objectContaining({ name: 'config.json' }));
|
||||
expect(searches.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should save a new search', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
const nodeId = 'saved-searches-node-id';
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => nodeId);
|
||||
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
|
||||
service.init();
|
||||
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
expect(service.nodesApi.updateNodeContent).toHaveBeenCalledWith(nodeId, jasmine.any(String));
|
||||
expect(service.savedSearches$).toBeDefined();
|
||||
service.savedSearches$.subscribe((searches) => {
|
||||
expect(searches.length).toBe(3);
|
||||
expect(searches[2].name).toBe('Search 2');
|
||||
expect(searches[2].order).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit initial saved searches on subscription', (done) => {
|
||||
const nodeId = 'saved-searches-node-id';
|
||||
spyOn(localStorage, 'getItem').and.returnValue(nodeId);
|
||||
service.init();
|
||||
|
||||
service.savedSearches$.pipe().subscribe((searches) => {
|
||||
expect(searches.length).toBe(2);
|
||||
expect(searches[0].name).toBe('Search 1');
|
||||
done();
|
||||
});
|
||||
|
||||
service.getSavedSearches().subscribe();
|
||||
});
|
||||
|
||||
it('should emit updated saved searches after saving a new search', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => testNodeId);
|
||||
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
|
||||
service.init();
|
||||
|
||||
let emissionCount = 0;
|
||||
|
||||
service.savedSearches$.subscribe((searches) => {
|
||||
emissionCount++;
|
||||
if (emissionCount === 1) {
|
||||
expect(searches.length).toBe(2);
|
||||
}
|
||||
if (emissionCount === 2) {
|
||||
expect(searches.length).toBe(3);
|
||||
expect(searches[2].name).toBe('Search 2');
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
service.saveSearch(newSearch).subscribe();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,108 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of, from, throwError } from 'rxjs';
|
||||
import { catchError, concatMap, first, map } from 'rxjs/operators';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
import { SavedSearch } from '../interfaces/saved-search.interface';
|
||||
import { AuthenticationService } from '@alfresco/adf-core';
|
||||
import { SavedSearchesBaseService } from './saved-searches-base.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SavedSearchesLegacyService extends SavedSearchesBaseService {
|
||||
private savedSearchFileNodeId: string;
|
||||
private currentUserLocalStorageKey: string;
|
||||
private createFileAttempt = false;
|
||||
|
||||
constructor(apiService: AlfrescoApiService, authService: AuthenticationService) {
|
||||
super(apiService, authService);
|
||||
}
|
||||
|
||||
protected fetchAllSavedSearches(): Observable<SavedSearch[]> {
|
||||
return this.getSavedSearchesNodeId().pipe(
|
||||
concatMap(() =>
|
||||
from(this.nodesApi.getNodeContent(this.savedSearchFileNodeId).then((content) => this.mapFileContentToSavedSearches(content))).pipe(
|
||||
catchError((error) => {
|
||||
if (!this.createFileAttempt) {
|
||||
this.createFileAttempt = true;
|
||||
localStorage.removeItem(this.getLocalStorageKey());
|
||||
return this.fetchAllSavedSearches();
|
||||
}
|
||||
return throwError(() => error);
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected updateSavedSearches(searches: SavedSearch[]): Observable<NodeEntry> {
|
||||
return from(this.nodesApi.updateNodeContent(this.savedSearchFileNodeId, JSON.stringify(searches)));
|
||||
}
|
||||
|
||||
private getSavedSearchesNodeId(): Observable<string> {
|
||||
const localStorageKey = this.getLocalStorageKey();
|
||||
if (this.currentUserLocalStorageKey && this.currentUserLocalStorageKey !== localStorageKey) {
|
||||
this.resetSavedSearchesStream();
|
||||
}
|
||||
this.currentUserLocalStorageKey = localStorageKey;
|
||||
let savedSearchesNodeId = localStorage.getItem(this.currentUserLocalStorageKey) ?? '';
|
||||
if (savedSearchesNodeId === '') {
|
||||
return from(this.nodesApi.getNode('-my-', { relativePath: 'config.json' })).pipe(
|
||||
first(),
|
||||
concatMap((configNode) => {
|
||||
savedSearchesNodeId = configNode.entry.id;
|
||||
localStorage.setItem(this.currentUserLocalStorageKey, savedSearchesNodeId);
|
||||
this.savedSearchFileNodeId = savedSearchesNodeId;
|
||||
return savedSearchesNodeId;
|
||||
}),
|
||||
catchError((error) => {
|
||||
const errorStatusCode = JSON.parse(error.message).error.statusCode;
|
||||
if (errorStatusCode === 404) {
|
||||
return this.createSavedSearchesNode('-my-').pipe(
|
||||
first(),
|
||||
map((node) => {
|
||||
localStorage.setItem(this.currentUserLocalStorageKey, node.entry.id);
|
||||
return node.entry.id;
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return throwError(() => error);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.savedSearchFileNodeId = savedSearchesNodeId;
|
||||
return of(savedSearchesNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
private createSavedSearchesNode(parentNodeId: string): Observable<NodeEntry> {
|
||||
return from(this.nodesApi.createNode(parentNodeId, { name: 'config.json', nodeType: 'cm:content' }));
|
||||
}
|
||||
|
||||
private async mapFileContentToSavedSearches(blob: Blob): Promise<Array<SavedSearch>> {
|
||||
return blob.text().then((content) => (content ? JSON.parse(content) : []));
|
||||
}
|
||||
|
||||
private getLocalStorageKey(): string {
|
||||
return `saved-searches-node-id__${this.authService.getUsername()}`;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { AlfrescoApiServiceMock } from '../../mock';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { SavedSearchesService } from './saved-searches.service';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { AuthenticationService } from '@alfresco/adf-core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@@ -48,7 +47,6 @@ describe('SavedSearchesService', () => {
|
||||
beforeEach(() => {
|
||||
testUserName = 'test-user';
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientTestingModule],
|
||||
providers: [
|
||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
||||
{ provide: AuthenticationService, useValue: { getUsername: () => {}, onLogin: new Subject() } },
|
||||
@@ -57,7 +55,6 @@ describe('SavedSearchesService', () => {
|
||||
});
|
||||
service = TestBed.inject(SavedSearchesService);
|
||||
authService = TestBed.inject(AuthenticationService);
|
||||
spyOn(service.nodesApi, 'getNode').and.callFake(() => Promise.resolve({ entry: { id: testNodeId } } as NodeEntry));
|
||||
spyOn(service.nodesApi, 'getNodeContent').and.callFake(() => createBlob());
|
||||
spyOn(service.nodesApi, 'deleteNode').and.callFake(() => Promise.resolve());
|
||||
spyOn(service.preferencesApi, 'getPreference').and.callFake(() =>
|
||||
@@ -72,117 +69,112 @@ describe('SavedSearchesService', () => {
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEY);
|
||||
});
|
||||
|
||||
it('should retrieve saved searches from the preferences API', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
service.init();
|
||||
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY);
|
||||
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
|
||||
expect(searches.length).toBe(2);
|
||||
expect(searches[0].name).toBe('Search 1');
|
||||
expect(searches[1].name).toBe('Search 2');
|
||||
done();
|
||||
describe('Saved searches retrieval and migration', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(service.nodesApi, 'getNode').and.callFake(() => Promise.resolve({ entry: { id: testNodeId } } as NodeEntry));
|
||||
});
|
||||
});
|
||||
it('should retrieve saved searches from the preferences API', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
service.init();
|
||||
|
||||
it('should automatically migrate saved searches if config.json file exists', (done) => {
|
||||
spyOn(localStorage, 'setItem');
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(service.nodesApi.getNode).toHaveBeenCalledWith('-my-', { relativePath: 'config.json' });
|
||||
expect(service.nodesApi.getNodeContent).toHaveBeenCalledWith(testNodeId);
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY, 'true');
|
||||
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', SAVED_SEARCHES_CONTENT);
|
||||
expect(service.nodesApi.deleteNode).toHaveBeenCalledWith(testNodeId, { permanent: true });
|
||||
expect(searches.length).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should save a new search', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
|
||||
service.init();
|
||||
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
|
||||
expect(service.savedSearches$).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit initial saved searches on subscription', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.returnValue('true');
|
||||
service.init();
|
||||
|
||||
service.savedSearches$.pipe().subscribe((searches) => {
|
||||
expect(searches.length).toBe(2);
|
||||
expect(searches[0].name).toBe('Search 1');
|
||||
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
|
||||
done();
|
||||
});
|
||||
|
||||
service.getSavedSearches().subscribe();
|
||||
});
|
||||
|
||||
it('should emit updated saved searches after saving a new search', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
|
||||
service.init();
|
||||
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
service.savedSearches$.subscribe((searches) => {
|
||||
expect(searches.length).toBe(3);
|
||||
expect(searches[2].name).toBe('Search 2');
|
||||
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should edit a search', (done) => {
|
||||
const updatedSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3', order: 0 };
|
||||
prepareDefaultMock();
|
||||
|
||||
service.editSavedSearch(updatedSearch).subscribe(() => {
|
||||
service.savedSearches$.subscribe((searches) => {
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY);
|
||||
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
|
||||
expect(searches.length).toBe(2);
|
||||
expect(searches[0].name).toBe('Search 3');
|
||||
expect(searches[0].order).toBe(0);
|
||||
|
||||
expect(searches[0].name).toBe('Search 1');
|
||||
expect(searches[1].name).toBe('Search 2');
|
||||
expect(searches[1].order).toBe(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should automatically migrate saved searches if config.json file exists', (done) => {
|
||||
spyOn(localStorage, 'setItem');
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(service.nodesApi.getNode).toHaveBeenCalledWith('-my-', { relativePath: 'config.json' });
|
||||
expect(service.nodesApi.getNodeContent).toHaveBeenCalledWith(testNodeId);
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY, 'true');
|
||||
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', SAVED_SEARCHES_CONTENT);
|
||||
expect(service.nodesApi.deleteNode).toHaveBeenCalledWith(testNodeId, { permanent: true });
|
||||
expect(searches.length).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should save a new search', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
|
||||
service.init();
|
||||
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
|
||||
expect(service.savedSearches$).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit initial saved searches on subscription', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.returnValue('true');
|
||||
service.init();
|
||||
|
||||
service.savedSearches$.pipe().subscribe((searches) => {
|
||||
expect(searches.length).toBe(2);
|
||||
expect(searches[0].name).toBe('Search 1');
|
||||
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
|
||||
done();
|
||||
});
|
||||
|
||||
service.getSavedSearches().subscribe();
|
||||
});
|
||||
|
||||
it('should emit updated saved searches after saving a new search', (done) => {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
|
||||
service.init();
|
||||
|
||||
service.saveSearch(newSearch).subscribe(() => {
|
||||
service.savedSearches$.subscribe((searches) => {
|
||||
expect(searches.length).toBe(3);
|
||||
expect(searches[2].name).toBe('Search 2');
|
||||
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete a search', (done) => {
|
||||
const searchToDelete = { name: 'Search 1', description: 'Description 1', encodedUrl: 'url1', order: 0 };
|
||||
prepareDefaultMock();
|
||||
describe('Saved searches error handling', () => {
|
||||
it('should fallback to preferences API if getting saved searches node ID fails', (done) => {
|
||||
spyOn(authService, 'getUsername').and.returnValue(testUserName);
|
||||
spyOn(localStorage, 'getItem').and.returnValue('');
|
||||
const error = new Error(JSON.stringify({ error: { statusCode: 500 } }));
|
||||
spyOn(service.nodesApi, 'getNode').and.returnValue(Promise.reject(error));
|
||||
|
||||
service.deleteSavedSearch(searchToDelete).subscribe(() => {
|
||||
service.savedSearches$.subscribe((searches) => {
|
||||
expect(searches.length).toBe(1);
|
||||
expect(searches[0].name).toBe('Search 2');
|
||||
expect(searches[0].order).toBe(0);
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
|
||||
expect(searches.length).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle 404 from getNode() by setting migration flag and falling back to preferences API', (done) => {
|
||||
spyOn(authService, 'getUsername').and.returnValue(testUserName);
|
||||
spyOn(localStorage, 'getItem').and.returnValue('');
|
||||
spyOn(localStorage, 'setItem');
|
||||
const notFoundError = new Error(JSON.stringify({ error: { statusCode: 404 } }));
|
||||
spyOn(service.nodesApi, 'getNode').and.returnValue(Promise.reject(notFoundError));
|
||||
|
||||
service.getSavedSearches().subscribe((searches) => {
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY, 'true');
|
||||
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
|
||||
expect(searches.length).toBe(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Prepares default mocks for service
|
||||
*/
|
||||
function prepareDefaultMock(): void {
|
||||
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
|
||||
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
|
||||
service.init();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NodesApi, NodeEntry, PreferencesApi, ContentFieldsQuery, PreferenceEntry } from '@alfresco/js-api';
|
||||
import { NodeEntry, PreferencesApi, ContentFieldsQuery, PreferenceEntry } from '@alfresco/js-api';
|
||||
import { inject, Injectable, InjectionToken } from '@angular/core';
|
||||
import { Observable, of, from, ReplaySubject, throwError } from 'rxjs';
|
||||
import { Observable, of, from, throwError } from 'rxjs';
|
||||
import { catchError, concatMap, first, map, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { SavedSearch } from '../interfaces/saved-search.interface';
|
||||
import { AuthenticationService } from '@alfresco/adf-core';
|
||||
import { SavedSearchesBaseService } from './saved-searches-base.service';
|
||||
|
||||
export interface SavedSearchesPreferencesApiService {
|
||||
getPreference: (personId: string, preferenceName: string, opts?: ContentFieldsQuery) => Promise<PreferenceEntry> | Observable<PreferenceEntry>;
|
||||
@@ -33,17 +34,11 @@ export const SAVED_SEARCHES_SERVICE_PREFERENCES = new InjectionToken<SavedSearch
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SavedSearchesService {
|
||||
export class SavedSearchesService extends SavedSearchesBaseService {
|
||||
private savedSearchFileNodeId: string;
|
||||
private _nodesApi: NodesApi;
|
||||
private _preferencesApi: SavedSearchesPreferencesApiService;
|
||||
private preferencesService = inject(SAVED_SEARCHES_SERVICE_PREFERENCES, { optional: true });
|
||||
|
||||
get nodesApi(): NodesApi {
|
||||
this._nodesApi = this._nodesApi ?? new NodesApi(this.apiService.getInstance());
|
||||
return this._nodesApi;
|
||||
}
|
||||
|
||||
get preferencesApi(): SavedSearchesPreferencesApiService {
|
||||
if (this.preferencesService) {
|
||||
this._preferencesApi = this.preferencesService;
|
||||
@@ -54,178 +49,35 @@ export class SavedSearchesService {
|
||||
return this._preferencesApi;
|
||||
}
|
||||
|
||||
readonly savedSearches$ = new ReplaySubject<SavedSearch[]>(1);
|
||||
|
||||
constructor(private readonly apiService: AlfrescoApiService, private readonly authService: AuthenticationService) {}
|
||||
|
||||
init(): void {
|
||||
this.fetchSavedSearches();
|
||||
constructor(apiService: AlfrescoApiService, authService: AuthenticationService) {
|
||||
super(apiService, authService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of saved searches by user.
|
||||
*
|
||||
* @returns SavedSearch list containing user saved searches
|
||||
*/
|
||||
getSavedSearches(): Observable<SavedSearch[]> {
|
||||
protected fetchAllSavedSearches(): Observable<SavedSearch[]> {
|
||||
const savedSearchesMigrated = localStorage.getItem(this.getLocalStorageKey()) ?? '';
|
||||
if (savedSearchesMigrated === 'true') {
|
||||
return from(this.preferencesApi.getPreference('-me-', 'saved-searches')).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value)),
|
||||
catchError(() => of([]))
|
||||
);
|
||||
return this.getSavedSearchesFromPreferenceApi();
|
||||
} else {
|
||||
return this.getSavedSearchesNodeId().pipe(
|
||||
take(1),
|
||||
concatMap(() => {
|
||||
switchMap(() => {
|
||||
if (this.savedSearchFileNodeId !== '') {
|
||||
return this.migrateSavedSearches();
|
||||
} else {
|
||||
return from(this.preferencesApi.getPreference('-me-', 'saved-searches')).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value)),
|
||||
catchError(() => of([]))
|
||||
);
|
||||
return this.getSavedSearchesFromPreferenceApi();
|
||||
}
|
||||
})
|
||||
}),
|
||||
catchError(() => this.getSavedSearchesFromPreferenceApi())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a new search into state and updates state. If there are less than 5 searches,
|
||||
* it will be pushed on first place, if more it will be pushed to 6th place.
|
||||
*
|
||||
* @param newSaveSearch object { name: string, description: string, encodedUrl: string }
|
||||
* @returns NodeEntry
|
||||
*/
|
||||
saveSearch(newSaveSearch: Pick<SavedSearch, 'name' | 'description' | 'encodedUrl'>): Observable<NodeEntry> {
|
||||
return this.getSavedSearches().pipe(
|
||||
take(1),
|
||||
switchMap((savedSearches: SavedSearch[]) => {
|
||||
let updatedSavedSearches: SavedSearch[] = [];
|
||||
|
||||
if (savedSearches.length < 5) {
|
||||
updatedSavedSearches = [{ ...newSaveSearch, order: 0 }, ...savedSearches];
|
||||
} else {
|
||||
const firstFiveSearches = savedSearches.slice(0, 5);
|
||||
const restOfSearches = savedSearches.slice(5);
|
||||
|
||||
updatedSavedSearches = [...firstFiveSearches, { ...newSaveSearch, order: 5 }, ...restOfSearches];
|
||||
}
|
||||
|
||||
updatedSavedSearches = updatedSavedSearches.map((search, index) => ({
|
||||
...search,
|
||||
order: index
|
||||
}));
|
||||
|
||||
return from(this.preferencesApi.updatePreference('-me-', 'saved-searches', JSON.stringify(updatedSavedSearches))).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value)),
|
||||
tap(() => this.savedSearches$.next(updatedSavedSearches))
|
||||
);
|
||||
}),
|
||||
catchError((error) => {
|
||||
console.error('Error saving new search:', error);
|
||||
return throwError(() => error);
|
||||
})
|
||||
protected updateSavedSearches(updatedSavedSearches: SavedSearch[]): Observable<NodeEntry> {
|
||||
return from(this.preferencesApi.updatePreference('-me-', 'saved-searches', JSON.stringify(updatedSavedSearches))).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace Save Search with new one and also updates the state.
|
||||
*
|
||||
* @param updatedSavedSearch - updated Save Search
|
||||
* @returns NodeEntry
|
||||
*/
|
||||
editSavedSearch(updatedSavedSearch: SavedSearch): Observable<NodeEntry> {
|
||||
let previousSavedSearches: SavedSearch[];
|
||||
return this.savedSearches$.pipe(
|
||||
take(1),
|
||||
map((savedSearches: SavedSearch[]) => {
|
||||
previousSavedSearches = [...savedSearches];
|
||||
return savedSearches.map((search) => (search.order === updatedSavedSearch.order ? updatedSavedSearch : search));
|
||||
}),
|
||||
tap((updatedSearches: SavedSearch[]) => {
|
||||
this.savedSearches$.next(updatedSearches);
|
||||
}),
|
||||
switchMap((updatedSearches: SavedSearch[]) =>
|
||||
from(this.preferencesApi.updatePreference('-me-', 'saved-searches', JSON.stringify(updatedSearches))).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value))
|
||||
)
|
||||
),
|
||||
catchError((error) => {
|
||||
this.savedSearches$.next(previousSavedSearches);
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Save Search and update state.
|
||||
*
|
||||
* @param deletedSavedSearch - Save Search to delete
|
||||
* @returns NodeEntry
|
||||
*/
|
||||
deleteSavedSearch(deletedSavedSearch: SavedSearch): Observable<NodeEntry> {
|
||||
let previousSavedSearchesOrder: SavedSearch[];
|
||||
return this.savedSearches$.pipe(
|
||||
take(1),
|
||||
map((savedSearches: SavedSearch[]) => {
|
||||
previousSavedSearchesOrder = [...savedSearches];
|
||||
const updatedSearches = savedSearches.filter((search) => search.order !== deletedSavedSearch.order);
|
||||
return updatedSearches.map((search, index) => ({
|
||||
...search,
|
||||
order: index
|
||||
}));
|
||||
}),
|
||||
tap((updatedSearches: SavedSearch[]) => {
|
||||
this.savedSearches$.next(updatedSearches);
|
||||
}),
|
||||
switchMap((updatedSearches: SavedSearch[]) =>
|
||||
from(this.preferencesApi.updatePreference('-me-', 'saved-searches', JSON.stringify(updatedSearches))).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value))
|
||||
)
|
||||
),
|
||||
catchError((error) => {
|
||||
this.savedSearches$.next(previousSavedSearchesOrder);
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders saved search place
|
||||
*
|
||||
* @param previousIndex - previous index of saved search
|
||||
* @param currentIndex - new index of saved search
|
||||
*/
|
||||
changeOrder(previousIndex: number, currentIndex: number): void {
|
||||
let previousSavedSearchesOrder: SavedSearch[];
|
||||
this.savedSearches$
|
||||
.pipe(
|
||||
take(1),
|
||||
map((savedSearches: SavedSearch[]) => {
|
||||
previousSavedSearchesOrder = [...savedSearches];
|
||||
const [movedSearch] = savedSearches.splice(previousIndex, 1);
|
||||
savedSearches.splice(currentIndex, 0, movedSearch);
|
||||
return savedSearches.map((search, index) => ({
|
||||
...search,
|
||||
order: index
|
||||
}));
|
||||
}),
|
||||
tap((savedSearches: SavedSearch[]) => this.savedSearches$.next(savedSearches)),
|
||||
switchMap((updatedSearches: SavedSearch[]) =>
|
||||
from(this.preferencesApi.updatePreference('-me-', 'saved-searches', JSON.stringify(updatedSearches))).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value))
|
||||
)
|
||||
),
|
||||
catchError((error) => {
|
||||
this.savedSearches$.next(previousSavedSearchesOrder);
|
||||
return throwError(() => error);
|
||||
})
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private getSavedSearchesNodeId(): Observable<string> {
|
||||
return from(this.nodesApi.getNode('-my-', { relativePath: 'config.json' })).pipe(
|
||||
first(),
|
||||
@@ -237,10 +89,8 @@ export class SavedSearchesService {
|
||||
const errorStatusCode = JSON.parse(error.message).error.statusCode;
|
||||
if (errorStatusCode === 404) {
|
||||
localStorage.setItem(this.getLocalStorageKey(), 'true');
|
||||
return '';
|
||||
} else {
|
||||
return throwError(() => error);
|
||||
}
|
||||
return throwError(() => error);
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -256,12 +106,6 @@ export class SavedSearchesService {
|
||||
return `saved-searches-${this.authService.getUsername()}-migrated`;
|
||||
}
|
||||
|
||||
private fetchSavedSearches(): void {
|
||||
this.getSavedSearches()
|
||||
.pipe(take(1))
|
||||
.subscribe((searches) => this.savedSearches$.next(searches));
|
||||
}
|
||||
|
||||
private migrateSavedSearches(): Observable<SavedSearch[]> {
|
||||
return from(this.nodesApi.getNodeContent(this.savedSearchFileNodeId).then((content) => this.mapFileContentToSavedSearches(content))).pipe(
|
||||
tap((savedSearches) => {
|
||||
@@ -271,4 +115,11 @@ export class SavedSearchesService {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private getSavedSearchesFromPreferenceApi(): Observable<SavedSearch[]> {
|
||||
return from(this.preferencesApi.getPreference('-me-', 'saved-searches')).pipe(
|
||||
map((preference) => JSON.parse(preference.entry.value)),
|
||||
catchError(() => of([]))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -9,6 +9,7 @@
|
||||
hideToggle>
|
||||
<mat-expansion-panel-header
|
||||
class="adf-metadata-properties-header"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.SECTION' | translate: { sectionName: ('CORE.METADATA.BASIC.HEADER' | translate) }"
|
||||
[class.adf-metadata-properties-header-expanded]="currentPanel.panelTitle === DefaultPanels.PROPERTIES && currentPanel.expanded">
|
||||
<adf-content-metadata-header
|
||||
[title]="'CORE.METADATA.BASIC.HEADER'"
|
||||
@@ -18,7 +19,7 @@
|
||||
mat-icon-button
|
||||
(click)="toggleGroupEditing(DefaultPanels.PROPERTIES, $event)"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate: { sectionName: ('CORE.METADATA.BASIC.HEADER' | translate) }"
|
||||
data-automation-id="meta-data-general-info-edit"
|
||||
class="adf-edit-icon-buttons">
|
||||
<mat-icon>mode_edit</mat-icon>
|
||||
@@ -65,6 +66,7 @@
|
||||
data-automation-id="adf-content-metadata-tags-panel">
|
||||
<mat-expansion-panel-header
|
||||
class="adf-metadata-properties-header"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.SECTION' | translate: { sectionName: ('METADATA.BASIC.TAGS' | translate) }"
|
||||
[class.adf-metadata-properties-header-expanded]="currentPanel.panelTitle === DefaultPanels.TAGS && currentPanel.expanded">
|
||||
<adf-content-metadata-header [title]="'METADATA.BASIC.TAGS'" [expanded]="currentPanel.panelTitle === DefaultPanels.TAGS && currentPanel.expanded">
|
||||
<button
|
||||
@@ -72,7 +74,7 @@
|
||||
mat-icon-button
|
||||
(click)="toggleGroupEditing(DefaultPanels.TAGS, $event)"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate: { sectionName: ('METADATA.BASIC.TAGS' | translate) }"
|
||||
data-automation-id="showing-tag-input-button"
|
||||
class="adf-edit-icon-buttons">
|
||||
<mat-icon>mode_edit</mat-icon>
|
||||
@@ -126,6 +128,7 @@
|
||||
data-automation-id="adf-content-metadata-categories-panel">
|
||||
<mat-expansion-panel-header
|
||||
class="adf-metadata-properties-header"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.SECTION' | translate: { sectionName: ('CATEGORIES_MANAGEMENT.CATEGORIES_TITLE' | translate) }"
|
||||
[class.adf-metadata-properties-header-expanded]="currentPanel.panelTitle === DefaultPanels.CATEGORIES && currentPanel.expanded">
|
||||
<adf-content-metadata-header
|
||||
[title]="'CATEGORIES_MANAGEMENT.CATEGORIES_TITLE'"
|
||||
@@ -135,7 +138,7 @@
|
||||
mat-icon-button
|
||||
(click)="toggleGroupEditing(DefaultPanels.CATEGORIES, $event)"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate: { sectionName: ('CATEGORIES_MANAGEMENT.CATEGORIES_TITLE' | translate) }"
|
||||
data-automation-id="meta-data-categories-edit"
|
||||
class="adf-categories-button adf-edit-icon-buttons">
|
||||
<mat-icon>mode_edit</mat-icon>
|
||||
@@ -188,6 +191,7 @@
|
||||
hideToggle>
|
||||
<mat-expansion-panel-header
|
||||
class="adf-metadata-properties-header"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.SECTION' | translate: { sectionName: (customPanel.panelTitle | translate) }"
|
||||
[class.adf-metadata-properties-header-expanded]="currentPanel.panelTitle === customPanel.panelTitle && currentPanel.expanded">
|
||||
<adf-content-metadata-header
|
||||
class="adf-metadata-custom-panel-title"
|
||||
@@ -208,13 +212,14 @@
|
||||
hideToggle>
|
||||
<mat-expansion-panel-header
|
||||
class="adf-metadata-properties-header"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.SECTION' | translate: { sectionName: (group.title | translate) }"
|
||||
[class.adf-metadata-properties-header-expanded]="currentPanel.panelTitle === group.title && currentPanel.expanded">
|
||||
<adf-content-metadata-header [title]="group.title" [expanded]="currentPanel.panelTitle === group.title && currentPanel.expanded">
|
||||
<button
|
||||
*ngIf="group.editable && !this.readOnly && !isPanelEditing(group.title)"
|
||||
mat-icon-button
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate"
|
||||
[attr.aria-label]="'CORE.METADATA.ACCESSIBILITY.EDIT' | translate: { sectionName: (group.title | translate) }"
|
||||
data-automation-id="meta-data-card-toggle-edit"
|
||||
class="adf-edit-icon-buttons"
|
||||
(click)="toggleGroupEditing(group.title, $event)">
|
||||
|
||||
+8
-8
@@ -32,7 +32,7 @@ import { MatChipHarness } from '@angular/material/chips/testing';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatExpansionPanel } from '@angular/material/expansion';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { EMPTY, of, throwError } from 'rxjs';
|
||||
import { EMPTY, firstValueFrom, of, throwError } from 'rxjs';
|
||||
import { CategoriesManagementComponent, CategoriesManagementMode } from '../../../category';
|
||||
import { TagsCreatorComponent, TagsCreatorMode } from '../../../tag';
|
||||
import { ContentTestingModule } from '../../../testing/content.testing.module';
|
||||
@@ -1144,7 +1144,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const verProp = queryDom('Versionable');
|
||||
@@ -1164,7 +1164,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const verProps = fixture.debugElement.queryAll(By.css('[data-automation-id="adf-metadata-group-Versionable"]'));
|
||||
@@ -1184,7 +1184,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const verProp = queryDom('Versionable');
|
||||
@@ -1205,7 +1205,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const verProp = queryDom('Versionable');
|
||||
@@ -1225,7 +1225,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const verProp = queryDom('Versionable');
|
||||
@@ -1249,7 +1249,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const exifProp = queryDom('Exif');
|
||||
@@ -1283,7 +1283,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
fixture.detectChanges();
|
||||
|
||||
await component.groupedProperties$.toPromise();
|
||||
await firstValueFrom(component.groupedProperties$);
|
||||
fixture.detectChanges();
|
||||
|
||||
const exifProps = fixture.debugElement.queryAll(By.css('[data-automation-id="adf-metadata-group-Exif"]'));
|
||||
|
||||
+10
-10
@@ -18,7 +18,7 @@
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
import { ClassesApi, Node } from '@alfresco/js-api';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { firstValueFrom, of } from 'rxjs';
|
||||
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||
import { OrganisedPropertyGroup } from '../interfaces/content-metadata.interfaces';
|
||||
import { PropertyGroup } from '../interfaces/property-group.interface';
|
||||
@@ -253,7 +253,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(exifResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeNode));
|
||||
|
||||
expect(groupedProperties.length).toEqual(1);
|
||||
expect(groupedProperties[0].title).toEqual('Exif');
|
||||
@@ -267,7 +267,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(exifResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeNode));
|
||||
|
||||
expect(groupedProperties.length).toEqual(1);
|
||||
expect(groupedProperties[0].title).toEqual('Exif');
|
||||
@@ -284,7 +284,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(verResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeContentNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeContentNode));
|
||||
|
||||
expect(groupedProperties.length).toEqual(1);
|
||||
expect(groupedProperties[0].title).toEqual('Versionable');
|
||||
@@ -301,7 +301,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(verResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeContentNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeContentNode));
|
||||
|
||||
expect(groupedProperties.length).toEqual(2);
|
||||
expect(groupedProperties[0].title).toEqual('Versionable');
|
||||
@@ -319,7 +319,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(verResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeContentNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeContentNode));
|
||||
expect(groupedProperties.length).toEqual(0);
|
||||
|
||||
expect(classesApi.getClass).toHaveBeenCalledTimes(1 + fakeContentNode.aspectNames.length);
|
||||
@@ -335,7 +335,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(verResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeContentNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeContentNode));
|
||||
expect(groupedProperties.length).toEqual(1);
|
||||
expect(groupedProperties[0].title).toEqual('Versionable');
|
||||
|
||||
@@ -351,7 +351,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(verResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeContentNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeContentNode));
|
||||
expect(groupedProperties.length).toEqual(0);
|
||||
|
||||
expect(classesApi.getClass).toHaveBeenCalledTimes(1 + fakeContentNode.aspectNames.length);
|
||||
@@ -367,7 +367,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(exifResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeNode));
|
||||
|
||||
expect(groupedProperties.length).toEqual(1);
|
||||
expect(groupedProperties[0].title).toEqual('Exif');
|
||||
@@ -387,7 +387,7 @@ describe('ContentMetaDataService', () => {
|
||||
|
||||
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve(exifResponse));
|
||||
|
||||
const groupedProperties = await service.getGroupedProperties(fakeNode).toPromise();
|
||||
const groupedProperties = await firstValueFrom(service.getGroupedProperties(fakeNode));
|
||||
|
||||
expect(groupedProperties.length).toEqual(2);
|
||||
expect(groupedProperties[0].title).toEqual('Exif');
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user