Compare commits

..
Author SHA1 Message Date
DominikIwanek 079047702f Release 8.0.3 2026-08-24 16:35:30 +02:00
DominikIwanek 85e46c7007 Release 8.0.3 2026-08-24 16:26:07 +02:00
DominikIwanek f2a0b3f826 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-21 09:33:26 +02:00
DominikIwanek 425b4bab67 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-21 09:14:17 +02:00
DominikIwanek 97f1136f96 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-21 09:04:42 +02:00
DominikIwanek 9cd94f8e39 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-21 08:45:17 +02:00
DominikIwanek 48391f2db5 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-21 08:23:01 +02:00
DominikIwanek b923e41b2f Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 15:52:17 +02:00
DominikIwanek 1e0c569f47 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 15:47:34 +02:00
DominikIwanek 4e38d1d44c Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 15:34:44 +02:00
DominikIwanek 21a275a777 Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 15:30:05 +02:00
DominikIwanek 5ecc05a84f Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 15:08:46 +02:00
DominikIwanek c52a63485b Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 15:01:18 +02:00
DominikIwanek d4e0da26ac Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 14:47:02 +02:00
DominikIwanek 4d54d8512b Release 8.0.3 - Fix PNG signature images in PDF viewer 2026-08-20 14:29:26 +02:00
MichalKinas a74338e21d Release 8.0.2 2026-02-25 11:15:17 +01:00
MichalKinas 31d293bdb2 [MNT-25541] Small unit testing fix 2026-02-25 11:04:01 +01:00
Anton Ramanovich d4714e2b01 [MNT-25541] PDFs containing JP2 images (JPEG 2000) cannot be displayed in ADW viewer (#11618)
* [MNT-25541]: adds wasmUrl to default options

* [MNT-25541]: updates UTs

* [MNT-25541]: naming change
2026-02-25 11:01:44 +01:00
MichalKinas f751370b60 Release from branch workflow fix 2025-08-11 12:55:29 +02:00
MichalKinas 49062ae19d Release 8.0.1 2025-08-11 08:56:26 +02:00
Copilotanderomano ecd4fed2ac Remove unused webdriver-manager dependency to eliminate vulnerable form-data ~2.3.2 (#11060)
* Initial plan

* Remove webdriver-manager to eliminate form-data ~2.3.2 dependency

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>
2025-08-11 08:48:13 +02:00
dependabot[bot] c7e6051b1a build(deps): bump form-data from 3.0.1 to 3.0.4 in /tools/doc (#11043)
Bumps [form-data](https://github.com/form-data/form-data) from 3.0.1 to 3.0.4.
- [Release notes](https://github.com/form-data/form-data/releases)
- [Changelog](https://github.com/form-data/form-data/blob/v3.0.4/CHANGELOG.md)
- [Commits](https://github.com/form-data/form-data/compare/v3.0.1...v3.0.4)

---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 3.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 08:35:43 +02:00
dependabot[bot] db0aafa5df build(deps): bump form-data from 4.0.0 to 4.0.4 in /lib/cli (#11046)
Bumps [form-data](https://github.com/form-data/form-data) from 4.0.0 to 4.0.4.
- [Release notes](https://github.com/form-data/form-data/releases)
- [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md)
- [Commits](https://github.com/form-data/form-data/compare/v4.0.0...v4.0.4)

---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-11 08:35:16 +02:00
122 changed files with 2250 additions and 4122 deletions
+26 -13
View File
@@ -9,18 +9,17 @@ inputs:
runs:
using: "composite"
steps:
- name: Before install
if: ${{ ! env.ACT }}
shell: bash
run: |
pip install --user --quiet awscli
- name: base vars
shell: bash
run: |
if [ -n "${GITHUB_BASE_REF:-}" ]; then
BASE_HASH=$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD 2>/dev/null || git rev-parse HEAD)
else
BASE_HASH=$(git rev-parse HEAD)
fi
{
echo "GIT_HASH=$(git rev-parse HEAD)";
echo "BASE_HASH=$(git merge-base origin/${GITHUB_BASE_REF} HEAD)";
echo "BASE_HASH=${BASE_HASH}";
echo "HEAD_HASH=HEAD";
echo "HEAD_COMMIT_HASH=${GH_COMMIT}";
echo "NX_CALCULATION_FLAGS=--all";
@@ -31,10 +30,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 }}
@@ -49,13 +60,15 @@ runs:
} >> $GITHUB_ENV
- name: RELEASE on master/develop patch branch
if: ${{ env.BREAK_ACTION == false && github.event.pull_request.merged }}
if: ${{ env.BREAK_ACTION == false && (github.event.pull_request.merged || github.event_name == 'push') }}
shell: bash
env:
REF_NAME: ${{ github.ref_name }}
run: |
if [[ "${{ github.ref_name }}" =~ ^master(-patch.*)?$ ]]; then
if [[ "$REF_NAME" =~ ^master(-patch.*)?$ ]]; then
# into master(-patch*)
echo "Setting up CI flags for Push on master patch"
elif [[ "${{ github.ref_name }}" =~ ^develop-patch.*$ ]]; then
elif [[ "$REF_NAME" =~ ^develop-patch.*$ ]]; then
# into develop-patch*
echo "Setting up CI flags for Push develop patch"
else
+1 -1
View File
@@ -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 }}
@@ -3,17 +3,33 @@ description: "Download build artifacts"
runs:
using: "composite"
steps:
- name: download and extract artifacts from s3
shell: bash
env:
REMOTE_PATH: "alfresco-ng2-components/build-cache/${{ github.run_id }}"
run: |
packages=( dist nxcache node_modules )
for i in "${packages[@]}"; do
time aws s3 cp --no-progress s3://${S3_BUILD_BUCKET_SHORT_NAME}/${REMOTE_PATH}/$i.tar.gz $i.tar.gz
du -h $i.tar.gz
time tar xzf $i.tar.gz
done
- name: Restore dist from cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: dist
key: dist-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
dist-${{ github.run_id }}-
fail-on-cache-miss: true
- name: Restore nxcache from cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: nxcache
key: nxcache-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
nxcache-${{ github.run_id }}-
fail-on-cache-miss: true
- name: Restore node_modules from cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: node_modules
key: node-modules-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
node-modules-${{ github.run_id }}-
fail-on-cache-miss: true
- name: show files
shell: bash
run: |
@@ -24,4 +40,4 @@ runs:
echo "====NXCACHE===="
find nxcache -maxdepth 1 -type d
echo "====ADF===="
find node_modules/@alfresco/ -maxdepth 1 -type d
find node_modules/@alfresco/ -maxdepth 1 -type d
+29 -21
View File
@@ -2,36 +2,44 @@ name: "set npm tag"
description: "se NPM tag"
inputs:
event_name:
description: "override github.event_name"
required: false
default: ${{ github.event_name }}
branch_name:
description: "override GITHUB_REF_NAME"
required: false
default: $GITHUB_REF_NAME
default: ${{ github.ref_name }}
outputs:
npm-tag:
description: "NPM tag"
value: ${{ steps.set-npm-tag.outputs.npm-tag }}
runs:
using: "composite"
steps:
- name: set TAG_NPM
id: set-npm-tag
shell: bash
env:
BRANCH_NAME: ${{ inputs.branch_name }}
run: |
TAG_NPM="alpha"
VERSION_IN_PACKAGE_JSON=$(node -p "require('./package.json')".version)
echo "version in package.json=${VERSION_IN_PACKAGE_JSON}"
if [[ ${{ inputs.branch_name }} =~ ^master(-patch.*)?$ ]]; then
# Pre-release versions
if [[ $VERSION_IN_PACKAGE_JSON =~ ^[0-9]*\.[0-9]*\.[0-9]*-A\.[0-9]*$ ]];
then
TAG_NPM=next
# Stable major versions
else
TAG_NPM=latest
fi
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
TAG_NPM="branch"
else
TAG_NPM="alpha"
VERSION_IN_PACKAGE_JSON=$(node -p "require('./package.json')".version)
echo "version in package.json=${VERSION_IN_PACKAGE_JSON}"
if [[ $BRANCH_NAME =~ ^master(-patch.*)?$ ]]; then
# Pre-release versions
if [[ $VERSION_IN_PACKAGE_JSON =~ ^[0-9]*\.[0-9]*\.[0-9]*-A\.[0-9]*$ ]]; then
TAG_NPM=next
# Stable major versions
else
TAG_NPM=latest
fi
fi
if [[ $BRANCH_NAME =~ ^develop(-patch.*)?$ ]]; then
TAG_NPM=alpha
fi
fi
if [[ ${{ inputs.branch_name }} =~ ^develop(-patch.*)?$ ]]; then
TAG_NPM=alpha
fi
echo "TAG_NPM=${TAG_NPM}" >> $GITHUB_ENV
echo "npm-tag=$TAG_NPM" >> $GITHUB_OUTPUT
echo "Computed tag: $TAG_NPM"
+36 -32
View File
@@ -1,13 +1,12 @@
name: 'Setup'
description: 'Initialize cache, env var load'
inputs:
enable-cache:
description: 'enable caching'
cache-suffix:
description: 'Suffix to make Nx cache key unique per job (e.g. matrix project name)'
required: false
type: boolean
default: 'true'
enable-node-modules-cache:
description: 'enable caching for node modules'
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'
@@ -16,43 +15,48 @@ inputs:
required: false
type: boolean
default: 'false'
outputs:
npm-tag:
description: 'NPM tag'
value: ${{ steps.set-npm-tag.outputs.npm-tag }}
runs:
using: "composite"
steps:
- name: install NPM
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- name: Set consistent machine ID for Nx cache
shell: bash
run: echo "nx-github-actions" | sudo tee /etc/machine-id > /dev/null
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
cache-dependency-path: package-lock.json
cache: 'npm'
- name: get latest tag sha
if: ${{ inputs.full-setup == 'true' }}
id: tag-sha
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@20d21f43addae05442096a7e935dc2b321361501 # v8.27.0
# CACHE
- name: Node Modules cache
id: node-modules-cache
if: ${{ inputs.enable-node-modules-cache == 'true' }}
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
env:
cache-name: node-modules-cache
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@98bcfbe06aafffdc0e9a790f352602316f82303b # v18.23.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: npm ci
- name: Security audit
shell: bash
run: npm audit --audit-level=critical || true
- name: Restore nx cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
node_modules
key: .npm-${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
nxcache
.nx
dist
key: ${{ runner.os }}-nxcache-${{ inputs.cache-suffix }}-${{ hashFiles('nx.json') }}-${{ github.sha }}
restore-keys: |
node_modules-${{ runner.os }}-build-${{ env.cache-name }}-
node_modules-${{ runner.os }}-build-
node_modules-${{ runner.os }}-
- name: pip cache
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
if: ${{ inputs.enable-cache == 'true' }}
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-
restore-keys: |
${{ runner.os }}
- name: load "NPM TAG"
uses: ./.github/actions/set-npm-tag
${{ 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 }}
@@ -4,16 +4,22 @@ description: "Upload build artifacts"
runs:
using: "composite"
steps:
- name: tar and upload artifacts
shell: bash
env:
REMOTE_PATH: "alfresco-ng2-components/build-cache/${{ github.run_id }}"
run: |
packages=( dist nxcache node_modules )
for i in "${packages[@]}"; do
time tar czf $i.tar.gz $i
du -h $i.tar.gz
time aws s3 cp --no-progress $i.tar.gz "s3://${S3_BUILD_BUCKET_SHORT_NAME}/${REMOTE_PATH}/$i.tar.gz"
done
- name: Save dist to cache
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: dist
key: dist-${{ github.run_id }}-${{ github.run_attempt }}
- name: Save nxcache to cache
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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: node_modules
key: node-modules-${{ github.run_id }}-${{ github.run_attempt }}
+3 -3
View File
@@ -30,7 +30,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
# 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@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
uses: github/codeql-action/autobuild@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
# ️ 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@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
-75
View File
@@ -1,75 +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 }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GITHUB_BRANCH: ${{ github.ref_name }}
GH_BUILD_DIR: ${{ github.workspace }}
GH_COMMIT: ${{ github.sha }}
BUILD_ID: ${{ github.run_id }}
GH_RUN_NUMBER: ${{ github.run_attempt }}
GH_BUILD_NUMBER: ${{ github.run_id }}
JOB_ID: ${{ github.run_id }}
LOG_LEVEL: "ERROR"
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
NODE_OPTIONS: "--max-old-space-size=5120"
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
NPM_REGISTRY_ADDRESS: ${{ secrets.NPM_REGISTRY_ADDRESS }}
NPM_REGISTRY_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
REPO_OWNER: "Alfresco"
REPO_NAME: "alfresco-ng2-components"
STORYBOOK_DIR: "./dist/storybook/stories"
BUILT_LIBS_DIR: "./dist/libs"
NODE_MODULES_DIR: "./node_modules"
REDIRECT_URI: /
jobs:
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- id: set-dryrun
uses: ./.github/actions/enable-dryrun
with:
dry-run-flag: ${{ inputs.dry-run-flag }}
- name: install NPM
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
- name: "Release tag"
run: |
git fetch --all --quiet
BRANCH=${GITHUB_REF##*/} ./scripts/github/release/git-tag.sh ${{ steps.set-dryrun.outputs.dryrun }}
+2 -2
View File
@@ -84,10 +84,10 @@ jobs:
fetch-depth: 0
- name: Get branch name
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@20d21f43addae05442096a7e935dc2b321361501 # v8.27.0
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@691c1d16c90c88a92d2438a001acdefc0efa7d2a # v8.26.0
- name: Save commit message
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@20d21f43addae05442096a7e935dc2b321361501 # v8.27.0
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@691c1d16c90c88a92d2438a001acdefc0efa7d2a # v8.26.0
- name: ci:force flag parser
shell: bash
@@ -9,6 +9,11 @@ on:
required: false
type: boolean
default: true
npm-tag:
description: 'NPM tag to use for publishing'
required: false
type: string
default: 'branch'
env:
BASE_REF: ${{ github.base_ref }}
@@ -46,7 +51,7 @@ jobs:
- name: set TAG_NPM BRANCH
shell: bash
run: |
TAG_NPM="branch"
TAG_NPM=${{ inputs.npm-tag }}
echo "Set TAG with name: ${TAG_NPM}"
echo "TAG_NPM=${TAG_NPM}" >> $GITHUB_ENV
- name: Checkout repository
@@ -86,6 +91,7 @@ jobs:
dry-run-flag: ${{ inputs.dry-run-flag }}
- uses: ./.github/actions/download-node-modules-and-artifacts
- name: Set libraries versions
if: ${{ inputs.npm-tag == 'branch' }}
run: |
set -u;
./scripts/update-version.sh -gnu || exit 1;
+29 -203
View File
@@ -1,237 +1,63 @@
name: "release"
on:
workflow_call:
workflow_dispatch:
inputs:
dry-run-flag:
dry-run:
description: 'enable dry-run on artifact push'
required: false
type: boolean
default: true
pull_request:
types: [closed]
branches:
- develop
- master
- develop-patch*
- master-patch*
default: false
permissions:
id-token: write # Required for OIDC
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
env:
BASE_REF: ${{ github.base_ref }}
HEAD_REF: ${{ github.head_ref }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GITHUB_BRANCH: ${{ github.ref_name }}
GH_BUILD_DIR: ${{ github.workspace }}
GH_COMMIT: ${{ github.sha }}
BUILD_ID: ${{ github.run_id }}
GH_RUN_NUMBER: ${{ github.run_attempt }}
GH_BUILD_NUMBER: ${{ github.run_id }}
JOB_ID: ${{ github.run_id }}
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
LOG_LEVEL: "ERROR"
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
NODE_OPTIONS: "--max-old-space-size=5120"
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
REPO_OWNER: "Alfresco"
REPO_NAME: "alfresco-ng2-components"
STORYBOOK_DIR: "./dist/storybook/stories"
BUILT_LIBS_DIR: "./dist/libs"
NODE_MODULES_DIR: "./node_modules"
REDIRECT_URI: /
jobs:
setup:
timeout-minutes: 20
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
name: "Setup"
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- uses: ./.github/actions/setup
with:
enable-cache: false
enable-node-modules-cache: false
- name: install
run: |
npm ci
npx nx run js-api:bundle
npx nx run cli:bundle
- uses: ./.github/actions/upload-node-modules-and-artifacts
release-storybook:
needs: [setup]
timeout-minutes: 15
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1
- run: git fetch --all
- id: set-dryrun
uses: ./.github/actions/enable-dryrun
with:
dry-run-flag: ${{ inputs.dry-run-flag }}
- uses: ./.github/actions/setup
with:
enable-cache: false
enable-node-modules-cache: false
act: ${{ inputs.dry-run-flag }}
- uses: ./.github/actions/download-node-modules-and-artifacts
- name: release Storybook docker
run: |
npx nx run stories:build-storybook --configuration ci
. ./scripts/github/release/docker-tag.sh
./scripts/github/release/release-storybook-docker.sh ${{ steps.set-dryrun.outputs.dryrun }}
release-npm:
needs: [setup]
outputs:
release_version: ${{ steps.set-version.outputs.release_version }}
timeout-minutes: 30
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
timeout-minutes: 45
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- uses: ./.github/actions/setup
with:
enable-cache: false
enable-node-modules-cache: false
- id: set-dryrun
uses: ./.github/actions/enable-dryrun
with:
dry-run-flag: ${{ inputs.dry-run-flag }}
- uses: ./.github/actions/download-node-modules-and-artifacts
- name: Set libraries versions
id: set-version
run: |
set -u;
./scripts/github/build/bumpversion.sh
- name: Set migrations
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const setMigrations = require('./scripts/github/release/set-migrations.js');
setMigrations();
- name: build libraries
run: |
npx nx run-many -t build --prod --skip-nx-cache
npx nx run-many -t build-schematics
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
name: release libraries GH registry
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: '.nvmrc'
registry-url: 'https://npm.pkg.github.com'
scope: '@alfresco'
- run: npx nx run-many -t npm-publish --tag=$TAG_NPM || exit 1
env:
NODE_AUTH_TOKEN: ${{ secrets.PAT_WRITE_PKG }}
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
cache: 'npm'
- name: install
run: npm ci
- name: build libraries
run: |
npm run build:libs
npm run build:schematics
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
name: release libraries Npm registry
with:
node-version-file: '.nvmrc'
registry-url: 'https://${{ vars.NPM_REGISTRY_ADDRESS }}'
scope: '@alfresco'
- run: npx nx run-many -t npm-publish --tag=$TAG_NPM || exit 1
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
create-git-tag:
runs-on: ubuntu-latest
needs: [setup, release-npm]
name: Create github tag
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1
- uses: './.github/actions/create-git-tag'
with:
tagName: ${{ needs.release-npm.outputs.release_version }}
- name: upgrade npm
run: |
npm install -g npm@11
npm --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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- 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
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: ./.github/actions/npm-check-bundle
push-translation-keys-to-crowdin:
name: Push translations keys to Crowdin
if: ${{ github.ref == 'refs/heads/develop' }}
runs-on: ubuntu-latest
needs: [setup]
permissions:
contents: read
packages: read
actions: read
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Push Source Files to Crowdin
uses: crowdin/github-action@9fd07c1c5b36b15f082d1d860dc399f16f849bd7 # v2.9.0
with:
upload_sources: true
upload_sources_args: --delete-obsolete
env:
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TRANSLATIONS_TOKEN }}
finalize:
if: always()
runs-on: ubuntu-latest
name: Final Results
needs: [release-storybook, release-npm, npm-check-bundle]
steps:
- name: Check job execution status
if: >-
${{
contains(needs.*.result, 'failure')
|| contains(needs.*.result, 'cancelled')
}}
run: exit 1
- run: npx nx run-many -t npm-publish --tag=branch ${{ inputs.dry-run && '--dry-run' || '' }}
+31 -32
View File
@@ -60,38 +60,37 @@ See the [Custom layout](#custom-layout) section for full details of all availabl
### Properties
| Name | Type | Default value | Description |
|-----------------------------| ---- | ------------- |-----------------------------------------------------------------------------------------------------------------------------------------|
| allowFullScreen | `boolean` | true | Toggles the 'Full Screen' feature. |
| allowGoBack | `boolean` | true | Allows `back` navigation. |
| closeButtonPosition | `CloseButtonPosition` | `left` | Set close button position right/left. |
| hideInfoButton | `boolean` | false | Toggles Info button. |
| allowLeftSidebar | `boolean` | false | Allow the left the sidebar. |
| allowNavigate | `boolean` | false | Toggles before/next navigation. You can use the arrow buttons to navigate between documents in the collection. |
| allowRightSidebar | `boolean` | false | Allow the right sidebar. |
| blobFile | [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) | | Loads a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) File |
| canNavigateBefore | `boolean` | true | Toggles the "before" ("&lt;") button. Requires `allowNavigate` to be enabled. |
| canNavigateNext | `boolean` | true | Toggles the next (">") button. Requires `allowNavigate` to be enabled. |
| fileName | `string` | | Override Content filename. |
| title | `string` | | Override Content title. |
| mimeType | `string` | | Overload mimeType |
| overlayMode | `boolean` | false | If `true` then show the Viewer as a full page over the current content. Otherwise fit inside the parent div. |
| readOnly | `boolean` | true | Enable when where is possible the editing functionalities |
| allowedEditActions | `{ [key: string]: boolean }` | `{ rotate: true, crop: true }` | Controls which editing actions are enabled when not in read-only mode. Allows granular control over actions like rotation and cropping. |
| showLeftSidebar | `boolean` | false | Toggles left sidebar visibility. Requires `allowLeftSidebar` to be set to `true`. |
| 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`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the left sidebar. The template context contains the loaded node data. |
| sidebarLeftTemplateContext | | null | Context object available for binding by the local sidebarLeftTemplate with let declarations. |
| sidebarRightTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the right sidebar. The template context contains the loaded node data. |
| sidebarRightTemplateContext | | null | Context object available for binding by the local sidebarRightTemplate with let declarations. |
| tracks | [`Track`](../../../lib/core/src/lib/viewer/models/viewer.model.ts)`[]` | \[] | media subtitles for the media player |
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
| viewerExtensions | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | Template containing ViewerExtensionDirective instances providing different viewer extensions based on supported file extension. |
| nodeId | `string` | null | Identifier of a node opened by a viewer. |
| nodeMimeType | `string` | undefined | Original node mime type, should be provided when renditiona mime type is different. |
| customError | `string` | undefined | Custom error message to be displayed in the viewer. |
| Name | Type | Default value | Description |
| ---- | ---- | ------------- | ----------- |
| allowFullScreen | `boolean` | true | Toggles the 'Full Screen' feature. |
| allowGoBack | `boolean` | true | Allows `back` navigation. |
| closeButtonPosition | `CloseButtonPosition` | `left` | Set close button position right/left. |
| hideInfoButton | `boolean` | false | Toggles Info button. |
| allowLeftSidebar | `boolean` | false | Allow the left the sidebar. |
| allowNavigate | `boolean` | false | Toggles before/next navigation. You can use the arrow buttons to navigate between documents in the collection. |
| allowRightSidebar | `boolean` | false | Allow the right sidebar. |
| blobFile | [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) | | Loads a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) File |
| canNavigateBefore | `boolean` | true | Toggles the "before" ("&lt;") button. Requires `allowNavigate` to be enabled. |
| canNavigateNext | `boolean` | true | Toggles the next (">") button. Requires `allowNavigate` to be enabled. |
| fileName | `string` | | Override Content filename. |
| mimeType | `string` | | Overload mimeType |
| overlayMode | `boolean` | false | If `true` then show the Viewer as a full page over the current content. Otherwise fit inside the parent div. |
| readOnly | `boolean` | true | Enable when where is possible the editing functionalities |
| allowedEditActions | `{ [key: string]: boolean }` | `{ rotate: true, crop: true }` | Controls which editing actions are enabled when not in read-only mode. Allows granular control over actions like rotation and cropping. |
| showLeftSidebar | `boolean` | false | Toggles left sidebar visibility. Requires `allowLeftSidebar` to be set to `true`. |
| 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`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the left sidebar. The template context contains the loaded node data. |
| sidebarLeftTemplateContext | | null | Context object available for binding by the local sidebarLeftTemplate with let declarations. |
| sidebarRightTemplate | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | The template for the right sidebar. The template context contains the loaded node data. |
| sidebarRightTemplateContext | | null | Context object available for binding by the local sidebarRightTemplate with let declarations. |
| tracks | [`Track`](../../../lib/core/src/lib/viewer/models/viewer.model.ts)`[]` | \[] | media subtitles for the media player |
| urlFile | `string` | "" | If you want to load an external file that does not come from ACS you can use this URL to specify where to load the file from. |
| viewerExtensions | [`TemplateRef`](https://angular.io/api/core/TemplateRef)`<any>` | null | Template containing ViewerExtensionDirective instances providing different viewer extensions based on supported file extension. |
| nodeId | `string` | null | Identifier of a node opened by a viewer. |
| nodeMimeType | `string` | undefined | Original node mime type, should be provided when renditiona mime type is different. |
| customError | `string` | undefined | Custom error message to be displayed in the viewer. |
### Events
+71 -25
View File
@@ -2,10 +2,10 @@
Title: Authentication Service
Added: v2.0.0
Status: Active
Last reviewed: 2025-06-12
Last reviewed: 2019-03-19
---
# Authentication Service
# [Authentication Service](../../../lib/core/src/lib/auth/services/authentication.service.ts "Defined in authentication.service.ts")
Provides authentication to ACS and APS.
@@ -13,57 +13,103 @@ Provides authentication to ACS and APS.
### Methods
- **addTokenToHeader**(requestUrl: `string`, headersArg?: `HttpHeaders`): [`Observable`](http://reactivex.io/documentation/observable.html)`<HttpHeaders>`<br/>
- **addTokenToHeader**(headersArg?: `HttpHeaders`): [`Observable`](http://reactivex.io/documentation/observable.html)`<HttpHeaders>`<br/>
Adds the auth token to an HTTP header using the 'bearer' scheme.
- _requestUrl:_ `string` - The URL of the request for which to set authentication headers.
- _headersArg:_ `HttpHeaders` - (Optional) Header that will receive the token
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<HttpHeaders>` - The new header with the token added
- **getBearerExcludedUrls**()<br/>
Gets the set of URLs that the token bearer is excluded from.
- **getBpmLoggedUser**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`UserRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/activiti-rest-api/docs/UserRepresentation.md)`>`<br/>
Gets information about the user currently logged into APS.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`UserRepresentation`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/activiti-rest-api/docs/UserRepresentation.md)`>` - User information
- **getBpmUsername**(): `string`<br/>
Gets the BPM username
- **Returns** `string` - The BPM username
- **getEcmUsername**(): `string`<br/>
Gets the ECM username.
- **Returns** `string` - The ECM username
- **getRedirect**(): `string`<br/>
Gets the URL to redirect to after login.
- **Returns** `string` - The redirect URL
- **getTicketBpm**(): `string|null`<br/>
Gets the BPM ticket stored in the Storage.
- **Returns** `string|null` - The ticket or `null` if none was found
- **getTicketEcm**(): `string|null`<br/>
Gets the ECM ticket stored in the Storage.
- **Returns** `string|null` - The ticket or `null` if none was found
- **getTicketEcmBase64**(): `string|null`<br/>
Gets the BPM ticket from the Storage in Base 64 format.
- **Returns** `string|null` - The ticket or `null` if none was found
- **getToken**(): `string`<br/>
Gets the auth token.
- **Returns** `string` - Auth token string
- **getUsername**(): `string`<br/>
Gets the username of the authenticated user.
- **Returns** `string` - Username of the authenticated user
- **getAuthHeaders**(requestUrl: `string`, headers: `HttpHeaders`): `HttpHeaders`<br/>
Gets and sets the necessary authentication headers for a given request URL.
- _requestUrl:_ `string` - The URL of the request for which to obtain authentication headers.
- _headers:_ `HttpHeaders` - The existing HTTP headers to which authentication details might be added.
- **Returns** `HttpHeaders` - The HTTP headers object, potentially updated with authentication tokens.
- **handleError**(error: `any`): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
Prints an error message in the console browser
- _error:_ `any` - Error message
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Object representing the error message
- **isALLProvider**(): `boolean`<br/>
Does the provider support both ECM and BPM?
- **Returns** `boolean` - True if both are supported, false otherwise
- **isAuthCodeFlow**(): `boolean`<br/>
- **Returns** `boolean` -
- **isBPMProvider**(): `boolean`<br/>
Does the provider support BPM?
- **Returns** `boolean` - True if supported, false otherwise
- **isBpmLoggedIn**(): `boolean`<br/>
Checks if the user is logged in on a BPM provider.
- **Returns** `boolean` - True if logged in, false otherwise
- **isECMProvider**(): `boolean`<br/>
Does the provider support ECM?
- **Returns** `boolean` - True if supported, false otherwise
- **isEcmLoggedIn**(): `boolean`<br/>
Checks if the user is logged in on an ECM provider.
- **Returns** `boolean` - True if logged in, false otherwise
- **isImplicitFlow**(): `boolean`<br/>
- **Returns** `boolean` -
- **isKerberosEnabled**(): `boolean`<br/>
Does kerberos enabled?
- **Returns** `boolean` - True if enabled, false otherwise
- **isLoggedIn**(): `boolean`<br/>
Checks if the user logged in.
- **Returns** `boolean` - True if logged in, false otherwise
- **isLoggedInWith**(provider: `string`): `boolean`<br/>
- _provider:_ `string` -
- **Returns** `boolean` -
- **isOauth**(): `boolean`<br/>
Does the provider support OAuth?
- **Returns** `boolean` - True if supported, false otherwise
- **login**(username: `string`, password: `string`, rememberMe?: `boolean`): [`Observable`](http://reactivex.io/documentation/observable.html)`<{ type: string; ticket: any }>`<br/>
- **isPublicUrl**(): `boolean`<br/>
- **Returns** `boolean` -
- **isRememberMeSet**(): `boolean`<br/>
Checks whether the "remember me" cookie was set or not.
- **Returns** `boolean` - True if set, false otherwise
- **login**(username: `string`, password: `string`, rememberMe: `boolean` = `false`): [`Observable`](http://reactivex.io/documentation/observable.html)`<Function>`<br/>
Logs the user in.
- _username:_ `string` - Username for the login
- _password:_ `string` - Password for the login
- _rememberMe:_ `boolean` - (Optional) Stores the user's login details if true
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<{ type: string; ticket: any }>` - An Observable that emits an object containing the authentication type (`type`) and the authentication ticket (`ticket`) upon successful login.
- **logout**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> Logs the user out.
- _rememberMe:_ `boolean` - Stores the user's login details if true
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<Function>` - Object with auth type ("ECM", "BPM" or "ALL") and auth ticket
- **logout**(): [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/>
Logs the user out.
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<any>` - Response event called when logout is complete
- **reset**(): `void`<br/>Resets the authentication state of the service.
- **on**(event: `string`, listener: `Function`): `void`<br/> Adds an event listener for the specified event.
- **off**(event: `string`, listener?: `Function`): `void`<br/> Removes an event listener for the specified event.
- **once**(event: `string`, listener: `Function`): `void`<br/> Adds a one-time event listener for the specified event.
- **emit**(event: `string`, ...args: `any[]`): `void`<br/> Emits an event with optional arguments.
- **onLogin**: [`Subject`](https://reactivex.io/documentation/subject)`<any>`<br/> Emitted when the user logs in successfully.
- **onLogout**: [`Subject`](https://reactivex.io/documentation/subject)`<any>`<br/> Emitted when the user logs out.
- **onTokenReceived**: [`Subject`](https://reactivex.io/documentation/subject)`<any>`<br/> Emitted when an authentication token is received.
- **onError**: [`Observable`](http://reactivex.io/documentation/observable.html)`<any>`<br/> An Observable that emits an error object when an authentication-related error occurs.
- **reset**()<br/>
- **saveRememberMeCookie**(rememberMe: `boolean`)<br/>
Saves the "remember me" cookie as either a long-life cookie or a session cookie.
- _rememberMe:_ `boolean` - Enables a long-life cookie
- **setRedirect**(url?: [`RedirectionModel`](../../../lib/core/src/lib/auth/models/redirection.model.ts))<br/>
Sets the URL to redirect to after login.
- _url:_ [`RedirectionModel`](../../../lib/core/src/lib/auth/models/redirection.model.ts) - (Optional) URL to redirect to
- **ssoImplicitLogin**()<br/>
Logs the user in with SSO
## Details
+2
View File
@@ -56,3 +56,5 @@ The pages linked below contain the licenses for all third party dependencies of
- [ADF 7.0.0-alpha.7](license-info-7.0.0-alpha.7.md)
- [ADF 7.0.0](license-info-7.0.0.md)
- [ADF 8.0.0](license-info-8.0.0.md)
- [ADF 8.0.1](license-info-8.0.1.md)
- [ADF 8.0.2](license-info-8.0.2.md)
+49
View File
@@ -0,0 +1,49 @@
---
Title: License info, alfresco-ng2-components 8.0.1
---
# License information for alfresco-ng2-components 8.0.1
This page lists all third party libraries the project depends on.
## Libraries
| Name | Version | License |
| --- | --- | --- |
| [@angular/animations](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/cdk](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/common](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/compiler](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/core](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/forms](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/material-date-fns-adapter](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/material](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/platform-browser](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/router](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@apollo/client](https://github.com/apollographql/apollo-client) | 3.13.1 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@cspell/eslint-plugin](https://github.com/streetsidesoftware/cspell) | 8.16.1 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker) | 15.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| @ngx-translate/core | 16.0.4 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@nx/webpack](https://github.com/nrwl/nx) | 20.8.0 | [MIT](http://www.opensource.org/licenses/MIT) |
| [angular-oauth2-oidc-jwks](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| [apollo-angular](https://github.com/kamilkisiela/apollo-angular) | 10.0.3 | [MIT](http://www.opensource.org/licenses/MIT) |
| [chart.js](https://github.com/chartjs/Chart.js) | 4.4.4 | [MIT](http://www.opensource.org/licenses/MIT) |
| [cropperjs](https://github.com/fengyuanchen/cropperjs) | 1.6.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| [date-fns](https://github.com/date-fns/date-fns) | 2.30.0 | [MIT](http://www.opensource.org/licenses/MIT) |
| [dotenv-expand](https://github.com/motdotla/dotenv-expand) | 11.0.7 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
| dotenv-expand | 5.1.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
| [event-emitter](https://github.com/medikoo/event-emitter) | 0.3.5 | [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) |
| [ts-morph](https://github.com/dsherret/ts-morph) | 26.0.0 | [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) |
+50
View File
@@ -0,0 +1,50 @@
---
Title: License info, alfresco-ng2-components 8.0.2
---
# License information for alfresco-ng2-components 8.0.2
This page lists all third party libraries the project depends on.
## Libraries
| Name | Version | License |
| --- | --- | --- |
| [@angular/animations](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/cdk](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/common](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/compiler](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/core](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/forms](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/material-date-fns-adapter](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/material](https://github.com/angular/components) | 19.2.9 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/platform-browser](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@angular/router](https://github.com/angular/angular) | 19.2.6 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@apollo/client](https://github.com/apollographql/apollo-client) | 3.13.1 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@cspell/eslint-plugin](https://github.com/streetsidesoftware/cspell) | 8.16.1 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@mat-datetimepicker/core](https://github.com/kuhnroyal/mat-datetimepicker) | 15.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| @ngx-translate/core | 16.0.4 | [MIT](http://www.opensource.org/licenses/MIT) |
| [@nx/webpack](https://github.com/nrwl/nx) | 20.8.0 | [MIT](http://www.opensource.org/licenses/MIT) |
| [angular-oauth2-oidc-jwks](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) | 17.0.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| [apollo-angular](https://github.com/kamilkisiela/apollo-angular) | 10.0.3 | [MIT](http://www.opensource.org/licenses/MIT) |
| [chart.js](https://github.com/chartjs/Chart.js) | 4.4.4 | [MIT](http://www.opensource.org/licenses/MIT) |
| [cropperjs](https://github.com/fengyuanchen/cropperjs) | 1.6.2 | [MIT](http://www.opensource.org/licenses/MIT) |
| [date-fns](https://github.com/date-fns/date-fns) | 2.30.0 | [MIT](http://www.opensource.org/licenses/MIT) |
| [dotenv-expand](https://github.com/motdotla/dotenv-expand) | 11.0.7 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
| dotenv-expand | 5.1.0 | [BSD-2-Clause](http://www.opensource.org/licenses/BSD-2-Clause) |
| [event-emitter](https://github.com/medikoo/event-emitter) | 0.3.5 | [MIT](http://www.opensource.org/licenses/MIT) |
| [graphql-ws](https://github.com/enisdenjo/graphql-ws) | 6.0.5 | [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) |
| [ts-morph](https://github.com/dsherret/ts-morph) | 26.0.0 | [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) |
+2
View File
@@ -9,6 +9,8 @@ The first **General Availability** release was v2.0.0.
## General Availability
- [8.0.2](RelNote-8.0.2.md)
- [8.0.1](RelNote-8.0.1.md)
- [8.0.0](RelNote-8.0.0.md)
- [7.0.0](RelNote-7.0.0.md)
- [7.0.0-alpha.7](RelNote-7.0.0-alpha.7.md)
+8
View File
@@ -0,0 +1,8 @@
---
Title: Changelog for alfresco-ng2-components v8.0.1
---
# Changelog
[4c4dd195a45cdb8cd0218a68972b7a77242359ed](https://github.com/Alfresco/alfresco-ng2-components/commit/4c4dd195a45cdb8cd0218a68972b7a77242359ed)Remove unused webdriver-manager dependency to eliminate vulnerable form-data ~2.3.2 (#11060)
[5e6e2b59495662c103b527e4cae5b019f5136f91](https://github.com/Alfresco/alfresco-ng2-components/commit/5e6e2b59495662c103b527e4cae5b019f5136f91) Bumps [form-data](https://github.com/form-data/form-data) from 3.0.1 to 3.0.4.
[31bff2806b0db10d260855c61034db7d4b48d6e5](https://github.com/Alfresco/alfresco-ng2-components/commit/31bff2806b0db10d260855c61034db7d4b48d6e5) Bumps [form-data](https://github.com/form-data/form-data) from 4.0.0 to 4.0.4.
+6
View File
@@ -0,0 +1,6 @@
---
Title: Changelog for alfresco-ng2-components v8.0.2
---
# Changelog
- [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)
-164
View File
@@ -1,164 +0,0 @@
---
Title: Upgrading from ADF v7.0 to v8.0
---
# Upgrading from ADF v7.0 to v8.0
This guide provides instructions for upgrading your v7.0.0 ADF projects to v8.0.0.
## Before you begin
Always perform upgrades on a "clean" project state. Back up your changes or create a full project backup before proceeding.
```shell
# Recommended clean up
nx reset && rm -rf .angular .nx dist node_modules nxcache tmp
```
## Libraries
Update your dependencies to the versions introduced in the 8.0.0 release:
```json
{
"dependencies": {
"@alfresco/adf-core": "8.0.0",
"@alfresco/adf-content-services": "8.0.0",
"@alfresco/adf-process-services-cloud": "8.0.0",
"@alfresco/adf-insights": "8.0.0",
"@alfresco/adf-extensions": "8.0.0",
"@alfresco/adf-cli": "8.0.0",
"@alfresco/eslint-plugin-eslint-angular": "8.0.0",
"@alfresco/adf-testing": "8.0.0",
"@alfresco/js-api": "9.0.0"
}
}
```
Currently used Node version: 22.14.0.
### Breaking changes
Major version updates have been applied to the following core libraries:
- Angular: 19.2.6
- Angular Material: 19.2.9
- Typescript: 5.8.2
> Details on Angular update can be found in *Update Guide* from Angular documentation.
### Added libraries
```json
{
"dependencies": {
"node-fetch": "^3.3.2"
},
"devDependencies": {
"resize-observer-polyfill": "^1.5.1",
"webdriver-manager": "12.1.9"
}
}
```
### Deleted libraries
```json
{
"devDependencies": {
"mini-css-extract-plugin": "X.X.X",
"css-loader": "X.X.X"
}
}
```
Reinstall your dependencies and perform an initial build:
```shell
npm i
npm run build
```
Review your applications as some styles and classes of Angular Material components might have changed.
## Deprecations
The following table lists deprecated features and modules that will be removed in upcoming releases. Consider replacing them as soon as you update ADF to minimize future technical debt.
| Name | Notes |
|-------------------------------|-----------------------------------------------------------------------------------------------|
| Custom Theme | Refer to [Custom Theme documentation](../../lib/core/custom-theme/README.md) |
| ShellModule | Refer to [Shell documentation](../../lib/core/shell/README.md) |
| FormBaseModule | Use standalone components instead. |
| CoreTestingModule | Use standalone components instead. |
| ProcessServicesCloudModule | Refer to [ProcessServicesCloudModule replacement](#processservicescloudmodule-replacement) |
### ProcessServicesCloudModule replacement
To replace this module, import the standalone components directly or use the following provider API to replicate its behavior:
```typescript
providers: [
provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud'),
provideCloudPreferences(),
provideCloudFormRenderer(),
{ provide: TASK_LIST_CLOUD_TOKEN, useClass: TaskListCloudService }
]
```
## New features and APIs
You can start using the new features and APIs introduced in the 8.0.0 release.
### XMLHttpRequest.withCredentials
Support for disabling the `withCredentials` property in `app.config.json` for identity providers that disallow credentials has been introduced. You can configure it as shown below:
```json
{
"auth": {
"withCredentials": false
}
}
```
### provideShell
The new provideShell API for providing the main application layout can replace the `withRoutes(routes: Routes | AppShellRoutesConfig)` method, as shown below.
```typescript
import { provideShell } from '@alfresco/adf-core/shell';
provideShell(
{
routes: [],
appService: AppService,
authGuard: AuthGuard,
navBar: {
minWidth: 0,
maxWidth: 100
}
}
)
```
### provideI18N
The new `provideI18N` API for providing translation can replace `provideTranslations('app', 'assets')` method, as shown below.
```typescript
import { provideI18N } from '@alfresco/adf-core';
provideI18N(
{
defaultLanguage: "en", // optional, defaults to "en"
assets: [['en', '/assets/i18n/en.json'], ['fr', '/assets/i18n/fr.json']]
}
)
```
## Final steps
After updating your code, thoroughly test your application to ensure everything works as expected.
If you encounter any issues during the upgrade process, refer to the Angular update guide or seek assistance from the ADF community.
+2
View File
@@ -53,3 +53,5 @@ The pages linked below contain the audit for all third party dependencies of ADF
- [ADF 7.0.0-alpha.7](audit-info-7.0.0-alpha.7.md)
- [ADF 7.0.0](audit-info-7.0.0.md)
- [ADF 8.0.0](audit-info-8.0.0.md)
- [ADF 8.0.1](audit-info-8.0.1.md)
- [ADF 8.0.2](audit-info-8.0.2.md)
+23
View File
@@ -0,0 +1,23 @@
---
Title: Audit info, alfresco-ng2-components 8.0.0
---
# Audit information for alfresco-ng2-components 8.0.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 |
| --- | --- | --- |
+53
View File
@@ -0,0 +1,53 @@
---
Title: Audit info, alfresco-ng2-components 8.0.2
---
# Audit information for alfresco-ng2-components 8.0.2
This page lists the security audit of the dependencies this project depends on.
## Risks
- Critical risk: 1
- High risk: 21
- Moderate risk: 4
- Low risk: 4
Dependencies analyzed:
## Libraries
| Severity | Module | Vulnerable versions |
| --- | --- | --- |
|high | @angular/animations | &#34;19.0.0-next.0 - 19.2.17&#34; |
|high | @angular/common | &#34;&lt;=19.2.17&#34; |
|high | @angular/compiler | &#34;19.0.0-next.0 - 19.2.17&#34; |
|high | @angular/core | &#34;19.0.0-next.0 - 19.2.17&#34; |
|high | @angular/forms | &#34;&lt;=19.2.17&#34; |
|high | @angular/platform-browser | &#34;&lt;=19.2.17&#34; |
|high | @angular/platform-browser-dynamic | &#34;&lt;=19.2.17&#34; |
|high | @angular/router | &#34;&lt;=0.0.0-ROUTERPLACEHOLDER || 2.0.0-rc.0 - 19.2.17&#34; |
|high | @isaacs/brace-expansion | &#34;5.0.0&#34; |
|high | @nx/devkit | &#34;&lt;=0.0.0-pr-34253-d811c6c || 18.4.0-canary.20240417-801a22b - 22.4.0-canary.20260121-1b12e1f&#34; |
|high | @nx/js | &#34;&lt;=0.0.0-pr-34253-d811c6c || 17.0.4 - 17.0.5 || 17.3.0-beta.1 - 22.4.0-canary.20260121-1b12e1f&#34; |
|high | @nx/webpack | &#34;&lt;=0.0.0-pr-34082-9d57132 || 18.4.0-canary.20240417-801a22b - 22.4.0-canary.20260121-1b12e1f&#34; |
|high | @nx/workspace | &#34;&lt;=0.0.0-pr-34253-d811c6c || 17.0.4 - 17.0.5 || 17.3.0-beta.1 - 22.4.0-canary.20260121-1b12e1f&#34; |
|moderate | ajv | &#34;&lt;6.14.0 || &gt;=7.0.0-alpha.0 &lt;8.18.0&#34; |
|high | axios | &#34;1.0.0 - 1.13.4&#34; |
|high | body-parser | &#34;&lt;=1.20.3 || 2.0.0-beta.1 - 2.0.2&#34; |
|low | compression | &#34;1.0.3 - 1.8.0&#34; |
|high | express | &#34;2.5.8 - 2.5.11 || 3.2.1 - 3.2.3 || 4.0.0-rc1 - 4.21.2 || 5.0.0-alpha.1 - 5.0.1&#34; |
|critical | form-data | &#34;4.0.0 - 4.0.3&#34; |
|high | glob | &#34;10.2.0 - 10.4.5&#34; |
|moderate | js-yaml | &#34;&lt;3.14.2 || &gt;=4.0.0 &lt;4.1.1&#34; |
|moderate | lodash | &#34;4.0.0 - 4.17.21&#34; |
|moderate | lodash-es | &#34;4.0.0 - 4.17.22&#34; |
|high | minimatch | &#34;&lt;=3.1.2 || 5.0.0 - 5.1.6 || 9.0.0 - 9.0.5 || 10.0.0 - 10.2.0&#34; |
|high | node-forge | &#34;&lt;=1.3.1&#34; |
|high | nx | &#34;&lt;=0.0.0-pr-34253-d811c6c || 17.0.4 - 17.0.5 || 17.3.0-beta.1 - 22.4.0-canary.20260121-1b12e1f&#34; |
|low | on-headers | &#34;&lt;1.1.0&#34; |
|high | qs | &#34;&lt;=6.14.1&#34; |
|low | tmp | &#34;&lt;=0.2.3&#34; |
|low | webpack | &#34;5.49.0 - 5.104.0&#34; |
+19 -13
View File
@@ -1,20 +1,20 @@
{
"name": "@alfresco/adf-cli",
"version": "9.0.0",
"version": "8.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@alfresco/adf-cli",
"version": "9.0.0",
"version": "8.0.2",
"license": "Apache-2.0",
"dependencies": {
"@alfresco/js-api": ">=9.0.0",
"@alfresco/js-api": ">=8.0.0-alpha.7",
"commander": "^6.2.1",
"ejs": "^3.1.9",
"license-checker": "^25.0.1",
"node-fetch": "^2.7.0",
"rxjs": "7.8.2",
"rxjs": "^6.6.6",
"shelljs": "^0.8.3",
"spdx-license-list": "^5.0.0"
},
@@ -30,10 +30,9 @@
}
},
"node_modules/@alfresco/js-api": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-9.0.0.tgz",
"integrity": "sha512-tkVc3vCmbyp1cAJOtga/c5kApWmkj7lBmnJk0M+Jx/aek5mUQkXvDKlpPBoE0QR8UHKEKgB6HgwmaOMumYQVAw==",
"license": "Apache-2.0",
"version": "8.0.0-alpha.7-12984503308",
"resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-8.0.0-alpha.7-12984503308.tgz",
"integrity": "sha512-ua8YgR6BHO751wKclLCQeJEByLJbLl5xmfQqEDJyRlnMvDCk+v7a5e2ibF58meQkmstR+CkIXi5ZlW9YhBKtZg==",
"dependencies": {
"event-emitter": "^0.3.5",
"superagent": "^9.0.1",
@@ -1142,14 +1141,21 @@
}
},
"node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"license": "Apache-2.0",
"version": "6.6.7",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
"dependencies": {
"tslib": "^2.1.0"
"tslib": "^1.9.0"
},
"engines": {
"npm": ">=2.0.0"
}
},
"node_modules/rxjs/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@alfresco/adf-cli",
"description": "Alfresco ADF cli and utils",
"version": "9.0.0",
"version": "8.0.3",
"author": "Hyland Software, Inc. and its affiliates",
"bin": {
"adf-cli": "bin/adf-cli",
@@ -20,7 +20,7 @@
"dist": "rm -rf ../../dist/libs/cli && npm run build && cp -R ./bin ../../dist/libs/cli && cp -R ./resources ../../dist/libs/cli && cp -R ./templates ../../dist/libs/cli && cp ./package.json ../../dist/libs/cli"
},
"dependencies": {
"@alfresco/js-api": ">=9.0.0",
"@alfresco/js-api": ">=9.0.2",
"commander": "^6.2.1",
"ejs": "^3.1.9",
"license-checker": "^25.0.1",
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@alfresco/adf-content-services",
"description": "Alfresco ADF content services",
"version": "9.0.0",
"version": "8.0.3",
"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": ">=10.0.0",
"@alfresco/js-api": ">=9.0.2",
"@ngx-translate/core": ">=16.0.0",
"@alfresco/adf-core": ">=9.0.0"
"@alfresco/adf-core": ">=8.0.2"
},
"keywords": [
"content-services",
@@ -156,7 +156,7 @@ describe('ContentService', () => {
});
it('should take current logged user id if userId undefined ', () => {
spyOn(authService, 'getUsername').and.returnValue('user1');
spyOn(authService, 'getEcmUsername').and.returnValue('user1');
const permissionNode = new Node({
permissions: {
inherited: [
@@ -84,7 +84,7 @@ export class ContentService {
*/
hasPermissions(node: Node, permission: PermissionsEnum | string, userId?: string): boolean {
let hasPermissions = false;
userId = userId ?? this.authService.getUsername();
userId = userId ?? this.authService.getEcmUsername();
const permissions = [...(node.permissions?.locallySet || []), ...(node.permissions?.inherited || [])].filter(
(currentPermission) => currentPermission.authorityId === userId
@@ -17,12 +17,13 @@
import { EventEmitter } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core';
import { AppConfigModule, AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core';
import { UploadService } from './upload.service';
import { RepositoryInfo } from '@alfresco/js-api';
import { BehaviorSubject } from 'rxjs';
import { DiscoveryApiService } from '../../common/services/discovery-api.service';
import { FileModel, FileUploadStatus } from '../../common/models/file.model';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AlfrescoApiService } from '../../services';
import { AlfrescoApiServiceMock } from '../../mock';
@@ -37,7 +38,7 @@ describe('UploadService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
imports: [AppConfigModule, HttpClientTestingModule],
providers: [
UploadService,
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
@@ -274,7 +274,7 @@ describe('DropdownSitesComponent', () => {
});
it('should show only sites which logged user is member of when member relation is set', async () => {
spyOn(authService, 'getUsername').and.returnValue('test');
spyOn(authService, 'getEcmUsername').and.returnValue('test');
fixture.detectChanges();
await fixture.whenStable();
@@ -295,7 +295,7 @@ describe('DropdownSitesComponent', () => {
});
it('should show all the sites if no relation is set', async () => {
spyOn(authService, 'getUsername').and.returnValue('test');
spyOn(authService, 'getEcmUsername').and.returnValue('test');
fixture.detectChanges();
await fixture.whenStable();
@@ -181,7 +181,7 @@ export class DropdownSitesComponent implements OnInit {
}
private filteredResultsByMember(sites: SitePaging): SitePaging {
const loggedUserName = this.authService.getUsername();
const loggedUserName = this.authService.getEcmUsername();
sites.list.entries = sites.list.entries.filter((site) => this.isCurrentUserMember(site, loggedUserName));
return sites;
}
@@ -646,7 +646,7 @@ describe('DocumentList', () => {
title: 'FileAction'
});
spyOn(authenticationService, 'getUsername').and.returnValue('lockOwner');
spyOn(authenticationService, 'getEcmUsername').and.returnValue('lockOwner');
documentList.actions = [documentMenu];
@@ -677,7 +677,7 @@ describe('DocumentList', () => {
title: 'FileAction'
});
spyOn(authenticationService, 'getUsername').and.returnValue('jerryTheKillerCow');
spyOn(authenticationService, 'getEcmUsername').and.returnValue('jerryTheKillerCow');
documentList.actions = [documentMenu];
@@ -137,22 +137,22 @@ describe('LockService', () => {
} as Node;
it('should return false when the user is the lock owner', () => {
spyOn(authenticationService, 'getUsername').and.returnValue('lock-owner-user');
spyOn(authenticationService, 'getEcmUsername').and.returnValue('lock-owner-user');
expect(service.isLocked(nodeOwnerAllowedLock)).toBeFalsy();
});
it('should return true when the user is not the lock owner', () => {
spyOn(authenticationService, 'getUsername').and.returnValue('banana-user');
spyOn(authenticationService, 'getEcmUsername').and.returnValue('banana-user');
expect(service.isLocked(nodeOwnerAllowedLock)).toBeTruthy();
});
it('should return false when the user is not the lock owner but the lock is expired', () => {
spyOn(authenticationService, 'getUsername').and.returnValue('banana-user');
spyOn(authenticationService, 'getEcmUsername').and.returnValue('banana-user');
expect(service.isLocked(nodeOwnerAllowedLockWithExpiredDate)).toBeFalsy();
});
it('should return true when is not the lock owner and the expiration date is valid', () => {
spyOn(authenticationService, 'getUsername').and.returnValue('banana-user');
spyOn(authenticationService, 'getEcmUsername').and.returnValue('banana-user');
expect(service.isLocked(nodeOwnerAllowedLockWithActiveExpiration)).toBeTruthy();
});
});
@@ -32,7 +32,7 @@ export class LockService {
if (this.isReadOnlyLock(node)) {
isLocked = !this.isLockExpired(node);
} else if (this.isLockOwnerAllowed(node)) {
isLocked = this.authService.getUsername() !== node.properties['cm:lockOwner'].id;
isLocked = this.authService.getEcmUsername() !== node.properties['cm:lockOwner'].id;
if (this.isLockExpired(node)) {
isLocked = false;
}
+2 -2
View File
@@ -184,8 +184,8 @@
"DUPLICATED_CATEGORY": "Kategoria została już dodana",
"CREATE_CATEGORIES": "Błąd podczas tworzenia kategorii",
"EXISTING_CATEGORIES": "Niektóre kategorie już istnieją",
"SPECIAL_CHARACTERS": "Nazwa kategorii nie może zawierać niedozwolonych znaków",
"ENDS_WITH_DOT": "Nazwa kategorii nie może kończyć się kropką"
"SPECIAL_CHARACTERS": "Category name cannot contain prohibited characters",
"ENDS_WITH_DOT": "Category name cannot end with a dot"
},
"CATEGORIES_SEARCH_PLACEHOLDER": "Kategorie wyszukiwania"
},
@@ -2,6 +2,7 @@
<mat-checkbox
*ngFor="let option of options"
[checked]="option.checked"
labelPosition="before"
(keydown.enter)="option.checked = !option.checked"
[attr.data-automation-id]="'checkbox-' + (option.name)"
[attr.aria-label]="option.name | translate"
@@ -25,14 +25,11 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { ReplaySubject } from 'rxjs';
import { UnitTestingUtils } from '@alfresco/adf-core';
import { MatCheckbox } from '@angular/material/checkbox';
describe('SearchCheckListComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<SearchCheckListComponent>;
let component: SearchCheckListComponent;
let unitTestingUtils: UnitTestingUtils;
beforeEach(() => {
TestBed.configureTestingModule({
@@ -41,7 +38,6 @@ describe('SearchCheckListComponent', () => {
fixture = TestBed.createComponent(SearchCheckListComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
unitTestingUtils = new UnitTestingUtils(fixture.debugElement);
component.context = {
queryFragments: {},
@@ -142,18 +138,6 @@ describe('SearchCheckListComponent', () => {
expect(component.context.filterRawParams[component.id]).toBeUndefined();
});
it('should have set labelPosition to after for checkboxes', () => {
component.options = new SearchFilterList<SearchListOption>([
{ name: 'Folder', value: `TYPE:'cm:folder'`, checked: true },
{ name: 'Document', value: `TYPE:'cm:content'`, checked: true }
]);
fixture.detectChanges();
const checkboxes = unitTestingUtils.getAllByDirective(MatCheckbox);
expect(checkboxes.length).toBe(2);
expect(checkboxes.every((checkbox) => checkbox.componentInstance.labelPosition === 'after')).toBeTrue();
});
describe('Pagination', () => {
it('should show 5 items when pageSize not defined', async () => {
component.id = 'checklist';
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@alfresco/adf-core",
"description": "Alfresco ADF core",
"version": "9.0.0",
"version": "8.0.3",
"author": "Hyland Software, Inc. and its affiliates",
"repository": {
"type": "git",
@@ -38,8 +38,8 @@
"@angular/router": ">=16.0.0",
"@mat-datetimepicker/core": ">=12.0.1",
"@ngx-translate/core": ">=16.0.0",
"@alfresco/js-api": ">=10.0.0",
"@alfresco/adf-extensions": ">=9.0.0",
"@alfresco/js-api": ">=9.0.2",
"@alfresco/adf-extensions": ">=8.0.2",
"minimatch": ">=10.0.0",
"pdfjs-dist": ">=3.3.122",
"ts-morph": ">=20.0.0"
@@ -15,18 +15,12 @@
* limitations under the License.
*/
import { InjectionToken, Provider, Type } from '@angular/core';
import { NgModule } from '@angular/core';
import { AppConfigPipe } from './app-config.pipe';
export const LANDING_PAGE_TOKEN = new InjectionToken<Type<any>>('LANDING_PAGE_TOKEN');
/**
*
* @param componentClass The component class to be registered as the landing page.
* @returns A provider that registers the landing page component class.
*/
export function provideLandingPage(componentClass: Type<any>): Provider {
return {
provide: LANDING_PAGE_TOKEN,
useValue: componentClass
};
}
/** @deprecated This module is deprecated, consider importing AppConfigPipe directly */
@NgModule({
imports: [AppConfigPipe],
exports: [AppConfigPipe]
})
export class AppConfigModule {}
@@ -20,4 +20,5 @@ export * from './debug-app-config.service';
export * from './app-config.pipe';
export * from './app-config-storage-prefix.factory';
export * from './app-config.module';
export * from './provide-app-config';
@@ -317,27 +317,14 @@ export class BasicAlfrescoAuthService extends BaseAuthenticationService {
return this.redirectUrl && (this.redirectUrl.provider === 'ALL' || provider === 'ALL');
}
/**
* @deprecated use `getUsername()` instead
* @returns the username of the authenticated user
*/
getBpmUsername(): string {
return this.processAuth.getUsername();
}
/**
* @deprecated use `getUsername()` instead
* @returns the username of the authenticated user
*/
getEcmUsername(): string {
return this.contentAuth.getUsername();
}
/**
* Gets the username of the authenticated user.
*
* @returns the username of the authenticated user
*/
getUsername(): string {
if (this.isBPMProvider()) {
return this.processAuth.getUsername();
@@ -94,7 +94,7 @@ describe('AuthGuardService BPM', () => {
});
it('if the alfresco js api is logged in should canActivate be true', async () => {
spyOn(authService, 'isLoggedIn').and.returnValue(true);
spyOn(authService, 'isBpmLoggedIn').and.returnValue(true);
authGuard = TestBed.runInInjectionContext(() => AuthGuardBpm(route, state)) as Promise<boolean>;
expect(await authGuard).toBeTruthy();
@@ -28,7 +28,7 @@ export const AuthGuardBpm: CanActivateFn = async (_: ActivatedRouteSnapshot, sta
return authGuardBaseService.redirectSSOSuccessURL();
}
if (authenticationService.isLoggedIn() || authGuardBaseService.withCredentials) {
if (authenticationService.isBpmLoggedIn() || authGuardBaseService.withCredentials) {
return true;
}
@@ -20,6 +20,7 @@ import ee from 'event-emitter';
import { Observable } from 'rxjs';
export interface AuthenticationServiceInterface {
onError: any;
onLogin: any;
onLogout: any;
@@ -30,26 +31,30 @@ export interface AuthenticationServiceInterface {
emit: (type: string, ...args: any[]) => void;
getToken(): string;
isLoggedIn(): boolean;
isOauth(): boolean;
logout(): any;
isECMProvider(): boolean;
isBPMProvider(): boolean;
isALLProvider(): boolean;
getUsername(): string;
getAuthHeaders(requestUrl: string, header: HttpHeaders): HttpHeaders;
addTokenToHeader(requestUrl: string, headersArg?: HttpHeaders): Observable<HttpHeaders>;
reset(): void;
/** @deprecated use `isLoggedIn` instead, use `isECMProvider` if you need to know the auth type */
isEcmLoggedIn(): boolean;
/** @deprecated use `isLoggedIn` instead, use `isBPMProvider` if you need to know the auth type */
isBpmLoggedIn(): boolean;
/** @deprecated use `getUsername` instead */
isECMProvider(): boolean;
isBPMProvider(): boolean;
isALLProvider(): boolean;
getEcmUsername(): string;
/** @deprecated use `getUsername` instead */
getBpmUsername(): string;
getAuthHeaders(requestUrl: string, header: HttpHeaders): HttpHeaders;
addTokenToHeader(requestUrl: string, headersArg?: HttpHeaders): Observable<HttpHeaders>;
reset(): void;
}
@@ -56,10 +56,6 @@ export class OidcAuthenticationService extends BaseAuthenticationService {
map(([authenticated, isDiscoveryDocumentLoaded]) => !authenticated && isDiscoveryDocumentLoaded)
);
/**
* @deprecated use `isLoggedIn` instead
* @returns true if the ECM provider is logged in
*/
isEcmLoggedIn(): boolean {
if (this.isECMProvider() || this.isALLProvider()) {
return this.isLoggedIn();
@@ -67,10 +63,6 @@ export class OidcAuthenticationService extends BaseAuthenticationService {
return false;
}
/**
* @deprecated use `isLoggedIn` instead
* @returns true if the BPM provider is logged in
*/
isBpmLoggedIn(): boolean {
if (this.isBPMProvider() || this.isALLProvider()) {
return this.isLoggedIn();
@@ -90,6 +82,16 @@ export class OidcAuthenticationService extends BaseAuthenticationService {
return this.oauthService.hasValidIdToken();
}
isImplicitFlow() {
const oauth2: OauthConfigModel = Object.assign({}, this.appConfig.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null));
return !!oauth2?.implicitFlow;
}
isAuthCodeFlow() {
const oauth2: OauthConfigModel = Object.assign({}, this.appConfig.get<OauthConfigModel>(AppConfigValues.OAUTHCONFIG, null));
return !!oauth2?.codeFlow;
}
login(username: string, password: string): Observable<{ type: string; ticket: any }> {
return this.auth.baseAuthLogin(username, password).pipe(
map((response) => {
@@ -123,17 +125,12 @@ export class OidcAuthenticationService extends BaseAuthenticationService {
});
}
/**
* Gets the username of the authenticated user.
*
* @returns the logged username
*/
getUsername() {
return this.jwtHelperService.getValueFromLocalToken<string>(JwtHelperService.USER_PREFERRED_USERNAME);
}
/**
* @deprecated use `getUsername` instead
* @deprecated
* @returns the logged username
*/
getEcmUsername(): string {
@@ -141,7 +138,7 @@ export class OidcAuthenticationService extends BaseAuthenticationService {
}
/**
* @deprecated use `getUsername` instead
* @deprecated
* @returns the logged username
*/
getBpmUsername(): string {
@@ -152,6 +149,10 @@ export class OidcAuthenticationService extends BaseAuthenticationService {
this.auth.login(redirectUrl);
}
ssoCodeFlowLogin() {
this.oauthService.initCodeFlow();
}
isRememberMeSet(): boolean {
return true;
}
@@ -116,25 +116,17 @@ export class AuthenticationService implements AuthenticationServiceInterface, ee
}
}
/**
* @deprecated use `isLoggedIn` instead
* @returns true if the ECM provider is logged in
*/
isEcmLoggedIn(): boolean {
if (this.isOauth()) {
return this.oidcAuthenticationService.isLoggedIn();
return this.oidcAuthenticationService.isEcmLoggedIn();
} else {
return this.basicAlfrescoAuthService.isEcmLoggedIn();
}
}
/**
* @deprecated use `isLoggedIn` instead
* @returns true if the BPM provider is logged in
*/
isBpmLoggedIn(): boolean {
if (this.isOauth()) {
return this.oidcAuthenticationService.isLoggedIn();
return this.oidcAuthenticationService.isBpmLoggedIn();
} else {
return this.basicAlfrescoAuthService.isBpmLoggedIn();
}
@@ -157,8 +149,6 @@ export class AuthenticationService implements AuthenticationServiceInterface, ee
}
/**
* Gets the username of the authenticated user.
*
* @returns the username of the authenticated user
*/
getUsername(): string {
@@ -170,19 +160,27 @@ export class AuthenticationService implements AuthenticationServiceInterface, ee
}
/**
* @deprecated use `getUsername` instead
* @deprecated
* @returns the logged username
*/
getEcmUsername(): string {
return this.getUsername();
if (this.isOauth()) {
return this.oidcAuthenticationService.getUsername();
} else {
return this.basicAlfrescoAuthService.getEcmUsername();
}
}
/**
* @deprecated use `getUsername` instead
* @deprecated
* @returns the logged username
*/
getBpmUsername(): string {
return this.getUsername();
if (this.isOauth()) {
return this.oidcAuthenticationService.getUsername();
} else {
return this.basicAlfrescoAuthService.getBpmUsername();
}
}
getAuthHeaders(requestUrl: string, headers: HttpHeaders): HttpHeaders {
@@ -40,23 +40,21 @@ export abstract class BaseAuthenticationService implements AuthenticationService
}
abstract getAuthHeaders(requestUrl: string, header: HttpHeaders): HttpHeaders;
abstract getToken(): string;
abstract isLoggedIn(): boolean;
abstract logout(): any;
/** @deprecated use `isLoggedIn` instead */
abstract isEcmLoggedIn(): boolean;
/** @deprecated use `isLoggedIn` instead */
abstract isBpmLoggedIn(): boolean;
abstract reset(): void;
abstract getUsername(): string;
/** @deprecated use `getUsername` instead */
abstract getEcmUsername(): string;
/** @deprecated use `getUsername` instead */
abstract getBpmUsername(): string;
/**
@@ -112,6 +110,11 @@ export abstract class BaseAuthenticationService implements AuthenticationService
return provider && provider.toUpperCase() === 'ALL';
}
isOauthConfiguration(): boolean {
const authType = this.appConfig.get('authType') as string;
return authType === 'OAUTH';
}
/**
* Prints an error message in the console browser
*
@@ -27,28 +27,12 @@ import { isOutcomeButtonVisible } from './helpers/buttons-visibility';
export abstract class FormBaseComponent {
protected _form: FormModel;
/**
* @deprecated Use {@link FormModel.SAVE_OUTCOME} instead.
*/
static readonly SAVE_OUTCOME_ID: string = FormModel.SAVE_OUTCOME;
/**
* @deprecated Use {@link FormModel.COMPLETE_OUTCOME} instead.
*/
static readonly COMPLETE_OUTCOME_ID: string = FormModel.COMPLETE_OUTCOME;
/**
* @deprecated Use {@link FormModel.START_PROCESS_OUTCOME} instead.
*/
static readonly START_PROCESS_OUTCOME_ID: string = FormModel.START_PROCESS_OUTCOME;
static readonly CUSTOM_OUTCOME_ID: string = '$custom';
static readonly COMPLETE_BUTTON_COLOR: ThemePalette = 'primary';
/**
* @deprecated Use {@link FormOutcomeModel.COMPLETE_ACTION} instead.
*/
static readonly COMPLETE_OUTCOME_NAME: string = FormOutcomeModel.COMPLETE_ACTION;
static SAVE_OUTCOME_ID: string = '$save';
static COMPLETE_OUTCOME_ID: string = '$complete';
static START_PROCESS_OUTCOME_ID: string = '$startProcess';
static CUSTOM_OUTCOME_ID: string = '$custom';
static COMPLETE_BUTTON_COLOR: ThemePalette = 'primary';
static COMPLETE_OUTCOME_NAME: string = 'COMPLETE';
/** Path of the folder where the metadata will be stored. */
@Input()
@@ -66,7 +50,7 @@ export abstract class FormBaseComponent {
@Input()
showCompleteButton: boolean = true;
/** If true then the `Complete` outcome button is shown, but it will be disabled. */
/** If true then the `Complete` outcome button is shown but it will be disabled. */
@Input()
disableCompleteButton: boolean = false;
@@ -154,7 +138,7 @@ export abstract class FormBaseComponent {
}
getColorForOutcome(outcomeName: string): ThemePalette {
return outcomeName === FormOutcomeModel.COMPLETE_ACTION ? FormBaseComponent.COMPLETE_BUTTON_COLOR : null;
return outcomeName === FormBaseComponent.COMPLETE_OUTCOME_NAME ? FormBaseComponent.COMPLETE_BUTTON_COLOR : null;
}
isOutcomeButtonEnabled(outcome?: FormOutcomeModel): boolean {
@@ -198,20 +182,20 @@ export abstract class FormBaseComponent {
}
if (outcome.isSystem) {
if (outcome.id === FormModel.SAVE_OUTCOME) {
if (outcome.id === FormBaseComponent.SAVE_OUTCOME_ID) {
this.disableSaveButton = true;
this.saveTaskForm();
return true;
}
if (outcome.id === FormModel.COMPLETE_OUTCOME) {
if (outcome.id === FormBaseComponent.COMPLETE_OUTCOME_ID) {
this.disableSaveButton = true;
this.disableCompleteButton = true;
this.completeTaskForm();
return true;
}
if (outcome.id === FormModel.START_PROCESS_OUTCOME) {
if (outcome.id === FormBaseComponent.START_PROCESS_OUTCOME_ID) {
this.completeTaskForm();
return true;
}
@@ -21,10 +21,6 @@
<ng-template #render let-fieldToRender="fieldToRender">
<div *ngFor="let currentRootElement of fieldToRender">
<div *ngIf="currentRootElement.type === 'section'" [id]="'field-' + currentRootElement?.id + '-container'" class="adf-container-widget">
<adf-form-section [field]="currentRootElement" />
</div>
<div *ngIf="currentRootElement.type === 'container' || currentRootElement.type === 'group'"
[id]="'field-' + currentRootElement?.id + '-container'"
class="adf-container-widget"
@@ -26,9 +26,9 @@
#{ms.$mat-tab-body} {
margin-bottom: 8em;
@include flex.layout-bp(lt-md) {
margin-bottom: 0;
margin-bottom: 0em;
}
}
@@ -66,22 +66,20 @@
display: flex;
margin-right: -1%;
width: 100%;
gap: 8px;
&-item {
width: 100%;
flex-grow: 1;
box-sizing: border-box;
}
.adf-radio-buttons-widget {
padding-left: 12px;
}
}
&-single-column {
display: flex;
flex-direction: column;
flex: 1 1 auto;
padding-right: 1%;
padding-left: 1%;
}
&-item {
@@ -1,31 +1,10 @@
@use '../../../../../src/lib/styles/flex' as flex;
.adf-grid-list {
&-section {
&-single-column {
display: flex;
flex-wrap: inherit;
align-items: baseline;
flex-direction: column;
gap: 1%;
@include flex.layout-bp(lt-md) {
flex: 1 1 100% !important;
flex-direction: column;
}
.adf-section-widget {
@include flex.layout-bp(lt-md) {
width: 100% !important;
}
}
> div {
@include flex.layout-bp(lt-md) {
width: 100% !important;
}
}
}
&-column-view-item {
@@ -16,11 +16,10 @@
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UnitTestingUtils, NoopTranslateModule } from '../../../testing';
import { UnitTestingUtils } from '../../../testing';
import { FormFieldModel, FormModel } from '../widgets';
import { FormSectionComponent } from './form-section.component';
import { mockSectionWithFields } from '../mock/form-renderer.component.mock';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
describe('FormSectionComponent', () => {
let fixture: ComponentFixture<FormSectionComponent>;
@@ -29,7 +28,7 @@ describe('FormSectionComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormSectionComponent, NoopTranslateModule, NoopAnimationsModule]
imports: [FormSectionComponent]
});
fixture = TestBed.createComponent(FormSectionComponent);
testingUtils = new UnitTestingUtils(fixture.debugElement);
@@ -60,87 +59,4 @@ describe('FormSectionComponent', () => {
const sectionFields = testingUtils.getAllByCSS('.adf-grid-list-section-column-view-item adf-form-field');
expect(sectionFields.length).toBe(2);
});
describe('getSectionColumnWidth', () => {
it('should cap width at 100% when numberOfColumns is not a number', () => {
const columnField = { colspan: 2 } as FormFieldModel;
const width = component.getSectionColumnWidth('invalid' as unknown as number, [columnField]);
expect(width).toBe('100');
});
it('should cap width at 100% when numberOfColumns is null', () => {
const columnField = { colspan: 3 } as FormFieldModel;
const width = component.getSectionColumnWidth(null as unknown as number, [columnField]);
expect(width).toBe('100');
});
it('should return 100% when numberOfColumns is undefined', () => {
const columnField = { colspan: 1 } as FormFieldModel;
const width = component.getSectionColumnWidth(undefined as unknown as number, [columnField]);
expect(width).toBe('100');
});
it('should cap width at 100% when numberOfColumns is 0', () => {
const columnField = { colspan: 2 } as FormFieldModel;
const width = component.getSectionColumnWidth(0, [columnField]);
expect(width).toBe('100');
});
it('should cap width at 100% when numberOfColumns is negative', () => {
const columnField = { colspan: 3 } as FormFieldModel;
const width = component.getSectionColumnWidth(-1, [columnField]);
expect(width).toBe('100');
});
it('should return 100 when numberOfColumns is falsy and no colspan is defined', () => {
const columnField = {} as FormFieldModel;
const width = component.getSectionColumnWidth(null as unknown as number, [columnField]);
expect(width).toBe('100');
});
it('should calculate percentage width when numberOfColumns is a valid number', () => {
const numberOfColumns = 4;
const columnField = { colspan: 2 } as FormFieldModel;
const width = component.getSectionColumnWidth(numberOfColumns, [columnField]);
expect(width).toBe('50');
});
it('should cap width at 100% when colspan exceeds numberOfColumns', () => {
const numberOfColumns = 2;
const columnField = { colspan: 5 } as FormFieldModel;
const width = component.getSectionColumnWidth(numberOfColumns, [columnField]);
expect(width).toBe('100');
});
it('should use default colspan of 1 when field has no colspan and numberOfColumns is valid', () => {
const numberOfColumns = 5;
const columnField = {} as FormFieldModel;
const width = component.getSectionColumnWidth(numberOfColumns, [columnField]);
expect(width).toBe('20');
});
it('should handle empty columnFields array', () => {
const numberOfColumns = 3;
const width = component.getSectionColumnWidth(numberOfColumns, []);
expect(parseFloat(width)).toBeCloseTo(33.33);
});
it('should use first field colspan when multiple fields are provided', () => {
const numberOfColumns = 2;
const columnFields = [{ colspan: 1 } as FormFieldModel, { colspan: 3 } as FormFieldModel];
const width = component.getSectionColumnWidth(numberOfColumns, columnFields);
expect(width).toBe('50');
});
});
});
@@ -43,10 +43,6 @@ export class FormSectionComponent implements OnInit {
const defaultColspan = 1;
const fieldColspan = columnFields[firstColumnFieldIndex]?.colspan ?? defaultColspan;
if (typeof numberOfColumns !== 'number' || !numberOfColumns || numberOfColumns <= 0) {
numberOfColumns = 1;
}
return Math.min(100, (100 / numberOfColumns) * fieldColspan) + '';
return (100 / numberOfColumns) * fieldColspan + '';
}
}
@@ -10,16 +10,25 @@
}
&-container {
display: grid;
display: flex;
align-items: flex-start;
flex-direction: column;
}
}
&-amount-widget__input {
margin-top: -15px;
#{ms.$mat-focused} {
transition: none;
}
#{ms.$mat-form-field-prefix} {
padding-top: 16px;
padding-bottom: 16px;
align-self: flex-end;
}
.adf-input {
margin-top: 3px;
}
@@ -21,9 +21,9 @@ import { FormWidgetModel } from './form-widget.model';
import { WidgetVisibilityModel } from '../../../models/widget-visibility.model';
export class FormOutcomeModel extends FormWidgetModel {
static readonly SAVE_ACTION: string = 'SAVE'; // Activiti 'Save' action name
static readonly COMPLETE_ACTION: string = 'COMPLETE'; // Activiti 'Complete' action name
static readonly START_PROCESS_ACTION: string = 'START PROCESS'; // Activiti 'Start Process' action name
static SAVE_ACTION: string = 'SAVE'; // Activiti 'Save' action name
static COMPLETE_ACTION: string = 'COMPLETE'; // Activiti 'Complete' action name
static START_PROCESS_ACTION: string = 'START PROCESS'; // Activiti 'Start Process' action name
isSystem: boolean = false;
isSelected: boolean = false;
@@ -708,103 +708,5 @@ describe('FormModel', () => {
expect(fields[1].type).toBe(FormFieldTypes.DATE);
expect(fields[2].type).toBe(FormFieldTypes.NUMBER);
});
it('should handle sections at root level correctly', () => {
const mockFormWithRootSection = {
id: 'test-form',
name: 'Test Form',
fields: [
{
id: 'root-section',
name: 'Root Section',
type: 'section',
numberOfColumns: 2,
fields: {
1: [
{
id: 'text-in-root-section',
name: 'Text in Root Section',
type: 'text',
required: false,
readOnly: false
}
]
}
}
]
};
const formWithRootSection = new FormModel(mockFormWithRootSection);
// Check that the root section is parsed correctly - wrapped in ContainerModel as expected
expect(formWithRootSection.fields.length).toBe(1);
expect(formWithRootSection.fields[0]).toBeInstanceOf(ContainerModel);
expect(formWithRootSection.fields[0].field.type).toBe('section');
expect(formWithRootSection.fields[0].field.id).toBe('root-section');
// Check that getFormFields returns all fields including the section and its children
const allFields = formWithRootSection.getFormFields();
expect(allFields.length).toBe(2); // section + text field inside
expect(allFields[0].type).toBe('section');
expect(allFields[1].type).toBe('text');
expect(allFields[1].id).toBe('text-in-root-section');
});
it('should process container fields before section fields in getFormFields', () => {
const mockFormWithContainerAndSection = {
id: 'test-form',
name: 'Test Form',
fields: [
{
id: 'container-field',
name: 'Container Field',
type: 'container',
numberOfColumns: 2,
fields: {
1: [
{
id: 'text-in-container',
name: 'Text in Container',
type: 'text',
required: false,
readOnly: false
}
]
}
},
{
id: 'section-field',
name: 'Section Field',
type: 'section',
numberOfColumns: 1,
fields: {
1: [
{
id: 'text-in-section',
name: 'Text in Section',
type: 'text',
required: false,
readOnly: false
}
]
}
}
]
};
const formWithMixed = new FormModel(mockFormWithContainerAndSection);
const allFields = formWithMixed.getFormFields();
// Check that the following order is correct: container, text-in-container, section, text-in-section
expect(allFields.length).toBe(4);
expect(allFields[0].type).toBe('container');
expect(allFields[0].id).toBe('container-field');
expect(allFields[1].type).toBe('text');
expect(allFields[1].id).toBe('text-in-container');
expect(allFields[2].type).toBe('section');
expect(allFields[2].id).toBe('section-field');
expect(allFields[3].type).toBe('text');
expect(allFields[3].id).toBe('text-in-section');
});
});
});
@@ -62,10 +62,10 @@ export interface FormRepresentationModel {
theme?: ThemeModel;
}
export class FormModel implements ProcessFormModel {
static readonly UNSET_TASK_NAME: string = 'Nameless task';
static readonly SAVE_OUTCOME: string = '$save';
static readonly COMPLETE_OUTCOME: string = '$complete';
static readonly START_PROCESS_OUTCOME: string = '$startProcess';
static UNSET_TASK_NAME: string = 'Nameless task';
static SAVE_OUTCOME: string = '$save';
static COMPLETE_OUTCOME: string = '$complete';
static START_PROCESS_OUTCOME: string = '$startProcess';
readonly id: string | number;
readonly name: string;
@@ -201,7 +201,7 @@ export class FormModel implements ProcessFormModel {
this.validateForm();
}
// Activiti supports 4 types of root fields: container|group|dynamic-table|section
// Activiti supports 3 types of root fields: container|group|dynamic-table
private parseRootFields(json: any): (ContainerModel | FormFieldModel)[] {
let fields = [];
@@ -354,10 +354,10 @@ export class FormModel implements ProcessFormModel {
private processFields(fields: (ContainerModel | FormFieldModel)[], formFieldModel: FormFieldModel[]): void {
fields.forEach((field) => {
if (this.isContainerField(field)) {
this.handleContainerField(field, formFieldModel);
} else if (this.isSectionField(field)) {
if (this.isSectionField(field)) {
this.handleSectionField(field, formFieldModel);
} else if (this.isContainerField(field)) {
this.handleContainerField(field, formFieldModel);
} else if (this.isFormField(field)) {
this.handleSingleField(field, formFieldModel);
}
@@ -410,28 +410,27 @@ export class FormModel implements ProcessFormModel {
}
protected parseOutcomes() {
if (!this.json.fields) return;
if (this.json.fields) {
const saveOutcome = new FormOutcomeModel(this, {
id: FormModel.SAVE_OUTCOME,
name: 'SAVE',
isSystem: true
});
const completeOutcome = new FormOutcomeModel(this, {
id: FormModel.COMPLETE_OUTCOME,
name: 'COMPLETE',
isSystem: true
});
const startProcessOutcome = new FormOutcomeModel(this, {
id: FormModel.START_PROCESS_OUTCOME,
name: 'START PROCESS',
isSystem: true
});
const saveOutcome = new FormOutcomeModel(this, {
id: FormModel.SAVE_OUTCOME,
name: FormOutcomeModel.SAVE_ACTION,
isSystem: true
});
const customOutcomes = (this.json.outcomes || []).map((obj) => new FormOutcomeModel(this, obj));
const completeOutcome = new FormOutcomeModel(this, {
id: FormModel.COMPLETE_OUTCOME,
name: FormOutcomeModel.COMPLETE_ACTION,
isSystem: true
});
const startProcessOutcome = new FormOutcomeModel(this, {
id: FormModel.START_PROCESS_OUTCOME,
name: FormOutcomeModel.START_PROCESS_ACTION,
isSystem: true
});
const customOutcomes = (this.json.outcomes ?? ([] as FormModel[])).map((formModel: FormModel) => new FormOutcomeModel(this, formModel));
this.outcomes = [saveOutcome].concat(customOutcomes.length > 0 ? customOutcomes : [completeOutcome, startProcessOutcome]);
this.outcomes = [saveOutcome].concat(customOutcomes.length > 0 ? customOutcomes : [completeOutcome, startProcessOutcome]);
}
}
addValuesNotPresent(valuesToSetIfNotPresent: FormValues) {
@@ -4,8 +4,9 @@
.adf {
&-date-time-widget {
&-container {
display: grid;
display: flex;
align-items: flex-start;
flex-direction: column;
}
#{ms.$mat-form-field-suffix} {
@@ -5,6 +5,4 @@
color: var(--adf-readonly-text-color, var(--adf-form-label-color, var(--theme-text-color)));
line-height: normal;
word-break: break-word;
position: relative;
top: 3px;
}
@@ -74,11 +74,6 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
}
}
@HostListener('blur')
onBlur() {
this._onTouched();
}
ngOnChanges(changes: SimpleChanges) {
if (changes['inputMask']?.currentValue['mask']) {
this.inputMask = changes['inputMask'].currentValue;
@@ -81,7 +81,7 @@ export class FormService implements FormValidationService {
if (!json.fields) {
form.outcomes = [
new FormOutcomeModel(form, {
id: FormModel.SAVE_OUTCOME,
id: '$save',
name: FormOutcomeModel.SAVE_ACTION,
isSystem: true
})
+1 -1
View File
@@ -453,7 +453,7 @@
"RESET": "Resetuj",
"THUMBNAILS": "Miniatura dokumentu",
"THUMBNAILS_PANLEL_CLOSE": "Zamknij panel miniatur",
"LOADING": "Wczytywanie dokumentu"
"LOADING": "Document is loading"
},
"PAGE_LABEL": {
"SHOWING": "Wyświetlanie",
@@ -75,10 +75,6 @@ export class UnitTestingUtils {
return this.debugElement.query(By.directive(directive));
}
getAllByDirective(directive: Type<any>): DebugElement[] {
return this.debugElement.queryAll(By.directive(directive));
}
/** Perform actions */
clickByCSS(selector: string): void {
@@ -17,19 +17,34 @@
export default {
GlobalWorkerOptions: {},
getDocument() {
return {
loadingTask: () => ({
destroy: () => Promise.resolve()
}),
promise: new Promise((resolve) => {
resolve({
numPages: 6,
getPage: () => 'fakePage'
});
})
};
},
getDocument: jasmine.createSpy('getDocument').and.callFake(() => ({
loadingTask: () => ({
destroy: () => Promise.resolve()
}),
promise: new Promise((resolve) => {
resolve({
numPages: 6,
getPage: () =>
Promise.resolve({
getAnnotations: () => [
{
subtype: 'Text',
name: 'NoIcon',
id: 'R13',
titleObj: {
str: 'Annotation title'
},
contentsObj: {
str: 'Annotation contents'
},
modificationDate: "D:20260202104106Z00'00",
popupRef: 'R1'
}
]
})
});
})
})),
PasswordResponses: {
NEED_PASSWORD: 1,
INCORRECT_PASSWORD: 2
@@ -17,7 +17,7 @@
import { FocusableOption } from '@angular/cdk/a11y';
import { AsyncPipe, NgIf } from '@angular/common';
import { Component, ElementRef, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, ElementRef, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { TranslatePipe } from '@ngx-translate/core';
@@ -29,13 +29,14 @@ import { TranslatePipe } from '@ngx-translate/core';
host: { tabindex: '0' }
})
export class PdfThumbComponent implements OnInit, FocusableOption {
private readonly sanitizer = inject(DomSanitizer);
private readonly element = inject(ElementRef);
@Input()
page: any = null;
page: any;
image$: Promise<string>;
constructor(private sanitizer: DomSanitizer, private element: ElementRef) {}
ngOnInit() {
this.image$ = this.page.getPage().then((page) => this.getThumb(page));
}
@@ -2,10 +2,12 @@
data-automation-id='adf-thumbnails-content'
[style.height.px]="virtualHeight"
[style.transform]="'translate(-50%, ' + translateY + 'px)'">
<adf-pdf-thumb *ngFor="let page of renderItems; trackBy: trackByFn"
class="adf-pdf-thumbnails__thumb"
[id]="page.id"
[ngClass]="{'adf-pdf-thumbnails__thumb--selected' : isSelected(page.id)}"
[page]="page"
(click)="goTo(page.id)" />
@for (page of renderItems; track page.id) {
<adf-pdf-thumb
class="adf-pdf-thumbnails__thumb"
[id]="page.id"
[ngClass]="{'adf-pdf-thumbnails__thumb--selected' : isSelected(page.id)}"
[page]="page"
(click)="goTo(page.id)" />
}
</div>
@@ -77,7 +77,7 @@ describe('PdfThumbListComponent', () => {
fixture = TestBed.createComponent(PdfThumbListComponent);
testingUtils = new UnitTestingUtils(fixture.debugElement);
component = fixture.componentInstance;
component.pdfViewer = viewerMock;
component.pdfViewer = viewerMock as any;
// provide scrollable container
fixture.nativeElement.style.display = 'block';
@@ -17,7 +17,7 @@
import { FocusKeyManager } from '@angular/cdk/a11y';
import { DOWN_ARROW, ESCAPE, TAB, UP_ARROW } from '@angular/cdk/keycodes';
import { DOCUMENT, NgClass, NgForOf } from '@angular/common';
import { DOCUMENT, NgClass } from '@angular/common';
import {
AfterViewInit,
Component,
@@ -25,7 +25,6 @@ import {
ElementRef,
EventEmitter,
HostListener,
Inject,
Input,
OnDestroy,
OnInit,
@@ -33,7 +32,8 @@ import {
QueryList,
TemplateRef,
ViewChildren,
ViewEncapsulation
ViewEncapsulation,
inject
} from '@angular/core';
import { delay } from 'rxjs/operators';
import { PdfThumbComponent } from '../pdf-viewer-thumb/pdf-viewer-thumb.component';
@@ -43,10 +43,13 @@ import { PdfThumbComponent } from '../pdf-viewer-thumb/pdf-viewer-thumb.componen
templateUrl: './pdf-viewer-thumbnails.component.html',
styleUrls: ['./pdf-viewer-thumbnails.component.scss'],
host: { class: 'adf-pdf-thumbnails' },
imports: [PdfThumbComponent, NgClass, NgForOf],
imports: [PdfThumbComponent, NgClass],
encapsulation: ViewEncapsulation.None
})
export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
private readonly element = inject(ElementRef);
private readonly document = inject(DOCUMENT);
@Input({ required: true }) pdfViewer: any;
@Output()
@@ -54,12 +57,12 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
virtualHeight: number = 0;
translateY: number = 0;
renderItems = [];
renderItems: any[] = [];
width: number = 91;
currentHeight: number = 0;
private items = [];
private margin: number = 15;
private items: any[] = [];
private readonly margin: number = 15;
private itemHeight: number = 114 + this.margin;
private previouslyFocusedElement: HTMLElement | null = null;
private keyManager: FocusKeyManager<PdfThumbComponent>;
@@ -103,12 +106,10 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
this.calculateItems();
}
constructor(private element: ElementRef, @Inject(DOCUMENT) private document: any) {
ngOnInit() {
this.calculateItems = this.calculateItems.bind(this);
this.onPageChange = this.onPageChange.bind(this);
}
ngOnInit() {
/* cspell:disable-next-line */
this.pdfViewer.eventBus.on('pagechanging', this.onPageChange);
this.element.nativeElement.addEventListener('scroll', this.calculateItems, true);
@@ -142,10 +143,6 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
}
}
trackByFn(_: number, item: any): number {
return item.id;
}
isSelected(pageNumber: number) {
return this.pdfViewer.currentPageNumber === pageNumber;
}
@@ -168,7 +165,7 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
}
}
getPages() {
getPages(): any[] {
// eslint-disable-next-line no-underscore-dangle
return this.pdfViewer._pages.map((page) => ({
id: page.id,
@@ -219,7 +216,7 @@ export class PdfThumbListComponent implements OnInit, AfterViewInit, OnDestroy {
};
}
private onPageChange(event) {
private onPageChange(event: any) {
const index = this.renderItems.findIndex((element) => element.id === event.pageNumber);
if (index < 0) {
@@ -16,7 +16,7 @@
*/
import { LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
import { Component, SimpleChange, ViewChild } from '@angular/core';
import { Component, SimpleChange, SimpleChanges, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { MatDialog } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
@@ -326,7 +326,7 @@ describe('Test PdfViewer component', () => {
() =>
({
afterClosed: () => of('')
} as any)
}) as any
);
spyOn(componentUrlTestPasswordComponent.pdfViewerComponent.close, 'emit');
@@ -510,6 +510,21 @@ describe('Test PdfViewer - User interaction', () => {
expect(component.displayPage).toBe(2);
});
it('should configure PDF.js with the correct wasmUrl', () => {
const changes: SimpleChanges = {
blobFile: new SimpleChange(null, component.blobFile, true)
};
component.ngOnChanges(changes);
const getDocumentSpy = pdfjsLibMock.getDocument;
expect(getDocumentSpy).toHaveBeenCalled();
const loadingArgs = getDocumentSpy.calls.mostRecent().args[0];
expect(loadingArgs.wasmUrl).toBe('./wasm/');
});
describe('Zoom', () => {
it('should zoom in increment the scale value', () => {
const zoomBefore = component.pdfViewer.currentScaleValue;
@@ -147,7 +147,8 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
disableAutoFetch: true,
disableStream: true,
cMapUrl: './cmaps/',
cMapPacked: true
cMapPacked: true,
wasmUrl: './wasm/'
};
private pdfjsWorkerDestroy$ = new Subject<boolean>();
@@ -1,118 +1,110 @@
@if (isLoading) {
<div class="adf-viewer-render-main-loader">
<div class="adf-viewer-render-layout-content adf-viewer__fullscreen-container">
<div class="adf-viewer-render-content-container">
<div class="adf-viewer-render__loading-screen">
<h2 id="loading-spinner-label">{{ 'ADF_VIEWER.LOADING' | translate }}</h2>
<div>
<mat-spinner aria-labelledby="loading-spinner-label" class="adf-viewer-render__loading-screen__spinner" />
</div>
<div *ngIf="isLoading" class="adf-viewer-render-main-loader">
<div class="adf-viewer-render-layout-content adf-viewer__fullscreen-container">
<div class="adf-viewer-render-content-container">
<div class="adf-viewer-render__loading-screen">
<h2 id="loading-spinner-label">{{ 'ADF_VIEWER.LOADING' | translate }}</h2>
<div>
<mat-spinner aria-labelledby="loading-spinner-label"
class="adf-viewer-render__loading-screen__spinner" />
</div>
</div>
</div>
</div>
}
</div>
@if (urlFile || blobFile) {
<div [style.visibility]="isLoading ? 'hidden' : 'visible'" class="adf-viewer-render-main">
<div class="adf-viewer-render-layout-content adf-viewer__fullscreen-container">
<div class="adf-viewer-render-content-container">
@switch (viewerType) {
@case ('external') {
@if (!!externalViewer) {
<adf-preview-extension
[id]="externalViewer.component"
[url]="urlFile"
[extension]="externalViewer.fileExtension"
[nodeId]="nodeId"
[attr.data-automation-id]="externalViewer.component"
(contentLoaded)="markAsLoaded()"
<div class="adf-viewer-render-content-container" [ngSwitch]="viewerType">
<ng-container *ngSwitchCase="'external'">
<adf-preview-extension
*ngIf="!!externalViewer"
[id]="externalViewer.component"
[url]="urlFile"
[extension]="externalViewer.fileExtension"
[nodeId]="nodeId"
[attr.data-automation-id]="externalViewer.component"
(contentLoaded)="markAsLoaded()"
/>
</ng-container>
<ng-container *ngSwitchCase="'pdf'">
<adf-pdf-viewer
[thumbnailsTemplate]="thumbnailsTemplate"
[allowThumbnails]="allowThumbnails"
[blobFile]="blobFile"
[urlFile]="urlFile"
[fileName]="internalFileName"
[cacheType]="cacheTypeForContent"
(pagesLoaded)="markAsLoaded()"
(close)="onClose()"
(error)="onUnsupportedFile()"
/>
</ng-container>
<ng-container *ngSwitchCase="'image'">
<adf-img-viewer
[urlFile]="urlFile"
[readOnly]="readOnly"
[fileName]="internalFileName"
[allowedEditActions]="allowedEditActions"
[blobFile]="blobFile"
(error)="onUnsupportedFile()"
(submit)="onSubmitFile($event)"
(imageLoaded)="markAsLoaded()"
(isSaving)="isSaving.emit($event)"
/>
</ng-container>
<ng-container *ngSwitchCase="'media'">
<adf-media-player
id="adf-mdedia-player"
[urlFile]="urlFile"
[tracks]="tracks"
[mimeType]="mimeType"
[blobFile]="blobFile"
[fileName]="internalFileName"
(error)="onUnsupportedFile()"
(canPlay)="markAsLoaded()"
/>
</ng-container>
<ng-container *ngSwitchCase="'text'">
<adf-txt-viewer [urlFile]="urlFile" [blobFile]="blobFile" (contentLoaded)="markAsLoaded()" />
</ng-container>
<ng-container *ngSwitchCase="'custom'">
<ng-container *ngFor="let ext of viewerExtensions">
<adf-preview-extension
*ngIf="checkExtensions(ext.fileExtension)"
[id]="ext.component"
[url]="urlFile"
[extension]="extension"
[nodeId]="nodeId"
[attr.data-automation-id]="ext.component"
(contentLoaded)="markAsLoaded()"
/>
</ng-container>
<ng-container *ngFor="let extensionTemplate of extensionTemplates">
<span *ngIf="extensionTemplate.isVisible" class="adf-viewer-render-custom-content">
<ng-template
[ngTemplateOutlet]="extensionTemplate.template"
[ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension, markAsLoaded: markAsLoaded.bind(this) }"
/>
}
}
</span>
</ng-container>
</ng-container>
@case ('pdf') {
<adf-pdf-viewer
[thumbnailsTemplate]="thumbnailsTemplate"
[allowThumbnails]="allowThumbnails"
[blobFile]="blobFile"
[urlFile]="urlFile"
[fileName]="internalFileName"
[cacheType]="cacheTypeForContent"
(pagesLoaded)="markAsLoaded()"
(close)="onClose()"
(error)="onUnsupportedFile()"
/>
}
@case ('image') {
<adf-img-viewer
[urlFile]="urlFile"
[readOnly]="readOnly"
[fileName]="internalFileName"
[allowedEditActions]="allowedEditActions"
[blobFile]="blobFile"
(error)="onUnsupportedFile()"
(submit)="onSubmitFile($event)"
(imageLoaded)="markAsLoaded()"
(isSaving)="isSaving.emit($event)"
/>
}
@case ('media') {
<adf-media-player
id="adf-mdedia-player"
[urlFile]="urlFile"
[tracks]="tracks"
[mimeType]="mimeType"
[blobFile]="blobFile"
[fileName]="internalFileName"
(error)="onUnsupportedFile()"
(canPlay)="markAsLoaded()"
/>
}
@case ('text') {
<adf-txt-viewer [urlFile]="urlFile" [blobFile]="blobFile" (contentLoaded)="markAsLoaded()" />
}
@case ('custom') {
@for (ext of viewerExtensions; track ext.id) {
@if (checkExtensions(ext.fileExtension)) {
<adf-preview-extension
[id]="ext.component"
[url]="urlFile"
[extension]="extension"
[nodeId]="nodeId"
[attr.data-automation-id]="ext.component"
(contentLoaded)="markAsLoaded()"
/>
}
}
<ng-container *ngFor="let extensionTemplate of extensionTemplates">
@if (extensionTemplate.isVisible) {
<span class="adf-viewer-render-custom-content">
<ng-template
[ngTemplateOutlet]="extensionTemplate.template"
[ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension, markAsLoaded: markAsLoaded.bind(this) }"
/>
</span>
}
</ng-container>
}
@default {
<adf-viewer-unknown-format [customError]="customError" />
}
}
<ng-container *ngSwitchDefault>
<adf-viewer-unknown-format [customError]="customError" />
</ng-container>
</div>
</div>
</div>
}
@if (viewerTemplateExtensions) {
<ng-container *ngIf="viewerTemplateExtensions">
<ng-template [ngTemplateOutlet]="viewerTemplateExtensions"
[ngTemplateOutletContext]="{ urlFile: urlFile, extension: extension, markAsLoaded: markAsLoaded.bind(this) }"
[ngTemplateOutletInjector]="injector" />
}
</ng-container>
@@ -15,8 +15,8 @@
* limitations under the License.
*/
import { AppExtensionService, ExtensionsModule, ViewerExtensionRef, PreviewExtensionComponent } from '@alfresco/adf-extensions';
import { NgForOf, NgTemplateOutlet } from '@angular/common';
import { AppExtensionService, ExtensionsModule, ViewerExtensionRef } from '@alfresco/adf-extensions';
import { NgForOf, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet } from '@angular/common';
import { Component, EventEmitter, Injector, Input, OnChanges, OnInit, Output, TemplateRef, ViewEncapsulation } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -38,6 +38,9 @@ import { UnknownFormatComponent } from '../unknown-format/unknown-format.compone
imports: [
TranslatePipe,
MatProgressSpinnerModule,
NgSwitch,
NgSwitchCase,
NgIf,
PdfViewerComponent,
ImgViewerComponent,
MediaPlayerComponent,
@@ -46,7 +49,7 @@ import { UnknownFormatComponent } from '../unknown-format/unknown-format.compone
UnknownFormatComponent,
ExtensionsModule,
NgForOf,
PreviewExtensionComponent
NgSwitchDefault
],
providers: [ViewUtilService]
})
@@ -46,20 +46,11 @@
[alt]="'ADF_VIEWER.ARIA.MIME_TYPE_ICON' | translate"
[src]="mimeTypeIconUrl"
data-automation-id="adf-file-thumbnail">
@if (displayTitle) {
<div class="adf-viewer__title-display-name-container"
id="adf-viewer-title-display-name"
[title]="displayTitle">
<p class="adf-viewer__title-value">{{ displayTitle }}</p>
<p class="adf-viewer__display-name-value">{{ displayName }}</p>
</div>
} @else {
<div class="adf-viewer__display-name"
id="adf-viewer-display-name"
[title]="fileName">
<span>{{ displayName }}</span>
</div>
}
<div class="adf-viewer__display-name"
id="adf-viewer-display-name"
[title]="fileName">
<span>{{ displayName }}</span>
</div>
<button *ngIf="allowNavigate && canNavigateNext"
data-automation-id="adf-toolbar-next-file"
mat-icon-button
@@ -53,7 +53,6 @@
}
}
&__title-display-name-container,
&__display-name {
font-size: var(--theme-subheading-2-font-size);
line-height: 1.5;
@@ -62,17 +61,6 @@
white-space: nowrap;
}
&__display-name-value,
&__title-value {
margin-top: 0;
margin-bottom: 0;
text-align: left;
}
&__display-name-value {
font-size: var(--theme-body-1-font-size);
}
&-container {
.adf-viewer-layout-content {
@extend .adf-full-screen;
@@ -51,7 +51,6 @@ describe('ViewerComponent', () => {
let testingUtils: UnitTestingUtils;
const getFileName = (): string => testingUtils.getByCSS('#adf-viewer-display-name').nativeElement.textContent;
const getTitle = (): string => testingUtils.getByCSS('.adf-viewer__title-value')?.nativeElement?.textContent;
const getDividers = (): DebugElement[] => testingUtils.getAllByCSS('.adf-toolbar-divider');
beforeEach(() => {
@@ -141,25 +140,25 @@ describe('ViewerComponent', () => {
});
});
describe('Display values Tests', () => {
describe('getDisplayTruncatedValue method', () => {
describe('File Name Display Tests', () => {
describe('displayFileName method', () => {
it('should return full filename when total length is 80 characters or less', () => {
const fileShortName = 'shortname.txt';
component.fileName = fileShortName;
fixture.detectChanges();
expect(component.getDisplayTruncatedValue(fileShortName)).toBe(fileShortName);
expect(component.getDisplayFileName()).toBe(fileShortName);
expect(getFileName()).toBe(fileShortName);
});
it('should truncate filename when total length exceeds 50 characters', () => {
it('should truncate filename when total length exceeds 80 characters', () => {
const longName =
'verylongfilenamethatexceedsmaximumlengthallowedverylongfilenamethatexceedsmaximumlengthallowed.verylongextensionnamethatistoolongverylongextensionnamethatistoolong';
component.fileName = longName;
fixture.detectChanges();
const result = component.getDisplayTruncatedValue(longName);
const result = component.getDisplayFileName();
expect(result).toContain('.....');
expect(result.length).toBe(50);
@@ -169,7 +168,7 @@ describe('ViewerComponent', () => {
component.fileName = '';
fixture.detectChanges();
expect(component.getDisplayTruncatedValue('')).toBe('');
expect(component.getDisplayFileName()).toBe('');
expect(getFileName()).toBe('');
});
});
@@ -199,37 +198,6 @@ describe('ViewerComponent', () => {
});
});
describe('displayTitle', () => {
it('should return full title when total length is 50 characters or less', () => {
const titleShortName = 'Custom mock title';
component.title = titleShortName;
fixture.detectChanges();
expect(component.getDisplayTruncatedValue(titleShortName)).toBe(titleShortName);
expect(getTitle()).toBe(titleShortName);
});
it('should truncate title when total length exceeds 50 characters', () => {
const longTitle =
'verylongTitlethatexceedsmaximumlengthallowedverylongTitlethatexceedsmaximumlengthallowedverylongTitlethatexceedsmaximumlengthallowed';
component.title = longTitle;
fixture.detectChanges();
const result = component.getDisplayTruncatedValue(longTitle);
expect(result).toContain('.....');
expect(result.length).toBe(50);
});
it('should handle empty title', () => {
component.title = undefined;
fixture.detectChanges();
expect(getTitle()).toBeFalsy();
});
});
describe('Viewer Example Component Rendering', () => {
it('should use custom toolbar', (done) => {
const customFixture = TestBed.createComponent(ViewerWithCustomToolbarComponent);
@@ -307,27 +307,19 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
private _fileExtension: string;
public displayName: string;
public displayTitle: string;
public downloadPromptTimer: number;
public downloadPromptReminderTimer: number;
public mimeTypeIconUrl: string;
private readonly destroyRef = inject(DestroyRef);
/** Override Content title. */
@Input()
set title(title: string) {
this.displayTitle = title ? this.getDisplayTruncatedValue(title) : '';
}
/** Override Content filename. */
@Input()
set fileName(fileName: string) {
this._fileName = fileName;
this._fileExtension = this.viewUtilsService.getFileExtension(this.fileName);
this._fileNameWithoutExtension = this.fileName?.replace(new RegExp(`${this.fileExtension}$`), '') || '';
const value = (this.fileNameWithoutExtension || '') + (this.fileExtension || '');
this.displayName = this.getDisplayTruncatedValue(value);
this.displayName = this.getDisplayFileName();
}
get fileName(): string {
@@ -481,11 +473,12 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
this.clearDownloadPromptTimeouts();
}
getDisplayTruncatedValue(value: string): string {
getDisplayFileName(): string {
const fullName = (this.fileNameWithoutExtension || '') + (this.fileExtension || '');
const maxLength = 50;
if (value.length <= maxLength) {
return value;
if (fullName.length <= maxLength) {
return fullName;
}
const amountOfTruncateDots = 5;
@@ -493,8 +486,8 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
const endLength = 8;
const startLength = availableSpace - endLength;
const start = value.substring(0, startLength);
const end = value.substring(value.length - endLength);
const start = fullName.substring(0, startLength);
const end = fullName.substring(fullName.length - endLength);
return start + '.....' + end;
}
-1
View File
@@ -24,7 +24,6 @@ export * from './lib/toolbar/index';
export * from './lib/header/index';
export * from './lib/pagination/index';
export * from './lib/login/index';
export * from './lib/landing-page/index';
export * from './lib/language-menu/index';
export * from './lib/info-drawer/index';
export * from './lib/identity-user-info/index';
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@alfresco/eslint-plugin-eslint-angular",
"version": "9.0.0",
"version": "8.0.3",
"description": "Alfresco ADF eslint angular custom rules",
"main": "main.js",
"author": "Hyland Software, Inc. and its affiliates",
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@alfresco/adf-extensions",
"description": "Provides extensibility support for ADF applications.",
"version": "9.0.0",
"version": "8.0.3",
"license": "Apache-2.0",
"author": "Hyland Software, Inc. and its affiliates",
"repository": {
@@ -14,7 +14,7 @@
"peerDependencies": {
"@angular/common": ">=14.1.3",
"@angular/core": ">=14.1.3",
"@alfresco/js-api": ">=10.0.0"
"@alfresco/js-api": ">=9.0.2"
},
"keywords": [
"extensions",
+15 -5
View File
@@ -15,26 +15,36 @@
* limitations under the License.
*/
import { DynamicExtensionComponent } from './components/dynamic-component/dynamic.component';
import { DynamicTabComponent } from './components/dynamic-tab/dynamic-tab.component';
import { DynamicColumnComponent } from './components/dynamic-column/dynamic-column.component';
import { PreviewExtensionComponent } from './components/viewer/preview-extension.component';
import { NgModule, ModuleWithProviders, inject, provideAppInitializer } from '@angular/core';
import { AppExtensionService } from './services/app-extension.service';
import { setupExtensions } from './services/startup-extension-factory';
/** @deprecated use provideAppExtensions() api instead */
@NgModule()
export const EXTENSION_DIRECTIVES = [DynamicExtensionComponent, DynamicTabComponent, DynamicColumnComponent, PreviewExtensionComponent] as const;
/** @deprecated import EXTENSION_DIRECTIVES or standalone components instead */
@NgModule({
imports: [...EXTENSION_DIRECTIVES],
exports: [...EXTENSION_DIRECTIVES]
})
export class ExtensionsModule {
static forRoot(): ModuleWithProviders<ExtensionsModule> {
return {
ngModule: ExtensionsModule,
providers: [
provideAppInitializer(() => {
const appExtensionService = inject(AppExtensionService);
return appExtensionService.load();
const initializerFn = setupExtensions(inject(AppExtensionService));
return initializerFn();
})
]
};
}
/**
* @deprecated use provideAppExtensions() api instead
* @deprecated use `ExtensionsModule` instead, `EXTENSION_DIRECTIVES` or direct standalone components
* @returns Module with providers
*/
static forChild(): ModuleWithProviders<ExtensionsModule> {
@@ -15,18 +15,6 @@
* limitations under the License.
*/
import { EnvironmentProviders, inject, provideAppInitializer, Provider } from '@angular/core';
import { AppExtensionService } from './services/app-extension.service';
import { AppExtensionService } from './app-extension.service';
/**
* Provides all necessary entries for the app extensibility
* @returns list of providers
*/
export function provideAppExtensions(): (Provider | EnvironmentProviders)[] {
return [
provideAppInitializer(() => {
const appExtensionService = inject(AppExtensionService);
return appExtensionService.load();
})
];
}
export const setupExtensions = (appExtensionService: AppExtensionService) => () => appExtensionService.load();
-1
View File
@@ -41,4 +41,3 @@ export * from './lib/store/states/repository.state';
export * from './lib/components/public-api';
export * from './lib/extensions.module';
export * from './lib/providers';
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@alfresco/adf-insights",
"description": "Alfresco ADF insights",
"version": "9.0.0",
"version": "8.0.3",
"author": "Hyland Software, Inc. and its affiliates",
"repository": {
"type": "git",
@@ -11,8 +11,8 @@
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
},
"dependencies": {
"@alfresco/adf-core": ">=9.0.0",
"@alfresco/adf-content-services": ">=9.0.0",
"@alfresco/adf-core": ">=8.0.2",
"@alfresco/adf-content-services": ">=8.0.2",
"@ngx-translate/core": ">=14.0.0",
"chart.js": "^4.3.0",
"ng2-charts": "^4.1.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@alfresco/js-api",
"version": "10.0.0",
"version": "9.0.3",
"license": "Apache-2.0",
"description": "JavaScript client library for the Alfresco REST API",
"author": "Hyland Software, Inc. and its affiliates",
+14 -1
View File
@@ -28,6 +28,19 @@
},
"allowedNonPeerDependencies": [
"@apollo/client",
"apollo-angular"
"apollo-angular",
"@editorjs/editorjs",
"@editorjs/code",
"@editorjs/header",
"@editorjs/inline-code",
"@editorjs/list",
"@editorjs/marker",
"@editorjs/paragraph",
"@editorjs/underline",
"@valano/change-font-size",
"editorjs-text-color-plugin",
"editorjs-html",
"editorjs-paragraph-with-alignment",
"editorjs-text-alignment-blocktune"
]
}
+19 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@alfresco/adf-process-services-cloud",
"description": "Alfresco ADF process services cloud",
"version": "9.0.0",
"version": "8.0.3",
"author": "Hyland Software, Inc. and its affiliates",
"repository": {
"type": "git",
@@ -10,6 +10,21 @@
"bugs": {
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
},
"dependencies": {
"@editorjs/code": "2.9.0",
"@editorjs/editorjs": "^2.28.2",
"@editorjs/header": "2.8.1",
"@editorjs/inline-code": "1.5.0",
"@editorjs/list": "1.9.0",
"@editorjs/marker": "1.4.0",
"@editorjs/paragraph": "^2.11.6",
"@editorjs/underline": "1.1.0",
"editorjs-html": "4.0.5",
"editorjs-paragraph-with-alignment": "3.0.0",
"editorjs-text-alignment-blocktune": "^1.0.3",
"editorjs-text-color-plugin": "1.13.1",
"@valano/change-font-size": "1.0.0"
},
"peerDependencies": {
"@angular/animations": ">=14.1.3",
"@angular/cdk": ">=14.1.2",
@@ -21,9 +36,9 @@
"@angular/platform-browser": ">=14.1.3",
"@angular/platform-browser-dynamic": ">=14.1.3",
"@angular/router": ">=14.1.3",
"@alfresco/js-api": ">=10.0.0",
"@alfresco/adf-core": ">=9.0.0",
"@alfresco/adf-content-services": ">=9.0.0",
"@alfresco/js-api": ">=9.0.2",
"@alfresco/adf-core": ">=8.0.2",
"@alfresco/adf-content-services": ">=8.0.2",
"@apollo/client": ">=3.7.2",
"@ngx-translate/core": ">=14.0.0",
"apollo-angular": ">=4.0.1"
@@ -91,7 +91,7 @@
class="adf-cloud-form-custom-outcome-button"
(click)="onOutcomeClicked(outcome)"
>
{{ getCustomOutcomeButtonText(outcome) || (outcome.name | translate | uppercase) }}
{{ outcome.name | translate | uppercase }}
</button>
</ng-container>
</mat-card-actions>
@@ -1492,54 +1492,6 @@ describe('FormCloudComponent', () => {
});
});
});
describe('Custom outcome button text for default outcomes', () => {
beforeEach(() => {
formComponent.form = formComponent.parseForm(emptyFormRepresentationJSON);
});
it('should display custom save button text when set', () => {
const customText = 'Custom Save Text';
formComponent.customSaveButtonText = customText;
fixture.detectChanges();
const buttonSelector = '#adf-form-save';
const outcomeButton = fixture.debugElement.query(By.css(buttonSelector));
expect(outcomeButton).toBeTruthy();
expect(outcomeButton.nativeElement.textContent.trim()).toBe(customText);
});
it('should display default save button text when not set', () => {
fixture.detectChanges();
const buttonSelector = '#adf-form-save';
const outcomeButton = fixture.debugElement.query(By.css(buttonSelector));
expect(outcomeButton).toBeTruthy();
expect(outcomeButton.nativeElement.textContent.trim()).toBe('SAVE');
});
it('should display custom complete button text when set', () => {
const customText = 'Custom Complete Text';
formComponent.customCompleteButtonText = customText;
fixture.detectChanges();
const buttonSelector = '#adf-form-complete';
const outcomeButton = fixture.debugElement.query(By.css(buttonSelector));
expect(outcomeButton).toBeTruthy();
expect(outcomeButton.nativeElement.textContent.trim()).toBe(customText);
});
it('should display default complete button text when not set', () => {
fixture.detectChanges();
const buttonSelector = '#adf-form-complete';
const outcomeButton = fixture.debugElement.query(By.css(buttonSelector));
expect(outcomeButton).toBeTruthy();
expect(outcomeButton.nativeElement.textContent.trim()).toBe('COMPLETE');
});
});
});
describe('Multilingual Form', () => {
@@ -121,20 +121,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
@Input()
showCompleteButton = false;
/**
* Custom text for the `Save` button.
* If not provided, the default text will be used.
*/
@Input()
customSaveButtonText: string = '';
/**
* Custom text for the `Complete` button.
* If not provided, the default text will be used.
*/
@Input()
customCompleteButtonText: string = '';
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
@Output()
formSaved = new EventEmitter<FormModel>();
@@ -312,15 +298,6 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
);
}
getCustomOutcomeButtonText(outcome: FormOutcomeModel): string {
if (outcome?.id === FormModel.SAVE_OUTCOME || outcome?.name === FormOutcomeModel.SAVE_ACTION) {
return this.customSaveButtonText;
} else if (outcome?.id === FormModel.COMPLETE_OUTCOME || outcome?.name === FormOutcomeModel.COMPLETE_ACTION) {
return this.customCompleteButtonText;
}
return '';
}
isAProcessTask(taskRepresentation: TaskDetailsCloudModel): boolean {
return taskRepresentation.processDefinitionId && taskRepresentation.processDefinitionDeploymentId !== 'null';
}
@@ -453,7 +430,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
* @returns list of form outcomes
*/
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
return [new FormOutcomeModel(form, { id: FormModel.SAVE_OUTCOME, name: FormOutcomeModel.SAVE_ACTION, isSystem: true })];
return [new FormOutcomeModel(form, { id: '$save', name: FormOutcomeModel.SAVE_ACTION, isSystem: true })];
}
checkVisibility(field: FormFieldModel) {
@@ -13,6 +13,7 @@
overflow-x: auto;
resize: vertical;
border-radius: 3px;
padding: 10px 12px;
outline: none;
width: 100%;
}
@@ -998,21 +998,6 @@ describe('DropdownCloudWidgetComponent', () => {
expect(widget.dropdownControl.value).toEqual({ id: 'testValue', name: '' });
});
it('should set dropdownControl value when form field value gets changed', () => {
widget.field = {
value: { id: 'Id_1', name: 'Label 1' },
options: [],
isVisible: true,
markAsValid: () => {}
} as FormFieldModel;
spyOn(widget.dropdownControl, 'setValue').and.callThrough();
widget.updateReactiveFormControl();
expect(widget.dropdownControl.setValue).toHaveBeenCalledWith({ id: 'Id_1', name: 'Label 1' }, { emitEvent: false });
expect(widget.dropdownControl.value).toEqual({ id: 'Id_1', name: 'Label 1' });
});
it('should set dropdownControl value without emitting events if is an object', () => {
widget.field = {
value: { id: 'testValueObj', name: 'testValueObjName' },
@@ -137,7 +137,6 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
updateReactiveFormControl(): void {
this.setFormControlValue();
this.updateFormControlState();
this.handleErrors();
}
@@ -29,9 +29,11 @@ import { RadioButtonsCloudWidgetComponent } from './components/widgets/radio-but
import { FilePropertiesTableCloudComponent } from './components/widgets/attach-file/file-properties-table/file-properties-table-cloud.component';
import { FileViewerWidgetComponent } from './components/widgets/file-viewer/file-viewer.widget';
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
import { RichTextEditorComponent } from '../rich-text-editor';
import { FormSpinnerComponent } from './components/spinner/form-spinner.component';
export const FORM_CLOUD_DIRECTIVES = [
RichTextEditorComponent,
FormSpinnerComponent,
PropertiesViewerWrapperComponent,
PropertiesViewerWidgetComponent,
@@ -210,7 +210,7 @@ export class FormCloudService extends BaseCloudService implements FormCloudServi
*
* @param json JSON data to create the form
* @param data Values for the form's fields
* @param readOnly Toggles whether the form should be read-only
* @param readOnly Toggles whether or not the form should be read-only
* @returns Form created from the JSON specification
*/
parseForm(json: any, data?: TaskVariableCloud[], readOnly: boolean = false): FormModel {
@@ -1,6 +1,7 @@
<form>
<mat-form-field
[subscriptSizing]="formFieldSubscriptSizing"
[floatLabel]="'auto'"
class="adf-people-cloud adf-form-field-input"
[class.adf-invalid]="hasError() && isDirty()"
>
@@ -23,6 +23,7 @@ import { ProcessCloudModule } from './process/process-cloud.module';
import { FORM_CLOUD_DIRECTIVES } from './form/form-cloud.module';
import { TASK_FORM_CLOUD_DIRECTIVES } from './task/task-form/task-form.module';
import { PreferenceCloudServiceInterface, TASK_LIST_CLOUD_TOKEN } from './services/public-api';
import { RichTextEditorComponent } from './rich-text-editor';
import { GroupCloudComponent } from './group/components/group-cloud.component';
import { PeopleCloudComponent } from './people/components/people-cloud.component';
import { provideCloudFormRenderer, provideCloudPreferences } from './providers';
@@ -32,7 +33,8 @@ export const PROCESS_SERVICES_CLOUD_DIRECTIVES = [
...APP_LIST_CLOUD_DIRECTIVES,
...FORM_CLOUD_DIRECTIVES,
...TASK_FORM_CLOUD_DIRECTIVES,
PeopleCloudComponent
PeopleCloudComponent,
RichTextEditorComponent
] as const;
/**
@@ -0,0 +1,102 @@
/*!
* @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.
*/
/** Plugin import */
import CodeTool from '@editorjs/code';
import Header from '@editorjs/header';
import Paragraph from '@editorjs/paragraph';
import InlineCode from '@editorjs/inline-code';
import List from '@editorjs/list';
import Marker from '@editorjs/marker';
import Underline from '@editorjs/underline';
import ChangeFontSize from '@valano/change-font-size';
import ColorPlugin from 'editorjs-text-color-plugin';
import AlignmentTuneTool from 'editorjs-text-alignment-blocktune';
export const editorJsConfig = {
autofocus: true,
logLevel: 'ERROR',
tools: {
underline: {
class: Underline,
shortcut: 'CMD+U'
},
header: {
class: Header,
inlineToolbar: true,
tunes: ['anyTuneName']
},
paragraph: {
class: Paragraph,
inlineToolbar: true,
tunes: ['anyTuneName']
},
list: {
class: List,
inlineToolbar: true,
config: {
defaultStyle: 'unordered'
}
},
Color: {
class: ColorPlugin,
config: {
customPicker: true,
colorCollections: [
'#FF1300',
'#ffa500',
'#9C27B0',
'#673AB7',
'#3F51B5',
'#0070FF',
'#03A9F4',
'#00BCD4',
'#5f9ea0',
'#4CAF50',
'#8BC34A',
'#CDDC39',
'#FFF',
'#000',
'#c0c0c0',
'#808080',
'#800000'
],
defaultColor: '#FF1300',
type: 'text'
}
},
Marker: {
class: Marker,
shortcut: 'CMD+M'
},
'Increase/Decrease font size': {
class: ChangeFontSize,
config: {
cssClass: 'plus20pc',
buttonIcon: '<span class="material-icons">format_size</span>'
}
},
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+M'
},
anyTuneName: {
class: AlignmentTuneTool
},
code: CodeTool
}
};
@@ -15,4 +15,5 @@
* limitations under the License.
*/
export * from './provider';
export * from './rich-text-editor.component';
export * from './rich-text-editor.module';
@@ -0,0 +1,3 @@
<div class="adf-rich-text-editor-container">
<div class="editorjs" id="{{dynamicId}}"></div>
</div>

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