mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
ACS-8610: cleanup demo shell protractor tests (#10148)
This commit is contained in:
parent
a754976ad9
commit
f1208d45c3
@ -10,10 +10,7 @@ node_modules
|
||||
scripts
|
||||
src
|
||||
lib
|
||||
integration
|
||||
tools
|
||||
demo-shell/src/
|
||||
demo-shell/resources/
|
||||
/angular.json
|
||||
/desktop.ini
|
||||
/cspell.json
|
||||
@ -21,5 +18,4 @@ demo-shell/resources/
|
||||
/.stylelintignore
|
||||
/ALFRESCOCORS.md
|
||||
/CONTRIBUTING.md
|
||||
/appveyor.yml
|
||||
/BROWSER-SUPPORT.md
|
||||
|
@ -18,7 +18,7 @@ module.exports = {
|
||||
{
|
||||
files: ['*.ts'],
|
||||
parserOptions: {
|
||||
project: ['tsconfig.json', 'e2e/tsconfig.e2e.json'],
|
||||
project: ['tsconfig.json'],
|
||||
createDefaultProgram: true
|
||||
},
|
||||
extends: [
|
||||
|
92
.github/actions/artifact-append/action.yml
vendored
92
.github/actions/artifact-append/action.yml
vendored
@ -1,92 +0,0 @@
|
||||
name: Append content to Artifact
|
||||
description: 'Allow the user to append content to an existing artifact'
|
||||
|
||||
inputs:
|
||||
artifact-name:
|
||||
description: 'The name of the artifact'
|
||||
required: true
|
||||
type: string
|
||||
file-name:
|
||||
description: 'The name of the file with extension created in the artifact'
|
||||
required: true
|
||||
type: string
|
||||
content:
|
||||
description: 'The content to append'
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
steps:
|
||||
- run: echo "Artifact Append"
|
||||
shell: bash
|
||||
- name: Download artifact
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
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
|
||||
env:
|
||||
contentFile: ${{ inputs.content }}
|
||||
fileName: ${{ inputs.file-name }}
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
const affectedLib = process.env.contentFile;
|
||||
const fileName = process.env.fileName;
|
||||
core.info(`Input Filename: ${fileName}`);
|
||||
core.info(`Input content: ${affectedLib}`);
|
||||
|
||||
const content = read(fileName)
|
||||
core.info(`File content: ${content}`);
|
||||
appendContent(content, affectedLib);
|
||||
|
||||
function read(filename) {
|
||||
try {
|
||||
const contentFile = fs.readFileSync(filename, 'utf8').replace('\n','');
|
||||
return contentFile;
|
||||
} catch (err) {
|
||||
core.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function write(filename, content) {
|
||||
try {
|
||||
fs.writeFileSync(filename, content);
|
||||
} catch (err) {
|
||||
core.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function appendContent(content, append) {
|
||||
let changedContent;
|
||||
const libs = content.split(' ');
|
||||
if (libs?.length>0) {
|
||||
if (libs.length === 1 && libs[0] === '') {
|
||||
libs[0] = append;
|
||||
changedContent = libs[0];
|
||||
}
|
||||
else if (!libs.includes(append)) {
|
||||
libs.push(append);
|
||||
changedContent = libs.join(' ');
|
||||
} else {
|
||||
core.info(`Lib ${append} already affected`);
|
||||
}
|
||||
}
|
||||
if (changedContent != undefined){
|
||||
core.info(`File content append: ${changedContent}`)
|
||||
write(fileName, changedContent);
|
||||
}
|
||||
}
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: ${{ inputs.artifact-name }}
|
||||
path: ${{ inputs.file-name }}
|
||||
|
42
.github/actions/artifact-extract/action.yml
vendored
42
.github/actions/artifact-extract/action.yml
vendored
@ -1,42 +0,0 @@
|
||||
name: Extract Artifact
|
||||
description: 'Allow the user to extract content from an artifact'
|
||||
|
||||
inputs:
|
||||
artifact-name:
|
||||
description: 'The name of the artifact'
|
||||
required: true
|
||||
type: string
|
||||
file-name:
|
||||
description: 'The name of the file with extension created in the artifact'
|
||||
required: true
|
||||
type: string
|
||||
content:
|
||||
description: 'The init content the file should have'
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
outputs:
|
||||
result:
|
||||
description: "the value extrated from the file inside the artifact"
|
||||
value: ${{ steps.extract.outputs.result }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- run: echo "Artifact Extract"
|
||||
shell: bash
|
||||
- name: Download artifact
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: ${{ inputs.artifact-name }}
|
||||
pattern: ${{ inputs.artifact-name }}-*
|
||||
merge-multiple: true
|
||||
- id: extract
|
||||
shell: bash
|
||||
run: |
|
||||
value=`cat ${{ inputs.file-name }}`
|
||||
echo "print $value"
|
||||
echo "result=$value" >> $GITHUB_OUTPUT
|
||||
|
32
.github/actions/artifact-initialize/action.yml
vendored
32
.github/actions/artifact-initialize/action.yml
vendored
@ -1,32 +0,0 @@
|
||||
name: Initialize Artifact
|
||||
description: 'Allow the user to initialize an empty artifact used globally'
|
||||
|
||||
inputs:
|
||||
artifact-name:
|
||||
description: 'The name of the artifact'
|
||||
required: true
|
||||
type: string
|
||||
file-name:
|
||||
description: 'The name of the file with extension created in the artifact'
|
||||
required: true
|
||||
type: string
|
||||
content:
|
||||
description: 'The init content the file should have'
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Create empty artifact
|
||||
shell: bash
|
||||
run:
|
||||
echo "${{inputs.content}}" > ${{ inputs.file-name }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: ${{ inputs.artifact-name }}
|
||||
path: ${{ inputs.file-name }}
|
204
.github/actions/e2e/action.yml
vendored
204
.github/actions/e2e/action.yml
vendored
@ -1,204 +0,0 @@
|
||||
name: "e2e"
|
||||
description: "e2e"
|
||||
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
|
||||
e2e-test-provider:
|
||||
description: "Test provider"
|
||||
required: true
|
||||
e2e-test-auth:
|
||||
description: "Test auth"
|
||||
required: true
|
||||
output:
|
||||
description: "Output path"
|
||||
required: true
|
||||
check-cs-env:
|
||||
required: true
|
||||
description: check cs env
|
||||
default: "false"
|
||||
check-ps-env:
|
||||
required: true
|
||||
description: check ps env
|
||||
default: "false"
|
||||
check-external-cs-env:
|
||||
required: true
|
||||
description: check external cs env
|
||||
default: "false"
|
||||
check-ps-cloud-env:
|
||||
required: true
|
||||
description: check ps cloud env
|
||||
default: "false"
|
||||
e2e-tar-name: #
|
||||
description: tarball name
|
||||
required: false
|
||||
default: e2e.tar.gz
|
||||
apa-proxy: #
|
||||
description: "proxy host"
|
||||
required: true
|
||||
deps:
|
||||
description: "Library dependencies"
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Determine if affected
|
||||
shell: bash
|
||||
id: determine-affected
|
||||
run: |
|
||||
isAffected=false
|
||||
affectedLibs=$(npx nx print-affected --type=lib --select=projects ${NX_CALCULATION_FLAGS} --plain)
|
||||
if [[ $affectedLibs =~ "${{ inputs.e2e-test-id }}" ]]; then
|
||||
isAffected=true
|
||||
fi;
|
||||
echo "Determine if ${{ inputs.e2e-test-id }} is affected: $isAffected";
|
||||
echo "isAffected=$isAffected" >> $GITHUB_OUTPUT
|
||||
- name: print value
|
||||
shell: bash
|
||||
run: |
|
||||
echo "value: ${{ steps.determine-affected.outputs.isAffected }}"
|
||||
- name: use APA as PROXY host if apa-proxy is set
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -n "${{ inputs.apa-proxy }}" ]]; then
|
||||
echo "APA proxy set."
|
||||
echo "PROXY_HOST_BPM=${E2E_HOST_APA}" >> $GITHUB_ENV
|
||||
echo "PROXY_HOST_ECM=${E2E_IDENTITY_HOST_APA}" >> $GITHUB_ENV
|
||||
echo "HOST_SSO=${E2E_IDENTITY_HOST_APA}" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: install aws cli
|
||||
shell: bash
|
||||
run: pip install awscli
|
||||
- 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
|
||||
run: |
|
||||
set -u;
|
||||
mkdir -p "${SMART_RUNNER_PATH}"
|
||||
if [[ $(aws s3 ls "s3://${S3_BUILD_BUCKET_SHORT_NAME}/adf/${REMOTE_PATH}" > /dev/null; echo $?) -eq 0 ]]; then
|
||||
echo "downloading test files"
|
||||
aws s3 cp "s3://${S3_BUILD_BUCKET_SHORT_NAME}/adf/${REMOTE_PATH}" .;
|
||||
tar xzf ${{ inputs.e2e-tar-name }};
|
||||
else
|
||||
echo "nothing to download";
|
||||
fi
|
||||
|
||||
- name: check EXTERNAL-CS is UP
|
||||
shell: bash
|
||||
if: ${{ inputs.check-external-cs-env == 'true' && steps.determine-affected.outputs.isAffected == 'true' }}
|
||||
run: |
|
||||
echo "running: check EXTERNAL-CS is UP"
|
||||
set -u;
|
||||
./node_modules/@alfresco/adf-cli/bin/adf-cli \
|
||||
check-cs-env \
|
||||
--host "$EXTERNAL_ACS_HOST" \
|
||||
-u "$E2E_USERNAME" \
|
||||
-p "$E2E_PASSWORD" || exit 1
|
||||
|
||||
- name: Check CS is UP
|
||||
shell: bash
|
||||
if: ${{ inputs.check-cs-env == 'true' && steps.determine-affected.outputs.isAffected == 'true' }}
|
||||
run: |
|
||||
echo "Running: Check CS is UP"
|
||||
set -u;
|
||||
./node_modules/@alfresco/adf-cli/bin/adf-cli \
|
||||
check-cs-env \
|
||||
--host "$E2E_HOST" \
|
||||
-u "$E2E_USERNAME" \
|
||||
-p "$E2E_PASSWORD" || exit 1
|
||||
|
||||
- name: check PS is UP
|
||||
shell: bash
|
||||
if: ${{ inputs.check-ps-env == 'true' && steps.determine-affected.outputs.isAffected == 'true' }}
|
||||
run: |
|
||||
echo "Running: check PS is UP"
|
||||
set -u;
|
||||
./node_modules/@alfresco/adf-cli/bin/adf-cli init-aps-env \
|
||||
--host "$E2E_HOST" \
|
||||
-u "$E2E_USERNAME" \
|
||||
-p "$E2E_PASSWORD" \
|
||||
--license "$AWS_S3_BUCKET_ACTIVITI_LICENSE" || exit 1
|
||||
|
||||
- name: check PS-CLOUD is UP
|
||||
shell: bash
|
||||
if: ${{ inputs.check-ps-cloud-env == 'true' && steps.determine-affected.outputs.isAffected == 'true' }}
|
||||
run: |
|
||||
echo "running: check PS-CLOUD is UP"
|
||||
set -u;
|
||||
./node_modules/@alfresco/adf-cli/bin/adf-cli init-aae-env \
|
||||
--oauth "$E2E_IDENTITY_HOST_APA" \
|
||||
--host "$E2E_HOST_APA" \
|
||||
--modelerUsername "$E2E_MODELER_USERNAME" \
|
||||
--modelerPassword "$E2E_MODELER_PASSWORD" \
|
||||
--devopsUsername "$E2E_DEVOPS_USERNAME" \
|
||||
--devopsPassword "$E2E_DEVOPS_PASSWORD" \
|
||||
--clientId 'alfresco' || exit 1
|
||||
|
||||
- name: variables sanitization
|
||||
env:
|
||||
FOLDER: "${{ inputs.e2e-test-folder }}"
|
||||
PROVIDER: "${{ inputs.e2e-test-provider }}"
|
||||
AUTH_TYPE: "${{ inputs.e2e-test-auth }}"
|
||||
E2E_TEST_ID: "${{ inputs.e2e-test-id }}"
|
||||
DEPS: "${{ inputs.deps }}"
|
||||
shell: bash
|
||||
run: |
|
||||
set -u;
|
||||
echo $PROXY_HOST_BPM
|
||||
echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV
|
||||
|
||||
- name: run test
|
||||
id: e2e_run
|
||||
if: ${{ steps.determine-affected.outputs.isAffected == 'true' }}
|
||||
env:
|
||||
FOLDER: "${{ inputs.e2e-test-folder }}"
|
||||
PROVIDER: "${{ inputs.e2e-test-provider }}"
|
||||
AUTH_TYPE: "${{ inputs.e2e-test-auth }}"
|
||||
E2E_TEST_ID: "${{ inputs.e2e-test-id }}"
|
||||
DEPS: "${{ inputs.deps }}"
|
||||
shell: bash
|
||||
run: |
|
||||
set -u;
|
||||
if [[ ${{ inputs.e2e-test-folder }} == 'content-services/upload' ]]; then
|
||||
export DISPLAY=:99
|
||||
chromedriver --url-base=/wd/hub &
|
||||
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 & # optional
|
||||
bash ./scripts/github/e2e/e2e.sh "$E2E_TEST_ID" "$DEPS" "browser" || exit 1
|
||||
else
|
||||
bash ./scripts/github/e2e/e2e.sh "$E2E_TEST_ID" "$DEPS" || exit 1
|
||||
fi
|
||||
- name: Trace failing e2e
|
||||
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 }}"
|
||||
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@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: e2e-artifact-output-${{inputs.e2e-artifact-id}}
|
||||
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"
|
||||
# description: always upload newer results
|
||||
run: |
|
||||
tar czf "${{ inputs.e2e-tar-name }}" "${SMART_RUNNER_PATH}"
|
||||
aws s3 cp "${{ inputs.e2e-tar-name }}" "s3://${S3_BUILD_BUCKET_SHORT_NAME}/adf/${REMOTE_PATH}"
|
13
.github/actions/setup-chrome/action.yml
vendored
13
.github/actions/setup-chrome/action.yml
vendored
@ -1,13 +0,0 @@
|
||||
name: 'Install Google Chrome'
|
||||
description: 'Install Google Chrome'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install google chrome
|
||||
shell: bash
|
||||
run: |
|
||||
wget -q https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_114.0.5735.133-1_amd64.deb
|
||||
sudo apt install -y --allow-downgrades ./google-chrome-stable_114.0.5735.133-1_amd64.deb
|
||||
sudo ln -s /usr/bin/google-chrome /usr/bin/chrome
|
||||
chrome --version
|
20
.github/dependabot.yml
vendored
20
.github/dependabot.yml
vendored
@ -30,18 +30,6 @@ updates:
|
||||
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:
|
||||
@ -50,10 +38,6 @@ updates:
|
||||
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:
|
||||
@ -78,10 +62,6 @@ updates:
|
||||
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:
|
||||
|
87
.github/workflows/cron-e2e.yml
vendored
87
.github/workflows/cron-e2e.yml
vendored
@ -1,87 +0,0 @@
|
||||
name: "cron e2e daily"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 12 * * 1-5' #At 12:00 on every day-of-week from Monday through Friday.
|
||||
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
GITHUB_BRANCH: ${{ github.ref_name }}
|
||||
GH_BUILD_DIR: ${{ github.workspace }}
|
||||
GH_COMMIT: ${{ github.sha }}
|
||||
BUILD_ID: ${{ github.run_id }}
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
PROXY_HOST_BPM: ${{ secrets.E2E_HOST }}
|
||||
E2E_HOST_APA: ${{ secrets.E2E_HOST_APA }}
|
||||
E2E_IDENTITY_HOST_APA: ${{ secrets.E2E_IDENTITY_HOST_APA }}
|
||||
E2E_HOST: ${{ secrets.E2E_HOST }}
|
||||
E2E_USERNAME: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
|
||||
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
USERNAME_ADF: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
PASSWORD_ADF: ${{ secrets.E2E_PASSWORD }}
|
||||
URL_HOST_ADF: "http://localhost:4200"
|
||||
IDENTITY_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
IDENTITY_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
AWS_S3_BUCKET_ACTIVITI_LICENSE: ${{ secrets.AWS_S3_BUCKET_ACTIVITI_LICENSE }}
|
||||
HOST_SSO: ${{ secrets.HOST_SSO }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
E2E_LOG_LEVEL: "ERROR"
|
||||
E2E_MODELER_USERNAME: ${{ secrets.E2E_MODELER_USERNAME }}
|
||||
E2E_MODELER_PASSWORD: ${{ secrets.E2E_MODELER_PASSWORD }}
|
||||
EXTERNAL_ACS_HOST: ${{ secrets.EXTERNAL_ACS_HOST }}
|
||||
E2E_DEVOPS_USERNAME: ${{ secrets.E2E_DEVOPS_USERNAME }}
|
||||
E2E_DEVOPS_PASSWORD: ${{ secrets.E2E_DEVOPS_PASSWORD }}
|
||||
USERNAME_SUPER_ADMIN_ADF: ${{ secrets.USERNAME_SUPER_ADMIN_ADF }}
|
||||
PASSWORD_SUPER_ADMIN_ADF: ${{ secrets.PASSWORD_SUPER_ADMIN_ADF }}
|
||||
HR_USER: ${{ secrets.HR_USER }}
|
||||
HR_USER_PASSWORD: ${{ secrets.HR_USER_PASSWORD }}
|
||||
SMART_RUNNER_PATH: ".protractor-smartrunner"
|
||||
S3_DBP_PATH: ${{ secrets.S3_DBP_PATH }}
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
DOCKER_REPOSITORY: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/demo-shell"
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
DEMO_SHELL_DIR: "./dist/demo-shell"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
SMART_RUNNER_DIRECTORY: ".protractor-smartrunner"
|
||||
SAVE_SCREENSHOT: true
|
||||
REDIRECT_URI: /
|
||||
BROWSER_RUN: false
|
||||
MAXINSTANCES: 2
|
||||
PLAYWRIGHT_WORKERS: 2
|
||||
PLAYWRIGHT_STORYBOOK_E2E_HOST: http://localhost
|
||||
PLAYWRIGHT_STORYBOOK_E2E_PORT: 4400
|
||||
PROXY_HOST_ECM: ${{ secrets.E2E_HOST }}
|
||||
|
||||
jobs:
|
||||
init-artifact:
|
||||
runs-on: ubuntu-latest
|
||||
name: Initialize artifacts
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: ./.github/actions/artifact-initialize
|
||||
with:
|
||||
artifact-name: global-e2e-result
|
||||
file-name: e2e-failures.txt
|
||||
|
||||
run-e2e:
|
||||
name: run e2e
|
||||
uses: ./.github/workflows/pull-request.yml
|
||||
with:
|
||||
cron-run: true
|
||||
secrets: inherit
|
37
.github/workflows/git-tag.yml
vendored
37
.github/workflows/git-tag.yml
vendored
@ -25,59 +25,22 @@ env:
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
PROXY_HOST_BPM: ${{ secrets.E2E_HOST }}
|
||||
E2E_IDENTITY_HOST_APA: ${{ secrets.E2E_IDENTITY_HOST_APA }}
|
||||
E2E_HOST_APA: ${{ secrets.E2E_HOST_APA }}
|
||||
E2E_HOST: ${{ secrets.E2E_HOST }}
|
||||
E2E_USERNAME: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
|
||||
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
USERNAME_ADF: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
PASSWORD_ADF: ${{ secrets.E2E_PASSWORD }}
|
||||
URL_HOST_ADF: "http://localhost:4200"
|
||||
IDENTITY_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
IDENTITY_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
AWS_S3_BUCKET_ACTIVITI_LICENSE: ${{ secrets.AWS_S3_BUCKET_ACTIVITI_LICENSE }}
|
||||
HOST_SSO: ${{ secrets.HOST_SSO }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
E2E_LOG_LEVEL: "ERROR"
|
||||
E2E_MODELER_USERNAME: ${{ secrets.E2E_MODELER_USERNAME }}
|
||||
E2E_MODELER_PASSWORD: ${{ secrets.E2E_MODELER_PASSWORD }}
|
||||
EXTERNAL_ACS_HOST: ${{ secrets.EXTERNAL_ACS_HOST }}
|
||||
E2E_DEVOPS_USERNAME: ${{ secrets.E2E_DEVOPS_USERNAME }}
|
||||
E2E_DEVOPS_PASSWORD: ${{ secrets.E2E_DEVOPS_PASSWORD }}
|
||||
USERNAME_SUPER_ADMIN_ADF: ${{ secrets.USERNAME_SUPER_ADMIN_ADF }}
|
||||
PASSWORD_SUPER_ADMIN_ADF: ${{ secrets.PASSWORD_SUPER_ADMIN_ADF }}
|
||||
HR_USER: ${{ secrets.HR_USER }}
|
||||
HR_USER_PASSWORD: ${{ secrets.HR_USER_PASSWORD }}
|
||||
SMART_RUNNER_PATH: ".protractor-smartrunner"
|
||||
S3_DBP_PATH: ${{ secrets.S3_DBP_PATH }}
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
DOCKER_REPOSITORY: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/demo-shell"
|
||||
NPM_REGISTRY_ADDRESS: ${{ secrets.NPM_REGISTRY_ADDRESS }}
|
||||
NPM_REGISTRY_TOKEN: ${{ secrets.NPM_REGISTRY_TOKEN }}
|
||||
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
DEMO_SHELL_DIR: "./dist/demo-shell"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
SMART_RUNNER_DIRECTORY: ".protractor-smartrunner"
|
||||
SAVE_SCREENSHOT: true
|
||||
REDIRECT_URI: /
|
||||
BROWSER_RUN: false
|
||||
MAXINSTANCES: 2
|
||||
PLAYWRIGHT_WORKERS: 2
|
||||
PLAYWRIGHT_STORYBOOK_E2E_HOST: http://localhost
|
||||
PLAYWRIGHT_STORYBOOK_E2E_PORT: 4400
|
||||
PROXY_HOST_ECM: ${{ secrets.E2E_HOST }}
|
||||
|
||||
jobs:
|
||||
|
||||
|
228
.github/workflows/pull-request.yml
vendored
228
.github/workflows/pull-request.yml
vendored
@ -42,56 +42,19 @@ env:
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
PROXY_HOST_BPM: ${{ secrets.E2E_HOST }}
|
||||
E2E_IDENTITY_HOST_APA: ${{ secrets.E2E_IDENTITY_HOST_APA }}
|
||||
E2E_HOST_APA: ${{ secrets.E2E_HOST_APA }}
|
||||
E2E_HOST: ${{ secrets.E2E_HOST }}
|
||||
E2E_USERNAME: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
|
||||
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
USERNAME_ADF: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
PASSWORD_ADF: ${{ secrets.E2E_PASSWORD }}
|
||||
URL_HOST_ADF: "http://localhost:4200"
|
||||
IDENTITY_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
IDENTITY_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
AWS_S3_BUCKET_ACTIVITI_LICENSE: ${{ secrets.AWS_S3_BUCKET_ACTIVITI_LICENSE }}
|
||||
HOST_SSO: ${{ secrets.HOST_SSO }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
E2E_LOG_LEVEL: "ERROR"
|
||||
E2E_MODELER_USERNAME: ${{ secrets.E2E_MODELER_USERNAME }}
|
||||
E2E_MODELER_PASSWORD: ${{ secrets.E2E_MODELER_PASSWORD }}
|
||||
EXTERNAL_ACS_HOST: ${{ secrets.EXTERNAL_ACS_HOST }}
|
||||
E2E_DEVOPS_USERNAME: ${{ secrets.E2E_DEVOPS_USERNAME }}
|
||||
E2E_DEVOPS_PASSWORD: ${{ secrets.E2E_DEVOPS_PASSWORD }}
|
||||
USERNAME_SUPER_ADMIN_ADF: ${{ secrets.USERNAME_SUPER_ADMIN_ADF }}
|
||||
PASSWORD_SUPER_ADMIN_ADF: ${{ secrets.PASSWORD_SUPER_ADMIN_ADF }}
|
||||
HR_USER: ${{ secrets.HR_USER }}
|
||||
HR_USER_PASSWORD: ${{ secrets.HR_USER_PASSWORD }}
|
||||
SMART_RUNNER_PATH: ".protractor-smartrunner"
|
||||
S3_DBP_PATH: ${{ secrets.S3_DBP_PATH }}
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
DOCKER_REPOSITORY: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/demo-shell"
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
DEMO_SHELL_DIR: "./dist/demo-shell"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
SMART_RUNNER_DIRECTORY: ".protractor-smartrunner"
|
||||
SAVE_SCREENSHOT: true
|
||||
REDIRECT_URI: /
|
||||
BROWSER_RUN: false
|
||||
MAXINSTANCES: 2
|
||||
PLAYWRIGHT_WORKERS: 2
|
||||
PLAYWRIGHT_STORYBOOK_E2E_HOST: http://localhost
|
||||
PLAYWRIGHT_STORYBOOK_E2E_PORT: 4400
|
||||
PROXY_HOST_ECM: ${{ secrets.E2E_HOST }}
|
||||
|
||||
jobs:
|
||||
pre-checks:
|
||||
@ -273,198 +236,9 @@ jobs:
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- run: npx nx affected:build $NX_CALCULATION_FLAGS --prod
|
||||
- run: npx nx build demoshell --configuration production
|
||||
- run: npx nx affected --target=build-storybook $NX_CALCULATION_FLAGS --configuration=ci --parallel=1
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
e2e-storybook:
|
||||
timeout-minutes: 20
|
||||
name: "e2e: storybook"
|
||||
needs: [build-libs, lint, unit-tests]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- name: Process Cloud Storybook Playwright
|
||||
run: |
|
||||
npx playwright install chromium
|
||||
sudo sysctl -w fs.inotify.max_user_watches=524288
|
||||
npx nx affected --target=e2e-playwright $NX_CALCULATION_FLAGS || exit 1
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
e2e:
|
||||
timeout-minutes: 90
|
||||
name: "e2e: ${{ matrix.e2e-test.description }}"
|
||||
needs: [build-libs, lint, unit-tests]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# max-parallel: 4
|
||||
matrix:
|
||||
e2e-test:
|
||||
- description: "Core"
|
||||
test-id: "core"
|
||||
artifact-id: "core"
|
||||
folder: "core"
|
||||
provider: "ALL"
|
||||
auth: "OAUTH"
|
||||
check-cs-env: "true"
|
||||
check-ps-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Content: Components"
|
||||
test-id: "content-services"
|
||||
artifact-id: "content-services-components"
|
||||
folder: "content-services/components"
|
||||
provider: "ECM"
|
||||
auth: "BASIC"
|
||||
check-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Content: Directives"
|
||||
test-id: "content-services"
|
||||
artifact-id: "content-services-directives"
|
||||
folder: "content-services/directives"
|
||||
provider: "ECM"
|
||||
auth: "BASIC"
|
||||
check-cs-env: "true"
|
||||
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"
|
||||
check-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Content: Metadata"
|
||||
test-id: "content-services"
|
||||
artifact-id: "content-services-metadata"
|
||||
folder: "content-services/metadata"
|
||||
provider: "ECM"
|
||||
auth: "BASIC"
|
||||
check-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Content: Upload and Versioning"
|
||||
test-id: "content-services"
|
||||
artifact-id: "content-services-upload"
|
||||
folder: "content-services/upload"
|
||||
provider: "ECM"
|
||||
auth: "BASIC"
|
||||
check-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Search"
|
||||
test-id: "content-services"
|
||||
artifact-id: "content-services-search"
|
||||
folder: "search"
|
||||
provider: "ECM"
|
||||
auth: "BASIC"
|
||||
check-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Process: Form"
|
||||
test-id: "process-services"
|
||||
artifact-id: "process-services-form"
|
||||
folder: "process-services/form"
|
||||
provider: "BPM"
|
||||
auth: "OAUTH"
|
||||
check-ps-env: "true"
|
||||
check-external-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Process: Process"
|
||||
test-id: "process-services"
|
||||
artifact-id: "process-services-process"
|
||||
folder: "process-services/process"
|
||||
provider: "BPM"
|
||||
auth: "OAUTH"
|
||||
check-ps-env: "true"
|
||||
check-external-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Process: Tasks"
|
||||
test-id: "process-services"
|
||||
artifact-id: "process-services-tasks"
|
||||
folder: "process-services/tasks"
|
||||
provider: "BPM"
|
||||
auth: "OAUTH"
|
||||
check-ps-env: "true"
|
||||
check-external-cs-env: "true"
|
||||
deps: "testing"
|
||||
- description: "Process: Widget"
|
||||
test-id: "process-services"
|
||||
artifact-id: "process-services-widgets"
|
||||
folder: "process-services/widgets"
|
||||
provider: "BPM"
|
||||
auth: "OAUTH"
|
||||
check-ps-env: "true"
|
||||
check-external-cs-env: "true"
|
||||
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"
|
||||
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"
|
||||
apa-proxy: true
|
||||
check-cs-env: "true"
|
||||
check-ps-cloud-env: "true"
|
||||
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"
|
||||
apa-proxy: true
|
||||
check-cs-env: "true"
|
||||
check-ps-cloud-env: "true"
|
||||
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"
|
||||
apa-proxy: true
|
||||
check-cs-env: "true"
|
||||
check-ps-cloud-env: "true"
|
||||
deps: "testing"
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for all
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: "true"
|
||||
enable-node-modules-cache: "true"
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- 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 }}
|
||||
check-ps-env: ${{ matrix.e2e-test.check-ps-env }}
|
||||
check-ps-cloud-env: ${{ matrix.e2e-test.check-ps-cloud-env }}
|
||||
check-external-cs-env: ${{ matrix.e2e-test.check-external-cs-env }}
|
||||
apa-proxy: ${{ matrix.e2e-test.apa-proxy }}
|
||||
deps: ${{ matrix.e2e-test.deps }}
|
||||
|
||||
PR-forbidden-labels:
|
||||
if: ${{ inputs.cron-run == '' || inputs.cron-run == 'false' }}
|
||||
runs-on: ubuntu-latest
|
||||
@ -496,7 +270,7 @@ 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, pre-checks, setup, unit-tests, lint, build-libs]
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: identify-slack-group
|
||||
|
39
.github/workflows/release-branch.yml
vendored
39
.github/workflows/release-branch.yml
vendored
@ -22,57 +22,20 @@ env:
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
PROXY_HOST_BPM: ${{ secrets.E2E_HOST }}
|
||||
E2E_IDENTITY_HOST_APA: ${{ secrets.E2E_IDENTITY_HOST_APA }}
|
||||
E2E_HOST_APA: ${{ secrets.E2E_HOST_APA }}
|
||||
E2E_HOST: ${{ secrets.E2E_HOST }}
|
||||
E2E_USERNAME: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
|
||||
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
#USERNAME_ADF: ${{ secrets.E2E_USERNAME }}
|
||||
USERNAME_ADF: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
PASSWORD_ADF: ${{ secrets.E2E_PASSWORD }}
|
||||
URL_HOST_ADF: "http://localhost:4200"
|
||||
IDENTITY_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
IDENTITY_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
AWS_S3_BUCKET_ACTIVITI_LICENSE: ${{ secrets.AWS_S3_BUCKET_ACTIVITI_LICENSE }}
|
||||
HOST_SSO: ${{ secrets.HOST_SSO }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
E2E_LOG_LEVEL: "ERROR"
|
||||
E2E_MODELER_USERNAME: ${{ secrets.E2E_MODELER_USERNAME }}
|
||||
E2E_MODELER_PASSWORD: ${{ secrets.E2E_MODELER_PASSWORD }}
|
||||
EXTERNAL_ACS_HOST: ${{ secrets.EXTERNAL_ACS_HOST }}
|
||||
E2E_DEVOPS_USERNAME: ${{ secrets.E2E_DEVOPS_USERNAME }}
|
||||
E2E_DEVOPS_PASSWORD: ${{ secrets.E2E_DEVOPS_PASSWORD }}
|
||||
USERNAME_SUPER_ADMIN_ADF: ${{ secrets.USERNAME_SUPER_ADMIN_ADF }}
|
||||
PASSWORD_SUPER_ADMIN_ADF: ${{ secrets.PASSWORD_SUPER_ADMIN_ADF }}
|
||||
HR_USER: ${{ secrets.HR_USER }}
|
||||
HR_USER_PASSWORD: ${{ secrets.HR_USER_PASSWORD }}
|
||||
SMART_RUNNER_PATH: ".protractor-smartrunner"
|
||||
S3_DBP_PATH: ${{ secrets.S3_DBP_PATH }}
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
DOCKER_REPOSITORY: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/demo-shell"
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
DEMO_SHELL_DIR: "./dist/demo-shell"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
SMART_RUNNER_DIRECTORY: ".protractor-smartrunner"
|
||||
SAVE_SCREENSHOT: true
|
||||
REDIRECT_URI: /
|
||||
BROWSER_RUN: false
|
||||
MAXINSTANCES: 2
|
||||
PLAYWRIGHT_WORKERS: 2
|
||||
PLAYWRIGHT_STORYBOOK_E2E_HOST: http://localhost
|
||||
PLAYWRIGHT_STORYBOOK_E2E_PORT: 4400
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
@ -135,7 +98,7 @@ jobs:
|
||||
setMigrations();
|
||||
- name: Build libraries
|
||||
run: |
|
||||
npx nx affected:build $NX_CALCULATION_FLAGS --prod --exclude="demoshell" --skip-nx-cache
|
||||
npx nx affected:build $NX_CALCULATION_FLAGS --prod --skip-nx-cache
|
||||
npx nx affected $NX_CALCULATION_FLAGS --target=pretheme
|
||||
npx nx affected $NX_CALCULATION_FLAGS --target=build-schematics
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
|
65
.github/workflows/release.yml
vendored
65
.github/workflows/release.yml
vendored
@ -32,57 +32,22 @@ env:
|
||||
GH_RUN_NUMBER: ${{ github.run_attempt }}
|
||||
GH_BUILD_NUMBER: ${{ github.run_id }}
|
||||
JOB_ID: ${{ github.run_id }}
|
||||
PROXY_HOST_BPM: ${{ secrets.E2E_HOST }}
|
||||
E2E_IDENTITY_HOST_APA: ${{ secrets.E2E_IDENTITY_HOST_APA }}
|
||||
E2E_HOST_APA: ${{ secrets.E2E_HOST_APA }}
|
||||
E2E_HOST: ${{ secrets.E2E_HOST }}
|
||||
E2E_USERNAME: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_PASSWORD: ${{ secrets.E2E_PASSWORD }}
|
||||
E2E_ADMIN_EMAIL_IDENTITY: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
E2E_ADMIN_PASSWORD_IDENTITY: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
#USERNAME_ADF: ${{ secrets.E2E_USERNAME }}
|
||||
USERNAME_ADF: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
PASSWORD_ADF: ${{ secrets.E2E_PASSWORD }}
|
||||
URL_HOST_ADF: "http://localhost:4200"
|
||||
IDENTITY_ADMIN_EMAIL: ${{ secrets.E2E_ADMIN_EMAIL_IDENTITY }}
|
||||
IDENTITY_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD_IDENTITY }}
|
||||
AWS_S3_BUCKET_ACTIVITI_LICENSE: ${{ secrets.AWS_S3_BUCKET_ACTIVITI_LICENSE }}
|
||||
HOST_SSO: ${{ secrets.HOST_SSO }}
|
||||
LOG_LEVEL: "ERROR"
|
||||
E2E_LOG_LEVEL: "ERROR"
|
||||
E2E_MODELER_USERNAME: ${{ secrets.E2E_MODELER_USERNAME }}
|
||||
E2E_MODELER_PASSWORD: ${{ secrets.E2E_MODELER_PASSWORD }}
|
||||
EXTERNAL_ACS_HOST: ${{ secrets.EXTERNAL_ACS_HOST }}
|
||||
E2E_DEVOPS_USERNAME: ${{ secrets.E2E_DEVOPS_USERNAME }}
|
||||
E2E_DEVOPS_PASSWORD: ${{ secrets.E2E_DEVOPS_PASSWORD }}
|
||||
USERNAME_SUPER_ADMIN_ADF: ${{ secrets.USERNAME_SUPER_ADMIN_ADF }}
|
||||
PASSWORD_SUPER_ADMIN_ADF: ${{ secrets.PASSWORD_SUPER_ADMIN_ADF }}
|
||||
HR_USER: ${{ secrets.HR_USER }}
|
||||
HR_USER_PASSWORD: ${{ secrets.HR_USER_PASSWORD }}
|
||||
SMART_RUNNER_PATH: ".protractor-smartrunner"
|
||||
S3_DBP_PATH: ${{ secrets.S3_DBP_PATH }}
|
||||
S3_BUILD_BUCKET_SHORT_NAME: ${{ secrets.S3_BUILD_BUCKET_SHORT_NAME }}
|
||||
NODE_OPTIONS: "--max-old-space-size=5120"
|
||||
DOCKER_REPOSITORY_DOMAIN: ${{ secrets.DOCKER_REPOSITORY_DOMAIN }}
|
||||
DOCKER_REPOSITORY_USER: ${{ secrets.DOCKER_REPOSITORY_USER }}
|
||||
DOCKER_REPOSITORY_PASSWORD: ${{ secrets.DOCKER_REPOSITORY_PASSWORD }}
|
||||
DOCKER_REPOSITORY_STORYBOOK: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/storybook"
|
||||
DOCKER_REPOSITORY: "${{ secrets.DOCKER_REPOSITORY_DOMAIN }}/alfresco/demo-shell"
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
REPO_OWNER: "Alfresco"
|
||||
REPO_NAME: "alfresco-ng2-components"
|
||||
DEMO_SHELL_DIR: "./dist/demo-shell"
|
||||
STORYBOOK_DIR: "./dist/storybook/stories"
|
||||
BUILT_LIBS_DIR: "./dist/libs"
|
||||
NODE_MODULES_DIR: "./node_modules"
|
||||
SMART_RUNNER_DIRECTORY: ".protractor-smartrunner"
|
||||
SAVE_SCREENSHOT: true
|
||||
REDIRECT_URI: /
|
||||
BROWSER_RUN: false
|
||||
MAXINSTANCES: 2
|
||||
PLAYWRIGHT_WORKERS: 2
|
||||
PLAYWRIGHT_STORYBOOK_E2E_HOST: http://localhost
|
||||
PLAYWRIGHT_STORYBOOK_E2E_PORT: 4400
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
@ -107,32 +72,6 @@ jobs:
|
||||
npx nx run testing:bundle
|
||||
- uses: ./.github/actions/upload-node-modules-and-artifacts
|
||||
|
||||
release-demoshell:
|
||||
needs: [setup]
|
||||
timeout-minutes: 15
|
||||
if: github.event.pull_request.merged == true || github.ref_name == 'master' || github.ref_name == 'master-patch-*'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- run: git fetch --all
|
||||
- id: set-dryrun
|
||||
uses: ./.github/actions/enable-dryrun
|
||||
with:
|
||||
dry-run-flag: ${{ inputs.dry-run-flag }}
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
enable-cache: false
|
||||
enable-node-modules-cache: false
|
||||
- uses: ./.github/actions/download-node-modules-and-artifacts
|
||||
- name: release Demoshell docker
|
||||
run: |
|
||||
npx nx build demoshell --configuration production
|
||||
. ./scripts/github/release/docker-tag.sh
|
||||
./scripts/github/release/release-demoshell-docker.sh ${{ steps.set-dryrun.outputs.dryrun }}
|
||||
|
||||
release-storybook:
|
||||
needs: [setup]
|
||||
timeout-minutes: 15
|
||||
@ -194,7 +133,7 @@ jobs:
|
||||
setMigrations();
|
||||
- name: build libraries
|
||||
run: |
|
||||
npx nx affected:build $NX_CALCULATION_FLAGS --prod --exclude="demoshell" --skip-nx-cache
|
||||
npx nx affected:build $NX_CALCULATION_FLAGS --prod --skip-nx-cache
|
||||
npx nx affected $NX_CALCULATION_FLAGS --target=pretheme
|
||||
npx nx affected $NX_CALCULATION_FLAGS --target=build-schematics
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
@ -250,7 +189,7 @@ jobs:
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
name: Final Results
|
||||
needs: [release-demoshell, release-storybook, release-npm, npm-check-bundle]
|
||||
needs: [release-storybook, release-npm, npm-check-bundle]
|
||||
steps:
|
||||
|
||||
- uses: slackapi/slack-github-action@37ebaef184d7626c5f204ab8d3baff4262dd30f0 # v1.27.0
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -13,22 +13,17 @@ e2e/.env.cloud
|
||||
tmp
|
||||
temp
|
||||
/nxcache
|
||||
e2e-output*/
|
||||
/e2e/downloads/
|
||||
*.npmrc
|
||||
.history
|
||||
/ng2-components/ng2-alfresco-core/prebuilt-themes/
|
||||
.ng_pkg_build/
|
||||
/demo-shell/dist-dev-temp/
|
||||
/lib/export-new.json
|
||||
/lib/config/exportCheck.js
|
||||
/docs/sourceinfo
|
||||
/docs/docs.json
|
||||
/protractorFailuresReport
|
||||
coverage/
|
||||
/desktop.ini
|
||||
out-tsc
|
||||
!/.protractor-smartrunner/
|
||||
/reports/
|
||||
e2e-result-*
|
||||
licenses.txt
|
||||
|
@ -3,7 +3,7 @@ module.exports = {
|
||||
name: '@storybook/angular',
|
||||
options: {}
|
||||
},
|
||||
staticDirs: [{ from: '../../../demo-shell/src/app.config.json', to: 'app.config.json' }],
|
||||
staticDirs: [],
|
||||
docs: {},
|
||||
stories: [],
|
||||
addons: []
|
||||
|
@ -15,7 +15,6 @@ USER 101
|
||||
ARG PROJECT_NAME
|
||||
|
||||
COPY docker/default.conf.template /etc/nginx/templates/
|
||||
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
|
||||
|
24
README.md
24
README.md
@ -28,6 +28,7 @@ You can find the sources for all ADF components in the [`lib`](/lib) folder.
|
||||
## Libraries
|
||||
|
||||
ADF Libraries list:
|
||||
|
||||
- [Content services](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/content-services)
|
||||
- [Core](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/core)
|
||||
- [Extensions](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/extensions)
|
||||
@ -36,24 +37,13 @@ ADF Libraries list:
|
||||
- [Process service](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/process-services)
|
||||
- [Stories](https://github.com/Alfresco/alfresco-ng2-components/tree/develop/lib/stories)
|
||||
|
||||
## Demo Application
|
||||
|
||||
A separate application showcasing integration of components can be found
|
||||
[here](https://github.com/Alfresco/alfresco-ng2-components/tree/master/demo-shell).
|
||||
The app has examples of basic interaction for both APS and ACS components.
|
||||
|
||||
## Application generator for Yeoman
|
||||
|
||||
To speed up the development, you can use the
|
||||
[Generator for Yeoman](https://github.com/Alfresco/generator-ng2-alfresco-app).
|
||||
|
||||
## Browser Support
|
||||
|
||||
All components are supported in the following browsers:
|
||||
|
||||
|**Browser** |**Version** |
|
||||
|--- |--- |
|
||||
| Chrome | Latest |
|
||||
| Safari | Latest |
|
||||
| Firefox | Latest |
|
||||
| Edge | Latest |
|
||||
| **Browser** | **Version** |
|
||||
|-------------|-------------|
|
||||
| Chrome | Latest |
|
||||
| Safari | Latest |
|
||||
| Firefox | Latest |
|
||||
| Edge | Latest |
|
||||
|
@ -1,95 +0,0 @@
|
||||
/**
|
||||
* This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching
|
||||
* and faster execution of tasks.
|
||||
*
|
||||
* It does this by:
|
||||
*
|
||||
* - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command.
|
||||
* - Symlinking the ng to nx command, so all commands run through the Nx CLI
|
||||
* - Updating the package.json postinstall script to give you control over this script
|
||||
*
|
||||
* The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it.
|
||||
* Every command you run should work the same when using the Nx CLI, except faster.
|
||||
*
|
||||
* Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case,
|
||||
* will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked.
|
||||
* The Nx CLI simply does some optimizations before invoking the Angular CLI.
|
||||
*
|
||||
* To opt out of this patch:
|
||||
* - Replace occurrences of nx with ng in your package.json
|
||||
* - Remove the script from your postinstall script in your package.json
|
||||
* - 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;
|
||||
|
||||
/**
|
||||
* Paths to files being patched
|
||||
*/
|
||||
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();
|
||||
|
||||
if (!angularCLIInit.includes("NX_CLI_SET")) {
|
||||
fs.writeFileSync(
|
||||
initPath,
|
||||
`
|
||||
if (!process.env['NX_CLI_SET']) {
|
||||
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}
|
||||
`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Symlink of ng to nx, so you can keep using `ng build/test/lint` and still
|
||||
* 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 {
|
||||
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"
|
||||
});
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
path = require('path');
|
||||
module.exports = {
|
||||
extends: '../.eslintrc.js',
|
||||
ignorePatterns: ['!**/*'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts'],
|
||||
parserOptions: {
|
||||
project: [
|
||||
path.join(__dirname, 'tsconfig.app.json'),
|
||||
path.join(__dirname, 'src/tsconfig.spec.json'),
|
||||
path.join(__dirname, 'e2e/tsconfig.e2e.json')
|
||||
],
|
||||
createDefaultProgram: true
|
||||
},
|
||||
plugins: ['eslint-plugin-unicorn', 'eslint-plugin-rxjs'],
|
||||
rules: {
|
||||
'@angular-eslint/component-selector': [
|
||||
'error',
|
||||
{
|
||||
type: 'element',
|
||||
prefix: ['adf', 'app'],
|
||||
style: 'kebab-case'
|
||||
}
|
||||
],
|
||||
'@angular-eslint/directive-selector': [
|
||||
'error',
|
||||
{
|
||||
type: ['element', 'attribute'],
|
||||
prefix: ['adf', 'app'],
|
||||
style: 'kebab-case'
|
||||
}
|
||||
],
|
||||
'@angular-eslint/no-host-metadata-property': 'off',
|
||||
'@angular-eslint/no-input-prefix': 'error',
|
||||
'@typescript-eslint/consistent-type-definitions': 'error',
|
||||
'@typescript-eslint/dot-notation': 'off',
|
||||
'@typescript-eslint/explicit-member-accessibility': [
|
||||
'off',
|
||||
{
|
||||
accessibility: 'explicit'
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/no-inferrable-types': 'off',
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'error',
|
||||
'comma-dangle': 'error',
|
||||
'default-case': 'error',
|
||||
'import/order': 'off',
|
||||
'max-len': [
|
||||
'error',
|
||||
{
|
||||
code: 240
|
||||
}
|
||||
],
|
||||
'no-bitwise': 'off',
|
||||
'no-duplicate-imports': 'error',
|
||||
'no-multiple-empty-lines': 'error',
|
||||
'no-redeclare': 'error',
|
||||
'no-return-await': 'error',
|
||||
'rxjs/no-create': 'error',
|
||||
'rxjs/no-subject-unsubscribe': 'error',
|
||||
'rxjs/no-subject-value': 'error',
|
||||
'rxjs/no-unsafe-takeuntil': 'error',
|
||||
'unicorn/filename-case': 'error'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.html'],
|
||||
rules: {}
|
||||
}
|
||||
]
|
||||
};
|
59
demo-shell/.gitignore
vendored
59
demo-shell/.gitignore
vendored
@ -1,59 +0,0 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
/e2e/*.map
|
||||
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
typings/
|
||||
node_modules/
|
||||
bower_components/
|
||||
lib/
|
||||
app/**/*.js
|
||||
app/**/*.js.map
|
||||
app/**/*.d.ts
|
||||
|
||||
!app/js/Polyline.js
|
||||
.idea
|
||||
|
||||
|
||||
dist/
|
||||
coverage/
|
||||
!/e2e/protractor.conf.js
|
@ -1,75 +0,0 @@
|
||||
|
||||
# ADF Demo Application
|
||||
|
||||
Please note that this application is not an official product, but a testing and demo application to showcase complex interactions of ADF components.
|
||||
|
||||
## Installing
|
||||
|
||||
To correctly use this demo check that on your machine you have [Node](https://nodejs.org/en/) version 5.x.x or higher.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/Alfresco/alfresco-ng2-components.git
|
||||
cd alfresco-ng2-components
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## Proxy settings and CORS
|
||||
|
||||
To simplify development and reduce the time to get the application started, we have the following Proxy settings:
|
||||
|
||||
- **http://localhost:3000/ecm** is mapped to **http://localhost:8080**
|
||||
- **http://localhost:3000/bpm** is mapped to **http://localhost:9999**
|
||||
|
||||
The settings above address most common scenarios for running ACS on port 8080 and APS on port 9999 and allow you to skip the CORS configuration.
|
||||
|
||||
If you would like to change default proxy settings, please edit the `proxy.conf.js` file.
|
||||
|
||||
## Application settings (server-side)
|
||||
|
||||
All server-side application settings are stored in the [src/app.config.json](src/app.config.json).
|
||||
By default the configuration files have the content similar to the following one:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "../../lib/core/app-config/schema.json",
|
||||
"ecmHost": "http://{hostname}:{port}",
|
||||
"bpmHost": "http://{hostname}:{port}",
|
||||
"application": {
|
||||
"name": "Alfresco ADF Application"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Development build
|
||||
|
||||
```sh
|
||||
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.
|
||||
|
||||
### Important notes
|
||||
|
||||
This script is recommended for development environment and not suited for headless servers and network access.
|
||||
|
||||
## Production build
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
npm run start:prod
|
||||
```
|
||||
|
||||
This command builds project in `production` mode.
|
||||
All output is placed to `dist` folder and can be served to your preferred web server.
|
||||
You should need no additional files outside the `dist` folder.
|
||||
|
||||
## Development branch build
|
||||
|
||||
If you want to run the demo shell with the latest changes from the development branch, use the following command :
|
||||
|
||||
```sh
|
||||
npm run start
|
||||
```
|
@ -1,56 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/0.13/config/configuration-file.html
|
||||
process.env.CHROME_BIN = require('puppeteer').executablePath();
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: './',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
require('karma-mocha-reporter')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
files: [],
|
||||
preprocessors: {},
|
||||
mime: {
|
||||
'text/x-typescript': ['ts', 'tsx']
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, 'coverage'), reports: ['html', 'lcovonly'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
|
||||
customLaunchers: {
|
||||
ChromeHeadless: {
|
||||
base: 'Chrome',
|
||||
flags: [
|
||||
'--no-sandbox',
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--remote-debugging-port=9222'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
captureTimeout: 180000,
|
||||
browserDisconnectTimeout: 180000,
|
||||
browserDisconnectTolerance: 3,
|
||||
browserNoActivityTimeout: 300000,
|
||||
|
||||
reporters: ['mocha', 'kjhtml'],
|
||||
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['ChromeHeadless'],
|
||||
singleRun: false
|
||||
});
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"name": "Alfresco-ADF-Angular-Demo",
|
||||
"description": "Demo shell for Alfresco Angular components",
|
||||
"version": "7.0.0-alpha.2",
|
||||
"author": "Hyland Software, Inc. and its affiliates",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Alfresco/alfresco-ng2-components.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"ng2",
|
||||
"angular",
|
||||
"angular2",
|
||||
"alfresco"
|
||||
],
|
||||
"private": true
|
||||
}
|
@ -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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
module.exports = {
|
||||
getDeployedAppsProxy: function(processHost, deployedApps) {
|
||||
let deployedAppProxy = {};
|
||||
|
||||
if (deployedApps) {
|
||||
try {
|
||||
const deployedAppsArray = JSON.parse(deployedApps);
|
||||
for (const app of deployedAppsArray) {
|
||||
const appName = app.name;
|
||||
const appPath = `/${appName}`;
|
||||
const appPathRewrite = `^/${appName}`;
|
||||
|
||||
deployedAppProxy = {
|
||||
...deployedAppProxy,
|
||||
[appPath]: {
|
||||
target: `${processHost}`,
|
||||
secure: false,
|
||||
pathRewrite: {
|
||||
[appPathRewrite]: appName,
|
||||
},
|
||||
changeOrigin: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
return deployedAppProxy;
|
||||
},
|
||||
getShareProxy: function(host) {
|
||||
console.log('Target for /alfresco', host);
|
||||
return {
|
||||
'/alfresco': {
|
||||
target: host,
|
||||
secure: false,
|
||||
logLevel: 'debug',
|
||||
changeOrigin: true,
|
||||
onProxyReq: function(request) {
|
||||
if(request["method"] !== "GET")
|
||||
request.setHeader("origin", host);
|
||||
},
|
||||
// workaround for REPO-2260
|
||||
onProxyRes: function (proxyRes, req, res) {
|
||||
const header = proxyRes.headers['www-authenticate'];
|
||||
if (header && header.startsWith('Basic')) {
|
||||
proxyRes.headers['www-authenticate'] = 'x' + header;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
getApsProxy: function(host) {
|
||||
console.log('Target for /activiti-app', host);
|
||||
return {
|
||||
'/activiti-app': {
|
||||
target: host,
|
||||
secure: false,
|
||||
logLevel: 'debug',
|
||||
changeOrigin: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
getIdentityAdapterServiceProxy: function(host) {
|
||||
console.log('Target for /identity-adapter-service', host);
|
||||
return {
|
||||
'/identity-adapter-service': {
|
||||
target: host,
|
||||
secure: false,
|
||||
logLevel: 'debug',
|
||||
changeOrigin: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
require('dotenv').config();
|
||||
|
||||
const { getDeployedAppsProxy, getShareProxy, getApsProxy, getIdentityAdapterServiceProxy } = require('./proxy-helpers');
|
||||
|
||||
const legacyHost = process.env.PROXY_HOST_ADF;
|
||||
const cloudHost = process.env.CLOUD_PROXY_HOST_ADF || process.env.PROXY_HOST_ADF;
|
||||
const cloudApps = process.env.APP_CONFIG_APPS_DEPLOYED;
|
||||
const apsHost = process.env.PROXY_HOST_ADF;
|
||||
|
||||
module.exports = {
|
||||
...getShareProxy(legacyHost),
|
||||
...getApsProxy(apsHost),
|
||||
...getDeployedAppsProxy(cloudHost, cloudApps),
|
||||
...getIdentityAdapterServiceProxy(cloudHost)
|
||||
};
|
@ -1,39 +0,0 @@
|
||||
{
|
||||
"title": "Welcome",
|
||||
"NOTIFICATIONS": {
|
||||
"TASK_ASSIGNED": "{{taskName}} task has been assigned to {{assignee}}",
|
||||
"PROCESS_STARTED": "{{processName}} process has been started",
|
||||
"TASK_UPDATED": "{{taskName}} task details have been updated",
|
||||
"TASK_CREATED": "{{taskName}} task was created"
|
||||
},
|
||||
"SEARCH": {
|
||||
"RESULTS": "Search results",
|
||||
"NO_RESULT": "No results found",
|
||||
"FACET_FIELDS": {
|
||||
"TYPE": "1:Type",
|
||||
"SIZE": "2:Size",
|
||||
"CREATOR": "3:Creator",
|
||||
"MODIFIER": "4:Modifier",
|
||||
"CREATED": "5:Created"
|
||||
},
|
||||
"FACET_QUERIES": {
|
||||
"MY_FACET_QUERIES": "My facet queries",
|
||||
"CREATED_THIS_YEAR": "1.Created This Year",
|
||||
"MIMETYPE": "2.Type: HTML",
|
||||
"XTRASMALL": "3.Size: xtra small",
|
||||
"SMALL": "4.Size: small",
|
||||
"MEDIUM": "5.Size: medium",
|
||||
"LARGE": "6.Size: large",
|
||||
"XTRALARGE": "7.Size: xtra large",
|
||||
"XXTRALARGE": "8.Size: XX large"
|
||||
}
|
||||
},
|
||||
"GROUP-TITLE1-TRANSLATION-KEY": "CUSTOM TITLE TRANSLATION ONE",
|
||||
"GROUP-TITLE2-TRANSLATION-KEY": "CUSTOM TITLE TRANSLATION TWO",
|
||||
"ERROR_CONTENT": {
|
||||
"507": {
|
||||
"TITLE": "ACS Disk full",
|
||||
"DESCRIPTION": "Content exceeds overall storage quota limit configured for the network or system"
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
File diff suppressed because it is too large
Load Diff
@ -1,4 +0,0 @@
|
||||
<div class="app-demo-app-container">
|
||||
<router-outlet></router-outlet>
|
||||
<router-outlet name="overlay"></router-outlet>
|
||||
</div>
|
@ -1,13 +0,0 @@
|
||||
router-outlet[name='overlay'] + * {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.app-demo-app-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, ViewEncapsulation, OnInit } from '@angular/core';
|
||||
import {
|
||||
AuthenticationService,
|
||||
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',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
|
||||
constructor(private pageTitleService: PageTitleService,
|
||||
private adfHttpClient: AdfHttpClient,
|
||||
private authenticationService: AuthenticationService,
|
||||
private router: Router,
|
||||
private dialogRef: MatDialog) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.pageTitleService.setTitle('title');
|
||||
|
||||
this.adfHttpClient.on('error', (error) => {
|
||||
if (error.status === 401) {
|
||||
if (!this.authenticationService.isLoggedIn()) {
|
||||
this.dialogRef.closeAll();
|
||||
this.router.navigate(['/login']);
|
||||
}
|
||||
}
|
||||
|
||||
if (error.status === 507) {
|
||||
if (!this.authenticationService.isLoggedIn()) {
|
||||
this.dialogRef.closeAll();
|
||||
this.router.navigate(['error/507']);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
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 { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||
import { AppComponent } from './app.component';
|
||||
import { appRoutes } from './app.routes';
|
||||
import { MonacoEditorModule } from 'ngx-monaco-editor-v2';
|
||||
import { ContentModule } from '@alfresco/adf-content-services';
|
||||
import { ProcessModule } from '@alfresco/adf-process-services';
|
||||
import { environment } from '../environments/environment';
|
||||
import { ProcessServicesCloudModule } from '@alfresco/adf-process-services-cloud';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { CoreAutomationService } from '../testing/automation.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
environment.e2e ? NoopAnimationsModule : BrowserAnimationsModule,
|
||||
RouterModule.forRoot(appRoutes, { useHash: true }),
|
||||
AuthModule.forRoot({ useHash: true }),
|
||||
HttpClientModule,
|
||||
TranslateModule.forRoot(),
|
||||
CoreModule.forRoot(),
|
||||
ContentModule.forRoot(),
|
||||
ProcessModule.forRoot(),
|
||||
ProcessServicesCloudModule.forRoot(),
|
||||
ExtensionsModule.forRoot(),
|
||||
NgChartsModule,
|
||||
MonacoEditorModule.forRoot()
|
||||
],
|
||||
declarations: [AppComponent],
|
||||
providers: [
|
||||
{ provide: AppConfigService, useClass: DebugAppConfigService }, // not use this service in production
|
||||
provideTranslations('app', 'resources'),
|
||||
provideTranslations('adf-insights', 'assets/adf-insights')
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(automationService: CoreAutomationService) {
|
||||
automationService.setup();
|
||||
}
|
||||
}
|
@ -1,327 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { Routes } from '@angular/router';
|
||||
import { AuthGuard, AuthGuardEcm, ErrorContentComponent, AuthGuardBpm, AuthGuardSsoRoleService } from '@alfresco/adf-core';
|
||||
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import { LogoutComponent } from './components/logout/logout.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 { SearchResultComponent } from './components/search/search-result.component';
|
||||
import { FilesComponent } from './components/files/files.component';
|
||||
import { AppFormComponent } from './components/form/app-form.component';
|
||||
import { DemoPermissionComponent } from './components/permissions/demo-permissions.component';
|
||||
import { AppComponent } from './app.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';
|
||||
import { ProcessesCloudDemoComponent } from './components/cloud/processes-cloud-demo.component';
|
||||
import { StartTaskCloudDemoComponent } from './components/cloud/start-task-cloud-demo.component';
|
||||
import { StartProcessCloudDemoComponent } from './components/cloud/start-process-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 { 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';
|
||||
|
||||
export const appRoutes: Routes = [
|
||||
{ path: 'login', component: AppLoginComponent },
|
||||
{ path: 'logout', component: LogoutComponent },
|
||||
{
|
||||
path: 'settings',
|
||||
component: SettingsComponent
|
||||
},
|
||||
{
|
||||
path: 'files/:nodeId/view',
|
||||
component: AppComponent,
|
||||
canActivate: [AuthGuardEcm],
|
||||
canActivateChild: [AuthGuardEcm],
|
||||
outlet: 'overlay',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: FileViewComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'files/:nodeId/:versionId/view',
|
||||
component: AppComponent,
|
||||
canActivate: [AuthGuardEcm],
|
||||
canActivateChild: [AuthGuardEcm],
|
||||
outlet: 'overlay',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: FileViewComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'preview/blob',
|
||||
component: AppComponent,
|
||||
outlet: 'overlay',
|
||||
pathMatch: 'full',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: FileViewComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: AppLayoutComponent,
|
||||
canActivate: [AuthGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: `/home`,
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'card-view',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: AppCardViewComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: HomeComponent
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
component: HomeComponent
|
||||
},
|
||||
{
|
||||
path: 'cloud',
|
||||
canActivate: [AuthGuardSsoRoleService],
|
||||
data: { roles: ['ACTIVITI_ADMIN', 'ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
data: { roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||
component: AppsCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: ':appName',
|
||||
canActivate: [AuthGuardSsoRoleService],
|
||||
data: { clientRoles: ['appName'], roles: ['ACTIVITI_USER'], redirectUrl: '/error/403' },
|
||||
component: ProcessCloudLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CloudLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'tasks',
|
||||
component: TasksCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: 'processes',
|
||||
component: ProcessesCloudDemoComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'start-task',
|
||||
component: StartTaskCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: 'start-process',
|
||||
component: StartProcessCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: 'task-details/:taskId',
|
||||
component: TaskDetailsCloudDemoComponent
|
||||
},
|
||||
{
|
||||
path: 'task-details/:taskId/files/:nodeId/view',
|
||||
component: CloudViewerComponent
|
||||
},
|
||||
{
|
||||
path: 'process-details/:processInstanceId',
|
||||
component: ProcessDetailsCloudDemoComponent
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'settings-layout',
|
||||
component: SettingsComponent
|
||||
},
|
||||
{
|
||||
path: 'files',
|
||||
component: FilesComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'files/:id',
|
||||
component: FilesComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'files/:id/display/:mode',
|
||||
component: FilesComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'search',
|
||||
component: SearchResultComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'search-filter-chips',
|
||||
component: AppSearchFilterChipsComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'activiti',
|
||||
component: AppsViewComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps',
|
||||
component: AppsViewComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps/:appId/tasks',
|
||||
component: ProcessServiceComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps/:appId/tasks/:filterId',
|
||||
component: ProcessServiceComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps/:appId/processes',
|
||||
component: ProcessServiceComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps/:appId/processes/:filterId',
|
||||
component: ProcessServiceComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps/:appId/diagram/:processDefinitionId',
|
||||
component: ShowDiagramComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'activiti/apps/:appId/report',
|
||||
component: ProcessServiceComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
// TODO: check if needed
|
||||
{
|
||||
path: 'activiti/appId/:appId',
|
||||
component: ProcessServiceComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
// TODO: check if needed
|
||||
{
|
||||
path: 'activiti/tasks/:id',
|
||||
component: FormViewerComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
// TODO: check if needed
|
||||
{
|
||||
/* cspell:disable-next-line */
|
||||
path: 'activiti/tasksnode/:id',
|
||||
component: FormNodeViewerComponent,
|
||||
canActivate: [AuthGuardBpm]
|
||||
},
|
||||
{
|
||||
path: 'permissions/:id',
|
||||
component: DemoPermissionComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{ path: 'form-cloud', component: FormCloudDemoComponent },
|
||||
{ path: 'form', component: AppFormComponent },
|
||||
{
|
||||
path: 'task-list',
|
||||
canActivate: [AuthGuardBpm],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: TaskListDemoComponent
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: TaskListDemoComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'process-list',
|
||||
canActivate: [AuthGuardBpm],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: ProcessListDemoComponent
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: ProcessListDemoComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'error/no-authorization',
|
||||
component: ErrorContentComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'error',
|
||||
component: AppLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/error/404',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: DemoErrorComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'error/404'
|
||||
}
|
||||
];
|
@ -1,93 +0,0 @@
|
||||
<adf-sidenav-layout
|
||||
[sidenavMin]="70"
|
||||
[sidenavMax]="220"
|
||||
[stepOver]="780"
|
||||
data-automation-id="sidenav-layout">
|
||||
|
||||
<adf-sidenav-layout-header>
|
||||
<ng-template>
|
||||
<adf-layout-header
|
||||
id="adf-header"
|
||||
title="ADF Demo Application"
|
||||
redirectUrl="/home"
|
||||
tooltip="ADF Demo Application"
|
||||
[showSidenavToggle]="false">
|
||||
|
||||
<div class="app-layout-menu-spacer"></div>
|
||||
|
||||
<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>
|
||||
<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 class="app-sidenav-link__expand-button" [matMenuTriggerData]="{links: link.children}"
|
||||
rippleTrigger mat-icon-button #trigger="matMenuTrigger"
|
||||
[matMenuTriggerFor]="nestedMenu">arrow_right</mat-icon>
|
||||
</mat-list-item>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!link.children">
|
||||
<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-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-list-item>
|
||||
</mat-nav-list>
|
||||
|
||||
</ng-template>
|
||||
</adf-sidenav-layout-navigation>
|
||||
|
||||
<adf-sidenav-layout-content>
|
||||
<ng-template>
|
||||
<router-outlet></router-outlet>
|
||||
</ng-template>
|
||||
</adf-sidenav-layout-content>
|
||||
|
||||
</adf-sidenav-layout>
|
||||
|
||||
<mat-menu #nestedMenu="matMenu" xPosition="after" class="nestedMenu">
|
||||
<ng-template matMenuContent let-links="links">
|
||||
<button mat-menu-item *ngFor="let link of links"
|
||||
class="app-sidenav-link"
|
||||
[attr.data-automation-id]="link.title | translate"
|
||||
routerLinkActive="app-sidenav-link--active"
|
||||
[routerLink]="link.href"
|
||||
[routerLinkActiveOptions]="{ exact: true }">
|
||||
|
||||
<mat-icon matListItemIcon>{{link.icon}}</mat-icon>
|
||||
{{ link.title | translate }}
|
||||
</button>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
|
||||
<adf-file-uploading-dialog #fileDialog position="left"></adf-file-uploading-dialog>
|
@ -1,14 +0,0 @@
|
||||
.app-layout {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 320px;
|
||||
height: 100%;
|
||||
|
||||
.app-sidenav-link--active {
|
||||
color: var(--theme-primary-color);
|
||||
}
|
||||
|
||||
&-menu-spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
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 { AlfrescoApiService, FileUploadingDialogComponent } from '@alfresco/adf-content-services';
|
||||
|
||||
@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' },
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class AppLayoutComponent {
|
||||
links: Array<any> = [
|
||||
{ href: '/home', icon: 'home', title: 'Home' },
|
||||
{ href: '/files', icon: 'folder_open', title: 'Content Services' },
|
||||
{ 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: '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: '/login', icon: 'vpn_key', title: 'Login' },
|
||||
{ href: '/settings-layout', icon: 'settings', title: 'Settings' }
|
||||
];
|
||||
|
||||
enableRedirect = true;
|
||||
|
||||
constructor(private alfrescoApiService: AlfrescoApiService) {
|
||||
if (this.alfrescoApiService.getInstance().isOauthConfiguration()) {
|
||||
this.enableRedirect = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
<div class="main-content">
|
||||
<mat-tab-group [animationDuration]="0">
|
||||
<mat-tab label="Form" class="form-cloud-render">
|
||||
<div class="app-form-container">
|
||||
<adf-cloud-form
|
||||
[showRefreshButton]="false"
|
||||
[form]="form"
|
||||
(formSaved)="onFormSaved()"
|
||||
(formError)="logErrors($event)">
|
||||
</adf-cloud-form>
|
||||
</div>
|
||||
|
||||
<div class="app-console">
|
||||
<h3>Error log:</h3>
|
||||
<p *ngFor="let error of errorFields">Error {{ error.name }} {{error.validationSummary.message | translate}}</p>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="Editor" class="form-cloud-editor">
|
||||
<ngx-monaco-editor
|
||||
id="adf-form-config-editor"
|
||||
class="app-form-config-editor"
|
||||
[options]="editorOptions"
|
||||
[(ngModel)]="formConfig"
|
||||
(onInit)="onInitFormEditor($event)">
|
||||
</ngx-monaco-editor>
|
||||
<div class="app-form-editor-buttons">
|
||||
<button mat-raised-button id="app-form-config-save" (click)="onSaveFormConfig()">Save form config</button>
|
||||
<button mat-raised-button id="app-form-config-clear" (click)="onClearFormConfig()">Clear form config</button>
|
||||
<a mat-raised-button class="app-upload-config-button">
|
||||
<mat-icon>file_upload</mat-icon>
|
||||
<label for="upload-config-file">Upload JSON File</label>
|
||||
<input
|
||||
id="upload-config-file"
|
||||
data-automation-id="upload-single-file"
|
||||
type="file"
|
||||
name="uploadConfig"
|
||||
accept=".json"
|
||||
(change)="onConfigAdded($event)">
|
||||
</a>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
@import 'styles/mat-selectors';
|
||||
|
||||
.app-form-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.app-main-content {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.app-console {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-left: 10px;
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
padding-bottom: 30px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.app-form-config-editor {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.app-form-editor-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 4px;
|
||||
}
|
||||
|
||||
.app-upload-config-button {
|
||||
input {
|
||||
cursor: pointer;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, 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 { 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';
|
||||
|
||||
@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 }]
|
||||
})
|
||||
export class FormCloudDemoComponent implements OnInit, OnDestroy {
|
||||
form: FormModel;
|
||||
errorFields: FormFieldModel[] = [];
|
||||
formConfig: string;
|
||||
editor: any;
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
editorOptions = {
|
||||
theme: 'vs-dark',
|
||||
language: 'json',
|
||||
autoIndent: true,
|
||||
formatOnPaste: true,
|
||||
formatOnType: true,
|
||||
automaticLayout: true
|
||||
};
|
||||
|
||||
constructor(
|
||||
private notificationService: NotificationService,
|
||||
private formService: FormCloudService,
|
||||
private automationService: CoreAutomationService,
|
||||
private formRenderingService: FormRenderingService
|
||||
) {
|
||||
this.formRenderingService.register({
|
||||
'demo-widget': () => CustomEditorComponent,
|
||||
'custom-editor': () => CustomEditorComponent,
|
||||
'custom-string': () => CustomWidgetComponent,
|
||||
'custom-datetime': () => CustomWidgetComponent,
|
||||
'custom-file': () => CustomWidgetComponent,
|
||||
'custom-number': () => CustomWidgetComponent,
|
||||
'custom-something': () => CustomWidgetComponent,
|
||||
'custom-boolean': () => CustomWidgetComponent,
|
||||
'custom-date': () => CustomWidgetComponent,
|
||||
custom: () => CustomWidgetComponent
|
||||
});
|
||||
}
|
||||
|
||||
logErrors(errorFields: FormFieldModel[]) {
|
||||
this.errorFields = errorFields;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.formConfig = JSON.stringify(this.automationService.forms.getFormCloudDefinition());
|
||||
this.parseForm();
|
||||
}
|
||||
|
||||
onFormSaved() {
|
||||
this.notificationService.openSnackMessage('Task has been saved successfully');
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
}
|
||||
|
||||
onInitFormEditor(editor) {
|
||||
this.editor = editor;
|
||||
setTimeout(() => {
|
||||
this.editor.getAction('editor.action.formatDocument').run();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
parseForm() {
|
||||
this.form = this.formService.parseForm(JSON.parse(this.formConfig));
|
||||
}
|
||||
|
||||
onSaveFormConfig() {
|
||||
try {
|
||||
this.parseForm();
|
||||
} catch (error) {
|
||||
this.notificationService.openSnackMessage('Wrong form configuration');
|
||||
}
|
||||
}
|
||||
|
||||
onClearFormConfig() {
|
||||
this.formConfig = '';
|
||||
}
|
||||
|
||||
onConfigAdded($event: any): void {
|
||||
const file = $event.currentTarget.files[0];
|
||||
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = () => {
|
||||
this.formConfig = fileReader.result as string;
|
||||
};
|
||||
fileReader.readAsText(file);
|
||||
|
||||
this.onInitFormEditor(this.editor);
|
||||
|
||||
$event.target.value = '';
|
||||
}
|
||||
}
|
@ -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,154 +0,0 @@
|
||||
@import 'styles/flex';
|
||||
|
||||
.adf {
|
||||
&-userinfo-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
&-userinfo-name-right {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&-userinfo-name {
|
||||
padding: 0 5px;
|
||||
|
||||
@include layout-bp(lt-md) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-userinfo-pic {
|
||||
background: var(--adf-theme-primary-300);
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
font-weight: bolder;
|
||||
font-size: var(--theme-adf-picture-1-font-size);
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
&-userinfo-profile-image {
|
||||
background: var(--adf-theme-primary-300);
|
||||
text-align: center;
|
||||
border-radius: 90%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 0;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&-userinfo-profile-container {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-userinfo-menu_button.adf-content-userinfo-button {
|
||||
margin-right: 0;
|
||||
border-radius: 90%;
|
||||
padding: 0;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
&-userinfo-card-header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
line-height: normal;
|
||||
height: 100px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&-userinfo-card.adf-content-userinfo-card {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-userinfo-supporting-text {
|
||||
overflow: hidden;
|
||||
padding: 32px;
|
||||
column-count: 2;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@include layout-bp(lt-sm) {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&-userinfo__detail-title {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-userinfo__secondary-info {
|
||||
font-size: var(--theme-body-1-font-size);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
line-height: 18px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
&-userinfo-profile-picture {
|
||||
background: var(--adf-theme-primary-300);
|
||||
background-size: cover;
|
||||
border-radius: 50%;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
&-userinfo-profile-initials {
|
||||
text-transform: uppercase;
|
||||
background-size: cover;
|
||||
background-color: var(--adf-theme-primary-300);
|
||||
border-radius: 50%;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
font-size: 35px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
line-height: 78px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
&-userinfo-button-profile {
|
||||
display: inline-block;
|
||||
border: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-userinfo-detail {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&-hide-small.adf-userinfo-profile-initials,
|
||||
&-hide-small.adf-userinfo-profile-container {
|
||||
@include layout-bp(lt-md) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (device-width >= 480px) {
|
||||
.adf-content-userinfo-menu.adf-userinfo-menu {
|
||||
max-height: 450px;
|
||||
min-width: 450px;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-content-userinfo-menu.adf-userinfo-menu > div {
|
||||
padding: 0;
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { FullNamePipe, IdentityUserModel, InitialUsernamePipe, UserInfoMode } from '@alfresco/adf-core';
|
||||
import { Component, Input, OnDestroy, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { MatMenuModule, MatMenuTrigger, MenuPositionX, MenuPositionY } from '@angular/material/menu';
|
||||
import { Subject } from 'rxjs';
|
||||
import { EcmUserModel, PeopleContentService } from '@alfresco/adf-content-services';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-content-user-info',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FullNamePipe, MatMenuModule, MatButtonModule, InitialUsernamePipe, MatCardModule, TranslateModule],
|
||||
templateUrl: './content-user-info.component.html',
|
||||
styleUrls: ['./content-user-info.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ContentUserInfoComponent implements OnDestroy {
|
||||
@ViewChild(MatMenuTrigger) trigger: MatMenuTrigger;
|
||||
|
||||
/** Determines if user is logged in. */
|
||||
@Input()
|
||||
isLoggedIn: boolean;
|
||||
|
||||
/** ECM user info. */
|
||||
@Input()
|
||||
ecmUser: EcmUserModel;
|
||||
|
||||
/** Identity user info. */
|
||||
@Input()
|
||||
identityUser: IdentityUserModel;
|
||||
|
||||
/** current mode. */
|
||||
@Input()
|
||||
mode: UserInfoMode = UserInfoMode.CONTENT;
|
||||
|
||||
/** Custom path for the background banner image for ACS users. */
|
||||
@Input()
|
||||
ecmBackgroundImage: string = './resources/images/ecm-background.png';
|
||||
|
||||
/** Custom path for the background banner image for APS users. */
|
||||
@Input()
|
||||
bpmBackgroundImage: string = './resources/images/bpm-background.png';
|
||||
|
||||
/** Custom choice for opening the menu at the bottom. Can be `before` or `after`. */
|
||||
@Input()
|
||||
menuPositionX: MenuPositionX = 'after';
|
||||
|
||||
/** Custom choice for opening the menu at the bottom. Can be `above` or `below`. */
|
||||
@Input()
|
||||
menuPositionY: MenuPositionY = 'below';
|
||||
|
||||
/** Shows/hides the username next to the user info button. */
|
||||
@Input()
|
||||
showName: boolean = true;
|
||||
|
||||
/**
|
||||
* When the username is shown, this defines its position relative to the user info button.
|
||||
* Can be `right` or `left`.
|
||||
*/
|
||||
@Input()
|
||||
namePosition: string = 'right';
|
||||
|
||||
userInfoMode = UserInfoMode;
|
||||
|
||||
private destroy$ = new Subject();
|
||||
|
||||
constructor(private peopleContentService: PeopleContentService) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next(true);
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
onKeyPress(event: KeyboardEvent) {
|
||||
this.closeUserModal(event);
|
||||
}
|
||||
|
||||
private closeUserModal($event: KeyboardEvent) {
|
||||
if ($event.keyCode === 27) {
|
||||
this.trigger.closeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
stopClosing(event: Event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
getEcmAvatar(avatarId: string): string {
|
||||
return this.peopleContentService.getUserProfileImage(avatarId);
|
||||
}
|
||||
|
||||
get showOnRight(): boolean {
|
||||
return this.namePosition === 'right';
|
||||
}
|
||||
|
||||
get canShow(): boolean {
|
||||
return this.isLoggedIn && !!this.ecmUser && !!this.mode;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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.
|
||||
*/
|
||||
|
||||
export * from './content-user-info.component';
|
@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
@ -1,109 +0,0 @@
|
||||
<div
|
||||
id="userinfo_container"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
[class.adf-userinfo-name-right]="showOnRight"
|
||||
(keyup)="onKeyPress($event)"
|
||||
class="adf-userinfo-container"
|
||||
*ngIf="canShow"
|
||||
>
|
||||
<span *ngIf="showName" id="adf-userinfo-bpm-name-display" class="adf-userinfo-name">
|
||||
{{bpmUser | fullName}}
|
||||
</span>
|
||||
<button mat-button [matMenuTriggerFor]="menu" class="adf-userinfo-menu_button"
|
||||
data-automation-id="adf-user-profile">
|
||||
<div class="adf-userinfo-button-profile" id="user-profile">
|
||||
<div *ngIf="ecmUser; else showBpmUserImage" 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 #showBpmUserImage>
|
||||
<div *ngIf="bpmUser" id="bpm-user-image">
|
||||
<div *ngIf="bpmUser.pictureId; else initialTemplate" class="adf-userinfo-profile-container">
|
||||
<img id="logged-user-img" [src]="getBpmUserImage()" alt="user-info-profile-button"
|
||||
class="adf-userinfo-profile-image"/>
|
||||
</div>
|
||||
<ng-template #initialTemplate>
|
||||
<div [outerHTML]="bpmUser | 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-tab-group id="tab-group-env" (click)="stopClosing($event)" selectedIndex="0" role="menuitem"
|
||||
class="adf-userinfo-tab" [class.adf-hide-tab]="!ecmUser">
|
||||
<mat-tab label="{{ 'USER_PROFILE.TAB.CS' | translate }}" role="dialog"
|
||||
*ngIf="mode===userInfoMode.ALL">
|
||||
<mat-card appearance="outlined" class="adf-userinfo-card" *ngIf="ecmUser">
|
||||
<mat-card-header class="adf-userinfo-card-header"
|
||||
[style.background-image]="'url(' + ecmBackgroundImage + ')'">
|
||||
<div *ngIf="ecmUser.avatarId; else initialTemplate"
|
||||
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>
|
||||
</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-tab>
|
||||
<mat-tab id="bpm-panel" label="{{ 'USER_PROFILE.TAB.PS' | translate }}" role="dialog"
|
||||
*ngIf="mode===userInfoMode.PROCESS || mode===userInfoMode.ALL">
|
||||
<mat-card appearance="outlined" class="adf-userinfo-card">
|
||||
<mat-card-header class="adf-userinfo-card-header"
|
||||
[style.background-image]="'url(' + bpmBackgroundImage + ')'">
|
||||
<img *ngIf="bpmUser.pictureId; else initialTemplate"
|
||||
class="adf-userinfo-profile-picture adf-hide-small" id="bpm-user-detail-image"
|
||||
alt="bpm-profile-image" [src]="getBpmUserImage()"/>
|
||||
<ng-template #initialTemplate>
|
||||
<div
|
||||
[outerHTML]="bpmUser | usernameInitials:'adf-userinfo-profile-initials adf-hide-small'"></div>
|
||||
</ng-template>
|
||||
<div class="mat-headline-6" id="bpm-username">{{bpmUser | fullName}}</div>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="adf-userinfo-supporting-text">
|
||||
<div class="adf-userinfo-detail">
|
||||
<h2 id="bpm-full-name"
|
||||
class="adf-userinfo__detail-title">{{ bpmUser | fullName }}</h2>
|
||||
<span id="bpm-email"> {{bpmUser.email}} </span>
|
||||
</div>
|
||||
<div class="adf-userinfo-detail">
|
||||
<span id="bpm-tenant" class="adf-userinfo__secondary-info">
|
||||
{{ 'USER_PROFILE.LABELS.BPM.TENANT' | translate }}
|
||||
<span>{{ bpmUser.tenantName ? bpmUser.tenantName : '' }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</mat-menu>
|
||||
</div>
|
@ -1,174 +0,0 @@
|
||||
@import 'styles/flex';
|
||||
@import 'styles/mat-selectors';
|
||||
|
||||
.adf {
|
||||
&-userinfo-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
&-userinfo-name-right {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&-userinfo-name {
|
||||
padding: 0 5px;
|
||||
|
||||
@include layout-bp(lt-md) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-userinfo-pic {
|
||||
background: var(--adf-theme-primary-300);
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
font-weight: bolder;
|
||||
font-size: var(--theme-adf-picture-1-font-size);
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
&-userinfo-profile-image {
|
||||
background: var(--adf-theme-primary-300);
|
||||
text-align: center;
|
||||
border-radius: 90%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 0;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&-userinfo-profile-container {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&-userinfo-menu_button#{$mat-button} {
|
||||
margin-right: 0;
|
||||
border-radius: 90%;
|
||||
padding: 0;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
&-userinfo-tab #{$mat-tab-header} {
|
||||
align-self: center;
|
||||
width: 100%;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
&-userinfo-tab #{$mat-tab-label-text} {
|
||||
flex: auto;
|
||||
font-weight: 500;
|
||||
font-size: var(--theme-body-1-font-size);
|
||||
text-transform: uppercase;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-userinfo-card-header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
line-height: normal;
|
||||
height: 100px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&-userinfo-card#{$mat-card} {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-userinfo-supporting-text {
|
||||
overflow: hidden;
|
||||
padding: 32px;
|
||||
column-count: 2;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@include layout-bp(lt-sm) {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&-userinfo__detail-title {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-userinfo__secondary-info {
|
||||
font-size: var(--theme-body-1-font-size);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
line-height: 18px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
&-userinfo-profile-picture {
|
||||
background: var(--adf-theme-primary-300);
|
||||
background-size: cover;
|
||||
border-radius: 50%;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
&-userinfo-profile-initials {
|
||||
text-transform: uppercase;
|
||||
background-size: cover;
|
||||
background-color: var(--adf-theme-primary-300);
|
||||
border-radius: 50%;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
font-size: 35px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
line-height: 78px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
&-userinfo-button-profile {
|
||||
display: inline-block;
|
||||
border: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-userinfo-detail {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&-hide-tab.adf-userinfo-tab#tab-group-env {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-hide-small.adf-userinfo-profile-initials,
|
||||
&-hide-small.adf-userinfo-profile-container {
|
||||
@include layout-bp(lt-md) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-device-width: 480px) {
|
||||
#{$mat-menu-panel}.adf-userinfo-menu {
|
||||
max-height: 450px;
|
||||
min-width: 450px;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#{$mat-menu-panel}.adf-userinfo-menu #{$mat-menu-content} {
|
||||
padding: 0;
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { CoreTestingModule, UserInfoMode } from '@alfresco/adf-core';
|
||||
import { fakeEcmUser, fakeEcmUserNoImage } from '@alfresco/adf-content-services';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ProcessUserInfoComponent } from './process-user-info.component';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatTabGroupHarness, MatTabHarness } from '@angular/material/tabs/testing';
|
||||
|
||||
const fakeBpmUser: any = {
|
||||
apps: [],
|
||||
capabilities: null,
|
||||
company: 'fake-company',
|
||||
created: 'fake-create-date',
|
||||
email: 'fakeBpm@fake.com',
|
||||
externalId: 'fake-external-id',
|
||||
firstName: 'fake-bpm-first-name',
|
||||
lastName: 'fake-bpm-last-name',
|
||||
groups: [],
|
||||
id: 'fake-id',
|
||||
lastUpdate: 'fake-update-date',
|
||||
latestSyncTimeStamp: 'fake-timestamp',
|
||||
password: 'fake-password',
|
||||
pictureId: 12,
|
||||
status: 'fake-status',
|
||||
tenantId: 'fake-tenant-id',
|
||||
tenantName: 'fake-tenant-name',
|
||||
tenantPictureId: 'fake-tenant-picture-id',
|
||||
type: 'fake-type'
|
||||
};
|
||||
|
||||
describe('ProcessUserInfoComponent', () => {
|
||||
const profilePictureUrl = 'alfresco-logo.svg';
|
||||
|
||||
let component: ProcessUserInfoComponent;
|
||||
let fixture: ComponentFixture<ProcessUserInfoComponent>;
|
||||
let loader: HarnessLoader;
|
||||
let element: HTMLElement;
|
||||
|
||||
const openUserInfo = () => {
|
||||
fixture.detectChanges();
|
||||
const imageButton = element.querySelector<HTMLButtonElement>('#logged-user-img');
|
||||
imageButton.click();
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
const whenFixtureReady = async () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreTestingModule, ProcessUserInfoComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(ProcessUserInfoComponent);
|
||||
component = fixture.componentInstance;
|
||||
loader = TestbedHarnessEnvironment.documentRootLoader(fixture);
|
||||
element = fixture.nativeElement;
|
||||
|
||||
spyOn(window, 'requestAnimationFrame').and.returnValue(1);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should not show any image if the user is not logged in', () => {
|
||||
expect(element.querySelector('#userinfo_container')).toBeDefined();
|
||||
expect(element.querySelector('#logged-user-img')).toBeNull();
|
||||
});
|
||||
|
||||
it('should NOT have users immediately after ngOnInit', () => {
|
||||
expect(element.querySelector('#userinfo_container')).toBeDefined();
|
||||
expect(element.querySelector('#ecm_username')).toBeNull();
|
||||
expect(element.querySelector('#bpm_username')).toBeNull();
|
||||
expect(element.querySelector('#user-profile-lists')).toBeNull();
|
||||
});
|
||||
|
||||
describe('when user is logged on bpm', () => {
|
||||
beforeEach(async () => {
|
||||
component.bpmUser = fakeBpmUser;
|
||||
component.isLoggedIn = true;
|
||||
});
|
||||
|
||||
it('should show full name next the user image', async () => {
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const bpmUserName = fixture.debugElement.query(By.css('#bpm-username'));
|
||||
expect(element.querySelector('#userinfo_container')).not.toBeNull();
|
||||
expect(bpmUserName).toBeDefined();
|
||||
expect(bpmUserName).not.toBeNull();
|
||||
expect(bpmUserName.nativeElement.innerHTML).toContain('fake-bpm-first-name fake-bpm-last-name');
|
||||
});
|
||||
|
||||
it('should get the bpm current user image from the service', async () => {
|
||||
spyOn(component, 'getBpmUserImage').and.returnValue(profilePictureUrl);
|
||||
await whenFixtureReady();
|
||||
expect(element.querySelector('#userinfo_container')).not.toBeNull();
|
||||
expect(element.querySelector('#logged-user-img')).not.toBeNull();
|
||||
expect(element.querySelector('#logged-user-img').getAttribute('src')).toContain(profilePictureUrl);
|
||||
});
|
||||
|
||||
it('should show last name if first name is null', async () => {
|
||||
component.bpmUser = {
|
||||
firstName: null,
|
||||
lastName: 'fake-last-name'
|
||||
} as any;
|
||||
await whenFixtureReady();
|
||||
const fullNameElement = element.querySelector('#adf-userinfo-bpm-name-display');
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#userinfo_container')).toBeDefined();
|
||||
expect(element.querySelector('#adf-userinfo-bpm-name-display')).not.toBeNull();
|
||||
expect(fullNameElement.textContent).toContain('fake-last-name');
|
||||
expect(fullNameElement.textContent).not.toContain('fake-first-name');
|
||||
});
|
||||
|
||||
it('should not show the tabs', async () => {
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const tabGroupHost = await (await loader.getHarness(MatTabGroupHarness.with({ selector: '#tab-group-env' }))).host();
|
||||
expect(await tabGroupHost.hasClass('adf-hide-tab')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user is logged on bpm and ecm', () => {
|
||||
beforeEach(async () => {
|
||||
component.bpmUser = fakeBpmUser;
|
||||
component.ecmUser = fakeEcmUser as any;
|
||||
component.isLoggedIn = true;
|
||||
component.mode = UserInfoMode.ALL;
|
||||
});
|
||||
|
||||
it('should show the tabs', async () => {
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const tabGroupHost = await (await loader.getHarness(MatTabGroupHarness.with({ selector: '#tab-group-env' }))).host();
|
||||
expect(await tabGroupHost.hasClass('adf-hide-tab')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should get the bpm user information', async () => {
|
||||
spyOn(component, 'getBpmUserImage').and.returnValue(profilePictureUrl);
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const bpmTab = await loader.getHarness(MatTabHarness.with({ label: 'USER_PROFILE.TAB.PS' }));
|
||||
await bpmTab.select();
|
||||
const bpmUsername = fixture.debugElement.query(By.css('#bpm-username'));
|
||||
const bpmImage = fixture.debugElement.query(By.css('#bpm-user-detail-image'));
|
||||
expect(element.querySelector('#userinfo_container')).not.toBeNull();
|
||||
expect(bpmUsername).not.toBeNull();
|
||||
expect(bpmImage).not.toBeNull();
|
||||
expect(bpmImage.properties.src).toContain(profilePictureUrl);
|
||||
expect(bpmUsername.nativeElement.textContent).toContain('fake-bpm-first-name fake-bpm-last-name');
|
||||
expect(fixture.debugElement.query(By.css('#bpm-tenant')).nativeElement.textContent).toContain('fake-tenant-name');
|
||||
});
|
||||
|
||||
it('should get the ecm user information', async () => {
|
||||
spyOn(component, 'getEcmAvatar').and.returnValue(profilePictureUrl);
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const ecmUsername = fixture.debugElement.query(By.css('#ecm-username'));
|
||||
const ecmImage = fixture.debugElement.query(By.css('#ecm-user-detail-image'));
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
expect(element.querySelector('#userinfo_container')).toBeDefined();
|
||||
expect(ecmUsername).not.toBeNull();
|
||||
expect(ecmImage).not.toBeNull();
|
||||
expect(ecmImage.properties.src).toContain(profilePictureUrl);
|
||||
expect(fixture.debugElement.query(By.css('#ecm-full-name')).nativeElement.textContent).toContain(
|
||||
'fake-ecm-first-name fake-ecm-last-name'
|
||||
);
|
||||
expect(fixture.debugElement.query(By.css('#ecm-job-title')).nativeElement.textContent).toContain('job-ecm-test');
|
||||
});
|
||||
|
||||
it('should show the ecm image if exists', async () => {
|
||||
spyOn(component, 'getEcmAvatar').and.returnValue(profilePictureUrl);
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
expect(element.querySelector('#userinfo_container')).toBeDefined();
|
||||
expect(element.querySelector('#logged-user-img')).toBeDefined();
|
||||
expect(element.querySelector('#logged-user-img').getAttribute('src')).toEqual(profilePictureUrl);
|
||||
});
|
||||
|
||||
it('should show the ecm initials if the ecm user has no image', async () => {
|
||||
component.ecmUser = fakeEcmUserNoImage as any;
|
||||
await whenFixtureReady();
|
||||
|
||||
expect(element.querySelector('#userinfo_container')).toBeDefined();
|
||||
expect(element.querySelector('[data-automation-id="user-initials-image"]').textContent).toContain('ff');
|
||||
});
|
||||
|
||||
it('should show the tabs for the env', async () => {
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const tabGroup = await loader.getHarness(MatTabGroupHarness.with({ selector: '#tab-group-env' }));
|
||||
const tabs = await tabGroup.getTabs();
|
||||
|
||||
expect(await (await tabGroup.host()).hasClass('adf-hide-tab')).toBeFalsy();
|
||||
expect(tabs.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should not close the menu when a tab is clicked', async () => {
|
||||
await whenFixtureReady();
|
||||
openUserInfo();
|
||||
const bpmTab = await loader.getHarness(MatTabHarness.with({ label: 'USER_PROFILE.TAB.PS' }));
|
||||
|
||||
bpmTab.select();
|
||||
expect(fixture.debugElement.query(By.css('#user-profile-lists'))).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
@ -1,125 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { FullNamePipe, InitialUsernamePipe, UserInfoMode } from '@alfresco/adf-core';
|
||||
import { EcmUserModel, PeopleContentService } from '@alfresco/adf-content-services';
|
||||
import { Component, Input, OnDestroy, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { MatMenuModule, MatMenuTrigger, MenuPositionX, MenuPositionY } from '@angular/material/menu';
|
||||
import { Subject } from 'rxjs';
|
||||
import { PeopleProcessService } from '@alfresco/adf-process-services';
|
||||
import { UserRepresentation } from '@alfresco/js-api';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-process-user-info',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FullNamePipe, MatButtonModule, MatMenuModule, InitialUsernamePipe, MatTabsModule, TranslateModule, MatCardModule],
|
||||
templateUrl: './process-user-info.component.html',
|
||||
styleUrls: ['./process-user-info.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ProcessUserInfoComponent implements OnDestroy {
|
||||
@ViewChild(MatMenuTrigger) trigger: MatMenuTrigger;
|
||||
|
||||
/** Determines if user is logged in. */
|
||||
@Input()
|
||||
isLoggedIn: boolean;
|
||||
|
||||
/** BPM user info. */
|
||||
@Input()
|
||||
bpmUser: UserRepresentation;
|
||||
|
||||
/** ECM user info. */
|
||||
@Input()
|
||||
ecmUser: EcmUserModel;
|
||||
|
||||
/** current mode. */
|
||||
@Input()
|
||||
mode: UserInfoMode = UserInfoMode.PROCESS;
|
||||
|
||||
/** Custom path for the background banner image for APS users. */
|
||||
@Input()
|
||||
bpmBackgroundImage: string = './resources/images/bpm-background.png';
|
||||
|
||||
/** Custom path for the background banner image for ACS users. */
|
||||
@Input()
|
||||
ecmBackgroundImage: string = './resources/images/ecm-background.png';
|
||||
|
||||
/** Custom choice for opening the menu at the bottom. Can be `before` or `after`. */
|
||||
@Input()
|
||||
menuPositionX: MenuPositionX = 'after';
|
||||
|
||||
/** Custom choice for opening the menu at the bottom. Can be `above` or `below`. */
|
||||
@Input()
|
||||
menuPositionY: MenuPositionY = 'below';
|
||||
|
||||
/** Shows/hides the username next to the user info button. */
|
||||
@Input()
|
||||
showName: boolean = true;
|
||||
|
||||
/**
|
||||
* When the username is shown, this defines its position relative to the user info button.
|
||||
* Can be `right` or `left`.
|
||||
*/
|
||||
@Input()
|
||||
namePosition: string = 'right';
|
||||
|
||||
userInfoMode = UserInfoMode;
|
||||
|
||||
private destroy$ = new Subject();
|
||||
|
||||
constructor(private peopleProcessService: PeopleProcessService, private peopleContentService: PeopleContentService) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next(true);
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
onKeyPress(event: KeyboardEvent) {
|
||||
this.closeUserModal(event);
|
||||
}
|
||||
|
||||
private closeUserModal($event: KeyboardEvent) {
|
||||
if ($event.keyCode === 27) {
|
||||
this.trigger.closeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
stopClosing(event: Event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
getBpmUserImage(): string {
|
||||
return this.peopleProcessService.getCurrentUserProfileImage();
|
||||
}
|
||||
|
||||
getEcmAvatar(avatarId: string): string {
|
||||
return this.peopleContentService.getUserProfileImage(avatarId);
|
||||
}
|
||||
|
||||
get showOnRight(): boolean {
|
||||
return this.namePosition === 'right';
|
||||
}
|
||||
|
||||
get canShow(): boolean {
|
||||
return this.isLoggedIn && !!this.bpmUser && !!this.mode;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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.
|
||||
*/
|
||||
|
||||
export * from './process-user-info.component';
|
@ -1,21 +0,0 @@
|
||||
<ng-container>
|
||||
<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
|
||||
*ngIf="mode === userInfoMode.SSO"
|
||||
[identityUser]="identityUser$ | async"
|
||||
[isLoggedIn]="isLoggedIn"
|
||||
></adf-identity-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>
|
@ -1,124 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { 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 { 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';
|
||||
|
||||
/** Custom choice for opening the menu at the bottom. Can be `above` or `below`. */
|
||||
@Input()
|
||||
menuPositionY: MenuPositionY = 'below';
|
||||
|
||||
mode: UserInfoMode;
|
||||
ecmUser$: Observable<EcmUserModel>;
|
||||
bpmUser$: Observable<UserRepresentation>;
|
||||
identityUser$: Observable<IdentityUserModel>;
|
||||
userInfoMode = UserInfoMode;
|
||||
|
||||
constructor(
|
||||
private peopleContentService: PeopleContentService,
|
||||
private peopleProcessService: PeopleProcessService,
|
||||
private identityUserService: IdentityUserService,
|
||||
private basicAlfrescoAuthService: BasicAlfrescoAuthService,
|
||||
private authService: AuthenticationService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.getUserInfo();
|
||||
}
|
||||
|
||||
getUserInfo() {
|
||||
if (this.authService.isOauth()) {
|
||||
this.loadIdentityUserInfo();
|
||||
this.mode = UserInfoMode.SSO;
|
||||
|
||||
if (this.authService.isECMProvider() && this.authService.isEcmLoggedIn()) {
|
||||
this.mode = UserInfoMode.CONTENT_SSO;
|
||||
this.loadEcmUserInfo();
|
||||
}
|
||||
} else if (this.isAllLoggedIn()) {
|
||||
this.loadEcmUserInfo();
|
||||
this.loadBpmUserInfo();
|
||||
this.mode = UserInfoMode.ALL;
|
||||
} else if (this.isEcmLoggedIn()) {
|
||||
this.loadEcmUserInfo();
|
||||
this.mode = UserInfoMode.CONTENT;
|
||||
} else if (this.isBpmLoggedIn()) {
|
||||
this.loadBpmUserInfo();
|
||||
this.mode = UserInfoMode.PROCESS;
|
||||
}
|
||||
}
|
||||
|
||||
get isLoggedIn(): boolean {
|
||||
if (this.basicAlfrescoAuthService.isKerberosEnabled()) {
|
||||
return true;
|
||||
}
|
||||
return this.authService.isLoggedIn();
|
||||
}
|
||||
|
||||
private loadEcmUserInfo(): void {
|
||||
this.ecmUser$ = this.peopleContentService.getCurrentUserInfo();
|
||||
}
|
||||
|
||||
private loadBpmUserInfo() {
|
||||
this.bpmUser$ = this.peopleProcessService.getCurrentUserInfo();
|
||||
}
|
||||
|
||||
private loadIdentityUserInfo() {
|
||||
this.identityUser$ = of(this.identityUserService.getCurrentUserInfo());
|
||||
}
|
||||
|
||||
private isAllLoggedIn() {
|
||||
return (
|
||||
(this.authService.isEcmLoggedIn() && this.authService.isBpmLoggedIn()) ||
|
||||
(this.authService.isALLProvider() && this.basicAlfrescoAuthService.isKerberosEnabled())
|
||||
);
|
||||
}
|
||||
|
||||
private isBpmLoggedIn() {
|
||||
return this.authService.isBpmLoggedIn() || (this.authService.isECMProvider() && this.basicAlfrescoAuthService.isKerberosEnabled());
|
||||
}
|
||||
|
||||
private isEcmLoggedIn() {
|
||||
return this.authService.isEcmLoggedIn() || (this.authService.isECMProvider() && this.basicAlfrescoAuthService.isKerberosEnabled());
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<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>
|
||||
|
||||
<div class="app-console">
|
||||
<h3>Changes log:</h3>
|
||||
<p *ngFor="let log of logs">{{ log }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p class="app-toggle">
|
||||
<mat-slide-toggle
|
||||
id="app-toggle-editable"
|
||||
[color]="'primary'"
|
||||
(change)="toggleEditable()"
|
||||
[checked]="isEditable">
|
||||
Editable
|
||||
</mat-slide-toggle><br>
|
||||
<mat-slide-toggle
|
||||
id="app-toggle-clear-date"
|
||||
[color]="'primary'"
|
||||
(change)="toggleClearDate()"
|
||||
[checked]="showClearDateAction">
|
||||
Show clear date icon
|
||||
</mat-slide-toggle><br>
|
||||
<mat-slide-toggle
|
||||
id="app-toggle-none-option"
|
||||
[color]="'primary'"
|
||||
(change)="toggleNoneOption()"
|
||||
[checked]="showNoneOption">
|
||||
Show none option
|
||||
</mat-slide-toggle><br>
|
||||
<mat-slide-toggle
|
||||
id="app-toggle-label-multivalued-chip"
|
||||
[color]="'primary'"
|
||||
(change)="toggleLabelForChips()"
|
||||
[checked]="showLabelForChips">
|
||||
Show label for chips property
|
||||
</mat-slide-toggle>
|
||||
</p>
|
||||
|
||||
<button mat-raised-button id="adf-reset-card-log" (click)="reset()">Reset Log</button>
|
@ -1,28 +0,0 @@
|
||||
.app-main-content {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
adf-card-view {
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.app-console {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-left: 10px;
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
padding-bottom: 30px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
@ -1,289 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, OnDestroy } from '@angular/core';
|
||||
import {
|
||||
CardViewTextItemModel,
|
||||
CardViewDateItemModel,
|
||||
CardViewDatetimeItemModel,
|
||||
CardViewBoolItemModel,
|
||||
CardViewIntItemModel,
|
||||
CardViewFloatItemModel,
|
||||
CardViewKeyValuePairsItemModel,
|
||||
CardViewSelectItemModel,
|
||||
CardViewUpdateService,
|
||||
CardViewMapItemModel,
|
||||
UpdateNotification,
|
||||
DecimalNumberPipe,
|
||||
CardViewArrayItemModel,
|
||||
CardViewComponent
|
||||
} 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 {
|
||||
isEditable = true;
|
||||
properties: any;
|
||||
logs: string[];
|
||||
showClearDateAction = false;
|
||||
showNoneOption = false;
|
||||
showLabelForChips = false;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private cardViewUpdateService: CardViewUpdateService, private decimalNumberPipe: DecimalNumberPipe) {
|
||||
this.logs = [];
|
||||
this.createCard();
|
||||
}
|
||||
|
||||
respondToCardClick() {
|
||||
this.logs.push(`clickable field`);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.cardViewUpdateService.itemUpdated$.pipe(takeUntil(this.onDestroy$)).subscribe(this.onItemChange.bind(this));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
createCard() {
|
||||
this.properties = [
|
||||
new CardViewTextItemModel({
|
||||
label: 'CardView Text Item',
|
||||
value: 'Spock',
|
||||
key: 'name',
|
||||
default: 'default bar',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewTextItemModel({
|
||||
label: 'CardView Text Item - Protected value',
|
||||
value: 'Spock',
|
||||
key: 'name',
|
||||
default: 'default bar',
|
||||
multiline: false,
|
||||
icon: 'icon',
|
||||
editable: false
|
||||
}),
|
||||
new CardViewTextItemModel({
|
||||
label: 'CardView Text Item - Multiline',
|
||||
value: 'Spock',
|
||||
key: 'name',
|
||||
default: 'default bar',
|
||||
multiline: true,
|
||||
icon: 'icon',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewTextItemModel({
|
||||
label: 'CardView Text Item - Default Value',
|
||||
value: '',
|
||||
key: 'name',
|
||||
default: 'default bar',
|
||||
multiline: false,
|
||||
icon: 'icon',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewTextItemModel({
|
||||
label: 'CardView Text Item - Multivalue (chips)',
|
||||
value: [1, 2, 3],
|
||||
key: 'name',
|
||||
default: 'default bar',
|
||||
multiline: true,
|
||||
multivalued: true,
|
||||
icon: 'icon',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewDateItemModel({
|
||||
label: 'CardView Date Item',
|
||||
value: new Date('1983-11-24T00:00:00Z'),
|
||||
key: 'date',
|
||||
default: new Date('1983-11-24T00:00:00Z'),
|
||||
format: 'shortDate',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewDateItemModel({
|
||||
label: 'CardView Date Item - Multivalue (chips)',
|
||||
value: [new Date('1983-11-24T00:00:00Z')],
|
||||
key: 'date',
|
||||
default: new Date('1983-11-24T00:00:00Z'),
|
||||
format: 'shortDate',
|
||||
editable: this.isEditable,
|
||||
multivalued: true
|
||||
}),
|
||||
new CardViewDatetimeItemModel({
|
||||
label: 'CardView Datetime Item',
|
||||
value: new Date(1983, 11, 24, 10, 0, 0),
|
||||
key: 'datetime',
|
||||
default: new Date(1983, 11, 24, 10, 0, 0),
|
||||
format: 'short',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewDatetimeItemModel({
|
||||
label: 'CardView Datetime Item - Multivalue (chips)',
|
||||
value: [new Date(1983, 11, 24, 10, 0, 0)],
|
||||
key: 'datetime',
|
||||
default: new Date(1983, 11, 24, 10, 0, 0),
|
||||
format: 'short',
|
||||
editable: this.isEditable,
|
||||
multivalued: true
|
||||
}),
|
||||
new CardViewBoolItemModel({
|
||||
label: 'CardView Boolean Item',
|
||||
value: true,
|
||||
key: 'boolean',
|
||||
default: false,
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewBoolItemModel({
|
||||
label: 'Agree to all terms and conditions',
|
||||
value: true,
|
||||
key: 'boolean',
|
||||
default: false,
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewIntItemModel({
|
||||
label: 'CardView Int Item',
|
||||
value: 213,
|
||||
key: 'int',
|
||||
default: 1,
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewFloatItemModel({
|
||||
label: 'CardView Float Item',
|
||||
value: 9.9,
|
||||
key: 'float',
|
||||
default: 0.0,
|
||||
editable: this.isEditable,
|
||||
pipes: [{ pipe: this.decimalNumberPipe }]
|
||||
}),
|
||||
new CardViewFloatItemModel({
|
||||
label: 'CardView Float Item - Multivalue (chips)',
|
||||
value: [9.9],
|
||||
key: 'float',
|
||||
default: 0.0,
|
||||
editable: this.isEditable,
|
||||
multivalued: true,
|
||||
pipes: [{ pipe: this.decimalNumberPipe }]
|
||||
}),
|
||||
new CardViewKeyValuePairsItemModel({
|
||||
label: 'CardView Key-Value Pairs Item',
|
||||
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' }
|
||||
],
|
||||
key: 'key-value-pairs',
|
||||
editable: false
|
||||
}),
|
||||
new CardViewSelectItemModel({
|
||||
label: 'CardView Select Item',
|
||||
value: 'one',
|
||||
options$: of([
|
||||
{ key: 'one', label: 'One' },
|
||||
{ key: 'two', label: 'Two' }
|
||||
]),
|
||||
key: 'select',
|
||||
editable: this.isEditable
|
||||
}),
|
||||
new CardViewMapItemModel({
|
||||
label: 'My map',
|
||||
value: new Map([['999', 'My Value']]),
|
||||
key: 'map',
|
||||
default: 'default map value'
|
||||
}),
|
||||
new CardViewTextItemModel({
|
||||
label: 'This is clickable ',
|
||||
value: 'click here',
|
||||
key: 'click',
|
||||
default: 'click here',
|
||||
editable: this.isEditable,
|
||||
clickable: true,
|
||||
icon: 'close',
|
||||
clickCallBack: () => {
|
||||
this.respondToCardClick();
|
||||
}
|
||||
}),
|
||||
new CardViewArrayItemModel({
|
||||
label: 'CardView Array of items',
|
||||
value: of([
|
||||
{ icon: 'directions_bike', value: 'Zlatan' },
|
||||
{ icon: 'directions_bike', value: 'Lionel Messi' },
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
{ value: 'Mohamed', directions_bike: 'save' },
|
||||
{ value: 'Ronaldo' }
|
||||
]),
|
||||
key: 'array',
|
||||
icon: 'edit',
|
||||
default: 'Empty',
|
||||
noOfItemsToDisplay: 2,
|
||||
editable: this.isEditable
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
onItemChange(notification: UpdateNotification) {
|
||||
let value = notification.changed[notification.target.key];
|
||||
|
||||
if (notification.target.type === 'keyvaluepairs') {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
|
||||
this.logs.push(`[${notification.target.label}] - ${value}`);
|
||||
}
|
||||
|
||||
toggleEditable() {
|
||||
this.isEditable = !this.isEditable;
|
||||
this.createCard();
|
||||
}
|
||||
|
||||
toggleClearDate() {
|
||||
this.showClearDateAction = !this.showClearDateAction;
|
||||
}
|
||||
|
||||
toggleNoneOption() {
|
||||
this.showNoneOption = !this.showNoneOption;
|
||||
}
|
||||
|
||||
toggleLabelForChips() {
|
||||
this.showLabelForChips = !this.showLabelForChips;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.isEditable = true;
|
||||
this.createCard();
|
||||
this.logs = [];
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
<adf-cloud-app-list (appClick)="onAppClick($event)"></adf-cloud-app-list>
|
@ -1,35 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } 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) {}
|
||||
|
||||
onAppClick(app) {
|
||||
this.cloudLayoutService.setCurrentTaskFilterParam({ key: 'my-tasks' });
|
||||
this.router.navigate([`/cloud/${app.name}`]);
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel [expanded]="expandTaskFilter" (opened)="onTaskFilterOpen()" (closed)="onTaskFilterClose()" data-automation-id='Task Filters'>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Task Filters
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<adf-cloud-task-filters
|
||||
*ngIf="expandTaskFilter"
|
||||
[appName]="appName"
|
||||
[showIcons]="true"
|
||||
[filterParam]="currentTaskFilter$ | async"
|
||||
(filterClicked)="onTaskFilterSelected($event)"
|
||||
(filterSelected)="onTaskFilterSelected($event)">
|
||||
</adf-cloud-task-filters>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel [expanded]="expandProcessFilter" (opened)="onProcessFilterOpen()" (closed)="onProcessFilterClose()" data-automation-id='Process Filters'>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Process Filters
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<adf-cloud-process-filters
|
||||
*ngIf="expandProcessFilter"
|
||||
[appName]="appName"
|
||||
[showIcons]="true"
|
||||
[filterParam]="currentProcessFilter$ | async"
|
||||
(filterClicked)="onProcessFilterSelected($event)"
|
||||
(filterSelected)="onProcessFilterSelected($event)">
|
||||
</adf-cloud-process-filters>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
@ -1,4 +0,0 @@
|
||||
app-cloud-task-filters .app-filters__entry,
|
||||
app-cloud-process-filters .app-filters__entry {
|
||||
padding-left: 0;
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, ViewEncapsulation, Input, OnInit } from '@angular/core';
|
||||
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';
|
||||
@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;
|
||||
|
||||
currentTaskFilter$: Observable<any>;
|
||||
currentProcessFilter$: Observable<any>;
|
||||
|
||||
toggleTaskFilter = true;
|
||||
toggleProcessFilter = true;
|
||||
|
||||
expandTaskFilter = true;
|
||||
expandProcessFilter = false;
|
||||
|
||||
constructor(
|
||||
private cloudLayoutService: CloudLayoutService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private cloudProcessFiltersService: CloudProcessFiltersService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.currentTaskFilter$ = this.cloudLayoutService.taskFilter$;
|
||||
this.currentProcessFilter$ = this.cloudLayoutService.processFilter$;
|
||||
|
||||
let root = '';
|
||||
if (this.route.snapshot?.firstChild) {
|
||||
root = this.route.snapshot.firstChild.url[0].path;
|
||||
if (root === 'tasks') {
|
||||
this.expandTaskFilter = true;
|
||||
this.expandProcessFilter = false;
|
||||
} else if (root === 'processes') {
|
||||
this.expandProcessFilter = true;
|
||||
this.expandTaskFilter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onTaskFilterSelected(filter) {
|
||||
if (filter) {
|
||||
this.router.navigate([`/cloud/${this.appName}/tasks/`], { queryParams: filter });
|
||||
}
|
||||
}
|
||||
|
||||
onProcessFilterSelected(filter: ProcessFilterCloudModel) {
|
||||
if (filter) {
|
||||
const { appName } = this;
|
||||
const { id } = filter;
|
||||
|
||||
const queryParams = this.cloudProcessFiltersService.writeQueryParams(filter, appName, id);
|
||||
this.router.navigate([`/cloud/${appName}/processes/`], { queryParams });
|
||||
}
|
||||
}
|
||||
|
||||
onTaskFilterOpen(): boolean {
|
||||
this.expandTaskFilter = true;
|
||||
this.expandProcessFilter = false;
|
||||
return this.toggleTaskFilter;
|
||||
}
|
||||
|
||||
onTaskFilterClose(): boolean {
|
||||
return !this.toggleTaskFilter;
|
||||
}
|
||||
|
||||
onProcessFilterOpen(): boolean {
|
||||
this.expandProcessFilter = true;
|
||||
this.expandTaskFilter = false;
|
||||
return this.toggleProcessFilter;
|
||||
}
|
||||
|
||||
onProcessFilterClose(): boolean {
|
||||
return !this.toggleProcessFilter;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<mat-tab-group class="app-cloud-layout-tab-body">
|
||||
<mat-tab label="App">
|
||||
<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>
|
||||
</ng-template>
|
||||
</adf-sidenav-layout-header>
|
||||
<adf-sidenav-layout-navigation>
|
||||
<ng-template>
|
||||
<adf-sidebar-action-menu [expanded]="true" [width]="205" title="CREATE">
|
||||
<mat-icon adf-sidebar-menu-title-icon>arrow_drop_down</mat-icon>
|
||||
<div adf-sidebar-menu-options>
|
||||
<button mat-menu-item data-automation-id="btn-start-task" (click)="onStartTask()">
|
||||
<mat-icon>assessment</mat-icon>
|
||||
<span>New Task</span>
|
||||
</button>
|
||||
</div>
|
||||
<div adf-sidebar-menu-options>
|
||||
<button mat-menu-item data-automation-id="btn-start-process" (click)="onStartProcess()">
|
||||
<mat-icon>assessment</mat-icon>
|
||||
<span>New Process</span>
|
||||
</button>
|
||||
</div>
|
||||
</adf-sidebar-action-menu>
|
||||
<app-cloud-filters-demo [appName]="appName"></app-cloud-filters-demo>
|
||||
</ng-template>
|
||||
</adf-sidenav-layout-navigation>
|
||||
<adf-sidenav-layout-content>
|
||||
<ng-template>
|
||||
<router-outlet></router-outlet>
|
||||
</ng-template>
|
||||
</adf-sidenav-layout-content>
|
||||
</adf-sidenav-layout>
|
||||
</mat-tab>
|
||||
<mat-tab label="Settings">
|
||||
<app-cloud-settings></app-cloud-settings>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
@ -1,28 +0,0 @@
|
||||
@import 'styles/mat-selectors';
|
||||
|
||||
.app-cloud-layout-overflow {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
app-cloud-layout {
|
||||
.app-cloud-layout-tab-body {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
|
||||
adf-sidenav-layout {
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.app-cloud-layout-toolbar {
|
||||
display: flex;
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 { Router, ActivatedRoute, RouterOutlet } 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 {
|
||||
appName: string;
|
||||
filterName: string;
|
||||
|
||||
constructor(private router: Router, private route: ActivatedRoute, private cloudLayoutService: CloudLayoutService) {}
|
||||
|
||||
ngOnInit() {
|
||||
let root: string = '';
|
||||
this.route.params.subscribe((params) => {
|
||||
this.appName = params.appName;
|
||||
});
|
||||
|
||||
if (this.route.snapshot?.firstChild) {
|
||||
root = this.route.snapshot.firstChild.url[0].path;
|
||||
}
|
||||
|
||||
this.route.queryParams.subscribe((params) => {
|
||||
if (root === 'tasks' && params.id) {
|
||||
this.cloudLayoutService.setCurrentTaskFilterParam({ id: params.id });
|
||||
}
|
||||
|
||||
if (root === 'processes' && params.id) {
|
||||
this.cloudLayoutService.setCurrentProcessFilterParam({ id: params.id });
|
||||
}
|
||||
|
||||
if (params.filterName) {
|
||||
this.filterName = params.filterName;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onStartTask() {
|
||||
this.router.navigate([`/cloud/${this.appName}/start-task/`]);
|
||||
}
|
||||
|
||||
onStartProcess() {
|
||||
this.router.navigate([`/cloud/${this.appName}/start-process/`]);
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
.activiti-form-viewer {
|
||||
margin: 10px;
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
<adf-alfresco-viewer [nodeId]="nodeId">
|
||||
</adf-alfresco-viewer>
|
@ -1,38 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } 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) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.params.subscribe((params: Params) => {
|
||||
this.nodeId = params['nodeId'];
|
||||
});
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } 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';
|
||||
/* 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> `
|
||||
})
|
||||
export class CustomEditorComponent extends WidgetComponent {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
@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>
|
||||
</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>
|
||||
</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 {
|
||||
constructor(public formService: FormService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.field.value = typeof this.field.value === 'object' ? JSON.stringify(this.field.value) : this.field.value;
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } 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 }]
|
||||
})
|
||||
export class ProcessCloudLayoutComponent {
|
||||
constructor(private formRenderingService: FormRenderingService) {
|
||||
this.formRenderingService.register({
|
||||
'custom-editor': () => CustomEditorComponent,
|
||||
'demo-widget': () => CustomEditorComponent,
|
||||
'custom-string': () => CustomWidgetComponent,
|
||||
'custom-datetime': () => CustomWidgetComponent,
|
||||
'custom-file': () => CustomWidgetComponent,
|
||||
'custom-number': () => CustomWidgetComponent,
|
||||
'custom-something': () => CustomWidgetComponent,
|
||||
'custom-boolean': () => CustomWidgetComponent,
|
||||
'custom-date': () => CustomWidgetComponent,
|
||||
custom: () => CustomWidgetComponent
|
||||
});
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<button data-automation-id="go-back" mat-icon-button (click)="onGoBack()">
|
||||
<mat-icon>arrow_back</mat-icon> Go Back
|
||||
</button>
|
||||
|
||||
<h4 data-automation-id="process-details-header">Simple page to show the process instance: {{ processInstanceId }} of the app: {{ appName }}</h4>
|
||||
|
||||
<div class="app-process-cloud-container">
|
||||
|
||||
<adf-cloud-task-list
|
||||
class="app-cloud-layout-overflow"
|
||||
[appName]="appName"
|
||||
[processInstanceId]="processInstanceId"
|
||||
(rowClick)="onRowClick($event)">
|
||||
</adf-cloud-task-list>
|
||||
|
||||
<adf-cloud-process-header
|
||||
class="app-process-cloud-header"
|
||||
[appName]="appName"
|
||||
[processInstanceId]="processInstanceId">
|
||||
</adf-cloud-process-header>
|
||||
</div>
|
@ -1,17 +0,0 @@
|
||||
app-process-details-cloud-demo {
|
||||
.app {
|
||||
&-process-cloud-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-cloud-layout-overflow {
|
||||
width: 67%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&-process-cloud-header {
|
||||
margin-left: 10px;
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, 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;
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router) {
|
||||
this.route.params.subscribe((params) => {
|
||||
this.processInstanceId = params.processInstanceId;
|
||||
});
|
||||
|
||||
this.route.parent.params.subscribe((params) => {
|
||||
this.appName = params.appName;
|
||||
});
|
||||
}
|
||||
|
||||
onGoBack() {
|
||||
this.router.navigate([`/cloud/${this.appName}/`]);
|
||||
}
|
||||
|
||||
onRowClick(taskId: string) {
|
||||
if (taskId) {
|
||||
this.router.navigate([`/cloud/${this.appName}/task-details/${taskId}`]);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
<adf-cloud-edit-process-filter
|
||||
[appName]="appName"
|
||||
[id]="filterId"
|
||||
[filterProperties]="filterProperties"
|
||||
[sortProperties]="filterSortProperties"
|
||||
[actions]="filterActions"
|
||||
[processFilter]="editedFilter"
|
||||
(filterChange)="onFilterChange($event)"
|
||||
(action)="onProcessFilterAction($event)">
|
||||
</adf-cloud-edit-process-filter>
|
||||
<div
|
||||
*ngIf="editedFilter"
|
||||
class="app-processes-list-container">
|
||||
<adf-cloud-process-list
|
||||
#processCloud
|
||||
class="app-cloud-layout-overflow"
|
||||
[appName]="editedFilter.appName"
|
||||
[appVersion]="editedFilter.appVersion"
|
||||
[initiator]="editedFilter.initiator"
|
||||
[processDefinitionId]="editedFilter.processDefinitionId"
|
||||
[processDefinitionName]="editedFilter.processDefinitionName"
|
||||
[processDefinitionKey]="editedFilter.processDefinitionKey"
|
||||
[id]="editedFilter.processInstanceId"
|
||||
[status]="editedFilter.status"
|
||||
[name]="editedFilter.processName"
|
||||
[businessKey]="editedFilter['businessKey']"
|
||||
[lastModifiedFrom]="editedFilter.lastModifiedFrom"
|
||||
[lastModifiedTo]="editedFilter.lastModifiedTo"
|
||||
[sorting]="[{orderBy: editedFilter.sort, direction: editedFilter.order}]"
|
||||
[selectionMode]="selectionMode"
|
||||
[stickyHeader]="true"
|
||||
[showActions]="actionMenu"
|
||||
[showContextMenu]="contextMenu"
|
||||
[multiselect]="multiselect"
|
||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||
(showRowContextMenu)="onShowRowContextMenu($event)"
|
||||
(executeRowAction)="onExecuteRowAction($event)"
|
||||
(rowClick)="onRowClick($event)"
|
||||
(rowsSelected)="onRowsSelected($event)">
|
||||
</adf-cloud-process-list>
|
||||
<adf-pagination
|
||||
[target]="processCloud"
|
||||
(changePageSize)="onChangePageSize($event)"
|
||||
(nextPage)="resetSelectedRows()"
|
||||
(prevPage)="resetSelectedRows()">
|
||||
</adf-pagination>
|
||||
<div *ngIf="testingMode">
|
||||
<div *ngIf="multiselect">
|
||||
Selected Rows:
|
||||
<ul>
|
||||
<li *ngFor="let row of selectedRows">{{ row.id }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div *ngIf="actionMenu">
|
||||
<span>Action Menu:</span>
|
||||
<br>
|
||||
<div *ngIf="selectedAction">
|
||||
<span>Process Instance ID: {{ selectedAction.id }}</span><br>
|
||||
<span>Action Type: {{ selectedAction.actionType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="contextMenu">
|
||||
<span>Context Menu:</span>
|
||||
<br>
|
||||
<div *ngIf="selectedContextAction">
|
||||
<span>Process Instance ID: {{ selectedContextAction.id }}</span><br>
|
||||
<span>Action Type}: {{ selectedContextAction.actionType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,22 +0,0 @@
|
||||
app-processes-cloud-demo {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
|
||||
.app-processes-list-container {
|
||||
box-sizing: border-box;
|
||||
place-content: stretch space-between;
|
||||
align-items: stretch;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
&, .app-processes-list-container {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.app-processes-list-container, .app-cloud-layout-overflow {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
PROCESS_FILTER_ACTION_DELETE,
|
||||
PROCESS_FILTER_ACTION_SAVE,
|
||||
PROCESS_FILTER_ACTION_SAVE_AS,
|
||||
ProcessFilterAction,
|
||||
ProcessFilterCloudModel,
|
||||
ProcessFiltersCloudModule,
|
||||
ProcessListCloudModule
|
||||
} from '@alfresco/adf-process-services-cloud';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { DataCellEvent, PaginationComponent, 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
|
||||
})
|
||||
export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
|
||||
appName: string = '';
|
||||
isFilterLoaded = false;
|
||||
|
||||
filterId: string = '';
|
||||
selectedRow: any;
|
||||
multiselect: boolean;
|
||||
selectionMode: string;
|
||||
selectedRows: any[] = [];
|
||||
testingMode: boolean;
|
||||
actionMenu: boolean;
|
||||
contextMenu: boolean;
|
||||
actions: any[] = [];
|
||||
selectedAction: { id: number; name: string; actionType: string };
|
||||
selectedContextAction: { id: number; name: string; actionType: string };
|
||||
|
||||
filterProperties: string[];
|
||||
filterSortProperties: string[];
|
||||
filterActions: string[];
|
||||
|
||||
processDetailsRedirection: boolean;
|
||||
|
||||
editedFilter: ProcessFilterCloudModel;
|
||||
|
||||
private performAction$ = new Subject<any>();
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private cloudLayoutService: CloudLayoutService,
|
||||
private cloudProcessFiltersService: CloudProcessFiltersService,
|
||||
private userPreference: UserPreferencesService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.filterProperties = this.cloudProcessFiltersService.filterProperties;
|
||||
this.filterSortProperties = this.cloudProcessFiltersService.sortProperties;
|
||||
this.filterActions = this.cloudProcessFiltersService.actions;
|
||||
|
||||
this.route.queryParams.subscribe((params) => {
|
||||
this.isFilterLoaded = true;
|
||||
|
||||
this.appName = params.appName;
|
||||
this.filterId = params.id;
|
||||
|
||||
const model = this.cloudProcessFiltersService.readQueryParams(params);
|
||||
this.loadFilter(model);
|
||||
});
|
||||
|
||||
this.cloudLayoutService.settings$.pipe(takeUntil(this.onDestroy$)).subscribe((settings) => this.setCurrentSettings(settings));
|
||||
this.performContextActions();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
setCurrentSettings(settings: CloudServiceSettings) {
|
||||
if (settings) {
|
||||
this.multiselect = settings.multiselect;
|
||||
this.testingMode = settings.testingMode;
|
||||
this.selectionMode = settings.selectionMode;
|
||||
this.processDetailsRedirection = settings.processDetailsRedirection;
|
||||
this.actionMenu = settings.actionMenu;
|
||||
this.contextMenu = settings.contextMenu;
|
||||
this.actions = settings.actions;
|
||||
}
|
||||
}
|
||||
|
||||
onChangePageSize(event: Pagination) {
|
||||
this.userPreference.paginationSize = event.maxItems;
|
||||
}
|
||||
|
||||
resetSelectedRows() {
|
||||
this.selectedRows = [];
|
||||
}
|
||||
|
||||
onRowClick(processInstanceId: string) {
|
||||
if (!this.multiselect && this.selectionMode !== 'multiple' && this.processDetailsRedirection) {
|
||||
this.router.navigate([`/cloud/${this.appName}/process-details/${processInstanceId}`]);
|
||||
}
|
||||
}
|
||||
|
||||
onFilterChange(filter: ProcessFilterCloudModel) {
|
||||
const queryParams = {
|
||||
...this.cloudProcessFiltersService.writeQueryParams(filter, this.appName, filter.id),
|
||||
filterId: filter.id
|
||||
};
|
||||
this.router.navigate([`/cloud/${this.appName}/processes/`], { queryParams });
|
||||
}
|
||||
|
||||
onProcessFilterAction(filterAction: ProcessFilterAction) {
|
||||
if (filterAction.actionType === PROCESS_FILTER_ACTION_DELETE) {
|
||||
this.cloudLayoutService.setCurrentProcessFilterParam({ index: 0 });
|
||||
} else {
|
||||
this.cloudLayoutService.setCurrentProcessFilterParam({ id: filterAction.filter.id });
|
||||
}
|
||||
|
||||
if ([PROCESS_FILTER_ACTION_SAVE, PROCESS_FILTER_ACTION_SAVE_AS].includes(filterAction.actionType)) {
|
||||
this.onFilterChange(filterAction.filter);
|
||||
}
|
||||
}
|
||||
|
||||
onRowsSelected(nodes) {
|
||||
this.resetSelectedRows();
|
||||
this.selectedRows = nodes.map((node) => node.obj);
|
||||
}
|
||||
|
||||
onShowRowActionsMenu(event: DataCellEvent) {
|
||||
event.value.actions = this.actions;
|
||||
}
|
||||
|
||||
onShowRowContextMenu(event: DataCellEvent) {
|
||||
event.value.actions = this.actions.map((action) => ({
|
||||
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 };
|
||||
}
|
||||
|
||||
performContextActions() {
|
||||
this.performAction$.pipe(takeUntil(this.onDestroy$)).subscribe((action: any) => {
|
||||
if (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 };
|
||||
}
|
||||
|
||||
private loadFilter(model: ProcessFilterCloudModel) {
|
||||
if (model?.appName && model.id) {
|
||||
this.editedFilter = model;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
export interface CloudServiceSettings {
|
||||
multiselect: boolean;
|
||||
actionMenu: boolean;
|
||||
contextMenu: boolean;
|
||||
testingMode: boolean;
|
||||
taskDetailsRedirection: boolean;
|
||||
processDetailsRedirection: boolean;
|
||||
selectionMode: string;
|
||||
actions: any[];
|
||||
}
|
||||
|
||||
export interface FilterSettings {
|
||||
id?: string;
|
||||
index?: number;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
export class ActionMenuModel {
|
||||
constructor(
|
||||
public key: string,
|
||||
public icon: string,
|
||||
public title: string,
|
||||
public visible?: boolean,
|
||||
public disabled?: boolean
|
||||
) { }
|
||||
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CloudLayoutService {
|
||||
|
||||
private settings: CloudServiceSettings = {
|
||||
multiselect: false,
|
||||
actionMenu: false,
|
||||
contextMenu: false,
|
||||
testingMode: false,
|
||||
taskDetailsRedirection: true,
|
||||
processDetailsRedirection: true,
|
||||
selectionMode: 'single',
|
||||
actions: []
|
||||
};
|
||||
|
||||
taskFilter$ = new BehaviorSubject<FilterSettings>({index: 0});
|
||||
processFilter$ = new BehaviorSubject<FilterSettings>({index: 0});
|
||||
settings$ = new BehaviorSubject<CloudServiceSettings>(this.settings);
|
||||
|
||||
setCurrentTaskFilterParam(param: FilterSettings) {
|
||||
this.taskFilter$.next(param);
|
||||
}
|
||||
|
||||
setCurrentProcessFilterParam(param: FilterSettings) {
|
||||
this.processFilter$.next(param);
|
||||
}
|
||||
|
||||
setCurrentSettings(param: CloudServiceSettings) {
|
||||
this.settings$.next(param);
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ProcessFilterCloudModel, ProcessFilterCloudService } from '@alfresco/adf-process-services-cloud';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CloudProcessFiltersService {
|
||||
constructor(private appConfigService: AppConfigService, private processFilterCloudService: ProcessFilterCloudService) {
|
||||
}
|
||||
|
||||
get filterProperties(): string[] {
|
||||
return this.appConfigService.get(
|
||||
'adf-edit-process-filter.filterProperties',
|
||||
['status', 'sort', 'order', 'processName']
|
||||
);
|
||||
}
|
||||
|
||||
get sortProperties(): string[] {
|
||||
return this.appConfigService.get(
|
||||
'adf-edit-process-filter.sortProperties',
|
||||
['id', 'name', 'status', 'startDate']
|
||||
);
|
||||
}
|
||||
|
||||
get actions(): string[] {
|
||||
return this.appConfigService.get(
|
||||
'adf-edit-process-filter.actions',
|
||||
['save', 'saveAs', 'delete']
|
||||
);
|
||||
}
|
||||
|
||||
readQueryParams(obj: any): ProcessFilterCloudModel {
|
||||
return this.processFilterCloudService.readQueryParams(obj);
|
||||
}
|
||||
|
||||
writeQueryParams(value: any, appName?: string, id?: string): any {
|
||||
return this.processFilterCloudService.writeQueryParams(value, this.filterProperties, appName, id);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
<mat-slide-toggle [checked]="multiselect" (change)="toggleMultiselect()" data-automation-id="multiSelection">
|
||||
Multiselection
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle [checked]="actionMenu" (change)="toggleActionMenu()" data-automation-id="actionmenu">
|
||||
Action Menu
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle [checked]="contextMenu" (change)="toggleContextMenu()" data-automation-id="contextmenu">
|
||||
Context Menu
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle [checked]="testingMode" (change)="toggleTestingMode()" data-automation-id="testingMode">
|
||||
Testing Mode
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle [checked]="taskDetailsRedirection" (change)="toggleTaskDetailsRedirection()" data-automation-id="taskDetailsRedirection">
|
||||
Display task details on task click
|
||||
</mat-slide-toggle>
|
||||
<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-label>Selection Mode</mat-label>
|
||||
<mat-select [(ngModel)]="selectionMode" (selectionChange)="onSelectionModeChange()">
|
||||
<mat-option *ngFor="let option of selectionModeOptions" [value]="option.value">
|
||||
{{ option.title }}
|
||||
</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>
|
@ -1,25 +0,0 @@
|
||||
app-cloud-settings {
|
||||
padding: 20px 30px;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.app-cloud-actions {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.adf-cloud-settings-selection-mode {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.app-cloud-settings-form {
|
||||
display: flex;
|
||||
place-content: center space-around;
|
||||
align-items: center;
|
||||
|
||||
.app-cloud-settings-form-input {
|
||||
flex: 1 1 100%;
|
||||
max-width: 23%;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, 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';
|
||||
|
||||
@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
|
||||
})
|
||||
export class CloudSettingsComponent implements OnInit, OnDestroy {
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
multiselect: boolean;
|
||||
actionMenu: boolean;
|
||||
contextMenu: boolean;
|
||||
actions: ActionMenuModel[] = [];
|
||||
selectionMode: string;
|
||||
testingMode: boolean;
|
||||
taskDetailsRedirection: boolean;
|
||||
processDetailsRedirection: boolean;
|
||||
|
||||
selectionModeOptions = [
|
||||
{ value: '', title: 'None' },
|
||||
{ value: 'single', title: 'Single' },
|
||||
{ value: 'multiple', title: 'Multiple' }
|
||||
];
|
||||
|
||||
actionMenuForm = new UntypedFormGroup({
|
||||
key: new UntypedFormControl(''),
|
||||
title: new UntypedFormControl(''),
|
||||
icon: new UntypedFormControl(''),
|
||||
visible: new UntypedFormControl(true),
|
||||
disabled: new UntypedFormControl(false)
|
||||
});
|
||||
|
||||
constructor(private cloudLayoutService: CloudLayoutService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.cloudLayoutService.settings$.pipe(takeUntil(this.onDestroy$)).subscribe((settings) => this.setCurrentSettings(settings));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
setCurrentSettings(settings) {
|
||||
if (settings) {
|
||||
this.multiselect = settings.multiselect;
|
||||
this.testingMode = settings.testingMode;
|
||||
this.selectionMode = settings.selectionMode;
|
||||
this.taskDetailsRedirection = settings.taskDetailsRedirection;
|
||||
this.processDetailsRedirection = settings.processDetailsRedirection;
|
||||
this.actionMenu = settings.actionMenu;
|
||||
this.contextMenu = settings.contextMenu;
|
||||
this.actions = settings.actions;
|
||||
}
|
||||
}
|
||||
|
||||
toggleMultiselect() {
|
||||
this.multiselect = !this.multiselect;
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
toggleTestingMode() {
|
||||
this.testingMode = !this.testingMode;
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
toggleTaskDetailsRedirection() {
|
||||
this.taskDetailsRedirection = !this.taskDetailsRedirection;
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
toggleProcessDetailsRedirection() {
|
||||
this.processDetailsRedirection = !this.processDetailsRedirection;
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
onSelectionModeChange() {
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
toggleActionMenu() {
|
||||
this.actionMenu = !this.actionMenu;
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
toggleContextMenu() {
|
||||
this.contextMenu = !this.contextMenu;
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
addAction() {
|
||||
this.actions.push(this.actionMenuForm.value);
|
||||
this.actionMenuForm.get('key').reset();
|
||||
this.actionMenuForm.get('title').reset();
|
||||
this.actionMenuForm.get('icon').reset();
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
removeAction(removedAction: ActionMenuModel) {
|
||||
this.actions = this.actions.filter((action: ActionMenuModel) => action.key !== removedAction.key);
|
||||
this.setSetting();
|
||||
}
|
||||
|
||||
setSetting() {
|
||||
this.cloudLayoutService.setCurrentSettings({
|
||||
multiselect: this.multiselect,
|
||||
actionMenu: this.actionMenu,
|
||||
contextMenu: this.contextMenu,
|
||||
actions: this.actions,
|
||||
testingMode: this.testingMode,
|
||||
selectionMode: this.selectionMode,
|
||||
taskDetailsRedirection: this.taskDetailsRedirection,
|
||||
processDetailsRedirection: this.processDetailsRedirection
|
||||
});
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<adf-cloud-start-process
|
||||
[appName]="appName"
|
||||
[name]="processName"
|
||||
[values]="formValues"
|
||||
[variables]="variables"
|
||||
(error)="openSnackMessage($event)"
|
||||
(success)="onStartProcessSuccess()"
|
||||
(formContentClicked)="onFormContentClicked($event)"
|
||||
(cancel)="onCancelStartProcess()">
|
||||
</adf-cloud-start-process>
|
@ -1,73 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } from '@angular/core';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [StartProcessCloudModule],
|
||||
templateUrl: './start-process-cloud-demo.component.html',
|
||||
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
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.parent.params.subscribe((params) => {
|
||||
this.appName = params.appName;
|
||||
});
|
||||
|
||||
this.processName = this.appConfig.get<string>('adf-cloud-start-process.name');
|
||||
this.formValues = this.appConfig.get<string>('adf-cloud-start-process.values');
|
||||
this.variables = this.appConfig.get<string>('adf-cloud-start-process.variables');
|
||||
}
|
||||
|
||||
onStartProcessSuccess() {
|
||||
this.cloudLayoutService.setCurrentProcessFilterParam({ key: 'running-processes' });
|
||||
this.router.navigate([`/cloud/${this.appName}/processes`]);
|
||||
}
|
||||
|
||||
onCancelStartProcess() {
|
||||
this.cloudLayoutService.setCurrentProcessFilterParam({ key: 'all-processes' });
|
||||
this.router.navigate([`/cloud/${this.appName}/processes`]);
|
||||
}
|
||||
|
||||
openSnackMessage(event: any) {
|
||||
this.notificationService.openSnackMessage(event.response.body.entry.message);
|
||||
}
|
||||
|
||||
onFormContentClicked(resourceClicked: any) {
|
||||
this.previewService.showResource(resourceClicked.nodeId);
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<adf-cloud-start-task
|
||||
[appName]="appName"
|
||||
(error)="openSnackMessage($event)"
|
||||
(success)="onStartTaskSuccess()"
|
||||
(cancel)="onCancelStartTask()">
|
||||
</adf-cloud-start-task>
|
@ -1,58 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } 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
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.parent.params.subscribe((params) => {
|
||||
this.appName = params.appName;
|
||||
});
|
||||
}
|
||||
|
||||
onStartTaskSuccess() {
|
||||
this.cloudLayoutService.setCurrentTaskFilterParam({ key: 'my-tasks' });
|
||||
this.router.navigate([`/cloud/${this.appName}/tasks`]);
|
||||
}
|
||||
|
||||
onCancelStartTask() {
|
||||
this.cloudLayoutService.setCurrentTaskFilterParam({ key: 'my-tasks' });
|
||||
this.router.navigate([`/cloud/${this.appName}/tasks`]);
|
||||
}
|
||||
|
||||
openSnackMessage(event: any) {
|
||||
this.notificationService.openSnackMessage(event.response.body.message);
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<h4 data-automation-id="task-details-header">Simple page to show the taskId: {{ taskId }} of the app: {{ appName }}</h4>
|
||||
|
||||
<div class="app-task-details-cloud-column">
|
||||
<div class="app-task-details-cloud-row">
|
||||
<adf-cloud-task-form
|
||||
[appName]="appName"
|
||||
[taskId]="taskId"
|
||||
(cancelClick)="goBack()"
|
||||
(taskCompleted)="onTaskCompleted()"
|
||||
(formContentClicked)="onFormContentClicked($event)"
|
||||
(formSaved)="onFormSaved()"
|
||||
(error)="onError($event)">
|
||||
</adf-cloud-task-form>
|
||||
<adf-cloud-task-header
|
||||
#taskHeader
|
||||
[appName]="appName"
|
||||
[taskId]="taskId">
|
||||
</adf-cloud-task-header>
|
||||
</div>
|
||||
</div>
|
@ -1,48 +0,0 @@
|
||||
app-task-details-cloud-demo {
|
||||
.app {
|
||||
&-task-detail-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-task-title {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
&-task-control {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
&-demop-card-container {
|
||||
width: 30%;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
&-task-details-cloud-column {
|
||||
margin: 0;
|
||||
flex-direction: column;
|
||||
|
||||
.app-task-details-cloud-row {
|
||||
flex-direction: row;
|
||||
|
||||
adf-cloud-task-form {
|
||||
flex: 1 1 100%;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
adf-cloud-task-header {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-task-details-cloud-column, &-task-details-cloud-row {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, 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 { 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;
|
||||
|
||||
taskId: string;
|
||||
appName: string;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
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 {
|
||||
return this.appName !== undefined && this.taskId !== undefined;
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.router.navigate([`/cloud/${this.appName}/`]);
|
||||
}
|
||||
|
||||
onTaskCompleted() {
|
||||
this.goBack();
|
||||
}
|
||||
|
||||
onFormContentClicked(resourceClicked: any) {
|
||||
this.previewService.showResource(resourceClicked.nodeId);
|
||||
}
|
||||
|
||||
onFormSaved() {
|
||||
this.notificationService.openSnackMessage('Task has been saved successfully');
|
||||
}
|
||||
|
||||
onError({ message: error }: Error) {
|
||||
let errorMessage;
|
||||
try {
|
||||
errorMessage = JSON.parse(error).message || JSON.parse(error).entry?.message;
|
||||
errorMessage = JSON.parse(errorMessage).message;
|
||||
} catch {}
|
||||
this.notificationService.showError(errorMessage || error);
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
<adf-cloud-edit-task-filter
|
||||
[appName]="appName"
|
||||
[id]="filterId"
|
||||
[filterProperties]="taskFilterProperties.filterProperties"
|
||||
[sortProperties]="taskFilterProperties.sortProperties"
|
||||
[actions]="taskFilterProperties.actions"
|
||||
(action)="onTaskFilterAction($event)"
|
||||
(filterChange)="onFilterChange($event)">
|
||||
</adf-cloud-edit-task-filter>
|
||||
<div class="adf-cloud-task-list-container" *ngIf="editedFilter">
|
||||
<adf-cloud-task-list
|
||||
#taskCloud
|
||||
class="app-cloud-layout-overflow"
|
||||
[appName]="editedFilter.appName"
|
||||
[processDefinitionId]="editedFilter.processDefinitionId"
|
||||
[processInstanceId]="editedFilter.processInstanceId"
|
||||
[name]="editedFilter.taskName"
|
||||
[id]="editedFilter.taskId"
|
||||
[parentTaskId]="editedFilter.parentTaskId"
|
||||
[priority]="editedFilter.priority"
|
||||
[owner]="editedFilter.owner"
|
||||
[lastModifiedFrom]="editedFilter.lastModifiedFrom"
|
||||
[lastModifiedTo]="editedFilter.lastModifiedTo"
|
||||
[status]="editedFilter.status"
|
||||
[assignee]="editedFilter.assignee"
|
||||
[createdDate]="editedFilter.createdDate"
|
||||
[dueDate]="editedFilter.dueDate"
|
||||
[sorting]="sortArray"
|
||||
[standalone]="editedFilter.standalone"
|
||||
[multiselect]="multiselect"
|
||||
[selectionMode]="selectionMode"
|
||||
[stickyHeader]="true"
|
||||
[showActions]="actionMenu"
|
||||
[showContextMenu]="contextMenu"
|
||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||
(showRowContextMenu)="onShowRowContextMenu($event)"
|
||||
(executeRowAction)="onExecuteRowAction($event)"
|
||||
(rowClick)="onRowClick($event)"
|
||||
(rowsSelected)="onRowsSelected($event)">
|
||||
</adf-cloud-task-list>
|
||||
<adf-pagination
|
||||
[target]="taskCloud"
|
||||
(changePageSize)="onChangePageSize($event)"
|
||||
(nextPage)="resetSelectedRows()"
|
||||
(prevPage)="resetSelectedRows()">
|
||||
</adf-pagination>
|
||||
<div *ngIf="testingMode">
|
||||
<div *ngIf="multiselect">
|
||||
Selected Rows:
|
||||
<ul>
|
||||
<li *ngFor="let row of selectedRows" [attr.data-automation-id]="row.id">{{ row.name }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div *ngIf="actionMenu">
|
||||
<span>Action Menu:</span>
|
||||
<br>
|
||||
<div *ngIf="selectedAction">
|
||||
<span [attr.data-automation-id]="selectedAction.id">Task ID: {{ selectedAction.id }}</span><br>
|
||||
<span [attr.data-automation-id]="selectedAction.actionType">Action Type: {{ selectedAction.actionType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="contextMenu">
|
||||
<span>Context Menu:</span>
|
||||
<br>
|
||||
<div *ngIf="selectedContextAction">
|
||||
<span [attr.data-automation-id]="selectedContextAction.id">Task ID: {{ selectedContextAction.id }}</span><br>
|
||||
<span [attr.data-automation-id]="selectedContextAction.actionType">Action Type: {{ selectedContextAction.actionType }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,22 +0,0 @@
|
||||
app-tasks-cloud-demo {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
|
||||
.adf-cloud-task-list-container {
|
||||
box-sizing: border-box;
|
||||
place-content: stretch space-between;
|
||||
align-items: stretch;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
&, .adf-cloud-task-list-container {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.adf-cloud-task-list-container, .app-cloud-layout-overflow {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, 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 { 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';
|
||||
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
|
||||
})
|
||||
export class TasksCloudDemoComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('taskCloud')
|
||||
taskCloud: TaskListCloudComponent;
|
||||
|
||||
appName: string = '';
|
||||
|
||||
isFilterLoaded = false;
|
||||
|
||||
selectedRow: any;
|
||||
|
||||
sortArray: TaskListCloudSortingModel[];
|
||||
editedFilter: TaskFilterCloudModel;
|
||||
taskFilterProperties: any = { filterProperties: [], sortProperties: [], actions: [] };
|
||||
|
||||
filterId;
|
||||
multiselect: boolean;
|
||||
selectedRows: any[] = [];
|
||||
actionMenu: boolean;
|
||||
contextMenu: boolean;
|
||||
actions: any[] = [];
|
||||
selectedAction: { id: number; name: string; actionType: string };
|
||||
selectedContextAction: { id: number; name: string; actionType: string };
|
||||
testingMode: boolean;
|
||||
selectionMode: string;
|
||||
taskDetailsRedirection: boolean;
|
||||
|
||||
private performAction$ = new Subject<any>();
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private cloudLayoutService: CloudLayoutService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private userPreference: UserPreferencesService,
|
||||
private appConfig: AppConfigService
|
||||
) {
|
||||
const properties = this.appConfig.get<Array<any>>(TASK_FILTER_PROPERTY_KEYS);
|
||||
if (properties) {
|
||||
this.taskFilterProperties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.isFilterLoaded = false;
|
||||
this.route.parent.params.subscribe((params) => {
|
||||
this.appName = params.appName;
|
||||
});
|
||||
|
||||
this.route.queryParams.subscribe((params) => {
|
||||
this.isFilterLoaded = true;
|
||||
this.onFilterChange(params);
|
||||
this.filterId = params.id;
|
||||
});
|
||||
|
||||
this.cloudLayoutService.settings$.pipe(takeUntil(this.onDestroy$)).subscribe((settings) => this.setCurrentSettings(settings));
|
||||
this.performContextActions();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
setCurrentSettings(settings) {
|
||||
if (settings) {
|
||||
this.multiselect = settings.multiselect;
|
||||
this.testingMode = settings.testingMode;
|
||||
this.selectionMode = settings.selectionMode;
|
||||
this.taskDetailsRedirection = settings.taskDetailsRedirection;
|
||||
this.actionMenu = settings.actionMenu;
|
||||
this.contextMenu = settings.contextMenu;
|
||||
this.actions = settings.actions;
|
||||
}
|
||||
}
|
||||
|
||||
onChangePageSize(event) {
|
||||
this.userPreference.paginationSize = event.maxItems;
|
||||
}
|
||||
|
||||
resetSelectedRows() {
|
||||
this.selectedRows = [];
|
||||
}
|
||||
|
||||
onRowClick(taskId) {
|
||||
if (!this.multiselect && this.selectionMode !== 'multiple' && this.taskDetailsRedirection) {
|
||||
this.router.navigate([`/cloud/${this.appName}/task-details/${taskId}`]);
|
||||
}
|
||||
}
|
||||
|
||||
onRowsSelected(nodes) {
|
||||
this.resetSelectedRows();
|
||||
this.selectedRows = nodes.map((node) => node.obj);
|
||||
}
|
||||
|
||||
onFilterChange(filter: any) {
|
||||
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 {
|
||||
this.cloudLayoutService.setCurrentTaskFilterParam({ id: filterAction.filter.id });
|
||||
}
|
||||
|
||||
if (filterAction.actionType === ACTION_SAVE_AS) {
|
||||
this.router.navigate([`/cloud/${this.appName}/tasks/`], { queryParams: filterAction.filter });
|
||||
}
|
||||
}
|
||||
|
||||
onShowRowActionsMenu(event: DataCellEvent) {
|
||||
event.value.actions = this.actions;
|
||||
}
|
||||
|
||||
onShowRowContextMenu(event: DataCellEvent) {
|
||||
event.value.actions = this.actions.map((action) => ({
|
||||
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 };
|
||||
}
|
||||
|
||||
performContextActions() {
|
||||
this.performAction$.pipe(takeUntil(this.onDestroy$)).subscribe((action: any) => {
|
||||
if (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 };
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
<adf-error-content [errorCode]="errorCode">
|
||||
<div adf-error-content-actions>
|
||||
<button mat-raised-button (click)="onReturnButton()">Back to home</button>
|
||||
</div>
|
||||
</adf-error-content>
|
@ -1,47 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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 } 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) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.route) {
|
||||
this.route.params.subscribe((params: Params) => {
|
||||
if (params['id']) {
|
||||
this.errorCode = params['id'];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onReturnButton() {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
<ng-container *ngIf="nodeId">
|
||||
<adf-alfresco-viewer
|
||||
(showViewerChange)="onViewerClosed()"
|
||||
[nodeId]="nodeId"
|
||||
[versionId]="versionId"
|
||||
[showToolbar]="true"
|
||||
[allowRightSidebar]="true"
|
||||
[sidebarRightTemplate]="sidebarRightTemplate">
|
||||
</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">
|
||||
|
||||
<adf-info-drawer-tab label="Comments">
|
||||
<adf-node-comments [nodeId]="nodeId" [readOnly]="!isCommentEnabled">
|
||||
</adf-node-comments>
|
||||
</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>
|
||||
|
||||
<p class="toggle">
|
||||
<mat-slide-toggle
|
||||
id="adf-metadata-default-properties"
|
||||
(change)="toggleDisplayProperties()"
|
||||
[checked]="displayDefaultProperties">
|
||||
Display Default Properties
|
||||
</mat-slide-toggle>
|
||||
</p>
|
||||
|
||||
<p class="toggle">
|
||||
<mat-slide-toggle
|
||||
id="adf-metadata-empty"
|
||||
(change)="toggleEmptyMetadata()"
|
||||
[checked]="displayEmptyMetadata">
|
||||
Display Empty Metadata
|
||||
</mat-slide-toggle>
|
||||
</p>
|
||||
|
||||
<p class="toggle">
|
||||
<mat-slide-toggle
|
||||
id="adf-metadata-multi"
|
||||
(change)="toggleMulti()"
|
||||
[checked]="multi">
|
||||
Multi accordion
|
||||
</mat-slide-toggle>
|
||||
</p>
|
||||
|
||||
<p class="toggle">
|
||||
<mat-slide-toggle
|
||||
id="adf-metadata-readonly"
|
||||
(change)="toggleReadOnly()"
|
||||
[checked]="isReadOnly">
|
||||
Read Only
|
||||
</mat-slide-toggle>
|
||||
</p>
|
||||
|
||||
<p class="toggle">
|
||||
<mat-slide-toggle
|
||||
id="adf-toggle-custom-preset"
|
||||
(change)="togglePreset()"
|
||||
[checked]="isPreset">
|
||||
Custom preset
|
||||
</mat-slide-toggle>
|
||||
</p>
|
||||
|
||||
<p class="toggle">
|
||||
|
||||
<mat-form-field floatPlaceholder="float">
|
||||
<input matInput placeholder="Display Aspect" [(ngModel)]="desiredAspect">
|
||||
</mat-form-field>
|
||||
|
||||
<button mat-raised-button (click)="applyAspect()">Apply Aspect</button>
|
||||
</p>
|
||||
|
||||
<p class="toggle">
|
||||
<ng-container *ngIf="isPreset">
|
||||
<mat-form-field floatPlaceholder="float">
|
||||
<input matInput placeholder="Custom Preset" [(ngModel)]="customPreset" data-automation-id="adf-text-custom-preset">
|
||||
</mat-form-field>
|
||||
<button mat-raised-button id="adf-metadata-aplly" (click)="applyCustomPreset()">Apply</button>
|
||||
</ng-container>
|
||||
</p>
|
||||
|
||||
</adf-info-drawer-tab>
|
||||
|
||||
<adf-info-drawer-tab label="Versions">
|
||||
<adf-version-manager [node]="node"
|
||||
(uploadError)="onUploadError($event)"
|
||||
(viewVersion)="onViewVersion($event)">
|
||||
</adf-version-manager>
|
||||
</adf-info-drawer-tab>
|
||||
</adf-info-drawer>
|
||||
</ng-template>
|
@ -1,158 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { InfoDrawerComponent, InfoDrawerTabComponent, NotificationService, ViewerComponent } from '@alfresco/adf-core';
|
||||
import {
|
||||
AlfrescoViewerComponent,
|
||||
AllowableOperationsEnum,
|
||||
ContentMetadataComponent,
|
||||
ContentService,
|
||||
FileUploadErrorEvent,
|
||||
NodeCommentsComponent,
|
||||
NodesApiService,
|
||||
PermissionsEnum,
|
||||
VersionManagerComponent
|
||||
} 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',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FileViewComponent implements OnInit {
|
||||
nodeId: string = null;
|
||||
versionId: string = null;
|
||||
displayEmptyMetadata = false;
|
||||
expanded: boolean;
|
||||
multi = false;
|
||||
isReadOnly = false;
|
||||
isPreset = false;
|
||||
customPreset: string = null;
|
||||
displayDefaultProperties = true;
|
||||
isCommentEnabled = 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
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.params.subscribe((params) => {
|
||||
const id = params.nodeId;
|
||||
this.versionId = params.versionId;
|
||||
if (id) {
|
||||
this.nodeApiService.getNode(id).subscribe(
|
||||
(node) => {
|
||||
if (node?.isFile) {
|
||||
this.isCommentEnabled =
|
||||
this.contentServices.hasPermissions(node, PermissionsEnum.NOT_CONSUMER) ||
|
||||
this.contentServices.hasAllowableOperations(node, AllowableOperationsEnum.UPDATE);
|
||||
this.nodeId = id;
|
||||
return;
|
||||
}
|
||||
this.router.navigate(['/files', id]);
|
||||
},
|
||||
() => this.router.navigate(['/files', id])
|
||||
);
|
||||
} else if (this.preview?.content) {
|
||||
this.blobFile = this.preview.content;
|
||||
this.fileName = this.preview.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onViewVersion(versionId: string) {
|
||||
this.preview.showResource(this.nodeId, versionId);
|
||||
}
|
||||
|
||||
onViewerClosed() {
|
||||
const primaryUrl = this.router.parseUrl(this.router.url).root.children[PRIMARY_OUTLET].toString();
|
||||
this.router.navigateByUrl(primaryUrl);
|
||||
}
|
||||
|
||||
onUploadError(event: FileUploadErrorEvent) {
|
||||
this.notificationService.showError(event.error);
|
||||
}
|
||||
|
||||
toggleEmptyMetadata() {
|
||||
this.displayEmptyMetadata = !this.displayEmptyMetadata;
|
||||
}
|
||||
|
||||
toggleMulti() {
|
||||
this.multi = !this.multi;
|
||||
}
|
||||
|
||||
toggleReadOnly() {
|
||||
this.isReadOnly = !this.isReadOnly;
|
||||
}
|
||||
|
||||
toggleDisplayProperties() {
|
||||
this.displayDefaultProperties = !this.displayDefaultProperties;
|
||||
}
|
||||
|
||||
togglePreset() {
|
||||
this.isPreset = !this.isPreset;
|
||||
if (!this.isPreset) {
|
||||
this.customPreset = null;
|
||||
}
|
||||
}
|
||||
|
||||
applyCustomPreset() {
|
||||
this.isPreset = false;
|
||||
setTimeout(() => {
|
||||
this.isPreset = true;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
applyAspect() {
|
||||
this.showAspect = this.desiredAspect;
|
||||
}
|
||||
}
|
@ -1,393 +0,0 @@
|
||||
<div class="app-container">
|
||||
<div
|
||||
id="document-list-container"
|
||||
class="app-document-list-container">
|
||||
<adf-upload-drag-area
|
||||
[disabled]="disableDragArea"
|
||||
[acceptedFilesType]="getFileFiltering()"
|
||||
[rootFolderId]="currentFolderId"
|
||||
[versioning]="versioning"
|
||||
[adf-check-allowable-operation]="'create'"
|
||||
[adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []"
|
||||
(updateFileVersion)="onUploadNewVersion($event)">
|
||||
<div *ngIf="errorMessage" class="app-error-message">
|
||||
<button (click)="resetError()" mat-icon-button>
|
||||
<mat-icon>highlight_off</mat-icon>
|
||||
</button>
|
||||
<span class="app-error-message--text">{{errorMessage}}</span>
|
||||
</div>
|
||||
<adf-toolbar *ngIf="!disableDragArea" class="app-files-toolbar">
|
||||
<adf-toolbar-title>
|
||||
<adf-breadcrumb root="Personal Files" [target]="documentList">
|
||||
</adf-breadcrumb>
|
||||
<adf-dropdown-breadcrumb [target]="documentList">
|
||||
</adf-dropdown-breadcrumb>
|
||||
</adf-toolbar-title>
|
||||
|
||||
<div class="app-document-action-buttons">
|
||||
<button
|
||||
data-automation-id="create-new-folder"
|
||||
mat-icon-button
|
||||
[disabled]="!canCreateContent(documentList.folderNode)"
|
||||
title="New folder"
|
||||
(error)="openSnackMessageError($event)"
|
||||
(success)="documentList.reload()"
|
||||
[adf-create-folder]="currentFolderId">
|
||||
<mat-icon>create_new_folder</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
[disabled]="!hasSelection(documentList.selection)"
|
||||
title="Download"
|
||||
[adfNodeDownload]="documentList.selection">
|
||||
<mat-icon>get_app</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
data-automation-id="delete-toolbar-button"
|
||||
adf-check-allowable-operation="delete"
|
||||
[permanent]="true"
|
||||
[adf-nodes]="documentList.selection"
|
||||
title="Delete"
|
||||
(delete)="onDeleteActionSuccess($event)"
|
||||
[adf-delete]="documentList.selection">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button mat-icon-button (click)="showVersions = !showVersions" class="app-show-versions-button"
|
||||
title="Toggle metadata">
|
||||
<mat-icon>{{ showVersions ? 'chevron_right' : 'chevron_left' }}</mat-icon>
|
||||
</button>
|
||||
|
||||
<adf-toolbar-divider class="app-toolbar-divider-before-more-menu"></adf-toolbar-divider>
|
||||
|
||||
<button class="app-toolbar-more-menu-button" mat-icon-button [matMenuTriggerFor]="menu">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item
|
||||
adf-check-allowable-operation="delete"
|
||||
[adf-nodes]="documentList.selection"
|
||||
(delete)="onDeleteActionSuccess($event)"
|
||||
[adf-delete]="documentList.selection">
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>Delete</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</adf-toolbar>
|
||||
|
||||
<div class="app-document-list-container-in-upload-drag-area app-document-list-container" [ngClass]="{'adf-sticky-document-list': stickyHeader }">
|
||||
<adf-document-list
|
||||
#documentList
|
||||
class="app-file-list-container"
|
||||
[permissionsStyle]="permissionsStyle"
|
||||
[currentFolderId]="currentFolderId"
|
||||
[contextMenuActions]="true"
|
||||
[contentActions]="true"
|
||||
[allowDropFiles]="allowDropFiles"
|
||||
[selectionMode]="selectionMode"
|
||||
[multiselect]="multiselect"
|
||||
[node]="nodeResult"
|
||||
[includeFields]="includeFields"
|
||||
[sorting]="sorting"
|
||||
[sortingMode]="sortingMode"
|
||||
[showHeader]="showHeader"
|
||||
[stickyHeader]="stickyHeader"
|
||||
[headerFilters]="headerFilters"
|
||||
[filterValue]="paramValues"
|
||||
(error)="onNavigationError($event)"
|
||||
(success)="resetError()"
|
||||
(ready)="emitReadyEvent($event)"
|
||||
(preview)="showFile($event)"
|
||||
(folderChange)="onFolderChange($event)"
|
||||
(permissionError)="handlePermissionError($event)"
|
||||
(name-click)="documentList.onNodeDblClick($any($event).detail?.node)"
|
||||
(filterSelection)="onFilterSelected($event)">
|
||||
|
||||
<adf-custom-empty-content-template *ngIf="disableDragArea">
|
||||
<div class="app-empty_template">
|
||||
<div class="app-no-result-message">{{ 'SEARCH.NO_RESULT' | translate }}</div>
|
||||
</div>
|
||||
</adf-custom-empty-content-template>
|
||||
<data-columns>
|
||||
<data-column
|
||||
key="$thumbnail"
|
||||
type="image"
|
||||
[sortable]="false">
|
||||
</data-column>
|
||||
<data-column
|
||||
key="name"
|
||||
sortingKey="name"
|
||||
title="Display name"
|
||||
class="adf-expand-cell-5">
|
||||
</data-column>
|
||||
<data-column
|
||||
key="content.sizeInBytes"
|
||||
title="Size"
|
||||
type="fileSize"
|
||||
sortingKey="sizeInBytes"
|
||||
class="adf-ellipsis-cell">
|
||||
</data-column>
|
||||
<data-column
|
||||
*ngIf="searchTerm"
|
||||
key="search"
|
||||
title="Search"
|
||||
class="adf-expand-cell-3">
|
||||
<ng-template let-entry="$implicit">
|
||||
<div [innerHTML]="searchResultsHighlight(entry.row.node.entry.search) | highlight:searchTerm">
|
||||
</div>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
|
||||
<data-column
|
||||
class="app-full-width adf-ellipsis-cell adf-desktop-only"
|
||||
title="Node id"
|
||||
[sortable]="false"
|
||||
key="id">
|
||||
</data-column>
|
||||
|
||||
<data-column
|
||||
title="Lock"
|
||||
key="lock"
|
||||
[focus]="false"
|
||||
[sortable]="false"
|
||||
class="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>
|
||||
<mat-icon *ngIf="!entry.row.getValue('isLocked')">lock_open</mat-icon>
|
||||
</button>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
<data-column
|
||||
title="Created by"
|
||||
key="createdByUser.displayName"
|
||||
sortingKey="createdByUser"
|
||||
class="adf-ellipsis-cell">
|
||||
</data-column>
|
||||
<data-column
|
||||
title="Created"
|
||||
key="createdAt"
|
||||
sortingKey="createdAt"
|
||||
type="date"
|
||||
[format]="'timeAgo'"
|
||||
class="adf-ellipsis-cell">
|
||||
</data-column>
|
||||
|
||||
</data-columns>
|
||||
|
||||
<content-actions>
|
||||
<content-action
|
||||
icon="get_app"
|
||||
title="Download"
|
||||
handler="download">
|
||||
</content-action>
|
||||
<content-action
|
||||
icon="delete"
|
||||
permission="delete"
|
||||
[disableWithNoPermission]="true"
|
||||
title="Delete"
|
||||
(permissionEvent)="handlePermissionError($event)"
|
||||
(success)="onDeleteActionSuccess($event)"
|
||||
handler="delete">
|
||||
</content-action>
|
||||
<content-action
|
||||
icon="supervisor_account"
|
||||
title="Permission"
|
||||
permission="copy"
|
||||
(error)="onContentActionError($event)"
|
||||
(execute)="onPermissionRequested($event)">
|
||||
</content-action>
|
||||
<!-- document actions -->
|
||||
<content-action
|
||||
icon="storage"
|
||||
target="document"
|
||||
title="Manage versions"
|
||||
(execute)="onManageVersions($event)">
|
||||
</content-action>
|
||||
<content-action
|
||||
icon="beach_access"
|
||||
target="document"
|
||||
title="Update Aspects"
|
||||
(execute)="onAspectUpdate($event)">
|
||||
</content-action>
|
||||
</content-actions>
|
||||
</adf-document-list>
|
||||
</div>
|
||||
<adf-pagination
|
||||
[target]="documentList"
|
||||
(changePageSize)="onChangePageSize($event)"
|
||||
(changePageNumber)="onChangePageNumber($event)"
|
||||
(nextPage)="onNextPage($event)"
|
||||
(prevPage)="onPrevPage($event)">
|
||||
</adf-pagination>
|
||||
</adf-upload-drag-area>
|
||||
|
||||
<adf-info-drawer-layout *ngIf="showVersions" class="app-manage-versions-sidebar">
|
||||
<div info-drawer-content>
|
||||
|
||||
<adf-info-drawer [title]="'Details'" *ngIf="documentList.selection[0]">
|
||||
<adf-info-drawer-tab label="Properties">
|
||||
<adf-content-metadata
|
||||
[node]="documentList.selection[0].entry"
|
||||
[displayEmpty]="displayEmptyMetadata"
|
||||
[displayTags]="true"
|
||||
[displayCategories]="true">
|
||||
</adf-content-metadata>
|
||||
</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"
|
||||
[allowDownload]="allowVersionDownload">
|
||||
</adf-version-manager>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-template #choose_document_template>
|
||||
<div class="app-manage-versions-empty">
|
||||
<mat-icon class="app-manage-versions-empty-icon">face</mat-icon>
|
||||
Select a file to see its versions
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #no_permission_to_versions>
|
||||
<div class="app-manage-versions-no-permission">
|
||||
<mat-icon class="app-manage-versions-no-permission-icon">warning</mat-icon>
|
||||
You don't have permission to manage versions of this content
|
||||
</div>
|
||||
</ng-template>
|
||||
</adf-info-drawer-tab>
|
||||
</adf-info-drawer>
|
||||
</div>
|
||||
</adf-info-drawer-layout>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="showSettingsPanel" class="app-content-service-settings">
|
||||
<p>Current folder ID: {{ documentList.currentFolderId }}</p>
|
||||
|
||||
<div class="app-p-10">
|
||||
Selected Nodes:
|
||||
<ul>
|
||||
<li *ngFor="let node of documentList.selection">
|
||||
{{ node.entry.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="app-container">
|
||||
<section>
|
||||
<mat-slide-toggle data-automation-id="multiSelectToggle" [(ngModel)]="multiselect">
|
||||
Multiselect (with checkboxes)
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-multiple-upload-switch" [(ngModel)]="multipleFileUpload" >
|
||||
Multiple File Upload
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-folder-upload-switch" [(ngModel)]="folderUpload">
|
||||
Folder upload
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-extension-filter-upload-switch" [(ngModel)]="acceptedFilesTypeShow">
|
||||
Custom extensions filter
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-max-size-filter-upload-switch" [(ngModel)]="maxSizeShow">
|
||||
Max size filter
|
||||
</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 [(ngModel)]="allowVersionDownload">
|
||||
Enable version download
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle [(ngModel)]="displayEmptyMetadata" id="displayEmptyMetadata">
|
||||
Display Empty Metadata
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle [(ngModel)]="stickyHeader" id="stickyHeader">
|
||||
Sticky Header
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<h5>Upload</h5>
|
||||
<section *ngIf="acceptedFilesTypeShow">
|
||||
<mat-form-field floatPlaceholder="float">
|
||||
<input matInput
|
||||
placeholder="Extension accepted"
|
||||
[(ngModel)]="acceptedFilesType"
|
||||
data-automation-id="accepted-files-type">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
<section *ngIf="maxSizeShow">
|
||||
<mat-form-field>
|
||||
<input matInput type="number" placeholder="Max file size" [(ngModel)]="maxFilesSize"
|
||||
data-automation-id="max-files-size">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
<div *ngIf="!acceptedFilesTypeShow">
|
||||
<adf-upload-button
|
||||
[disabled]="!enableUpload"
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[multipleFiles]="multipleFileUpload"
|
||||
[uploadFolders]="folderUpload"
|
||||
[maxFilesSize]="maxSizeShow ? maxFilesSize : null"
|
||||
(error)="openSnackMessageError($event)"
|
||||
[versioning]="versioning"
|
||||
[adf-check-allowable-operation]="'create'"
|
||||
[adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []"
|
||||
(permissionEvent)="handlePermissionError($event)">
|
||||
</adf-upload-button>
|
||||
</div>
|
||||
<div *ngIf="acceptedFilesTypeShow">
|
||||
<adf-upload-button
|
||||
[disabled]="!enableUpload"
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[acceptedFilesType]="acceptedFilesType"
|
||||
[multipleFiles]="multipleFileUpload"
|
||||
[uploadFolders]="folderUpload"
|
||||
[versioning]="versioning"
|
||||
(error)="openSnackMessageError($event)"
|
||||
[adf-check-allowable-operation]="'create'"
|
||||
[adf-nodes]="enableUpload ? getCurrentDocumentListNode() : []"
|
||||
(permissionEvent)="handlePermissionError($event)">
|
||||
</adf-upload-button>
|
||||
</div>
|
||||
<section>
|
||||
<mat-checkbox id="adf-disable-upload" [(ngModel)]="enableUpload">
|
||||
Enable upload
|
||||
</mat-checkbox>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="app-p-10">
|
||||
<p>Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items</p>
|
||||
<mat-form-field>
|
||||
<mat-select placeholder="Selection Mode" [(ngModel)]="selectionMode" name="food">
|
||||
<mat-option *ngFor="let mode of selectionModes" [value]="mode.value">
|
||||
{{mode.viewValue}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
@ -1,76 +0,0 @@
|
||||
.app-container:has(.app-document-list-container) {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.app-error-message {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.app-error-message--text {
|
||||
color: var(--theme-warn-color);
|
||||
}
|
||||
|
||||
.app-document-list-container {
|
||||
min-height: 400px;
|
||||
|
||||
.app-datatable-list {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
adf-upload-drag-area {
|
||||
margin-right: 16px;
|
||||
|
||||
adf-toolbar-title {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.app-document-action-buttons {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.app-document-list-container-in-upload-drag-area) {
|
||||
display: flex;
|
||||
place-content: stretch flex-start;
|
||||
align-items: stretch;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-datatable-card .app-lock-button {
|
||||
top: -10px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.app-content-service-settings {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.app-manage-versions-sidebar {
|
||||
flex: 0 0 auto;
|
||||
|
||||
&.adf-info-drawer-layout {
|
||||
width: 360px;
|
||||
}
|
||||
}
|
||||
|
||||
.app-no-result__empty_doc_lib {
|
||||
width: 565px;
|
||||
height: 161px;
|
||||
object-fit: contain;
|
||||
margin-top: 17px;
|
||||
}
|
||||
|
||||
.app-empty_template {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.app-no-result-message {
|
||||
height: 32px;
|
||||
opacity: 0.26;
|
||||
font-size: var(--theme-headline-font-size);
|
||||
line-height: 1.33;
|
||||
letter-spacing: -1px;
|
||||
}
|
@ -1,571 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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,
|
||||
Input,
|
||||
OnInit,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
Optional,
|
||||
EventEmitter,
|
||||
ViewChild,
|
||||
SimpleChanges,
|
||||
Output,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { NodeEntry, NodePaging, Pagination, Node, SearchEntry } from '@alfresco/js-api';
|
||||
import {
|
||||
NotificationService,
|
||||
UserPreferencesService,
|
||||
PaginationComponent,
|
||||
ShowHeaderMode,
|
||||
FormRenderingService,
|
||||
ToolbarTitleComponent,
|
||||
ToolbarComponent,
|
||||
ToolbarDividerComponent,
|
||||
DataColumnComponent,
|
||||
HighlightPipe,
|
||||
DataColumnListComponent,
|
||||
CustomEmptyContentTemplateDirective,
|
||||
InfoDrawerTabComponent,
|
||||
InfoDrawerComponent,
|
||||
InfoDrawerLayoutComponent
|
||||
} from '@alfresco/adf-core';
|
||||
import {
|
||||
ContentService,
|
||||
FolderCreatedEvent,
|
||||
UploadService,
|
||||
DocumentListComponent,
|
||||
PermissionStyleModel,
|
||||
ContentMetadataService,
|
||||
FilterSearch,
|
||||
DialogAspectListService,
|
||||
FileUploadEvent,
|
||||
NodesApiService,
|
||||
UploadDragAreaComponent,
|
||||
CheckAllowableOperationDirective,
|
||||
BreadcrumbComponent,
|
||||
DropdownBreadcrumbComponent,
|
||||
NodeDownloadDirective,
|
||||
NodeDeleteDirective,
|
||||
NodeLockDirective,
|
||||
ContentActionListComponent,
|
||||
ContentActionComponent,
|
||||
ContentMetadataComponent,
|
||||
VersionManagerComponent,
|
||||
UploadButtonComponent
|
||||
} from '@alfresco/adf-content-services';
|
||||
import { ProcessFormRenderingService } from '@alfresco/adf-process-services';
|
||||
import { VersionManagerDialogAdapterComponent } from './version-manager-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,
|
||||
providers: [{ provide: FormRenderingService, useClass: ProcessFormRenderingService }]
|
||||
})
|
||||
export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
||||
protected onDestroy$ = new Subject<boolean>();
|
||||
|
||||
errorMessage: string = null;
|
||||
nodeId: any;
|
||||
showViewer = false;
|
||||
showVersions = false;
|
||||
allowDropFiles = true;
|
||||
includeFields = ['isFavorite', 'isLocked', 'aspectNames', 'definition'];
|
||||
|
||||
selectionModes = [
|
||||
{ value: 'none', viewValue: 'None' },
|
||||
{ value: 'single', viewValue: 'Single' },
|
||||
{ value: 'multiple', viewValue: 'Multiple' }
|
||||
];
|
||||
|
||||
// The identifier of a node. You can also use one of these well-known aliases: -my- | -shared- | -root-
|
||||
@Input()
|
||||
currentFolderId: string = DEFAULT_FOLDER_TO_SHOW;
|
||||
|
||||
@Input()
|
||||
sorting = ['name', 'ASC'];
|
||||
|
||||
@Input()
|
||||
sortingMode: 'server' | 'client' = 'server';
|
||||
|
||||
@Input()
|
||||
showSettingsPanel = true;
|
||||
|
||||
@Input()
|
||||
showHeader = ShowHeaderMode.Always;
|
||||
|
||||
@Input()
|
||||
selectionMode = 'multiple';
|
||||
|
||||
@Input()
|
||||
multiselect = false;
|
||||
|
||||
@Input()
|
||||
multipleFileUpload = false;
|
||||
|
||||
@Input()
|
||||
folderUpload = false;
|
||||
|
||||
@Input()
|
||||
acceptedFilesTypeShow = false;
|
||||
|
||||
@Input()
|
||||
maxSizeShow = false;
|
||||
|
||||
@Input()
|
||||
versioning = false;
|
||||
|
||||
@Input()
|
||||
allowVersionDownload = true;
|
||||
|
||||
@Input()
|
||||
acceptedFilesType = '.jpg,.pdf,.js';
|
||||
|
||||
@Input()
|
||||
maxFilesSize: number = null;
|
||||
|
||||
@Input()
|
||||
enableUpload = true;
|
||||
|
||||
@Input()
|
||||
nodeResult: NodePaging;
|
||||
|
||||
@Input()
|
||||
pagination: Pagination;
|
||||
|
||||
@Input()
|
||||
disableDragArea = false;
|
||||
|
||||
@Input()
|
||||
searchTerm = '';
|
||||
|
||||
@Input()
|
||||
navigationRoute = '/files';
|
||||
|
||||
@Input()
|
||||
headerFilters = false;
|
||||
|
||||
@Input()
|
||||
paramValues: Map<any, any> = null;
|
||||
|
||||
@Input()
|
||||
filterSorting: string = null;
|
||||
|
||||
@Output()
|
||||
documentListReady: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
changedPageSize: EventEmitter<Pagination> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
changedPageNumber: EventEmitter<Pagination> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
turnedNextPage: EventEmitter<Pagination> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
turnedPreviousPage: EventEmitter<Pagination> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
loadNext: EventEmitter<Pagination> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
deleteElementSuccess: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@ViewChild('documentList', { static: true })
|
||||
documentList: DocumentListComponent;
|
||||
|
||||
@ViewChild('standardPagination')
|
||||
standardPagination: PaginationComponent;
|
||||
|
||||
permissionsStyle: PermissionStyleModel[] = [];
|
||||
stickyHeader: boolean;
|
||||
displayEmptyMetadata = false;
|
||||
|
||||
constructor(
|
||||
private notificationService: NotificationService,
|
||||
private uploadService: UploadService,
|
||||
private contentService: ContentService,
|
||||
private dialog: MatDialog,
|
||||
private router: Router,
|
||||
private preference: UserPreferencesService,
|
||||
private preview: PreviewService,
|
||||
@Optional() private route: ActivatedRoute,
|
||||
private contentMetadataService: ContentMetadataService,
|
||||
private dialogAspectListService: DialogAspectListService,
|
||||
private nodeService: NodesApiService
|
||||
) {}
|
||||
|
||||
showFile(event) {
|
||||
const entry = event.value.entry;
|
||||
if (entry?.isFile) {
|
||||
this.preview.showResource(entry.id);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (!this.pagination) {
|
||||
this.pagination = {
|
||||
maxItems: this.preference.paginationSize,
|
||||
skipCount: 0
|
||||
} as Pagination;
|
||||
}
|
||||
|
||||
if (this.route) {
|
||||
this.route.params.forEach((params: Params) => {
|
||||
if (params['id'] && this.currentFolderId !== params['id']) {
|
||||
this.currentFolderId = params['id'];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.uploadService.fileUploadComplete
|
||||
.pipe(
|
||||
debounceTime(300),
|
||||
scan((files, currentFile) => [...files, currentFile], []),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe((value: any[]) => {
|
||||
this.onFileUploadEvent(value[0]);
|
||||
});
|
||||
|
||||
this.uploadService.fileUploadDeleted.pipe(takeUntil(this.onDestroy$)).subscribe((value) => this.onFileUploadEvent(value));
|
||||
|
||||
this.contentService.folderCreated.pipe(takeUntil(this.onDestroy$)).subscribe((value) => this.onFolderCreated(value));
|
||||
|
||||
this.contentService.folderCreate.pipe(takeUntil(this.onDestroy$)).subscribe((value) => this.onFolderAction(value));
|
||||
|
||||
this.contentService.folderEdit.pipe(takeUntil(this.onDestroy$)).subscribe((value) => this.onFolderAction(value));
|
||||
|
||||
this.contentMetadataService.error.pipe(takeUntil(this.onDestroy$)).subscribe((err: { message: string }) => {
|
||||
this.notificationService.showError(err.message);
|
||||
});
|
||||
}
|
||||
|
||||
onFileUploadEvent(event: FileUploadEvent) {
|
||||
if (event && event.file.options.parentId === this.documentList.currentFolderId) {
|
||||
this.documentList.reload();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.nodeResult?.currentValue) {
|
||||
this.nodeResult = changes.nodeResult.currentValue;
|
||||
this.pagination = this.nodeResult.list.pagination;
|
||||
}
|
||||
if (!this.pagination) {
|
||||
this.giveDefaultPaginationWhenNotDefined();
|
||||
}
|
||||
}
|
||||
|
||||
giveDefaultPaginationWhenNotDefined() {
|
||||
this.pagination = {
|
||||
maxItems: this.preference.paginationSize,
|
||||
skipCount: 0,
|
||||
totalItems: 0,
|
||||
hasMoreItems: false
|
||||
} as Pagination;
|
||||
}
|
||||
|
||||
getCurrentDocumentListNode(): NodeEntry[] {
|
||||
if (this.documentList.folderNode) {
|
||||
return [{ entry: this.documentList.folderNode }];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
onNavigationError(error: any) {
|
||||
if (error) {
|
||||
this.router.navigate(['/error', error.status]);
|
||||
}
|
||||
}
|
||||
|
||||
resetError() {
|
||||
this.errorMessage = null;
|
||||
}
|
||||
|
||||
onFolderCreated(event: FolderCreatedEvent) {
|
||||
if (event && event.parentId === this.documentList.currentFolderId) {
|
||||
this.documentList.reload();
|
||||
}
|
||||
}
|
||||
|
||||
onFolderAction(node) {
|
||||
if (node && node.parentId === this.documentList.currentFolderId) {
|
||||
this.documentList.reload();
|
||||
}
|
||||
}
|
||||
|
||||
onFolderChange($event) {
|
||||
this.router.navigate([this.navigationRoute, $event.value.id]);
|
||||
}
|
||||
|
||||
handlePermissionError(event: any) {
|
||||
this.notificationService.showError('PERMISSION.LACKOF', null, {
|
||||
permission: event.permission,
|
||||
action: event.action,
|
||||
type: event.type
|
||||
});
|
||||
}
|
||||
|
||||
openSnackMessageError(error: any) {
|
||||
this.notificationService.showError(error.value || error);
|
||||
}
|
||||
|
||||
openSnackMessageInfo(message: string) {
|
||||
this.notificationService.showInfo(message);
|
||||
}
|
||||
|
||||
emitReadyEvent(event: NodePaging) {
|
||||
this.documentListReady.emit(event);
|
||||
}
|
||||
|
||||
onContentActionError(errors: any) {
|
||||
const errorStatusCode = JSON.parse(errors.message).error.statusCode;
|
||||
let message: string;
|
||||
|
||||
switch (errorStatusCode) {
|
||||
case 403:
|
||||
message = 'OPERATION.ERROR.PERMISSION';
|
||||
break;
|
||||
case 409:
|
||||
message = 'OPERATION.ERROR.CONFLICT';
|
||||
break;
|
||||
default:
|
||||
message = 'OPERATION.ERROR.UNKNOWN';
|
||||
}
|
||||
|
||||
this.openSnackMessageError(message);
|
||||
}
|
||||
|
||||
onDeleteActionSuccess(message: string) {
|
||||
this.uploadService.fileDeleted.next(message);
|
||||
this.deleteElementSuccess.emit();
|
||||
this.documentList.reload();
|
||||
this.openSnackMessageInfo(message);
|
||||
}
|
||||
|
||||
onPermissionRequested(node: any) {
|
||||
this.router.navigate(['/permissions', node.value.entry.id]);
|
||||
}
|
||||
|
||||
onManageVersions(event: any) {
|
||||
const contentEntry = event.value.entry;
|
||||
const showComments = true;
|
||||
const allowDownload = this.allowVersionDownload;
|
||||
|
||||
if (this.contentService.hasAllowableOperations(contentEntry, 'update')) {
|
||||
this.dialog.open(VersionManagerDialogAdapterComponent, {
|
||||
data: { contentEntry, showComments, allowDownload },
|
||||
panelClass: 'adf-version-manager-dialog',
|
||||
width: '630px'
|
||||
});
|
||||
} else {
|
||||
this.openSnackMessageError('OPERATION.ERROR.PERMISSION');
|
||||
}
|
||||
}
|
||||
|
||||
onAspectUpdate(event: any) {
|
||||
this.dialogAspectListService.openAspectListDialog(event.value.entry.id).subscribe((aspectList) => {
|
||||
this.nodeService.updateNode(event.value.entry.id, { aspectNames: [...aspectList] }).subscribe(() => {
|
||||
this.openSnackMessageInfo('Node Aspects Updated');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
hasSelection(selection: Array<any>): boolean {
|
||||
return selection && selection.length > 0;
|
||||
}
|
||||
|
||||
hasOneFileSelected(): boolean {
|
||||
const selection = this.documentList.selection;
|
||||
return selection && selection.length === 1 && selection[0].entry.isFile;
|
||||
}
|
||||
|
||||
userHasPermissionToManageVersions(): boolean {
|
||||
const selection = this.documentList.selection;
|
||||
return this.contentService.hasAllowableOperations(selection[0].entry, 'update');
|
||||
}
|
||||
|
||||
canCreateContent(parentNode: Node): boolean {
|
||||
if (parentNode) {
|
||||
return this.contentService.hasAllowableOperations(parentNode, 'create');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
onChangePageSize(event: Pagination): void {
|
||||
this.preference.paginationSize = event.maxItems;
|
||||
this.pagination.maxItems = event.maxItems;
|
||||
this.pagination.skipCount = event.skipCount;
|
||||
this.changedPageSize.emit(event);
|
||||
}
|
||||
|
||||
onChangePageNumber(event: Pagination): void {
|
||||
this.pagination.maxItems = event.maxItems;
|
||||
this.pagination.skipCount = event.skipCount;
|
||||
this.changedPageNumber.emit(event);
|
||||
}
|
||||
|
||||
onNextPage(event: Pagination): void {
|
||||
this.pagination.maxItems = event.maxItems;
|
||||
this.pagination.skipCount = event.skipCount;
|
||||
this.turnedNextPage.emit(event);
|
||||
}
|
||||
|
||||
onPrevPage(event: Pagination): void {
|
||||
this.pagination.maxItems = event.maxItems;
|
||||
this.pagination.skipCount = event.skipCount;
|
||||
this.turnedPreviousPage.emit(event);
|
||||
}
|
||||
|
||||
onUploadNewVersion(ev) {
|
||||
const contentEntry = ev.detail.data.node.entry;
|
||||
const showComments = true;
|
||||
const allowDownload = this.allowVersionDownload;
|
||||
const newFileVersion = ev.detail.files[0].file;
|
||||
|
||||
if (this.contentService.hasAllowableOperations(contentEntry, 'update')) {
|
||||
this.dialog.open(VersionManagerDialogAdapterComponent, {
|
||||
data: {
|
||||
contentEntry,
|
||||
showComments,
|
||||
allowDownload,
|
||||
newFileVersion,
|
||||
showComparison: true
|
||||
},
|
||||
panelClass: 'adf-version-manager-dialog',
|
||||
width: '630px'
|
||||
});
|
||||
} else {
|
||||
this.openSnackMessageError('OPERATION.ERROR.PERMISSION');
|
||||
}
|
||||
}
|
||||
|
||||
getFileFiltering(): string {
|
||||
return this.acceptedFilesTypeShow ? this.acceptedFilesType : '*';
|
||||
}
|
||||
|
||||
searchResultsHighlight(search: SearchEntry): string {
|
||||
if (search?.highlight) {
|
||||
return search.highlight.map((currentHighlight) => currentHighlight.snippets).join(', ');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
onFilterSelected(activeFilters: FilterSearch[]) {
|
||||
if (activeFilters.length) {
|
||||
this.navigateToFilter(activeFilters);
|
||||
} else {
|
||||
this.clearFilterNavigation();
|
||||
}
|
||||
}
|
||||
|
||||
navigateToFilter(activeFilters: FilterSearch[]) {
|
||||
const objectFromMap = {};
|
||||
activeFilters.forEach((filter: FilterSearch) => {
|
||||
let paramValue = null;
|
||||
if (filter.value?.from && filter.value.to) {
|
||||
paramValue = `${filter.value.from}||${filter.value.to}`;
|
||||
} else {
|
||||
paramValue = filter.value;
|
||||
}
|
||||
objectFromMap[filter.key] = paramValue;
|
||||
});
|
||||
|
||||
this.router.navigate([], { relativeTo: this.route, queryParams: objectFromMap });
|
||||
}
|
||||
|
||||
clearFilterNavigation() {
|
||||
this.documentList.node = null;
|
||||
if (this.currentFolderId === '-my-') {
|
||||
this.router.navigate([this.navigationRoute, '']);
|
||||
} else {
|
||||
this.router.navigate([this.navigationRoute, this.currentFolderId]);
|
||||
}
|
||||
this.documentList.reload();
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<header mat-dialog-title>Manage Versions</header>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-version-manager-switch-readonly" [(ngModel)]="readOnly">
|
||||
Read-only
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-version-manager-switch-download" [(ngModel)]="allowDownload">
|
||||
Enable version download
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle id="adf-version-manager-switch-comments" [(ngModel)]="showComments">
|
||||
Show comments
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section *ngIf="newFileVersion">
|
||||
<mat-slide-toggle id="adf-version-manager-switch-comparison" [(ngModel)]="showVersionComparison">
|
||||
Show version comparison
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section mat-dialog-content *ngIf="!readOnly">
|
||||
<adf-version-manager [node]="contentEntry"
|
||||
(uploadCancel)="hideVersionComparison($event)"
|
||||
(uploadSuccess)="hideVersionComparison($event)"
|
||||
[showVersionComparison]="showVersionComparison"
|
||||
[newFileVersion]="newFileVersion"
|
||||
[allowDownload]="allowDownload"
|
||||
[showComments]="showComments"
|
||||
(uploadError)="uploadError($event)"
|
||||
(viewVersion)="onViewVersion($event)"
|
||||
></adf-version-manager>
|
||||
</section>
|
||||
<section mat-dialog-content *ngIf="readOnly">
|
||||
<adf-version-list [node]="contentEntry" [showActions]="false"></adf-version-list>
|
||||
</section>
|
||||
|
||||
<footer mat-dialog-actions>
|
||||
<button mat-button (click)="close()">Close</button>
|
||||
</footer>
|
@ -1,74 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 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, MatDialogModule, 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';
|
||||
|
||||
@Component({
|
||||
templateUrl: './version-manager-dialog-adapter.component.html',
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatDialogModule, MatSlideToggleModule, FormsModule, VersionManagerComponent, VersionListComponent, MatButtonModule],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class VersionManagerDialogAdapterComponent {
|
||||
contentEntry: Node;
|
||||
newFileVersion: File;
|
||||
showComments = true;
|
||||
allowDownload = true;
|
||||
readOnly = false;
|
||||
showVersionComparison = false;
|
||||
|
||||
constructor(
|
||||
private previewService: PreviewService,
|
||||
private notificationService: NotificationService,
|
||||
@Inject(MAT_DIALOG_DATA) data: any,
|
||||
private containingDialog?: MatDialogRef<VersionManagerDialogAdapterComponent>
|
||||
) {
|
||||
this.contentEntry = data.contentEntry;
|
||||
this.newFileVersion = Object.prototype.hasOwnProperty.call(data, 'newFileVersion') ? data.newFileVersion : this.newFileVersion;
|
||||
this.showComments = Object.prototype.hasOwnProperty.call(data, 'showComments') ? data.showComments : this.showComments;
|
||||
this.allowDownload = Object.prototype.hasOwnProperty.call(data, 'allowDownload') ? data.allowDownload : this.allowDownload;
|
||||
}
|
||||
|
||||
uploadError(event: FileUploadErrorEvent) {
|
||||
this.notificationService.showError(event.error);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.containingDialog.close();
|
||||
}
|
||||
|
||||
onViewVersion(versionId: string) {
|
||||
this.previewService.showResource(this.contentEntry.id, versionId);
|
||||
this.close();
|
||||
}
|
||||
|
||||
hideVersionComparison(isCancelled: any) {
|
||||
if (isCancelled) {
|
||||
this.showVersionComparison = false;
|
||||
this.newFileVersion = null;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user