Compare commits

..
Author SHA1 Message Date
Anukriti Singh c9bcbb2286 [APPS-2132] momet to date fns 2023-10-11 14:54:54 +05:30
5011 changed files with 106666 additions and 186461 deletions
-11
View File
@@ -1,11 +0,0 @@
.angular
nxcache
node_modules
dist
coverage
.github
.vscode
scripts
/angular.json
docs/**/*.md
lib/js-api/docs/**/*.md
+10 -28
View File
@@ -1,6 +1,5 @@
module.exports = {
root: true,
ignorePatterns: [
'projects/**/*',
'**/node_modules/**/*',
@@ -11,9 +10,7 @@ module.exports = {
'**/scripts',
'**/docs'
],
plugins: ['@nx'],
plugins: ['@nrwl/nx'],
overrides: [
{
files: ['*.ts'],
@@ -22,10 +19,11 @@ module.exports = {
createDefaultProgram: true
},
extends: [
'plugin:@nx/typescript',
'plugin:@nx/angular',
'plugin:@nrwl/nx/typescript',
'plugin:@nrwl/nx/angular',
'plugin:@cspell/recommended',
'plugin:@angular-eslint/recommended',
'plugin:@angular-eslint/ng-cli-compat',
'plugin:@angular-eslint/ng-cli-compat--formatting-add-on',
'plugin:@angular-eslint/template/process-inline-templates',
'plugin:jsdoc/recommended-typescript-error'
],
@@ -80,7 +78,6 @@ module.exports = {
accessibility: 'explicit'
}
],
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/prefer-optional-chain': 'warn',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-require-imports': 'off',
@@ -104,7 +101,7 @@ module.exports = {
],
'@typescript-eslint/member-ordering': 'off',
'prefer-arrow/prefer-arrow-functions': 'off',
'prefer-promise-reject-errors': 'error',
'brace-style': 'off',
'@typescript-eslint/brace-style': 'error',
'comma-dangle': 'error',
@@ -163,7 +160,7 @@ module.exports = {
[
'/*!',
' * @license',
' * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.',
' * Copyright © 2005-2023 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.',
@@ -178,28 +175,13 @@ module.exports = {
' * limitations under the License.',
' */'
]
],
'@nx/dependency-checks': 'warn'
]
}
},
{
files: ['*.html'],
extends: ['plugin:@angular-eslint/template/recommended', 'plugin:@angular-eslint/template/accessibility'],
extends: ['plugin:@angular-eslint/template/recommended'],
rules: {}
},
{
files: ['*.spec.ts'],
plugins: ['@alfresco/eslint-angular'],
rules: {
'@alfresco/eslint-angular/no-angular-material-selectors': 'error'
}
},
{
files: ['*.ts'],
extends: ['plugin:@angular-eslint/template/process-inline-templates'],
excludedFiles: ['*.spec.ts']
}
],
extends: ['plugin:storybook/recommended']
]
};
-3
View File
@@ -1,3 +0,0 @@
{
"extends": ["./.eslintrc.js"]
}
+3 -5
View File
@@ -22,15 +22,13 @@ runs:
- run: echo "Artifact Append"
shell: bash
- name: Download artifact
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/download-artifact@v3
with:
name: ${{ inputs.artifact-name }}
pattern: ${{ inputs.artifact-name }}-*
merge-multiple: true
- run: ls
shell: bash
- name: Append content
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v6
env:
contentFile: ${{ inputs.content }}
fileName: ${{ inputs.file-name }}
@@ -85,7 +83,7 @@ runs:
}
}
- name: Upload artifact
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.file-name }}
+2 -4
View File
@@ -24,15 +24,13 @@ runs:
using: "composite"
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v3
- run: echo "Artifact Extract"
shell: bash
- name: Download artifact
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/download-artifact@v3
with:
name: ${{ inputs.artifact-name }}
pattern: ${{ inputs.artifact-name }}-*
merge-multiple: true
- id: extract
shell: bash
run: |
@@ -19,14 +19,14 @@ runs:
using: "composite"
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v3
- name: Create empty artifact
shell: bash
run:
run:
echo "${{inputs.content}}" > ${{ inputs.file-name }}
- name: Upload artifact
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.file-name }}
+2 -3
View File
@@ -60,9 +60,8 @@ runs:
echo "Setting up CI flags for Push develop patch"
else
echo "Setting up CI flags for Push on develop branch"
# base=$(git describe --tags $(git rev-list --tags --max-count=1))
# we publish always all the libs until we don't handle partial release
echo "NX_CALCULATION_FLAGS=--all" >> $GITHUB_ENV
base=$(git describe --tags $(git rev-list --tags --max-count=1))
echo "NX_CALCULATION_FLAGS=--base=$base --head=$HEAD_HASH" >> $GITHUB_ENV
fi
echo "BREAK_ACTION=true" >> $GITHUB_ENV
+6 -10
View File
@@ -4,9 +4,6 @@ inputs:
e2e-test-id:
description: "Test id"
required: true
e2e-artifact-id:
description: "Artifact id"
required: true
e2e-test-folder:
description: "Test folder"
required: true
@@ -36,7 +33,6 @@ inputs:
description: check ps cloud env
default: "false"
e2e-tar-name: #
description: tarball name
required: false
default: e2e.tar.gz
apa-proxy: #
@@ -81,7 +77,7 @@ runs:
- name: download smartrunner test results from s3 bucket if they exist
shell: bash
env:
REMOTE_PATH: smart-runner/${{ github.run_id}}/${{ inputs.e2e-test-folder }}-${{ inputs.e2e-artifact-id}}/e2e.tar.gz
REMOTE_PATH: smart-runner/${{ github.run_id}}/${{ inputs.e2e-test-folder }}-${{ inputs.e2e-test-id}}/e2e.tar.gz
run: |
set -u;
mkdir -p "${SMART_RUNNER_PATH}"
@@ -157,7 +153,7 @@ runs:
echo $PROXY_HOST_BPM
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
- name: run test
- name: run test
id: e2e_run
if: ${{ steps.determine-affected.outputs.isAffected == 'true' }}
env:
@@ -181,23 +177,23 @@ runs:
if: ${{ steps.determine-affected.outputs.isAffected == 'true' && github.event_name == 'schedule' && failure() }}
uses: ./.github/actions/artifact-append
with:
artifact-name: "global-e2e-result-${{ inputs.e2e-test-id }}"
artifact-name: global-e2e-result
file-name: e2e-failures.txt
content: "${{ inputs.e2e-test-id }}"
- name: upload artifacts on gh
id: upload_gh
if: ${{ steps.determine-affected.outputs.isAffected == 'true' }}
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
uses: actions/upload-artifact@v3
with:
name: e2e-artifact-output-${{inputs.e2e-artifact-id}}
name: e2e-artifact-output
path: /home/runner/work/alfresco-ng2-components/alfresco-ng2-components/e2e-output-*
- name: upload smart-runner tests results on s3 to cache tests
shell: bash
if: always()
env:
REMOTE_PATH: "smart-runner/${{ github.run_id}}/${{ inputs.e2e-test-folder }}-${{inputs.e2e-artifact-id}}/e2e.tar.gz"
REMOTE_PATH: "smart-runner/${{ github.run_id}}/${{ inputs.e2e-test-folder }}-${{ inputs.e2e-test-id}}/e2e.tar.gz"
# description: always upload newer results
run: |
tar czf "${{ inputs.e2e-tar-name }}" "${SMART_RUNNER_PATH}"
+5 -3
View File
@@ -20,7 +20,9 @@ runs:
id: sha_out
run: |
if [[ -z $TAG_NPM ]]; then
echo "TAG_NPM not set, aborting"
exit 1
echo "TAG_NPM not set, aborting"
exit 1
fi
./scripts/github/build/npm-check-bundles.sh
ADF_VERSION=$(npm view @alfresco/adf-core@${TAG_NPM} version)
echo "check bundle on TAG_NPM='${TAG_NPM}' and ADF_VERSION='${ADF_VERSION}'"
./scripts/github/build/npm-check-bundles.sh -v ${ADF_VERSION}
+4 -4
View File
@@ -20,18 +20,18 @@ runs:
using: "composite"
steps:
- name: install NPM
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
cache-dependency-path: package-lock.json
- name: get latest tag sha
id: tag-sha
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@9d00215f539f669b41c7fabf7b88ccc8f316926c # v6.0.1
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@v1.29.0
# CACHE
- name: Node Modules cache
id: node-modules-cache
if: ${{ inputs.enable-node-modules-cache == 'true' }}
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@v3
env:
cache-name: node-modules-cache
with:
@@ -43,7 +43,7 @@ runs:
node_modules-${{ runner.os }}-build-
node_modules-${{ runner.os }}-
- name: pip cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@v3
if: ${{ inputs.enable-cache == 'true' }}
with:
path: ~/.cache/pip
+1 -1
View File
@@ -18,7 +18,7 @@ runs:
steps:
- name: Append group
id: group
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v6
env:
affectedLib: ${{ inputs.affected }}
with:
+2 -2
View File
@@ -1,6 +1,6 @@
name: "CodeQL config"
paths-ignore:
- 'e2e/resources/**'
- 'docs/**'
- 'e2e/resources/**/*.*'
- 'docs/**/*.*'
+25 -86
View File
@@ -1,92 +1,31 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: "weekly"
day: "sunday"
time: "07:00"
open-pull-requests-limit: 5
target-branch: develop
groups:
angular:
patterns:
- package-ecosystem: npm
directory: "/"
schedule:
interval: "weekly"
day: "sunday"
time: "07:00"
open-pull-requests-limit: 5
target-branch: develop
groups:
- label: "Angular Updates"
packages:
- "@angular/*"
angular-devkit:
patterns:
version: "widen"
- label: "Angular-devkit Updates"
packages:
- "@angular-devkit/*"
ngrx:
patterns:
version: "widen"
- label: "ngrx Updates"
packages:
- "@ngrx/*"
nrwl:
patterns:
version: "widen"
- label: "nrwl Updates"
packages:
- "@nrwl/*"
ignore:
- dependency-name: "pdfjs-dist"
- dependency-name: "@types/*"
- dependency-name: "typescript"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/artifact-append"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/artifact-extract"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/artifact-initialize"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/before-install"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/download-node-modules-and-artifacts"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/e2e"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/enable-dryrun"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/get-latest-tag-sha"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/npm-check-bundle"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/print-affected-libs"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/set-npm-tag"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/setup"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/setup-chrome"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/slack-group-area"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/.github/actions/upload-node-modules-and-artifacts"
schedule:
interval: "weekly"
version: "widen"
ignore:
- dependency-name: "pdfjs-dist"
- dependency-name: "@types/*"
- dependency-name: "typescript"
+8 -8
View File
@@ -4,14 +4,14 @@ on:
push:
branches: [develop, master]
paths-ignore:
- 'e2e/resources/**'
- 'docs/**'
- 'e2e/resources/**/*.*'
- 'docs/**/*.*'
pull_request:
# The branches below must be a subset of the branches above
branches: [develop]
paths-ignore:
- 'e2e/resources/**'
- 'docs/**'
- 'e2e/resources/**/*.*'
- 'docs/**/*.*'
schedule:
- cron: '0 5 * * 0'
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -30,7 +30,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0
uses: github/codeql-action/init@v2
# 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@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0
uses: github/codeql-action/autobuild@v2
# ️ 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@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0
uses: github/codeql-action/analyze@v2
+1 -1
View File
@@ -73,7 +73,7 @@ jobs:
runs-on: ubuntu-latest
name: Initialize artifacts
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v3
- uses: ./.github/actions/artifact-initialize
with:
artifact-name: global-e2e-result
+3 -3
View File
@@ -91,18 +91,18 @@ jobs:
needs: release
timeout-minutes: 20
name: "Release tag"
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
env:
GITHUB_TOKEN: $BOT_GITHUB_TOKEN
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
- id: set-dryrun
uses: ./.github/actions/enable-dryrun
with:
dry-run-flag: ${{ inputs.dry-run-flag }}
- name: install NPM
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- name: "Release tag"
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
if: github.event.registry_package.package_type == 'npm' && github.event.registry_package.name == 'adf-core'
steps:
- name: Dispatch event to monorepo
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v6
with:
github-token: ${{ secrets.PAT_WRITE_PKG }}
retries: 3
+54 -56
View File
@@ -11,7 +11,7 @@ on:
devel:
description: 'devel'
required: false
type: boolean
type: string
default: false
cron-run:
description: 'disables jobs which should not run when cron runs e2es'
@@ -94,14 +94,11 @@ env:
PROXY_HOST_ECM: ${{ secrets.E2E_HOST }}
jobs:
pre-checks:
runs-on: ubuntu-latest
check-package-lock:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Ensure SHA pinned actions
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@b88cd0aad2c36a63e42c71f81cb1958fed95ac87 # v3.0.10
uses: actions/checkout@v3
- name: Check package-lock.json version
run: |
@@ -113,18 +110,18 @@ jobs:
fi
check-if-pr-is-approved:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get branch name
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@76affd16a4dd9a440cf66bf42656b1d826e8dfc2 # v5.34.0
uses: Alfresco/alfresco-build-tools/.github/actions/get-branch-name@v1.36.0
- name: Save commit message
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@76affd16a4dd9a440cf66bf42656b1d826e8dfc2 # v5.34.0
uses: Alfresco/alfresco-build-tools/.github/actions/get-commit-message@v1.36.0
- name: ci:force flag parser
shell: bash
@@ -138,8 +135,8 @@ jobs:
fi
- name: Get PR number
if: ${{ github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' }}
uses: kamatama41/get-pr-number-action@0bcaab5752c0b699149e74667c8ce2f764cbb7fa # v0.9.1
if: ${{ github.event_name != 'schedule' }}
uses: kamatama41/get-pr-number-action@5c77b38a1b4974ebf8a9521a689f38a5898eadd6
id: action
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
@@ -167,7 +164,8 @@ jobs:
echo -e "\033[32mCommit by ${{ github.actor }}. No need for approval.\033[0m"
skip_check="true"
fi
if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
if [ "${{ github.event_name }}" == "schedule" ]; then
echo -e "\033[32mSchedule event\033[0m"
skip_check="true"
fi
@@ -194,18 +192,17 @@ jobs:
# long timeout required when cache has to be recreated
timeout-minutes: 30
name: "Setup"
runs-on: ubuntu-latest
needs: [check-if-pr-is-approved, pre-checks]
runs-on: ubuntu-22.04
needs: [check-if-pr-is-approved, check-package-lock]
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all tags and branches
- uses: ./.github/actions/setup
- name: install
run: |
npm ci
npx nx run js-api:bundle
npx nx run cli:bundle
npx nx run testing:bundle
- run: npx nx print-affected $NX_CALCULATION_FLAGS
@@ -214,28 +211,26 @@ jobs:
unit-tests:
timeout-minutes: 30
name: "Unit tests: ${{ matrix.unit-tests.name }}"
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: [setup]
strategy:
fail-fast: false
# max-parallel: 4
matrix:
unit-tests:
- name: js-api
exclude: "core,insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular"
- name: content-services
exclude: "insights,core,extensions,process-services,process-services-cloud,eslint-plugin-eslint-angular,js-api"
exclude: "insights,core,extensions,process-services,process-services-cloud,eslint-plugin-eslint-angular"
- name: core
exclude: "insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular,js-api"
exclude: "insights,content-services,process-services,process-services-cloud,eslint-plugin-eslint-angular"
- name: insights
exclude: "core,extensions,content-services,process-services-cloud,process-services,eslint-plugin-eslint-angular,js-api"
exclude: "core,extensions,content-services,process-services-cloud,process-services,eslint-plugin-eslint-angular"
- name: process-services
exclude: "core,extensions,content-services,process-services-cloud,insights,eslint-plugin-eslint-angular,js-api"
exclude: "core,extensions,content-services,process-services-cloud,insights,eslint-plugin-eslint-angular"
- name: process-cloud
exclude: "insights,core,extensions,content-services,process-services,eslint-plugin-eslint-angular,js-api"
exclude: "insights,core,extensions,content-services,process-services,eslint-plugin-eslint-angular"
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all tags and branches
- uses: ./.github/actions/setup
@@ -248,11 +243,11 @@ jobs:
# long timeout required when cache has to be recreated
timeout-minutes: 30
name: "Lint"
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: [setup]
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all tags and branches
- uses: ./.github/actions/setup
@@ -263,11 +258,11 @@ jobs:
# long timeout required when cache has to be recreated
timeout-minutes: 30
name: "Build libs"
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: [setup]
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all tags and branches
- uses: ./.github/actions/setup
@@ -281,10 +276,10 @@ jobs:
timeout-minutes: 20
name: "e2e: storybook"
needs: [build-libs, lint, unit-tests]
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all
- uses: ./.github/actions/setup
@@ -300,7 +295,7 @@ jobs:
timeout-minutes: 90
name: "e2e: ${{ matrix.e2e-test.description }}"
needs: [build-libs, lint, unit-tests]
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
strategy:
fail-fast: false
# max-parallel: 4
@@ -308,7 +303,6 @@ jobs:
e2e-test:
- description: "Core"
test-id: "core"
artifact-id: "core"
folder: "core"
provider: "ALL"
auth: "OAUTH"
@@ -317,7 +311,6 @@ jobs:
deps: "testing"
- description: "Content: Components"
test-id: "content-services"
artifact-id: "content-services-components"
folder: "content-services/components"
provider: "ECM"
auth: "BASIC"
@@ -325,7 +318,6 @@ jobs:
deps: "testing"
- description: "Content: Directives"
test-id: "content-services"
artifact-id: "content-services-directives"
folder: "content-services/directives"
provider: "ECM"
auth: "BASIC"
@@ -333,7 +325,6 @@ jobs:
deps: "testing"
- description: "Content: Document List"
test-id: "content-services"
artifact-id: "content-services-document-list"
folder: "content-services/document-list"
provider: "ECM"
auth: "BASIC"
@@ -341,7 +332,6 @@ jobs:
deps: "testing"
- description: "Content: Metadata"
test-id: "content-services"
artifact-id: "content-services-metadata"
folder: "content-services/metadata"
provider: "ECM"
auth: "BASIC"
@@ -349,7 +339,6 @@ jobs:
deps: "testing"
- description: "Content: Upload and Versioning"
test-id: "content-services"
artifact-id: "content-services-upload"
folder: "content-services/upload"
provider: "ECM"
auth: "BASIC"
@@ -357,7 +346,6 @@ jobs:
deps: "testing"
- description: "Search"
test-id: "content-services"
artifact-id: "content-services-search"
folder: "search"
provider: "ECM"
auth: "BASIC"
@@ -365,7 +353,6 @@ jobs:
deps: "testing"
- description: "Process: Form"
test-id: "process-services"
artifact-id: "process-services-form"
folder: "process-services/form"
provider: "BPM"
auth: "OAUTH"
@@ -374,7 +361,6 @@ jobs:
deps: "testing"
- description: "Process: Process"
test-id: "process-services"
artifact-id: "process-services-process"
folder: "process-services/process"
provider: "BPM"
auth: "OAUTH"
@@ -383,7 +369,6 @@ jobs:
deps: "testing"
- description: "Process: Tasks"
test-id: "process-services"
artifact-id: "process-services-tasks"
folder: "process-services/tasks"
provider: "BPM"
auth: "OAUTH"
@@ -392,7 +377,6 @@ jobs:
deps: "testing"
- description: "Process: Widget"
test-id: "process-services"
artifact-id: "process-services-widgets"
folder: "process-services/widgets"
provider: "BPM"
auth: "OAUTH"
@@ -401,7 +385,6 @@ jobs:
deps: "testing"
- description: "Process Cloud: Form"
test-id: "process-services-cloud"
artifact-id: "process-services-cloud-form-field"
folder: "process-services-cloud/form-field"
provider: "ALL"
auth: "OAUTH"
@@ -409,9 +392,17 @@ jobs:
check-cs-env: "true"
check-ps-cloud-env: "true"
deps: "testing"
- description: "Process Cloud: People"
test-id: "process-services-cloud"
folder: "process-services-cloud/people"
provider: "ALL"
auth: "OAUTH"
apa-proxy: true
check-cs-env: "true"
check-ps-cloud-env: "true"
deps: "testing"
- description: "Process Cloud: Process"
test-id: "process-services-cloud"
artifact-id: "process-services-cloud-process"
folder: "process-services-cloud/process"
provider: "ALL"
auth: "OAUTH"
@@ -421,7 +412,6 @@ jobs:
deps: "testing"
- description: "Process Cloud: Start Task"
test-id: "process-services-cloud"
artifact-id: "process-services-cloud-start-task"
folder: "process-services-cloud/start-task"
provider: "ALL"
auth: "OAUTH"
@@ -431,7 +421,6 @@ jobs:
deps: "testing"
- description: "Process Cloud: Tasks List"
test-id: "process-services-cloud"
artifact-id: "process-services-cloud-task-list"
folder: "process-services-cloud/task-list"
provider: "ALL"
auth: "OAUTH"
@@ -442,7 +431,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0 # Fetch all history for all
- uses: ./.github/actions/setup
@@ -450,12 +439,13 @@ jobs:
enable-cache: "true"
enable-node-modules-cache: "true"
- uses: ./.github/actions/download-node-modules-and-artifacts
- name: setup chrome
uses: ./.github/actions/setup-chrome
- name: e2e
uses: ./.github/actions/e2e
with:
e2e-test-id: ${{ matrix.e2e-test.test-id }}
e2e-test-folder: ${{ matrix.e2e-test.folder }}
e2e-artifact-id: ${{matrix.e2e-test.artifact-id}}
e2e-test-provider: ${{ matrix.e2e-test.provider }}
e2e-test-auth: ${{ matrix.e2e-test.auth }}
check-cs-env: ${{ matrix.e2e-test.check-cs-env }}
@@ -471,12 +461,12 @@ jobs:
steps:
- id: checkoutRepo
name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: PR contains forbidden labels
id: pr-forbidden
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
uses: actions/github-script@v6
with:
script: |
const issueHasLabels = require('./scripts/github/update/check-issue-has-label.js');
@@ -496,16 +486,23 @@ jobs:
if: ${{ always() }}
runs-on: ubuntu-latest
name: Final Results
needs: [check-if-pr-is-approved, pre-checks, setup, unit-tests, lint, build-libs, e2e, e2e-storybook]
needs: [check-if-pr-is-approved, check-package-lock, setup, unit-tests, lint, build-libs, e2e, e2e-storybook]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v3
- name: Log e2e result
id: e2e-result
if: ${{ github.event_name == 'schedule' }}
uses: ./.github/actions/artifact-extract
with:
artifact-name: global-e2e-result
file-name: e2e-failures.txt
- name: identify-slack-group
id: groups
if: ${{ github.event_name == 'schedule' }}
uses: ./.github/actions/slack-group-area
with:
affected: ${{ steps.e2e-result.outputs.result }}
- uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
- uses: slackapi/slack-github-action@v1.23.0
name: Nofify QA failure
if: ${{ github.event_name == 'schedule' && contains(needs.*.result, 'failure') }}
env:
@@ -522,3 +519,4 @@ jobs:
- name: workflow success
run: exit 0
if: ${{ contains(needs.*.result, 'success') }}
+2 -2
View File
@@ -9,10 +9,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the latest code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Automatic Rebase
uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 # 1.8
uses: cirrus-actions/rebase@1.8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+9 -10
View File
@@ -78,7 +78,7 @@ jobs:
setup:
timeout-minutes: 20
name: "Setup"
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: set TAG_NPM BRANCH
shell: bash
@@ -87,7 +87,7 @@ jobs:
echo "Set TAG with name: ${TAG_NPM}"
echo "TAG_NPM=${TAG_NPM}" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: ./.github/actions/setup
@@ -97,7 +97,6 @@ jobs:
- name: install
run: |
npm ci
npx nx run js-api:bundle
npx nx run cli:bundle
npx nx run testing:bundle
- uses: ./.github/actions/upload-node-modules-and-artifacts
@@ -105,13 +104,13 @@ jobs:
release-npm:
needs: [setup]
timeout-minutes: 30
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: ./.github/actions/setup
@@ -126,10 +125,10 @@ jobs:
- name: build libraries
run: |
set -u;
./scripts/update-version.sh -gnu || exit 1;
./scripts/update-version.sh -gnu -nextalpha|| exit 1;
npx nx affected:build $NX_CALCULATION_FLAGS --prod --exclude="demoshell" --skip-nx-cache
npx nx affected $NX_CALCULATION_FLAGS --target=pretheme
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@v3
name: release libraries GH registry
with:
node-version-file: '.nvmrc'
@@ -138,7 +137,7 @@ jobs:
- run: npx nx affected --target=npm-publish $NX_CALCULATION_FLAGS --tag=branch|| exit 1
env:
NODE_AUTH_TOKEN: ${{ secrets.PAT_WRITE_PKG }}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@v3
name: release libraries Npm registry
with:
node-version-file: '.nvmrc'
@@ -151,8 +150,8 @@ jobs:
npm-check-bundle:
needs: [release-npm]
timeout-minutes: 15
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
- uses: ./.github/actions/npm-check-bundle
+16 -41
View File
@@ -16,10 +16,6 @@ on:
- develop-patch*
- master-patch*
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
env:
BASE_REF: ${{ github.base_ref }}
HEAD_REF: ${{ github.head_ref }}
@@ -89,10 +85,10 @@ jobs:
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
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: ./.github/actions/setup
@@ -102,7 +98,6 @@ jobs:
- name: install
run: |
npm ci
npx nx run js-api:bundle
npx nx run cli:bundle
npx nx run testing:bundle
- uses: ./.github/actions/upload-node-modules-and-artifacts
@@ -111,10 +106,10 @@ jobs:
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
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 1
- run: git fetch --all
@@ -137,10 +132,10 @@ jobs:
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
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 1
- run: git fetch --all
@@ -164,13 +159,13 @@ jobs:
needs: [setup]
timeout-minutes: 30
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: ./.github/actions/setup
@@ -188,7 +183,7 @@ jobs:
./scripts/github/build/bumpversion.sh
npx nx affected:build $NX_CALCULATION_FLAGS --prod --exclude="demoshell" --skip-nx-cache
npx nx affected $NX_CALCULATION_FLAGS --target=pretheme
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@v3
name: release libraries GH registry
with:
node-version-file: '.nvmrc'
@@ -197,7 +192,7 @@ jobs:
- run: npx nx affected --target=npm-publish $NX_CALCULATION_FLAGS --tag=$TAG_NPM || exit 1
env:
NODE_AUTH_TOKEN: ${{ secrets.PAT_WRITE_PKG }}
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@v3
name: release libraries Npm registry
with:
node-version-file: '.nvmrc'
@@ -207,34 +202,14 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- 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
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v3
- uses: ./.github/actions/npm-check-bundle
finalize:
@@ -244,11 +219,11 @@ jobs:
needs: [release-demoshell, release-storybook, release-npm, npm-check-bundle]
steps:
- uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
name: Nofify FE eng-guild-front-end workflow failed
- uses: slackapi/slack-github-action@v1.23.0
name: Nofify FE hxp-front-end-apps workflow failed
if: ${{ contains(toJson(needs.*.result), 'failure') }}
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
with:
channel-id: 'C016SMNNL8L' #eng-guild-front-end
slack-message: "🔴 Warning: The release workflow of alfresco-ng2-components pipe failed\n Author username: ${{ github.event.pull_request.user.login }}\n Workflow run <https://github.com/Alfresco/alfresco-ng2-components/actions/runs/${{ github.run_id }}| here>\n>"
channel-id: 'C04N93XU491' #hxp-front-end-apps
slack-message: "🔴 Warning: The release workflow of alfresco-ng2-components pipe failed\n Author: name:${{ github.event.pusher.name }}\n Workflow run : <https://github.com/Alfresco/alfresco-ng2-components/actions/runs/${{ github.run_id }}| here>\n>"
+214
View File
@@ -0,0 +1,214 @@
name: Upstream js
on:
schedule:
- cron: '0 */3 * * *' # “At minute 0 past every 3rd hour.”
workflow_dispatch:
inputs:
tag_version:
description: image tag
type: choice
required: true
options:
- alpha
- latest
default: alpha
jobs:
upstream:
runs-on: ubuntu-latest
outputs:
hasAtLeastOneNewVersion: ${{ steps.fetchLatestPkg.outputs.hasAtLeastOneNewVersion }}
hasNewVersionAvailableJS: ${{ steps.fetchLatestPkg.outputs.hasVersionNewJS }}
latestVersionAvailableJS: ${{ steps.fetchLatestPkg.outputs.latestVersionJS }}
hasAtLeastOneNewVersionWithoutPR: ${{ steps.checkPrAlreadyExist.outputs.hasAtLeastOneNewVersionWithoutPR }}
steps:
- id: checkoutRepo
name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1
- id: fetchLatestPkg
name: Fetch the latest package version
uses: actions/github-script@v6
env:
TAG_VERSION: ${{ inputs.tag_version }}
with:
github-token: ${{ secrets.PAT_WRITE_PKG }}
script: |
const tagVersion = process.env.TAG_VERSION;
console.log('tagVersion:',tagVersion);
const getLatestVersionOf = require('./scripts/github/update/latest-version-of.js');
const { hasVersionNew: hasVersionNewJS, latestVersion: latestVersionJS } = await getLatestVersionOf({github, context, dependencyName: 'js-api', tagVersion});
console.log('hasVersionNewJS', hasVersionNewJS)
console.log('latestVersionJS', latestVersionJS)
if (hasVersionNewJS === 'true' ) {
core.setOutput('hasAtLeastOneNewVersion', 'true');
core.setOutput('hasVersionNewJS', 'true');
core.setOutput('latestVersionJS', latestVersionJS);
} else {
core.setOutput('hasAtLeastOneNewVersion', 'false');
console.log('No new version available, skipping upstream!')
}
- name: Check value after
run: |
echo "The value hasAtLeastOneNewVersion is: ${{ steps.fetchLatestPkg.outputs.hasAtLeastOneNewVersion }}"
echo "The value hasVersionNewJS is: ${{ steps.fetchLatestPkg.outputs.hasVersionNewJS }}"
echo "The value latestVersionJS is: ${{ steps.fetchLatestPkg.outputs.latestVersionJS }}"
- id: checkPrAlreadyExist
name: Check PR with latest already exist
if: ${{ steps.fetchLatestPkg.outputs.hasAtLeastOneNewVersion == 'true' }}
uses: actions/github-script@v6
env:
HAS_NEW_JS_VERSION: ${{ steps.fetchLatestPkg.outputs.hasVersionNewJS }}
LATEST_JS_VERSION: ${{ steps.fetchLatestPkg.outputs.latestVersionJS }}
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const hasVersionNewJS = process.env.HAS_NEW_JS_VERSION;
const latestVersionJS = process.env.LATEST_JS_VERSION;
const checkPRAlreadyExist = require('./scripts/github/update/check-pr-already-exist.js');
let isPRWithLatestJSAlreadyAvailable = false;
if (hasVersionNewJS === 'true') {
isPRWithLatestJSAlreadyAvailable = await checkPRAlreadyExist({github, context, version: latestVersionJS});
console.log('isPRWithLatestJSAlreadyAvailable', isPRWithLatestJSAlreadyAvailable);
}
if (isPRWithLatestJSAlreadyAvailable) {
console.log('Warning: Upstream PR already exist, stop the migration execution!');
core.setOutput('hasAtLeastOneNewVersionWithoutPR', 'false');
} else {
core.setOutput('hasAtLeastOneNewVersionWithoutPR', 'true');
}
migrate:
if: ${{ needs.upstream.outputs.hasAtLeastOneNewVersionWithoutPR == 'true' }}
runs-on: ubuntu-latest
needs: upstream
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
fetch-depth: 1
- name: setup NPM
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
cache-dependency-path: package-lock.json
- name: "General :: dbpci-install"
run: |
npm ci --ignore-scripts
- name: Migration
shell: bash
env:
IS_JS_AFFECTED: ${{ needs.upstream.outputs.hasNewVersionAvailableJS }}
PACKAGE_VERSION_JS: ${{ needs.upstream.outputs.latestVersionAvailableJS }}
BRANCH_TO_CREATE: "upstream-dependencies"
run: |
migrateDependenciesJS() {
echo "Update JS dependencies to: ${PACKAGE_VERSION_JS}"
echo "Calling migration JS"
npx nx migrate @alfresco/js-api@${PACKAGE_VERSION_JS}
echo "Migration JS done"
}
migrateLibDependenciesJS() {
eval projects=( "cli"
"core"
"content-services"
"process-services"
"process-services-cloud"
"insights"
"testing"
"extensions" )
projectslength=${#projects[@]}
for (( i=0; i<${projectslength}; i++ ));
do
echo "Update JS dependencies in adf-${projects[$i]} to: ${PACKAGE_VERSION_JS}"
DESTDIR="lib/${projects[$i]}"
sed -i "${sedi[@]}" "s/\"@alfresco\/js-api\": \".*\"/\"@alfresco\/js-api\": \">=${PACKAGE_VERSION_JS}\"/g" ${DESTDIR}/package.json
done
}
regeneratePackageLock() {
echo "Regenerate lock"
npm i --package-lock-only
echo "Package-lock done."
}
if git checkout ${BRANCH_TO_CREATE} 2>/dev/null ; then
git reset --hard origin/develop
echo "Reset branch"
fi
if [[ "$IS_JS_AFFECTED" == "true" ]]; then
migrateDependenciesJS
migrateLibDependenciesJS
fi
regeneratePackageLock
- name: Commit Code
if: ${{ needs.upstream.outputs.hasAtLeastOneNewVersion == 'true' }}
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "[ci:force][auto-commit] Update dependencies JS:${{ needs.upstream.outputs.latestVersionAvailableJS }}"
branch: upstream-dependencies
push_options: '--force'
create_branch: true
- name: Create a Pull request
uses: actions/github-script@v6
env:
PACKAGE_VERSION_JS: ${{ needs.upstream.outputs.latestVersionAvailableJS }}
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const { PACKAGE_VERSION_JS } = process.env
const BRANCH_TO_CREATE = 'upstream-dependencies';
const { data: prs } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${context.repo.owner}:${BRANCH_TO_CREATE}`,
base: 'develop'
});
if (prs.length < 1) {
const payloadPullRequest = {
owner: context.repo.owner,
repo: context.repo.repo,
title: `GH Auto: Upstream dependencies JS-API:${PACKAGE_VERSION_JS}`,
head: `${context.repo.owner}:${BRANCH_TO_CREATE}`,
base: 'develop',
body: `Automatic PR`
};
console.log('Payload: ',payloadPullRequest);
const { data: pr } = await github.rest.pulls.create(payloadPullRequest);
return pr.number;
} else {
const upstreamPrOpen = prs[0];
// override the title to contains the latest js dep number
const payloadUpdatePullRequest = {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: upstreamPrOpen.number,
title: `GH Auto: Upstream dependencies JS-API:${PACKAGE_VERSION_JS}`,
};
await github.rest.pulls.update(payloadUpdatePullRequest);
return upstreamPrOpen.number;
}
console.log(`Trigger a dispatch event for the monorepo`);
-1
View File
@@ -35,4 +35,3 @@ licenses.txt
.DS_Store
.angular
NX
.nx
+1 -2
View File
@@ -1,5 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
export NODE_OPTIONS=--max_old_space_size=8192
npx lint-staged
npm run affected:lint
-4
View File
@@ -1,4 +0,0 @@
{
"*.{ts,js}": ["prettier --write", "eslint"],
"*.{css,scss}": ["prettier --write", "stylelint --fix"]
}
+1 -1
View File
@@ -1 +1 @@
18.20.3
18
+4 -7
View File
@@ -1,10 +1,7 @@
module.exports = {
framework: {
name: '@storybook/angular',
options: {}
},
staticDirs: [{ from: '../../../demo-shell/src/app.config.json', to: 'app.config.json' }],
docs: {},
stories: [],
addons: ['@chromatic-com/storybook']
addons: ['@storybook/addon-essentials'],
framework: '@storybook/angular',
staticDirs: [ { from: '../../../demo-shell/src/app.config.json', to: 'app.config.json' } ],
core: { builder: 'webpack5' }
};
-1
View File
@@ -2,4 +2,3 @@ export const parameters = {
docs: { inlineStories: true },
controls: { expanded: true }
};
export const tags = ['autodocs'];
-65
View File
@@ -1,65 +0,0 @@
{
"extends": ["stylelint-config-standard-scss"],
"rules": {
"color-function-notation": "legacy",
"alpha-value-notation": "number",
"color-no-invalid-hex": true,
"function-calc-no-unspaced-operator": true,
"function-name-case": "lower",
"function-url-quotes": "always",
"function-url-scheme-disallowed-list": [
"data"
],
"length-zero-no-unit": true,
"string-no-newline": true,
"unit-no-unknown": true,
"unit-allowed-list": [
"px",
"%",
"deg",
"ms",
"em",
"vh",
"vw",
"vmin",
"s",
"rem"
],
"shorthand-property-no-redundant-values": true,
"declaration-no-important": true,
"no-duplicate-at-import-rules": true,
"declaration-block-no-duplicate-properties": [
true,
{
"ignore": [
"consecutive-duplicates-with-different-values"
]
}
],
"declaration-block-single-line-max-declarations": 1,
"declaration-property-value-disallowed-list": [
{
"/.*/": [
"initial"
]
},
{
"message": "The `initial` value is not supported in IE."
}
],
"selector-pseudo-element-colon-notation": "double",
"selector-pseudo-element-no-unknown": [true, {
"ignorePseudoElements": ["ng-deep"]
}],
"selector-type-case": "lower",
"selector-max-id": 0,
"selector-class-pattern": [
"^_?(adf|adf-|app|app-|example-|demo-|textLayer|canvasWrapper|page)",
{
"resolveNestedSelectors": true
}
],
"scss/dollar-variable-empty-line-before": null,
"scss/at-rule-conditional-no-parentheses": null
}
}
+1 -1
View File
@@ -10,7 +10,7 @@
"name": "e2e",
"program": "${workspaceFolder}/node_modules/protractor/bin/protractor",
"args": [
"./e2e/protractor.conf.js",
"`${workspaceFolder}/.vscode/closest-config-finder.sh ${file} e2e/protractor.conf.js`",
"--specs=${file}"
],
"envFile": "${workspaceFolder}/.env",
+3 -4
View File
@@ -22,15 +22,14 @@
"css.validate": false,
"scss.validate": false,
"stylelint.config": {
"extends": "./.stylelintrc.json"
"extends": "./stylelint-config"
},
"stylelint.configFile": ".stylelintrc.json",
"stylelint.configFile": "stylelint-config.json",
"stylelint.validate": [
"css",
"less",
"postcss",
"scss"
],
"editor.guides.indentation": true,
"typescript.tsdk": "node_modules/typescript/lib"
"editor.guides.indentation": true
}
+6 -3
View File
@@ -45,11 +45,14 @@ Note: If you need more information about how to sync your fork, see [this page](
## Code style
The code style for ADF follows the [Angular style guide](https://angular.io/guide/styleguide) plus some internal rules.
You dont have to worry too much about those rules because they are automatically checked by tslint/codelyzer/adf-rules.
If your code is not compliant with one of these rules you will see an error when you build the project along with some help on how to fix it.
The codebase is also checked with:
The ADF-Rules are as follows:
- ESLint tool
- Stylelint tool
* File name component/directive cannot start with Alfresco/Activiti/adf - this rule is to help developers find files easily
* Class names cannot start with Alfresco/Activiti/adf for the same reason as above
* scss is mandatory. All the classes need to have the `adf-` prefix
## Test guide
+5
View File
@@ -4,6 +4,10 @@ FROM node:18.16-alpine3.17 AS builder
WORKDIR /usr/src/alfresco
COPY package.json package.json
RUN mkdir -p ./licenses && \
yarn licenses list > ./licenses/licenses.txt && \
yarn licenses generate-disclaimer > ./licenses/disclaimer.txt
# 2. Generate image
FROM nginxinc/nginx-unprivileged:1.21-alpine
@@ -19,6 +23,7 @@ COPY docker/docker-entrypoint.d/* /docker-entrypoint.d/
COPY dist/$PROJECT_NAME /usr/share/nginx/html/
COPY dist/$PROJECT_NAME/app.config.json /etc/nginx/templates/app.config.json.template
COPY --from=builder /usr/src/alfresco/licenses /usr/share/nginx/html/
USER root
RUN chmod a+w -R /etc/nginx/conf.d
+1074
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

+4 -8
View File
@@ -1,5 +1,5 @@
{
"version": "0.2",
"version": "0.1",
"language": "en",
"words": [
"activiti",
@@ -77,6 +77,7 @@
"lastname",
"listgrid",
"mapitem",
"markdownlint",
"mimetype",
"mincount",
"minlength",
@@ -90,7 +91,6 @@
"numbervisibilityprocess",
"OAUTHCONFIG",
"oidc",
"overridable",
"pdfjs",
"penta",
"printf",
@@ -138,14 +138,10 @@
"waypoint",
"waypoints",
"webm",
"webscript",
"Whitespaces",
"xdescribe",
"xsrf",
"BPMECM",
"berseria",
"zestiria",
"validatable",
"edjs"
"xsrf"
],
"dictionaries": [
"html",
+44 -42
View File
@@ -21,35 +21,35 @@
* - Delete and reinstall your node_modules
*/
const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const isWindows = os.platform() === 'win32';
const output = require('nx/src/utils/output').output;
const fs = require("fs");
const os = require("os");
const cp = require("child_process");
const isWindows = os.platform() === "win32";
const { output } = require("@nrwl/workspace");
/**
* Paths to files being patched
*/
const angularCLIInitPath = 'node_modules/@angular/cli/lib/cli/index.js';
const angularCLIInitPath = "node_modules/@angular/cli/lib/cli/index.js";
/**
* Patch index.js to warn you if you invoke the undecorated Angular CLI.
*/
function patchAngularCLI(initPath) {
const angularCLIInit = fs.readFileSync(initPath, 'utf-8').toString();
const angularCLIInit = fs.readFileSync(initPath, "utf-8").toString();
if (!angularCLIInit.includes('NX_CLI_SET')) {
fs.writeFileSync(
initPath,
`
if (!angularCLIInit.includes("NX_CLI_SET")) {
fs.writeFileSync(
initPath,
`
if (!process.env['NX_CLI_SET']) {
const { output } = require('@nx/workspace');
const { output } = require('@nrwl/workspace');
output.warn({ title: 'The Angular CLI was invoked instead of the Nx CLI. Use "npx ng [command]" or "nx [command]" instead.' });
}
${angularCLIInit}
`
);
}
);
}
}
/**
@@ -57,37 +57,39 @@ ${angularCLIInit}
* invoke the Nx CLI and get the benefits of computation caching.
*/
function symlinkNgCLItoNxCLI() {
try {
const ngPath = './node_modules/.bin/ng';
const nxPath = './node_modules/.bin/nx';
if (isWindows) {
/**
* This is the most reliable way to create symlink-like behavior on Windows.
* Such that it works in all shells and works with npx.
*/
['', '.cmd', '.ps1'].forEach((ext) => {
fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext));
});
} else {
// If unix-based, symlink
cp.execSync(`ln -sf ./nx ${ngPath}`);
}
} catch (e) {
output.error({
title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message
});
throw e;
try {
const ngPath = "./node_modules/.bin/ng";
const nxPath = "./node_modules/.bin/nx";
if (isWindows) {
/**
* This is the most reliable way to create symlink-like behavior on Windows.
* Such that it works in all shells and works with npx.
*/
["", ".cmd", ".ps1"].forEach(ext => {
fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext));
});
} else {
// If unix-based, symlink
cp.execSync(`ln -sf ./nx ${ngPath}`);
}
} catch (e) {
output.error({
title:
"Unable to create a symlink from the Angular CLI to the Nx CLI:" +
e.message
});
throw e;
}
}
try {
symlinkNgCLItoNxCLI();
patchAngularCLI(angularCLIInitPath);
output.log({
title: 'Angular CLI has been decorated to enable computation caching.'
});
symlinkNgCLItoNxCLI();
patchAngularCLI(angularCLIInitPath);
output.log({
title: "Angular CLI has been decorated to enable computation caching."
});
} catch (e) {
output.error({
title: 'Decoration of the Angular CLI did not complete successfully'
});
output.error({
title: "Decoration of the Angular CLI did not complete successfully"
});
}
+1 -1
View File
@@ -49,7 +49,7 @@ npm start
This command compiles and starts the project in watch mode.
Browser will automatically reload upon changes.
Upon start, you can navigate to `http://localhost:3000` with your preferred browser.
Upon start you can navigate to `http://localhost:3000` with your preferred browser.
### Important notes
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -15,16 +15,17 @@
* limitations under the License.
*/
import { Node } from './node';
import { MyAppPage } from './app.po';
export class NodeEntry {
entry: Node;
describe('MyApp App', () => {
let page: MyAppPage;
constructor(input?: Partial<NodeEntry>) {
if (input) {
Object.assign(this, input);
this.entry = input.entry ? new Node(input.entry) : undefined;
}
}
beforeEach(() => {
page = new MyAppPage();
});
}
it('should display toolbar', () => {
page.navigateTo();
expect(page.getToolbar()).toBeDefined();
});
});
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -15,14 +15,14 @@
* limitations under the License.
*/
export class ChildAssociation {
childId: string;
assocType: string;
import { browser, element, by } from 'protractor';
constructor(input?: Partial<ChildAssociation>) {
if (input) {
Object.assign(this, input);
}
export class MyAppPage {
navigateTo() {
return browser.get('/');
}
getToolbar() {
return element(by.tagName('adf-toolbar'));
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": ["jasmine", "jasminewd2", "node"]
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "Alfresco-ADF-Angular-Demo",
"description": "Demo shell for Alfresco Angular components",
"version": "6.9.0",
"version": "6.3.0",
"author": "Hyland Software, Inc. and its affiliates",
"repository": {
"type": "git",
-201
View File
@@ -1,201 +0,0 @@
{
"name": "demoshell",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "demo-shell/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"minimatch",
"minimatch-browser",
"superagent",
"event-emitter",
"brace-expansion",
"zen-observable",
"subscriptions-transport-ws",
"d",
"chart.js",
"cropperjs"
],
"outputPath": "dist/demo-shell",
"index": "demo-shell/src/index.html",
"main": "demo-shell/src/main.ts",
"tsConfig": "tsconfig.dev.json",
"polyfills": "demo-shell/src/polyfills.ts",
"stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"]
},
"assets": [
"demo-shell/src/assets",
"demo-shell/src/favicon-96x96.png",
"demo-shell/src/app.config.json",
{
"glob": "**/*",
"input": "demo-shell/src/assets",
"output": "/assets"
},
{
"glob": "app.config.json",
"input": "demo-shell/src",
"output": "/"
},
{
"glob": "**/*",
"input": "demo-shell/resources",
"output": "/resources"
},
{
"glob": "**/*",
"input": "lib/core/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/process-services/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/process-services-cloud/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/content-services/src/lib/assets",
"output": "/assets"
},
{
"glob": "**/*",
"input": "lib/core/src/lib/i18n",
"output": "/assets/adf-core/i18n"
},
{
"glob": "**/*",
"input": "lib/content-services/src/lib/i18n",
"output": "/assets/adf-content-services/i18n"
},
{
"glob": "**/*",
"input": "lib/process-services/src/lib/i18n",
"output": "/assets/adf-process-services/i18n"
},
{
"glob": "**/*",
"input": "lib/process-services-cloud/src/lib/i18n",
"output": "/assets/adf-process-services-cloud/i18n"
},
{
"glob": "**/*",
"input": "lib/insights/src/lib/i18n",
"output": "/assets/adf-insights/i18n"
},
{
"glob": "pdf.worker.min.js",
"input": "node_modules/pdfjs-dist/build",
"output": "/"
},
{
"glob": "**/*",
"input": "node_modules/monaco-editor",
"output": "/assets/monaco/"
}
],
"styles": [
"demo-shell/src/styles.scss",
"demo-shell/src/custom-style-dev.scss",
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"scripts": ["node_modules/pdfjs-dist/build/pdf.js", "node_modules/pdfjs-dist/web/pdf_viewer.js", "node_modules/raphael/raphael.min.js"],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": false,
"sourceMap": true,
"optimization": false,
"namedChunks": true
},
"configurations": {
"production": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "12kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"buildOptimizer": true,
"verbose": false,
"fileReplacements": [
{
"replace": "demo-shell/src/environments/environment.ts",
"with": "demo-shell/src/environments/environment.prod.ts"
}
]
},
"canary": {
"fileReplacements": [
{
"replace": "demo-shell/src/environments/environment.ts",
"with": "demo-shell/src/environments/environment.canary.ts"
}
]
},
"e2e": {
"budgets": [
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"buildOptimizer": true,
"verbose": false,
"fileReplacements": [
{
"replace": "demo-shell/src/environments/environment.ts",
"with": "demo-shell/src/environments/environment.e2e.ts"
}
]
}
},
"defaultConfiguration": ""
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "demoshell:build",
"host": "0.0.0.0",
"port": 3000,
"proxyConfig": "demo-shell/proxy.conf.js",
"disableHostCheck": true
},
"configurations": {
"production": {
"browserTarget": "demoshell:build:production"
},
"canary": {
"browserTarget": "demoshell:build:canary"
},
"e2e": {
"browserTarget": "demoshell:build:e2e"
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": ["demo-shell/**/*.ts", "demo-shell/**/*.html"]
}
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

+21 -11
View File
@@ -1,5 +1,5 @@
{
"$schema": "../../lib/core/src/lib/app-config/app.config.schema.json",
"$schema": "../../lib/core/src/lib/app-config/schema.json",
"ecmHost": "{protocol}//{hostname}{:port}",
"bpmHost": "{protocol}//{hostname}{:port}",
"identityHost": "{protocol}//{hostname}{:port}/auth/admin/realms/alfresco",
@@ -20,8 +20,7 @@
"clientId": "alfresco",
"scope": "openid profile email",
"secret": "",
"implicitFlow": false,
"codeFlow": true,
"implicitFlow": true,
"silentLogin": true,
"redirectSilentIframeUri": "{protocol}//{hostname}{:port}/assets/silent-refresh.html",
"redirectUri": "/",
@@ -35,7 +34,7 @@
"application": {
"storagePrefix": "ADF",
"name": "Alfresco ADF Application",
"copyright": "© 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved."
"copyright": "© 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved."
},
"notifications": true,
"search": [{
@@ -310,12 +309,25 @@
}
}
},
{
"id": "createdDateRange",
"name": "Created Date (range)",
"enabled": true,
"component": {
"selector": "date-range",
"settings": {
"field": "cm:created",
"dateFormat": "DD-MMM-YY",
"maxDate": "today"
}
}
},
{
"id": "createdModifiedDateRange",
"name": "Date",
"enabled": true,
"component": {
"selector": "date-range",
"selector": "date-range-advanced",
"settings": {
"dateFormat": "dd-MMM-yy",
"maxDate": "today",
@@ -622,7 +634,7 @@
"unit": "Byte",
"field": "cm:content.size",
"min": 0,
"max": 4000,
"max": 18,
"step": 1,
"thumbLabel": true
}
@@ -733,17 +745,15 @@
{
"id": "createdDateRange",
"name": "SEARCH.SEARCH_HEADER.FILTERS.DATE.TITLE",
"columnKey": "createdAt",
"enabled": true,
"component": {
"selector": "date-range",
"settings": {
"allowUpdateOnChange": false,
"dateFormat": "dd-MMM-yy",
"maxDate": "today",
"field": "cm:created",
"displayedLabelsByField": {
"cm:created": "Created Date"
}
"dateFormat": "DD-MMM-YY",
"maxDate": "today"
}
}
}
+4
View File
@@ -11,3 +11,7 @@ router-outlet[name='overlay'] + * {
height: 100%;
width: 100%;
}
[dir='rtl'] .mat-icon {
transform: scale(-1, 1);
}
+4 -4
View File
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -18,11 +18,11 @@
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import {
AuthenticationService,
AlfrescoApiService,
PageTitleService
} from '@alfresco/adf-core';
import { Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { AdfHttpClient } from '@alfresco/adf-core/api';
@Component({
selector: 'app-root',
@@ -33,7 +33,7 @@ import { AdfHttpClient } from '@alfresco/adf-core/api';
export class AppComponent implements OnInit {
constructor(private pageTitleService: PageTitleService,
private adfHttpClient: AdfHttpClient,
private alfrescoApiService: AlfrescoApiService,
private authenticationService: AuthenticationService,
private router: Router,
private dialogRef: MatDialog) {
@@ -43,7 +43,7 @@ export class AppComponent implements OnInit {
ngOnInit() {
this.pageTitleService.setTitle('title');
this.adfHttpClient.on('error', (error) => {
this.alfrescoApiService.getInstance().on('error', (error) => {
if (error.status === 401) {
if (!this.authenticationService.isLoggedIn()) {
this.dialogRef.closeAll();
+92 -6
View File
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -17,30 +17,77 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgChartsModule } from 'ng2-charts';
import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateModule } from '@ngx-translate/core';
import { AppConfigService, DebugAppConfigService, CoreModule, AuthModule, provideTranslations } from '@alfresco/adf-core';
import {
AppConfigService,
DebugAppConfigService,
CoreModule,
CoreAutomationService,
AuthModule,
provideTranslations
} from '@alfresco/adf-core';
import { ExtensionsModule } from '@alfresco/adf-extensions';
import { AppComponent } from './app.component';
import { MaterialModule } from './material.module';
import { LogoutComponent } from './components/logout/logout.component';
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
import { HomeComponent } from './components/home/home.component';
import { SearchBarComponent } from './components/search/search-bar.component';
import { SearchResultComponent } from './components/search/search-result.component';
import { FormComponent } from './components/form/form.component';
import { ProcessServiceComponent } from './components/process-service/process-service.component';
import { ShowDiagramComponent } from './components/process-service/show-diagram.component';
import { FormViewerComponent } from './components/process-service/form-viewer.component';
import { FormNodeViewerComponent } from './components/process-service/form-node-viewer.component';
import { AppsViewComponent } from './components/process-service/apps-view.component';
import { FilesComponent } from './components/files/files.component';
import { VersionManagerDialogAdapterComponent } from './components/files/version-manager-dialog-adapter.component';
import { MetadataDialogAdapterComponent } from './components/files/metadata-dialog-adapter.component';
import { appRoutes } from './app.routes';
import { TaskAttachmentsComponent } from './components/process-service/task-attachments.component';
import { ProcessAttachmentsComponent } from './components/process-service/process-attachments.component';
import { DemoPermissionComponent } from './components/permissions/demo-permissions.component';
import { MonacoEditorModule } from 'ngx-monaco-editor-v2';
import { ContentModule } from '@alfresco/adf-content-services';
import { InsightsModule } from '@alfresco/adf-insights';
import { ProcessModule } from '@alfresco/adf-process-services';
import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component';
import { CloudLayoutComponent } from './components/cloud/cloud-layout.component';
import { AppsCloudDemoComponent } from './components/cloud/apps-cloud-demo.component';
import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component';
import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component';
import { TaskDetailsCloudDemoComponent } from './components/cloud/task-details-cloud-demo.component';
import { CloudViewerComponent } from './components/cloud/cloud-viewer.component';
import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-details-cloud-demo.component';
import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component';
import { StartProcessCloudDemoComponent } from './components/cloud/start-process-cloud-demo.component';
import { CloudBreadcrumbsComponent } from './components/cloud/cloud-breadcrumb-component';
import { CloudFiltersDemoComponent } from './components/cloud/cloud-filters-demo.component';
import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component';
import { environment } from '../environments/environment';
import { AppCloudSharedModule } from './components/cloud/shared/cloud.shared.module';
import { DemoErrorComponent } from './components/error/demo-error.component';
import { ProcessServicesCloudModule } from '@alfresco/adf-process-services-cloud';
import { RouterModule } from '@angular/router';
import { CoreAutomationService } from '../testing/automation.service';
import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-layout.component';
import { CustomEditorComponent, CustomWidgetComponent } from './components/cloud/custom-form-components/custom-editor.component';
import { SearchFilterChipsComponent } from './components/search/search-filter-chips.component';
import { UserInfoComponent } from './components/app-layout/user-info/user-info.component';
@NgModule({
imports: [
BrowserModule,
environment.e2e ? NoopAnimationsModule : BrowserAnimationsModule,
RouterModule.forRoot(appRoutes, { useHash: true }),
AuthModule.forRoot({ useHash: true }),
ReactiveFormsModule,
RouterModule.forRoot(appRoutes, { useHash: true, relativeLinkResolution: 'legacy' }),
...(environment.oidc ? [AuthModule.forRoot({ useHash: true })] : []),
FormsModule,
HttpClientModule,
MaterialModule,
TranslateModule.forRoot(),
CoreModule.forRoot(),
ContentModule.forRoot(),
@@ -49,9 +96,48 @@ import { CoreAutomationService } from '../testing/automation.service';
ProcessServicesCloudModule.forRoot(),
ExtensionsModule.forRoot(),
NgChartsModule,
AppCloudSharedModule,
MonacoEditorModule.forRoot()
],
declarations: [AppComponent],
declarations: [
AppComponent,
LogoutComponent,
AppLayoutComponent,
UserInfoComponent,
HomeComponent,
SearchBarComponent,
SearchResultComponent,
ProcessServiceComponent,
ShowDiagramComponent,
FormViewerComponent,
FormNodeViewerComponent,
AppsViewComponent,
FilesComponent,
FormComponent,
VersionManagerDialogAdapterComponent,
MetadataDialogAdapterComponent,
TaskAttachmentsComponent,
ProcessAttachmentsComponent,
DemoPermissionComponent,
DemoErrorComponent,
TreeViewSampleComponent,
CloudLayoutComponent,
AppsCloudDemoComponent,
TasksCloudDemoComponent,
ProcessesCloudDemoComponent,
TaskDetailsCloudDemoComponent,
CloudViewerComponent,
ProcessDetailsCloudDemoComponent,
StartTaskCloudDemoComponent,
StartProcessCloudDemoComponent,
CloudBreadcrumbsComponent,
CloudFiltersDemoComponent,
FormCloudDemoComponent,
CustomEditorComponent,
CustomWidgetComponent,
ProcessCloudLayoutComponent,
SearchFilterChipsComponent
],
providers: [
{ provide: AppConfigService, useClass: DebugAppConfigService }, // not use this service in production
provideTranslations('app', 'resources')
+21 -58
View File
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -27,9 +27,10 @@ import { FormNodeViewerComponent } from './components/process-service/form-node-
import { AppsViewComponent } from './components/process-service/apps-view.component';
import { SearchResultComponent } from './components/search/search-result.component';
import { FilesComponent } from './components/files/files.component';
import { AppFormComponent } from './components/form/app-form.component';
import { FormComponent } from './components/form/form.component';
import { DemoPermissionComponent } from './components/permissions/demo-permissions.component';
import { AppComponent } from './app.component';
import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component';
import { AppsCloudDemoComponent } from './components/cloud/apps-cloud-demo.component';
import { CloudLayoutComponent } from './components/cloud/cloud-layout.component';
import { TasksCloudDemoComponent } from './components/cloud/tasks-cloud-demo.component';
@@ -42,20 +43,14 @@ import { ProcessDetailsCloudDemoComponent } from './components/cloud/process-det
import { FormCloudDemoComponent } from './components/app-layout/cloud/form-demo/cloud-form-demo.component';
import { DemoErrorComponent } from './components/error/demo-error.component';
import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-layout.component';
import { AppSearchFilterChipsComponent } from './components/search/search-filter-chips.component';
import { FileViewComponent } from './components/file-view/file-view.component';
import { SettingsComponent } from './components/settings/settings.component';
import { AppLoginComponent } from './components/login/login.component';
import { TaskListDemoComponent } from './components/task-list-demo/task-list-demo.component';
import { ProcessListDemoComponent } from './components/process-list-demo/process-list-demo.component';
import { AppCardViewComponent } from './components/card-view/card-view.component';
import { SearchFilterChipsComponent } from './components/search/search-filter-chips.component';
export const appRoutes: Routes = [
{ path: 'login', component: AppLoginComponent },
{ path: 'login', loadChildren: () => import('./components/login/login.module').then(m => m.AppLoginModule) },
{ path: 'logout', component: LogoutComponent },
{
path: 'settings',
component: SettingsComponent
loadChildren: () => import('./components/settings/settings.module').then(m => m.AppSettingsModule)
},
{
path: 'files/:nodeId/view',
@@ -63,12 +58,7 @@ export const appRoutes: Routes = [
canActivate: [AuthGuardEcm],
canActivateChild: [AuthGuardEcm],
outlet: 'overlay',
children: [
{
path: '',
component: FileViewComponent
}
]
loadChildren: () => import('./components/file-view/file-view.module').then(m => m.FileViewModule)
},
{
path: 'files/:nodeId/:versionId/view',
@@ -76,24 +66,14 @@ export const appRoutes: Routes = [
canActivate: [AuthGuardEcm],
canActivateChild: [AuthGuardEcm],
outlet: 'overlay',
children: [
{
path: '',
component: FileViewComponent
}
]
loadChildren: () => import('./components/file-view/file-view.module').then(m => m.FileViewModule)
},
{
path: 'preview/blob',
component: AppComponent,
outlet: 'overlay',
pathMatch: 'full',
children: [
{
path: '',
component: FileViewComponent
}
]
loadChildren: () => import('./components/file-view/file-view.module').then(m => m.FileViewModule)
},
{
path: '',
@@ -107,12 +87,7 @@ export const appRoutes: Routes = [
},
{
path: 'card-view',
children: [
{
path: '',
component: AppCardViewComponent
}
]
loadChildren: () => import('./components/card-view/card-view.module').then(m => m.AppCardViewModule)
},
{
path: '',
@@ -172,13 +147,14 @@ export const appRoutes: Routes = [
path: 'process-details/:processInstanceId',
component: ProcessDetailsCloudDemoComponent
}
]
}
]
},
{
path: 'settings-layout',
component: SettingsComponent
loadChildren: () => import('./components/settings/settings.module').then(m => m.AppSettingsModule)
},
{
path: 'files',
@@ -202,7 +178,7 @@ export const appRoutes: Routes = [
},
{
path: 'search-filter-chips',
component: AppSearchFilterChipsComponent,
component: SearchFilterChipsComponent,
canActivate: [AuthGuardEcm]
},
{
@@ -269,35 +245,22 @@ export const appRoutes: Routes = [
component: DemoPermissionComponent,
canActivate: [AuthGuardEcm]
},
{
path: 'treeview',
component: TreeViewSampleComponent,
canActivate: [AuthGuardEcm]
},
{ path: 'form-cloud', component: FormCloudDemoComponent },
{ path: 'form', component: AppFormComponent },
{ path: 'form', component: FormComponent },
{
path: 'task-list',
canActivate: [AuthGuardBpm],
children: [
{
path: '',
component: TaskListDemoComponent
},
{
path: ':id',
component: TaskListDemoComponent
}
]
loadChildren: () => import('./components/task-list-demo/task-list.module').then(m => m.AppTaskListModule)
},
{
path: 'process-list',
canActivate: [AuthGuardBpm],
children: [
{
path: '',
component: ProcessListDemoComponent
},
{
path: ':id',
component: ProcessListDemoComponent
}
]
loadChildren: () => import('./components/process-list-demo/process-list.module').then(m => m.AppProcessListModule)
},
{
path: 'error/no-authorization',
@@ -18,30 +18,18 @@
<app-search-bar></app-search-bar>
<app-shell-user-info [menuPositionX]="'before'" [menuPositionY]="'above'"></app-shell-user-info>
<adf-avatar
size="32px"
src="https://avatars.githubusercontent.com/u/503991?v=4&size=64"
initials="DV"
tooltip="Denys Vuika"
cursor="pointer"
[matMenuTriggerFor]="userMenu">
</adf-avatar>
<mat-menu #userMenu="matMenu">
<button mat-menu-item>Item 1</button>
<button mat-menu-item>Item 2</button>
</mat-menu>
</adf-layout-header>
</ng-template>
</adf-sidenav-layout-header>
<adf-sidenav-layout-navigation>
<ng-template>
<ng-template let-isMenuMinimized="isMenuMinimized">
<mat-nav-list class="app-sidenav-linklist">
<ng-container *ngFor="let link of links">
<ng-container *ngIf="link.children">
<mat-list-item (click)="trigger.openMenu()" [attr.data-automation-id]="link.title | translate" class="app-sidenav-link">
<mat-icon matListItemIcon>{{link.icon}}</mat-icon>
<span matLine>{{ link.title | translate }}</span>
<mat-icon matListIcon>{{link.icon}}</mat-icon>
<span matLine *ngIf="!isMenuMinimized()">{{link.title | translate }}</span>
<mat-icon class="app-sidenav-link__expand-button" [matMenuTriggerData]="{links: link.children}"
rippleTrigger mat-icon-button #trigger="matMenuTrigger"
[matMenuTriggerFor]="nestedMenu">arrow_right</mat-icon>
@@ -52,15 +40,15 @@
<mat-list-item [routerLink]="link.href"
routerLinkActive="app-sidenav-link--active" [routerLinkActiveOptions]="{ exact: true }"
[attr.data-automation-id]="link.title | translate" class="app-sidenav-link">
<mat-icon matListItemIcon >{{link.icon}}</mat-icon>
<span matLine>{{link.title | translate }}</span>
<mat-icon matListIcon >{{link.icon}}</mat-icon>
<span matLine *ngIf="!isMenuMinimized()">{{link.title | translate }}</span>
</mat-list-item>
</ng-container>
</ng-container>
<mat-list-item adf-logout [enableRedirect]="enableRedirect" redirectUri="/logout" class="app-sidenav-link" data-automation-id="Logout" >
<mat-icon matListItemIcon>exit_to_app</mat-icon>
<span matLine>Logout</span>
<mat-icon matListIcon>exit_to_app</mat-icon>
<span matLine *ngIf="!isMenuMinimized()">Logout</span>
</mat-list-item>
</mat-nav-list>
@@ -84,7 +72,7 @@
[routerLink]="link.href"
[routerLinkActiveOptions]="{ exact: true }">
<mat-icon matListItemIcon>{{link.icon}}</mat-icon>
<mat-icon matListIcon>{{link.icon}}</mat-icon>
{{ link.title | translate }}
</button>
</ng-template>
@@ -1,3 +1,7 @@
adf-file-uploading-dialog {
z-index: 1100;
}
.app-layout {
display: flex;
flex: 1;
@@ -8,7 +12,25 @@
color: var(--theme-primary-color);
}
.app-sidenav-link {
.mat-list-text {
font-size: 14px;
white-space: nowrap;
min-width: 120px;
padding: 0 10px;
}
}
&-menu-spacer {
flex: 1 1 auto;
}
}
mat-sidenav-content > div {
display: flex;
height: 100%;
> div {
flex: auto;
}
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,50 +16,9 @@
*/
import { Component, ViewEncapsulation } from '@angular/core';
import {
AlfrescoApiService,
AvatarComponent,
HeaderLayoutComponent,
LogoutDirective,
SidenavLayoutComponent,
SidenavLayoutContentDirective,
SidenavLayoutHeaderDirective,
SidenavLayoutNavigationDirective
} from '@alfresco/adf-core';
import { SearchBarComponent } from '../search/search-bar.component';
import { UserInfoComponent } from './user-info/user-info.component';
import { MatMenuModule } from '@angular/material/menu';
import { MatListModule } from '@angular/material/list';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatLineModule } from '@angular/material/core';
import { CommonModule } from '@angular/common';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import { FileUploadingDialogComponent } from '@alfresco/adf-content-services';
import { AlfrescoApiService } from '@alfresco/adf-core';
@Component({
standalone: true,
imports: [
CommonModule,
SidenavLayoutComponent,
SidenavLayoutHeaderDirective,
HeaderLayoutComponent,
SearchBarComponent,
UserInfoComponent,
AvatarComponent,
MatMenuModule,
SidenavLayoutNavigationDirective,
MatListModule,
TranslateModule,
MatIconModule,
MatLineModule,
RouterLink,
RouterLinkActive,
LogoutDirective,
SidenavLayoutContentDirective,
RouterOutlet,
FileUploadingDialogComponent
],
templateUrl: './app-layout.component.html',
styleUrls: ['./app-layout.component.scss'],
host: { class: 'app-layout' },
@@ -72,26 +31,19 @@ export class AppLayoutComponent {
{ href: '/card-view', icon: 'view_headline', title: 'CardView' },
{ href: '/task-list', icon: 'assignment', title: 'Task List' },
{
href: '/cloud',
icon: 'cloud',
title: 'Process Cloud',
children: [
href: '/cloud', icon: 'cloud', title: 'Process Cloud', children: [
{ href: '/cloud/', icon: 'cloud', title: 'Home' },
{ href: '/form-cloud', icon: 'poll', title: 'Form' }
]
},
{
href: '/activiti',
icon: 'device_hub',
title: 'Process Services',
children: [
{ href: '/activiti', icon: 'vpn_key', title: 'App' },
{ href: '/process-list', icon: 'assignment', title: 'Process List' },
{ href: '/form', icon: 'poll', title: 'Form' }
]
},
{ href: '/activiti', icon: 'device_hub', title: 'Process Services', children: [
{ href: '/activiti', icon: 'vpn_key', title: 'App' },
{ href: '/process-list', icon: 'assignment', title: 'Process List' },
{ href: '/form', icon: 'poll', title: 'Form' }
]},
{ href: '/login', icon: 'vpn_key', title: 'Login' },
{ href: '/settings-layout', icon: 'settings', title: 'Settings' }
{ href: '/settings-layout', icon: 'settings', title: 'Settings' },
{ href: '/treeview', icon: 'nature', title: 'Tree View' }
];
enableRedirect = true;
@@ -10,7 +10,7 @@
</adf-cloud-form>
</div>
<div class="app-console">
<div class="app-console" #console>
<h3>Error log:</h3>
<p *ngFor="let error of errorFields">Error {{ error.name }} {{error.validationSummary.message | translate}}</p>
</div>
@@ -1,5 +1,3 @@
@import 'styles/mat-selectors';
.app-form-container {
padding: 10px;
}
@@ -29,13 +27,13 @@
}
.app-form-config-editor {
height: 500px;
height: 500px !important;
}
.app-form-editor-buttons {
display: flex;
flex-direction: row;
column-gap: 4px;
& > .mat-raised-button {
margin-right: 5px;
}
}
.app-upload-config-button {
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,27 +16,32 @@
*/
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormFieldModel, FormModel, FormRenderingService, NotificationService } from '@alfresco/adf-core';
import { CloudFormRenderingService, FormCloudModule, FormCloudService } from '@alfresco/adf-process-services-cloud';
import {
CoreAutomationService,
FormFieldModel,
FormModel,
FormRenderingService,
NotificationService
} from '@alfresco/adf-core';
import {
CloudFormRenderingService,
FormCloudService
} from '@alfresco/adf-process-services-cloud';
import { Subscription } from 'rxjs';
import { CustomEditorComponent, CustomWidgetComponent } from '../../../cloud/custom-form-components/custom-editor.component';
import { CoreAutomationService } from '../../../../../testing/automation.service';
import { CommonModule } from '@angular/common';
import { MatTabsModule } from '@angular/material/tabs';
import { MonacoEditorModule } from 'ngx-monaco-editor-v2';
import { TranslateModule } from '@ngx-translate/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import {
CustomEditorComponent,
CustomWidgetComponent
} from '../../../cloud/custom-form-components/custom-editor.component';
@Component({
templateUrl: './cloud-form-demo.component.html',
standalone: true,
imports: [CommonModule, MatTabsModule, FormCloudModule, MonacoEditorModule, TranslateModule, FormsModule, MatButtonModule, MatIconModule],
styleUrls: ['./cloud-form-demo.component.scss'],
providers: [{ provide: FormRenderingService, useClass: CloudFormRenderingService }]
providers: [
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
]
})
export class FormCloudDemoComponent implements OnInit, OnDestroy {
form: FormModel;
errorFields: FormFieldModel[] = [];
formConfig: string;
@@ -56,8 +61,7 @@ export class FormCloudDemoComponent implements OnInit, OnDestroy {
private notificationService: NotificationService,
private formService: FormCloudService,
private automationService: CoreAutomationService,
private formRenderingService: FormRenderingService
) {
private formRenderingService: FormRenderingService) {
this.formRenderingService.register({
'demo-widget': () => CustomEditorComponent,
'custom-editor': () => CustomEditorComponent,
@@ -1,101 +0,0 @@
<div
id="userinfo_container"
[class.adf-userinfo-name-right]="showOnRight"
(keyup)="onKeyPress($event)"
tabindex="0"
role="button"
class="adf-userinfo-container"
*ngIf="canShow"
>
<span *ngIf="showName" id="adf-userinfo-ecm-name-display" class="adf-userinfo-name">
{{ecmUser | fullName}}
</span>
<button mat-button [matMenuTriggerFor]="menu" class="adf-userinfo-menu_button adf-content-userinfo-button"
data-automation-id="adf-user-profile">
<div class="adf-userinfo-button-profile" id="user-profile">
<div *ngIf="identityUser; else showEcmUserImage" id="identity-user-image">
<div *ngIf="ecmUser?.avatarId; else initialTemplate">
<div class="adf-userinfo-profile-container">
<img id="logged-user-img" [src]="getEcmAvatar(ecmUser.avatarId)" alt="user-info-profile-button"
class="adf-userinfo-profile-image"/>
</div>
</div>
<ng-template #initialTemplate>
<div [innerHTML]="identityUser | usernameInitials:'adf-userinfo-pic'"></div>
</ng-template>
</div>
<ng-template #showEcmUserImage>
<div id="ecm-user-image">
<div *ngIf="ecmUser.avatarId; else initialTemplate" class="adf-userinfo-profile-container">
<img id="logged-user-img" [src]="getEcmAvatar(ecmUser.avatarId)" alt="user-info-profile-button"
class="adf-userinfo-profile-image"/>
</div>
<ng-template #initialTemplate>
<div [outerHTML]="ecmUser | usernameInitials:'adf-userinfo-pic'"></div>
</ng-template>
</div>
</ng-template>
</div>
</button>
<mat-menu #menu="matMenu" id="user-profile-lists" [xPosition]="menuPositionX" [yPosition]="menuPositionY"
[overlapTrigger]="false" class="adf-userinfo-menu">
<mat-card appearance="outlined" *ngIf="mode === userInfoMode.CONTENT" class="adf-userinfo-card adf-content-userinfo-card">
<mat-card-header class="adf-userinfo-card-header" [style.background-image]="'url(' + ecmBackgroundImage + ')'">
<div *ngIf="ecmUser.avatarId; else initialTemplate"
class="adf-userinfo-profile-container adf-hide-small">
<img class="adf-userinfo-profile-picture" id="ecm-user-detail-image"
alt="ecm-profile-image" [src]="getEcmAvatar(ecmUser.avatarId)"/>
</div>
<ng-template #initialTemplate>
<div
[outerHTML]="ecmUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
</ng-template>
<div class="mat-headline-6" id="ecm-username">{{ecmUser | fullName}}</div>
</mat-card-header>
<mat-card-content>
<div class="adf-userinfo-supporting-text">
<div class="adf-userinfo-detail">
<h2 id="ecm-full-name"
class="adf-userinfo__detail-title">{{ecmUser | fullName}}</h2>
<span id="ecm-email"> {{ecmUser.email}} </span>
<a href="#/profile">{{ 'USER_PROFILE.LABELS.MY_PROFILE' | translate }}</a>
</div>
<div class="adf-userinfo-detail">
<span class="adf-userinfo__secondary-info" id="ecm-job-title-label">
{{ 'USER_PROFILE.LABELS.ECM.JOB_TITLE' | translate }}
<span id="ecm-job-title"> {{ ecmUser.jobTitle ? ecmUser.jobTitle : 'N/A' }} </span>
</span>
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card appearance="outlined" *ngIf="mode === userInfoMode.CONTENT_SSO" class="adf-userinfo-card adf-content-userinfo-card">
<mat-card-header class="adf-userinfo-card-header"
[style.background-image]="'url(' + bpmBackgroundImage + ')'">
<div *ngIf="ecmUser.avatarId; else initialTemplate"
class="adf-userinfo-profile-container adf-hide-small">
<img class="adf-userinfo-profile-picture" id="ecm-user-detail-image"
alt="ecm-profile-image" [src]="getEcmAvatar(ecmUser.avatarId)"/>
</div>
<ng-template #initialTemplate>
<div
[outerHTML]="identityUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
</ng-template>
<div class="mat-headline-6" id="identity-username">{{identityUser | fullName}}</div>
</mat-card-header>
<mat-card-content>
<div class="adf-userinfo-supporting-text">
<div class="adf-userinfo-detail">
<h2 id="identity-full-name"
class="adf-userinfo__detail-title">{{identityUser | fullName}}</h2>
<span id="identity-email"> {{identityUser.email}} </span>
<a href="#/profile">
{{ 'USER_PROFILE.LABELS.MY_PROFILE' | translate }}</a>
</div>
</div>
</mat-card-content>
</mat-card>
</mat-menu>
</div>
@@ -1,21 +1,21 @@
<ng-container>
<adf-content-user-info
<adf-content-user-info
*ngIf="mode === userInfoMode.CONTENT || mode === userInfoMode.CONTENT_SSO"
[ecmUser]="ecmUser$ | async"
[identityUser]="identityUser$ | async"
[isLoggedIn]="isLoggedIn"
[mode]="mode"
></adf-content-user-info>
<adf-identity-user-info
<adf-identity-user-info
*ngIf="mode === userInfoMode.SSO"
[identityUser]="identityUser$ | async"
[isLoggedIn]="isLoggedIn"
></adf-identity-user-info>
<adf-process-user-info
<adf-process-user-info
*ngIf="mode === userInfoMode.PROCESS || mode === userInfoMode.ALL"
[bpmUser]="bpmUser$ | async"
[ecmUser]="ecmUser$ | async"
[isLoggedIn]="isLoggedIn"
[mode]="mode"
></adf-process-user-info>
</ng-container>
</ng-container>
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,30 +16,18 @@
*/
import { EcmUserModel, PeopleContentService } from '@alfresco/adf-content-services';
import { PeopleProcessService } from '@alfresco/adf-process-services';
import {
AuthenticationService,
BasicAlfrescoAuthService,
IdentityUserInfoComponent,
IdentityUserModel,
IdentityUserService,
UserInfoMode
} from '@alfresco/adf-core';
import { BpmUserModel, PeopleProcessService } from '@alfresco/adf-process-services';
import { AuthenticationService, IdentityUserModel, IdentityUserService, UserInfoMode } from '@alfresco/adf-core';
import { Component, OnInit, Input } from '@angular/core';
import { MenuPositionX, MenuPositionY } from '@angular/material/menu';
import { Observable, of } from 'rxjs';
import { CommonModule } from '@angular/common';
import { UserRepresentation } from '@alfresco/js-api';
import { ContentUserInfoComponent } from './content-user-info';
import { ProcessUserInfoComponent } from './process-user-info';
@Component({
selector: 'app-shell-user-info',
standalone: true,
imports: [CommonModule, ContentUserInfoComponent, IdentityUserInfoComponent, ProcessUserInfoComponent],
templateUrl: './user-info.component.html'
})
export class UserInfoComponent implements OnInit {
/** Custom choice for opening the menu at the bottom. Can be `before` or `after`. */
@Input()
menuPositionX: MenuPositionX = 'after';
@@ -50,17 +38,16 @@ export class UserInfoComponent implements OnInit {
mode: UserInfoMode;
ecmUser$: Observable<EcmUserModel>;
bpmUser$: Observable<UserRepresentation>;
bpmUser$: Observable<BpmUserModel>;
identityUser$: Observable<IdentityUserModel>;
selectedIndex: number;
userInfoMode = UserInfoMode;
constructor(
private peopleContentService: PeopleContentService,
private peopleProcessService: PeopleProcessService,
private identityUserService: IdentityUserService,
private basicAlfrescoAuthService: BasicAlfrescoAuthService,
private authService: AuthenticationService
) { /* empty */ }
constructor(private peopleContentService: PeopleContentService,
private peopleProcessService: PeopleProcessService,
private identityUserService: IdentityUserService,
private authService: AuthenticationService) {
}
ngOnInit() {
this.getUserInfo();
@@ -75,6 +62,7 @@ export class UserInfoComponent implements OnInit {
this.mode = UserInfoMode.CONTENT_SSO;
this.loadEcmUserInfo();
}
} else if (this.isAllLoggedIn()) {
this.loadEcmUserInfo();
this.loadBpmUserInfo();
@@ -89,7 +77,7 @@ export class UserInfoComponent implements OnInit {
}
get isLoggedIn(): boolean {
if (this.basicAlfrescoAuthService.isKerberosEnabled()) {
if (this.authService.isKerberosEnabled()) {
return true;
}
return this.authService.isLoggedIn();
@@ -108,17 +96,15 @@ export class UserInfoComponent implements OnInit {
}
private isAllLoggedIn() {
return (
(this.authService.isEcmLoggedIn() && this.authService.isBpmLoggedIn()) ||
(this.authService.isALLProvider() && this.basicAlfrescoAuthService.isKerberosEnabled())
);
return (this.authService.isEcmLoggedIn() && this.authService.isBpmLoggedIn()) || (this.authService.isALLProvider() && this.authService.isKerberosEnabled());
}
private isBpmLoggedIn() {
return this.authService.isBpmLoggedIn() || (this.authService.isECMProvider() && this.basicAlfrescoAuthService.isKerberosEnabled());
return this.authService.isBpmLoggedIn() || (this.authService.isECMProvider() && this.authService.isKerberosEnabled());
}
private isEcmLoggedIn() {
return this.authService.isEcmLoggedIn() || (this.authService.isECMProvider() && this.basicAlfrescoAuthService.isKerberosEnabled());
return this.authService.isEcmLoggedIn() || (this.authService.isECMProvider() && this.authService.isKerberosEnabled());
}
}
@@ -1,15 +1,17 @@
<div class="app-main-content">
<h1>CardView Component</h1>
<adf-card-view
[properties]="properties"
[editable]="isEditable"
[displayClearAction]="showClearDateAction"
[displayNoneOption]="showNoneOption"
[displayLabelForChips]="showLabelForChips">
</adf-card-view>
<mat-card class="app-card-view">
<adf-card-view
[properties]="properties"
[editable]="isEditable"
[displayClearAction]="showClearDateAction"
[displayNoneOption]="showNoneOption"
[displayLabelForChips]="showLabelForChips">
</adf-card-view>
</mat-card>
<div class="app-console">
<div class="app-console" #console>
<h3>Changes log:</h3>
<p *ngFor="let log of logs">{{ log }}</p>
</div>
@@ -2,7 +2,7 @@
padding: 0 15px;
}
adf-card-view {
.app-card-view {
width: 30%;
display: inline-block;
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit, ElementRef, ViewChild, OnDestroy } from '@angular/core';
import {
CardViewTextItemModel,
CardViewDateItemModel,
@@ -29,22 +29,19 @@ import {
CardViewMapItemModel,
UpdateNotification,
DecimalNumberPipe,
CardViewArrayItemModel,
CardViewComponent
CardViewArrayItemModel
} from '@alfresco/adf-core';
import { of, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatButtonModule } from '@angular/material/button';
@Component({
standalone: true,
imports: [CommonModule, MatSlideToggleModule, MatButtonModule, CardViewComponent],
templateUrl: './card-view.component.html',
styleUrls: ['./card-view.component.scss']
})
export class AppCardViewComponent implements OnInit, OnDestroy {
export class CardViewComponent implements OnInit, OnDestroy {
@ViewChild('console', { static: true }) console: ElementRef;
isEditable = true;
properties: any;
logs: string[];
@@ -54,7 +51,8 @@ export class AppCardViewComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>();
constructor(private cardViewUpdateService: CardViewUpdateService, private decimalNumberPipe: DecimalNumberPipe) {
constructor(private cardViewUpdateService: CardViewUpdateService,
private decimalNumberPipe: DecimalNumberPipe) {
this.logs = [];
this.createCard();
}
@@ -64,7 +62,9 @@ export class AppCardViewComponent implements OnInit, OnDestroy {
}
ngOnInit() {
this.cardViewUpdateService.itemUpdated$.pipe(takeUntil(this.onDestroy$)).subscribe(this.onItemChange.bind(this));
this.cardViewUpdateService.itemUpdated$
.pipe(takeUntil(this.onDestroy$))
.subscribe(this.onItemChange.bind(this));
}
ngOnDestroy() {
@@ -120,17 +120,17 @@ export class AppCardViewComponent implements OnInit, OnDestroy {
}),
new CardViewDateItemModel({
label: 'CardView Date Item',
value: new Date('1983-11-24T00:00:00Z'),
value: new Date(1983, 11, 24, 10, 0, 30),
key: 'date',
default: new Date('1983-11-24T00:00:00Z'),
default: new Date(1983, 11, 24, 10, 0, 30),
format: 'shortDate',
editable: this.isEditable
}),
new CardViewDateItemModel({
label: 'CardView Date Item - Multivalue (chips)',
value: [new Date('1983-11-24T00:00:00Z')],
value: [new Date(1983, 11, 24, 10, 0, 30)],
key: 'date',
default: new Date('1983-11-24T00:00:00Z'),
default: new Date(1983, 11, 24, 10, 0, 30),
format: 'shortDate',
editable: this.isEditable,
multivalued: true
@@ -192,29 +192,20 @@ export class AppCardViewComponent implements OnInit, OnDestroy {
}),
new CardViewKeyValuePairsItemModel({
label: 'CardView Key-Value Pairs Item',
value: [
{ name: 'hey', value: 'you' },
{ name: 'hey', value: 'you' }
],
value: [{ name: 'hey', value: 'you' }, { name: 'hey', value: 'you' }],
key: 'key-value-pairs',
editable: this.isEditable
}),
new CardViewKeyValuePairsItemModel({
label: 'CardView Key-Value Pairs Item',
value: [
{ name: 'hey', value: 'you' },
{ name: 'hey', value: 'you' }
],
value: [{ name: 'hey', value: 'you' }, { name: 'hey', value: 'you' }],
key: 'key-value-pairs',
editable: false
}),
new CardViewSelectItemModel({
label: 'CardView Select Item',
value: 'one',
options$: of([
{ key: 'one', label: 'One' },
{ key: 'two', label: 'Two' }
]),
options$: of([{ key: 'one', label: 'One' }, { key: 'two', label: 'Two' }]),
key: 'select',
editable: this.isEditable
}),
@@ -262,6 +253,7 @@ export class AppCardViewComponent implements OnInit, OnDestroy {
}
this.logs.push(`[${notification.target.label}] - ${value}`);
this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight;
}
toggleEditable() {
@@ -0,0 +1,39 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NgModule } from '@angular/core';
import { CardViewComponent } from './card-view.component';
import { Routes, RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { CoreModule } from '@alfresco/adf-core';
const routes: Routes = [
{
path: '',
component: CardViewComponent
}
];
@NgModule({
imports: [
CommonModule,
CoreModule,
RouterModule.forChild(routes)
],
declarations: [CardViewComponent]
})
export class AppCardViewModule {}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -18,18 +18,18 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { CloudLayoutService } from './services/cloud-layout.service';
import { AppListCloudModule } from '@alfresco/adf-process-services-cloud';
@Component({
standalone: true,
imports: [AppListCloudModule],
templateUrl: './apps-cloud-demo.component.html'
})
export class AppsCloudDemoComponent {
constructor(private router: Router, private cloudLayoutService: CloudLayoutService) {}
constructor(private router: Router, private cloudLayoutService: CloudLayoutService) {
}
onAppClick(app) {
this.cloudLayoutService.setCurrentTaskFilterParam({ key: 'my-tasks' });
this.cloudLayoutService.setCurrentTaskFilterParam({key: 'my-tasks'});
this.router.navigate([`/cloud/${app.name}`]);
}
}
@@ -0,0 +1,4 @@
<adf-toolbar>
<div class="app-crumb">{{appName + ' >'}} </div>
<div class="app-filter-crumb"> {{filterName | translate}}</div>
</adf-toolbar>
@@ -0,0 +1,14 @@
app-cloud-breadcrumbs {
.app-app-crumb {
opacity: 0.5;
}
.app-filter-crumb {
opacity: 0.8;
margin-left: 5px;
}
adf-toolbar {
display: flex;
}
}
@@ -0,0 +1,43 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-cloud-breadcrumbs',
templateUrl: './cloud-breadcrumb-component.html',
styleUrls: ['./cloud-breadcrumb-component.scss'],
encapsulation: ViewEncapsulation.None
})
export class CloudBreadcrumbsComponent implements OnInit {
appName: string;
filterName: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.parent.params.subscribe(params => {
this.appName = params.appName;
});
this.route.queryParams.subscribe(params => {
if (params.filterName) {
this.filterName = params.filterName;
}
});
}
}
@@ -1,4 +1,4 @@
app-cloud-task-filters .app-filters__entry,
app-cloud-process-filters .app-filters__entry {
padding-left: 0;
padding-left: 0 !important;
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -20,18 +20,15 @@ import { Observable } from 'rxjs';
import { CloudLayoutService } from './services/cloud-layout.service';
import { Router, ActivatedRoute } from '@angular/router';
import { CloudProcessFiltersService } from './services/cloud-process-filters.service';
import { ProcessFilterCloudModel, ProcessFiltersCloudModule, TaskFiltersCloudModule } from '@alfresco/adf-process-services-cloud';
import { CommonModule } from '@angular/common';
import { MatExpansionModule } from '@angular/material/expansion';
import { ProcessFilterCloudModel } from '@alfresco/adf-process-services-cloud';
@Component({
selector: 'app-cloud-filters-demo',
standalone: true,
imports: [CommonModule, MatExpansionModule, TaskFiltersCloudModule, ProcessFiltersCloudModule],
templateUrl: './cloud-filters-demo.component.html',
styleUrls: ['./cloud-filters-demo.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class CloudFiltersDemoComponent implements OnInit {
@Input()
appName: string;
@@ -49,7 +46,7 @@ export class CloudFiltersDemoComponent implements OnInit {
private router: Router,
private route: ActivatedRoute,
private cloudProcessFiltersService: CloudProcessFiltersService
) { /* empty */ }
) {}
ngOnInit() {
this.currentTaskFilter$ = this.cloudLayoutService.taskFilter$;
@@ -70,17 +67,17 @@ export class CloudFiltersDemoComponent implements OnInit {
onTaskFilterSelected(filter) {
if (filter) {
this.router.navigate([`/cloud/${this.appName}/tasks/`], { queryParams: filter });
this.router.navigate([`/cloud/${this.appName}/tasks/`], {queryParams: filter});
}
}
onProcessFilterSelected(filter: ProcessFilterCloudModel) {
if (filter) {
const { appName } = this;
const { id } = filter;
const {appName} = this;
const {id} = filter;
const queryParams = this.cloudProcessFiltersService.writeQueryParams(filter, appName, id);
this.router.navigate([`/cloud/${appName}/processes/`], { queryParams });
this.router.navigate([`/cloud/${appName}/processes/`], {queryParams});
}
}
@@ -3,10 +3,7 @@
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="270" [stepOver]="780">
<adf-sidenav-layout-header>
<ng-template>
<div class="app-cloud-layout-toolbar">
<span>{{appName}}</span>
<span *ngIf="filterName">{{ ' > ' + (filterName | translate)}}</span>
</div>
<app-cloud-breadcrumbs></app-cloud-breadcrumbs>
</ng-template>
</adf-sidenav-layout-header>
<adf-sidenav-layout-navigation>
@@ -1,9 +1,11 @@
@import 'styles/mat-selectors';
.app-cloud-layout-overflow {
overflow: auto;
}
.app-cloud-layout-tab-body .mat-tab-body-wrapper {
height: 100%;
}
app-cloud-layout {
.app-cloud-layout-tab-body {
height: 100%;
@@ -16,13 +18,5 @@ app-cloud-layout {
box-sizing: border-box;
display: flex;
}
& > div {
height: 100%;
}
}
.app-cloud-layout-toolbar {
display: flex;
}
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,50 +16,24 @@
*/
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Router, ActivatedRoute, RouterOutlet } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
import { CloudLayoutService } from './services/cloud-layout.service';
import { CommonModule } from '@angular/common';
import { MatTabsModule } from '@angular/material/tabs';
import {
SidebarActionMenuComponent,
SidenavLayoutComponent,
SidenavLayoutContentDirective,
SidenavLayoutHeaderDirective,
SidenavLayoutNavigationDirective
} from '@alfresco/adf-core';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { CloudFiltersDemoComponent } from './cloud-filters-demo.component';
import { CloudSettingsComponent } from './shared/cloud-settings.component';
@Component({
selector: 'app-cloud-layout',
standalone: true,
imports: [
CommonModule,
MatTabsModule,
SidenavLayoutComponent,
TranslateModule,
SidenavLayoutHeaderDirective,
SidenavLayoutNavigationDirective,
SidebarActionMenuComponent,
MatIconModule,
MatMenuModule,
SidenavLayoutContentDirective,
RouterOutlet,
CloudFiltersDemoComponent,
CloudSettingsComponent
],
templateUrl: './cloud-layout.component.html',
styleUrls: ['./cloud-layout.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class CloudLayoutComponent implements OnInit {
displayMenu = true;
appName: string;
filterName: string;
constructor(private router: Router, private route: ActivatedRoute, private cloudLayoutService: CloudLayoutService) { /* empty */ }
constructor(
private router: Router,
private route: ActivatedRoute,
private cloudLayoutService: CloudLayoutService
) { }
ngOnInit() {
let root: string = '';
@@ -79,10 +53,6 @@ export class CloudLayoutComponent implements OnInit {
if (root === 'processes' && params.id) {
this.cloudLayoutService.setCurrentProcessFilterParam({ id: params.id });
}
if (params.filterName) {
this.filterName = params.filterName;
}
});
}
@@ -1,2 +1,3 @@
<adf-alfresco-viewer [nodeId]="nodeId">
<adf-alfresco-viewer
[nodeId]="nodeId">
</adf-alfresco-viewer>
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -17,18 +17,17 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { AlfrescoViewerComponent } from '@alfresco/adf-content-services';
@Component({
selector: 'app-cloud-viewer',
standalone: true,
imports: [AlfrescoViewerComponent],
templateUrl: './cloud-viewer.component.html'
})
export class CloudViewerComponent implements OnInit {
nodeId: string;
constructor(private route: ActivatedRoute) {}
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.route.params.subscribe((params: Params) => {
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,18 +16,16 @@
*/
import { Component, OnInit } from '@angular/core';
import { ErrorWidgetComponent, FormService, WidgetComponent } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslateModule } from '@ngx-translate/core';
import { FormsModule } from '@angular/forms';
import { FormService, WidgetComponent } from '@alfresco/adf-core';
/* eslint-disable @angular-eslint/component-selector */
@Component({
selector: 'custom-editor-widget',
standalone: true,
template: ` <div style="color: green">ADF version of custom form widget</div> `
template: `
<div style="color: green">
ADF version of custom form widget
</div>
`
})
export class CustomEditorComponent extends WidgetComponent {
constructor() {
@@ -37,35 +35,32 @@ export class CustomEditorComponent extends WidgetComponent {
@Component({
selector: 'app-sample-widget',
standalone: true,
imports: [CommonModule, MatFormFieldModule, MatInputModule, TranslateModule, FormsModule, ErrorWidgetComponent],
template: `
<div style="color: red">
<p *ngIf="field.readOnly || readOnly">
<label class="adf-label" [attr.for]="field.id">{{ field.name | translate }}<span *ngIf="isRequired()">*</span></label>
<span>{{ field.value }}</span>
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span *ngIf="isRequired()">*</span></label>
<span>{{field.value}}</span>
</p>
<mat-form-field *ngIf="!(field.readOnly || readOnly)">
<label class="adf-label" [attr.for]="field.id">{{ field.name | translate }}<span *ngIf="isRequired()">*</span></label>
<input
matInput
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)"
/>
<mat-hint>{{ field.placeholder }}</mat-hint>
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span *ngIf="isRequired()">*</span></label>
<input matInput
class="adf-input"
type="text"
[id]="field.id"
[required]="isRequired()"
[value]="field.value"
[(ngModel)]="field.value"
(ngModelChange)="onFieldChanged(field)">
<mat-hint>{{field.placeholder}}</mat-hint>
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>
`
})
export class CustomWidgetComponent extends WidgetComponent implements OnInit {
export class CustomWidgetComponent extends WidgetComponent implements OnInit {
constructor(public formService: FormService) {
super(formService);
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -19,15 +19,15 @@ import { Component } from '@angular/core';
import { FormRenderingService } from '@alfresco/adf-core';
import { CloudFormRenderingService } from '@alfresco/adf-process-services-cloud';
import { CustomEditorComponent, CustomWidgetComponent } from './custom-form-components/custom-editor.component';
import { RouterOutlet } from '@angular/router';
@Component({
template: `<router-outlet></router-outlet>`,
standalone: true,
imports: [RouterOutlet],
providers: [{ provide: FormRenderingService, useClass: CloudFormRenderingService }]
providers: [
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
]
})
export class ProcessCloudLayoutComponent {
constructor(private formRenderingService: FormRenderingService) {
this.formRenderingService.register({
'custom-editor': () => CustomEditorComponent,
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -17,19 +17,15 @@
import { Component, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { ProcessHeaderCloudModule, TaskListCloudModule } from '@alfresco/adf-process-services-cloud';
@Component({
selector: 'app-process-details-cloud-demo',
standalone: true,
imports: [MatIconModule, MatButtonModule, TaskListCloudModule, ProcessHeaderCloudModule],
templateUrl: './process-details-cloud-demo.component.html',
styleUrls: ['./process-details-cloud-demo.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ProcessDetailsCloudDemoComponent {
processInstanceId: string;
appName: string;
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -21,23 +21,18 @@ import {
PROCESS_FILTER_ACTION_SAVE,
PROCESS_FILTER_ACTION_SAVE_AS,
ProcessFilterAction,
ProcessFilterCloudModel,
ProcessFiltersCloudModule,
ProcessListCloudModule
ProcessFilterCloudModel
} from '@alfresco/adf-process-services-cloud';
import { ActivatedRoute, Router } from '@angular/router';
import { DataCellEvent, PaginationComponent, UserPreferencesService } from '@alfresco/adf-core';
import { DataCellEvent, UserPreferencesService } from '@alfresco/adf-core';
import { CloudLayoutService, CloudServiceSettings } from './services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Pagination } from '@alfresco/js-api';
import { CloudProcessFiltersService } from './services/cloud-process-filters.service';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-processes-cloud-demo',
standalone: true,
imports: [CommonModule, ProcessFiltersCloudModule, ProcessListCloudModule, PaginationComponent],
templateUrl: './processes-cloud-demo.component.html',
styleUrls: ['./processes-cloud-demo.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -55,8 +50,8 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
actionMenu: boolean;
contextMenu: boolean;
actions: any[] = [];
selectedAction: { id: number; name: string; actionType: string };
selectedContextAction: { id: number; name: string; actionType: string };
selectedAction: { id: number; name: string; actionType: string};
selectedContextAction: { id: number; name: string; actionType: string};
filterProperties: string[];
filterSortProperties: string[];
@@ -74,8 +69,8 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
private router: Router,
private cloudLayoutService: CloudLayoutService,
private cloudProcessFiltersService: CloudProcessFiltersService,
private userPreference: UserPreferencesService
) {}
private userPreference: UserPreferencesService) {
}
ngOnInit() {
this.filterProperties = this.cloudProcessFiltersService.filterProperties;
@@ -92,7 +87,9 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
this.loadFilter(model);
});
this.cloudLayoutService.settings$.pipe(takeUntil(this.onDestroy$)).subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
this.performContextActions();
}
@@ -132,7 +129,7 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
...this.cloudProcessFiltersService.writeQueryParams(filter, this.appName, filter.id),
filterId: filter.id
};
this.router.navigate([`/cloud/${this.appName}/processes/`], { queryParams });
this.router.navigate([`/cloud/${this.appName}/processes/`], {queryParams});
}
onProcessFilterAction(filterAction: ProcessFilterAction) {
@@ -158,30 +155,33 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
onShowRowContextMenu(event: DataCellEvent) {
event.value.actions = this.actions.map((action) => ({
data: event.value.row['obj'],
model: action,
subject: this.performAction$
data: event.value.row['obj'],
model: action,
subject: this.performAction$
}));
}
onExecuteRowAction(row: any) {
const value = row.value.row['obj'].entry;
const action = row.value.action;
this.selectedAction = { id: value.id, name: value.name, actionType: action.title };
this.selectedAction = {id: value.id, name: value.name, actionType: action.title};
}
performContextActions() {
this.performAction$.pipe(takeUntil(this.onDestroy$)).subscribe((action: any) => {
this.performAction$
.pipe(takeUntil(this.onDestroy$))
.subscribe((action: any) => {
if (action) {
this.onExecuteContextAction(action);
this.onExecuteContextAction(action);
}
});
});
}
onExecuteContextAction(contextAction: any) {
const value = contextAction.data.entry;
const action = contextAction.model;
this.selectedContextAction = { id: value.id, name: value.name, actionType: action.title };
this.selectedContextAction = {id: value.id, name: value.name, actionType: action.title};
}
private loadFilter(model: ProcessFilterCloudModel) {
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,8 +16,7 @@
<mat-slide-toggle [checked]="processDetailsRedirection" (change)="toggleProcessDetailsRedirection()" data-automation-id="processDetailsRedirection">
Display process details on process click
</mat-slide-toggle>
<mat-form-field data-automation-id="selectionMode" class="adf-cloud-settings-selection-mode">
<mat-form-field data-automation-id="selectionMode">
<mat-label>Selection Mode</mat-label>
<mat-select [(ngModel)]="selectionMode" (selectionChange)="onSelectionModeChange()">
<mat-option *ngFor="let option of selectionModeOptions" [value]="option.value">
@@ -25,29 +24,32 @@
</mat-option>
</mat-select>
</mat-form-field>
<div class="app-cloud-actions" *ngIf="actionMenu || contextMenu">
<h2>Add Action</h2>
<form class="app-cloud-settings-form" [formGroup]="actionMenuForm">
<mat-form-field class="app-cloud-settings-form-input">
<input matInput formControlName="key" placeholder="Key">
</mat-form-field>
<mat-form-field class="app-cloud-settings-form-input">
<input matInput formControlName="title" placeholder="Title">
</mat-form-field>
<mat-form-field class="app-cloud-settings-form-input">
<input matInput formControlName="icon" placeholder="Icon">
</mat-form-field>
<mat-checkbox formControlName="visible">Visible</mat-checkbox>
<mat-checkbox formControlName="disabled">Disable</mat-checkbox>
<button mat-raised-button (click)="addAction()">Add</button>
</form>
<div *ngIf="actions.length > 0">
<mat-chip-listbox>
<mat-chip-option *ngFor="let action of actions" [removable]="true">
{{action.title}}
<mat-icon matChipRemove (click)="removeAction(action)">cancel</mat-icon>
</mat-chip-option>
</mat-chip-listbox>
</div>
</div>
<mat-card *ngIf="actionMenu || contextMenu">
<mat-card-header>
<mat-card-title>Add Action</mat-card-title>
</mat-card-header>
<mat-card-content>
<form class="app-cloud-settings-form" [formGroup]="actionMenuForm">
<mat-form-field>
<input matInput formControlName="key" placeholder="Key">
</mat-form-field>
<mat-form-field>
<input matInput formControlName="title" placeholder="Title">
</mat-form-field>
<mat-form-field>
<input matInput formControlName="icon" placeholder="Icon">
</mat-form-field>
<mat-checkbox formControlName="visible">Visible</mat-checkbox>
<mat-checkbox formControlName="disabled">Disable</mat-checkbox>
<button mat-raised-button (click)="addAction()">Add</button>
</form>
<div *ngIf="actions.length > 0">
<mat-chip-list>
<mat-chip *ngFor="let action of actions" [removable]="true">
{{action.title}}
<mat-icon matChipRemove (click)="removeAction(action)">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</div>
</mat-card-content>
</mat-card>
@@ -4,11 +4,7 @@ app-cloud-settings {
display: flex;
flex: 1;
.app-cloud-actions {
background-color: white;
}
.adf-cloud-settings-selection-mode {
mat-form-field {
max-width: 200px;
}
@@ -17,9 +13,13 @@ app-cloud-settings {
place-content: center space-around;
align-items: center;
.app-cloud-settings-form-input {
mat-form-field {
flex: 1 1 100%;
max-width: 23%;
}
mat-form-field, mat-checkbox {
margin-right: 20px;
}
}
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -19,33 +19,10 @@ import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { ActionMenuModel, CloudLayoutService } from '../services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FormsModule, ReactiveFormsModule, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button';
import { MatChipsModule } from '@angular/material/chips';
import { MatIconModule } from '@angular/material/icon';
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
@Component({
selector: 'app-cloud-settings',
standalone: true,
imports: [
CommonModule,
MatSlideToggleModule,
MatFormFieldModule,
MatSelectModule,
FormsModule,
MatInputModule,
ReactiveFormsModule,
MatCheckboxModule,
MatButtonModule,
MatChipsModule,
MatIconModule
],
templateUrl: './cloud-settings.component.html',
styleUrls: ['./cloud-settings.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -74,12 +51,15 @@ export class CloudSettingsComponent implements OnInit, OnDestroy {
icon: new UntypedFormControl(''),
visible: new UntypedFormControl(true),
disabled: new UntypedFormControl(false)
});
});
constructor(private cloudLayoutService: CloudLayoutService) {}
constructor(private cloudLayoutService: CloudLayoutService) { }
ngOnInit() {
this.cloudLayoutService.settings$.pipe(takeUntil(this.onDestroy$)).subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService
.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
}
ngOnDestroy() {
@@ -0,0 +1,40 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CloudSettingsComponent } from './cloud-settings.component';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { CoreModule } from '@alfresco/adf-core';
@NgModule({
imports: [
CommonModule,
CoreModule,
MatDialogModule,
MatInputModule,
MatSelectModule,
MatSlideToggleModule
],
declarations: [ CloudSettingsComponent ],
exports: [ CommonModule, CloudSettingsComponent]
})
export class AppCloudSharedModule {}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -20,28 +20,28 @@ import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService, AppConfigService, FormRenderingService } from '@alfresco/adf-core';
import { CloudLayoutService } from './services/cloud-layout.service';
import { PreviewService } from '../../services/preview.service';
import { CloudFormRenderingService, StartProcessCloudModule } from '@alfresco/adf-process-services-cloud';
import { CloudFormRenderingService } from '@alfresco/adf-process-services-cloud';
@Component({
standalone: true,
imports: [StartProcessCloudModule],
templateUrl: './start-process-cloud-demo.component.html',
providers: [{ provide: FormRenderingService, useClass: CloudFormRenderingService }]
providers: [
{ provide: FormRenderingService, useClass: CloudFormRenderingService }
]
})
export class StartProcessCloudDemoComponent implements OnInit {
appName;
processName: string;
formValues: any;
variables: any;
constructor(
private appConfig: AppConfigService,
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
private previewService: PreviewService,
private notificationService: NotificationService,
private router: Router
) {}
constructor(private appConfig: AppConfigService,
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
private previewService: PreviewService,
private notificationService: NotificationService,
private router: Router) {
}
ngOnInit() {
this.route.parent.params.subscribe((params) => {
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -19,22 +19,20 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService } from '@alfresco/adf-core';
import { CloudLayoutService } from './services/cloud-layout.service';
import { StartTaskCloudModule } from '@alfresco/adf-process-services-cloud';
@Component({
standalone: true,
imports: [StartTaskCloudModule],
templateUrl: './start-task-cloud-demo.component.html'
})
export class StartTaskCloudDemoComponent implements OnInit {
appName;
constructor(
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
private notificationService: NotificationService,
private router: Router
) {}
private router: Router) {
}
ngOnInit() {
this.route.parent.params.subscribe((params) => {
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -18,18 +18,17 @@
import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService } from '@alfresco/adf-core';
import { TaskFormModule, TaskHeaderCloudComponent, TaskHeaderCloudModule } from '@alfresco/adf-process-services-cloud';
import { TaskHeaderCloudComponent } from '@alfresco/adf-process-services-cloud';
import { PreviewService } from '../../services/preview.service';
@Component({
selector: 'app-task-details-cloud-demo',
standalone: true,
imports: [TaskFormModule, TaskHeaderCloudModule],
templateUrl: './task-details-cloud-demo.component.html',
styleUrls: ['./task-details-cloud-demo.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TaskDetailsCloudDemoComponent {
@ViewChild('taskHeader', { static: true })
taskHeader: TaskHeaderCloudComponent;
@@ -41,13 +40,14 @@ export class TaskDetailsCloudDemoComponent {
private router: Router,
private notificationService: NotificationService,
private previewService: PreviewService
) {
) {
this.route.params.subscribe((params) => {
this.taskId = params.taskId;
});
this.route.parent.params.subscribe((params) => {
this.appName = params.appName;
});
}
isTaskValid(): boolean {
@@ -75,7 +75,7 @@ export class TaskDetailsCloudDemoComponent {
try {
errorMessage = JSON.parse(error).message || JSON.parse(error).entry?.message;
errorMessage = JSON.parse(errorMessage).message;
} catch { /* empty */ }
} catch {}
this.notificationService.showError(errorMessage || error);
}
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -18,17 +18,14 @@
import { Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import {
TaskFilterCloudModel,
TaskFiltersCloudModule,
TaskListCloudComponent,
TaskListCloudModule,
TaskListCloudSortingModel
} from '@alfresco/adf-process-services-cloud';
import { AppConfigService, DataCellEvent, PaginationComponent, UserPreferencesService } from '@alfresco/adf-core';
import { AppConfigService, DataCellEvent, UserPreferencesService } from '@alfresco/adf-core';
import { ActivatedRoute, Router } from '@angular/router';
import { CloudLayoutService } from './services/cloud-layout.service';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
const ACTION_SAVE_AS = 'saveAs';
const ACTION_DELETE = 'delete';
@@ -36,8 +33,6 @@ const TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter';
@Component({
selector: 'app-tasks-cloud-demo',
standalone: true,
imports: [CommonModule, TaskFiltersCloudModule, TaskListCloudModule, PaginationComponent],
templateUrl: './tasks-cloud-demo.component.html',
styleUrls: ['./tasks-cloud-demo.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -54,7 +49,7 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
sortArray: TaskListCloudSortingModel[];
editedFilter: TaskFilterCloudModel;
taskFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] };
taskFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] };
filterId;
multiselect: boolean;
@@ -62,8 +57,8 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
actionMenu: boolean;
contextMenu: boolean;
actions: any[] = [];
selectedAction: { id: number; name: string; actionType: string };
selectedContextAction: { id: number; name: string; actionType: string };
selectedAction: { id: number; name: string; actionType: string};
selectedContextAction: { id: number; name: string; actionType: string};
testingMode: boolean;
selectionMode: string;
taskDetailsRedirection: boolean;
@@ -76,8 +71,8 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private userPreference: UserPreferencesService,
private appConfig: AppConfigService
) {
private appConfig: AppConfigService) {
const properties = this.appConfig.get<Array<any>>(TASK_FILTER_PROPERTY_KEYS);
if (properties) {
this.taskFilterProperties = properties;
@@ -96,7 +91,9 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
this.filterId = params.id;
});
this.cloudLayoutService.settings$.pipe(takeUntil(this.onDestroy$)).subscribe((settings) => this.setCurrentSettings(settings));
this.cloudLayoutService.settings$
.pipe(takeUntil(this.onDestroy$))
.subscribe(settings => this.setCurrentSettings(settings));
this.performContextActions();
}
@@ -137,11 +134,12 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
}
onFilterChange(filter: any) {
this.editedFilter = Object.assign({ /* empty */ }, filter);
this.editedFilter = Object.assign({}, filter);
this.sortArray = [new TaskListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })];
}
onTaskFilterAction(filterAction: any) {
if (filterAction.actionType === ACTION_DELETE) {
this.cloudLayoutService.setCurrentTaskFilterParam({ index: 0 });
} else {
@@ -159,29 +157,32 @@ export class TasksCloudDemoComponent implements OnInit, OnDestroy {
onShowRowContextMenu(event: DataCellEvent) {
event.value.actions = this.actions.map((action) => ({
data: event.value.row['obj'],
model: action,
subject: this.performAction$
data: event.value.row['obj'],
model: action,
subject: this.performAction$
}));
}
onExecuteRowAction(row: any) {
const value = row.value.row['obj'].entry;
const action = row.value.action;
this.selectedAction = { id: value.id, name: value.name, actionType: action.title };
this.selectedAction = {id: value.id, name: value.name, actionType: action.title};
}
performContextActions() {
this.performAction$.pipe(takeUntil(this.onDestroy$)).subscribe((action: any) => {
this.performAction$
.pipe(takeUntil(this.onDestroy$))
.subscribe((action: any) => {
if (action) {
this.onExecuteContextAction(action);
this.onExecuteContextAction(action);
}
});
});
}
onExecuteContextAction(contextAction: any) {
const value = contextAction.data.entry;
const action = contextAction.model;
this.selectedContextAction = { id: value.id, name: value.name, actionType: action.title };
this.selectedContextAction = {id: value.id, name: value.name, actionType: action.title};
}
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -17,19 +17,17 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { ErrorContentComponent } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button';
@Component({
selector: 'app-demo-error',
standalone: true,
imports: [ErrorContentComponent, MatButtonModule],
templateUrl: './demo-error.component.html'
})
export class DemoErrorComponent implements OnInit {
errorCode: string = '';
constructor(private route: ActivatedRoute, private router: Router) {}
constructor(private route: ActivatedRoute, private router: Router) {
}
ngOnInit() {
if (this.route) {
@@ -44,4 +42,5 @@ export class DemoErrorComponent implements OnInit {
onReturnButton() {
this.router.navigate(['/']);
}
}
@@ -1,24 +1,71 @@
<ng-container *ngIf="nodeId">
<adf-alfresco-viewer
(showViewerChange)="onViewerClosed()"
[nodeId]="nodeId"
[versionId]="versionId"
[showToolbar]="true"
[allowRightSidebar]="true"
[showRightSidebar]="showRightSidebar"
[showLeftSidebar]="showLeftSidebar"
[allowGoBack]="allowGoBack"
[showToolbar]="showToolbar"
[allowPrint]="allowPrint"
[allowDownload]="allowDownload"
[allowRightSidebar]="allowRightSidebar"
[allowLeftSidebar]="allowLeftSidebar"
[sidebarLeftTemplate]="sidebarLeftTemplate"
[sidebarRightTemplate]="sidebarRightTemplate">
<adf-viewer-toolbar *ngIf="customToolbar" data-automation-id="adf-viewer-custom-toolbar">
<h1>My custom toolbar</h1>
</adf-viewer-toolbar>
<adf-viewer-toolbar-actions *ngIf="moreActions">
<button mat-icon-button id="adf-viewer-time">
<mat-icon>alarm</mat-icon>
</button>
<button mat-icon-button id="adf-viewer-upload">
<mat-icon>backup</mat-icon>
</button>
<button mat-icon-button id="adf-viewer-bug">
<mat-icon>bug_report</mat-icon>
</button>
</adf-viewer-toolbar-actions>
<adf-viewer-more-actions *ngIf="moreActionsMenu">
<button mat-menu-item id="adf-viewer-more-menu-alarm">
<mat-icon>alarm</mat-icon>
<span>Alarm</span>
</button>
<button mat-menu-item id="adf-viewer-more-menu-backup">
<mat-icon>backup</mat-icon>
<span>Backup</span>
</button>
<button mat-menu-item id="adf-viewer-more-menu-bug">
<mat-icon>bug_report</mat-icon>
<span>Bug report</span>
</button>
</adf-viewer-more-actions>
<ng-container *ngIf="openWith">
<adf-viewer-open-with>
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Option 1</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Option 2</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Option 3</span>
</button>
</adf-viewer-open-with>
</ng-container>
</adf-alfresco-viewer>
</ng-container>
<ng-container *ngIf="blobFile">
<adf-viewer
[blobFile]="blobFile"
[fileName]="fileName"
[showToolbar]="true"
[allowRightSidebar]="true"
(showViewerChange)="onViewerClosed()"
[sidebarRightTemplate]="sidebarRightTemplate">
</adf-viewer>
</ng-container>
<ng-template let-node="node" #sidebarRightTemplate>
<adf-info-drawer title="Details">
@@ -29,17 +76,20 @@
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Properties">
<adf-content-metadata
[node]="node"
[multi]="multi"
[preset]="isPreset ? customPreset : null"
[readOnly]="isReadOnly"
[displayAspect]="showAspect"
[displayDefaultProperties]="displayDefaultProperties"
[displayTags]="false"
[displayCategories]="false"
[displayEmpty]="displayEmptyMetadata">
</adf-content-metadata>
<adf-content-metadata-card *ngIf="isPreset" [node]="node"
[multi]="multi"
[preset]="customPreset"
[readOnly]="isReadOnly"
[displayAspect]="showAspect"
[displayDefaultProperties]="displayDefaultProperties"
[displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card>
<adf-content-metadata-card *ngIf="!isPreset" [node]="node"
[multi]="multi"
[readOnly]="isReadOnly"
[displayAspect]="showAspect"
[displayDefaultProperties]="displayDefaultProperties"
[displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card>
<p class="toggle">
<mat-slide-toggle
@@ -107,10 +157,242 @@
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Versions">
<adf-version-manager [node]="node"
(uploadError)="onUploadError($event)"
(viewVersion)="onViewVersion($event)">
</adf-version-manager>
<mat-card>
<mat-card-content>
<adf-version-manager [node]="node"
(uploadError)="onUploadError($event)"
(viewVersion)="onViewVersion($event)">
</adf-version-manager>
</mat-card-content>
</mat-card>
</adf-info-drawer-tab>
</adf-info-drawer>
</ng-template>
<ng-template #sidebarLeftTemplate>
<adf-info-drawer [title]="'Viewer Options'">
<adf-info-drawer-tab label="Settings">
<p class="toggle">
<mat-slide-toggle
id="adf-switch-fileurl"
(change)="toggleFileUrl()"
[checked]="fileUrlSwitch">
Url File
</mat-slide-toggle>
</p>
<p class="toggle">
<ng-container *ngIf="fileUrlSwitch">
<mat-form-field floatPlaceholder="float">
<input matInput
placeholder="Url File"
[(ngModel)]="urlFile"
data-automation-id="adf-text-file-url">
</mat-form-field>
</ng-container>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-toolbar"
(change)="toggleShowToolbar()"
[checked]="showToolbar">
Show Toolbar
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-goback"
(change)="toggleAllowGoBack()"
[checked]="allowGoBack">
Allow GoBack
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-openwith"
(change)="toggleOpenWith()"
[checked]="openWith">
Open With
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-moreactions"
(change)="toggleOpenMoreActions()"
[checked]="moreActions">
More Actions
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-moreactionsmenu"
(change)="toggleMoreActionsMenu()"
[checked]="moreActionsMenu">
More Actions Menu
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-download"
(change)="toggleAllowDownload()"
[checked]="allowDownload">
Allow Download
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-print"
(change)="toggleAllowPrint()"
[checked]="allowPrint">
Allow Print
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-allowsidebar"
(change)="toggleAllowRightSidebar()"
[checked]="allowRightSidebar">
Allow Right Sidebar
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-switch-allowLeftSidebar"
(change)="toggleAllowLeftSidebar()"
[checked]="allowLeftSidebar">
Allow Left Sidebar
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-toggle-custom-toolbar"
(change)="toggleToolbar()"
[checked]="customToolbar">
Custom Toolbar
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-tab-with-icon"
(change)="toggleShowTabWithIcon()"
[checked]="showTabWithIcon">
Show tab with icon
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-icon-and-label-tab"
(change)="toggleShowTabWithIconAndLabel()"
[checked]="showTabWithIconAndLabel">
Show tab with icon and label
</mat-slide-toggle>
</p>
<p class="toggle">
<button mat-raised-button id="adf-switch-showrightsidebar" (click)="toggleShowRightSidebar()">
Toggle Right Sidebar
</button>
</p>
<p class="toggle">
<button mat-raised-button id="adf-switch-showleftsidebar" (click)="hideLeftSidebar()">
Hide Left Sidebar
</button>
</p>
</adf-info-drawer-tab>
<adf-info-drawer-tab
*ngIf="showTabWithIcon"
[label]=""
[icon]="'face'"
data-automation-id="adf-settings-tab">
</adf-info-drawer-tab>
<adf-info-drawer-tab
*ngIf="showTabWithIconAndLabel"
[label]="'Comments'"
[icon]="'comment'"
data-automation-id="adf-settings-tab">
</adf-info-drawer-tab>
</adf-info-drawer>
</ng-template>
<ng-container *ngIf="blobFile">
<adf-viewer
[blobFile]="blobFile"
[fileName]="fileName"
[showRightSidebar]="showRightSidebar"
[showLeftSidebar]="showLeftSidebar"
[allowGoBack]="allowGoBack"
[showToolbar]="showToolbar"
[allowRightSidebar]="allowRightSidebar"
[allowLeftSidebar]="allowLeftSidebar"
(showViewerChange)="onViewerClosed()"
[sidebarLeftTemplate]="sidebarLeftTemplate"
[sidebarRightTemplate]="sidebarRightTemplate">
<adf-viewer-toolbar *ngIf="customToolbar" data-automation-id="adf-viewer-custom-toolbar">
<h1>My custom toolbar</h1>
</adf-viewer-toolbar>
<adf-viewer-toolbar-actions *ngIf="moreActions">
<button mat-icon-button id="adf-viewer-time">
<mat-icon>alarm</mat-icon>
</button>
<button mat-icon-button id="adf-viewer-upload">
<mat-icon>backup</mat-icon>
</button>
<button mat-icon-button id="adf-viewer-bug">
<mat-icon>bug_report</mat-icon>
</button>
</adf-viewer-toolbar-actions>
<adf-viewer-more-actions *ngIf="moreActionsMenu">
<button mat-menu-item id="adf-viewer-more-menu-alarm">
<mat-icon>alarm</mat-icon>
<span>Alarm</span>
</button>
<button mat-menu-item id="adf-viewer-more-menu-backup">
<mat-icon>backup</mat-icon>
<span>Backup</span>
</button>
<button mat-menu-item id="adf-viewer-more-menu-bug">
<mat-icon>bug_report</mat-icon>
<span>Bug report</span>
</button>
</adf-viewer-more-actions>
<ng-container *ngIf="openWith">
<adf-viewer-open-with>
<button mat-menu-item>
<mat-icon>dialpad</mat-icon>
<span>Option 1</span>
</button>
<button mat-menu-item disabled>
<mat-icon>voicemail</mat-icon>
<span>Option 2</span>
</button>
<button mat-menu-item>
<mat-icon>notifications_off</mat-icon>
<span>Option 3</span>
</button>
</adf-viewer-open-with>
</ng-container>
</adf-viewer>
</ng-container>
@@ -0,0 +1,12 @@
.app-viewer__sidebar {
width: 380px !important;
}
/* stylelint-disable */
.monaco-scrollable-element {
width: 600px;
}
app-preview-extension {
width: 600px;
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,49 +16,27 @@
*/
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, PRIMARY_OUTLET, Router } from '@angular/router';
import { InfoDrawerComponent, InfoDrawerTabComponent, NotificationService, ViewerComponent } from '@alfresco/adf-core';
import { ActivatedRoute, Router, PRIMARY_OUTLET } from '@angular/router';
import {
NotificationService
} from '@alfresco/adf-core';
import {
AlfrescoViewerComponent,
AllowableOperationsEnum,
ContentMetadataComponent,
ContentService,
FileUploadErrorEvent,
NodeCommentsComponent,
NodesApiService,
AllowableOperationsEnum,
PermissionsEnum,
VersionManagerComponent
NodesApiService,
FileUploadErrorEvent
} from '@alfresco/adf-content-services';
import { PreviewService } from '../../services/preview.service';
import { CommonModule } from '@angular/common';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-file-view',
standalone: true,
imports: [
CommonModule,
AlfrescoViewerComponent,
ViewerComponent,
NodeCommentsComponent,
ContentMetadataComponent,
MatSlideToggleModule,
MatFormFieldModule,
MatButtonModule,
MatInputModule,
FormsModule,
VersionManagerComponent,
InfoDrawerTabComponent,
InfoDrawerComponent
],
templateUrl: './file-view.component.html',
styleUrls: ['./file-view.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FileViewComponent implements OnInit {
nodeId: string = null;
versionId: string = null;
displayEmptyMetadata = false;
@@ -68,21 +46,36 @@ export class FileViewComponent implements OnInit {
isPreset = false;
customPreset: string = null;
displayDefaultProperties = true;
showToolbar = true;
urlFile = null;
allowGoBack = true;
openWith = false;
allowDownload = true;
allowPrint = true;
allowRightSidebar = true;
allowLeftSidebar = true;
moreActions = true;
moreActionsMenu = false;
fileUrlSwitch = false;
showLeftSidebar = null;
showRightSidebar = false;
customToolbar = false;
isCommentEnabled = false;
showTabWithIcon = false;
showTabWithIconAndLabel = false;
desiredAspect: string = null;
showAspect: string = null;
name: string;
fileName: string;
blobFile: Blob;
constructor(
private router: Router,
private route: ActivatedRoute,
private nodeApiService: NodesApiService,
private contentServices: ContentService,
private preview: PreviewService,
private notificationService: NotificationService
) { /* empty */ }
constructor(private router: Router,
private route: ActivatedRoute,
private nodeApiService: NodesApiService,
private contentServices: ContentService,
private preview: PreviewService,
private notificationService: NotificationService) {
}
ngOnInit() {
this.route.params.subscribe((params) => {
@@ -92,8 +85,7 @@ export class FileViewComponent implements OnInit {
this.nodeApiService.getNode(id).subscribe(
(node) => {
if (node?.isFile) {
this.isCommentEnabled =
this.contentServices.hasPermissions(node, PermissionsEnum.NOT_CONSUMER) ||
this.isCommentEnabled = this.contentServices.hasPermissions(node, PermissionsEnum.NOT_CONSUMER) ||
this.contentServices.hasAllowableOperations(node, AllowableOperationsEnum.UPDATE);
this.nodeId = id;
return;
@@ -119,7 +111,8 @@ export class FileViewComponent implements OnInit {
}
onUploadError(event: FileUploadErrorEvent) {
this.notificationService.showError(event.error);
const errorMessage = event.error;
this.notificationService.showError(errorMessage);
}
toggleEmptyMetadata() {
@@ -138,6 +131,66 @@ export class FileViewComponent implements OnInit {
this.displayDefaultProperties = !this.displayDefaultProperties;
}
toggleShowToolbar() {
this.showToolbar = !this.showToolbar;
}
toggleAllowGoBack() {
this.allowGoBack = !this.allowGoBack;
}
toggleOpenWith() {
this.openWith = !this.openWith;
}
toggleAllowDownload() {
this.allowDownload = !this.allowDownload;
}
toggleAllowPrint() {
this.allowPrint = !this.allowPrint;
}
toggleOpenMoreActions() {
this.moreActions = !this.moreActions;
}
toggleMoreActionsMenu() {
this.moreActionsMenu = !this.moreActionsMenu;
}
toggleShowRightSidebar() {
this.showRightSidebar = !this.showRightSidebar;
}
hideLeftSidebar() {
this.showLeftSidebar = false;
}
toggleAllowRightSidebar() {
this.allowRightSidebar = !this.allowRightSidebar;
}
toggleAllowLeftSidebar() {
this.allowLeftSidebar = !this.allowLeftSidebar;
}
toggleShowTabWithIcon() {
this.showTabWithIcon = !this.showTabWithIcon;
}
toggleShowTabWithIconAndLabel() {
this.showTabWithIconAndLabel = !this.showTabWithIconAndLabel;
}
toggleFileUrl() {
this.fileUrlSwitch = !this.fileUrlSwitch;
if (!this.fileUrlSwitch) {
this.urlFile = null;
}
}
togglePreset() {
this.isPreset = !this.isPreset;
if (!this.isPreset) {
@@ -145,6 +198,10 @@ export class FileViewComponent implements OnInit {
}
}
toggleToolbar() {
this.customToolbar = !this.customToolbar;
}
applyCustomPreset() {
this.isPreset = false;
setTimeout(() => {
@@ -0,0 +1,49 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';
import { CoreModule, InfoDrawerModule } from '@alfresco/adf-core';
import { ContentModule, ContentDirectiveModule, VersionManagerModule, ContentMetadataModule } from '@alfresco/adf-content-services';
import { FileViewComponent } from './file-view.component';
const routes: Routes = [
{
path: '',
component: FileViewComponent
}
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(routes),
CoreModule,
ContentModule,
InfoDrawerModule,
ContentModule,
ContentDirectiveModule,
ContentMetadataModule,
VersionManagerModule
],
declarations: [FileViewComponent],
exports: [FileViewComponent]
})
export class FileViewModule {
}
@@ -1,4 +1,9 @@
<div class="app-container">
<div *ngIf="showSitePicker" class="app-site-container-style" id="site-container">
<adf-sites-dropdown (change)="onSiteChange($event)" [hideMyFiles]="false" [relations]="'members'">
</adf-sites-dropdown>
</div>
<div
id="document-list-container"
class="app-document-list-container">
@@ -9,6 +14,7 @@
[versioning]="versioning"
[adf-check-allowable-operation]="'create'"
[adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []"
(beginUpload)="onBeginUpload($event)"
(updateFileVersion)="onUploadNewVersion($event)">
<div *ngIf="errorMessage" class="app-error-message">
<button (click)="resetError()" mat-icon-button>
@@ -24,7 +30,16 @@
</adf-dropdown-breadcrumb>
</adf-toolbar-title>
<adf-toolbar-divider></adf-toolbar-divider>
<div class="app-document-action-buttons">
<button
mat-icon-button
data-automation-id="document-list-grid-view"
title="Toggle display mode"
(click)="toggleGalleryView()">
<mat-icon>list</mat-icon>
</button>
<button
data-automation-id="create-new-folder"
mat-icon-button
@@ -64,6 +79,24 @@
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="toggleGalleryView()">
<mat-icon *ngIf="displayMode === 'list'">view_comfy</mat-icon>
<mat-icon *ngIf="displayMode === 'gallery'">list</mat-icon>
<span>Card view mode</span>
</button>
<button mat-menu-item
(error)="openSnackMessageError($event)"
[adf-create-folder]="currentFolderId">
<mat-icon>create_new_folder</mat-icon>
<span>New folder</span>
</button>
<button mat-menu-item
[disabled]="!canEditFolder(documentList.selection)"
(error)="openSnackMessageError($event)"
[adf-edit-folder]="documentList.selection[0]?.entry">
<mat-icon>create</mat-icon>
<span>Edit folder</span>
</button>
<button mat-menu-item
adf-check-allowable-operation="delete"
[adf-nodes]="documentList.selection"
@@ -86,11 +119,13 @@
[allowDropFiles]="allowDropFiles"
[selectionMode]="selectionMode"
[multiselect]="multiselect"
[display]="displayMode"
[node]="nodeResult"
[includeFields]="includeFields"
[sorting]="sorting"
[sortingMode]="sortingMode"
[showHeader]="showHeader"
[thumbnails]="thumbnails"
[stickyHeader]="stickyHeader"
[headerFilters]="headerFilters"
[filterValue]="paramValues"
@@ -112,26 +147,41 @@
<data-column
key="$thumbnail"
type="image"
[sortable]="false">
[sortable]="false"
class="app-image-table-cell"
[class.adf-cell-thumbnail]="thumbnails">
</data-column>
<data-column
*ngIf="showNameColumn && hyperlinkNavigation"
key="name"
sortingKey="name"
class="app-ellipsis-cell"
title="Display name"
[formatTooltip]="getNodeNameTooltip">
<ng-template let-context>
<adf-name-column key="name" [context]="context"></adf-name-column>
</ng-template>
</data-column>
<data-column
*ngIf="showNameColumn && !hyperlinkNavigation"
key="name"
sortingKey="name"
title="Display name"
class="adf-expand-cell-5">
[formatTooltip]="getNodeNameTooltip"
class="app-ellipsis-cell adf-expand-cell-5">
</data-column>
<data-column
key="content.sizeInBytes"
title="Size"
type="fileSize"
sortingKey="sizeInBytes"
class="adf-ellipsis-cell">
class="app-desktop-only adf-ellipsis-cell">
</data-column>
<data-column
*ngIf="searchTerm"
key="search"
title="Search"
class="adf-expand-cell-3">
class="app-desktop-only adf-expand-cell-3">
<ng-template let-entry="$implicit">
<div [innerHTML]="searchResultsHighlight(entry.row.node.entry.search) | highlight:searchTerm">
</div>
@@ -150,7 +200,7 @@
key="lock"
[focus]="false"
[sortable]="false"
class="adf-ellipsis-cell">
class="app-desktop-only adf-ellipsis-cell">
<ng-template let-entry="$implicit">
<button mat-icon-button [adf-node-lock]="entry.row.node.entry" class="app-lock-button">
<mat-icon *ngIf="entry.row.getValue('isLocked')">lock</mat-icon>
@@ -162,15 +212,15 @@
title="Created by"
key="createdByUser.displayName"
sortingKey="createdByUser"
class="adf-ellipsis-cell">
class="app-desktop-only adf-ellipsis-cell">
</data-column>
<data-column
title="Created"
key="createdAt"
sortingKey="createdAt"
type="date"
[format]="'timeAgo'"
class="adf-ellipsis-cell">
[format]="enableMediumTimeFormat ? 'medium' : 'timeAgo'"
class="app-desktop-only adf-ellipsis-cell">
</data-column>
</data-columns>
@@ -190,6 +240,11 @@
(success)="onDeleteActionSuccess($event)"
handler="delete">
</content-action>
<content-action
icon="info"
title="Info"
(execute)="onManageMetadata($event)">
</content-action>
<content-action
icon="supervisor_account"
title="Permission"
@@ -214,12 +269,21 @@
</adf-document-list>
</div>
<adf-pagination
#standardPagination
*ngIf="!infiniteScrolling"
class="app-documentlist-pagination"
[target]="documentList"
(changePageSize)="onChangePageSize($event)"
(changePageNumber)="onChangePageNumber($event)"
(nextPage)="onNextPage($event)"
(prevPage)="onPrevPage($event)">
</adf-pagination>
<adf-infinite-pagination
[hidden]="!infiniteScrolling"
[target]="documentList"
[loading]="documentList.loading">
{{ 'ADF-DOCUMENT-LIST.LAYOUT.LOAD_MORE' | translate }}
</adf-infinite-pagination>
</adf-upload-drag-area>
<adf-info-drawer-layout *ngIf="showVersions" class="app-manage-versions-sidebar">
@@ -227,19 +291,17 @@
<adf-info-drawer [title]="'Details'" *ngIf="documentList.selection[0]">
<adf-info-drawer-tab label="Properties">
<adf-content-metadata
<adf-content-metadata-card
[node]="documentList.selection[0].entry"
[displayEmpty]="displayEmptyMetadata"
[displayTags]="true"
[displayCategories]="true">
</adf-content-metadata>
[displayEmpty]="displayEmptyMetadata">
</adf-content-metadata-card>
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Versions">
<ng-container *ngIf="hasOneFileSelected();else choose_document_template">
<ng-container *ngIf="userHasPermissionToManageVersions(); else no_permission_to_versions">
<adf-version-manager
[node]="documentList.selection[0].entry"
[showComments]="true"
[showComments]="showVersionComments"
[allowDownload]="allowVersionDownload">
</adf-version-manager>
</ng-container>
@@ -276,6 +338,18 @@
</div>
<div class="app-container">
<section>
<mat-slide-toggle [(ngModel)]="showNameColumn">
Show Name Column
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle [(ngModel)]="hyperlinkNavigation">
Hyperlink navigation
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle data-automation-id="multiSelectToggle" [(ngModel)]="multiselect">
Multiselect (with checkboxes)
@@ -306,18 +380,48 @@
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle id="adf-thumbnails-upload-switch" (click)="toggleThumbnails()">
Enable Thumbnails
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle id="adf-version-upload-switch" [(ngModel)]="versioning">
Enable versioning
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle (click)="onInfiniteScrolling()">
Enable Infinite Scrolling
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle [(ngModel)]="showVersionComments">
Show comments on versions
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle [(ngModel)]="allowVersionDownload">
Enable version download
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle [(ngModel)]="warnOnMultipleUploads">
Display warning for multiple uploads
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle [(ngModel)]="enableMediumTimeFormat" id="enableMediumTimeFormat">
Enable medium time format for document list
</mat-slide-toggle>
</section>
<section>
<mat-slide-toggle [(ngModel)]="displayEmptyMetadata" id="displayEmptyMetadata">
Display Empty Metadata
@@ -347,6 +451,7 @@
</section>
<div *ngIf="!acceptedFilesTypeShow">
<adf-upload-button
#uploadButton
[disabled]="!enableUpload"
[rootFolderId]="documentList.currentFolderId"
[multipleFiles]="multipleFileUpload"
@@ -356,11 +461,13 @@
[versioning]="versioning"
[adf-check-allowable-operation]="'create'"
[adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []"
(permissionEvent)="handlePermissionError($event)">
(permissionEvent)="handlePermissionError($event)"
(beginUpload)="onBeginUpload($event)">
</adf-upload-button>
</div>
<div *ngIf="acceptedFilesTypeShow">
<adf-upload-button
#uploadButton
[disabled]="!enableUpload"
[rootFolderId]="documentList.currentFolderId"
[acceptedFilesType]="acceptedFilesType"
@@ -1,5 +1,15 @@
.app-container:has(.app-document-list-container) {
margin: 10px;
.app-container {
margin: 10px !important;
}
@media screen and (max-width: 599px) {
.app-container {
margin: 0;
}
.app-show-versions-button.mat-icon-button {
display: none;
}
}
.app-error-message {
@@ -27,6 +37,18 @@
.app-document-action-buttons {
flex: 0 0 auto;
}
@media screen and (max-width: 600px) {
adf-breadcrumb, .app-document-action-buttons {
display: none;
}
}
@media screen and (min-width: 600px) {
adf-dropdown-breadcrumb, .app-toolbar-divider-before-more-menu, .app-toolbar-more-menu-button {
display: none;
}
}
}
&:not(.app-document-list-container-in-upload-drag-area) {
@@ -42,6 +64,13 @@
position: absolute;
}
.app-site-container-style {
margin-top: 10px;
margin-bottom: 10px;
width: 100%;
min-width: 200px;
}
.app-content-service-settings {
padding: 16px;
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -28,112 +28,46 @@ import {
Output,
ViewEncapsulation
} from '@angular/core';
import { Location } from '@angular/common';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { NodeEntry, NodePaging, Pagination, Node, SearchEntry } from '@alfresco/js-api';
import { NodeEntry, NodePaging, Pagination, Node, SiteEntry, SearchEntry } from '@alfresco/js-api';
import {
NotificationService,
DataRow,
UserPreferencesService,
PaginationComponent,
DisplayMode,
ShowHeaderMode,
FormRenderingService,
ToolbarTitleComponent,
ToolbarComponent,
ToolbarDividerComponent,
DataColumnComponent,
HighlightPipe,
DataColumnListComponent,
CustomEmptyContentTemplateDirective,
InfoDrawerTabComponent,
InfoDrawerComponent,
InfoDrawerLayoutComponent
InfinitePaginationComponent,
FormRenderingService
} from '@alfresco/adf-core';
import {
ContentService,
FolderCreatedEvent,
UploadService,
DocumentListComponent,
PermissionStyleModel,
UploadFilesEvent,
ConfirmDialogComponent,
ContentMetadataService,
FilterSearch,
DialogAspectListService,
FileUploadEvent,
NodesApiService,
UploadDragAreaComponent,
CheckAllowableOperationDirective,
BreadcrumbComponent,
DropdownBreadcrumbComponent,
NodeDownloadDirective,
NodeDeleteDirective,
NodeLockDirective,
ContentActionListComponent,
ContentActionComponent,
ContentMetadataComponent,
VersionManagerComponent,
UploadButtonComponent
NodesApiService
} from '@alfresco/adf-content-services';
import { ProcessFormRenderingService } from '@alfresco/adf-process-services';
import { VersionManagerDialogAdapterComponent } from './version-manager-dialog-adapter.component';
import { MetadataDialogAdapterComponent } from './metadata-dialog-adapter.component';
import { Subject } from 'rxjs';
import { PreviewService } from '../../services/preview.service';
import { takeUntil, debounceTime, scan } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { FolderCreateDirective } from '../../folder-directive';
import { MatMenuModule } from '@angular/material/menu';
import { TranslateModule } from '@ngx-translate/core';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatSelectModule } from '@angular/material/select';
const DEFAULT_FOLDER_TO_SHOW = '-my-';
@Component({
selector: 'app-files-component',
standalone: true,
imports: [
CommonModule,
UploadDragAreaComponent,
MatButtonModule,
MatIconModule,
CheckAllowableOperationDirective,
ToolbarTitleComponent,
ToolbarComponent,
BreadcrumbComponent,
DropdownBreadcrumbComponent,
DocumentListComponent,
FolderCreateDirective,
NodeDownloadDirective,
NodeDeleteDirective,
ToolbarDividerComponent,
MatMenuModule,
TranslateModule,
DataColumnComponent,
NodeLockDirective,
ContentActionListComponent,
ContentActionComponent,
PaginationComponent,
ContentMetadataComponent,
VersionManagerComponent,
MatSlideToggleModule,
FormsModule,
MatFormFieldModule,
MatInputModule,
UploadButtonComponent,
MatCheckboxModule,
MatSelectModule,
HighlightPipe,
DataColumnListComponent,
CustomEmptyContentTemplateDirective,
VersionManagerDialogAdapterComponent,
InfoDrawerTabComponent,
InfoDrawerComponent,
InfoDrawerLayoutComponent
],
templateUrl: './files.component.html',
styleUrls: ['./files.component.scss'],
encapsulation: ViewEncapsulation.None,
@@ -147,6 +81,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
showViewer = false;
showVersions = false;
allowDropFiles = true;
displayMode = DisplayMode.List;
includeFields = ['isFavorite', 'isLocked', 'aspectNames', 'definition'];
selectionModes = [
@@ -165,6 +100,12 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
@Input()
sortingMode: 'server' | 'client' = 'server';
@Input()
showRecentFiles = true;
@Input()
showSitePicker = true;
@Input()
showSettingsPanel = true;
@@ -189,6 +130,9 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
@Input()
maxSizeShow = false;
@Input()
showVersionComments = true;
@Input()
versioning = false;
@@ -213,6 +157,9 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
@Input()
disableDragArea = false;
@Input()
showNameColumn = true;
@Input()
searchTerm = '';
@@ -255,15 +202,24 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
@ViewChild('standardPagination')
standardPagination: PaginationComponent;
@ViewChild(InfinitePaginationComponent, { static: true })
infinitePaginationComponent: InfinitePaginationComponent;
permissionsStyle: PermissionStyleModel[] = [];
infiniteScrolling: boolean;
stickyHeader: boolean;
warnOnMultipleUploads = false;
thumbnails = false;
enableMediumTimeFormat = false;
displayEmptyMetadata = false;
hyperlinkNavigation = false;
constructor(
private notificationService: NotificationService,
private uploadService: UploadService,
private contentService: ContentService,
private dialog: MatDialog,
private location: Location,
private router: Router,
private preference: UserPreferencesService,
private preview: PreviewService,
@@ -271,7 +227,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
private contentMetadataService: ContentMetadataService,
private dialogAspectListService: DialogAspectListService,
private nodeService: NodesApiService
) { /* empty */ }
) {}
showFile(event) {
const entry = event.value.entry;
@@ -280,6 +236,11 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
}
}
toggleThumbnails() {
this.thumbnails = !this.thumbnails;
this.documentList.reload();
}
ngOnInit() {
if (!this.pagination) {
this.pagination = {
@@ -293,6 +254,10 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
if (params['id'] && this.currentFolderId !== params['id']) {
this.currentFolderId = params['id'];
}
if (params['mode'] && params['mode'] === DisplayMode.Gallery) {
this.displayMode = DisplayMode.Gallery;
}
});
}
@@ -380,7 +345,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
}
onFolderChange($event) {
this.router.navigate([this.navigationRoute, $event.value.id]);
this.router.navigate([this.navigationRoute, $event.value.id, 'display', this.displayMode]);
}
handlePermissionError(event: any) {
@@ -434,7 +399,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
onManageVersions(event: any) {
const contentEntry = event.value.entry;
const showComments = true;
const showComments = this.showVersionComments;
const allowDownload = this.allowVersionDownload;
if (this.contentService.hasAllowableOperations(contentEntry, 'update')) {
@@ -456,6 +421,28 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
});
}
onManageMetadata(event: any) {
const contentEntry = event.value.entry;
const displayEmptyMetadata = this.displayEmptyMetadata;
if (this.contentService.hasAllowableOperations(contentEntry, 'update')) {
this.dialog.open(MetadataDialogAdapterComponent, {
data: {
contentEntry,
displayEmptyMetadata
},
panelClass: 'adf-metadata-manager-dialog',
width: '630px'
});
} else {
this.openSnackMessageError('OPERATION.ERROR.PERMISSION');
}
}
onSiteChange(site: SiteEntry) {
this.currentFolderId = site.entry.guid;
}
hasSelection(selection: Array<any>): boolean {
return selection && selection.length > 0;
}
@@ -470,6 +457,24 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
return this.contentService.hasAllowableOperations(selection[0].entry, 'update');
}
getNodeNameTooltip(row: DataRow): string {
if (row) {
return row.getValue('name');
}
return null;
}
canEditFolder(selection: Array<NodeEntry>): boolean {
if (selection && selection.length === 1) {
const entry = selection[0].entry;
if (entry?.isFolder) {
return this.contentService.hasAllowableOperations(entry, 'update');
}
}
return false;
}
canCreateContent(parentNode: Node): boolean {
if (parentNode) {
return this.contentService.hasAllowableOperations(parentNode, 'create');
@@ -502,9 +507,44 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
this.turnedPreviousPage.emit(event);
}
toggleGalleryView(): void {
this.displayMode = this.displayMode === DisplayMode.List ? DisplayMode.Gallery : DisplayMode.List;
const url = this.router.createUrlTree(['/files', this.currentFolderId, 'display', this.displayMode]).toString();
this.location.go(url);
}
onInfiniteScrolling(): void {
this.infiniteScrolling = !this.infiniteScrolling;
this.infinitePaginationComponent.reset();
}
onBeginUpload(event: UploadFilesEvent) {
if (this.warnOnMultipleUploads && event) {
const files = event.files || [];
if (files.length > 1) {
event.pauseUpload();
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
data: {
title: 'Upload',
message: `Are you sure you want to upload ${files.length} file(s)?`
},
minWidth: '250px'
});
dialogRef.afterClosed().subscribe((result) => {
if (result === true) {
event.resumeUpload();
}
});
}
}
}
onUploadNewVersion(ev) {
const contentEntry = ev.detail.data.node.entry;
const showComments = true;
const showComments = this.showVersionComments;
const allowDownload = this.allowVersionDownload;
const newFileVersion = ev.detail.files[0].file;
@@ -545,7 +585,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
}
navigateToFilter(activeFilters: FilterSearch[]) {
const objectFromMap = { /* empty */ };
const objectFromMap = {};
activeFilters.forEach((filter: FilterSearch) => {
let paramValue = null;
if (filter.value?.from && filter.value.to) {
@@ -564,7 +604,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
if (this.currentFolderId === '-my-') {
this.router.navigate([this.navigationRoute, '']);
} else {
this.router.navigate([this.navigationRoute, this.currentFolderId]);
this.router.navigate([this.navigationRoute, this.currentFolderId, 'display', this.displayMode]);
}
this.documentList.reload();
}
@@ -0,0 +1,10 @@
<header mat-dialog-title>Metadata</header>
<section mat-dialog-content>
<adf-content-metadata-card
[node]="contentEntry"
[displayEmpty]="displayEmptyMetadata">
</adf-content-metadata-card>
</section>
<footer mat-dialog-actions>
<button mat-button (click)="close()">Close</button>
</footer>
@@ -0,0 +1,38 @@
/*!
* @license
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Node } from '@alfresco/js-api';
@Component({
templateUrl: './metadata-dialog-adapter.component.html',
encapsulation: ViewEncapsulation.None
})
export class MetadataDialogAdapterComponent {
contentEntry: Node;
displayEmptyMetadata = false;
constructor(@Inject(MAT_DIALOG_DATA) data: any, private containingDialog?: MatDialogRef<MetadataDialogAdapterComponent>) {
this.contentEntry = data.contentEntry;
this.displayEmptyMetadata = data.displayEmptyMetadata;
}
close() {
this.containingDialog.close();
}
}
@@ -1,6 +1,6 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
* Copyright © 2005-2023 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.
@@ -16,20 +16,14 @@
*/
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Node } from '@alfresco/js-api';
import { PreviewService } from '../../services/preview.service';
import { NotificationService } from '@alfresco/adf-core';
import { FileUploadErrorEvent, VersionListComponent, VersionManagerComponent } from '@alfresco/adf-content-services';
import { CommonModule } from '@angular/common';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { FileUploadErrorEvent } from '@alfresco/adf-content-services';
@Component({
templateUrl: './version-manager-dialog-adapter.component.html',
standalone: true,
imports: [CommonModule, MatDialogModule, MatSlideToggleModule, FormsModule, VersionManagerComponent, VersionListComponent, MatButtonModule],
encapsulation: ViewEncapsulation.None
})
export class VersionManagerDialogAdapterComponent {

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