mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-16 18:13:06 +00:00
Compare commits
382
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adcf1e64a1 | ||
|
|
22956e4671 | ||
|
|
699f45e486 | ||
|
|
416f04d6bd | ||
|
|
5123e80bd9 | ||
|
|
283a0ab18a | ||
|
|
bab668033e | ||
|
|
1a50dad132 | ||
|
|
d0f9c3d5a4 | ||
|
|
2808988171 | ||
|
|
bd7f393db9 | ||
|
|
d2d6696c05 | ||
|
|
7546aa91a3 | ||
|
|
74d67c39a0 | ||
|
|
20c20f2749 | ||
|
|
2c3020c7fc | ||
|
|
100d348f5e | ||
|
|
b498d5744c | ||
|
|
80eef35e1d | ||
|
|
49a3f1e104 | ||
|
|
0beaa18452 | ||
|
|
76fd461741 | ||
|
|
78697ee62a | ||
|
|
43c5bc17fb | ||
|
|
cda20e0386 | ||
|
|
8f5099e822 | ||
|
|
5dd709ed58 | ||
|
|
9d353bf271 | ||
|
|
633702860f | ||
|
|
bf5b3af285 | ||
|
|
caeaa74704 | ||
|
|
7bf0939a49 | ||
|
|
ec04358796 | ||
|
|
49a28b357c | ||
|
|
dd9e58ddaa | ||
|
|
c723e19b6d | ||
|
|
bb6f9b1f3d | ||
|
|
7bb219e4dd | ||
|
|
9ec31dd543 | ||
|
|
70038bea26 | ||
|
|
a445569139 | ||
|
|
5ad3dca38d | ||
|
|
fd3802f2dc | ||
|
|
a8eee9fe3a | ||
|
|
0a7fa14d0f | ||
|
|
4dde6d2a45 | ||
|
|
78661f11c5 | ||
|
|
faf9d3faac | ||
|
|
75d9845754 | ||
|
|
5c8eb21ab3 | ||
|
|
7d76d789b2 | ||
|
|
a71cc84f11 | ||
|
|
cdcfab0240 | ||
|
|
5a20501577 | ||
|
|
34acdd20cf | ||
|
|
f39b9167b8 | ||
|
|
aa2a357fb2 | ||
|
|
e52b63eaf9 | ||
|
|
f9899883dc | ||
|
|
46b2d0380b | ||
|
|
274ddb3098 | ||
|
|
f602070f1e | ||
|
|
d206d28f1c | ||
|
|
80e9e51cfa | ||
|
|
345e1e69ad | ||
|
|
a2b026ed7e | ||
|
|
e40fd2250e | ||
|
|
cfdd3f9c50 | ||
|
|
1314f0751f | ||
|
|
f4882e99be | ||
|
|
b5d2de583d | ||
|
|
70f90c65a5 | ||
|
|
e6ef0de7a8 | ||
|
|
8559d27a04 | ||
|
|
c9b2939588 | ||
|
|
b69776012f | ||
|
|
27c62f2632 | ||
|
|
b8fa940dc9 | ||
|
|
637b67da59 | ||
|
|
cefc666a09 | ||
|
|
f339647f40 | ||
|
|
a7fa68056d | ||
|
|
8280aa2f6d | ||
|
|
5553aaaefe | ||
|
|
15814380a5 | ||
|
|
4044fafc39 | ||
|
|
ece50ac32c | ||
|
|
1d163c6749 | ||
|
|
1fbd869902 | ||
|
|
165d0fc521 | ||
|
|
64d9f3a6d4 | ||
|
|
454236873e | ||
|
|
16202197f7 | ||
|
|
dbdcc3175b | ||
|
|
b1cb7060d1 | ||
|
|
fc55aa0a44 | ||
|
|
b8c115a725 | ||
|
|
9e106b006c | ||
|
|
8309d2dc55 | ||
|
|
a21908a782 | ||
|
|
e3430ae36e | ||
|
|
7bf7610cf5 | ||
|
|
57ec1ab835 | ||
|
|
1860fefd42 | ||
|
|
e5eb90f93b | ||
|
|
c9464581e8 | ||
|
|
53abaaf246 | ||
|
|
9fe4006a0d | ||
|
|
62fb51e910 | ||
|
|
b7783d2259 | ||
|
|
410490158f | ||
|
|
57bf066164 | ||
|
|
9cdacf3ebf | ||
|
|
8821980913 | ||
|
|
a73b100fae | ||
|
|
2649cdea2d | ||
|
|
3a543d8a0a | ||
|
|
3fc59b2358 | ||
|
|
d7487e30bd | ||
|
|
b6d292df2b | ||
|
|
992f4779fc | ||
|
|
337b82e988 | ||
|
|
0faa2e1a56 | ||
|
|
d6262eafc6 | ||
|
|
bba9a0afe2 | ||
|
|
d3ad66d25b | ||
|
|
b49513e9c2 | ||
|
|
aa2de3bde6 | ||
|
|
d1d06a68bc | ||
|
|
a394222c54 | ||
|
|
0a6da1ba13 | ||
|
|
7853121080 | ||
|
|
d3ac5362ba | ||
|
|
ddb8adc0e4 | ||
|
|
85005c9c1c | ||
|
|
67b4486b44 | ||
|
|
a4f4f5eb47 | ||
|
|
02009108e9 | ||
|
|
e7c5e5371b | ||
|
|
5a032945bc | ||
|
|
407c6c1829 | ||
|
|
e3fc03c58d | ||
|
|
510a813ed2 | ||
|
|
7864f1a8e0 | ||
|
|
c09edd71ff | ||
|
|
64826c3a99 | ||
|
|
423c646bac | ||
|
|
d1bda4f898 | ||
|
|
03f04bf118 | ||
|
|
0dd3e454f5 | ||
|
|
025e3cf636 | ||
|
|
07455c4217 | ||
|
|
9beeaeed8d | ||
|
|
a86f0790da | ||
|
|
86e8fb75d0 | ||
|
|
af95723f30 | ||
|
|
d70ae599c7 | ||
|
|
e2ae224924 | ||
|
|
07c6a4d923 | ||
|
|
6fc8dda887 | ||
|
|
b550712160 | ||
|
|
969bb4455e | ||
|
|
48eb258311 | ||
|
|
32850a0ce8 | ||
|
|
8a6bcac29e | ||
|
|
7a70ae8eb6 | ||
|
|
1ee94fcb2c | ||
|
|
c1a6c28a29 | ||
|
|
747da93b0f | ||
|
|
714434f755 | ||
|
|
17bedfd940 | ||
|
|
8ce0561ef5 | ||
|
|
0e063beb40 | ||
|
|
6b15cd05c7 | ||
|
|
868a9204f4 | ||
|
|
bddf2d9cf0 | ||
|
|
69a9dc1386 | ||
|
|
70a6f42649 | ||
|
|
74252797b7 | ||
|
|
79871455f4 | ||
|
|
2cd51b4789 | ||
|
|
a3e34d35a4 | ||
|
|
d7a8f03dbf | ||
|
|
7b32eb49d8 | ||
|
|
a3e13da3a4 | ||
|
|
565db01819 | ||
|
|
f321b74be0 | ||
|
|
28fe6d3a76 | ||
|
|
7b29d56272 | ||
|
|
7953eee9b0 | ||
|
|
c6d577a6c3 | ||
|
|
bda12d5105 | ||
|
|
641cfd8cf4 | ||
|
|
8cdc05d433 | ||
|
|
4751563d3b | ||
|
|
d526d31425 | ||
|
|
430bd08fa9 | ||
|
|
23eca963b7 | ||
|
|
31a85fe5df | ||
|
|
9d03588f07 | ||
|
|
e97439f09b | ||
|
|
bdd4b687c6 | ||
|
|
30a15dec46 | ||
|
|
f1895f725d | ||
|
|
74953b7098 | ||
|
|
d88be7122b | ||
|
|
56d5593b46 | ||
|
|
d25d8044ef | ||
|
|
e0b4113c8c | ||
|
|
171087d11e | ||
|
|
d9811b6bd9 | ||
|
|
46989ae081 | ||
|
|
22d8d00e2e | ||
|
|
a50dfd050d | ||
|
|
e57910f5c3 | ||
|
|
3bea95b8e0 | ||
|
|
adce4cabf5 | ||
|
|
ebf742c54b | ||
|
|
759d206302 | ||
|
|
a865372819 | ||
|
|
6c5a205d3e | ||
|
|
983c8a1b5f | ||
|
|
2bab1560be | ||
|
|
5c6dcb8f3c | ||
|
|
f3cf57c9d8 | ||
|
|
2bab587876 | ||
|
|
e325ad3871 | ||
|
|
a8ae3d3b4e | ||
|
|
bc41c33ba8 | ||
|
|
83e80906d8 | ||
|
|
ef5944a09c | ||
|
|
2e668fc7b2 | ||
|
|
f44e4e90e8 | ||
|
|
89851a625a | ||
|
|
68b1b98c83 | ||
|
|
c428f547bc | ||
|
|
bea42ac52a | ||
|
|
ba9515b017 | ||
|
|
93c2d1bbc4 | ||
|
|
62dd64c695 | ||
|
|
74eb779df2 | ||
|
|
3e44f2d358 | ||
|
|
05e5f120b8 | ||
|
|
a27575ca84 | ||
|
|
3cb734d288 | ||
|
|
45f80bd106 | ||
|
|
1f1816130a | ||
|
|
dc8e6a9fb3 | ||
|
|
0b7b89e5d8 | ||
|
|
a15b1f4c85 | ||
|
|
294e6254c2 | ||
|
|
ec312d49ab | ||
|
|
c216cea81b | ||
|
|
9f641a18c3 | ||
|
|
d239d1f0ec | ||
|
|
ad966af662 | ||
|
|
8b23b61d9c | ||
|
|
dd66ecc72a | ||
|
|
3b14351389 | ||
|
|
3535fa3d89 | ||
|
|
68d174c3e6 | ||
|
|
4cc56421ee | ||
|
|
1061e762f8 | ||
|
|
358367bcb1 | ||
|
|
52ad50fbc7 | ||
|
|
2a0d5df2d5 | ||
|
|
7405b2d2e4 | ||
|
|
7a3650e6a7 | ||
|
|
de34579038 | ||
|
|
2f8d8c2007 | ||
|
|
303a9efb3e | ||
|
|
9be5eae00c | ||
|
|
fad9192af7 | ||
|
|
9dfdecaf04 | ||
|
|
7f8b49cb07 | ||
|
|
f1f2000db8 | ||
|
|
512c151249 | ||
|
|
5935fbfb5b | ||
|
|
57b8fe7174 | ||
|
|
cfb9a505e4 | ||
|
|
e5471c8741 | ||
|
|
1baddb2b37 | ||
|
|
e48950b200 | ||
|
|
4581f714d7 | ||
|
|
7b574fc0d0 | ||
|
|
bc30b74213 | ||
|
|
3f542d99ba | ||
|
|
f8fa996b04 | ||
|
|
93fc7c166c | ||
|
|
b6a6c1bc86 | ||
|
|
5850dafca7 | ||
|
|
fafa5d6c41 | ||
|
|
1f49af4c8f | ||
|
|
84affe9f37 | ||
|
|
7004f54821 | ||
|
|
732aae97d8 | ||
|
|
766b66d509 | ||
|
|
1372bb5281 | ||
|
|
84d2c50e39 | ||
|
|
d74029dacf | ||
|
|
314761ed4a | ||
|
|
40b15689d5 | ||
|
|
d274d62d73 | ||
|
|
1fa683e2a9 | ||
|
|
823a147656 | ||
|
|
8b050481ab | ||
|
|
faa22f2fde | ||
|
|
4df5b9282c | ||
|
|
30afd2d863 | ||
|
|
10ae06b755 | ||
|
|
0b805f3e9b | ||
|
|
4d99262ba3 | ||
|
|
14899931d2 | ||
|
|
012b1b4495 | ||
|
|
6df7563d29 | ||
|
|
a6123f2d26 | ||
|
|
20dc673569 | ||
|
|
21819b64f6 | ||
|
|
518f385d3a | ||
|
|
283b996063 | ||
|
|
5df193b255 | ||
|
|
dcf133b37e | ||
|
|
31bafd718e | ||
|
|
0c50bfd4e3 | ||
|
|
e859923541 | ||
|
|
6ff7ce4add | ||
|
|
6db0fb84c7 | ||
|
|
302b3e18ec | ||
|
|
84de7c7765 | ||
|
|
c770c9a896 | ||
|
|
b74ffc81f4 | ||
|
|
9d81ecbbaa | ||
|
|
d8a7ea4f80 | ||
|
|
271bcb9a71 | ||
|
|
5fba7d5a92 | ||
|
|
3b44f893dc | ||
|
|
5a3ea414ed | ||
|
|
0cd55fe243 | ||
|
|
3e9b5a097c | ||
|
|
ba3d9d5be4 | ||
|
|
8cda30db45 | ||
|
|
1780aa9663 | ||
|
|
3bba02264a | ||
|
|
4987bbadef | ||
|
|
9cb8b962ae | ||
|
|
6bb78f9d26 | ||
|
|
2b79f18d79 | ||
|
|
4a6e9fc5d6 | ||
|
|
6131bf3890 | ||
|
|
15806d7c9f | ||
|
|
42c2f78baf | ||
|
|
1028df91da | ||
|
|
b2c105dd67 | ||
|
|
1c59b2fb15 | ||
|
|
198e18bef5 | ||
|
|
1022e1e51f | ||
|
|
6927af4ec3 | ||
|
|
3f01a92d67 | ||
|
|
6a269dde79 | ||
|
|
d658e3e337 | ||
|
|
2911bf5314 | ||
|
|
0dc87bf0fc | ||
|
|
4f6f7f6791 | ||
|
|
62c2ac733c | ||
|
|
0b93115135 | ||
|
|
e78da9dea0 | ||
|
|
a3c309c676 | ||
|
|
6eaaff33bb | ||
|
|
22478f8097 | ||
|
|
b04e1ca081 | ||
|
|
0edb04eeb2 | ||
|
|
5c536079c9 | ||
|
|
6c4bdf0c5c | ||
|
|
f5c696ed7e | ||
|
|
5cdcd97201 | ||
|
|
096ead8648 | ||
|
|
547c17f4d2 | ||
|
|
9dbf97cccf | ||
|
|
670e77580d | ||
|
|
c81a64be79 | ||
|
|
506aeecdc2 | ||
|
|
5076862e07 |
@@ -11,3 +11,4 @@ docs/**/*.md
|
||||
lib/js-api/docs/**/*.md
|
||||
.storybook
|
||||
webpack.config.js
|
||||
lib/core/src/lib/icon
|
||||
|
||||
+38
-3
@@ -68,6 +68,7 @@ module.exports = {
|
||||
],
|
||||
'@angular-eslint/no-host-metadata-property': 'off',
|
||||
'@angular-eslint/no-input-prefix': 'error',
|
||||
'@angular-eslint/prefer-inject': 'error',
|
||||
'@typescript-eslint/consistent-type-definitions': 'error',
|
||||
'@typescript-eslint/dot-notation': 'off',
|
||||
'@typescript-eslint/explicit-member-accessibility': [
|
||||
@@ -78,6 +79,7 @@ module.exports = {
|
||||
],
|
||||
'@typescript-eslint/await-thenable': 'error',
|
||||
'@typescript-eslint/prefer-optional-chain': 'warn',
|
||||
'@typescript-eslint/prefer-readonly': 'error',
|
||||
'@typescript-eslint/no-inferrable-types': 'off',
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'error',
|
||||
@@ -100,10 +102,9 @@ module.exports = {
|
||||
],
|
||||
'@typescript-eslint/member-ordering': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'prefer-arrow/prefer-arrow-functions': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'prefer-promise-reject-errors': 'error',
|
||||
'brace-style': 'off',
|
||||
'@typescript-eslint/brace-style': 'error',
|
||||
'comma-dangle': 'error',
|
||||
'default-case': 'error',
|
||||
'import/order': 'off',
|
||||
@@ -141,7 +142,16 @@ module.exports = {
|
||||
],
|
||||
'no-duplicate-imports': 'error',
|
||||
'no-multiple-empty-lines': 'error',
|
||||
'no-redeclare': 'error',
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-redeclare': ['off', { ignoreDeclarationMerge: true }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_'
|
||||
}
|
||||
],
|
||||
'no-return-await': 'error',
|
||||
'rxjs/no-create': 'error',
|
||||
'rxjs/no-subject-unsubscribe': 'error',
|
||||
@@ -176,6 +186,25 @@ module.exports = {
|
||||
' * limitations under the License.',
|
||||
' */'
|
||||
]
|
||||
],
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: "Identifier[name='CUSTOM_ELEMENTS_SCHEMA']",
|
||||
message: 'The use of CUSTOM_ELEMENTS_SCHEMA is not allowed. Consider alternatives for proper schema handling.'
|
||||
},
|
||||
{
|
||||
selector: "Identifier[name='NO_ERRORS_SCHEMA']",
|
||||
message: 'The use of NO_ERRORS_SCHEMA is not allowed. Consider alternatives for proper schema handling.'
|
||||
},
|
||||
{
|
||||
selector: 'TSEnumDeclaration',
|
||||
message: 'Enums are not allowed. Use string literal types (e.g., type Foo = "a" | "b") or const objects instead.'
|
||||
},
|
||||
{
|
||||
selector: ':matches(Literal[value=/ng-reflect-/], TemplateElement[value.cooked=/ng-reflect-/])',
|
||||
message: '*ng-reflect-* attributes should not be used. Consider alternatives for proper selectors.'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -206,6 +235,12 @@ module.exports = {
|
||||
rules: {
|
||||
'comma-dangle': ['error', 'never']
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.stories.ts'],
|
||||
rules: {
|
||||
'@cspell/spellchecker': 'off'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.github/workflows/*.lock.yml linguist-generated=true merge=ours
|
||||
+3
-3
@@ -4,15 +4,15 @@
|
||||
# the repo. Unless a later match takes precedence,
|
||||
# these users will be requested for
|
||||
# review when someone opens a pull request.
|
||||
* @eromano @popovicsandras @DenysVuika
|
||||
* @eromano
|
||||
|
||||
# Order is important; the last matching pattern takes the most
|
||||
# precedence. When someone opens a pull request that only
|
||||
# modifies JS files, only @js-owner and not the global
|
||||
# owner(s) will be requested for a review.
|
||||
/e2e/ @eromano @cristinaj
|
||||
/e2e/ @eromano
|
||||
|
||||
# The `docs/*` pattern will match files like
|
||||
# `docs/getting-started.md` but not further nested files like
|
||||
# `docs/build-app/troubleshooting.md`.
|
||||
/docs/ @m-hulbert @eromano
|
||||
/docs/ @eromano
|
||||
|
||||
@@ -25,10 +25,22 @@ runs:
|
||||
|
||||
- name: affected:* flag parser
|
||||
shell: bash
|
||||
if: ${{ contains(github.event.head_commit.message , '[affected:*]') }}
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
echo "Setting up CI to run with commit flag [affected:*] flag."
|
||||
echo "BREAK_ACTION=true" >> $GITHUB_ENV
|
||||
# Get commit message safely from git to avoid script injection
|
||||
# For PRs, use the PR head SHA; for other events use HEAD
|
||||
if [ "$EVENT_NAME" == "pull_request" ] && [ -n "$PR_HEAD_SHA" ]; then
|
||||
COMMIT_MSG=$(git log -1 --format=%B "$PR_HEAD_SHA" 2>/dev/null || echo "")
|
||||
else
|
||||
COMMIT_MSG=$(git log -1 --format=%B 2>/dev/null || echo "")
|
||||
fi
|
||||
|
||||
if echo "$COMMIT_MSG" | grep -qF "[affected:*]"; then
|
||||
echo "Setting up CI to run with commit flag [affected:*] flag."
|
||||
echo "BREAK_ACTION=true" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: PULL_REQUEST event
|
||||
if: ${{ env.BREAK_ACTION == false && github.event_name == 'pull_request' && !github.event.pull_request.merged }}
|
||||
|
||||
@@ -12,7 +12,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
name: Create git tag
|
||||
env:
|
||||
TAG_NAME: ${{ inputs.tagName }}
|
||||
|
||||
@@ -4,7 +4,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Restore dist from cache
|
||||
uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: dist
|
||||
key: dist-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Restore nxcache from cache
|
||||
uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: nxcache
|
||||
key: nxcache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
@@ -22,7 +22,7 @@ runs:
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
name: 'Save Nx Cache'
|
||||
description: 'Save Nx cache and dist outputs only when the job succeeds'
|
||||
inputs:
|
||||
cache-suffix:
|
||||
description: 'Must match the cache-suffix used in the setup action'
|
||||
required: true
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Save nx cache
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: |
|
||||
nxcache
|
||||
.nx
|
||||
dist
|
||||
key: ${{ runner.os }}-nxcache-${{ inputs.cache-suffix }}-${{ hashFiles('nx.json') }}-${{ github.sha }}
|
||||
@@ -1,8 +1,12 @@
|
||||
name: 'Setup'
|
||||
description: 'Initialize cache, env var load'
|
||||
inputs:
|
||||
enable-node-modules-cache:
|
||||
description: 'enable caching for node modules'
|
||||
cache-suffix:
|
||||
description: 'Suffix to make Nx cache key unique per job (e.g. matrix project name)'
|
||||
required: false
|
||||
default: 'default'
|
||||
full-setup:
|
||||
description: 'Run git-latest-tag, npm-tag, and before-install (requires fetch-depth: 0). Set to false for matrix jobs that only need node/cache.'
|
||||
required: false
|
||||
type: boolean
|
||||
default: 'true'
|
||||
@@ -18,33 +22,43 @@ outputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: install NPM
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
- name: Set consistent machine ID for Nx cache
|
||||
shell: bash
|
||||
run: echo "nx-github-actions" | sudo tee /etc/machine-id > /dev/null
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache-dependency-path: package-lock.json
|
||||
cache: 'pnpm'
|
||||
- name: get latest tag sha
|
||||
if: ${{ inputs.full-setup == 'true' }}
|
||||
id: tag-sha
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@45b096a6666afcf321d6979aedda63b0998d3c60 # v12.5.1
|
||||
# CACHE
|
||||
- name: Node Modules cache
|
||||
id: node-modules-cache
|
||||
if: ${{ inputs.enable-node-modules-cache == 'true' }}
|
||||
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
env:
|
||||
cache-name: node-modules-cache
|
||||
with:
|
||||
path: |
|
||||
node_modules
|
||||
key: .npm-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
node_modules-${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
node_modules-${{ runner.os }}-build-
|
||||
node_modules-${{ runner.os }}-
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@10cea6c0b390c4f8af21d9dc1670d581bd10319f # v18.13.0
|
||||
- name: load "NPM TAG"
|
||||
if: ${{ inputs.full-setup == 'true' }}
|
||||
id: set-npm-tag
|
||||
uses: ./.github/actions/set-npm-tag
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Security audit
|
||||
shell: bash
|
||||
run: pnpm audit --audit-level=critical
|
||||
- name: Restore nx cache
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: |
|
||||
nxcache
|
||||
.nx
|
||||
dist
|
||||
key: ${{ runner.os }}-nxcache-${{ inputs.cache-suffix }}-${{ hashFiles('nx.json') }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nxcache-${{ inputs.cache-suffix }}-${{ hashFiles('nx.json') }}-
|
||||
${{ runner.os }}-nxcache-${{ inputs.cache-suffix }}-
|
||||
- name: before install script
|
||||
if: ${{ inputs.full-setup == 'true' }}
|
||||
uses: ./.github/actions/before-install
|
||||
with:
|
||||
act: ${{ inputs.act }}
|
||||
|
||||
@@ -5,19 +5,19 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Save dist to cache
|
||||
uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: dist
|
||||
key: dist-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
- name: Save nxcache to cache
|
||||
uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: nxcache
|
||||
key: nxcache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
- name: Save node_modules to cache
|
||||
uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"entries": {
|
||||
},
|
||||
"containers": {
|
||||
"ghcr.io/github/gh-aw-firewall/agent:0.25.58": {
|
||||
"image": "ghcr.io/github/gh-aw-firewall/agent:0.25.58",
|
||||
"digest": "sha256:a316a2c021accba8a9ea194c75466b0c4a166be6ac783bf8c2d0afd73373dec2",
|
||||
"pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.25.58@sha256:a316a2c021accba8a9ea194c75466b0c4a166be6ac783bf8c2d0afd73373dec2"
|
||||
},
|
||||
"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.58": {
|
||||
"image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.25.58",
|
||||
"digest": "sha256:43a5cdbe4e1156920dcdaab26d6c6761777d5c6bdc572d7d07b11739fb34c749",
|
||||
"pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.25.58@sha256:43a5cdbe4e1156920dcdaab26d6c6761777d5c6bdc572d7d07b11739fb34c749"
|
||||
},
|
||||
"ghcr.io/github/gh-aw-firewall/squid:0.25.58": {
|
||||
"image": "ghcr.io/github/gh-aw-firewall/squid:0.25.58",
|
||||
"digest": "sha256:558682b7b6313a5443cbb3d702899823bd732f991c8b52db6b5b8066abefe7a1",
|
||||
"pinned_image": "ghcr.io/github/gh-aw-firewall/squid:0.25.58@sha256:558682b7b6313a5443cbb3d702899823bd732f991c8b52db6b5b8066abefe7a1"
|
||||
},
|
||||
"ghcr.io/github/gh-aw-mcpg:v0.3.22": {
|
||||
"image": "ghcr.io/github/gh-aw-mcpg:v0.3.22",
|
||||
"digest": "sha256:ce5c6f5461b077af0d8e8eb1763436e85153f8e9531117d58a7bdb23de71f00a",
|
||||
"pinned_image": "ghcr.io/github/gh-aw-mcpg:v0.3.22@sha256:ce5c6f5461b077af0d8e8eb1763436e85153f8e9531117d58a7bdb23de71f00a"
|
||||
},
|
||||
"ghcr.io/github/github-mcp-server:v1.1.0": {
|
||||
"image": "ghcr.io/github/github-mcp-server:v1.1.0",
|
||||
"digest": "sha256:71b07d9abecb83b4a2595bcd8ccb35f9a0166361a12335f9e16da1ef07172029",
|
||||
"pinned_image": "ghcr.io/github/github-mcp-server:v1.1.0@sha256:71b07d9abecb83b4a2595bcd8ccb35f9a0166361a12335f9e16da1ef07172029"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
# General Code Review Instructions
|
||||
|
||||
## Review Priorities
|
||||
When performing a code review, prioritize issues in the following order:
|
||||
|
||||
🔴 CRITICAL (Block merge)
|
||||
* Security: Vulnerabilities, exposed secrets, authentication/authorization issues, injection, XSS
|
||||
* Memory/resource leaks
|
||||
* Crashes or undefined behavior
|
||||
* Correctness: Logic errors, data corruption risks, race conditions, missing error handling
|
||||
* Data Loss: Risk of data loss or corruption
|
||||
|
||||
🟡 IMPORTANT (Requires discussion)
|
||||
* Code Quality: Severe violations of SOLID principles, excessive duplication
|
||||
* Test Coverage: Missing tests for critical paths or new functionality
|
||||
* Performance: Obvious performance bottlenecks (N+1 queries, memory leaks)
|
||||
* Architecture: Significant deviations from established patterns
|
||||
|
||||
🟢 SUGGESTION (Non-blocking improvements)
|
||||
* Readability: Poor naming, complex logic that could be simplified
|
||||
* Optimization: Performance improvements without functional impact
|
||||
* Best Practices: Minor deviations from conventions
|
||||
* Documentation: Missing or incomplete comments/documentation
|
||||
|
||||
## General Review Principles
|
||||
When performing a code review, follow these principles:
|
||||
|
||||
* Be specific: Reference exact lines, files, and provide concrete examples
|
||||
* Be pragmatic: Not every suggestion needs immediate implementation
|
||||
* Provide context: Explain WHY something is an issue and the potential impact
|
||||
* Suggest solutions: Show corrected code when applicable, not just what's wrong
|
||||
* Be constructive: Focus on improving the code, not criticizing the author
|
||||
* Recognize good practices: Acknowledge well-written code and smart solutions
|
||||
* Group related comments: Avoid multiple comments about the same topic
|
||||
* Ask clarifying questions when code intent is unclear
|
||||
|
||||
## Code Quality Standards
|
||||
When performing a code review, check for:
|
||||
|
||||
### Clean Code
|
||||
* Descriptive and meaningful names for variables, functions, and classes
|
||||
* Single Responsibility Principle: each function/class does one thing well
|
||||
* DRY (Don't Repeat Yourself): no code duplication
|
||||
* Functions should be small and focused (ideally < 20-30 lines)
|
||||
* Avoid deeply nested code (max 3-4 levels), unit tests should be an exception from this rule
|
||||
* Avoid magic numbers and strings (use constants)
|
||||
* Code should be self-documenting; comments only when necessary
|
||||
* Code follows consistent style and conventions
|
||||
* No commented-out code or TODO without tickets
|
||||
|
||||
## Error Handling
|
||||
* Proper error handling at appropriate levels
|
||||
* Meaningful error messages
|
||||
* No silent failures or ignored exceptions
|
||||
* Fail fast: validate inputs early
|
||||
* Use appropriate error types/exceptions
|
||||
|
||||
## Testing Standards
|
||||
When performing a code review, verify test quality:
|
||||
|
||||
* Coverage: Critical paths and new functionality must have tests
|
||||
* Test Names: Descriptive names that explain what is being tested
|
||||
* Independence: Tests should not depend on each other or external state
|
||||
* Assertions: Use specific assertions, avoid generics
|
||||
* Edge Cases: Test boundary conditions, null values, empty inputs
|
||||
* Mock Appropriately: Mock external dependencies, not domain logic
|
||||
* New code has appropriate test coverage
|
||||
* No tests that always pass or are commented out
|
||||
|
||||
## Architecture and Design
|
||||
When performing a code review, verify architectural principles:
|
||||
|
||||
* Separation of Concerns: Clear boundaries between layers/modules
|
||||
* Dependency Direction: High-level modules don't depend on low-level details
|
||||
* Interface Segregation: Prefer small, focused interfaces
|
||||
* Loose Coupling: Components should be independently testable
|
||||
* High Cohesion: Related functionality grouped together
|
||||
* Consistent Patterns: Follow established patterns in the codebase
|
||||
+29
-33
@@ -6,6 +6,8 @@ updates:
|
||||
interval: "weekly"
|
||||
day: "sunday"
|
||||
time: "07:00"
|
||||
cooldown:
|
||||
default-days: 3
|
||||
open-pull-requests-limit: 5
|
||||
target-branch: develop
|
||||
groups:
|
||||
@@ -21,44 +23,38 @@ updates:
|
||||
nrwl:
|
||||
patterns:
|
||||
- "@nrwl/*"
|
||||
typescript-eslint:
|
||||
patterns:
|
||||
- "@typescript-eslint/*"
|
||||
ignore:
|
||||
- dependency-name: "pdfjs-dist"
|
||||
- dependency-name: "@types/*"
|
||||
- dependency-name: "typescript"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/before-install"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/download-node-modules-and-artifacts"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/enable-dryrun"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/get-latest-tag-sha"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/npm-check-bundle"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/set-npm-tag"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/setup"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/upload-node-modules-and-artifacts"
|
||||
directories:
|
||||
- "/"
|
||||
- "/.github/actions/before-install"
|
||||
- "/.github/actions/create-git-tag"
|
||||
- "/.github/actions/download-node-modules-and-artifacts"
|
||||
- "/.github/actions/enable-dryrun"
|
||||
- "/.github/actions/get-latest-tag-sha"
|
||||
- "/.github/actions/npm-check-bundle"
|
||||
- "/.github/actions/save-nx-cache"
|
||||
- "/.github/actions/set-npm-tag"
|
||||
- "/.github/actions/setup"
|
||||
- "/.github/actions/upload-node-modules-and-artifacts"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
cooldown:
|
||||
default-days: 3
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
ignore:
|
||||
# Managed by gh aw add. Version-locked to the gh-aw compiler; do not bump.
|
||||
- dependency-name: "github/gh-aw-actions"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
applyTo: "**/*.html"
|
||||
---
|
||||
|
||||
# HTML Development Standards
|
||||
|
||||
* Simple Templates: Keep templates as simple as possible, avoiding complex logic directly in the template. Delegate complex logic to the component's TypeScript code.
|
||||
* Native Control Flow: Use the new built-in control flow syntax (`@if`, `@for`, `@switch`) instead of the older structural directives (`*ngIf`, `*ngFor`, `*ngSwitch`).
|
||||
* NgOptimizedImage: Use `NgOptimizedImage` for all static images to automatically optimize image loading and performance.
|
||||
* Async Pipe: Use the `async` pipe to handle observables in templates. This automatically subscribes and unsubscribes, preventing memory leaks.
|
||||
* Prefer pipes over functions in templates for performance reasons, as pipes are only re-evaluated when their inputs change.
|
||||
|
||||
## Accessibility Standards
|
||||
|
||||
* Add `alt` text to all images
|
||||
* Label form inputs with `<mat-label>` or `aria-label`
|
||||
* Ensure interactive elements have accessible names
|
||||
* Add `role`, `aria-labelledby`, and `aria-describedby` when semantic HTML isn't sufficient
|
||||
* All interactive elements must be keyboard accessible
|
||||
* Ensure 4.5:1 contrast ratio for normal text, 3:1 for large text
|
||||
* Use `aria-live="polite"` for status updates
|
||||
* Watch out for misused/non-semantic elements (e.g., <div> instead of <section>)
|
||||
* Avoid broken heading hierarchy (e.g., h1 → h3 without h2)
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
applyTo: "**/*.scss"
|
||||
---
|
||||
|
||||
# SCSS Development Standards
|
||||
|
||||
* Avoid using `!important` to override styles unless absolutely necessary; instead, increase specificity or refactor the code structure.
|
||||
* Avoid using Angular Material internal class; prefer using Angular Material Design 3 theming and tokens.
|
||||
* Use variables for colors, fonts, and other design tokens to maintain consistency across the project.
|
||||
* Use mixins for reusable styles and to avoid code duplication.
|
||||
* Ensure that styles are responsive and work well across different screen sizes and devices.
|
||||
* Use CSS Grid and Flexbox for layout to create flexible and responsive designs.
|
||||
* Avoid using overly specific selectors (e.g., #header .nav ul li a)
|
||||
* Be DRY (avoid repeated styles for similar elements)
|
||||
* Check for inconsistent naming (e.g., mixing BEM and arbitrary classes)
|
||||
* Make sure selected colors have right contrast (satisfy WCAG AA)
|
||||
* All interactive elements should have focus state
|
||||
* Avoid disabled outline without alternative focus indicators
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
applyTo: "**/*.ts"
|
||||
---
|
||||
|
||||
# TypeScript Development Standards
|
||||
|
||||
## Type Safety
|
||||
|
||||
* Strict Type Checking: Always enable and adhere to strict type checking. This helps catch errors early and improves code quality.
|
||||
* Prefer Type Inference: Allow TypeScript to infer types when they are obvious from the context. This reduces verbosity while maintaining type safety.
|
||||
* Avoid `any`: Do not use the `any` type unless absolutely necessary as it bypasses type checking. Prefer `unknown` when a type is uncertain and you need to handle it safely.
|
||||
* Use strict null checks (no `null` or `undefined` without explicit handling)
|
||||
* Use type guards and union types for robust type checking
|
||||
* Check for missing return types in function signatures
|
||||
* Avoid implicit `any` (untyped function parameters)
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
* Use PascalCase for types, interfaces, and classes
|
||||
* Use camelCase for variables, functions, and methods
|
||||
* Use UPPER_CASE for constants
|
||||
|
||||
## Modern TypeScript Patterns
|
||||
|
||||
* Use optional chaining (`?.`) and nullish coalescing (`??`)
|
||||
* Prefer `const` over `let`; never use `var`
|
||||
* Use arrow functions for callbacks and short functions
|
||||
* Avoid enums - they generate additional code at compile time, which increases the size of the final file. This can have a negative impact on the loading speed and performance of the app. Prefer union types or literal types instead.
|
||||
* Avoid unhandled promise rejections (missing .catch() or try/catch)
|
||||
* Use proper async/await pattern
|
||||
* Avoid inefficient array operations (e.g., nested .map())
|
||||
* Use destructuring for object/array access
|
||||
* Prefer arrow functions
|
||||
|
||||
## Angular Best Practices
|
||||
|
||||
* Standalone Components: Always use standalone components, directives, and pipes. Avoid using `NgModules` for new features or refactoring existing ones.
|
||||
* Implicit Standalone: When creating standalone components, you do not need to explicitly set `standalone: true` inside the `@Component`, `@Directive` and `@Pipe` decorators, as it is implied by default.
|
||||
* Lazy Loading: Implement lazy loading for feature routes to improve initial load times of your application.
|
||||
* Use Angular Material or other modern UI libraries for consistent styling and UI components.
|
||||
* Implement proper error handling with RxJS operators (e.g., catchError)
|
||||
* Verify if newly added functionalities can utilize Angular Signals for fine-grained reactivity, reducing change detection overhead.
|
||||
* Utilize AOT (Ahead-of-Time) compilation and tree-shaking for efficient, smaller bundle sizes.
|
||||
* Prefer class binding over `ngClass` and `ngStyle` for better performance.
|
||||
* Use protected on class members that are only used by a component's template, as it allows for better encapsulation while still being accessible to the template.
|
||||
* Use readonly for properties that shouldn't change.
|
||||
* Use `takeUntilDestroyed` & `destroyRef`: The `takeUntilDestroyed` and `destroyRef` have been introduced with Angular 16 and help to reduce boilerplate code related to unsubscribing on the `OnDestroy` hook.
|
||||
* Organize the order of properties and methods in Angular components for readability and maintainability. Recommended order is:
|
||||
1. **Injected services** Whether they are public or private, it's clear they are dependencies of the class.
|
||||
2. **Inputs**: Properties that receive data from outside.
|
||||
3. **Outputs**: Events that the component can trigger.
|
||||
4. **ViewChild/ContentChild**: References to HTML elements.
|
||||
5. **Public static properties**: Constants and static members that are accessible to everyone.
|
||||
6. **Readonly properties**: Immutable public properties.
|
||||
7. **Public properties**: Data and functions available to everyone.
|
||||
8. **Private static properties**: Constants and static members that are only accessible within the class.
|
||||
9. **Private readonly properties**: Immutable private properties.
|
||||
10. **Private properties**: Data and functions used only inside the component.
|
||||
11. **Setters and Getters**: Methods for accessing and modifying properties.
|
||||
12. **Constructor**: Used to initialize the component.
|
||||
13. **Lifecycle Hooks**: Methods that run at specific times in the component’s lifecycle.
|
||||
14. **Public methods**: Functions available to everyone.
|
||||
15. **Private methods**: Functions used only inside the component.
|
||||
|
||||
## Components
|
||||
|
||||
* Single Responsibility: Keep components small, focused, and responsible for a single piece of functionality.
|
||||
* Reactive Forms: Prefer Reactive forms over Template-driven forms for complex forms, validation, and dynamic controls due to their explicit, immutable, and synchronous nature.
|
||||
* Use Typed Forms: Typed Forms in Angular are a new feature introduced in Angular 14 that provide stronger type checking for reactive forms. They allow developers to define the structure and types of form controls, making it easier to catch errors at compile-time rather than runtime.
|
||||
|
||||
## Services
|
||||
|
||||
* Single Responsibility: Design services around a single, well-defined responsibility.
|
||||
* `providedIn: 'root'`: Use the `providedIn: 'root'` option when declaring injectable services to ensure they are singletons and tree-shakable.
|
||||
* `inject()` Function: Prefer the `inject()` function over constructor injection when injecting dependencies, especially within `provide` functions, `computed` properties, or outside of constructor context.
|
||||
|
||||
## Unit testing
|
||||
|
||||
* Write unit tests for components, services, and pipes using Jasmine and Karma.
|
||||
* Test cases should be reasonably groupped based on tested functionality/behaviour using describe blocks.
|
||||
* Use plain English test names based on the should <expectedBehavior> when <stateUnderTest> pattern as a guideline.
|
||||
* Use Angular's TestBed for component testing with mocked dependencies
|
||||
* Avoid Direct Calls to Component Lifecycle Hooks: Instead of directly invoking lifecycle hooks like `ngOnInit()`, use Angular's testing utilities to trigger them naturally. For example, use `fixture.detectChanges()` to trigger change detection, which will automatically call `ngOnInit()` and other lifecycle hooks in the correct order.
|
||||
* Use fixture.componentRef.setInput() Instead of Direct Input Assignment: When testing components with inputs, use `fixture.componentRef.setInput()` to set input values. This method ensures that Angular's change detection is properly triggered, allowing the component to react to input changes as it would in a real application.
|
||||
* Use the Provide Mock Store for testing components that rely on NgRx state management. This allows you to mock the store and control the state during tests without needing to set up a full NgRx environment.
|
||||
* Mock HTTP requests using provideHttpClientTesting
|
||||
* Import only the minimal required modules
|
||||
* Avoid NO_ERRORS_SCHEMA and CUSTOM_ELEMENTS_SCHEMA in tests to ensure proper error detection
|
||||
* Do not verify mocked methods
|
||||
* Avoid mocking component methods unless necessary; prefer testing actual behavior
|
||||
* Avoid testing private methods directly; test them through public methods instead
|
||||
* Avoid testing methods or behaviours of children components; use shallow testing or mock child components instead
|
||||
* Use the overrideProviders API to replace components, directives, pipes, or services declared deep within the module hierarchy
|
||||
* Avoid async/await in synchronous unit tests
|
||||
* Prefer data-automation-id over CSS class when possible
|
||||
* Do not use toBeDefined() to check if an element is visible.
|
||||
@@ -0,0 +1,39 @@
|
||||
name: "Build Lib Workflow"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
base_ref:
|
||||
description: 'Base branch for affected calculation'
|
||||
required: false
|
||||
type: string
|
||||
default: 'develop'
|
||||
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build affected libs"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup environment
|
||||
id: setup-env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
cache-suffix: build
|
||||
full-setup: 'false'
|
||||
- name: Build affected libs
|
||||
env:
|
||||
BASE_REF: ${{ inputs.base_ref }}
|
||||
run: pnpm nx affected --target=build --base=origin/$BASE_REF --head=HEAD --configuration=production --exclude=stories
|
||||
- name: Save nx cache
|
||||
if: ${{ success() }}
|
||||
uses: ./.github/actions/save-nx-cache
|
||||
with:
|
||||
cache-suffix: build
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.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@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v3.29.5
|
||||
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # 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@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v3.29.5
|
||||
uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # 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@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v3.29.5
|
||||
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3.29.5
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
name: "git-tag"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
dry-run-flag:
|
||||
description: 'enable dry-run on artifact push'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- master-patch-*
|
||||
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
NPM_REGISTRY_ADDRESS: ${{ secrets.NPM_REGISTRY_ADDRESS }}
|
||||
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
|
||||
release:
|
||||
uses: ./.github/workflows/release.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
dry-run-flag: false
|
||||
|
||||
setup:
|
||||
needs: release
|
||||
timeout-minutes: 20
|
||||
name: "Release tag"
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_TOKEN: $BOT_GITHUB_TOKEN
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- id: set-dryrun
|
||||
uses: ./.github/actions/enable-dryrun
|
||||
with:
|
||||
dry-run-flag: ${{ inputs.dry-run-flag }}
|
||||
- name: install NPM
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.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 $DRYRUN_FLAG
|
||||
@@ -9,7 +9,7 @@ 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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
PACKAGE_NAME: ${{ github.event.registry_package.name }}
|
||||
PACKAGE_VERSION: ${{ github.event.registry_package.package_version.name }}
|
||||
|
||||
@@ -3,21 +3,36 @@ on:
|
||||
schedule:
|
||||
- cron: "0 7-17 * * 1-5"
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
secrets:
|
||||
BOT_GITHUB_TOKEN:
|
||||
required: true
|
||||
CROWDIN_TRANSLATIONS_TOKEN:
|
||||
required: true
|
||||
HXPS_GIT_COMMIT_SIGNING_PRIVATE_KEY:
|
||||
required: true
|
||||
jobs:
|
||||
pull-from-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- name: Pull translations from Crowdin
|
||||
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
ref: develop
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
- name: Pull translations from Crowdin
|
||||
uses: crowdin/github-action@52aa776766211d83d975df51f3b9c53c2f8ba35f # v2.16.3
|
||||
with:
|
||||
skip_ref_checkout: true
|
||||
upload_sources: false
|
||||
download_translations: true
|
||||
create_pull_request: true
|
||||
localization_branch_name: automated-translations-update
|
||||
pull_request_title: "GH auto: Automated Update of Translations from Crowdin"
|
||||
pull_request_base_branch_name: develop
|
||||
github_user_name: ${{ vars.HXPS_GIT_USERNAME }}
|
||||
github_user_email: ${{ vars.HXPS_GIT_EMAIL }}
|
||||
gpg_private_key: ${{ secrets.HXPS_GIT_COMMIT_SIGNING_PRIVATE_KEY }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TRANSLATIONS_TOKEN }}
|
||||
|
||||
+217
-174
@@ -31,249 +31,295 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
|
||||
jobs:
|
||||
pre-checks:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
code-changed: ${{ steps.path-filter.outputs.code-changed }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure SHA pinned actions
|
||||
uses: hyland/github-actions-ensure-sha-pinned-actions@22ca7a8cf33e873ba1d6fbcd2b71fa0ec5006b17 # v1.1.0
|
||||
uses: hyland/github-actions-ensure-sha-pinned-actions@7957efb76aba0eec7580a9c0392d3e5bec381359 # v2.0.1
|
||||
|
||||
- name: Check package-lock.json version
|
||||
- name: Check pnpm-lock.yaml version
|
||||
run: |
|
||||
if [[ $(jq '.lockfileVersion == 3' package-lock.json) == "true" ]] ; then
|
||||
echo "package-lock.json has a correct version"
|
||||
if [[ -f "pnpm-lock.yaml" ]]; then
|
||||
LOCKFILE_VERSION=$(grep "^lockfileVersion:" pnpm-lock.yaml | cut -d"'" -f2)
|
||||
if [[ "$LOCKFILE_VERSION" == "9.0" ]]; then
|
||||
echo "pnpm-lock.yaml has correct version: $LOCKFILE_VERSION"
|
||||
else
|
||||
echo "pnpm-lock.yaml must be version 9.0, found: $LOCKFILE_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "package-lock must be version 3"
|
||||
echo "pnpm-lock.yaml is missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Detect code changes
|
||||
id: path-filter
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" != "pull_request" ]; then
|
||||
echo "Not a PR event — assuming code changed"
|
||||
echo "code-changed=true" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FILES=$(gh api /repos/$GITHUB_REPOSITORY/pulls/${{ github.event.pull_request.number }}/files --paginate --jq '.[].filename')
|
||||
|
||||
CODE_CHANGED="false"
|
||||
while IFS= read -r file; do
|
||||
case "$file" in
|
||||
*.md|docs/*|.github/*.md|.github/CODEOWNERS|.github/dependabot.yml|LICENSE*|NOTICE*|.editorconfig|.gitattributes)
|
||||
;;
|
||||
*)
|
||||
CODE_CHANGED="true"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done <<< "$FILES"
|
||||
|
||||
echo "code-changed=$CODE_CHANGED" >> $GITHUB_OUTPUT
|
||||
echo "Code changed: $CODE_CHANGED"
|
||||
|
||||
check-if-pr-is-approved:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Get branch name
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@45b096a6666afcf321d6979aedda63b0998d3c60 # v12.5.1
|
||||
|
||||
- name: Save commit message
|
||||
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@45b096a6666afcf321d6979aedda63b0998d3c60 # v12.5.1
|
||||
with:
|
||||
header-only: true
|
||||
|
||||
- name: ci:force flag parser
|
||||
shell: bash
|
||||
- name: Check if PR approval can be skipped
|
||||
id: skip-check
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
DEVEL_FLAG: ${{ inputs.devel }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
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
|
||||
echo -e "\033[32m[ci:force] flag detected. No need for approval.\033[0m"
|
||||
skip_check="true"
|
||||
skip="false"
|
||||
|
||||
# Get commit message safely from git to avoid script injection
|
||||
if [ "$EVENT_NAME" == "pull_request" ] && [ -n "$PR_HEAD_SHA" ]; then
|
||||
COMMIT_MESSAGE=$(git log -1 --format=%B "$PR_HEAD_SHA" 2>/dev/null || echo "")
|
||||
else
|
||||
COMMIT_MESSAGE=$(git log -1 --format=%B 2>/dev/null || echo "")
|
||||
fi
|
||||
|
||||
if [ "$EVENT_NAME" == "schedule" ] || [ "$EVENT_NAME" == "workflow_dispatch" ]; then
|
||||
echo -e "\033[32mSchedule/dispatch event — skipping approval check\033[0m"
|
||||
skip="true"
|
||||
elif [ "$ACTOR" == "dependabot[bot]" ] || [ "$ACTOR" == "alfresco-build" ]; then
|
||||
echo -e "\033[32mCommit by $ACTOR — skipping approval check\033[0m"
|
||||
skip="true"
|
||||
elif echo "$PR_TITLE" | grep -qF "[ci:force]"; then
|
||||
echo -e "\033[32m[ci:force] flag detected in PR title — skipping approval check\033[0m"
|
||||
skip="true"
|
||||
elif echo "$COMMIT_MESSAGE" | grep -qF "[ci:force]"; then
|
||||
echo -e "\033[32m[ci:force] flag detected in commit message — skipping approval check\033[0m"
|
||||
skip="true"
|
||||
elif [[ "$DEVEL_FLAG" == "true" ]]; then
|
||||
echo -e "\033[32mDevel flag — skipping approval check\033[0m"
|
||||
skip="true"
|
||||
fi
|
||||
|
||||
echo "skip=$skip" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get PR number
|
||||
if: ${{ github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' }}
|
||||
uses: kamatama41/get-pr-number-action@0bcaab5752c0b699149e74667c8ce2f764cbb7fa # v0.9.1
|
||||
id: action
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: show pr number
|
||||
shell: bash
|
||||
if: ${{ steps.skip-check.outputs.skip != 'true' }}
|
||||
id: pr-number
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.action.outputs.number }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
PR_NUMBER="${{ github.event.pull_request.number }}"
|
||||
if [ -z "$PR_NUMBER" ]; then
|
||||
PR_NUMBER=$(gh pr view --json number --jq '.number' 2>/dev/null || echo "")
|
||||
fi
|
||||
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
echo "PR: $PR_NUMBER"
|
||||
|
||||
- name: check if pr is approved
|
||||
- name: Check if PR is approved
|
||||
if: ${{ steps.skip-check.outputs.skip != 'true' && steps.pr-number.outputs.pr_number != '' }}
|
||||
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 }}
|
||||
PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
|
||||
run: |
|
||||
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
|
||||
echo -e "\033[32m[ci:force] flag detected. No need for approval.\033[0m"
|
||||
skip_check="true"
|
||||
fi
|
||||
|
||||
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 [ "$EVENT_NAME" == "schedule" ] || [ "$EVENT_NAME" == "workflow_dispatch" ]; then
|
||||
echo -e "\033[32mSchedule event\033[0m"
|
||||
skip_check="true"
|
||||
fi
|
||||
|
||||
if [[ "$DEVEL_FLAG" == "true" ]]; then
|
||||
echo -e "\033[32mDevel flag\033[0m"
|
||||
skip_check="true"
|
||||
fi
|
||||
|
||||
if [ "$skip_check" == "false" ]; then
|
||||
echo "Checking PR approval"
|
||||
prNumber=$PR_NUMBER
|
||||
echo "PR: $prNumber"
|
||||
checkApproval=$(gh api /repos/$GITHUB_REPOSITORY/pulls/$prNumber/reviews | jq '.[] | select(.state == "APPROVED") | .user.login')
|
||||
if [[ $checkApproval ]]; then
|
||||
echo -e "\033[32mPR approved\033[0m"
|
||||
else
|
||||
echo -e "\033[31mPR NOT approved\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
echo "Checking approval for PR: $PR_NUMBER"
|
||||
checkApproval=$(gh api /repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews | jq '.[] | select(.state == "APPROVED") | .user.login')
|
||||
if [[ $checkApproval ]]; then
|
||||
echo -e "\033[32mPR approved\033[0m"
|
||||
else
|
||||
echo -e "\033[31mPR NOT approved\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
setup:
|
||||
# long timeout required when cache has to be recreated
|
||||
timeout-minutes: 30
|
||||
name: "Setup"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-if-pr-is-approved, pre-checks]
|
||||
if: ${{ needs.pre-checks.outputs.code-changed == 'true' }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all tags and branches
|
||||
- uses: ./.github/actions/setup
|
||||
- name: install
|
||||
run: |
|
||||
npm ci
|
||||
npm run bundle:js-api
|
||||
npm run bundle:cli
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
unit-tests:
|
||||
timeout-minutes: 30
|
||||
name: "Unit tests: ${{ matrix.unit-tests.name }}"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# max-parallel: 4
|
||||
matrix:
|
||||
unit-tests:
|
||||
- name: js-api
|
||||
exclude: "core,insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular"
|
||||
- name: content-services
|
||||
exclude: "insights,core,extensions,process-services,process-services-cloud,eslint-plugin-eslint-angular,js-api"
|
||||
- name: core
|
||||
exclude: "insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular,js-api"
|
||||
- name: insights
|
||||
exclude: "core,extensions,content-services,process-services-cloud,process-services,eslint-plugin-eslint-angular,js-api"
|
||||
- name: process-services
|
||||
exclude: "core,extensions,content-services,process-services-cloud,insights,eslint-plugin-eslint-angular,js-api"
|
||||
- name: process-services-cloud
|
||||
exclude: "insights,core,extensions,content-services,process-services$,eslint-plugin-eslint-angular,js-api"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
fetch-depth: 0
|
||||
- name: Setup environment
|
||||
id: setup-env
|
||||
uses: ./.github/actions/setup
|
||||
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 }}
|
||||
cache-suffix: setup
|
||||
- name: Bundle
|
||||
run: |
|
||||
/usr/bin/xvfb-run --auto-servernum npm run test:affected -- $NX_CALCULATION_FLAGS --exclude=$EXCLUDE_PATTERN
|
||||
pnpm bundle:js-api
|
||||
pnpm bundle:cli
|
||||
- name: Save nx cache
|
||||
if: ${{ success() }}
|
||||
uses: ./.github/actions/save-nx-cache
|
||||
with:
|
||||
cache-suffix: setup
|
||||
|
||||
lint:
|
||||
# long timeout required when cache has to be recreated
|
||||
timeout-minutes: 30
|
||||
name: "Lint"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [setup]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.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: npm run lint:affected -- $NX_CALCULATION_FLAGS
|
||||
fetch-depth: 0
|
||||
- name: Setup environment
|
||||
id: setup-env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
cache-suffix: lint
|
||||
full-setup: 'false'
|
||||
- name: Run lint
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref || 'develop' }}
|
||||
run: pnpm nx affected --target=lint --base=origin/$BASE_REF --head=HEAD
|
||||
- name: Save nx cache
|
||||
if: ${{ success() }}
|
||||
uses: ./.github/actions/save-nx-cache
|
||||
with:
|
||||
cache-suffix: lint
|
||||
|
||||
build-libs:
|
||||
# long timeout required when cache has to be recreated
|
||||
timeout-minutes: 30
|
||||
name: "Build libs"
|
||||
runs-on: ubuntu-latest
|
||||
trigger-build:
|
||||
name: "Build Libs"
|
||||
needs: [setup]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
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 npm run build:affected -- $NX_CALCULATION_FLAGS --prod
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
uses: ./.github/workflows/build-lib-workflow.yml
|
||||
with:
|
||||
base_ref: ${{ github.base_ref || 'develop' }}
|
||||
|
||||
build-storybook:
|
||||
timeout-minutes: 30
|
||||
name: "Build storybook"
|
||||
runs-on: ubuntu-latest
|
||||
name: "Build Storybook"
|
||||
needs: [setup]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.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: npm run build-storybook
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
fetch-depth: 0
|
||||
- name: Setup environment
|
||||
id: setup-env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
cache-suffix: storybook
|
||||
full-setup: 'false'
|
||||
- name: Build Storybook
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref || 'develop' }}
|
||||
run: |
|
||||
pnpm nx affected --target=build-storybook --base=origin/$BASE_REF --head=HEAD --configuration=ci
|
||||
- name: Save nx cache
|
||||
if: ${{ success() }}
|
||||
uses: ./.github/actions/save-nx-cache
|
||||
with:
|
||||
cache-suffix: storybook
|
||||
|
||||
trigger-unit-tests:
|
||||
name: "Unit Tests"
|
||||
needs: [setup]
|
||||
uses: ./.github/workflows/unit-test-workflow.yml
|
||||
with:
|
||||
base_ref: ${{ github.base_ref || 'develop' }}
|
||||
|
||||
PR-size-check:
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check PR size
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
const additions = pr.additions;
|
||||
const deletions = pr.deletions;
|
||||
const totalChanges = additions + deletions;
|
||||
const changedFiles = pr.changed_files;
|
||||
|
||||
let size = 'S';
|
||||
if (totalChanges > 1000 || changedFiles > 30) size = 'XL';
|
||||
else if (totalChanges > 500 || changedFiles > 20) size = 'L';
|
||||
else if (totalChanges > 200 || changedFiles > 10) size = 'M';
|
||||
|
||||
core.summary
|
||||
.addHeading('PR Size: ' + size, 3)
|
||||
.addTable([
|
||||
[{data: 'Metric', header: true}, {data: 'Count', header: true}],
|
||||
['Files changed', String(changedFiles)],
|
||||
['Additions', '+' + String(additions)],
|
||||
['Deletions', '-' + String(deletions)],
|
||||
['Total changes', String(totalChanges)],
|
||||
]);
|
||||
|
||||
if (size === 'XL') {
|
||||
core.summary.addRaw('⚠️ This PR is very large. Consider splitting it into smaller PRs for easier review.');
|
||||
}
|
||||
|
||||
await core.summary.write();
|
||||
|
||||
if (size === 'XL') {
|
||||
core.warning('This PR has ' + totalChanges + ' changes across ' + changedFiles + ' files. Consider splitting it for easier review.');
|
||||
}
|
||||
|
||||
PR-forbidden-labels:
|
||||
if: ${{ inputs.cron-run == '' || inputs.cron-run == 'false' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: checkoutRepo
|
||||
name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: PR contains forbidden labels
|
||||
id: pr-forbidden
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
- name: Check for forbidden labels
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const issueHasLabels = require('./scripts/github/update/check-issue-has-label.js');
|
||||
const checkLabels = ['next version ➡️', 'do not merge🙅🏻♂️'];
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
const labels = issue.labels?.map(item => item.name) || [];
|
||||
const forbidden = ['next version ➡️', 'do not merge🙅🏻♂️'];
|
||||
|
||||
const hasLabel = await issueHasLabels({github, context, checkLabels})
|
||||
|
||||
if(hasLabel) {
|
||||
if (forbidden.some(l => labels.includes(l))) {
|
||||
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 "Step result: $STEP_RESULT"
|
||||
echo "Has failure: $HAS_FAILURE"
|
||||
|
||||
finalize:
|
||||
if: ${{ always() }}
|
||||
@@ -284,16 +330,13 @@ jobs:
|
||||
check-if-pr-is-approved,
|
||||
pre-checks,
|
||||
setup,
|
||||
unit-tests,
|
||||
trigger-unit-tests,
|
||||
lint,
|
||||
build-libs,
|
||||
trigger-build,
|
||||
build-storybook,
|
||||
PR-forbidden-labels,
|
||||
]
|
||||
steps:
|
||||
- name: Check job execution status
|
||||
if: >-
|
||||
${{
|
||||
contains(needs.*.result, 'failure')
|
||||
|| contains(needs.*.result, 'cancelled')
|
||||
}}
|
||||
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
|
||||
run: exit 1
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Automatic Rebase
|
||||
|
||||
@@ -19,9 +19,11 @@ on:
|
||||
types: [closed]
|
||||
branches:
|
||||
- develop
|
||||
- master
|
||||
- develop-patch*
|
||||
- master-patch*
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- master-patch-*
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC
|
||||
@@ -47,7 +49,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/setup
|
||||
@@ -55,9 +57,9 @@ jobs:
|
||||
enable-node-modules-cache: false
|
||||
- name: install
|
||||
run: |
|
||||
npm ci
|
||||
npm run bundle:js-api
|
||||
npm run bundle:cli
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm bundle:js-api
|
||||
pnpm bundle:cli
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
release-npm:
|
||||
@@ -73,7 +75,7 @@ jobs:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: setup
|
||||
@@ -91,31 +93,31 @@ jobs:
|
||||
set -u;
|
||||
./scripts/github/build/bumpversion.sh
|
||||
- name: Set migrations
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const setMigrations = require('./scripts/github/release/set-migrations.js');
|
||||
setMigrations();
|
||||
- name: build libraries
|
||||
run: |
|
||||
npm run build:libs
|
||||
npm run build:schematics
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
pnpm build:libs
|
||||
pnpm build:schematics
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
name: release libraries GH registry
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
scope: '@alfresco'
|
||||
- run: npm run publish -- --tag=${{ steps.setup.outputs.npm-tag }}
|
||||
- run: pnpm run publish --tag ${{ steps.setup.outputs.npm-tag }} --provenance=false
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
name: release libraries Npm registry
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: 'https://${{ vars.NPM_REGISTRY_ADDRESS }}'
|
||||
scope: '@alfresco'
|
||||
- run: npm run publish -- --tag=${{ steps.setup.outputs.npm-tag }}
|
||||
- run: pnpm run publish --tag ${{ steps.setup.outputs.npm-tag }}
|
||||
|
||||
create-git-tag:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -126,33 +128,13 @@ jobs:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- uses: './.github/actions/create-git-tag'
|
||||
with:
|
||||
tagName: ${{ needs.release-npm.outputs.release_version }}
|
||||
|
||||
propagate:
|
||||
needs: [release-npm]
|
||||
if: ${{ contains(toJson(github.event.pull_request.labels.*.name), 'hxp-upstream') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- name: HxP upstream invoke
|
||||
uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7 # v4.0.0
|
||||
with:
|
||||
repo: Alfresco/hxp-frontend-apps
|
||||
ref: develop
|
||||
workflow: upstream-adf.yml
|
||||
token: ${{ secrets.ALFRESCO_BUILD_GH_TOKEN }}
|
||||
wait-for-completion: false
|
||||
inputs: >
|
||||
{
|
||||
"tag_version": "alpha"
|
||||
}
|
||||
|
||||
npm-check-bundle:
|
||||
needs: [release-npm]
|
||||
timeout-minutes: 15
|
||||
@@ -160,7 +142,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: ./.github/actions/npm-check-bundle
|
||||
|
||||
push-translation-keys-to-crowdin:
|
||||
@@ -174,16 +156,25 @@ jobs:
|
||||
actions: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Push Source Files to Crowdin
|
||||
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
|
||||
uses: crowdin/github-action@52aa776766211d83d975df51f3b9c53c2f8ba35f # v2.16.3
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_sources_args: --delete-obsolete
|
||||
env:
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TRANSLATIONS_TOKEN }}
|
||||
|
||||
pull-translation-keys-from-crowdin:
|
||||
needs: push-translation-keys-to-crowdin
|
||||
name: Run Crowdin pull pipeline for up-to-date sync
|
||||
uses: ./.github/workflows/pull-from-crowdin.yml
|
||||
secrets:
|
||||
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
CROWDIN_TRANSLATIONS_TOKEN: ${{ secrets.CROWDIN_TRANSLATIONS_TOKEN }}
|
||||
HXPS_GIT_COMMIT_SIGNING_PRIVATE_KEY: ${{ secrets.HXPS_GIT_COMMIT_SIGNING_PRIVATE_KEY }}
|
||||
|
||||
finalize:
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
name: Stale PR Cleanup
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
stale-pr-cleanup:
|
||||
uses: Alfresco/alfresco-build-tools/.github/workflows/stale-pr-cleanup.yml@10cea6c0b390c4f8af21d9dc1670d581bd10319f # v18.13.0
|
||||
@@ -0,0 +1,31 @@
|
||||
name: Supply Chain Review - PR Instructions
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
paths:
|
||||
- "package.json"
|
||||
- "pnpm-lock.yaml"
|
||||
- "**/package.json"
|
||||
- "pom.xml"
|
||||
- "**/pom.xml"
|
||||
|
||||
jobs:
|
||||
instructions:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/github-upsert-comment@10cea6c0b390c4f8af21d9dc1670d581bd10319f # v18.13.0
|
||||
with:
|
||||
comment-identifier: supply-chain-review-instructions
|
||||
comment-body: |
|
||||
## 🔒 Supply Chain Security
|
||||
|
||||
This PR modifies dependencies. To run a security analysis, comment:
|
||||
|
||||
```
|
||||
/supply-chain-review
|
||||
```
|
||||
|
||||
The analysis will check for vulnerabilities, typosquatting, maintainer takeovers, and other supply chain risks.
|
||||
+1586
File diff suppressed because one or more lines are too long
@@ -0,0 +1,355 @@
|
||||
---
|
||||
on:
|
||||
slash_command:
|
||||
name: supply-chain-review
|
||||
reaction: rocket
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
engine:
|
||||
id: copilot
|
||||
model: gpt-5.4-nano
|
||||
|
||||
tools:
|
||||
github:
|
||||
toolsets: [context, pull_requests, repos]
|
||||
|
||||
network:
|
||||
allowed:
|
||||
- defaults
|
||||
- node
|
||||
- java
|
||||
- api.osv.dev
|
||||
- api.scorecard.dev
|
||||
- search.maven.org
|
||||
|
||||
safe-outputs:
|
||||
add-comment:
|
||||
hide-older-comments: true
|
||||
add-labels:
|
||||
allowed: [security:low, security:medium, security:high]
|
||||
submit-pull-request-review:
|
||||
|
||||
source: Alfresco/alfresco-build-tools/.github/workflows/supply-chain-review.md@52467f0241079de71fe14591f97bdec7555ab545
|
||||
---
|
||||
|
||||
# Supply Chain Review
|
||||
|
||||
You are a supply chain security analyst reviewing a pull request for dependency changes.
|
||||
Your goal is to identify any dependency additions or upgrades and produce a thorough risk assessment for each change, covering known vulnerabilities, typosquatting, maintainer takeover, install script abuse, version anomalies, source code changes, and project health.
|
||||
|
||||
You are the primary and only analysis engine. There is no secondary check. Be thorough but calibrated: false positives erode trust, but missed threats have severe consequences.
|
||||
|
||||
## Step 1 — Identify Dependency Changes
|
||||
|
||||
Read the pull request diff and find all modified dependency files (`package.json`, `package-lock.json`, `pom.xml`, `yarn.lock`, `build.gradle`, etc.). For each changed dependency extract:
|
||||
|
||||
- Package name (including scope/groupId if applicable)
|
||||
- Ecosystem (`npm` or `maven`)
|
||||
- Old version (or mark as `NEW DEPENDENCY` if newly added)
|
||||
- New version
|
||||
|
||||
If no dependency files were changed, post a brief PR comment stating that no dependency changes were detected and no review is needed, then stop.
|
||||
|
||||
## Step 1b — Filter Internal Dependencies
|
||||
|
||||
Before collecting external data, identify and exclude internal/private dependencies that cannot be resolved by public APIs.
|
||||
|
||||
**Internal dependency namespaces (skip these):**
|
||||
|
||||
- **Maven**: Any dependency with a `groupId` starting with `com.hyland.`, `org.alfresco.`, or `org.activiti.`
|
||||
- **npm**: Any package under the `@hyland/`, `@hylandsoftware/`, or `@alfresco/` scopes
|
||||
|
||||
For each internal dependency found:
|
||||
|
||||
1. Remove it from the analysis pipeline — do NOT query OSV.dev, OpenSSF Scorecard, or registry APIs for these packages (they will fail or return irrelevant data).
|
||||
2. Record the package name (with `@` replaced by `(at)` for GitHub comment compatibility), ecosystem, old version, and new version in a separate "Internal Dependencies (Skipped)" list.
|
||||
3. Continue with Step 2 only for the remaining external/public dependencies.
|
||||
|
||||
If ALL changed dependencies are internal, skip Steps 2-4 and proceed directly to Step 5, posting a report that lists the internal dependencies and notes that no external supply chain analysis was performed.
|
||||
|
||||
## Step 2 — Collect Data for Each Dependency
|
||||
|
||||
For every changed dependency, gather the following data. Fetch all data sources in parallel where possible. If any request fails or returns no data, note it and continue — missing data alone is not proof of malice, but factor it into your confidence level.
|
||||
|
||||
### 2a. Known Vulnerabilities (OSV.dev)
|
||||
|
||||
Query the OSV.dev API for vulnerabilities affecting the **new** version:
|
||||
|
||||
- **npm**: `POST https://api.osv.dev/v1/query` with body `{"package":{"name":"<package-name>","ecosystem":"npm"},"version":"<new-version>"}`
|
||||
- **Maven**: `POST https://api.osv.dev/v1/query` with body `{"package":{"name":"<groupId>:<artifactId>","ecosystem":"Maven"},"version":"<new-version>"}`
|
||||
|
||||
Record all returned vulnerability IDs, severity ratings, and summaries. CRITICAL and HIGH severity CVEs in the new version are the most urgent signal.
|
||||
|
||||
### 2b. OpenSSF Scorecard
|
||||
|
||||
Fetch the project health score. First determine the source repository from the package metadata (see 2c), then query:
|
||||
|
||||
`GET https://api.scorecard.dev/projects/github.com/{owner}/{repo}`
|
||||
|
||||
Record the overall score (0-10) and individual check results. Pay special attention to: Maintained, Code-Review, Vulnerabilities, Branch-Protection, Signed-Releases. A score below 3 is very concerning; below 5 warrants caution. If the package has no linked source repository, the scorecard will be unavailable — this is itself a risk signal.
|
||||
|
||||
### 2c. Package Metadata (Registry)
|
||||
|
||||
**For npm packages**, fetch:
|
||||
|
||||
`GET https://registry.npmjs.org/<package-name>`
|
||||
|
||||
From the full registry document, extract for BOTH the old and new versions:
|
||||
|
||||
- `versions[<version>]._npmUser` — the publisher
|
||||
- `versions[<version>].maintainers` — the maintainer list
|
||||
- `versions[<version>].scripts` — lifecycle scripts (`preinstall`, `install`, `postinstall`)
|
||||
- `versions[<version>].dependencies` — runtime dependencies
|
||||
- `time[<version>]` — publish timestamp
|
||||
- `repository` — source repository URL
|
||||
|
||||
Also extract the `time` object to build a version history (last 10 versions with publish dates).
|
||||
|
||||
**For Maven packages**, fetch:
|
||||
|
||||
`GET https://central.sonatype.com/api/v1/search?q=g:<groupId>+AND+a:<artifactId>&sort=published&limit=10`
|
||||
|
||||
For POM details (build plugins, dependencies): `GET https://repo1.maven.org/maven2/<groupId-as-path>/<artifactId>/<version>/<artifactId>-<version>.pom`
|
||||
|
||||
### 2d. Source Code Diff and Release Notes
|
||||
|
||||
Use the PR diff itself to review the actual file changes for dependency manifest files. Additionally, if a source repository is identified (from 2c), fetch release notes and compare tags:
|
||||
|
||||
- Release notes: `GET https://api.github.com/repos/{owner}/{repo}/releases/tags/v<new-version>` (try with and without the `v` prefix)
|
||||
- For a code-level diff between old and new versions: `GET https://api.github.com/repos/{owner}/{repo}/compare/v<old-version>...v<new-version>` (try with and without the `v` prefix)
|
||||
|
||||
## Step 3 — Analyze Against Threat Taxonomy
|
||||
|
||||
Evaluate each dependency against ALL of the following threat categories. Not every category applies to every package — use judgment.
|
||||
|
||||
### 3a. Known Vulnerabilities
|
||||
|
||||
Assess the severity and exploitability of any CVEs or advisories returned from OSV.dev. CRITICAL and HIGH severity vulnerabilities in the new version are the most urgent signal. Also check whether the upgrade itself fixes known vulnerabilities in the old version (a positive signal).
|
||||
|
||||
### 3b. Typosquatting / Name Confusion
|
||||
|
||||
Determine if the package name could be a typosquatting attempt targeting a well-known package. Consider:
|
||||
|
||||
- Levenshtein distance to popular packages (e.g., `lodas` vs `lodash`)
|
||||
- Dash/underscore/separator swaps (e.g., `my_package` vs `my-package`)
|
||||
- Suffix variants (e.g., `express-js`, `express.js`)
|
||||
- Scope squatting for npm (e.g., `@attacker/lodash` vs `lodash`)
|
||||
- GroupId squatting for Maven (e.g., `org.apach.commons` vs `org.apache.commons`)
|
||||
|
||||
Use your knowledge of the ecosystem to identify plausible targets. Reason from your training data about popular packages.
|
||||
|
||||
### 3c. Maintainer Takeover
|
||||
|
||||
Compare the publisher and maintainer metadata between the old and new versions. Red flags:
|
||||
|
||||
- Publisher changed between versions (different `_npmUser`)
|
||||
- Old maintainers removed and replaced
|
||||
- New publisher has no prior history with the package
|
||||
- Classic pattern: publisher change + maintainer removal (like the event-stream incident)
|
||||
|
||||
### 3d. Install Script Abuse
|
||||
|
||||
**For npm**: Analyze lifecycle scripts (`preinstall`, `install`, `postinstall`) from the registry metadata. Red flags:
|
||||
|
||||
- Scripts that download and execute remote code (`curl`, `wget`, `http://`)
|
||||
- `eval()`, `Function()`, `child_process` usage
|
||||
- Environment variable access (`process.env`) for credential theft
|
||||
- Base64/hex decoding of payloads
|
||||
- Access to sensitive paths (`~/.ssh`, `~/.aws`, `~/.npmrc`, `/etc/passwd`)
|
||||
- Network calls (`dns.lookup`, `net.connect`) for exfiltration
|
||||
- Scripts that are NEW in this version (not present in the old version) are especially suspicious
|
||||
|
||||
**For Maven**: Look for dangerous build plugins in POM changes:
|
||||
|
||||
- `exec-maven-plugin`, `maven-antrun-plugin` with `<exec>`
|
||||
- `<extensions>true</extensions>` on untrusted plugins
|
||||
- Download plugins, Groovy/script plugins
|
||||
|
||||
### 3e. Version Anomalies
|
||||
|
||||
Analyze the version change pattern and history from the registry metadata:
|
||||
|
||||
- Major version jumps (skipping 1+ major versions)
|
||||
- Version downgrade (new version < old version)
|
||||
- Stable to prerelease transition
|
||||
- Very recent publish (less than 48 hours old) — could indicate a rush to distribute malicious code
|
||||
- Rapid successive publishes (many versions in a short window)
|
||||
- Long dormancy then sudden publish (more than 1 year gap) — may indicate account takeover
|
||||
|
||||
### 3f. Source Code Changes
|
||||
|
||||
If source diffs are available (from the GitHub compare API or the PR diff itself), analyze for:
|
||||
|
||||
- Obfuscated code (minified without source maps, hex/unicode escapes, string concatenation to hide function names)
|
||||
- Data exfiltration (network calls sending `process.env`, API keys, tokens to external endpoints)
|
||||
- Filesystem access outside the package directory
|
||||
- Dynamic code execution (`eval()`, `Function()`, `vm.runInNewContext`, `WebAssembly.instantiate`)
|
||||
- Encoded payloads (Base64/hex decoded and executed at runtime)
|
||||
- Inconsistency between release notes and actual changes (changelog says "bug fix" but diff adds network calls)
|
||||
- Cryptocurrency mining patterns
|
||||
- Suspicious new transitive dependencies
|
||||
|
||||
### 3g. Project Health
|
||||
|
||||
Interpret the OpenSSF Scorecard data:
|
||||
|
||||
- Overall score below 3/10 is very concerning
|
||||
- Score below 5/10 warrants caution
|
||||
- Pay attention to specific failing checks: Maintained, Code-Review, Vulnerabilities, Branch-Protection, Signed-Releases
|
||||
- Missing scorecard data (no source repo linked) is itself a risk signal
|
||||
|
||||
### 3h. Missing Source Repository
|
||||
|
||||
A package with no linked source repository prevents code audit and is a risk signal, especially combined with other concerns.
|
||||
|
||||
### 3i. Tag Poisoning / Build Provenance
|
||||
|
||||
Evaluate whether the published artifact can be traced back to a verified source commit. This category covers attacks where a legitimate-looking version tag is manipulated to distribute malicious code.
|
||||
|
||||
#### Tag-to-Registry Provenance Mismatch
|
||||
|
||||
Check whether the git tag for the new version corresponds to the published artifact:
|
||||
|
||||
- Compare the tag commit date with the registry publish timestamp. A discrepancy of more than a few hours (allowing for CI/CD pipeline time) is suspicious.
|
||||
- If the source diff between the tag and the previous tag includes changes not documented in release notes, flag as suspicious.
|
||||
|
||||
#### Mutable/Moved Tags
|
||||
|
||||
Check if the tag appears to have been recreated:
|
||||
|
||||
- Use `GET https://api.github.com/repos/{owner}/{repo}/git/refs/tags/{tag}` to get the tag reference.
|
||||
- For annotated tags, use `GET https://api.github.com/repos/{owner}/{repo}/git/tags/{sha}` to check the tag object and its `tagger.date`.
|
||||
- If the tag creation date is significantly newer than the commit it points to (e.g., more than 7 days), this may indicate the tag was deleted and recreated pointing to a different commit.
|
||||
|
||||
#### Unsigned Tags
|
||||
|
||||
Determine tag type and signing status:
|
||||
|
||||
- **Annotated + signed tags** (GPG or SSH signature present) — strongest integrity signal.
|
||||
- **Annotated but unsigned tags** — moderate integrity; the tag is immutable but unverified.
|
||||
- **Lightweight tags** — weakest integrity; easily moved without trace. Flag as a risk signal for high-profile or security-critical packages.
|
||||
|
||||
For the tag object, check the `verification` field in the GitHub API response for signature status.
|
||||
|
||||
#### Build Provenance / Attestation
|
||||
|
||||
Check for SLSA provenance attestations or Sigstore signatures:
|
||||
|
||||
**For npm packages**: Query `GET https://registry.npmjs.org/-/npm/v1/attestations/<package-name>@<new-version>`. If attestations are present, verify:
|
||||
|
||||
- The `predicateType` matches a known SLSA provenance type
|
||||
- The `subject` digest matches the published package tarball
|
||||
- The build was performed by a trusted CI system (e.g., GitHub Actions)
|
||||
|
||||
**For Maven packages**: Check if Sigstore `.sigstore` bundle files exist alongside the artifact at:
|
||||
`GET https://repo1.maven.org/maven2/<groupId-as-path>/<artifactId>/<version>/<artifactId>-<version>.jar.sigstore`
|
||||
|
||||
The absence of provenance attestations on a high-profile package (>1000 weekly downloads for npm, or widely used in the ecosystem) is a moderate risk signal. Packages that previously published with provenance but stopped doing so are especially suspicious.
|
||||
|
||||
#### Tag Mimicry on Forks
|
||||
|
||||
Verify that the source repository URL in registry metadata points to the canonical repository:
|
||||
|
||||
- Cross-reference the `repository` field from package metadata (Step 2c) with the GitHub API response.
|
||||
- If the repository URL points to a fork rather than the original project, flag as HIGH risk — this may indicate a hijacked tag on a lookalike fork.
|
||||
- Check that the repository owner matches known maintainers of the package.
|
||||
|
||||
## Step 4 — Score and Classify Risk
|
||||
|
||||
Assign a risk score (0-100) to each dependency using these guidelines:
|
||||
|
||||
| Priority | Signal | Typical Impact |
|
||||
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
|
||||
| Highest | Known CRITICAL/HIGH CVEs in new version, confirmed typosquatting, malicious code in diff, build provenance mismatch (tag points to different code than published artifact), tag mimicry on fork | 60+ points |
|
||||
| High | Maintainer takeover pattern (publisher changed + old maintainers removed), dangerous install scripts, known compromised package, moved/recreated tag with different commit, provenance attestations removed from package that previously had them | 20-40 points |
|
||||
| Medium | Low OpenSSF Scorecard (< 3), publisher changed (without full takeover), new install scripts, very recent publish (< 48h), obfuscated code in diff, unsigned lightweight tags on security-critical packages, absence of provenance on high-profile packages | 10-20 points |
|
||||
| Lower | Scorecard 3-5, version anomalies, missing source repository, long dormancy, rapid publishes, tag date slightly newer than commit (within 7 days), annotated but unsigned tags | 5-10 points |
|
||||
|
||||
These are guidelines, not rigid formulas. Use judgment to combine signals — multiple medium signals can compound into a high-risk assessment.
|
||||
|
||||
**Risk level thresholds**: 0-20 = LOW, 21-50 = MEDIUM, 51-80 = HIGH, 81-100 = CRITICAL.
|
||||
|
||||
If no suspicious patterns are found, assign a score of 0-10 and risk level LOW. Most legitimate upgrades should score LOW.
|
||||
|
||||
## Step 5 — Post Findings as PR Comment
|
||||
|
||||
Post a structured report in the following format.
|
||||
|
||||
**CRITICAL: Sanitize all `@` symbols before posting**
|
||||
|
||||
GitHub enforces a maximum of 10 mentions per comment. Package names containing `@` (like `@hyland/core`, `@alfresco/js-api`) are interpreted as user/team mentions and trigger this limit, causing comment post failures.
|
||||
|
||||
**Before generating the comment text**:
|
||||
|
||||
1. Replace **every** `@` symbol in package names with `(at)` — e.g., `@hyland/core` → `(at)hyland/core`
|
||||
2. Apply this transformation to ALL occurrences: table cells, headings, inline code blocks, findings sections, reason columns
|
||||
3. This applies to both external and internal dependencies
|
||||
4. Do NOT skip this step — even if only a few packages are affected, GitHub counts all `@` symbols
|
||||
|
||||
```txt
|
||||
## Supply Chain Security Review
|
||||
|
||||
| Package | Ecosystem | Old Version | New Version | Risk Score | Risk Level |
|
||||
|---------|-----------|-------------|-------------|------------|------------|
|
||||
| example | npm | 1.0.0 | 2.0.0 | 5 | LOW |
|
||||
|
||||
### Internal Dependencies (Skipped)
|
||||
|
||||
| Package | Ecosystem | Old Version | New Version | Reason |
|
||||
|-------------------|-----------|-------------|-------------|---------------------------------|
|
||||
| (at)hyland/core | npm | 3.1.0 | 3.2.0 | Internal ((at)hyland/* scope) |
|
||||
|
||||
_These dependencies are internal packages not available on public registries. External API checks were skipped._
|
||||
|
||||
### Findings
|
||||
|
||||
#### `<package-name-sanitized>` (<old-version> -> <new-version>) — <RISK_LEVEL>
|
||||
|
||||
**Risk Score**: <score>/100
|
||||
|
||||
<If findings exist, list each one:>
|
||||
|
||||
**<Category>** (<severity>) — <title>
|
||||
<detailed explanation with specific evidence>
|
||||
|
||||
<If no findings:>
|
||||
No suspicious patterns detected. Routine upgrade.
|
||||
|
||||
---
|
||||
|
||||
### Data Collection Notes
|
||||
|
||||
<List any APIs that were unavailable or returned errors, so reviewers know what was and wasn't checked.>
|
||||
|
||||
---
|
||||
|
||||
### Overall Risk: <highest risk level across all dependencies>
|
||||
|
||||
**Recommendation**: <approve|review|block>
|
||||
- **approve**: LOW risk, routine upgrade, no concerns found
|
||||
- **review**: MEDIUM risk, a human should examine specific findings before merging
|
||||
- **block**: HIGH/CRITICAL risk, should not be merged without security team review
|
||||
```
|
||||
|
||||
## Step 6 — Apply Label and Review Status
|
||||
|
||||
- Apply a label to the PR based on the highest risk level found:
|
||||
- `security:low` for LOW risk
|
||||
- `security:medium` for MEDIUM risk
|
||||
- `security:high` for HIGH or CRITICAL risk
|
||||
- If the highest risk level is HIGH or CRITICAL, submit a pull request review requesting changes, with a summary of the critical findings.
|
||||
- If the risk is MEDIUM, submit a pull request review as a comment, noting that human review is recommended.
|
||||
- If the risk is LOW, do not submit a review — the PR comment is sufficient.
|
||||
|
||||
## Important Guidelines
|
||||
|
||||
- **Never approve or merge the PR** — all actions are advisory or blocking only. A human always makes the merge decision.
|
||||
- Be specific in findings — cite exact data (vulnerability ID, maintainer name, script content, file path, API response) rather than vague warnings.
|
||||
- For Maven packages, adapt npm-specific checks appropriately (e.g., install scripts become build plugin analysis, maintainer metadata may be limited).
|
||||
- When a package is a NEW dependency (no old version), pay extra attention to project health, name legitimacy, and install scripts since there is no historical baseline to compare against.
|
||||
- If data collection fails for all external APIs, still analyze the PR diff directly and provide the best assessment you can with available information, noting the limitations clearly.
|
||||
- For tag poisoning checks, not all packages will have provenance attestations — this is still an emerging practice. Weight the absence of attestations proportionally to the package's profile and criticality. Do not flag low-download utility packages for missing provenance.
|
||||
- When checking tag dates, allow for reasonable CI/CD pipeline delays (up to a few hours between tag push and publish). Only flag significant discrepancies (days or weeks).
|
||||
@@ -0,0 +1,81 @@
|
||||
name: "Unit Tests Workflow"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
base_ref:
|
||||
description: 'Base branch for affected calculation'
|
||||
required: false
|
||||
type: string
|
||||
default: 'develop'
|
||||
|
||||
jobs:
|
||||
generate-affected-matrix:
|
||||
name: "Generate affected matrix"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
unitMatrix: ${{ steps.set-matrix.outputs.unitMatrix }}
|
||||
hasProjects: ${{ steps.set-matrix.outputs.hasProjects }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup environment
|
||||
id: setup-env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
cache-suffix: test-matrix
|
||||
- name: Generate affected projects matrix
|
||||
id: set-matrix
|
||||
env:
|
||||
BASE_REF: ${{ inputs.base_ref }}
|
||||
run: |
|
||||
echo "Base ref is $BASE_REF"
|
||||
AFFECTED_UNIT=$(pnpm nx show projects --affected --target=test --base=origin/$BASE_REF --head=HEAD --select=projects --plain --exclude=cli,stories,eslint-angular)
|
||||
echo "Affected projects for UNIT: $AFFECTED_UNIT"
|
||||
|
||||
if [ -z "$AFFECTED_UNIT" ]; then
|
||||
echo "No affected projects found"
|
||||
echo "hasProjects=false" >> $GITHUB_OUTPUT
|
||||
echo "unitMatrix=[]" >> $GITHUB_OUTPUT
|
||||
else
|
||||
UNIT_MATRIX_JSON=$(echo "$AFFECTED_UNIT" | xargs -n1 | jq -R -s -c 'split("\n") | map(select(length > 0)) | map({ "project": . })')
|
||||
echo "Matrix UNIT: $UNIT_MATRIX_JSON"
|
||||
echo "hasProjects=true" >> $GITHUB_OUTPUT
|
||||
echo "unitMatrix=$UNIT_MATRIX_JSON" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Save nx cache
|
||||
if: ${{ success() }}
|
||||
uses: ./.github/actions/save-nx-cache
|
||||
with:
|
||||
cache-suffix: test-matrix
|
||||
|
||||
unit-tests:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
needs: generate-affected-matrix
|
||||
if: ${{ needs.generate-affected-matrix.outputs.hasProjects == 'true' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.generate-affected-matrix.outputs.unitMatrix) }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Setup environment
|
||||
id: setup-env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
cache-suffix: test-${{ matrix.project }}
|
||||
full-setup: 'false'
|
||||
- name: Run unit tests for ${{ matrix.project }}
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
run: |
|
||||
xvfb-run --auto-servernum pnpm nx run ${{ matrix.project }}:test
|
||||
- name: Save nx cache
|
||||
if: ${{ success() }}
|
||||
uses: ./.github/actions/save-nx-cache
|
||||
with:
|
||||
cache-suffix: test-${{ matrix.project }}
|
||||
+1
-1
@@ -8,7 +8,6 @@ bundles
|
||||
dist
|
||||
tmp
|
||||
temp
|
||||
*.npmrc
|
||||
.history
|
||||
.ng_pkg_build/
|
||||
coverage/
|
||||
@@ -24,3 +23,4 @@ nxcache
|
||||
.husky
|
||||
.cursor/rules/nx-rules.mdc
|
||||
.github/instructions/nx.instructions.md
|
||||
lib/eslint-angular/dist/
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
export NODE_OPTIONS=--max_old_space_size=8192
|
||||
|
||||
lint-staged
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Fail on high severity vulnerabilities during audit
|
||||
audit-level=high
|
||||
|
||||
# Use exact versions to prevent unexpected updates
|
||||
save-exact=true
|
||||
@@ -11,6 +11,9 @@ const config: StorybookConfig = {
|
||||
stories: ['lib/**/*.stories.ts'],
|
||||
features: {
|
||||
backgrounds: false
|
||||
},
|
||||
core: {
|
||||
disableTelemetry: true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
{
|
||||
"extends": ["stylelint-config-standard-scss"],
|
||||
"rules": {
|
||||
"custom-property-pattern": [
|
||||
"^(mat-sys|mdc)",
|
||||
{
|
||||
"message": "Use only Angular Material system variables (--mat-sys-*, --mdc-*)"
|
||||
}
|
||||
],
|
||||
"color-function-notation": "legacy",
|
||||
"alpha-value-notation": "number",
|
||||
"color-no-invalid-hex": true,
|
||||
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"meterian.meterian-heidi"
|
||||
]
|
||||
}
|
||||
Vendored
+2
-4
@@ -20,10 +20,8 @@
|
||||
"stylelint.enable": true,
|
||||
"css.validate": false,
|
||||
"scss.validate": false,
|
||||
"stylelint.config": {
|
||||
"extends": "./.stylelintrc.json"
|
||||
},
|
||||
"stylelint.configFile": ".stylelintrc.json",
|
||||
"stylelint.configFile": "${workspaceFolder}/.stylelintrc.json",
|
||||
"stylelint.configBasedir": "${workspaceFolder}",
|
||||
"stylelint.validate": [
|
||||
"css",
|
||||
"less",
|
||||
|
||||
@@ -21,6 +21,29 @@ for full details on what you may need to install before using ADF.
|
||||
- [Node Version Manager](docs/tutorials/nvm.md)
|
||||
- [CORS guide](ALFRESCOCORS.md)
|
||||
|
||||
## Installation
|
||||
|
||||
This project uses **pnpm** for package management with built-in supply chain attack protection.
|
||||
|
||||
```bash
|
||||
pnpm install # install all packages
|
||||
pnpm run add <package> # add a new package (with security check)
|
||||
```
|
||||
|
||||
### Supply Chain Security
|
||||
|
||||
**Layer 1: pnpm script blocking**
|
||||
- All lifecycle scripts (postinstall, etc.) are blocked by default
|
||||
- Only trusted packages in `pnpm-workspace.yaml` can run scripts
|
||||
- Protects during `pnpm install` and `pnpm add`
|
||||
|
||||
**Layer 2: Security database check**
|
||||
- `pnpm run add` checks packages against OSV and GitHub Advisory databases BEFORE installing
|
||||
- Pre-commit hook blocks commits containing known malicious packages
|
||||
|
||||
**Layer 3: npm blocked**
|
||||
- Running `npm install` will fail - enforces pnpm usage
|
||||
|
||||
## Components
|
||||
|
||||
You can find the sources for all ADF components in the [`lib`](/lib) folder.
|
||||
|
||||
+4
-2
@@ -145,7 +145,8 @@
|
||||
"Whitespaces",
|
||||
"xdescribe",
|
||||
"xsrf",
|
||||
"zestiria"
|
||||
"zestiria",
|
||||
"webscript"
|
||||
],
|
||||
"dictionaries": [
|
||||
"html",
|
||||
@@ -156,7 +157,8 @@
|
||||
],
|
||||
"ignorePaths": [
|
||||
"lib/{content-services,core,extensions,insights,process-services}/**/*.spec.ts",
|
||||
"lib/{content-services,core,extensions,insights,process-services}/**/*.mock.ts"
|
||||
"lib/{content-services,core,extensions,insights,process-services}/**/*.mock.ts",
|
||||
"**/*.stories.ts"
|
||||
],
|
||||
"ignoreRegExpList": [
|
||||
"(\"|'|`)((?:\\\\1|(?:(?!\\1).))*)\\1"
|
||||
|
||||
@@ -118,7 +118,6 @@ A collection of Angular components for generic use.
|
||||
| [Sidebar action menu component](core/components/sidebar-action-menu.component.md) | Displays a sidebar-action menu information panel. | [Source](../lib/core/src/lib/layout/components/sidebar-action/sidebar-action-menu.component.ts) |
|
||||
| [Sidenav Layout component](core/components/sidenav-layout.component.md) | Displays the standard three-region ADF application layout. | [Source](../lib/core/src/lib/layout/components/sidenav-layout/sidenav-layout.component.ts) |
|
||||
| [Snackbar Content Component](core/components/snackbar-content.component.md) | Custom content for Snackbar which allows use icon as action. | [Source](../lib/core/src/lib/snackbar-content/snackbar-content.component.ts) |
|
||||
| [Sorting Picker Component](core/components/sorting-picker.component.md) | Selects from a set of predefined sorting definitions and directions. | [Source](../lib/core/src/lib/sorting-picker/sorting-picker.component.ts) |
|
||||
| [Start Form component](core/components/start-form.component.md) | Displays the Start Form for a process. | [Source](../lib/process-services/src/lib/form/start-form/start-form.component.ts) |
|
||||
| [Text Mask directive](core/components/text-mask.component.md) | Implements text field input masks. | [Source](../lib/core/src/lib/form/components/widgets/text/text-mask.component.ts) |
|
||||
| [Toolbar Divider Component](core/components/toolbar-divider.component.md) | Divides groups of elements in a Toolbar with a visual separator. | [Source](../lib/core/src/lib/toolbar/toolbar-divider.component.ts) |
|
||||
@@ -293,7 +292,6 @@ for more information about installing and using the source code.
|
||||
| [Search number range component](content-services/components/search-number-range.component.md) | Implements a number range widget for the Search Filter component. | [Source](../lib/content-services/src/lib/search/components/search-number-range/search-number-range.component.ts) |
|
||||
| [Search radio component](content-services/components/search-radio.component.md) | Implements a radio button list widget for the Search Filter component. | [Source](../lib/content-services/src/lib/search/components/search-radio/search-radio.component.ts) |
|
||||
| [Search slider component](content-services/components/search-slider.component.md) | Implements a numeric slider widget for the Search Filter component. | [Source](../lib/content-services/src/lib/search/components/search-slider/search-slider.component.ts) |
|
||||
| [Search Sorting Picker Component](content-services/components/search-sorting-picker.component.md) | Provides an ability to select one of the predefined sorting definitions for search results: | [Source](../lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.ts) |
|
||||
| [Search text component](content-services/components/search-text.component.md) | Implements a text input widget for the Search Filter component. | [Source](../lib/content-services/src/lib/search/components/search-text/search-text.component.ts) |
|
||||
| [Search component](content-services/components/search.component.md) | Searches items for supplied search terms. | [Source](../lib/content-services/src/lib/search/components/search.component.ts) |
|
||||
| [Sites Dropdown component](content-services/components/sites-dropdown.component.md) | Displays a dropdown menu to show and interact with the sites of the current user. | [Source](../lib/content-services/src/lib/content-node-selector/site-dropdown/sites-dropdown.component.ts) |
|
||||
@@ -325,7 +323,6 @@ for more information about installing and using the source code.
|
||||
| [Node Favorite directive](content-services/directives/node-favorite.directive.md) | Selectively toggles nodes as favorites. | [Source](../lib/content-services/src/lib/directives/node-favorite.directive.ts) |
|
||||
| [Node Lock directive](content-services/directives/node-lock.directive.md) | Locks or unlocks a node. | [Source](../lib/content-services/src/lib/directives/node-lock.directive.ts) |
|
||||
| [Node Restore directive](content-services/directives/node-restore.directive.md) | Restores deleted nodes to their original location. | [Source](../lib/content-services/src/lib/directives/node-restore.directive.ts) |
|
||||
| [Toggle Icon directive](content-services/directives/toggle-icon.directive.md) | Toggle icon on mouse or keyboard event for a selectable element. | [Source](../lib/content-services/src/lib/upload/directives/toggle-icon.directive.ts) |
|
||||
| [Version Compatibility Directive](content-services/directives/version-compatibility.directive.md) | Enables/disables components based on ACS version in use. | [Source](../lib/content-services/src/lib/version-compatibility/version-compatibility.directive.ts) |
|
||||
|
||||
### Dialogs
|
||||
@@ -350,12 +347,6 @@ for more information about installing and using the source code.
|
||||
| [Permission Style model](content-services/models/permissions-style.model.md) | Sets custom CSS styles for rows of a Document List according to the item's permissions. | [Source](../lib/content-services/src/lib/document-list/models/permissions-style.model.ts) |
|
||||
| [Row Filter Model](content-services/models/row-filter.model.md) | Defines the Row Filter function used by the Document List Component. | [Source](../lib/content-services/document-list/data/row-filter.model.ts) |
|
||||
|
||||
### Pipes
|
||||
|
||||
| Name | Description | Source link |
|
||||
| ---- | ----------- | ----------- |
|
||||
| [File upload error pipe](content-services/pipes/file-upload-error.pipe.md) | Converts an upload error code to an error message. | [Source](../lib/content-services/src/lib/upload/pipes/file-upload-error.pipe.ts) |
|
||||
|
||||
### Services
|
||||
|
||||
| Name | Description | Source link |
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# CI Commands and Labels
|
||||
|
||||
Reference for flags and labels that control CI behavior on pull requests.
|
||||
|
||||
## PR Title Flags
|
||||
|
||||
Include these flags anywhere in the **PR title** to modify CI behavior.
|
||||
|
||||
| Flag | Effect |
|
||||
|------|--------|
|
||||
| `[ci:force]` | Skips the PR approval check, allowing the full pipeline to run without an approved review. Useful for testing CI changes on draft PRs. |
|
||||
|
||||
Example: `[AAE-12345] Fix pagination component [ci:force]`
|
||||
|
||||
## Commit Message Flags
|
||||
|
||||
Include these flags in a **commit message** to modify CI behavior.
|
||||
|
||||
| Flag | Effect |
|
||||
|------|--------|
|
||||
| `[ci:force]` | Skips the PR approval check (same as PR title flag). |
|
||||
| `[affected:*]` | Forces all Nx targets to run against all projects, ignoring the affected calculation. Equivalent to `--all`. |
|
||||
|
||||
## PR Labels
|
||||
|
||||
Labels applied to the PR that affect CI behavior.
|
||||
|
||||
| Label | Effect |
|
||||
|-------|--------|
|
||||
| `do not merge` | Blocks the PR from passing the finalize check. CI will fail until the label is removed. |
|
||||
| `next version` | Same as above - blocks the PR from merging. Used to hold PRs for the next release cycle. |
|
||||
|
||||
## Automatic Skip Conditions
|
||||
|
||||
The approval check is automatically skipped for:
|
||||
|
||||
- **Scheduled runs** (`schedule` event)
|
||||
- **Workflow dispatch** (`workflow_dispatch` event)
|
||||
- **Dependabot PRs** (actor is `dependabot[bot]`)
|
||||
- **Build bot PRs** (actor is `alfresco-build`)
|
||||
- **Devel flag** (when `devel: true` is passed via `workflow_call`)
|
||||
|
||||
## Path-Based Filtering
|
||||
|
||||
PRs that only modify non-code files skip the build, test, and lint jobs entirely. Files considered non-code:
|
||||
|
||||
- Markdown files (`*.md`)
|
||||
- Documentation (`docs/`)
|
||||
- `LICENSE`, `NOTICE`
|
||||
- `.editorconfig`, `.gitattributes`
|
||||
- `.github/CODEOWNERS`, `.github/dependabot.yml`
|
||||
|
||||
## PR Size Check
|
||||
|
||||
Every PR gets an automatic size classification displayed in the job summary:
|
||||
|
||||
| Size | Criteria |
|
||||
|------|----------|
|
||||
| **S** | < 200 total changes and < 10 files |
|
||||
| **M** | 200-500 total changes or 10-20 files |
|
||||
| **L** | 500-1000 total changes or 20-30 files |
|
||||
| **XL** | > 1000 total changes or > 30 files (warning annotation added) |
|
||||
@@ -92,8 +92,8 @@ See the [Custom layout](#custom-layout) section for full details of all availabl
|
||||
| showRightSidebar | `boolean` | false | Toggles right sidebar visibility. Requires `allowRightSidebar` to be set to `true`. |
|
||||
| showToolbar | `boolean` | true | Hide or show the toolbar |
|
||||
| showViewer | `boolean` | true | Hide or show the viewer |
|
||||
| sidebarLeftTemplate | `TemplateRef<any>` | null | The template for the left sidebar. The template context contains the loaded node data. |
|
||||
| sidebarRightTemplate | `TemplateRef<any>` | null | The template for the right sidebar. The template context contains the loaded node data. |
|
||||
| sidebarLeftTemplate | `TemplateRef<unknown>` | null | The template for the left sidebar. The template context contains the loaded node data. |
|
||||
| sidebarRightTemplate | `TemplateRef<unknown>` | null | The template for the right sidebar. The template context contains the loaded node data. |
|
||||
| versionId | `string` | null | Version Id of the file to load. |
|
||||
|
||||
### Events
|
||||
|
||||
@@ -40,4 +40,3 @@ This component should be used in combination with the
|
||||
|
||||
- [Upload button component](upload-button.component.md)
|
||||
- [Upload drag area component](upload-drag-area.component.md)
|
||||
- [File upload error pipe](../pipes/file-upload-error.pipe.md)
|
||||
|
||||
@@ -33,7 +33,6 @@ to build and execute the query.
|
||||
- [Search Query Builder service](../services/search-query-builder.service.md)
|
||||
- [Search filter chips component](./search-filter-chips.component.md)
|
||||
- [Search Chip List Component](search-chip-list.component.md)
|
||||
- [Search Sorting Picker Component](search-sorting-picker.component.md)
|
||||
- [Search Widget Interface](../interfaces/search-widget.interface.md)
|
||||
- [Search check list component](search-check-list.component.md)
|
||||
- [Search date range tabbed component](search-date-range-tabbed.component.md)
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
Title: Search Sorting Picker Component
|
||||
Added: v2.3.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# [Search Sorting Picker Component](../../../lib/content-services/src/lib/search/components/search-sorting-picker/search-sorting-picker.component.ts "Defined in search-sorting-picker.component.ts")
|
||||
|
||||
Provides an ability to select one of the predefined sorting definitions for search results:
|
||||
|
||||
```html
|
||||
<adf-search-sorting-picker></adf-search-sorting-picker>
|
||||
<adf-search-filter></adf-search-filter>
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Search Configuration Guide](../../user-guide/search-configuration-guide.md)
|
||||
- [Search filter chips component](search-filter-chips.component.md)
|
||||
@@ -18,7 +18,6 @@ Shows the nodes in tree structure, each node containing children is collapsible/
|
||||
[displayName]="'Tree display name'"
|
||||
[loadMoreSuffix]="'subnodes'"
|
||||
[emptyContentTemplate]="emptyContentTemplate"
|
||||
[nodeActionsMenuTemplate]="nodeActionsMenuTemplate"
|
||||
(paginationChanged)="onPaginationChanged($event)">
|
||||
</adf-tree>
|
||||
```
|
||||
@@ -34,7 +33,6 @@ Shows the nodes in tree structure, each node containing children is collapsible/
|
||||
| emptyContentTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | | [TemplateRef](https://angular.io/api/core/TemplateRef) to provide empty template when no nodes are loaded |
|
||||
| expandIcon | `string` | "chevron_right" | Icon shown when node has children and is collapsed. By default set to chevron_right |
|
||||
| loadMoreSuffix | `string` | | Load more suffix for load more button |
|
||||
| nodeActionsMenuTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | | [TemplateRef](https://angular.io/api/core/TemplateRef) to provide context menu items for context menu displayed on each row |
|
||||
| selectableNodes | `boolean` | false | Variable defining if tree nodes should be selectable. By default set to false |
|
||||
| stickyHeader | `boolean` | false | Variable defining if tree header should be sticky. By default set to false |
|
||||
| contextMenuOptions | `any[]` | | Array of context menu options which should be displayed for each row. |
|
||||
@@ -88,7 +86,6 @@ First step is to provide necessary input value.
|
||||
[loadMoreSuffix]="'subnodes'"
|
||||
[selectableNodes]="true"
|
||||
[emptyContentTemplate]="emptyContentTemplate"
|
||||
[nodeActionsMenuTemplate]="nodeActionsMenuTemplate"
|
||||
(paginationChanged)="onPaginationChanged($event)">
|
||||
</adf-tree>
|
||||
```
|
||||
|
||||
@@ -86,4 +86,3 @@ export class MyComponent {
|
||||
## See also
|
||||
|
||||
- [Upload Version Button component](upload-version-button.component.md)
|
||||
- [File upload error pipe](../pipes/file-upload-error.pipe.md)
|
||||
|
||||
@@ -141,4 +141,3 @@ This could be either a selection of 2 or more files, or a folder with multiple e
|
||||
|
||||
- [File uploading dialog component](file-uploading-dialog.component.md)
|
||||
- [Upload button component](upload-button.component.md)
|
||||
- [File upload error pipe](../pipes/file-upload-error.pipe.md)
|
||||
|
||||
@@ -13,7 +13,6 @@ Update the current node by adding/removing the inherited permissions.
|
||||
|
||||
```html
|
||||
<button mat-raised-button
|
||||
color="primary"
|
||||
adf-inherit-permission [nodeId]="nodeId"
|
||||
(updated)="onUpdatedPermissions($node)">PERMISSION</button>
|
||||
```
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
Title: Toggle Icon directive
|
||||
Added: v2.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2019-04-09
|
||||
---
|
||||
|
||||
# [Toggle Icon directive](../../../lib/content-services/src/lib/upload/directives/toggle-icon.directive.ts "Defined in toggle-icon.directive.ts")
|
||||
|
||||
Toggle icon on mouse or keyboard event for a selectable element.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```html
|
||||
<button mat-icon-button adf-toggle-icon #toggle="toggleIcon">
|
||||
<mat-icon *ngIf="!toggle.isToggled">
|
||||
check_circle
|
||||
</mat-icon>
|
||||
|
||||
<mat-icon *ngIf="toggle.isToggled">
|
||||
remove_circle
|
||||
</mat-icon>
|
||||
<button></button>
|
||||
</button>
|
||||
```
|
||||
|
||||
## Class members
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
Title: File upload error pipe
|
||||
Added: v3.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2019-01-17
|
||||
---
|
||||
|
||||
# [File upload error pipe](../../../lib/content-services/src/lib/upload/pipes/file-upload-error.pipe.ts "Defined in file-upload-error.pipe.ts")
|
||||
|
||||
Converts an upload error code to an error message.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
<!-- {% raw %} -->
|
||||
|
||||
```HTML
|
||||
<div>
|
||||
Upload failed: {{ errorCode | adfFileUploadError }}
|
||||
</div>
|
||||
```
|
||||
|
||||
<!-- {% endraw %} -->
|
||||
|
||||
## Details
|
||||
|
||||
The pipe takes an upload error code (eg, from the `error` event of one of the
|
||||
upload components) and converts it to a human-readable message. The message is
|
||||
automatically translated to the user's chosen language.
|
||||
|
||||
## See also
|
||||
|
||||
- [File uploading dialog component](../components/file-uploading-dialog.component.md)
|
||||
- [Upload drag area component](../components/upload-drag-area.component.md)
|
||||
- [Upload button component](../components/upload-button.component.md)
|
||||
@@ -2,7 +2,7 @@
|
||||
Title: Document List service
|
||||
Added: v2.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2019-01-16
|
||||
Last reviewed: 2026-06-16
|
||||
---
|
||||
|
||||
# Document List Service
|
||||
@@ -21,10 +21,11 @@ import { DocumentListService } from '@alfresco/adf-core';
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Description |
|
||||
|-------------------|-------------------------------------------------|
|
||||
| `reload$` | Emits when the document list should be reloaded |
|
||||
| `resetSelection$` | Emits when the selection should be reset |
|
||||
| Name | Description |
|
||||
|-------------------|----------------------------------------------------------------------------------------------|
|
||||
| `reload$` | Emits when the document list should be reloaded. |
|
||||
| `resetSelection$` | Emits when the selection should be reset. |
|
||||
| `reloadSilently$` | Emits when the document list should be reloaded **without** resetting the current selection. |
|
||||
|
||||
### Methods
|
||||
|
||||
@@ -32,6 +33,8 @@ import { DocumentListService } from '@alfresco/adf-core';
|
||||
Reloads the document list.
|
||||
- **resetSelection**(): `void`<br/>
|
||||
Resets the selection.
|
||||
- **reloadSilently**(): `void`<br/>
|
||||
Reloads the document list **without** resetting the current selection.
|
||||
- **copyNode**(nodeId: `string`, targetParentId: `string`): `Observable<NodeEntry>`<br/>
|
||||
Copy a node to destination node
|
||||
- _nodeId:_ `string` - The id of the node to be copied
|
||||
|
||||
@@ -351,7 +351,6 @@ while the data for the table is loading:
|
||||
<!--Add your custom loading template here-->
|
||||
<mat-progress-spinner
|
||||
class="adf-document-list-loading-margin"
|
||||
[color]="'primary'"
|
||||
[mode]="'indeterminate'">
|
||||
</mat-progress-spinner>
|
||||
</ng-template>
|
||||
@@ -464,6 +463,8 @@ Learn more about styling your datatable: [Customizing the component's styles](#c
|
||||
|
||||
## Details
|
||||
|
||||
This component supports rows reordering via keyboard. To enable it first set `enableDragRows` to `true`, focus any selected row and use shift + ArrowUp/ArrowDown combination to reorder selected row.
|
||||
|
||||
### Supplying data for the table
|
||||
|
||||
The column layout and row data are supplied to the table using an object that implements the
|
||||
|
||||
@@ -14,9 +14,8 @@ Reusable header for Alfresco applications.
|
||||
```html
|
||||
<adf-layout-header
|
||||
title="title"
|
||||
logo="logo.png"
|
||||
logo="logo.svg"
|
||||
[redirectUrl]="'/home'"
|
||||
color="primary"
|
||||
(clicked)=toggleMenu($event)>
|
||||
</adf-layout-header>
|
||||
```
|
||||
@@ -38,7 +37,7 @@ body of the element:
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| color | [`ThemePalette`](https://github.com/angular/components/blob/master/src/material/core/common-behaviors/color.ts) | | Background color for the header. It can be any hex color code or one of the Material theme colors: 'primary', 'accent' or 'warn'. |
|
||||
| backgroundColor | [`string`] | Background color for the header. It can be any hex color code or CSS variable. |
|
||||
| expandedSidenav | `boolean` | true | expandedSidenav: Toggles the expanded state of the component. |
|
||||
| logo | `string` | | Path to an image file for the application logo. |
|
||||
| position | `string` | "start" | The side of the page that the drawer is attached to (can be 'start' or 'end') |
|
||||
@@ -58,5 +57,5 @@ body of the element:
|
||||
## Details
|
||||
|
||||
This component displays a customizable header that can be reused. Use the input properties to
|
||||
configure the left side (title, button) and the primary color of the header. The right part of the
|
||||
configure the left side (title, button) and the background color of the header. The right part of the
|
||||
header can contain other components which are transcluded in the header component.
|
||||
|
||||
@@ -27,6 +27,21 @@ The main purpose of the [Notification history component](../../core/components/n
|
||||
| maxNotifications | `number` | 5 | Maximum number of notifications to display. The rest will remain hidden until load more is clicked |
|
||||
| menuPositionX | [`MenuPositionX`](https://github.com/angular/components/blob/master/src/material/menu/menu-positions.ts) | "after" | Custom choice for opening the menu at the bottom. Can be `before` or `after`. |
|
||||
| menuPositionY | [`MenuPositionY`](https://github.com/angular/components/blob/master/src/material/menu/menu-positions.ts) | "below" | Custom choice for opening the menu at the bottom. Can be `above` or `below`. |
|
||||
| badgeSize | [`MatBadgeSize`](https://v19.material.angular.dev/components/badge/api#MatBadgeSize) | `small` | Badge size. Can be `small`, `medium` or `large`. |
|
||||
|
||||
### App config
|
||||
|
||||
You can set a default badge size in `app.config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"notification": {
|
||||
"badgeSize": "medium"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `notification.badgeSize` value is applied on init when the `badgeSize` input is not set explicitly on the component.
|
||||
|
||||
## See also
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../lib/core/src/lib/progress/progress.component.md
|
||||
@@ -1,67 +0,0 @@
|
||||
---
|
||||
Title: Sorting Picker Component
|
||||
Added: v2.4.0
|
||||
Status: Active
|
||||
Last reviewed: 2018-06-08
|
||||
---
|
||||
|
||||
# [Sorting Picker Component](../../../lib/core/src/lib/sorting-picker/sorting-picker.component.ts "Defined in sorting-picker.component.ts")
|
||||
|
||||
Selects from a set of predefined sorting definitions and directions.
|
||||
|
||||

|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-sorting-picker
|
||||
[options]="options"
|
||||
[selected]="value"
|
||||
[ascending]="ascending"
|
||||
(change)="onChanged($event)">
|
||||
</adf-sorting-picker>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| ascending | `boolean` | true | Current sorting direction |
|
||||
| options | `Array<Function>` | \[] | Available sorting options |
|
||||
| selected | `string` | | Currently selected option key |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| sortingChange | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<boolean>` | Raised each time direction gets changed. |
|
||||
| valueChange | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Raised each time sorting key gets changed. |
|
||||
|
||||
## Details
|
||||
|
||||
The picker shows the user a menu of sorting options (which could be data columns to sort on
|
||||
alphabetical vs numerical search, etc) and the choice of ascending vs descending sort order.
|
||||
Note that picker only implements the menu, so you are responsible for implementing the sorting
|
||||
options yourself.
|
||||
|
||||
The `options` property contains an array of any objects that expose the following properties:
|
||||
|
||||
```ts
|
||||
{
|
||||
key: string;
|
||||
label: string;
|
||||
}
|
||||
```
|
||||
|
||||
The `key` is an identifying value and the `label` is the text that the user will see in the
|
||||
picker. The selected `key` is reported by the `change` event, which passes an object like the
|
||||
following as its parameter:
|
||||
|
||||
```ts
|
||||
{
|
||||
key: string,
|
||||
ascending: boolean
|
||||
}
|
||||
```
|
||||
@@ -19,7 +19,6 @@ Simple container for headers, titles, actions and breadcrumbs.
|
||||
- [Properties](#properties)
|
||||
- [Details](#details)
|
||||
- [Dropdown menu](#dropdown-menu)
|
||||
- [Custom color](#custom-color)
|
||||
- [See also](#see-also)
|
||||
|
||||
## Basic Usage
|
||||
@@ -74,7 +73,6 @@ pushed to the right by a spacer:
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| color | [`ThemePalette`](https://github.com/angular/components/blob/master/src/material/core/common-behaviors/color.ts) | | Toolbar color. Can be changed to empty value (default), `primary`, `accent` or `warn`. |
|
||||
| title | `string` | "" | Toolbar title. |
|
||||
|
||||
## Details
|
||||
@@ -116,21 +114,6 @@ when you click the menu button:
|
||||
|
||||

|
||||
|
||||
### Custom color
|
||||
|
||||
Besides the default color you can use 'primary', 'accent', or 'warn' values:
|
||||
|
||||
You might also want to change colors to follow your application's color
|
||||
[theme](../../user-guide/theming.md):
|
||||
|
||||
For example:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## See also
|
||||
|
||||
- [Toolbar Divider component](toolbar-divider.component.md)
|
||||
|
||||
@@ -236,7 +236,7 @@ Next in your component you need to get a reference of created template
|
||||
|
||||
```ts
|
||||
@ViewChild('viewerExtensions')
|
||||
viewerTemplateExtensions: TemplateRef<any>;
|
||||
viewerTemplateExtensions: TemplateRef<unknown>;
|
||||
```
|
||||
|
||||
and pass it via `viewerTemplateExtensions` input:
|
||||
|
||||
@@ -53,8 +53,8 @@ With icon:
|
||||
```
|
||||
|
||||
```ts
|
||||
@ViewChild('contentDialogTemplate') contentDialogTemplate: TemplateRef<any>;
|
||||
@ViewChild('actionsDialogTemplate') actionsDialogTemplate: TemplateRef<any>;
|
||||
@ViewChild('contentDialogTemplate') contentDialogTemplate: TemplateRef<unknown>;
|
||||
@ViewChild('actionsDialogTemplate') actionsDialogTemplate: TemplateRef<unknown>;
|
||||
|
||||
constructor(private dialog: MatDialog) {}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ interface DataColumn {
|
||||
title?: string;
|
||||
srTitle?: string;
|
||||
cssClass?: string;
|
||||
template?: TemplateRef<any>;
|
||||
template?: TemplateRef<unknown>;
|
||||
formatTooltip?: Function;
|
||||
focus?: boolean;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ interface DialogData {
|
||||
isCloseButtonHidden?: boolean;
|
||||
isCancelButtonHidden?: boolean;
|
||||
dialogSize?: DialogSizes;
|
||||
contentTemplate?: TemplateRef<any>;
|
||||
actionsTemplate?: TemplateRef<any>;
|
||||
descriptionTemplate?: TemplateRef<any>;
|
||||
contentTemplate?: TemplateRef<unknown>;
|
||||
actionsTemplate?: TemplateRef<unknown>;
|
||||
descriptionTemplate?: TemplateRef<unknown>;
|
||||
headerIcon?: string;
|
||||
additionalActionButtons?: AdditionalDialogActionButton[];
|
||||
componentData?: any;
|
||||
@@ -46,9 +46,9 @@ interface DialogData {
|
||||
| dialogSize | `DialogSize` | `Medium` | Set dialog size. Can be `Large`, `Medium`, `Alert`. (optional) |
|
||||
| contentText | `string` | | Inserts a content text. (optional) |
|
||||
| contentComponent | `Type<any>` | | Inserts a content component. (optional) |
|
||||
| contentTemplate | `TemplateRef<any>` | | Inserts a content template. (optional) |
|
||||
| actionsTemplate | `TemplateRef<any>` | | Inserts a template styled on the left. Should be used for additional `mat-button` style buttons. (optional) |
|
||||
| descriptionTemplate | `TemplateRef<any>` | | Inserts a description template. (optional) |
|
||||
| contentTemplate | `TemplateRef<unknown>` | | Inserts a content template. (optional) |
|
||||
| actionsTemplate | `TemplateRef<unknown>` | | Inserts a template styled on the left. Should be used for additional `mat-button` style buttons. (optional) |
|
||||
| descriptionTemplate | `TemplateRef<unknown>` | | Inserts a description template. (optional) |
|
||||
| additionalActionButtons | `AdditionalDialogActionButton[]` | | Inserts additional base-styled buttons into the action bar on the left. (optional) |
|
||||
| componentData | `any` | | Data that injected in contentComponent. (optional) |
|
||||
| dataOnConfirm$ | `Subject<any>` | | Data to be passed on confirm action after dialog closed. (optional) |
|
||||
|
||||
@@ -5,7 +5,7 @@ Status: Active
|
||||
Last reviewed: 2019-08-05
|
||||
---
|
||||
|
||||
# [Decimal Number Pipe](../../../lib/core/src/lib/pipes/decimal-number.pipe.ts "Defined in decimal-number.pipe.ts")
|
||||
# Decimal Number Pipe
|
||||
|
||||
Transforms a number to have a certain amount of digits in its integer part and also in its decimal part.
|
||||
|
||||
@@ -15,7 +15,7 @@ Transforms a number to have a certain amount of digits in its integer part and a
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| digitsInfo | [`DecimalNumberModel`](../../../lib/core/src/lib/models/decimal-number.model.ts) | | A format to apply to the date value. [Date Pipe Formats.](https://angular.io/api/common/DatePipe#custom-format-options) |
|
||||
| digitsInfo | `DecimalNumberModel` | | A format to apply to the date value. [Date Pipe Formats.](https://angular.io/api/common/DatePipe#custom-format-options) |
|
||||
| locale | string | 'en-US' | A locale id for the locale format rules to use. |
|
||||
|
||||
## Details
|
||||
@@ -30,11 +30,11 @@ This pipe transforms a given number so it follows the set configuration for the
|
||||
}
|
||||
```
|
||||
|
||||
You can also overwrite this config by passing a [`DecimalNumberModel`](../../../lib/core/src/lib/models/decimal-number.model.ts) as an argument for this pipe.
|
||||
You can also overwrite this config by passing a `DecimalNumberModel` as an argument for this pipe.
|
||||
|
||||
The number can be also localized so it applies commas and dots in the right place depending on the locale id in use.
|
||||
|
||||
#### Result
|
||||
### Result
|
||||
|
||||
```ts
|
||||
decimalNumberPipe.transform(1234.567);
|
||||
|
||||
@@ -98,6 +98,11 @@ Accesses and manipulates ACS document nodes using their node IDs.
|
||||
- _nodeId:_ `string` - ID of the target node
|
||||
- _jobId:_ `string` - ID of the job started by the `initiateFolderSizeCalculation` request
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`SizeDetailsEntry`](../../../lib/js-api/src/api/content-rest-api/docs/NodesApi.md#sizedetailsentry)`>` - Details of the folder
|
||||
- **listParents**(nodeId: `string`, opts: `{ where?: string; includeSource?: boolean;} & NodesIncludeQuery & ContentPagingQuery`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeAssociationPaging`](../../../lib/js-api/src/api/content-rest-api/docs/NodesApi.md#NodeAssociationPaging)`>`<br/>
|
||||
Lists parents of a node.
|
||||
- _nodeId:_ `string` - ID of the target node
|
||||
- _opts:_ `{ where?: string; includeSource?: boolean;} & NodesIncludeQuery & ContentPagingQuery` - additional options that API can take
|
||||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodeAssociationPaging`](../../../lib/js-api/src/api/content-rest-api/docs/NodesApi.md#NodeAssociationPaging)`>` - List of node's parents.
|
||||
|
||||
## Details
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ Let's say we have an upload button as follows:
|
||||
|
||||
```html
|
||||
<div>
|
||||
<button mat-button color="accent" mat-mini-fab (click)="fileInput.click()">
|
||||
<button mat-button mat-mini-fab (click)="fileInput.click()">
|
||||
<mat-icon>attachment</mat-icon>
|
||||
</button>
|
||||
<input hidden type="file" #fileInput (change)="onUploadFile($event)"/>
|
||||
|
||||
@@ -60,3 +60,6 @@ The pages linked below contain the licenses for all third party dependencies of
|
||||
- [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)
|
||||
- [ADF 8.3.1](license-info-8.3.1.md)
|
||||
- [ADF 8.4.1](license-info-8.4.1.md)
|
||||
- [ADF 8.5.0](license-info-8.5.0.md)
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
Title: License info, alfresco-ng2-components 8.3.1
|
||||
---
|
||||
|
||||
# License information for alfresco-ng2-components 8.3.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.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/cdk](https://github.com/angular/components) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/common](https://github.com/angular/angular) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/compiler](https://github.com/angular/angular) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/core](https://github.com/angular/angular) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/forms](https://github.com/angular/angular) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/material-date-fns-adapter](https://github.com/angular/components) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/material](https://github.com/angular/components) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/platform-browser](https://github.com/angular/angular) | 19.2.19 | [MIT](http://www.opensource.org/licenses/MIT) |
|
||||
| [@angular/router](https://github.com/angular/angular) | 19.2.19 | [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) | 9.4.0 | [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) |
|
||||
| [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 | 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) | 5.0.4 | [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,48 @@
|
||||
---
|
||||
Title: License info, alfresco-ng2-components 8.4.1
|
||||
---
|
||||
|
||||
# License information for alfresco-ng2-components 8.4.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.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/cdk](https://github.com/angular/components) | 19.2.19 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/common](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/compiler](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/core](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/forms](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/material-date-fns-adapter](https://github.com/angular/components) | 19.2.19 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/material](https://github.com/angular/components) | 19.2.19 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/platform-browser](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/router](https://github.com/angular/angular) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@apollo/client](https://github.com/apollographql/apollo-client) | 3.13.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@cspell/eslint-plugin](https://github.com/streetsidesoftware/cspell) | 9.4.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker) | 15.0.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@ngx-translate/core](https://github.com/ngx-translate/core) | 17.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [angular-oauth2-oidc-jwks](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [apollo-angular](https://github.com/kamilkisiela/apollo-angular) | 10.0.3 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [chart.js](https://github.com/chartjs/Chart.js) | 4.4.4 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [cropperjs](https://github.com/fengyuanchen/cropperjs) | 1.6.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [date-fns](https://github.com/date-fns/date-fns) | 2.30.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| dotenv-expand | 5.1.0 | [BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause) |
|
||||
| editorjs-html | 4.0.5 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [eventemitter3](https://github.com/primus/eventemitter3) | 5.0.4 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [graphql-ws](https://github.com/enisdenjo/graphql-ws) | 6.0.7 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [material-icons](https://github.com/marella/material-icons) | 1.13.14 | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [minimatch-browser](https://github.com/isaacs/minimatch) | 1.0.0 | [ISC](https://www.isc.org/licenses/) |
|
||||
| [ng2-charts](https://github.com/valor-software/ng2-charts) | 4.1.1 | [ISC](https://www.isc.org/licenses/) |
|
||||
| [node-fetch](https://github.com/node-fetch/node-fetch) | 3.3.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [pdfjs-dist](https://github.com/mozilla/pdf.js) | 5.1.91 | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [raphael](https://github.com/DmitryBaranovskiy/raphael) | 2.3.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [rxjs](https://github.com/reactivex/rxjs) | 7.8.2 | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [superagent](https://github.com/ladjs/superagent) | 9.0.2 | [MIT](https://opensource.org/license/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](https://opensource.org/license/mit/) |
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
Title: License info, alfresco-ng2-components 8.5.0
|
||||
---
|
||||
|
||||
# License information for alfresco-ng2-components 8.5.0
|
||||
|
||||
This page lists all third party libraries the project depends on.
|
||||
|
||||
## Libraries
|
||||
|
||||
| Name | Version | License |
|
||||
| --- | --- | --- |
|
||||
| [@angular/animations](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/cdk](https://github.com/angular/components.git) | 19.2.19 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/common](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/compiler](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/core](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/forms](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/material](https://github.com/angular/components.git) | 19.2.19 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/material-date-fns-adapter](https://github.com/angular/components.git) | 19.2.19 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/platform-browser](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/platform-browser-dynamic](https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@angular/router](git+https://github.com/angular/angular.git) | 19.2.20 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@apollo/client](git+https://github.com/apollographql/apollo-client.git) | 3.13.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@babel/runtime](https://github.com/babel/babel.git) | 7.26.10 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@cspell/eslint-plugin](https://github.com/streetsidesoftware/cspell.git) | 10.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@graphql-typed-document-node/core](git@github.com:dotansimha/graphql-typed-document-node.git) | 3.2.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker.git) | 15.0.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@napi-rs/canvas](git+https://github.com/Brooooooklyn/canvas.git) | 0.1.100 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@napi-rs/canvas-darwin-arm64](git+https://github.com/Brooooooklyn/canvas.git) | 0.1.100 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@ngx-translate/core](https://github.com/ngx-translate/core) | 17.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@wry/caches](git+https://github.com/benjamn/wryware.git) | 1.0.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@wry/context](git+https://github.com/benjamn/wryware.git) | 0.7.4 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@wry/equality](git+https://github.com/benjamn/wryware.git) | 0.5.7 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [@wry/trie](git+https://github.com/benjamn/wryware.git) | 0.5.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) | 19.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [apollo-angular](https://github.com/kamilkisiela/apollo-angular) | 10.0.3 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [balanced-match](git://github.com/juliangruber/balanced-match.git) | 1.0.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [brace-expansion](git://github.com/juliangruber/brace-expansion.git) | 1.1.15 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [brace-expansion](git://github.com/juliangruber/brace-expansion.git) | 2.1.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [concat-map](git://github.com/substack/node-concat-map.git) | 0.0.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [cropperjs](git+https://github.com/fengyuanchen/cropperjs.git) | 1.6.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [date-fns](https://github.com/date-fns/date-fns) | 2.30.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| dotenv-expand | 5.1.0 | [BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause) |
|
||||
| editorjs-html | 4.0.5 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [eve-raphael](https://github.com/tomasAlabes/eve.git) | 0.5.0 | UNKNOWN |
|
||||
| [eventemitter3](git://github.com/primus/eventemitter3.git) | 5.0.4 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [fetch-blob](https://github.com/node-fetch/fetch-blob.git) | 3.2.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [formdata-polyfill](git+https://jimmywarting@github.com/jimmywarting/FormData.git) | 4.0.10 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [graphql-tag](git+https://github.com/apollographql/graphql-tag.git) | 2.12.6 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [graphql-ws](git+https://github.com/enisdenjo/graphql-ws.git) | 6.0.8 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [hoist-non-react-statics](git://github.com/mridgway/hoist-non-react-statics.git) | 3.3.2 | [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) |
|
||||
| [js-tokens](lydell/js-tokens) | 4.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [lodash-es](lodash/lodash) | 4.18.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [loose-envify](git://github.com/zertosh/loose-envify.git) | 1.4.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [material-icons](git+https://github.com/marella/material-icons.git) | 1.13.14 | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [minimatch](git://github.com/isaacs/minimatch.git) | 5.1.9 | [ISC](https://www.isc.org/licenses/) |
|
||||
| [minimatch-browser](git://github.com/isaacs/minimatch.git) | 1.0.0 | [ISC](https://www.isc.org/licenses/) |
|
||||
| [ng2-charts](git+https://github.com/valor-software/ng2-charts.git) | 4.1.1 | [ISC](https://www.isc.org/licenses/) |
|
||||
| [node-domexception](git+https://github.com/jimmywarting/node-domexception.git) | 1.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [node-fetch](https://github.com/node-fetch/node-fetch.git) | 3.3.2 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [object-assign](sindresorhus/object-assign) | 4.1.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [optimism](git+https://github.com/benjamn/optimism.git) | 0.18.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [pdfjs-dist](git+https://github.com/mozilla/pdf.js.git) | 5.1.91 | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [prop-types](facebook/prop-types) | 15.8.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [raphael](git://github.com/DmitryBaranovskiy/raphael.git) | 2.3.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [react-is](https://github.com/facebook/react.git) | 16.13.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [regenerator-runtime](https://github.com/facebook/regenerator/tree/main/packages/runtime) | 0.14.1 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [rehackt](git+https://github.com/phryneas/rehackt.git) | 0.1.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [rxjs](https://github.com/reactivex/rxjs.git) | 7.8.2 | [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||
| [symbol-observable](blesh/symbol-observable) | 4.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [ts-invariant](git+https://github.com/apollographql/invariant-packages.git) | 0.10.3 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [tslib](https://github.com/Microsoft/tslib.git) | 2.8.1 | [0BSD](http://landley.net/toybox/license.html) |
|
||||
| [uuid](https://github.com/uuidjs/uuid.git) | 14.0.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [web-streams-polyfill](git+https://github.com/MattiasBuelens/web-streams-polyfill.git) | 3.3.3 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [zen-observable](zenparsing/zen-observable) | 0.8.15 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [zen-observable-ts](git+https://github.com/apollographql/zen-observable-ts.git) | 1.2.5 | [MIT](https://opensource.org/license/mit/) |
|
||||
| [zone.js](git://github.com/angular/angular.git) | 0.15.0 | [MIT](https://opensource.org/license/mit/) |
|
||||
|
||||
@@ -89,7 +89,7 @@ The template defined inside `empty-form` will be shown when no form definition i
|
||||
| path | `string` | | Path of the folder where the metadata will be stored. |
|
||||
| processInstanceId | `string` | | ProcessInstanceId id to fetch corresponding form and values. |
|
||||
| readOnly | `boolean` | false | Toggle readonly state of the form. Forces all form widgets to render as readonly if enabled. |
|
||||
| showCompleteButton | `boolean` | true | Toggle rendering of the `Complete` outcome button. |
|
||||
| showCompleteButton | `boolean` | false | Toggle rendering of the `Complete` outcome button. |
|
||||
| showRefreshButton | `boolean` | true | Toggle rendering of the `Refresh` button. |
|
||||
| showSaveButton | `boolean` | true | Toggle rendering of the `Save` outcome button. |
|
||||
| showTitle | `boolean` | true | Toggle rendering of the form title. |
|
||||
|
||||
@@ -9,6 +9,9 @@ The first **General Availability** release was v2.0.0.
|
||||
|
||||
## General Availability
|
||||
|
||||
- [8.5.0](RelNote-8.5.0.md)
|
||||
- [8.4.1](RelNote-8.4.1.md)
|
||||
- [8.3.1](RelNote-8.3.1.md)
|
||||
- [8.2.1](RelNote-8.2.1.md)
|
||||
- [8.2.0](RelNote-8.2.0.md)
|
||||
- [8.1.1](RelNote-8.1.1.md)
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
---
|
||||
Title: Changelog for alfresco-ng2-components v8.3.1
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
- [68b1b98c83](git@github.com:Alfresco/alfresco-ng2-components/commit/68b1b98c83) AAE-42904 Escape html in evaluated fields and variables for rich-text display widget (#11718)
|
||||
- [3e44f2d358](git@github.com:Alfresco/alfresco-ng2-components/commit/3e44f2d358) [ACS-11259] Fix categories deletion in content metadata component (#11717)
|
||||
- [dc8e6a9fb3](git@github.com:Alfresco/alfresco-ng2-components/commit/dc8e6a9fb3) [PRODSEC-11289] Fix Angular i18n vulnerable to CSS (#11710)
|
||||
- [0b7b89e5d8](git@github.com:Alfresco/alfresco-ng2-components/commit/0b7b89e5d8) [ACS-11213] Reverted ngx translate upgrade (#11702)
|
||||
- [a15b1f4c85](git@github.com:Alfresco/alfresco-ng2-components/commit/a15b1f4c85) AAE-42804 Fixing task filter query param (#11701)
|
||||
- [294e6254c2](git@github.com:Alfresco/alfresco-ng2-components/commit/294e6254c2) AAE-42804 Adding adf active class to activated link (#11698)
|
||||
- [ec312d49ab](git@github.com:Alfresco/alfresco-ng2-components/commit/ec312d49ab) [ACS-11213] Updated ngx translate in libs (#11699)
|
||||
- [c216cea81b](git@github.com:Alfresco/alfresco-ng2-components/commit/c216cea81b) Fix minimatch version for adf-cli (#11697)
|
||||
- [ad966af662](git@github.com:Alfresco/alfresco-ng2-components/commit/ad966af662) [ACS-11213] Upgrade ngx-translate to v17 (#11692)
|
||||
- [8b23b61d9c](git@github.com:Alfresco/alfresco-ng2-components/commit/8b23b61d9c) [PRODSEC-11257] audit fix @cspell/eslint-plugin (#11696)
|
||||
- [dd66ecc72a](git@github.com:Alfresco/alfresco-ng2-components/commit/dd66ecc72a) AAE-42804 Cleaning up tasks and process filter components (#11693)
|
||||
- [3b14351389](git@github.com:Alfresco/alfresco-ng2-components/commit/3b14351389) [ACS-11225] Remove @nx/webpack dependency (#11688)
|
||||
- [3535fa3d89](git@github.com:Alfresco/alfresco-ng2-components/commit/3535fa3d89) ACS-11224 Migrate upload components to Angular control flow (#11691)
|
||||
- [68d174c3e6](git@github.com:Alfresco/alfresco-ng2-components/commit/68d174c3e6) [ACS-11033] add node id field to ai answer references (#11690)
|
||||
- [4cc56421ee](git@github.com:Alfresco/alfresco-ng2-components/commit/4cc56421ee) AAE-42658 Remove check for outcome.id as name based outcomes are valid (#11685)
|
||||
- [1061e762f8](git@github.com:Alfresco/alfresco-ng2-components/commit/1061e762f8) Apply Copilot suggestion
|
||||
- [358367bcb1](git@github.com:Alfresco/alfresco-ng2-components/commit/358367bcb1) AAE-42643 Fix long error messages overlapping with icon
|
||||
- [52ad50fbc7](git@github.com:Alfresco/alfresco-ng2-components/commit/52ad50fbc7) refactor: update PDF viewer component imports and types for better compatibility (#11686)
|
||||
- [2a0d5df2d5](git@github.com:Alfresco/alfresco-ng2-components/commit/2a0d5df2d5) [ACS-11173] Initial set of rules for Copilot review (#11683)
|
||||
- [7405b2d2e4](git@github.com:Alfresco/alfresco-ng2-components/commit/7405b2d2e4) fix pdf import for the Viewer (#11684)
|
||||
- [7a3650e6a7](git@github.com:Alfresco/alfresco-ng2-components/commit/7a3650e6a7) [ACS-11204] Fix: Duplicated site name is displayed instead of id when there are two libraries with the same name (#11682)
|
||||
- [de34579038](git@github.com:Alfresco/alfresco-ng2-components/commit/de34579038) AAE-42156 Update text and multiline fields to show custom regex validation message. (#11670)
|
||||
- [2f8d8c2007](git@github.com:Alfresco/alfresco-ng2-components/commit/2f8d8c2007) chore: update ESLint and cspell configurations to ignore story files (#11681)
|
||||
- [303a9efb3e](git@github.com:Alfresco/alfresco-ng2-components/commit/303a9efb3e) chore: eslint fixes for @typescript-eslint/no-explicit-any (#11672)
|
||||
- [7f8b49cb07](git@github.com:Alfresco/alfresco-ng2-components/commit/7f8b49cb07) Remove excess disabled attribute (#11680)
|
||||
- [f1f2000db8](git@github.com:Alfresco/alfresco-ng2-components/commit/f1f2000db8) AAE-42525 Updated condition for mat-error (#11669)
|
||||
- [5935fbfb5b](git@github.com:Alfresco/alfresco-ng2-components/commit/5935fbfb5b) [ACS-11153] Changed eslint rule for ng-reflect after copilot suggestion in ACA (#11673)
|
||||
- [57b8fe7174](git@github.com:Alfresco/alfresco-ng2-components/commit/57b8fe7174) [ACS-11153] Corrected eslint rule for ng-reflect (#11671)
|
||||
- [cfb9a505e4](git@github.com:Alfresco/alfresco-ng2-components/commit/cfb9a505e4) [ACS-10847] Location filter breaks the page when user value used (#11667)
|
||||
- [e5471c8741](git@github.com:Alfresco/alfresco-ng2-components/commit/e5471c8741) Add missing input type (#11668)
|
||||
- [1baddb2b37](git@github.com:Alfresco/alfresco-ng2-components/commit/1baddb2b37) AAE-42291 Double-click to copy to clipboard does not work on disabled/read-only fields in card-view-textitem (#11656)
|
||||
- [e48950b200](git@github.com:Alfresco/alfresco-ng2-components/commit/e48950b200) [MNT-25123] Fixed incorrectly displayed some annotations (#11662)
|
||||
- [4581f714d7](git@github.com:Alfresco/alfresco-ng2-components/commit/4581f714d7) [ACS-11153] remove the usage of ng reflect from the unit tests (#11666)
|
||||
- [bc30b74213](git@github.com:Alfresco/alfresco-ng2-components/commit/bc30b74213) AAE-39679 Counting click event twice for attach file widget (#11645)
|
||||
- [3f542d99ba](git@github.com:Alfresco/alfresco-ng2-components/commit/3f542d99ba) Migrate to @angular-eslint/prefer-inject and @typescript-eslint/prefer-readonly (#11665)
|
||||
- [f8fa996b04](git@github.com:Alfresco/alfresco-ng2-components/commit/f8fa996b04) AAE-33828 Fix for the runtime errors on data-table should be handled (#11639)
|
||||
- [93fc7c166c](git@github.com:Alfresco/alfresco-ng2-components/commit/93fc7c166c) AAE-41605 Add ability to filter by linked processes (#11664)
|
||||
- [b6a6c1bc86](git@github.com:Alfresco/alfresco-ng2-components/commit/b6a6c1bc86) [MNT-24175]: fixes non node values handling (#11641)
|
||||
- [5850dafca7](git@github.com:Alfresco/alfresco-ng2-components/commit/5850dafca7) [ACS-11158]: removes mat selectors for tooltips (#11659)
|
||||
- [fafa5d6c41](git@github.com:Alfresco/alfresco-ng2-components/commit/fafa5d6c41) ACS-11160: improve context menu overlay service implementation (#11661)
|
||||
- [1f49af4c8f](git@github.com:Alfresco/alfresco-ng2-components/commit/1f49af4c8f) ACS-11154 Viewer stabilisation, lint fixes (#11660)
|
||||
- [84affe9f37](git@github.com:Alfresco/alfresco-ng2-components/commit/84affe9f37) ACS-11155: update conditional checks to use optional chaining (#11658)
|
||||
- [40b15689d5](git@github.com:Alfresco/alfresco-ng2-components/commit/40b15689d5) AAE-21047 Get rid of enums (#11643)
|
||||
- [d274d62d73](git@github.com:Alfresco/alfresco-ng2-components/commit/d274d62d73) AAE-40604 Fix edge case for REST/Variable for dropdown showing required message (#11638)
|
||||
- [1fa683e2a9](git@github.com:Alfresco/alfresco-ng2-components/commit/1fa683e2a9) Fix for ACA upstream (#11642)
|
||||
- [faa22f2fde](git@github.com:Alfresco/alfresco-ng2-components/commit/faa22f2fde) Fix for ACA upstream (#11640)
|
||||
- [4df5b9282c](git@github.com:Alfresco/alfresco-ng2-components/commit/4df5b9282c) [MNT-25478] Expose list parents method in nodes api service (#11622)
|
||||
- [30afd2d863](git@github.com:Alfresco/alfresco-ng2-components/commit/30afd2d863) AAE-42151 [FE - Studio Admin] Improve types for Integration Contexts (#11633)
|
||||
- [0b805f3e9b](git@github.com:Alfresco/alfresco-ng2-components/commit/0b805f3e9b) Revert "AAE-40604 Fix case when rest/variable are okay and dropdown is requir…" (#11634)
|
||||
- [4d99262ba3](git@github.com:Alfresco/alfresco-ng2-components/commit/4d99262ba3) AAE-41699 Evaluate variables in form display text (#11620)
|
||||
- [14899931d2](git@github.com:Alfresco/alfresco-ng2-components/commit/14899931d2) AAE-41742 Add processRelatedTo payload for processes list (#11632)
|
||||
- [283b996063](git@github.com:Alfresco/alfresco-ng2-components/commit/283b996063) [MNT-25541] PDFs containing JP2 images (JPEG 2000) cannot be displayed in ADW viewer (#11618)
|
||||
- [5df193b255](git@github.com:Alfresco/alfresco-ng2-components/commit/5df193b255) [MNT-25123] pdf annotations incorrect and or not visible (#11621)
|
||||
- [dcf133b37e](git@github.com:Alfresco/alfresco-ng2-components/commit/dcf133b37e) [MNT-25410] ADW - Saved Searches can load the wrong search set, and t… (#11599)
|
||||
- [31bafd718e](git@github.com:Alfresco/alfresco-ng2-components/commit/31bafd718e) AAE-40604 Fix case when rest/variable are okay and dropdown is required and not selected (#11619)
|
||||
- [0c50bfd4e3](git@github.com:Alfresco/alfresco-ng2-components/commit/0c50bfd4e3) [ACS-10957] new locators for errors in ACC dialogs (#11617)
|
||||
- [e859923541](git@github.com:Alfresco/alfresco-ng2-components/commit/e859923541) [ACS-10304] KN: personal files: Column resizing available via mouse but not accessible via keyboard (#11616)
|
||||
- [6ff7ce4add](git@github.com:Alfresco/alfresco-ng2-components/commit/6ff7ce4add) [MNT-25501]: APS - Process instance pagination failure in ADF due to conflicting parameters sent from ADF to APS API (#11615)
|
||||
- [302b3e18ec](git@github.com:Alfresco/alfresco-ng2-components/commit/302b3e18ec) AAE-40604 Fix for Dropdown required validation message is not present (#11600)
|
||||
- [84de7c7765](git@github.com:Alfresco/alfresco-ng2-components/commit/84de7c7765) Satori adotion icon fix (#11614)
|
||||
- [b74ffc81f4](git@github.com:Alfresco/alfresco-ng2-components/commit/b74ffc81f4) [ACS-10247] a11y: SR not announce Start/End Date as required fields (#11613)
|
||||
- [3e9b5a097c](git@github.com:Alfresco/alfresco-ng2-components/commit/3e9b5a097c) [ACS-10193] Other A11y My Libraries Link (#11587)
|
||||
- [ba3d9d5be4](git@github.com:Alfresco/alfresco-ng2-components/commit/ba3d9d5be4) [ACS-7768] Styling fixes for permission management page (#11597)
|
||||
- [8cda30db45](git@github.com:Alfresco/alfresco-ng2-components/commit/8cda30db45) [ACS-10203]: Checkbox "Select All" has no visible label (#11594)
|
||||
- [1780aa9663](git@github.com:Alfresco/alfresco-ng2-components/commit/1780aa9663) [ACS-10281] a11y fix: Approve step folder control is focusable twice (#11589)
|
||||
- [3bba02264a](git@github.com:Alfresco/alfresco-ng2-components/commit/3bba02264a) [ACS-10241]: Personal files: Column sorting state and role not communicated by buttons (parially reverted to align with hxp) (#11598)
|
||||
- [4987bbadef](git@github.com:Alfresco/alfresco-ng2-components/commit/4987bbadef) [ACS-10302] Add aria-live to selected aspects counter (#11593)
|
||||
- [9cb8b962ae](git@github.com:Alfresco/alfresco-ng2-components/commit/9cb8b962ae) [ACS-10213] Libraries: Radio buttons for Public, Private, and Moderated lack a grouped label (#11590)
|
||||
- [6bb78f9d26](git@github.com:Alfresco/alfresco-ng2-components/commit/6bb78f9d26) [ACS-10274] sr personal files sr announces white heavy check mark in entitlements row of repository section (#11595)
|
||||
- [2b79f18d79](git@github.com:Alfresco/alfresco-ng2-components/commit/2b79f18d79) [ACS-10247] a11y fix: SR announces Start/End Date fields incorrectly in date popup (#11592)
|
||||
- [4a6e9fc5d6](git@github.com:Alfresco/alfresco-ng2-components/commit/4a6e9fc5d6) [ACS-10241]: SR: Personal files: Column sorting state and role not communicated by buttons (#11591)
|
||||
- [6131bf3890](git@github.com:Alfresco/alfresco-ng2-components/commit/6131bf3890) AAE-38626 Reload columns on appname change (#11560)
|
||||
- [15806d7c9f](git@github.com:Alfresco/alfresco-ng2-components/commit/15806d7c9f) HXIDP-5181 Allow form text fields to render custom field status content (#11523)
|
||||
- [42c2f78baf](git@github.com:Alfresco/alfresco-ng2-components/commit/42c2f78baf) Fixes icon button color in array item (#11588)
|
||||
- [1028df91da](git@github.com:Alfresco/alfresco-ng2-components/commit/1028df91da) [ACS-7768] ADF Form fields cleanup (#11484)
|
||||
- [1c59b2fb15](git@github.com:Alfresco/alfresco-ng2-components/commit/1c59b2fb15) [ACS-10307] SR: Personal files: No confirmation announced when creating new folder or document (#11549)
|
||||
- [198e18bef5](git@github.com:Alfresco/alfresco-ng2-components/commit/198e18bef5) [ACS-10239] Add aria hidden to visual separators (#11572)
|
||||
- [1022e1e51f](git@github.com:Alfresco/alfresco-ng2-components/commit/1022e1e51f) [ACS-10276] Add proper title and aria label to chip remove button (#11569)
|
||||
- [6927af4ec3](git@github.com:Alfresco/alfresco-ng2-components/commit/6927af4ec3) [ACS-10288] Aria label for user initials pipe (#11568)
|
||||
- [3f01a92d67](git@github.com:Alfresco/alfresco-ng2-components/commit/3f01a92d67) AAE-34140 Asynchronous Forms - automatically populated value cannot be used in another task (#11574)
|
||||
- [e78da9dea0](git@github.com:Alfresco/alfresco-ng2-components/commit/e78da9dea0) ACS-8395: remove old and unused search picker components (#11573)
|
||||
- [a3c309c676](git@github.com:Alfresco/alfresco-ng2-components/commit/a3c309c676) AAE-41613 Hiding tooltip card on click (#11571)
|
||||
- [6eaaff33bb](git@github.com:Alfresco/alfresco-ng2-components/commit/6eaaff33bb) [ACS-10289] No notifications info is no longer mat menu item (#11566)
|
||||
- [22478f8097](git@github.com:Alfresco/alfresco-ng2-components/commit/22478f8097) Update Storybook & Regenerate lockfile [ci:force][affected:*] (#11567)
|
||||
- [b04e1ca081](git@github.com:Alfresco/alfresco-ng2-components/commit/b04e1ca081) [ACS-10323] Fix not announced aria-label (#11553)
|
||||
- [0edb04eeb2](git@github.com:Alfresco/alfresco-ng2-components/commit/0edb04eeb2) [ACS-10301] Add aria-hidden to a decorative icon (#11564)
|
||||
- [5c536079c9](git@github.com:Alfresco/alfresco-ng2-components/commit/5c536079c9) Refactor alfresco-viewer component tests to use [adf-icon] directive for icons (#11565)
|
||||
- [6c4bdf0c5c](git@github.com:Alfresco/alfresco-ng2-components/commit/6c4bdf0c5c) Exclude adf-icon from linting (#11563)
|
||||
- [f5c696ed7e](git@github.com:Alfresco/alfresco-ng2-components/commit/f5c696ed7e) AAE-41553 Fix again crowdin exec from release workflow_call (#11562)
|
||||
- [5cdcd97201](git@github.com:Alfresco/alfresco-ng2-components/commit/5cdcd97201) [ACS-10259] Add an option to reorder rows with keyboard (#11548)
|
||||
- [670e77580d](git@github.com:Alfresco/alfresco-ng2-components/commit/670e77580d) AAE-41553 Fix crowdin exec from release workflow_call (#11561)
|
||||
- [c81a64be79](git@github.com:Alfresco/alfresco-ng2-components/commit/c81a64be79) [ACS-10206]: setting haspopup after init (#11475)
|
||||
- [506aeecdc2](git@github.com:Alfresco/alfresco-ng2-components/commit/506aeecdc2) [ACS-10280] Keyboard Navigation: Search: Unnecessary stops in the results table using the Tab key: (#11529)
|
||||
- [5076862e07](git@github.com:Alfresco/alfresco-ng2-components/commit/5076862e07) AAE-41553 Fix CI validation on crowdin PRs (#11557)
|
||||
- [ee7fa5bfa4](git@github.com:Alfresco/alfresco-ng2-components/commit/ee7fa5bfa4) Revert "AAE-38626 Updating columns when appName changes (#11554)" (#11556)
|
||||
- [934765f2f6](git@github.com:Alfresco/alfresco-ng2-components/commit/934765f2f6) [ACS-10304] KN: personal files: Column resizing available via mouse but not accessible via keyboard (#11525)
|
||||
- [d838d93abc](git@github.com:Alfresco/alfresco-ng2-components/commit/d838d93abc) AAE-41496 Deprecate icon component (#11550)
|
||||
- [69b73c8490](git@github.com:Alfresco/alfresco-ng2-components/commit/69b73c8490) AAE-38626 Updating columns when appName changes (#11554)
|
||||
- [d411d93689](git@github.com:Alfresco/alfresco-ng2-components/commit/d411d93689) AAE-41500 Added linked processes properties (#11552)
|
||||
- [1c53dfa42e](git@github.com:Alfresco/alfresco-ng2-components/commit/1c53dfa42e) chore: add peer flag to multiple dependencies in package-lock.json
|
||||
- [4200f9abce](git@github.com:Alfresco/alfresco-ng2-components/commit/4200f9abce) AAE-40748 Bug fixes for translation and storage services (#11551)
|
||||
- [0b7124a638](git@github.com:Alfresco/alfresco-ng2-components/commit/0b7124a638) remove unused blank page component (#11533)
|
||||
- [50913dd4e4](git@github.com:Alfresco/alfresco-ng2-components/commit/50913dd4e4) [ACS-10335] Corrected screen reader reading for between group in search date range component (#11534)
|
||||
- [219f52a361](git@github.com:Alfresco/alfresco-ng2-components/commit/219f52a361) [ACS-6821] Adjust the search filter icon in document list (#11528)
|
||||
- [4bf065561a](git@github.com:Alfresco/alfresco-ng2-components/commit/4bf065561a) [ACS-10313] KN: Personal Files: Row selection checkboxes are not accessible for keyboard and screen reader users (#11531)
|
||||
- [17f9b3eeba](git@github.com:Alfresco/alfresco-ng2-components/commit/17f9b3eeba) ACS-8224 Make Multi Value Pipe internal (#11530)
|
||||
- [08725100d8](git@github.com:Alfresco/alfresco-ng2-components/commit/08725100d8) [ACS-10331] Corrected columns visibility title (#11526)
|
||||
- [304216b36b](git@github.com:Alfresco/alfresco-ng2-components/commit/304216b36b) AAE-41330 Unify adf-icon use in adf-core (#11527)
|
||||
- [e01cd40b1f](git@github.com:Alfresco/alfresco-ng2-components/commit/e01cd40b1f) [ACS-10205]: Extends DataTableAdapter interface to handle focus for accessibility (#11506)
|
||||
- [e44e00304a](git@github.com:Alfresco/alfresco-ng2-components/commit/e44e00304a) AAE-38334 Add link process payload (#11524)
|
||||
- [236726b67c](git@github.com:Alfresco/alfresco-ng2-components/commit/236726b67c) AAE-40657 Support multiple integration contexts in task service (#11463)
|
||||
- [8ed1f4d8df](git@github.com:Alfresco/alfresco-ng2-components/commit/8ed1f4d8df) [ACS-1882] Keyboard Navigation: Personal files: Wrong focus order when adding a comment in "Details" section (#11521)
|
||||
- [8824331f3b](git@github.com:Alfresco/alfresco-ng2-components/commit/8824331f3b) [ACS-10884] Keyboard interactions for crop tool in image viewer (#11522)
|
||||
- [716ce228ce](git@github.com:Alfresco/alfresco-ng2-components/commit/716ce228ce) ACS-8772: Migrate node tooltip to Angular signals (#11498)
|
||||
- [d7c01d3558](git@github.com:Alfresco/alfresco-ng2-components/commit/d7c01d3558) Update Angular packages to version 19.2.18 [ci:force] (#11518)
|
||||
- [572231bf49](git@github.com:Alfresco/alfresco-ng2-components/commit/572231bf49) AAE-41225 update typescript target to es2022 and fix FormService propagation (#11508)
|
||||
- [0c3cdaa006](git@github.com:Alfresco/alfresco-ng2-components/commit/0c3cdaa006) [ACS-10335] Grouped input controls with radio buttons for search date range component (#11507)
|
||||
- [38070c210c](git@github.com:Alfresco/alfresco-ng2-components/commit/38070c210c) Remove unused adf-button component (#11520)
|
||||
- [d6aaede8d8](git@github.com:Alfresco/alfresco-ng2-components/commit/d6aaede8d8) [MNT-25408]: improves facet resetting flow (#11485)
|
||||
- [5f9de1fde8](git@github.com:Alfresco/alfresco-ng2-components/commit/5f9de1fde8) AAE-40269 Add storybook v10 (#11401)
|
||||
- [f0c6cc0ff7](git@github.com:Alfresco/alfresco-ng2-components/commit/f0c6cc0ff7) ACS-10937 Remove unused mat-progress wrapper (#11505)
|
||||
- [1950bbe7be](git@github.com:Alfresco/alfresco-ng2-components/commit/1950bbe7be) AAE-41138 Fix commit message extraction (#11501)
|
||||
- [c64c6e4f7e](git@github.com:Alfresco/alfresco-ng2-components/commit/c64c6e4f7e) [ACS-10242] - Personal files: Filter by Size popup announces entire c… (#11468)
|
||||
- [d0b3faad6a](git@github.com:Alfresco/alfresco-ng2-components/commit/d0b3faad6a) [ACS-10201] Snackbar content is hidden and not announced by SR (#11504)
|
||||
- [d2021b9ae9](git@github.com:Alfresco/alfresco-ng2-components/commit/d2021b9ae9) AAE-40714 fixing the filter cut issue on admin-hxp (#11499)
|
||||
- [66911491e3](git@github.com:Alfresco/alfresco-ng2-components/commit/66911491e3) AAE-39182 Update (some) Angular packages to version 19.2.19
|
||||
- [c25690cf84](git@github.com:Alfresco/alfresco-ng2-components/commit/c25690cf84) ACS-10936: Remove unused LANDING_PAGE_TOKEN (#11503)
|
||||
- [74262fcc17](git@github.com:Alfresco/alfresco-ng2-components/commit/74262fcc17) AAE-40934 style: replace mat-raise-button with mat-flat-button (#11502)
|
||||
- [98ce8d810c](git@github.com:Alfresco/alfresco-ng2-components/commit/98ce8d810c) AAE-41025 Add adf-icon to process-services-cloud lib (#11497)
|
||||
- [d93d963a8d](git@github.com:Alfresco/alfresco-ng2-components/commit/d93d963a8d) AAE-41024 Add adf-icon to content-services lib (#11496)
|
||||
- [b13ae23173](git@github.com:Alfresco/alfresco-ng2-components/commit/b13ae23173) ACS-10914 Remove unused allowable operation directive (#11476)
|
||||
- [41b97eb835](git@github.com:Alfresco/alfresco-ng2-components/commit/41b97eb835) AAE-40911 Add adf-icon to core lib (#11471)
|
||||
- [4113eeb2ab](git@github.com:Alfresco/alfresco-ng2-components/commit/4113eeb2ab) Allows closing dropdown with Escape key (#11489)
|
||||
- [fcb15868f8](git@github.com:Alfresco/alfresco-ng2-components/commit/fcb15868f8) ACS-7579 Remove unused process audit directive (#11474)
|
||||
- [744bb671f1](git@github.com:Alfresco/alfresco-ng2-components/commit/744bb671f1) ACS-10908 Cleanup unit test configuration for Content (#11470)
|
||||
- [52cadb5b8a](git@github.com:Alfresco/alfresco-ng2-components/commit/52cadb5b8a) AAE-40896 Create adf-icon directive (#11467)
|
||||
- [fe39b3c1bd](git@github.com:Alfresco/alfresco-ng2-components/commit/fe39b3c1bd) [AAE-40028] Added group/section validation skipping to cloud forms for workspace (#11466)
|
||||
- [8c1118984d](git@github.com:Alfresco/alfresco-ng2-components/commit/8c1118984d) remove webpack and webpack cli [ci:force] (#11464)
|
||||
- [21d6818de5](git@github.com:Alfresco/alfresco-ng2-components/commit/21d6818de5) ACS-10083 Fixes filters behavior with queryParams (#11426)
|
||||
- [331b4459a8](git@github.com:Alfresco/alfresco-ng2-components/commit/331b4459a8) AAE-40359 Filter out service processes on start process (#11446)
|
||||
- [062b8060bc](git@github.com:Alfresco/alfresco-ng2-components/commit/062b8060bc) ACS-7461 Remove ADF_DOCUMENT_PARENT_COMPONENT token (#11372)
|
||||
- [8da24884ec](git@github.com:Alfresco/alfresco-ng2-components/commit/8da24884ec) AAE-40703 Add support for content projection (#11462)
|
||||
- [0f9969a387](git@github.com:Alfresco/alfresco-ng2-components/commit/0f9969a387) AAE-39668 Add ability to filter by unlinked processes (#11461)
|
||||
- [f6c7d90578](git@github.com:Alfresco/alfresco-ng2-components/commit/f6c7d90578) AAE-38626 Made cloud services extentable (#11450)
|
||||
- [205b5c7df5](git@github.com:Alfresco/alfresco-ng2-components/commit/205b5c7df5) AAE-40700 Add remapping icons support (#11449)
|
||||
- [7dddbf7d91](git@github.com:Alfresco/alfresco-ng2-components/commit/7dddbf7d91) [ACS-10232][ACS-10326] Fix focus trap for search filters (#11447)
|
||||
- [8a7359c769](git@github.com:Alfresco/alfresco-ng2-components/commit/8a7359c769) Update Simpleapp (#11448)
|
||||
- [7eb2034008](git@github.com:Alfresco/alfresco-ng2-components/commit/7eb2034008) AAE-40093 Support defining translations from code (#11442)
|
||||
- [68ab5b1c16](git@github.com:Alfresco/alfresco-ng2-components/commit/68ab5b1c16) AAE-39923 Placholeder is formatted according to the enableFractions (#11441)
|
||||
- [ec7ede3830](git@github.com:Alfresco/alfresco-ng2-components/commit/ec7ede3830) AAE-40544 Add ability to filter out subprocesses (#11445)
|
||||
- [34a929ec47](git@github.com:Alfresco/alfresco-ng2-components/commit/34a929ec47) [AAE-40654] added space for label (#11443)
|
||||
- [8c0d5fc8a1](git@github.com:Alfresco/alfresco-ng2-components/commit/8c0d5fc8a1) [ACS-10282] screen reader personal files perform actions empty state not announced by screen reader (#11444)
|
||||
- [8fa3e6acdf](git@github.com:Alfresco/alfresco-ng2-components/commit/8fa3e6acdf) [MNT-25408]: updates changing search config logic; exposes stream for active filters (#11386)
|
||||
- [6567c02220](git@github.com:Alfresco/alfresco-ng2-components/commit/6567c02220) AAE-40269 Cleanup deprecated global sass mixins (#11420)
|
||||
- [9717a88818](git@github.com:Alfresco/alfresco-ng2-components/commit/9717a88818) [ACS-10226] Improve color contrast for better accessibility (#11429)
|
||||
- [58591c67dc](git@github.com:Alfresco/alfresco-ng2-components/commit/58591c67dc) [ACS-10835] Add new param for recent filters in custom resources services (#11428)
|
||||
- [ab0cb46065](git@github.com:Alfresco/alfresco-ng2-components/commit/ab0cb46065) AAE-40641 Upgarde Nx Workspace to latest (v22) (#11440)
|
||||
- [de62fe181a](git@github.com:Alfresco/alfresco-ng2-components/commit/de62fe181a) [MNT-24950] Preview a file from APS doesn't work in ADW (#11439)
|
||||
- [cc053a76ae](git@github.com:Alfresco/alfresco-ng2-components/commit/cc053a76ae) AAE-40540 fixing tab misplacement issue on ADW (#11427)
|
||||
- [10eae07cc0](git@github.com:Alfresco/alfresco-ng2-components/commit/10eae07cc0) [AAE-39923] provide transformed placeholder if possible (#11422)
|
||||
- [4dab69d4dc](git@github.com:Alfresco/alfresco-ng2-components/commit/4dab69d4dc) Revert "[ACS-10281] a11y fix - Approve step folder control is focusable twice…" (#11424)
|
||||
- [e6fe929b02](git@github.com:Alfresco/alfresco-ng2-components/commit/e6fe929b02) [ACS-10260] Add required format to search date range (#11423)
|
||||
- [40df22b576](git@github.com:Alfresco/alfresco-ng2-components/commit/40df22b576) AAE-40028 Added improvement to ignore field validation if it is inside a group/section that is hidden (#11362)
|
||||
- [06d8f48862](git@github.com:Alfresco/alfresco-ng2-components/commit/06d8f48862) AAE-40492 Align chip content in cardview arrayitem component (#11421)
|
||||
- [5625cf72d6](git@github.com:Alfresco/alfresco-ng2-components/commit/5625cf72d6) AAE-40254 Remove excludeByProcessCategoryName input (#11406)
|
||||
- [f379d99474](git@github.com:Alfresco/alfresco-ng2-components/commit/f379d99474) [ACS-10281] a11y fix - Approve step folder control is focusable twice causing duplicate screen reader (#11385)
|
||||
- [f317374a2e](git@github.com:Alfresco/alfresco-ng2-components/commit/f317374a2e) [ACS-10306] Proper alt for user or group icons (#11403)
|
||||
- [a9efe36e5f](git@github.com:Alfresco/alfresco-ng2-components/commit/a9efe36e5f) AAE-40427 Replace shelljs with native node api (#11404)
|
||||
- [c5f3008301](git@github.com:Alfresco/alfresco-ng2-components/commit/c5f3008301) [MNT-25276] sorting using sorting key configuration is not correctly saved in localstorage (#11383)
|
||||
- [514754d0eb](git@github.com:Alfresco/alfresco-ng2-components/commit/514754d0eb) AAE-40395 Security fixes (#11400)
|
||||
- [57090bd76e](git@github.com:Alfresco/alfresco-ng2-components/commit/57090bd76e) Stabilize data conversion methods for rows and columns in datatable (#11398)
|
||||
- [0f911b1259](git@github.com:Alfresco/alfresco-ng2-components/commit/0f911b1259) CSX-268 Remove outdated css rule (#11397)
|
||||
- [91447f8646](git@github.com:Alfresco/alfresco-ng2-components/commit/91447f8646) [ACS-10765] Switch to NPM trusted publishing (#11388)
|
||||
- [533bf89b18](git@github.com:Alfresco/alfresco-ng2-components/commit/533bf89b18) Revert "AAE-40254 Remove excludeByProcessCategoryName input (#11392)" (#11395)
|
||||
- [f5f7c04a85](git@github.com:Alfresco/alfresco-ng2-components/commit/f5f7c04a85) [ACS-10219] add class selector (#11387)
|
||||
- [3d07d7e942](git@github.com:Alfresco/alfresco-ng2-components/commit/3d07d7e942) AAE-40254 Remove excludeByProcessCategoryName input (#11392)
|
||||
- [2009a4ec27](git@github.com:Alfresco/alfresco-ng2-components/commit/2009a4ec27) AAE-40356 Fix misaligned datetime card view element (#11391)
|
||||
- [dbdc402756](git@github.com:Alfresco/alfresco-ng2-components/commit/dbdc402756) AAE-40078 Fix visibility condition not working (#11389)
|
||||
- [f63f0a85c0](git@github.com:Alfresco/alfresco-ng2-components/commit/f63f0a85c0) [ACS-10765] Enable workflow_dispatch for release workflow (#11390)
|
||||
- [3031ec1f66](git@github.com:Alfresco/alfresco-ng2-components/commit/3031ec1f66) AAE-39988 Dropdown conditional not working for repeatable section (#11360)
|
||||
- [c68f638992](git@github.com:Alfresco/alfresco-ng2-components/commit/c68f638992) AAE-39796 Reduce customizations of card view fields (#11373)
|
||||
- [eff64284e9](git@github.com:Alfresco/alfresco-ng2-components/commit/eff64284e9) Revert "AAE-39923 Placeholder transformed with currency based on locale (#11342)" (#11370)
|
||||
- [9a6cd813de](git@github.com:Alfresco/alfresco-ng2-components/commit/9a6cd813de) ACS-10745 File size columns not translating the tooltips (#11368)
|
||||
- [03f67c861f](git@github.com:Alfresco/alfresco-ng2-components/commit/03f67c861f) [ACS-10740] Adjust Karma and Jest config (#11365)
|
||||
- [58a25fe19e](git@github.com:Alfresco/alfresco-ng2-components/commit/58a25fe19e) AAE-40136 Migrate locale settings to signals (#11361)
|
||||
- [2f5139df73](git@github.com:Alfresco/alfresco-ng2-components/commit/2f5139df73) fix post release version bump
|
||||
- [9fd304b66d](git@github.com:Alfresco/alfresco-ng2-components/commit/9fd304b66d) post release version bump (#11366)
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
Title: Changelog for alfresco-ng2-components v8.4.1
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
- [af95723f30](https://github.com/Alfresco/alfresco-ng2-components/commit/af95723f30) [ACS-11589] [ACA] info drawer test-area does not show full text (#11816)
|
||||
- [d70ae599c7](https://github.com/Alfresco/alfresco-ng2-components/commit/d70ae599c7) Fix security vulnerabilities in npm dependencies (#11815)
|
||||
- [07c6a4d923](https://github.com/Alfresco/alfresco-ng2-components/commit/07c6a4d923) Remove jasmine-spec-reporter dependency from package.json and package-lock.json (#11814)
|
||||
- [6fc8dda887](https://github.com/Alfresco/alfresco-ng2-components/commit/6fc8dda887) Remove mocha and jasmine-ajax dependencies (#11813)
|
||||
- [48eb258311](https://github.com/Alfresco/alfresco-ng2-components/commit/48eb258311) AAE-44184 Colspan setting on form fields is ignored or not properly applied (#11800)
|
||||
- [32850a0ce8](https://github.com/Alfresco/alfresco-ng2-components/commit/32850a0ce8) [MNT-25185] Display authority name instead of id if provided (#11809)
|
||||
- [8a6bcac29e](https://github.com/Alfresco/alfresco-ng2-components/commit/8a6bcac29e) [ACS-11506]: moved aria-live region (#11808)
|
||||
- [8ce0561ef5](https://github.com/Alfresco/alfresco-ng2-components/commit/8ce0561ef5) AAE-44086 Unify styling and coloring of errors in forms (#11797)
|
||||
- [69a9dc1386](https://github.com/Alfresco/alfresco-ng2-components/commit/69a9dc1386) AAE-44002 Allow user input for date and datetime fields (#11791)
|
||||
- [70a6f42649](https://github.com/Alfresco/alfresco-ng2-components/commit/70a6f42649) AAE-40741 Form rule `Validate form` doesn't do anything (#11788)
|
||||
- [74252797b7](https://github.com/Alfresco/alfresco-ng2-components/commit/74252797b7) AAE-28918 Fix for start process button is enabled when required widgets are read only without value (#11781)
|
||||
- [79871455f4](https://github.com/Alfresco/alfresco-ng2-components/commit/79871455f4) [ACS-10242] SR: Personal files: Filter by Size popup announces entire content instead of dialog title (#11782)
|
||||
- [d7a8f03dbf](https://github.com/Alfresco/alfresco-ng2-components/commit/d7a8f03dbf) AAE-43749 Added date formatting according to locale (#11769)
|
||||
- [a3e13da3a4](https://github.com/Alfresco/alfresco-ng2-components/commit/a3e13da3a4) [ACS-10280]: Keyboard Navigation: Search: Unnecessary stops in the results table using the Tab key (#11736)
|
||||
- [565db01819](https://github.com/Alfresco/alfresco-ng2-components/commit/565db01819) [MNT-25635] Search filter autocomplete search for tags when input changes (#11780)
|
||||
- [f321b74be0](https://github.com/Alfresco/alfresco-ng2-components/commit/f321b74be0) AAE-21162 Add deploymentCompletion property to ApplicationInstance model (#11784)
|
||||
- [28fe6d3a76](https://github.com/Alfresco/alfresco-ng2-components/commit/28fe6d3a76) AAE-43710 Fix form field spacing misalignments (#11763)
|
||||
- [d526d31425](https://github.com/Alfresco/alfresco-ng2-components/commit/d526d31425) AAE-34137 Fix for disabling `complete` button on the form after declining form confirmation dialog (#11766)
|
||||
- [e97439f09b](https://github.com/Alfresco/alfresco-ng2-components/commit/e97439f09b) AAE-43391 Disable 'Start process' and 'Complete' when whitespace is entered into required form fields (#11760)
|
||||
- [bdd4b687c6](https://github.com/Alfresco/alfresco-ng2-components/commit/bdd4b687c6) AAE-43290 updating the minor version for angular in ADF (#11752)
|
||||
- [46989ae081](https://github.com/Alfresco/alfresco-ng2-components/commit/46989ae081) [ACS-11319] Move tree actions menu item buttons inside the component (#11749)
|
||||
- [a50dfd050d](https://github.com/Alfresco/alfresco-ng2-components/commit/a50dfd050d) CSX-460 Revert Remove excess disabled attribute PR (#11748)
|
||||
- [e57910f5c3](https://github.com/Alfresco/alfresco-ng2-components/commit/e57910f5c3) [ACS-11271] Rebranding of FE apps (#11746)
|
||||
- [3bea95b8e0](https://github.com/Alfresco/alfresco-ng2-components/commit/3bea95b8e0) Revert "[ACS-10219] add class selector (#11387)" (#11745)
|
||||
- [adce4cabf5](https://github.com/Alfresco/alfresco-ng2-components/commit/adce4cabf5) [MNT-25447] Fix: Viewing preview renditions for versions fails (#11747)
|
||||
- [ebf742c54b](https://github.com/Alfresco/alfresco-ng2-components/commit/ebf742c54b) AAE-43331 Expand adf-icon (#11744)
|
||||
- [759d206302](https://github.com/Alfresco/alfresco-ng2-components/commit/759d206302) HXIDP-6471 Provide start process variables to custom screen (#11712)
|
||||
- [a865372819](https://github.com/Alfresco/alfresco-ng2-components/commit/a865372819) [ACS-10267] Announce titles for repository info as headings (#11728)
|
||||
- [2bab587876](https://github.com/Alfresco/alfresco-ng2-components/commit/2bab587876) [ACS-11205] Bring back removed getter (#11735)
|
||||
- [e325ad3871](https://github.com/Alfresco/alfresco-ng2-components/commit/e325ad3871) AAE-39678 Apply visibility conditions if dependent field's value is changed with form rules (#11729)
|
||||
- [a8ae3d3b4e](https://github.com/Alfresco/alfresco-ng2-components/commit/a8ae3d3b4e) AAE-42908 Evaluate expressions for rich-text-display list types (#11726)
|
||||
- [bc41c33ba8](https://github.com/Alfresco/alfresco-ng2-components/commit/bc41c33ba8) [ACS-11205] Add LazyApi decorator (#11711)
|
||||
- [83e80906d8](https://github.com/Alfresco/alfresco-ng2-components/commit/83e80906d8) [ACS-11213] upgrade ngx translate to v17 (#11719)
|
||||
- [ef5944a09c](https://github.com/Alfresco/alfresco-ng2-components/commit/ef5944a09c) Post-release version bump (#11734)
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
Title: Changelog for alfresco-ng2-components v8.5.0
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
- [ec04358796](https://github.com/Alfresco/alfresco-ng2-components/commit/ec04358796) AAE-46943 Rename git signing secret/vars to HXPS_GIT_* (#11978)
|
||||
- [49a28b357c](https://github.com/Alfresco/alfresco-ng2-components/commit/49a28b357c) AAE-46943 Sign Crowdin translation PR commits with GPG (#11974)
|
||||
- [dd9e58ddaa](https://github.com/Alfresco/alfresco-ng2-components/commit/dd9e58ddaa) [ACS-11927] init acs aps scripts update terraform (#11976)
|
||||
- [c723e19b6d](https://github.com/Alfresco/alfresco-ng2-components/commit/c723e19b6d) AAE-46971 Update Supply Chain Review GH AW to latest (#11972)
|
||||
- [bb6f9b1f3d](https://github.com/Alfresco/alfresco-ng2-components/commit/bb6f9b1f3d) AAE-46434 Fix disabled stying for people widgets (#11967)
|
||||
- [7bb219e4dd](https://github.com/Alfresco/alfresco-ng2-components/commit/7bb219e4dd) AAE-46654 Fix - return empty string when no value is provided in card… (#11969)
|
||||
- [70038bea26](https://github.com/Alfresco/alfresco-ng2-components/commit/70038bea26) AAE-46246 Format typed values in form display widgets v2 (#11952)
|
||||
- [5ad3dca38d](https://github.com/Alfresco/alfresco-ng2-components/commit/5ad3dca38d) AAE-46684 fix release workflow eslint publish fix provenance (#11963)
|
||||
- [fd3802f2dc](https://github.com/Alfresco/alfresco-ng2-components/commit/fd3802f2dc) AAE-46684 fix release workflow eslint publish fix (#11962)
|
||||
- [a8eee9fe3a](https://github.com/Alfresco/alfresco-ng2-components/commit/a8eee9fe3a) Improvements/aae 46684 fix release workflow fixed command (#11961)
|
||||
- [0a7fa14d0f](https://github.com/Alfresco/alfresco-ng2-components/commit/0a7fa14d0f) Improvements/aae 46684 fix release workflow ignore (#11960)
|
||||
- [4dde6d2a45](https://github.com/Alfresco/alfresco-ng2-components/commit/4dde6d2a45) [AAE-46514] - Fix release workflow (#11959)
|
||||
- [78661f11c5](https://github.com/Alfresco/alfresco-ng2-components/commit/78661f11c5) [AAE-46514] - Migration to PNPM (#11926)
|
||||
- [faf9d3faac](https://github.com/Alfresco/alfresco-ng2-components/commit/faf9d3faac) AAE-46388 Update Supply Chain Review GH AW to latest (#11957)
|
||||
- [5c8eb21ab3](https://github.com/Alfresco/alfresco-ng2-components/commit/5c8eb21ab3) AAE-46387 Standardize DependaBot config schedule/grouping (#11953)
|
||||
- [7d76d789b2](https://github.com/Alfresco/alfresco-ng2-components/commit/7d76d789b2) AAE-41418 Add process instance id input to task header cloud component (#11897)
|
||||
- [a71cc84f11](https://github.com/Alfresco/alfresco-ng2-components/commit/a71cc84f11) AAE-46507 Next Task Endpoint (#11943)
|
||||
- [34acdd20cf](https://github.com/Alfresco/alfresco-ng2-components/commit/34acdd20cf) Revert "AAE-46246 Format typed values in form display widgets (#11935)" (#11951)
|
||||
- [f39b9167b8](https://github.com/Alfresco/alfresco-ng2-components/commit/f39b9167b8) AAE-46246 Format typed values in form display widgets (#11935)
|
||||
- [aa2a357fb2](https://github.com/Alfresco/alfresco-ng2-components/commit/aa2a357fb2) AAE-46434 Fix read-only field styling on forms (#11928)
|
||||
- [f9899883dc](https://github.com/Alfresco/alfresco-ng2-components/commit/f9899883dc) Revert AAE-46242 crowdin locale mapping changes (#11949)
|
||||
- [46b2d0380b](https://github.com/Alfresco/alfresco-ng2-components/commit/46b2d0380b) AAE-45774 Shorten invalid date error message (#11920)
|
||||
- [274ddb3098](https://github.com/Alfresco/alfresco-ng2-components/commit/274ddb3098) AAE-46386 Set DependaBot cooldown for all ecosystems as 3d (#11947)
|
||||
- [f602070f1e](https://github.com/Alfresco/alfresco-ng2-components/commit/f602070f1e) AAE-46388 Fix DependaBot config to ignore gh-aw-actions (#11946)
|
||||
- [d206d28f1c](https://github.com/Alfresco/alfresco-ng2-components/commit/d206d28f1c) [AAE-32905] Fix commit messages commands aren't working (#11922)
|
||||
- [80e9e51cfa](https://github.com/Alfresco/alfresco-ng2-components/commit/80e9e51cfa) AAE-46242 - Looks like we need to override the mapping as crowding config is not set to this format (#11939)
|
||||
- [345e1e69ad](https://github.com/Alfresco/alfresco-ng2-components/commit/345e1e69ad) AAE-46242 - should use the variable osx_locale to match the format xx-YY (#11936)
|
||||
- [a2b026ed7e](https://github.com/Alfresco/alfresco-ng2-components/commit/a2b026ed7e) [AAE-46242] - Changed the name convention for translation files to ISO standard naming (#11924)
|
||||
- [e40fd2250e](https://github.com/Alfresco/alfresco-ng2-components/commit/e40fd2250e) AAE-46388 Add Supply Chain Review agentic workflow (#11927)
|
||||
- [cfdd3f9c50](https://github.com/Alfresco/alfresco-ng2-components/commit/cfdd3f9c50) MD3 migration fixes (#11919)
|
||||
- [1314f0751f](https://github.com/Alfresco/alfresco-ng2-components/commit/1314f0751f) AAE-46476 Fix sorting functionality of task list retrieval from runtime bundle (#11921)
|
||||
- [f4882e99be](https://github.com/Alfresco/alfresco-ng2-components/commit/f4882e99be) Revert "New Crowdin translations by GitHub Action (#11796)" (#11923)
|
||||
- [b5d2de583d](https://github.com/Alfresco/alfresco-ng2-components/commit/b5d2de583d) build(deps): update 3rd party dependencies (#11916)
|
||||
- [70f90c65a5](https://github.com/Alfresco/alfresco-ng2-components/commit/70f90c65a5) AAE-46392 Fix card view select item crash on numeric initial value (#11917)
|
||||
- [f339647f40](https://github.com/Alfresco/alfresco-ng2-components/commit/f339647f40) refactor: migrate license checks off license-checker (#11905)
|
||||
- [a7fa68056d](https://github.com/Alfresco/alfresco-ng2-components/commit/a7fa68056d) chore: remove unused @nx/node dependency (#11895)
|
||||
- [8280aa2f6d](https://github.com/Alfresco/alfresco-ng2-components/commit/8280aa2f6d) chore: update NX packages to version 22.7.2 and related dependencies (#11904)
|
||||
- [5553aaaefe](https://github.com/Alfresco/alfresco-ng2-components/commit/5553aaaefe) [MNT-25522] Add support for fileLink icon (#11903)
|
||||
- [15814380a5](https://github.com/Alfresco/alfresco-ng2-components/commit/15814380a5) [ci:force] AAE-46219 [TEST] Revert cli build/installDeps changes from #11880 and #11899 (#11901)
|
||||
- [4044fafc39](https://github.com/Alfresco/alfresco-ng2-components/commit/4044fafc39) AAE-46219 Skip prod deps in cli:installDeps to unblock release (#11899)
|
||||
- [ece50ac32c](https://github.com/Alfresco/alfresco-ng2-components/commit/ece50ac32c) [MNT-25149] Card view select item multivalued property support (#11891)
|
||||
- [1d163c6749](https://github.com/Alfresco/alfresco-ng2-components/commit/1d163c6749) Revert "AAE-44065 Change date picker to match other styles (#11868)" (#11896)
|
||||
- [1fbd869902](https://github.com/Alfresco/alfresco-ng2-components/commit/1fbd869902) chore: remove unused eslint-plugin-prefer-arrow (#11894)
|
||||
- [165d0fc521](https://github.com/Alfresco/alfresco-ng2-components/commit/165d0fc521) chore: remove unused moment dependency (#11893)
|
||||
- [64d9f3a6d4](https://github.com/Alfresco/alfresco-ng2-components/commit/64d9f3a6d4) AAE-45774 Show error for date fields if invalid format (#11886)
|
||||
- [9e106b006c](https://github.com/Alfresco/alfresco-ng2-components/commit/9e106b006c) AAE-43881 Fix for form rules not applying when new [data] comes in (#11879)
|
||||
- [8309d2dc55](https://github.com/Alfresco/alfresco-ng2-components/commit/8309d2dc55) AAE-44065 Change date picker to match other styles (#11868)
|
||||
- [e3430ae36e](https://github.com/Alfresco/alfresco-ng2-components/commit/e3430ae36e) AAE-45695 Group @typescript-eslint/* packages in dependabot (#11880)
|
||||
- [1860fefd42](https://github.com/Alfresco/alfresco-ng2-components/commit/1860fefd42) [MNT-25647] Handle facets label wrapped in quotes (#11866)
|
||||
- [9fe4006a0d](https://github.com/Alfresco/alfresco-ng2-components/commit/9fe4006a0d) AAE-45391 Lazy loading and improvements for pdfJS (#11869)
|
||||
- [62fb51e910](https://github.com/Alfresco/alfresco-ng2-components/commit/62fb51e910) Update CODEOWNERS
|
||||
- [b7783d2259](https://github.com/Alfresco/alfresco-ng2-components/commit/b7783d2259) AAE-39830 Removing Material components color property (#11865)
|
||||
- [410490158f](https://github.com/Alfresco/alfresco-ng2-components/commit/410490158f) AAE-30881 Remove jsrassign (#11863)
|
||||
- [57bf066164](https://github.com/Alfresco/alfresco-ng2-components/commit/57bf066164) AAE-30882 Remove superagent for fetch (#11856)
|
||||
- [9cdacf3ebf](https://github.com/Alfresco/alfresco-ng2-components/commit/9cdacf3ebf) AAE-45312 Removing propagate job from release workflow (#11864)
|
||||
- [8821980913](https://github.com/Alfresco/alfresco-ng2-components/commit/8821980913) AAE-38566 Remove globals mixin (#11798)
|
||||
- [a73b100fae](https://github.com/Alfresco/alfresco-ng2-components/commit/a73b100fae) AAE-45003 Extend task cloud services (#11850)
|
||||
- [2649cdea2d](https://github.com/Alfresco/alfresco-ng2-components/commit/2649cdea2d) AAE-44003 Allow manual input for date field (#11830)
|
||||
- [3a543d8a0a](https://github.com/Alfresco/alfresco-ng2-components/commit/3a543d8a0a) AAE-32905 Rework pr pipeline (#11853)
|
||||
- [3fc59b2358](https://github.com/Alfresco/alfresco-ng2-components/commit/3fc59b2358) AAE-45216 Removing custom theme from core (#11862)
|
||||
- [337b82e988](https://github.com/Alfresco/alfresco-ng2-components/commit/337b82e988) AAE-45215 Removing unused breadcrumb theme (#11861)
|
||||
- [0faa2e1a56](https://github.com/Alfresco/alfresco-ng2-components/commit/0faa2e1a56) [AAE-0000] - fixed run for process-service-cloud (#11855)
|
||||
- [d6262eafc6](https://github.com/Alfresco/alfresco-ng2-components/commit/d6262eafc6) [ACS-11628] small for for init-acs-env.ts (#11860)
|
||||
- [d3ad66d25b](https://github.com/Alfresco/alfresco-ng2-components/commit/d3ad66d25b) AAE-44435 Fix incorrect Start process button on user task forms (#11837)
|
||||
- [aa2de3bde6](https://github.com/Alfresco/alfresco-ng2-components/commit/aa2de3bde6) AAE-45173 Adding background color to tooltip card (#11852)
|
||||
- [d1d06a68bc](https://github.com/Alfresco/alfresco-ng2-components/commit/d1d06a68bc) AAE-44098 Bottom tab navigation buttons (#11834)
|
||||
- [0a6da1ba13](https://github.com/Alfresco/alfresco-ng2-components/commit/0a6da1ba13) AAE-45076 Fix svg icon style (#11849)
|
||||
- [d3ac5362ba](https://github.com/Alfresco/alfresco-ng2-components/commit/d3ac5362ba) AAE-44946 - Sending also previous value to allow valuation and valida… (#11836)
|
||||
- [ddb8adc0e4](https://github.com/Alfresco/alfresco-ng2-components/commit/ddb8adc0e4) AAE-44752 Add type to ProcessInstanceCloud (#11847)
|
||||
- [85005c9c1c](https://github.com/Alfresco/alfresco-ng2-components/commit/85005c9c1c) AAE-44987 Applying color and background to sidenav (#11846)
|
||||
- [407c6c1829](https://github.com/Alfresco/alfresco-ng2-components/commit/407c6c1829) [ACS-11350] keyboard navigation user incorrect focus order after collapsing the left navigation menu (#11835)
|
||||
- [e3fc03c58d](https://github.com/Alfresco/alfresco-ng2-components/commit/e3fc03c58d) Revert "AAE-44098 Bottom Tab nav buttons (#11801)" (#11832)
|
||||
- [510a813ed2](https://github.com/Alfresco/alfresco-ng2-components/commit/510a813ed2) [ACS-11472] Fix file icon is not updated for version renditions (#11807)
|
||||
- [7864f1a8e0](https://github.com/Alfresco/alfresco-ng2-components/commit/7864f1a8e0) AAE-44098 Bottom Tab nav buttons (#11801)
|
||||
- [c09edd71ff](https://github.com/Alfresco/alfresco-ng2-components/commit/c09edd71ff) AAE-44761 Remove unused imports (#11829)
|
||||
- [64826c3a99](https://github.com/Alfresco/alfresco-ng2-components/commit/64826c3a99) AAE-40649 Material Design 3 migration (#11286)
|
||||
- [423c646bac](https://github.com/Alfresco/alfresco-ng2-components/commit/423c646bac) Post release version bump (#11828)
|
||||
@@ -40,21 +40,6 @@ ADF is based on Angular Material library, which offers solutions for theming you
|
||||
|
||||
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.
|
||||
|
||||
## Customizing deprecated theme variables
|
||||
|
||||
Currently we have an amount of custom variables around components to mange libraries look and feel consistently and globally.
|
||||
|
||||
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.
|
||||
|
||||
For example:
|
||||
```css
|
||||
:root {
|
||||
--theme-primary-color: --mat-sys-primary;
|
||||
--theme-accent-color: --mat-sys-tertiary;
|
||||
}
|
||||
```
|
||||
**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
|
||||
@@ -73,14 +58,14 @@ For example:
|
||||
|
||||
Avoid adding css variables with names related to components:
|
||||
```
|
||||
--my-component-nr-xxx-background-color: mat.get-color-from-palette($primary, 50), // bad
|
||||
--theme-primary-color-50: mat.get-color-from-palette($primary, 50) // good
|
||||
--my-component-nr-xxx-background-color: var(--mat-sys-primary), // bad
|
||||
--theme-primary-color-50: var(--mat-sys-primary) // good
|
||||
```
|
||||
|
||||
Avoid adding css variables with custom values, values should come from the theme:
|
||||
```
|
||||
--new-variable: yellow // bad
|
||||
--new-variable: mat.get-color-from-palette($primary, 50), // good
|
||||
--new-variable: var(--mat-sys-primary), // good
|
||||
```
|
||||
|
||||
When styling components use Angular Material system variables (colors, typography, elevation):
|
||||
|
||||
@@ -354,7 +354,6 @@ backend services have been tested with each released version of ADF.
|
||||
- [Edit process filter cloud component](process-services-cloud/components/edit-process-filter-cloud.component.md)
|
||||
- [Edit task filter cloud component](process-services-cloud/components/edit-task-filter-cloud.component.md)
|
||||
- [Extension service](extensions/services/extension.service.md)
|
||||
- [File upload error pipe](content-services/pipes/file-upload-error.pipe.md)
|
||||
- [Format space pipe](core/pipes/format-space.pipe.md)
|
||||
- [Full name pipe](core/pipes/full-name.pipe.md)
|
||||
- [Group cloud component](process-services-cloud/components/group-cloud.component.md)
|
||||
@@ -663,7 +662,6 @@ backend services have been tested with each released version of ADF.
|
||||
- [Text mask component](core/components/text-mask.component.md)
|
||||
- [Thumbnail service](core/services/thumbnail.service.md)
|
||||
- [Time ago pipe](core/pipes/time-ago.pipe.md)
|
||||
- [Toggle icon directive](content-services/directives/toggle-icon.directive.md)
|
||||
- [Toolbar divider component](core/components/toolbar-divider.component.md)
|
||||
- [Toolbar title component](core/components/toolbar-title.component.md)
|
||||
- [Toolbar component](core/components/toolbar.component.md)
|
||||
|
||||
@@ -57,3 +57,6 @@ The pages linked below contain the audit for all third party dependencies of ADF
|
||||
- [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)
|
||||
- [ADF 8.3.1](audit-info-8.3.1.md)
|
||||
- [ADF 8.4.1](audit-info-8.4.1.md)
|
||||
- [ADF 8.5.0](audit-info-8.5.0.md)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
Title: Audit info, alfresco-ng2-components 8.3.1
|
||||
---
|
||||
|
||||
# Audit information for alfresco-ng2-components 8.3.1
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: 0
|
||||
- High risk: 0
|
||||
- Moderate risk: 0
|
||||
- Low risk: 0
|
||||
|
||||
Dependencies analyzed:
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
Title: Audit info, alfresco-ng2-components 8.4.1
|
||||
---
|
||||
|
||||
# Audit information for alfresco-ng2-components 8.4.1
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: 0
|
||||
- High risk: 0
|
||||
- Moderate risk: 0
|
||||
- Low risk: 0
|
||||
|
||||
Dependencies analyzed:
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
Title: Audit info, alfresco-ng2-components 8.4.1
|
||||
---
|
||||
|
||||
# Audit information for alfresco-ng2-components 8.5.0
|
||||
|
||||
This page lists the security audit of the dependencies this project depends on.
|
||||
|
||||
## Risks
|
||||
|
||||
- Critical risk: 0
|
||||
- High risk: 0
|
||||
- Moderate risk: 0
|
||||
- Low risk: 0
|
||||
|
||||
Dependencies analyzed:
|
||||
|
||||
## Libraries
|
||||
|
||||
| Severity | Module | Vulnerable versions |
|
||||
| --- | --- | --- |
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"createDefaultProgram": true
|
||||
},
|
||||
"rules": {
|
||||
"prefer-arrow/prefer-arrow-functions": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/naming-convention": "warn",
|
||||
"quote-props": "off",
|
||||
|
||||
Generated
-1239
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.3.0",
|
||||
"version": "9.0.0",
|
||||
"author": "Hyland Software, Inc. and its affiliates",
|
||||
"bin": {
|
||||
"adf-cli": "bin/adf-cli",
|
||||
@@ -22,9 +22,8 @@
|
||||
"unlink": "cd ../../dist/libs/cli && npm unlink"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alfresco/js-api": ">=9.2.0",
|
||||
"@alfresco/js-api": ">=9.5.0",
|
||||
"ejs": "^3.1.10",
|
||||
"license-checker": "^25.0.1",
|
||||
"node-fetch": "^2.7.0",
|
||||
"spdx-license-list": "^5.0.0"
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "nx:run-commands",
|
||||
"outputs": ["{workspaceRoot}/dist/libs/cli"],
|
||||
"options": {
|
||||
"command": "cd lib/cli && npm run dist"
|
||||
},
|
||||
@@ -30,6 +31,7 @@
|
||||
},
|
||||
"copyToNodeModules": {
|
||||
"executor": "nx:run-commands",
|
||||
"cache": false,
|
||||
"options": {
|
||||
"commands": [
|
||||
{
|
||||
@@ -62,7 +64,7 @@
|
||||
"cwd": "dist/libs/cli",
|
||||
"commands": [
|
||||
{
|
||||
"command": "npm publish --tag {args.tag}",
|
||||
"command": "pnpm publish --no-git-checks --tag {args.tag}",
|
||||
"forwardAllArgs": true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
function readJson(filePath) {
|
||||
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
}
|
||||
|
||||
function resolvePackageJson(packageName, fromDirectory) {
|
||||
try {
|
||||
return require.resolve(`${packageName}/package.json`, {
|
||||
paths: [fromDirectory]
|
||||
});
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function getRepositoryUrl(repository) {
|
||||
if (typeof repository === 'string') {
|
||||
return repository;
|
||||
}
|
||||
|
||||
if (repository && typeof repository === 'object' && typeof repository.url === 'string') {
|
||||
return repository.url;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getRawLicenseExpression(packageJson) {
|
||||
if (typeof packageJson.license === 'string' && packageJson.license.trim()) {
|
||||
return packageJson.license.trim();
|
||||
}
|
||||
|
||||
if (packageJson.license && typeof packageJson.license === 'object' && typeof packageJson.license.type === 'string') {
|
||||
return packageJson.license.type.trim();
|
||||
}
|
||||
|
||||
if (Array.isArray(packageJson.licenses)) {
|
||||
const values = packageJson.licenses
|
||||
.map((entry) => {
|
||||
if (typeof entry === 'string') {
|
||||
return entry.trim();
|
||||
}
|
||||
|
||||
if (entry && typeof entry === 'object' && typeof entry.type === 'string') {
|
||||
return entry.type.trim();
|
||||
}
|
||||
|
||||
return '';
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
if (values.length > 0) {
|
||||
return values.join(' OR ');
|
||||
}
|
||||
}
|
||||
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
|
||||
function extractLicenseTokens(rawExpression) {
|
||||
const tokens = (rawExpression || '').match(/[A-Za-z0-9-.+]+/g) || [];
|
||||
const operators = new Set(['AND', 'OR', 'WITH']);
|
||||
|
||||
return tokens.map((token) => token.toUpperCase()).filter((token) => !operators.has(token));
|
||||
}
|
||||
|
||||
function hasDeniedLicense(rawExpression, denyList) {
|
||||
const licenseTokens = extractLicenseTokens(rawExpression);
|
||||
|
||||
return denyList.some((rule) => {
|
||||
const normalizedRule = (rule || '').trim().toUpperCase();
|
||||
if (!normalizedRule) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Treat common copyleft family keywords as SPDX id prefixes.
|
||||
if (normalizedRule === 'GPL' || normalizedRule === 'LGPL' || normalizedRule === 'AGPL') {
|
||||
return licenseTokens.some((token) => token === normalizedRule || token.startsWith(`${normalizedRule}-`));
|
||||
}
|
||||
|
||||
// Support explicit wildcard rules like "GPL-*".
|
||||
if (normalizedRule.endsWith('*')) {
|
||||
const prefix = normalizedRule.slice(0, -1);
|
||||
return prefix.length > 0 && licenseTokens.some((token) => token.startsWith(prefix));
|
||||
}
|
||||
|
||||
// Otherwise require exact SPDX token match.
|
||||
return licenseTokens.includes(normalizedRule);
|
||||
});
|
||||
}
|
||||
|
||||
function getDependencyNames(packageJson) {
|
||||
return Array.from(new Set([...Object.keys(packageJson.dependencies || {}), ...Object.keys(packageJson.optionalDependencies || {})]));
|
||||
}
|
||||
|
||||
function collectProductionLicenses(packagePath, options = {}) {
|
||||
const packageJsonFile = readJson(packagePath);
|
||||
const mainDependencies = getDependencyNames(packageJsonFile);
|
||||
const packageDirectory = path.dirname(packagePath);
|
||||
const missingRepositories = options.missingRepositories || {};
|
||||
const denyList = options.denyList || [];
|
||||
|
||||
const queue = mainDependencies.map((name) => ({
|
||||
name,
|
||||
fromDirectory: packageDirectory
|
||||
}));
|
||||
|
||||
const visited = new Set();
|
||||
const packages = [];
|
||||
const deniedPackages = [];
|
||||
|
||||
for (const current of queue) {
|
||||
const packageJsonPath = resolvePackageJson(current.name, current.fromDirectory);
|
||||
|
||||
if (!packageJsonPath || !fs.existsSync(packageJsonPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const currentPackage = readJson(packageJsonPath);
|
||||
const name = currentPackage.name || current.name;
|
||||
const version = currentPackage.version || 'unknown';
|
||||
const packageFolder = path.dirname(packageJsonPath);
|
||||
const uniqueKey = `${name}@${version}:${packageFolder}`;
|
||||
|
||||
if (visited.has(uniqueKey)) {
|
||||
continue;
|
||||
}
|
||||
visited.add(uniqueKey);
|
||||
|
||||
const rawLicenseExpression = getRawLicenseExpression(currentPackage);
|
||||
const packageKey = `${name}@${version}`;
|
||||
const repository = getRepositoryUrl(currentPackage.repository) || missingRepositories[name] || '';
|
||||
|
||||
const record = {
|
||||
key: packageKey,
|
||||
name,
|
||||
version,
|
||||
repository,
|
||||
rawLicenseExpression,
|
||||
dependencies: currentPackage.dependencies || {},
|
||||
optionalDependencies: currentPackage.optionalDependencies || {}
|
||||
};
|
||||
|
||||
packages.push(record);
|
||||
|
||||
if (hasDeniedLicense(rawLicenseExpression, denyList)) {
|
||||
deniedPackages.push(`${packageKey}: ${rawLicenseExpression}`);
|
||||
}
|
||||
|
||||
const dependencies = getDependencyNames(currentPackage);
|
||||
for (const dependencyName of dependencies) {
|
||||
queue.push({
|
||||
name: dependencyName,
|
||||
fromDirectory: packageFolder
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
packages.sort((a, b) => {
|
||||
const nameCompare = a.name.localeCompare(b.name);
|
||||
if (nameCompare !== 0) {
|
||||
return nameCompare;
|
||||
}
|
||||
|
||||
return a.version.localeCompare(b.version);
|
||||
});
|
||||
|
||||
return { packages, deniedPackages };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
collectProductionLicenses
|
||||
};
|
||||
+269
-140
@@ -28,12 +28,16 @@ interface InitAcsEnvArgs {
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
const MAX_RETRY = 10;
|
||||
let counter = 0;
|
||||
const TIMEOUT = 6000;
|
||||
const RETRY_DELAY_MS = 6000;
|
||||
const ACS_DEFAULT = require('./resources').ACS_DEFAULT;
|
||||
|
||||
let alfrescoJsApi: AlfrescoApi;
|
||||
let nodesApi: NodesApi;
|
||||
let uploadApi: UploadApi;
|
||||
let sharedlinksApi: SharedlinksApi;
|
||||
let favoritesApi: FavoritesApi;
|
||||
|
||||
/**
|
||||
* Init ACS environment command
|
||||
@@ -46,7 +50,6 @@ 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
|
||||
@@ -56,11 +59,6 @@ Options:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
@@ -92,160 +90,293 @@ Options:
|
||||
|
||||
await checkEnv(opts);
|
||||
|
||||
logger.info(`***** Step initialize ACS *****`);
|
||||
logger.info('***** Step initialize ACS *****');
|
||||
await initializeDefaultFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup default files
|
||||
* Initialize default files. Creates the e2e folder and ensures each file
|
||||
* exists with its required state (locked, shared, favorite).
|
||||
* Idempotent: only creates/modifies what is missing.
|
||||
*/
|
||||
async function initializeDefaultFiles() {
|
||||
const e2eFolder = ACS_DEFAULT.e2eFolder;
|
||||
const parentFolder = await createFolder(e2eFolder.name, '-my-');
|
||||
const parentFolderId = parentFolder.entry.id;
|
||||
const e2eFolderName: string = ACS_DEFAULT.e2eFolder.name;
|
||||
|
||||
for (let j = 0; j < ACS_DEFAULT.files.length; j++) {
|
||||
const fileInfo = ACS_DEFAULT.files[j];
|
||||
switch (fileInfo.action) {
|
||||
case 'UPLOAD': {
|
||||
await uploadFile(fileInfo.name, parentFolderId);
|
||||
break;
|
||||
}
|
||||
case 'LOCK': {
|
||||
const fileToLock = await uploadFile(fileInfo.name, parentFolderId);
|
||||
await lockFile(fileToLock.entry.id);
|
||||
break;
|
||||
}
|
||||
case 'SHARE': {
|
||||
const fileToShare = await uploadFile(fileInfo.name, parentFolderId);
|
||||
await shareFile(fileToShare.entry.id);
|
||||
break;
|
||||
}
|
||||
case 'FAVORITE': {
|
||||
const fileToFav = await uploadFile(fileInfo.name, parentFolderId);
|
||||
await favoriteFile(fileToFav.entry.id);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.error('No action found for file ', fileInfo.name, parentFolderId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create folder
|
||||
*
|
||||
* @param folderName folder name
|
||||
* @param parentId parent folder id
|
||||
*/
|
||||
async function createFolder(folderName: string, parentId: string) {
|
||||
let createdFolder: NodeEntry;
|
||||
const body = {
|
||||
name: folderName,
|
||||
nodeType: 'cm:folder'
|
||||
};
|
||||
let parentFolder: NodeEntry;
|
||||
try {
|
||||
createdFolder = await new NodesApi(alfrescoJsApi).createNode(parentId, body, { overwrite: true });
|
||||
parentFolder = await withRetry(() => ensureFolder(e2eFolderName, '-my-'), `ensure folder ${e2eFolderName}`);
|
||||
} catch (error: any) {
|
||||
logger.warn(`Skipping file initialization: test-data folder could not be created: ${formatError(error)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Folder ${folderName} was created`);
|
||||
} catch (err) {
|
||||
if (err.status === 409) {
|
||||
const relativePath = `/${folderName}`;
|
||||
createdFolder = await new NodesApi(alfrescoJsApi).getNode('-my-', { relativePath });
|
||||
}
|
||||
const parentFolderId = getEntryId(parentFolder, `folder ${e2eFolderName}`);
|
||||
|
||||
for (const fileInfo of ACS_DEFAULT.files) {
|
||||
await withRetry(() => processFile(fileInfo, parentFolderId), `initialize ${fileInfo.name}`);
|
||||
}
|
||||
return createdFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param fileName file name
|
||||
* @param fileDestination destination path
|
||||
* Process a single file: upload if missing, then apply its action (lock/share/favorite).
|
||||
* @param fileInfo file descriptor from ACS_DEFAULT
|
||||
* @param fileInfo.name file name
|
||||
* @param fileInfo.action action to apply (LOCK, SHARE, FAVORITE)
|
||||
* @param parentFolderId parent folder node id
|
||||
*/
|
||||
async function uploadFile(fileName: string, fileDestination: string): Promise<NodeEntry> {
|
||||
async function processFile(fileInfo: { name: string; action: string }, parentFolderId: string) {
|
||||
const existingNode = await findNodeByRelativePath(parentFolderId, fileInfo.name);
|
||||
|
||||
let nodeId: string;
|
||||
if (existingNode?.entry?.id) {
|
||||
logger.info(`File ${fileInfo.name} already exists, verifying required state.`);
|
||||
nodeId = existingNode.entry.id;
|
||||
} else {
|
||||
const createdNode = await uploadFile(fileInfo.name, parentFolderId);
|
||||
nodeId = getEntryId(createdNode, `file ${fileInfo.name}`);
|
||||
}
|
||||
|
||||
switch (fileInfo.action) {
|
||||
case 'LOCK':
|
||||
await ensureLocked(nodeId, fileInfo.name, existingNode?.entry?.isLocked);
|
||||
break;
|
||||
case 'SHARE':
|
||||
await ensureShared(nodeId, fileInfo.name);
|
||||
break;
|
||||
case 'FAVORITE':
|
||||
await ensureFavorite(nodeId, fileInfo.name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a folder exists under the given parent. Creates it if missing.
|
||||
* Handles 409 conflict (race condition) by fetching the existing folder.
|
||||
* @param folderName folder name
|
||||
* @param parentId parent node id
|
||||
* @returns the folder node entry
|
||||
*/
|
||||
async function ensureFolder(folderName: string, parentId: string): Promise<NodeEntry> {
|
||||
const existingFolder = await findNodeByRelativePath(parentId, folderName);
|
||||
|
||||
if (existingFolder?.entry?.id) {
|
||||
if (!existingFolder.entry.isFolder) {
|
||||
throw new Error(
|
||||
`Cannot use ${folderName} as test-data folder: a non-folder node with that name already exists (nodeType: ${existingFolder.entry.nodeType}, id: ${existingFolder.entry.id}).`
|
||||
);
|
||||
}
|
||||
logger.info(`Folder ${folderName} already exists.`);
|
||||
return existingFolder;
|
||||
}
|
||||
|
||||
try {
|
||||
const createdFolder = await nodesApi.createNode(parentId, { name: folderName, nodeType: 'cm:folder' }, { overwrite: true });
|
||||
logger.info(`Folder ${folderName} was created`);
|
||||
return createdFolder;
|
||||
} catch (error: any) {
|
||||
if (error?.status === 409) {
|
||||
const conflictingFolder = await findNodeByRelativePath(parentId, folderName);
|
||||
|
||||
if (conflictingFolder?.entry?.id) {
|
||||
if (!conflictingFolder.entry.isFolder) {
|
||||
throw new Error(
|
||||
`Cannot use ${folderName} as test-data folder: a non-folder node with that name already exists (nodeType: ${conflictingFolder.entry.nodeType}, id: ${conflictingFolder.entry.id}).`
|
||||
);
|
||||
}
|
||||
logger.info(`Folder ${folderName} already exists.`);
|
||||
return conflictingFolder;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Failed to ensure folder ${folderName}: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a node by relative path under a parent. Returns null if not found (404).
|
||||
* @param parentId parent node id
|
||||
* @param fileName relative path / file name
|
||||
* @returns the node entry or null if not found
|
||||
*/
|
||||
async function findNodeByRelativePath(parentId: string, fileName: string): Promise<NodeEntry | null> {
|
||||
try {
|
||||
return await nodesApi.getNode(parentId, { relativePath: `/${fileName}`, include: ['isLocked'] });
|
||||
} catch (error: any) {
|
||||
if (error?.status === 404) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new Error(`Failed to fetch ${fileName}: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file to the given destination folder.
|
||||
* @param fileName file name
|
||||
* @param destinationId destination folder node id
|
||||
* @returns the uploaded node entry
|
||||
*/
|
||||
async function uploadFile(fileName: string, destinationId: string): Promise<NodeEntry> {
|
||||
const filePath = `../resources/content/${fileName}`;
|
||||
const file = createReadStream(path.join(__dirname, filePath));
|
||||
let uploadedFile: NodeEntry;
|
||||
|
||||
try {
|
||||
uploadedFile = await new UploadApi(alfrescoJsApi).uploadFile(file, '', fileDestination, null, {
|
||||
const uploadedFile = await uploadApi.uploadFile(file, '', destinationId, null, {
|
||||
name: fileName,
|
||||
nodeType: 'cm:content',
|
||||
renditions: 'doclib',
|
||||
overwrite: true
|
||||
});
|
||||
logger.info(`File ${fileName} was uploaded`);
|
||||
} catch (err) {
|
||||
logger.error(`Failed to upload file with error: `, err.stack);
|
||||
return uploadedFile;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to upload ${fileName}: ${formatError(error)}`);
|
||||
}
|
||||
return uploadedFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock file node
|
||||
*
|
||||
* Ensure a file is locked. Skips if already locked.
|
||||
* @param nodeId node id
|
||||
* @param fileName file name (for logging)
|
||||
* @param isAlreadyLocked whether the node is already locked
|
||||
*/
|
||||
async function lockFile(nodeId: string): Promise<NodeEntry> {
|
||||
const data = {
|
||||
type: 'ALLOW_OWNER_CHANGES'
|
||||
};
|
||||
async function ensureLocked(nodeId: string, fileName: string, isAlreadyLocked = false) {
|
||||
if (isAlreadyLocked) {
|
||||
logger.info(`File ${fileName} is already locked.`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = new NodesApi(alfrescoJsApi).lockNode(nodeId, data);
|
||||
logger.info('File was locked');
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error('Failed to lock file with error: ', error.stack);
|
||||
return null;
|
||||
await nodesApi.lockNode(nodeId, { type: 'ALLOW_OWNER_CHANGES' });
|
||||
logger.info(`File ${fileName} was locked`);
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to lock ${fileName}: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Share file node
|
||||
*
|
||||
* Ensure a file is shared. Handles 409 (already shared) gracefully.
|
||||
* @param nodeId node id
|
||||
* @param fileName file name (for logging)
|
||||
*/
|
||||
async function shareFile(nodeId: string) {
|
||||
const data = {
|
||||
nodeId
|
||||
};
|
||||
async function ensureShared(nodeId: string, fileName: string) {
|
||||
try {
|
||||
await new SharedlinksApi(alfrescoJsApi).createSharedLink(data);
|
||||
logger.info('File was shared');
|
||||
} catch (error) {
|
||||
logger.error('Failed to share file with error: ', error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Favorite file node
|
||||
*
|
||||
* @param nodeId node id
|
||||
*/
|
||||
async function favoriteFile(nodeId: string) {
|
||||
const data = {
|
||||
target: {
|
||||
['file']: {
|
||||
guid: nodeId
|
||||
}
|
||||
await sharedlinksApi.createSharedLink({ nodeId });
|
||||
logger.info(`File ${fileName} was shared`);
|
||||
} catch (error: any) {
|
||||
if (error?.status === 409) {
|
||||
logger.info(`File ${fileName} is already shared.`);
|
||||
return;
|
||||
}
|
||||
};
|
||||
try {
|
||||
await new FavoritesApi(alfrescoJsApi).createFavorite('-me-', data);
|
||||
logger.info('File was add to favorites');
|
||||
} catch (error) {
|
||||
logger.error('Failed to add the file to favorites with error: ', error.stack);
|
||||
|
||||
throw new Error(`Failed to share ${fileName}: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check environment state
|
||||
*
|
||||
* @param opts command options
|
||||
* Ensure a file is favorite. Handles 409 (already favorite) gracefully.
|
||||
* @param nodeId node id
|
||||
* @param fileName file name (for logging)
|
||||
*/
|
||||
async function checkEnv(opts: InitAcsEnvArgs) {
|
||||
async function ensureFavorite(nodeId: string, fileName: string) {
|
||||
try {
|
||||
await favoritesApi.createFavorite('-me-', {
|
||||
target: {
|
||||
file: {
|
||||
guid: nodeId
|
||||
}
|
||||
}
|
||||
});
|
||||
logger.info(`File ${fileName} was added to favorites`);
|
||||
} catch (error: any) {
|
||||
if (error?.status === 409) {
|
||||
logger.info(`File ${fileName} is already a favorite.`);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`Failed to favorite ${fileName}: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract entry id from a node response. Throws if missing.
|
||||
* @param nodeEntry node entry response
|
||||
* @param label label for error message
|
||||
* @returns the node id
|
||||
*/
|
||||
function getEntryId(nodeEntry: NodeEntry, label: string): string {
|
||||
const nodeId = nodeEntry?.entry?.id;
|
||||
|
||||
if (nodeId) {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
throw new Error(`Missing ACS response entry for ${label}.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an error for logging.
|
||||
* @param error error object
|
||||
* @returns formatted error string
|
||||
*/
|
||||
function formatError(error: any): string {
|
||||
if (!error) {
|
||||
return 'Unknown error';
|
||||
}
|
||||
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
}
|
||||
|
||||
try {
|
||||
return error?.message || error?.stack || JSON.stringify(error);
|
||||
} catch {
|
||||
return 'Unknown error (unable to serialize)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry wrapper for transient failures.
|
||||
* @param fn async function to execute
|
||||
* @param label label for logging
|
||||
* @param maxAttempts maximum retry attempts
|
||||
* @returns the result of the function
|
||||
*/
|
||||
async function withRetry<T>(fn: () => Promise<T>, label: string, maxAttempts = 3): Promise<T> {
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (error: any) {
|
||||
if (attempt === maxAttempts) {
|
||||
logger.error(`${label}: failed after ${maxAttempts} attempts: ${formatError(error)}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
logger.warn(`${label}: attempt ${attempt} failed, retrying in ${RETRY_DELAY_MS / 1000}s: ${formatError(error)}`);
|
||||
await wait(RETRY_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`${label}: exhausted all ${maxAttempts} attempts`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Async delay.
|
||||
* @param ms milliseconds to wait
|
||||
* @returns a promise that resolves after the delay
|
||||
*/
|
||||
function wait(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check environment state and authenticate. Retries on transient failures.
|
||||
* @param opts command options
|
||||
* @param attempt current attempt number
|
||||
*/
|
||||
async function checkEnv(opts: InitAcsEnvArgs, attempt = 1) {
|
||||
try {
|
||||
alfrescoJsApi = new AlfrescoApi({
|
||||
provider: 'ALL',
|
||||
@@ -260,31 +391,29 @@ async function checkEnv(opts: InitAcsEnvArgs) {
|
||||
},
|
||||
contextRoot: 'alfresco'
|
||||
});
|
||||
|
||||
await alfrescoJsApi.login(opts.username, opts.password);
|
||||
} catch (e) {
|
||||
if (e.error.code === 'ETIMEDOUT') {
|
||||
logger.error('The env is not reachable. Terminating');
|
||||
exit(1);
|
||||
|
||||
nodesApi = new NodesApi(alfrescoJsApi);
|
||||
uploadApi = new UploadApi(alfrescoJsApi);
|
||||
sharedlinksApi = new SharedlinksApi(alfrescoJsApi);
|
||||
favoritesApi = new FavoritesApi(alfrescoJsApi);
|
||||
} catch (error: any) {
|
||||
const errorCode = error?.error?.code;
|
||||
|
||||
if (errorCode === 'ETIMEDOUT' || error?.status === 504) {
|
||||
logger.warn('Login attempt timed out or received a gateway error, environment may still be starting up.');
|
||||
} else {
|
||||
logger.error('Login error, environment down or inaccessible.');
|
||||
}
|
||||
logger.error('Login error environment down or inaccessible');
|
||||
counter++;
|
||||
if (MAX_RETRY === counter) {
|
||||
|
||||
if (attempt >= MAX_RETRY) {
|
||||
logger.error('Give up');
|
||||
exit(1);
|
||||
} else {
|
||||
logger.error(`Retry in 1 minute attempt N ${counter}`);
|
||||
sleep(TIMEOUT);
|
||||
await checkEnv(opts);
|
||||
}
|
||||
|
||||
logger.warn(`Retry in ${RETRY_DELAY_MS / 1000} seconds, attempt ${attempt}`);
|
||||
await wait(RETRY_DELAY_MS);
|
||||
await checkEnv(opts, attempt + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a delay
|
||||
*
|
||||
* @param delay timeout in milliseconds
|
||||
*/
|
||||
function sleep(delay: number) {
|
||||
const start = new Date().getTime();
|
||||
while (new Date().getTime() < start + delay) {}
|
||||
}
|
||||
|
||||
+151
-87
@@ -30,8 +30,11 @@ import { parseArgs } from 'node:util';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { createReadStream } from 'node:fs';
|
||||
import * as path from 'path';
|
||||
import { config } from 'dotenv';
|
||||
import { logger } from './logger';
|
||||
|
||||
config({ path: path.resolve(__dirname, '../../../.env') });
|
||||
|
||||
interface InitApsEnvArgs {
|
||||
host?: string;
|
||||
clientId?: string;
|
||||
@@ -40,12 +43,12 @@ interface InitApsEnvArgs {
|
||||
license?: string;
|
||||
}
|
||||
const MAX_RETRY = 10;
|
||||
let counter = 0;
|
||||
const TIMEOUT = 6000;
|
||||
const RETRY_DELAY_MS = 6000;
|
||||
const TENANT_DEFAULT_ID = 1;
|
||||
const TENANT_DEFAULT_NAME = 'default';
|
||||
const CONTENT_DEFAULT_NAME = 'adw-content';
|
||||
const ACTIVITI_APPS = require('./resources').ACTIVITI_APPS;
|
||||
const E2E_USER_PASSWORD = process.env.HR_USER_PASSWORD;
|
||||
|
||||
let alfrescoJsApi: AlfrescoApi;
|
||||
|
||||
@@ -60,7 +63,6 @@ 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
|
||||
@@ -71,11 +73,6 @@ Options:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argv.includes('-v') || argv.includes('--version')) {
|
||||
console.log('0.1.0');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const { values } = parseArgs({
|
||||
args: argv.slice(2),
|
||||
options: {
|
||||
@@ -111,6 +108,14 @@ Options:
|
||||
|
||||
await checkEnv(opts);
|
||||
|
||||
const e2eAppReady = await ensureE2eApplicationDeployed();
|
||||
if (e2eAppReady) {
|
||||
logger.info(`APS environment already initialized (terraform). Skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
await alfrescoJsApi.login(opts.username, opts.password);
|
||||
|
||||
logger.info(`***** Step 1 - Check License *****`);
|
||||
|
||||
let licenceUploaded = false;
|
||||
@@ -146,25 +151,24 @@ Options:
|
||||
logger.info(`***** Step 4 - Create users *****`);
|
||||
const users = await getDefaultApsUsersFromRealm(opts);
|
||||
if (tenantId && users && users.length > 0) {
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
await createUsers(tenantId, users[i]);
|
||||
for (const user of users) {
|
||||
await createUsers(tenantId, user);
|
||||
}
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
logger.info('Impersonate user: ' + users[i].username);
|
||||
await alfrescoJsApi.login(users[i].username, 'password');
|
||||
await authorizeUserToContentRepo(opts, users[i]);
|
||||
for (const user of users) {
|
||||
logger.info('Impersonate user: ' + user.username);
|
||||
await alfrescoJsApi.login(user.username, E2E_USER_PASSWORD);
|
||||
await authorizeUserToContentRepo(opts, user);
|
||||
|
||||
const defaultUser = 'hruser';
|
||||
if (users[i].username.includes(defaultUser)) {
|
||||
logger.info(`***** Step initialize APS apps for user ${defaultUser} *****`);
|
||||
if (user.username.includes('hruser')) {
|
||||
logger.info(`***** Step initialize APS apps for user hruser *****`);
|
||||
await initializeDefaultApps();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.info('Something went wrong. Was not able to create the users');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Aps something went wrong. Tenant id ${tenantId}`, error);
|
||||
} catch (error: any) {
|
||||
logger.error(`Aps something went wrong. Tenant id ${tenantId}: ${formatError(error)}`);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
@@ -173,15 +177,56 @@ Options:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure e2e-Application is deployed for hruser.
|
||||
* If the app is already present, returns true (skip full init).
|
||||
* If hruser can log in but the app is missing, imports, publishes and deploys it.
|
||||
* Returns false only if hruser cannot log in or deployment fails.
|
||||
* @returns `true` if app is deployed, otherwise `false`
|
||||
*/
|
||||
async function ensureE2eApplicationDeployed(): Promise<boolean> {
|
||||
try {
|
||||
await alfrescoJsApi.login('hruser', E2E_USER_PASSWORD);
|
||||
const runtimeAppDefinitionsApi = new RuntimeAppDefinitionsApi(alfrescoJsApi);
|
||||
const availableApps = await runtimeAppDefinitionsApi.getAppDefinitions();
|
||||
const e2eApp = availableApps.data?.filter((app) => app.name?.includes('e2e-Application'));
|
||||
if (e2eApp && e2eApp.length > 0) {
|
||||
logger.info(`e2e-Application is already deployed for hruser`);
|
||||
return true;
|
||||
}
|
||||
logger.info(`e2e-Application not found for hruser - uploading and deploying it now`);
|
||||
const appDefinition = await importPublishApp('e2e-Application');
|
||||
if (appDefinition?.appDefinition?.id) {
|
||||
await deployApp(appDefinition.appDefinition.id);
|
||||
const verifyApps = await runtimeAppDefinitionsApi.getAppDefinitions();
|
||||
const deployed = verifyApps.data?.some((app) => app.name?.includes('e2e-Application'));
|
||||
if (deployed) {
|
||||
logger.info(`e2e-Application successfully deployed for hruser`);
|
||||
return true;
|
||||
}
|
||||
logger.info(`e2e-Application deployment could not be verified - proceeding with full initialization`);
|
||||
return false;
|
||||
}
|
||||
logger.info(`Failed to import/deploy e2e-Application for hruser - proceeding with full initialization`);
|
||||
return false;
|
||||
} catch (error: any) {
|
||||
logger.info(`Unable to verify APS state for hruser - proceeding with initialization: ${formatError(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise default applications
|
||||
*/
|
||||
async function initializeDefaultApps() {
|
||||
for (let x = 0; x < ACTIVITI_APPS.apps.length; x++) {
|
||||
const appInfo = ACTIVITI_APPS.apps[x];
|
||||
for (const appInfo of ACTIVITI_APPS.apps) {
|
||||
const isDeployed = await isDefaultAppDeployed(appInfo.name);
|
||||
if (isDeployed !== undefined && !isDeployed) {
|
||||
const appDefinition = await importPublishApp(`${appInfo.name}`);
|
||||
if (!isDeployed) {
|
||||
const appDefinition = await importPublishApp(appInfo.name);
|
||||
if (!appDefinition?.appDefinition?.id) {
|
||||
logger.error(`Failed to import app ${appInfo.name}, skipping deployment.`);
|
||||
continue;
|
||||
}
|
||||
await deployApp(appDefinition.appDefinition.id);
|
||||
} else {
|
||||
logger.info(`***** App ${appInfo.name} already deployed *****`);
|
||||
@@ -190,11 +235,11 @@ async function initializeDefaultApps() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check environment
|
||||
*
|
||||
* Check environment state and authenticate. Retries on transient failures.
|
||||
* @param opts command options
|
||||
* @param attempt current attempt number
|
||||
*/
|
||||
async function checkEnv(opts: InitApsEnvArgs) {
|
||||
async function checkEnv(opts: InitApsEnvArgs, attempt = 1) {
|
||||
try {
|
||||
alfrescoJsApi = new AlfrescoApi({
|
||||
provider: 'ALL',
|
||||
@@ -210,27 +255,28 @@ async function checkEnv(opts: InitApsEnvArgs) {
|
||||
}
|
||||
});
|
||||
await alfrescoJsApi.login(opts.username, opts.password);
|
||||
} catch (e) {
|
||||
if (e.error.code === 'ETIMEDOUT') {
|
||||
logger.error('The env is not reachable. Terminating');
|
||||
exit(1);
|
||||
} catch (error: any) {
|
||||
const errorCode = error?.error?.code;
|
||||
|
||||
if (errorCode === 'ETIMEDOUT' || error?.status === 504) {
|
||||
logger.warn('Login attempt timed out or received a gateway error, environment may still be starting up.');
|
||||
} else {
|
||||
logger.error('Login error, environment down or inaccessible.');
|
||||
}
|
||||
logger.info('Login error environment down or inaccessible');
|
||||
counter++;
|
||||
if (MAX_RETRY === counter) {
|
||||
|
||||
if (attempt >= MAX_RETRY) {
|
||||
logger.error('Give up');
|
||||
exit(1);
|
||||
} else {
|
||||
logger.error(`Retry in 1 minute attempt N ${counter}`);
|
||||
sleep(TIMEOUT);
|
||||
await checkEnv(opts);
|
||||
}
|
||||
|
||||
logger.warn(`Retry in ${RETRY_DELAY_MS / 1000} seconds, attempt ${attempt}`);
|
||||
await wait(RETRY_DELAY_MS);
|
||||
await checkEnv(opts, attempt + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the default tenant is present
|
||||
*
|
||||
* @param tenantId tenant id
|
||||
* @param tenantName tenant name
|
||||
* @returns `true` if tenant is found, otherwise `false`
|
||||
@@ -241,7 +287,7 @@ async function hasDefaultTenant(tenantId: number, tenantName: string): Promise<b
|
||||
try {
|
||||
const adminTenantsApi = new AdminTenantsApi(alfrescoJsApi);
|
||||
tenant = await adminTenantsApi.getTenant(tenantId);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
logger.info(`Aps: does not have tenant with id: ${tenantId}`);
|
||||
return false;
|
||||
}
|
||||
@@ -258,8 +304,8 @@ async function hasDefaultTenant(tenantId: number, tenantName: string): Promise<b
|
||||
|
||||
/**
|
||||
* Create default tenant
|
||||
*
|
||||
* @param tenantName tenant name
|
||||
* @returns the tenant id or null
|
||||
*/
|
||||
async function createDefaultTenant(tenantName: string) {
|
||||
const tenantPost = {
|
||||
@@ -273,28 +319,27 @@ async function createDefaultTenant(tenantName: string) {
|
||||
const tenant = await adminTenantsApi.createTenant(tenantPost);
|
||||
logger.info(`APS: Tenant ${tenantName} created with id: ${tenant.id}`);
|
||||
return tenant.id;
|
||||
} catch (error) {
|
||||
logger.info(`APS: not able to create the default tenant: ${JSON.parse(error.message)}`);
|
||||
} catch (error: any) {
|
||||
logger.info(`APS: not able to create the default tenant: ${formatError(error)}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create users
|
||||
*
|
||||
* @param tenantId tenant id
|
||||
* @param user user object
|
||||
* @returns the created user
|
||||
*/
|
||||
async function createUsers(tenantId: number, user: any) {
|
||||
logger.info(`Create user ${user.email} on tenant: ${tenantId}`);
|
||||
const passwordCamelCase = 'Password';
|
||||
const userJson = new UserRepresentation({
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
status: 'active',
|
||||
type: 'enterprise',
|
||||
password: passwordCamelCase,
|
||||
password: E2E_USER_PASSWORD,
|
||||
tenantId
|
||||
});
|
||||
|
||||
@@ -303,15 +348,15 @@ async function createUsers(tenantId: number, user: any) {
|
||||
const userInfo = await adminUsersApi.createNewUser(userJson);
|
||||
logger.info(`APS: User ${userInfo.email} created with id: ${userInfo.id}`);
|
||||
return user;
|
||||
} catch (error) {
|
||||
logger.info(`APS: not able to create the default user: ${error.message}`);
|
||||
} catch (error: any) {
|
||||
logger.info(`APS: not able to create the default user: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Activiti license
|
||||
*
|
||||
* @param opts command options
|
||||
* @returns `true` if license uploaded successfully, otherwise `false`
|
||||
*/
|
||||
async function updateLicense(opts: InitApsEnvArgs) {
|
||||
const fileContent = createReadStream(path.join(__dirname, '/activiti.lic'));
|
||||
@@ -330,15 +375,14 @@ async function updateLicense(opts: InitApsEnvArgs) {
|
||||
);
|
||||
logger.info(`Aps License uploaded!`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error(`Aps License failed!`, error.message);
|
||||
} catch (error: any) {
|
||||
logger.error(`Aps License failed! ${formatError(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if default application is deployed
|
||||
*
|
||||
* @param appName application name
|
||||
* @returns `true` if application is deployed, otherwise `false`
|
||||
*/
|
||||
@@ -349,18 +393,18 @@ async function isDefaultAppDeployed(appName: string): Promise<boolean> {
|
||||
const availableApps = await runtimeAppDefinitionsApi.getAppDefinitions();
|
||||
const defaultApp = availableApps.data?.filter((app) => app.name?.includes(appName));
|
||||
return defaultApp && defaultApp.length > 0;
|
||||
} catch (error) {
|
||||
logger.error(`Aps app failed to import/Publish!`);
|
||||
} catch (error: any) {
|
||||
logger.error(`Failed to check if ${appName} is deployed: ${formatError(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import and publish the application
|
||||
*
|
||||
* @param appName application name
|
||||
* @returns the app definition result
|
||||
*/
|
||||
async function importPublishApp(appName: string): Promise<AppDefinitionUpdateResultRepresentation> {
|
||||
async function importPublishApp(appName: string): Promise<AppDefinitionUpdateResultRepresentation | null> {
|
||||
const appNameExtension = `../resources/${appName}.zip`;
|
||||
logger.info(`Import app ${appNameExtension}`);
|
||||
const pathFile = path.join(__dirname, appNameExtension);
|
||||
@@ -371,15 +415,14 @@ async function importPublishApp(appName: string): Promise<AppDefinitionUpdateRes
|
||||
const result = await appDefinitionsApi.importAndPublishApp(fileContent, { renewIdmEntries: true });
|
||||
logger.info(`Aps app imported and published!`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error(`Aps app failed to import/Publish!`, error.message);
|
||||
} catch (error: any) {
|
||||
logger.error(`Aps app failed to import/Publish! ${formatError(error)}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy application
|
||||
*
|
||||
* @param appDefinitionId app definition id
|
||||
*/
|
||||
async function deployApp(appDefinitionId: number) {
|
||||
@@ -392,15 +435,15 @@ async function deployApp(appDefinitionId: number) {
|
||||
const runtimeAppDefinitionsApi = new RuntimeAppDefinitionsApi(alfrescoJsApi);
|
||||
await runtimeAppDefinitionsApi.deployAppDefinitions(body);
|
||||
logger.info(`Aps app deployed`);
|
||||
} catch (error) {
|
||||
logger.error(`Aps app failed to deploy!`);
|
||||
} catch (error: any) {
|
||||
logger.error(`Aps app failed to deploy: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Activiti app has license
|
||||
*
|
||||
* @param opts command options
|
||||
* @returns `true` if license is valid, otherwise `false`
|
||||
*/
|
||||
async function hasLicense(opts: InitApsEnvArgs): Promise<boolean> {
|
||||
try {
|
||||
@@ -415,13 +458,13 @@ async function hasLicense(opts: InitApsEnvArgs): Promise<boolean> {
|
||||
['application/json'],
|
||||
['application/json']
|
||||
);
|
||||
if (license && license.status === 'valid') {
|
||||
if (license?.status === 'valid') {
|
||||
logger.info(`Aps has a valid License!`);
|
||||
return true;
|
||||
}
|
||||
logger.info(`Aps does NOT have a valid License!`);
|
||||
return false;
|
||||
} catch (error) {
|
||||
} catch {
|
||||
logger.error(`Aps not able to check the license`);
|
||||
return false;
|
||||
}
|
||||
@@ -429,8 +472,8 @@ async function hasLicense(opts: InitApsEnvArgs): Promise<boolean> {
|
||||
|
||||
/**
|
||||
* Get default users from the realm
|
||||
*
|
||||
* @param opts command options
|
||||
* @returns array of default APS users or null
|
||||
*/
|
||||
async function getDefaultApsUsersFromRealm(opts: InitApsEnvArgs) {
|
||||
try {
|
||||
@@ -449,18 +492,18 @@ async function getDefaultApsUsersFromRealm(opts: InitApsEnvArgs) {
|
||||
const apsDefaultUsers = users.filter((user) => usernamesOfApsDefaultUsers.includes(user.username));
|
||||
logger.info(`Keycloak found ${apsDefaultUsers.length} users`);
|
||||
return apsDefaultUsers;
|
||||
} catch (error) {
|
||||
logger.error(`APS: not able to fetch user: ${error.message}`);
|
||||
} catch (error: any) {
|
||||
logger.error(`APS: not able to fetch user: ${formatError(error)}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that ACS repo for Activiti is present
|
||||
*
|
||||
* @param opts command options
|
||||
* @param tenantId tenant id
|
||||
* @param contentName content service name
|
||||
* @returns `true` if content repo is present, otherwise `false`
|
||||
*/
|
||||
async function isContentRepoPresent(opts: InitApsEnvArgs, tenantId: number, contentName: string): Promise<boolean> {
|
||||
try {
|
||||
@@ -476,18 +519,18 @@ async function isContentRepoPresent(opts: InitApsEnvArgs, tenantId: number, cont
|
||||
['application/json']
|
||||
);
|
||||
return !!contentRepos.data.find((repo) => repo.name === contentName);
|
||||
} catch (error) {
|
||||
logger.error(`APS: not able to create content: ${error.message}`);
|
||||
return null;
|
||||
} catch (error: any) {
|
||||
logger.error(`APS: not able to check content repo: ${formatError(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add content service with basic auth
|
||||
*
|
||||
* @param opts command options
|
||||
* @param tenantId tenant id
|
||||
* @param name content name
|
||||
* @returns the created content repo
|
||||
*/
|
||||
async function addContentRepoWithBasic(opts: InitApsEnvArgs, tenantId: number, name: string) {
|
||||
logger.info(`Create Content with name ${name} and basic auth`);
|
||||
@@ -517,14 +560,13 @@ async function addContentRepoWithBasic(opts: InitApsEnvArgs, tenantId: number, n
|
||||
);
|
||||
logger.info(`Content created!`);
|
||||
return content;
|
||||
} catch (error) {
|
||||
logger.error(`APS: not able to create content: ${error.message}`);
|
||||
} catch (error: any) {
|
||||
logger.error(`APS: not able to create content: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize activiti user to ACS repo
|
||||
*
|
||||
* @param opts command options
|
||||
* @param user user object
|
||||
*/
|
||||
@@ -551,22 +593,22 @@ async function authorizeUserToContentRepo(opts: InitApsEnvArgs, user: any) {
|
||||
}
|
||||
}
|
||||
return;
|
||||
} catch (error) {
|
||||
logger.error(`APS: not able to authorize content: ${error.message}`);
|
||||
} catch (error: any) {
|
||||
logger.error(`APS: not able to authorize content: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize user with content using basic auth
|
||||
*
|
||||
* @param opts command options
|
||||
* @param username username
|
||||
* @param contentId content id
|
||||
* @returns the authorized content
|
||||
*/
|
||||
async function authorizeUserToContentWithBasic(opts: InitApsEnvArgs, username: string, contentId: string) {
|
||||
logger.info(`Authorize ${username} on contentId: ${contentId} in basic auth`);
|
||||
try {
|
||||
const body = { username, password: 'password' };
|
||||
const body = { username, password: E2E_USER_PASSWORD };
|
||||
const content = await alfrescoJsApi.oauth2Auth.callCustomApi(
|
||||
`${opts.host}/activiti-app/api/enterprise/integration/alfresco/${contentId}/account`,
|
||||
'POST',
|
||||
@@ -580,15 +622,15 @@ async function authorizeUserToContentWithBasic(opts: InitApsEnvArgs, username: s
|
||||
);
|
||||
logger.info(`User authorized!`);
|
||||
return content;
|
||||
} catch (error) {
|
||||
logger.error(`APS: not able to authorize content: ${error.message}`);
|
||||
} catch (error: any) {
|
||||
logger.error(`APS: not able to authorize content: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download APS license file
|
||||
*
|
||||
* @param apsLicensePath path to license file
|
||||
* @returns `true` if download succeeded, otherwise `false`
|
||||
*/
|
||||
async function downloadLicenseFile(apsLicensePath: string) {
|
||||
const args = [`s3`, `cp`, apsLicensePath, `./`];
|
||||
@@ -606,11 +648,33 @@ async function downloadLicenseFile(apsLicensePath: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a delay
|
||||
*
|
||||
* @param delay timeout in milliseconds
|
||||
* Format an error for logging.
|
||||
* @param error error object
|
||||
* @returns formatted error string
|
||||
*/
|
||||
function sleep(delay: number) {
|
||||
const start = new Date().getTime();
|
||||
while (new Date().getTime() < start + delay) {}
|
||||
function formatError(error: any): string {
|
||||
if (!error) {
|
||||
return 'Unknown error';
|
||||
}
|
||||
|
||||
if (typeof error === 'string') {
|
||||
return error;
|
||||
}
|
||||
|
||||
try {
|
||||
return error?.message || error?.stack || JSON.stringify(error);
|
||||
} catch {
|
||||
return 'Unknown error (unable to serialize)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Async delay.
|
||||
* @param ms milliseconds to wait
|
||||
* @returns a promise that resolves after the delay
|
||||
*/
|
||||
function wait(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
+60
-67
@@ -21,10 +21,11 @@ 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';
|
||||
|
||||
const { collectProductionLicenses } = require('../resources/license-collector.cjs');
|
||||
|
||||
interface LicensesCommandArgs {
|
||||
package?: string;
|
||||
outDir?: string;
|
||||
@@ -34,7 +35,14 @@ interface PackageInfo {
|
||||
name: string;
|
||||
description: string;
|
||||
version: string;
|
||||
dependencies: Record<string, string>;
|
||||
dependencies?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface PackageInfoWithMetadata {
|
||||
name: string;
|
||||
version: string;
|
||||
licenseExp: string;
|
||||
repository?: string;
|
||||
}
|
||||
|
||||
const nonStandardLicenses = {
|
||||
@@ -93,6 +101,17 @@ function getPackageFile(packagePath: string): PackageInfo {
|
||||
}
|
||||
}
|
||||
|
||||
function toLinkedLicenseExpression(rawExpression: string): string {
|
||||
return rawExpression.replace(/\*/g, '').replace(/[a-zA-Z0-9\-.]+/g, (match: string) => {
|
||||
const lowerMatch = match.toLowerCase();
|
||||
if (lowerMatch !== 'and' && lowerMatch !== 'or' && lowerMatch !== 'with') {
|
||||
return licenseWithMDLinks(match);
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Licenses command
|
||||
*
|
||||
@@ -155,76 +174,50 @@ Options:
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(`Checking ${packagePath}`);
|
||||
const packageJsonFile = getPackageFile(packagePath);
|
||||
const mainDependencies = Object.keys(packageJsonFile.dependencies || {});
|
||||
const licenseScan = collectProductionLicenses(packagePath, {
|
||||
denyList: ['GPL'],
|
||||
missingRepositories
|
||||
});
|
||||
|
||||
checker.init(
|
||||
const filteredPackages: Record<string, PackageInfoWithMetadata> = {};
|
||||
for (const pack of licenseScan.packages) {
|
||||
filteredPackages[pack.key] = {
|
||||
name: pack.name,
|
||||
version: pack.version,
|
||||
licenseExp: toLinkedLicenseExpression(pack.rawLicenseExpression),
|
||||
repository: pack.repository
|
||||
};
|
||||
}
|
||||
|
||||
if (licenseScan.deniedPackages.length > 0) {
|
||||
const deniedError = new Error(`Denied licenses found:\n${licenseScan.deniedPackages.join('\n')}`);
|
||||
console.error(deniedError.message);
|
||||
reject(deniedError);
|
||||
return;
|
||||
}
|
||||
|
||||
const packageJson: PackageInfo = getPackageFile(packagePath);
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
{
|
||||
start: workingDir,
|
||||
production: true,
|
||||
failOn: 'GPL'
|
||||
filteredPackages,
|
||||
projVersion: packageJson.version,
|
||||
projName: packageJson.name
|
||||
},
|
||||
(err: any, packages: any[]) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
{},
|
||||
(ejsError: unknown, mdText: string) => {
|
||||
if (ejsError) {
|
||||
console.error(ejsError);
|
||||
reject(ejsError);
|
||||
} else {
|
||||
const filteredPackages = {};
|
||||
const outputPath = path.resolve(options.outDir || workingDir);
|
||||
const outputFile = path.join(outputPath, `license-info-${packageJson.version}.md`);
|
||||
|
||||
// eslint-disable-next-line guard-for-in
|
||||
for (const packageName in packages) {
|
||||
const pack = packages[packageName];
|
||||
|
||||
const lastAtSignPos = packageName.lastIndexOf('@');
|
||||
const basePackageName = packageName.substring(0, lastAtSignPos);
|
||||
|
||||
if (mainDependencies.includes(basePackageName)) {
|
||||
pack['licenseExp'] = pack['licenses']
|
||||
.toString()
|
||||
.replace(/\*/g, '')
|
||||
.replace(/[a-zA-Z0-9\-.]+/g, (match: string) => {
|
||||
const lowerMatch = match.toLowerCase();
|
||||
if (lowerMatch !== 'and' && lowerMatch !== 'or' && lowerMatch !== 'with') {
|
||||
return licenseWithMDLinks(match);
|
||||
} else {
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
filteredPackages[packageName] = pack;
|
||||
}
|
||||
|
||||
if (!pack['repository'] && missingRepositories[basePackageName]) {
|
||||
pack['repository'] = missingRepositories[basePackageName];
|
||||
filteredPackages[packageName] = pack;
|
||||
}
|
||||
}
|
||||
|
||||
const packageJson: PackageInfo = getPackageFile(packagePath);
|
||||
|
||||
ejs.renderFile(
|
||||
templatePath,
|
||||
{
|
||||
filteredPackages,
|
||||
projVersion: packageJson.version,
|
||||
projName: packageJson.name
|
||||
},
|
||||
{},
|
||||
(ejsError: any, mdText: string) => {
|
||||
if (ejsError) {
|
||||
console.error(ejsError);
|
||||
reject(ejsError);
|
||||
} else {
|
||||
const outputPath = path.resolve(options.outDir || workingDir);
|
||||
const outputFile = path.join(outputPath, `license-info-${packageJson.version}.md`);
|
||||
|
||||
fs.writeFileSync(outputFile, mdText);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Report saved as ${outputFile}`);
|
||||
resolve(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
fs.writeFileSync(outputFile, mdText);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Report saved as ${outputFile}`);
|
||||
resolve(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
"no-bitwise": "off",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-multiple-empty-lines": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-return-await": "error",
|
||||
"rxjs/no-create": "error",
|
||||
"rxjs/no-subject-unsubscribe": "error",
|
||||
|
||||
@@ -13,6 +13,9 @@ const config: StorybookConfig = {
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/angular'),
|
||||
options: {}
|
||||
},
|
||||
core: {
|
||||
disableTelemetry: true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = function (config) {
|
||||
{ pattern: 'lib/config/app.config.json', included: false, served: true, watched: false }
|
||||
],
|
||||
|
||||
frameworks: ['jasmine-ajax', 'jasmine', '@angular-devkit/build-angular'],
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
|
||||
proxies: {
|
||||
'/assets/images/': '/base/lib/core/src/lib/assets/images/',
|
||||
@@ -42,13 +42,11 @@ module.exports = function (config) {
|
||||
},
|
||||
|
||||
plugins: [
|
||||
require('karma-jasmine-ajax'),
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
require('karma-mocha-reporter')
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false,
|
||||
@@ -61,10 +59,6 @@ module.exports = function (config) {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
|
||||
mochaReporter: {
|
||||
ignoreSkipped: process.env.KARMA_IGNORE_SKIPPED === 'true'
|
||||
},
|
||||
|
||||
coverageReporter: {
|
||||
dir: join(__dirname, '../../coverage/content-services'),
|
||||
subdir: '.',
|
||||
@@ -86,7 +80,7 @@ module.exports = function (config) {
|
||||
}
|
||||
},
|
||||
|
||||
reporters: ['mocha', 'kjhtml'],
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: constants.LOG_INFO,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-content-services",
|
||||
"description": "Alfresco ADF content services",
|
||||
"version": "8.3.0",
|
||||
"version": "9.0.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.2.1",
|
||||
"@ngx-translate/core": ">=16.0.0",
|
||||
"@alfresco/adf-core": ">=8.2.1"
|
||||
"@alfresco/js-api": ">=9.5.0",
|
||||
"@ngx-translate/core": ">=17.0.0",
|
||||
"@alfresco/adf-core": ">=8.5.0"
|
||||
},
|
||||
"keywords": [
|
||||
"content-services",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"options": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "stylelint lib/content-services/**/*.scss --config stylelint-config.json"
|
||||
"command": "stylelint \"lib/content-services/**/*.scss\" --config .stylelintrc.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -55,7 +55,7 @@
|
||||
"cwd": "dist/libs/content-services",
|
||||
"commands": [
|
||||
{
|
||||
"command": "npm publish --tag {args.tag}",
|
||||
"command": "pnpm publish --no-git-checks --tag {args.tag}",
|
||||
"forwardAllArgs": true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Agent, AgentsApi } from '@alfresco/js-api';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Agent, AgentsApi, LazyApi } from '@alfresco/js-api';
|
||||
import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { AlfrescoApiService } from '../../services';
|
||||
@@ -25,18 +25,15 @@ import { AlfrescoApiService } from '../../services';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AgentService {
|
||||
private _agentsApi: AgentsApi;
|
||||
private agents = new BehaviorSubject<Agent[]>([]);
|
||||
private readonly apiService = inject(AlfrescoApiService);
|
||||
|
||||
get agentsApi(): AgentsApi {
|
||||
this._agentsApi = this._agentsApi ?? new AgentsApi(this.apiService.getInstance());
|
||||
return this._agentsApi;
|
||||
}
|
||||
private readonly agents = new BehaviorSubject<Agent[]>([]);
|
||||
|
||||
@LazyApi((self: AgentService) => new AgentsApi(self.apiService.getInstance()))
|
||||
declare readonly agentsApi: AgentsApi;
|
||||
|
||||
agents$ = this.agents.asObservable();
|
||||
|
||||
constructor(private apiService: AlfrescoApiService) {}
|
||||
|
||||
/**
|
||||
* Gets all agents from cache. If cache is empty, fetches agents from backend.
|
||||
*
|
||||
|
||||
@@ -1 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="17.2 134.6 562 573.1"><path fill="#FFF" d="M298.2,421.3L219,340.4l-2.9-2.9c-45.4-46.5-119.5-46.5-164.7-0.2c-45.6,46.3-45.6,121.5,0,167.8 c45.2,46.4,119,46.4,164.4,0L298.2,421.3z"/><path fill="#FFF" d="M298.2,421.2v114.3l0.2,4.2c0,65.5-52.2,119-116.5,119c-64.3,0-116.5-53.1-116.5-118.6 c0-65.6,52.4-118.8,116.5-118.8H298.2z"/><path fill="#FFF" d="M298.2,421.2v114.3l0.2,4.2c0,65.5-52.2,119-116.5,119c-64.3,0-116.5-53.1-116.5-118.6 c0-65.6,52.4-118.8,116.5-118.8H298.2z"/><path fill="#FFF" d="M298.2,421.2v114.3l0.2,4.2c0,65.5-52.2,119-116.5,119c-64.3,0-116.5-53.1-116.5-118.6 c0-7.3,0.8-14.4,2-21.2c45.4,32.2,108.2,27.7,148.6-13.7l82.4-83.8V421.2z"/><path fill="#8ABF42" d="M181.9,436.1c-56.1,0-101.6,46.5-101.6,103.8c0,57.1,45.6,103.5,101.6,103.5c56.2,0,101.7-46.4,101.7-103.5 v-4.5v-99.3H182.1H181.9z"/><path fill="#FFF" d="M298.2,421.2l79.2,80.8l3.3,2.9c45.2,46.4,45.5,121.8,0,168.1c-45.6,46.3-119.2,46.3-164.8,0 c-45.4-46.3-45.4-121.5,0-168L298.2,421.2z"/><path fill="#8ABF42" d="M226.5,515.6c-39.8,40.5-39.8,106.2,0,146.6c39.6,40.5,104,40.5,143.8,0c39.6-40.4,39.6-106.1,0-146.6 l-3.3-3l-68.7-70.2l-71.7,73.1V515.6z"/><path fill="#FFF" d="M298.2,421.2h112.2l4.1-0.2c64.4,0,116.5,53.2,116.5,118.8c0,65.6-52,118.6-116.3,118.6 c-64.3,0-116.5-53.1-116.5-118.6V421.2z"/><path fill="#8ABF42" d="M313.1,539.8c0,57.3,45.4,103.7,101.6,103.7c56,0,101.4-46.4,101.4-103.7c0-57.3-45.4-103.6-101.4-103.6 h-4.3h-97.4v103.3V539.8z"/><path fill="#FFF" d="M298.2,421.2l79.2-80.9l3.1-3.1c45.4-46.3,119.2-46.5,164.6-0.2c45.4,46.4,45.4,121.5,0,167.9 c-45.4,46.4-119.2,46.4-164.6,0L298.2,421.2z"/><path fill="#8ABF42" d="M391.1,494.3c39.4,40.6,103.8,40.6,143.6,0c39.8-40.4,39.8-106,0-146.5c-39.8-40.5-104.1-40.5-143.6,0 l-3.3,3.2l-68.6,70.3l71.5,73L391.1,494.3z"/><path fill="#FFF" d="M298.2,421.2V306.8v-4.3c0-65.5,51.9-118.8,116.5-118.8c64.2,0,116.1,52.9,116.1,118.6 c0,65.6-52,118.8-116.1,118.8H298.2z"/><path fill="#F89F31" d="M414.7,406.1c56,0,101.4-46.4,101.4-103.7c0-57.1-45.4-103.6-101.4-103.6c-56.3,0-101.8,46.5-101.8,103.6 l0.2,4.4v99.3h101.1H414.7z"/><path fill="#FFF" d="M298.2,421.2L219,340.3l-3.1-2.9c-45.4-46.5-45.4-121.8,0-168.1c45.2-46.4,119.1-46.4,164.6,0 c45.4,46.3,45.4,121.6,0,167.9L298.2,421.2z"/><path fill="#0080C5" d="M370.1,327.6c39.6-40.5,39.6-106.2,0-146.6c-39.8-40.5-104-40.5-143.7,0c-39.8,40.4-39.8,106.1,0,146.6 l2.9,3.1l69,70.1l71.6-73L370.1,327.6z"/><path fill="#FFF" d="M298.2,422.1H186.1l-4.2,0.1c-64.1,0-116.5-53.2-116.5-118.8c0-65.5,52.2-118.7,116.3-118.7 c64.3,0,116.6,53.2,116.6,118.8V422.1z"/><path fill="#0080C5" d="M283.5,303.5c0-57.3-45.4-103.6-101.8-103.6c-56,0-101.6,46.3-101.6,103.5c0,57.2,45.6,103.7,101.6,103.7 l4.4-0.1h97.4V303.8V303.5z"/><path fill="#FFF" d="M298.2,422.1l-281,0.1c0-30.4,11.2-60.8,34.2-84c45.2-46.3,119-46.3,164.4,0L298.2,422.1z"/><path fill="#0080C5" d="M205.4,348.9l71.9,73.3h-95.5c-51.6,0-95.5,34.3-110.7,81.9c-3.1-2.7-6.4-5.5-9.3-8.7 c-39.8-40.5-39.8-106,0-146.5C101.3,308.4,165.8,308.4,205.4,348.9"/><path fill="#005DA9" d="M205.6,349l56.9,58l-80.9,0.2c-46.6,0-85.8-31.9-97.8-75.5c38.6-22.1,89.2-16.8,121.6,17.1L205.6,349z"/><path fill="#005DA9" d="M283.5,303.7l-0.1,82.1l-57.1-58.2c-32.9-33.6-38.7-84.4-17-123.8c42.7,12.2,74.2,52.2,74.2,99.8V303.7z"/><path fill="#005DA9" d="M312.6,386v-82.4c0-47.5,31.5-87.5,74.2-99.8c21.6,39.5,17.6,89-16.4,123.3L312.6,386z"/><path fill="#FFDE4F" d="M333.9,406.1l57.1-58.3c32.9-33.6,82.8-39.3,121.4-17.2c-12.2,43.5-49.4,74.8-95.3,75.6L333.9,406.1z"/><path fill="#48A64A" d="M333.8,436.1h80.8c46.6,0,85.8,31.7,97.8,75.4c-38.9,22.2-88.7,16.3-121.8-17.2L333.8,436.1z"/><path fill="#48A64A" d="M313.1,539.2v-82l57.2,58.2c32.9,33.7,38.5,84.7,16.8,124.1c-42.7-12.2-74-52.4-74-99.9V539.2z"/><path fill="#48A64A" d="M226.6,515.4l56.9-58l0.1,82.4c0,47.5-31.3,87.4-74,99.7c-21.6-39.5-15.8-90.4,17-123.9V515.4z"/><path fill="#48A64A" d="M182.4,436.1h80.4l-57,58.2c-32.8,33.5-83.1,39.3-121.7,17.3c12.1-43.7,51.4-75.5,98-75.5H182.4z"/></svg>
|
||||
<svg width="24" height="24" viewBox="0 0 316 316" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M159.2 162.346L152.375 169.174L114.409 207.15L114.41 207.151C95.0944 226.491 91.3457 255.445 103.066 278.58L105.601 283.58L100.048 284.35C97.5523 284.696 95.002 284.89 92.4004 284.89C58.599 284.89 31.2188 257.426 31.2188 223.6C31.2189 189.771 58.6023 162.346 92.4004 162.346H159.2Z" fill="#F1CB60" stroke="white" stroke-width="8"/>
|
||||
<path d="M161.863 223.528C161.863 250.858 179.632 273.984 204.244 282.042L209.613 283.799L206.171 288.28C204.697 290.199 203.069 292.185 201.168 294.053L201.169 294.054C177.272 317.982 138.527 317.982 114.63 294.054C90.7354 270.129 90.7354 231.344 114.63 207.419L114.737 207.312L155.033 166.965L161.863 160.126V223.528Z" fill="#52A1FF" stroke="white" stroke-width="8"/>
|
||||
<path d="M168.975 163.484L206.938 201.495C226.257 220.806 255.17 224.584 278.189 212.857L283.198 210.306L283.968 215.873C284.313 218.371 284.508 220.924 284.508 223.528C284.508 257.357 257.124 284.783 223.326 284.783C189.528 284.783 162.145 257.357 162.145 223.528V156.646L168.975 163.484Z" fill="#52A1FF" stroke="white" stroke-width="8"/>
|
||||
<path d="M287.968 109.621C289.701 110.956 291.383 112.384 293.011 113.93L293.705 114.6L293.721 114.615L293.735 114.629C317.63 138.554 317.63 177.339 293.735 201.264C269.838 225.192 231.094 225.192 207.196 201.264L207.089 201.157L166.793 160.809L159.975 153.983H223.291C250.543 153.983 273.676 136.196 281.725 111.548L283.482 106.166L287.968 109.621Z" fill="#06C9A4" stroke="white" stroke-width="8"/>
|
||||
<path d="M223.29 31.1108C257.091 31.1108 284.472 58.5754 284.472 92.4009C284.472 126.23 257.088 153.655 223.29 153.655H156.496L163.314 146.829L201.28 108.814C220.562 89.5077 224.344 60.5534 212.624 37.4214L210.09 32.4214L215.643 31.6509C218.138 31.3049 220.688 31.1108 223.29 31.1108Z" fill="#06C9A4" stroke="white" stroke-width="8"/>
|
||||
<path d="M114.521 21.9453C138.419 -1.98214 177.163 -1.98201 201.061 21.9453C224.953 45.8676 224.956 84.6509 201.062 108.542L201.062 108.543L200.953 108.652L160.657 148.999L153.827 155.838V92.4365C153.827 65.1407 136.058 41.9797 111.447 33.9229L106.023 32.1465L109.542 27.6543C111.031 25.7534 112.682 23.7871 114.521 21.9453Z" fill="#6E33FF" stroke="white" stroke-width="8"/>
|
||||
<path d="M92.3301 31.2173C126.128 31.2174 153.512 58.6426 153.512 92.4712V153.69H147.817L146.646 152.516L110.4 116.225L110.37 116.195L110.34 116.164L108.773 114.526C89.4526 95.1918 60.4773 91.3832 37.4277 103.108L32.3408 105.696L31.6445 100.031C31.3429 97.577 31.1484 95.0763 31.1484 92.4712C31.1486 58.6426 58.532 31.2173 92.3301 31.2173Z" fill="#6E33FF" stroke="white" stroke-width="8"/>
|
||||
<path d="M21.9209 114.737C45.8182 90.8094 84.5627 90.8094 108.46 114.737L148.863 155.192L155.682 162.019H92.3652C90.8311 162.019 89.3122 162.086 87.7979 162.189L87.6611 162.198H87.5254C87.4492 162.198 87.2902 162.209 86.9639 162.246L86.9277 162.25L86.8926 162.252C85.408 162.391 83.9689 162.56 82.5908 162.79L82.5107 162.803L82.4297 162.813C82.4583 162.809 82.4593 162.807 82.3359 162.833C82.29 162.842 82.1909 162.863 82.0977 162.881C82.0291 162.895 81.945 162.908 81.8506 162.923L81.8516 162.925C80.5313 163.163 79.241 163.434 77.9443 163.742L77.8125 163.773L77.6797 163.794C77.6455 163.8 77.6113 163.806 77.585 163.81C77.5563 163.815 77.5338 163.818 77.5127 163.822C77.5041 163.823 77.4963 163.824 77.4893 163.826L77.4492 163.839L77.2891 163.878C75.9507 164.205 74.6195 164.604 73.2402 165.053C73.1272 165.091 73.0137 165.131 72.8691 165.182C72.735 165.23 72.5701 165.286 72.3916 165.346L72.3926 165.347C71.0135 165.83 69.646 166.344 68.3232 166.887L68.1299 166.966C66.862 167.502 65.6611 168.056 64.5137 168.663L64.4746 168.683L64.4355 168.703C64.3466 168.747 64.2575 168.795 64.1172 168.87C64.0059 168.929 63.8551 169.008 63.6885 169.092L63.6895 169.093C62.4463 169.75 61.2522 170.416 60.1152 171.131L60.1143 171.13C59.9666 171.227 59.8284 171.315 59.7422 171.368C59.6129 171.447 59.5605 171.48 59.5244 171.504L59.4756 171.537L59.4248 171.568C58.4258 172.193 57.4061 172.892 56.3779 173.62C56.2243 173.749 56.0938 173.847 56.0088 173.909C55.9378 173.96 55.8634 174.012 55.8408 174.028C55.8034 174.054 55.8117 174.048 55.833 174.032L55.7861 174.067C54.7178 174.845 53.6631 175.701 52.6191 176.612L52.6074 176.623L52.5947 176.633C52.4695 176.741 52.3441 176.848 52.2188 176.956C52.1013 177.056 51.9828 177.156 51.8652 177.257L51.8662 177.258C50.8262 178.165 49.7815 179.144 48.8047 180.122L48.5537 180.373C47.6777 181.25 46.8437 182.176 45.9697 183.183C45.8135 183.387 45.6703 183.554 45.5732 183.665C45.3997 183.862 45.4018 183.855 45.3564 183.91L45.3486 183.919C44.4388 185.006 43.5746 186.073 42.7939 187.148C42.7312 187.236 42.6712 187.323 42.5967 187.431C42.5177 187.545 42.4206 187.685 42.3115 187.838L42.3047 187.847C41.5605 188.884 40.8682 189.937 40.1514 191.063C40.1001 191.151 40.0531 191.227 40.0127 191.289C39.98 191.339 39.9466 191.385 39.9199 191.423C39.1621 192.724 38.4678 193.918 37.8467 195.129C37.7813 195.26 37.7157 195.391 37.6504 195.522C37.5787 195.665 37.5072 195.809 37.4355 195.953C36.7984 197.228 36.2384 198.388 35.7441 199.573C35.6963 199.727 35.6486 199.856 35.6094 199.958C35.5728 200.052 35.5371 200.136 35.5205 200.175C35.4987 200.227 35.4954 200.237 35.4922 200.245L35.4707 200.297C34.9663 201.509 34.5042 202.735 34.1133 203.942L34.0723 204.069L34.0225 204.193C33.9639 204.339 33.7844 204.809 33.4883 205.303L31.1553 209.196L27.5869 206.393C25.6385 204.863 23.7246 203.178 21.9209 201.372C-1.97351 177.447 -1.97359 138.662 21.9209 114.737Z" fill="#F1CB60" stroke="white" stroke-width="8"/>
|
||||
<ellipse cx="157.5" cy="158" rx="5.5" ry="5" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5.5 KiB |
@@ -16,16 +16,13 @@
|
||||
*/
|
||||
|
||||
import { AdfHttpClient } from '@alfresco/adf-core/api';
|
||||
import { StorageService, AppConfigService } from '@alfresco/adf-core';
|
||||
import { AlfrescoApi, AlfrescoApiConfig } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class AlfrescoApiNoAuthService extends AlfrescoApiService {
|
||||
constructor(storage: StorageService, appConfig: AppConfigService, private readonly adfHttpClient: AdfHttpClient) {
|
||||
super(appConfig, storage);
|
||||
}
|
||||
private readonly adfHttpClient = inject(AdfHttpClient);
|
||||
|
||||
override createInstance(config: AlfrescoApiConfig) {
|
||||
return new AlfrescoApi(
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { AlfrescoApiConfig } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { AppConfigService, AppConfigValues, StorageService } from '@alfresco/adf-core';
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { SecurityOptionsLoaderService } from '../security-options-loader/security-options-loader.service';
|
||||
@@ -35,12 +35,10 @@ export function createAlfrescoApiInstance(angularAlfrescoApiService: AlfrescoApi
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AlfrescoApiLoaderService {
|
||||
constructor(
|
||||
private readonly appConfig: AppConfigService,
|
||||
private readonly apiService: AlfrescoApiService,
|
||||
private readonly securityOptionsLoaderService: SecurityOptionsLoaderService,
|
||||
private storageService: StorageService
|
||||
) {}
|
||||
private readonly appConfig = inject(AppConfigService);
|
||||
private readonly apiService = inject(AlfrescoApiService);
|
||||
private readonly securityOptionsLoaderService = inject(SecurityOptionsLoaderService);
|
||||
private readonly storageService = inject(StorageService);
|
||||
|
||||
async init(): Promise<any> {
|
||||
await this.appConfig.load(this.securityOptionsLoaderService.load);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<div class="adf-aspect-list-dialog-information">
|
||||
<p id="aspect-list-dialog-over-table-message">{{overTableMessage | translate}}</p>
|
||||
<p id="aspect-list-dialog-counter">{{counter}}
|
||||
<p id="aspect-list-dialog-counter" aria-live="polite">{{counter}}
|
||||
{{'ADF-ASPECT-LIST.DIALOG.SELECTED' | translate}}</p>
|
||||
</div>
|
||||
<mat-dialog-content class="adf-aspect-dialog-content">
|
||||
|
||||
@@ -9,8 +9,7 @@ adf-aspect-list-dialog {
|
||||
}
|
||||
|
||||
.adf-aspect-list-dialog-title {
|
||||
font-size: large;
|
||||
font-weight: 200;
|
||||
font: var(--mat-sys-headline-medium);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@@ -44,11 +43,6 @@ adf-aspect-list-dialog {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.adf-aspect-property-table {
|
||||
.adf-aspect-property-table-cell {
|
||||
font-size: smaller;
|
||||
color: var(--adf-theme-foreground-text-color-087);
|
||||
}
|
||||
|
||||
.adf-aspect-property-table-column {
|
||||
&-name {
|
||||
width: 30%;
|
||||
|
||||
@@ -27,6 +27,8 @@ import { NodesApiService } from '../common/services/nodes-api.service';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { AspectListComponent } from './aspect-list.component';
|
||||
import { provideApiTesting } from '../testing/providers';
|
||||
import { UnitTestingUtils } from '@alfresco/adf-core';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
const aspectListMock: AspectEntry[] = [
|
||||
{
|
||||
@@ -99,11 +101,19 @@ describe('AspectListDialogComponent', () => {
|
||||
let aspectListService: AspectListService;
|
||||
let nodeService: NodesApiService;
|
||||
let data: AspectListDialogComponentData;
|
||||
let testingUtils: UnitTestingUtils;
|
||||
const event = new KeyboardEvent('keydown', {
|
||||
bubbles: true,
|
||||
keyCode: 27
|
||||
} as KeyboardEventInit);
|
||||
|
||||
const getResetButton = (): DebugElement => testingUtils.getByCSS('#aspect-list-dialog-actions-reset');
|
||||
const getClearButton = (): DebugElement => testingUtils.getByCSS('#aspect-list-dialog-actions-clear');
|
||||
const getCancelButton = (): DebugElement => testingUtils.getByCSS('#aspect-list-dialog-actions-cancel');
|
||||
const getApplyButton = (): DebugElement => testingUtils.getByCSS('#aspect-list-dialog-actions-apply');
|
||||
const getAspectCounter = (): string => testingUtils.getInnerTextByCSS('#aspect-list-dialog-counter');
|
||||
const getAspectCheckbox = (index: number): HTMLInputElement => testingUtils.getByCSS(`#aspect-list-${index}-check-input`).nativeElement;
|
||||
|
||||
beforeEach(() => {
|
||||
data = {
|
||||
title: 'Title',
|
||||
@@ -128,6 +138,7 @@ describe('AspectListDialogComponent', () => {
|
||||
]
|
||||
});
|
||||
fixture = TestBed.createComponent(AspectListDialogComponent);
|
||||
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||
});
|
||||
|
||||
describe('Without passing node id', () => {
|
||||
@@ -144,91 +155,81 @@ describe('AspectListDialogComponent', () => {
|
||||
});
|
||||
|
||||
it('should show 4 actions : CLEAR, RESET, CANCEL and APPLY', () => {
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-reset')).not.toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-reset')).toBeDefined();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-clear')).not.toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-clear')).toBeDefined();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-cancel')).not.toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-cancel')).toBeDefined();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-apply')).not.toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('#aspect-list-dialog-actions-apply')).toBeDefined();
|
||||
expect(getResetButton()).toBeDefined();
|
||||
expect(getClearButton()).toBeDefined();
|
||||
expect(getCancelButton()).toBeDefined();
|
||||
expect(getApplyButton()).toBeDefined();
|
||||
});
|
||||
|
||||
it('should show basic information for the dialog', () => {
|
||||
const dialogTitle = fixture.nativeElement.querySelector('[data-automation-id="aspect-list-dialog-title"] .adf-aspect-list-dialog-title');
|
||||
expect(dialogTitle).not.toBeNull();
|
||||
expect(dialogTitle.innerText).toBe(data.title);
|
||||
const dialogTitleText = testingUtils.getInnerTextByCSS('[data-automation-id="aspect-list-dialog-title"] .adf-aspect-list-dialog-title');
|
||||
expect(dialogTitleText).toBe(data.title);
|
||||
|
||||
const dialogDescription = fixture.nativeElement.querySelector(
|
||||
const dialogDescription = testingUtils.getInnerTextByCSS(
|
||||
'[data-automation-id="aspect-list-dialog-title"] .adf-aspect-list-dialog-description'
|
||||
);
|
||||
expect(dialogDescription).not.toBeNull();
|
||||
expect(dialogDescription.innerText).toBe(data.description);
|
||||
expect(dialogDescription).toBe(data.description);
|
||||
|
||||
const overTableMessage = fixture.nativeElement.querySelector('#aspect-list-dialog-over-table-message');
|
||||
expect(overTableMessage).not.toBeNull();
|
||||
expect(overTableMessage.innerText).toBe(data.overTableMessage);
|
||||
|
||||
const selectionCounter = fixture.nativeElement.querySelector('#aspect-list-dialog-counter');
|
||||
expect(selectionCounter).not.toBeNull();
|
||||
expect(selectionCounter.innerText).toBe('0 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
expect(testingUtils.getInnerTextByCSS('#aspect-list-dialog-over-table-message')).toBe(data.overTableMessage);
|
||||
expect(getAspectCounter()).toBe('0 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
});
|
||||
|
||||
it('should update the counter when an option is selcted and unselected', async () => {
|
||||
const firstAspectCheckbox: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
it('should update the counter when an option is selected and unselected', async () => {
|
||||
const firstAspectCheckbox = getAspectCheckbox(0);
|
||||
expect(firstAspectCheckbox).toBeDefined();
|
||||
expect(firstAspectCheckbox).not.toBeNull();
|
||||
let selectionCounter = fixture.nativeElement.querySelector('#aspect-list-dialog-counter');
|
||||
expect(selectionCounter).not.toBeNull();
|
||||
expect(selectionCounter.innerText).toBe('0 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
firstAspectCheckbox.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
selectionCounter = fixture.nativeElement.querySelector('#aspect-list-dialog-counter');
|
||||
expect(selectionCounter).not.toBeNull();
|
||||
expect(selectionCounter.innerText).toBe('1 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
expect(getAspectCounter()).toBe('0 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
|
||||
firstAspectCheckbox.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
selectionCounter = fixture.nativeElement.querySelector('#aspect-list-dialog-counter');
|
||||
expect(selectionCounter).not.toBeNull();
|
||||
expect(selectionCounter.innerText).toBe('0 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
expect(getAspectCounter()).toBe('1 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
|
||||
firstAspectCheckbox.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(getAspectCounter()).toBe('0 ADF-ASPECT-LIST.DIALOG.SELECTED');
|
||||
});
|
||||
|
||||
it('should reset to the node values when Reset button is clicked', async () => {
|
||||
let firstAspectCheckbox: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
let firstAspectCheckbox = getAspectCheckbox(0);
|
||||
expect(firstAspectCheckbox).toBeDefined();
|
||||
expect(firstAspectCheckbox).not.toBeNull();
|
||||
|
||||
firstAspectCheckbox.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const resetButton: HTMLButtonElement = fixture.nativeElement.querySelector('#aspect-list-dialog-actions-reset');
|
||||
|
||||
const resetButton: HTMLButtonElement = getResetButton().nativeElement;
|
||||
expect(resetButton).toBeDefined();
|
||||
expect(firstAspectCheckbox.checked).toBeTruthy();
|
||||
|
||||
resetButton.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
firstAspectCheckbox = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
|
||||
firstAspectCheckbox = getAspectCheckbox(0);
|
||||
expect(firstAspectCheckbox.checked).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should clear all the value when Clear button is clicked', async () => {
|
||||
let firstAspectCheckbox: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
let firstAspectCheckbox = getAspectCheckbox(0);
|
||||
expect(firstAspectCheckbox).toBeDefined();
|
||||
expect(firstAspectCheckbox).not.toBeNull();
|
||||
|
||||
firstAspectCheckbox.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const clearButton: HTMLButtonElement = fixture.nativeElement.querySelector('#aspect-list-dialog-actions-clear');
|
||||
|
||||
const clearButton: HTMLButtonElement = getClearButton().nativeElement;
|
||||
expect(clearButton).toBeDefined();
|
||||
expect(firstAspectCheckbox.checked).toBeTruthy();
|
||||
|
||||
clearButton.click();
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
firstAspectCheckbox = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
|
||||
firstAspectCheckbox = getAspectCheckbox(0);
|
||||
expect(firstAspectCheckbox.checked).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -238,7 +239,7 @@ describe('AspectListDialogComponent', () => {
|
||||
() => {},
|
||||
() => done()
|
||||
);
|
||||
const cancelButton: HTMLButtonElement = fixture.nativeElement.querySelector('#aspect-list-dialog-actions-cancel');
|
||||
const cancelButton: HTMLButtonElement = getCancelButton().nativeElement;
|
||||
expect(cancelButton).toBeDefined();
|
||||
cancelButton.click();
|
||||
fixture.detectChanges();
|
||||
@@ -272,17 +273,14 @@ describe('AspectListDialogComponent', () => {
|
||||
await fixture.whenRenderingDone();
|
||||
const firstAspectCheckbox: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
expect(firstAspectCheckbox).toBeDefined();
|
||||
expect(firstAspectCheckbox).not.toBeNull();
|
||||
expect(firstAspectCheckbox.checked).toBeTruthy();
|
||||
|
||||
const notCheckedAspect: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-1-check-input');
|
||||
expect(notCheckedAspect).toBeDefined();
|
||||
expect(notCheckedAspect).not.toBeNull();
|
||||
expect(notCheckedAspect.checked).toBeFalsy();
|
||||
|
||||
const customAspectCheckbox: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-2-check-input');
|
||||
expect(customAspectCheckbox).toBeDefined();
|
||||
expect(customAspectCheckbox).not.toBeNull();
|
||||
expect(customAspectCheckbox.checked).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -298,14 +296,16 @@ describe('AspectListDialogComponent', () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
const applyButton = fixture.nativeElement.querySelector('#aspect-list-dialog-actions-apply');
|
||||
|
||||
fixture.nativeElement.querySelector('#aspect-list-dialog-actions-clear').click();
|
||||
getClearButton().nativeElement.click();
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(applyButton.disabled).toBe(false);
|
||||
expect(getApplyButton().nativeElement.disabled).toBe(false);
|
||||
});
|
||||
|
||||
it('should announce the amount of selected aspects', () => {
|
||||
expect(testingUtils.getByCSS('#aspect-list-dialog-counter').nativeElement.getAttribute('aria-live')).toBe('polite');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user