[ACS-6071] fix jsdoc warnings and errors (#8948)

* fix content docs

* fix extensions docs

* fix insights docs

* [ci:force] fix jsdoc errors and warnings

* enable jsdoc linter

* [ci:force] fix demo shell jsdoc

* [ci:force] fix e2e typings

* fix typo

* fix typo
This commit is contained in:
Denys Vuika
2023-09-29 08:11:58 +01:00
committed by GitHub
parent 501516c8f5
commit d72eb5ebd3
86 changed files with 1233 additions and 254 deletions
+4 -2
View File
@@ -24,7 +24,8 @@ module.exports = {
'plugin:@cspell/recommended', 'plugin:@cspell/recommended',
'plugin:@angular-eslint/ng-cli-compat', 'plugin:@angular-eslint/ng-cli-compat',
'plugin:@angular-eslint/ng-cli-compat--formatting-add-on', 'plugin:@angular-eslint/ng-cli-compat--formatting-add-on',
'plugin:@angular-eslint/template/process-inline-templates' 'plugin:@angular-eslint/template/process-inline-templates',
'plugin:jsdoc/recommended-typescript-error'
], ],
plugins: [ plugins: [
'eslint-plugin-unicorn', 'eslint-plugin-unicorn',
@@ -35,7 +36,8 @@ module.exports = {
'@cspell', '@cspell',
'eslint-plugin-import', 'eslint-plugin-import',
'@angular-eslint/eslint-plugin', '@angular-eslint/eslint-plugin',
'@typescript-eslint' '@typescript-eslint',
'jsdoc'
], ],
rules: { rules: {
// Uncomment this to enable prettier checks as part of the ESLint // Uncomment this to enable prettier checks as part of the ESLint
@@ -28,6 +28,14 @@ import { PreviewService } from '../../services/preview.service';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
/**
* Provide a factory for process upload service
*
* @param api api client
* @param config config service
* @param discoveryApiService discovery service
* @returns factory function
*/
export function processUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService, discoveryApiService: DiscoveryApiService) { export function processUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService, discoveryApiService: DiscoveryApiService) {
return new ProcessUploadService(api, config, discoveryApiService); return new ProcessUploadService(api, config, discoveryApiService);
} }
@@ -28,6 +28,14 @@ import { PreviewService } from '../../services/preview.service';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
/**
* Provide a task upload service factory
*
* @param api api client
* @param config config service
* @param discoveryApiService discovery service
* @returns factory function
*/
export function taskUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService, discoveryApiService: DiscoveryApiService) { export function taskUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService, discoveryApiService: DiscoveryApiService) {
return new TaskUploadService(api, config, discoveryApiService); return new TaskUploadService(api, config, discoveryApiService);
} }
+18
View File
@@ -22,23 +22,41 @@ import { exec } from './exec';
import { logger } from './logger'; import { logger } from './logger';
import program from 'commander'; import program from 'commander';
/**
* Perform a test
*
* @param output output path
*/
function test(output: string) { function test(output: string) {
const response = exec('test !', [`-d ${output} && mkdir ${output}`], {}); const response = exec('test !', [`-d ${output} && mkdir ${output}`], {});
logger.info(response); logger.info(response);
} }
/**
* Copy AWS S3
*
* @param artifact artifact name
*/
function awsCp(artifact: string) { function awsCp(artifact: string) {
logger.info(`aws s3 cp ${artifact}`); logger.info(`aws s3 cp ${artifact}`);
const response = exec(`aws s3 cp ${artifact}`, [`./s3-artifact.tmp ${artifact}`], {}); const response = exec(`aws s3 cp ${artifact}`, [`./s3-artifact.tmp ${artifact}`], {});
logger.info(response); logger.info(response);
} }
/**
* Zip artifact
*
* @param output output name
*/
function zipArtifact(output: string) { function zipArtifact(output: string) {
logger.info(`Perform zip artifact ${output}`); logger.info(`Perform zip artifact ${output}`);
const response = exec('tar', ['-xvf', `./s3-artifact.tmp`, '-C ' + program.output], {}); const response = exec('tar', ['-xvf', `./s3-artifact.tmp`, '-C ' + program.output], {});
logger.info(response); logger.info(response);
} }
/**
* Artifact from S3 command
*/
export default function main() { export default function main() {
program program
.version('0.1.0') .version('0.1.0')
+13
View File
@@ -22,6 +22,11 @@ import { exec } from './exec';
import { logger } from './logger'; import { logger } from './logger';
import program from 'commander'; import program from 'commander';
/**
* Zip artifact
*
* @param artifact artifact name
*/
function zipArtifact(artifact: string) { function zipArtifact(artifact: string) {
logger.info(`Perform zip artifact ${artifact}`); logger.info(`Perform zip artifact ${artifact}`);
@@ -29,6 +34,11 @@ function zipArtifact(artifact: string) {
logger.info(response); logger.info(response);
} }
/**
* Copy to AWS S3
*
* @param output output path
*/
function awsCp(output: string) { function awsCp(output: string) {
logger.info(`aws s3 cp ${output}`); logger.info(`aws s3 cp ${output}`);
const response = exec('aws s3 cp', [`./s3-artifact.tmp ${output}`], {}); const response = exec('aws s3 cp', [`./s3-artifact.tmp ${output}`], {});
@@ -36,6 +46,9 @@ function awsCp(output: string) {
} }
/**
* Artifact to S3 command
*/
export default function main() { export default function main() {
program program
.version('0.1.0') .version('0.1.0')
+7
View File
@@ -24,6 +24,13 @@ import * as fs from 'fs';
import { argv, exit } from 'node:process'; import { argv, exit } from 'node:process';
import program from 'commander'; import program from 'commander';
/**
* Audit report command
*
* @param _args (unused)
* @param workingDir working directory
* @returns void
*/
export default function main(_args: string[], workingDir: string) { export default function main(_args: string[], workingDir: string) {
program program
.description('Generate an audit report') .description('Generate an audit report')
+14
View File
@@ -120,11 +120,25 @@ function getCommits(options: DiffOptions): Array<Commit> {
.filter((commit: Commit) => commitAuthorAllowed(commit, authorFilter)); .filter((commit: Commit) => commitAuthorAllowed(commit, authorFilter));
} }
/**
* Check if commit author is allowed
*
* @param commit git commit
* @param authorFilter filter
* @returns `true` if author is allowed, otherwise `false`
*/
function commitAuthorAllowed(commit: Commit, authorFilter: string): boolean { function commitAuthorAllowed(commit: Commit, authorFilter: string): boolean {
const filterRegex = RegExp(authorFilter); const filterRegex = RegExp(authorFilter);
return !(filterRegex.test(commit.author) || filterRegex.test(commit.author_email)); return !(filterRegex.test(commit.author) || filterRegex.test(commit.author_email));
} }
/**
* Changelog command
*
* @param _args (unused)
* @param workingDir working directory
* @returns void
*/
export default function main(_args: string[], workingDir: string) { export default function main(_args: string[], workingDir: string) {
program program
.description('Generate changelog report for two branches of git repository') .description('Generate changelog report for two branches of git repository')
+11
View File
@@ -25,6 +25,9 @@ const TIMEOUT = 20000;
let counter = 0; let counter = 0;
let alfrescoJsApi: AlfrescoApi; let alfrescoJsApi: AlfrescoApi;
/**
* Check CS environment command
*/
export default async function main() { export default async function main() {
program program
.version('0.1.0') .version('0.1.0')
@@ -42,6 +45,9 @@ export default async function main() {
// await checkDiskSpaceFullEnv(); // await checkDiskSpaceFullEnv();
} }
/**
* Check environment
*/
async function checkEnv() { async function checkEnv() {
try { try {
alfrescoJsApi = new AlfrescoApi({ alfrescoJsApi = new AlfrescoApi({
@@ -111,6 +117,11 @@ async function checkDiskSpaceFullEnv() {
} }
*/ */
/**
* Perform a delay
*
* @param delay timeout in milliseconds
*/
function sleep(delay: number) { function sleep(delay: number) {
const start = new Date().getTime(); const start = new Date().getTime();
while (new Date().getTime() < start + delay) {} while (new Date().getTime() < start + delay) {}
+13 -1
View File
@@ -25,7 +25,10 @@ import { GovernanceCheckPlugin } from './plugins/governance-check-plugin';
let pluginEnv: CheckEnv; let pluginEnv: CheckEnv;
export default async function main(_args: string[]) { /**
* Check environment plugin
*/
export default async function main() {
program program
.version('0.1.0') .version('0.1.0')
.option('--host [type]', 'Remote environment host') .option('--host [type]', 'Remote environment host')
@@ -53,6 +56,9 @@ export default async function main(_args: string[]) {
} }
} }
/**
* Check PS plugin
*/
async function checkProcessServicesPlugin() { async function checkProcessServicesPlugin() {
const processServiceCheckPlugin = new ProcessServiceCheckPlugin( const processServiceCheckPlugin = new ProcessServiceCheckPlugin(
{ {
@@ -64,6 +70,9 @@ async function checkProcessServicesPlugin() {
await processServiceCheckPlugin.checkProcessServicesPlugin(); await processServiceCheckPlugin.checkProcessServicesPlugin();
} }
/**
* Check APA plugin
*/
async function checkProcessAutomationPlugin() { async function checkProcessAutomationPlugin() {
const processAutomationCheckPlugin = new ProcessAutomationCheckPlugin( const processAutomationCheckPlugin = new ProcessAutomationCheckPlugin(
{ {
@@ -77,6 +86,9 @@ async function checkProcessAutomationPlugin() {
await processAutomationCheckPlugin.checkProcessAutomationPlugin(); await processAutomationCheckPlugin.checkProcessAutomationPlugin();
} }
/**
* Check AGS plugin
*/
async function checkGovernancePlugin() { async function checkGovernancePlugin() {
const governancePluginCheck = new GovernanceCheckPlugin( const governancePluginCheck = new GovernanceCheckPlugin(
{ {
+11
View File
@@ -23,6 +23,9 @@ const MAX_RETRY = 10;
const TIMEOUT = 60000; const TIMEOUT = 60000;
let counter = 0; let counter = 0;
/**
* Check PS environment command
*/
export default async function main() { export default async function main() {
program program
.version('0.1.0') .version('0.1.0')
@@ -36,6 +39,9 @@ export default async function main() {
await checkEnv(); await checkEnv();
} }
/**
* Check environment
*/
async function checkEnv() { async function checkEnv() {
try { try {
const alfrescoJsApi = new AlfrescoApi({ const alfrescoJsApi = new AlfrescoApi({
@@ -63,6 +69,11 @@ async function checkEnv() {
} }
} }
/**
* Perform a delay
*
* @param delay timeout in milliseconds
*/
function sleep(delay: number) { function sleep(delay: number) {
const start = new Date().getTime(); const start = new Date().getTime();
while (new Date().getTime() < start + delay) {} while (new Date().getTime() < start + delay) {}
+5
View File
@@ -19,6 +19,11 @@
import * as docker from './docker'; import * as docker from './docker';
/**
* Docker publish command
*
* @param args command arguments
*/
export default function(args: any) { export default function(args: any) {
docker.default(args); docker.default(args);
} }
+55 -14
View File
@@ -46,13 +46,24 @@ export interface PublishArgs {
sourceTag?: string; sourceTag?: string;
} }
function loginPerform(args: PublishArgs) { /**
* Perform a login
*
* @param args arguments
*/
function login(args: PublishArgs) {
logger.info(`Perform docker login...${args.loginRepo}`); logger.info(`Perform docker login...${args.loginRepo}`);
const loginDockerRes = exec('docker', ['login', `-u=${args.loginUsername}`, `-p=${args.loginPassword}`, `${args.loginRepo}`]); const loginDockerRes = exec('docker', ['login', `-u=${args.loginUsername}`, `-p=${args.loginPassword}`, `${args.loginRepo}`]);
logger.info(loginDockerRes); logger.info(loginDockerRes);
} }
function buildImagePerform(args: PublishArgs, tag: string) { /**
* Build Docker image
*
* @param args command arguments
* @param tag tag
*/
function buildImage(args: PublishArgs, tag: string) {
logger.info(`Perform docker build...${args.dockerRepo}:${tag}`); logger.info(`Perform docker build...${args.dockerRepo}:${tag}`);
const buildArgs = []; const buildArgs = [];
@@ -71,19 +82,38 @@ function buildImagePerform(args: PublishArgs, tag: string) {
logger.info(response); logger.info(response);
} }
function tagImagePerform(args: PublishArgs, tagImage: string, newTag: string) { /**
logger.info(`Perform docker tag... ${args.dockerRepo}:${tagImage} on ${args.dockerRepo}:${newTag}`); * Tag Docker image
const response = exec('docker', ['tag', `${args.dockerRepo}:${tagImage}`, `${args.dockerRepo}:${newTag}`], {}); *
* @param args command arguments
* @param imageTag image tag
* @param newTag new image tag
*/
function tagImage(args: PublishArgs, imageTag: string, newTag: string) {
logger.info(`Perform docker tag... ${args.dockerRepo}:${imageTag} on ${args.dockerRepo}:${newTag}`);
const response = exec('docker', ['tag', `${args.dockerRepo}:${imageTag}`, `${args.dockerRepo}:${newTag}`], {});
logger.info(response); logger.info(response);
} }
function pullImagePerform(dockerRepo: string, sourceTag: string) { /**
* Pull Docker image
*
* @param dockerRepo repository
* @param sourceTag tag
*/
function pullImage(dockerRepo: string, sourceTag: string) {
logger.info(`Perform docker pull... ${dockerRepo}:${sourceTag}`); logger.info(`Perform docker pull... ${dockerRepo}:${sourceTag}`);
const response = exec('docker', ['pull', `${dockerRepo}:${sourceTag}`], {}); const response = exec('docker', ['pull', `${dockerRepo}:${sourceTag}`], {});
logger.info(response); logger.info(response);
} }
function pushImagePerform(args: PublishArgs, tag: string) { /**
* Push Docker image
*
* @param args command arguments
* @param tag tag
*/
function pushImage(args: PublishArgs, tag: string) {
if (args.dryrun) { if (args.dryrun) {
logger.info(`Dry-run Perform docker push... ${args.dockerRepo}:${tag}`); logger.info(`Dry-run Perform docker push... ${args.dockerRepo}:${tag}`);
} else { } else {
@@ -93,12 +123,23 @@ function pushImagePerform(args: PublishArgs, tag: string) {
} }
} }
function cleanImagePerform(args: PublishArgs, tag: string) { /**
* Clean Docker image
*
* @param args command arguments
* @param tag tag
*/
function cleanImage(args: PublishArgs, tag: string) {
logger.info(`Perform docker clean on tag:${tag}...`); logger.info(`Perform docker clean on tag:${tag}...`);
const response = exec('docker', ['rmi', `-f`, `${args.dockerRepo}:${tag}`], {}); const response = exec('docker', ['rmi', `-f`, `${args.dockerRepo}:${tag}`], {});
logger.info(response); logger.info(response);
} }
/**
* Publish to Docker command
*
* @param args command arguments
*/
export default function main(args: PublishArgs) { export default function main(args: PublishArgs) {
program program
.version('0.1.0') .version('0.1.0')
@@ -150,7 +191,7 @@ export default function main(args: PublishArgs) {
} }
if (args.loginCheck === true) { if (args.loginCheck === true) {
loginPerform(args); login(args);
} }
let mainTag: string; let mainTag: string;
@@ -162,17 +203,17 @@ export default function main(args: PublishArgs) {
if (index === 0) { if (index === 0) {
logger.info(`Build only once`); logger.info(`Build only once`);
mainTag = tag; mainTag = tag;
buildImagePerform(args, mainTag); buildImage(args, mainTag);
} }
} else { } else {
mainTag = args.sourceTag; mainTag = args.sourceTag;
pullImagePerform(args.dockerRepo, mainTag); pullImage(args.dockerRepo, mainTag);
} }
tagImagePerform(args, mainTag, tag); tagImage(args, mainTag, tag);
pushImagePerform(args, tag); pushImage(args, tag);
} }
}); });
cleanImagePerform(args, mainTag); cleanImage(args, mainTag);
} else { } else {
logger.error(`dockerTags cannot be empty ...`); logger.error(`dockerTags cannot be empty ...`);
} }
+13 -1
View File
@@ -20,7 +20,19 @@
import { spawnSync } from 'child_process'; import { spawnSync } from 'child_process';
import { logger } from './logger'; import { logger } from './logger';
export function exec(command: string, args?: string[], opts?: { cwd?: string }) { export interface ExecOptions {
cwd?: string;
}
/**
* Exec function
*
* @param command command to execute
* @param args command arguments
* @param opts optional settings
* @returns void function
*/
export function exec(command: string, args?: string[], opts?: ExecOptions) {
if (process.platform.startsWith('win')) { if (process.platform.startsWith('win')) {
args.unshift('/c', command); args.unshift('/c', command);
command = 'cmd.exe'; command = 'cmd.exe';
+128 -7
View File
@@ -48,6 +48,11 @@ export interface ConfigArgs {
export const AAE_MICROSERVICES = ['deployment-service', 'modeling-service', 'dmn-service']; export const AAE_MICROSERVICES = ['deployment-service', 'modeling-service', 'dmn-service'];
/**
* Perform a health check
*
* @param nameService service name
*/
async function healthCheck(nameService: string) { async function healthCheck(nameService: string) {
const url = `${args.host}/${nameService}/actuator/health`; const url = `${args.host}/${nameService}/actuator/health`;
@@ -85,6 +90,11 @@ async function healthCheck(nameService: string) {
} }
} }
/**
* Get deployed application by status
*
* @param status application status
*/
async function getApplicationByStatus(status: string) { async function getApplicationByStatus(status: string) {
const url = `${args.host}/deployment-service/v1/applications`; const url = `${args.host}/deployment-service/v1/applications`;
@@ -120,6 +130,11 @@ async function getApplicationByStatus(status: string) {
} }
} }
/**
* Get descriptors
*
* @returns deployment service descriptors
*/
function getDescriptors() { function getDescriptors() {
const url = `${args.host}/deployment-service/v1/descriptors`; const url = `${args.host}/deployment-service/v1/descriptors`;
@@ -149,6 +164,11 @@ function getDescriptors() {
} }
} }
/**
* Get projects
*
* @returns deployment service projects
*/
function getProjects() { function getProjects() {
const url = `${args.host}/modeling-service/v1/projects`; const url = `${args.host}/modeling-service/v1/projects`;
@@ -178,6 +198,12 @@ function getProjects() {
} }
} }
/**
* Get project release
*
* @param projectId project id
* @returns project release
*/
function getProjectRelease(projectId: string) { function getProjectRelease(projectId: string) {
const url = `${args.host}/modeling-service/v1/projects/${projectId}/releases`; const url = `${args.host}/modeling-service/v1/projects/${projectId}/releases`;
@@ -207,6 +233,11 @@ function getProjectRelease(projectId: string) {
} }
} }
/**
* Release project
*
* @param projectId project id
*/
async function releaseProject(projectId: string) { async function releaseProject(projectId: string) {
const url = `${args.host}/modeling-service/v1/projects/${projectId}/releases`; const url = `${args.host}/modeling-service/v1/projects/${projectId}/releases`;
@@ -237,6 +268,12 @@ async function releaseProject(projectId: string) {
} }
} }
/**
* Delete project
*
* @param projectId project id
* @returns response payload
*/
function deleteProject(projectId: string) { function deleteProject(projectId: string) {
const url = `${args.host}/modeling-service/v1/projects/${projectId}`; const url = `${args.host}/modeling-service/v1/projects/${projectId}`;
@@ -266,6 +303,11 @@ function deleteProject(projectId: string) {
} }
} }
/**
* Import and release project
*
* @param absoluteFilePath path to project file
*/
async function importAndReleaseProject(absoluteFilePath: string) { async function importAndReleaseProject(absoluteFilePath: string) {
const fileContent = fs.createReadStream(absoluteFilePath); const fileContent = fs.createReadStream(absoluteFilePath);
@@ -302,6 +344,12 @@ async function importAndReleaseProject(absoluteFilePath: string) {
} }
} }
/**
* Deletes descriptor
*
* @param name descriptor name
* @returns response payload
*/
function deleteDescriptor(name: string) { function deleteDescriptor(name: string) {
const url = `${args.host}/deployment-service/v1/descriptors/${name}`; const url = `${args.host}/deployment-service/v1/descriptors/${name}`;
@@ -331,6 +379,12 @@ function deleteDescriptor(name: string) {
} }
} }
/**
* Deploys a model
*
* @param model model object
* @returns response payload
*/
function deploy(model: any) { function deploy(model: any) {
const url = `${args.host}/deployment-service/v1/applications`; const url = `${args.host}/deployment-service/v1/applications`;
@@ -360,11 +414,23 @@ function deploy(model: any) {
} }
} }
function initializeDefaultToken(options) { /**
* Initialise default endpoint token
*
* @param options token options
* @returns options
*/
function initializeDefaultToken(options: any): any {
options.tokenEndpoint = options.tokenEndpoint.replace('${clientId}', options.clientId); options.tokenEndpoint = options.tokenEndpoint.replace('${clientId}', options.clientId);
return options; return options;
} }
/**
* Get a new Alfresco Api instance
*
* @param configArgs command params
* @returns a new instance of Alfresco Api client
*/
function getAlfrescoJsApiInstance(configArgs: ConfigArgs): AlfrescoApi { function getAlfrescoJsApiInstance(configArgs: ConfigArgs): AlfrescoApi {
let ssoHost = configArgs.oauth; let ssoHost = configArgs.oauth;
ssoHost = ssoHost ?? configArgs.host; ssoHost = ssoHost ?? configArgs.host;
@@ -388,6 +454,12 @@ function getAlfrescoJsApiInstance(configArgs: ConfigArgs): AlfrescoApi {
return new AlfrescoApi(config); return new AlfrescoApi(config);
} }
/**
* Deploy missing applications
*
* @param tag tag
* @param envs environments
*/
async function deployMissingApps(tag?: string, envs?: string[]) { async function deployMissingApps(tag?: string, envs?: string[]) {
const deployedApps = await getApplicationByStatus(''); const deployedApps = await getApplicationByStatus('');
findMissingApps(deployedApps.list.entries); findMissingApps(deployedApps.list.entries);
@@ -411,6 +483,13 @@ async function deployMissingApps(tag?: string, envs?: string[]) {
} }
} }
/**
* Check if application is released
*
* @param missingApps applications
* @param tag tag
* @param envs environments
*/
async function checkIfAppIsReleased(missingApps: any[], tag?: string, envs?: string[]) { async function checkIfAppIsReleased(missingApps: any[], tag?: string, envs?: string[]) {
const projectList = await getProjects(); const projectList = await getProjects();
let TIME = 5000; let TIME = 5000;
@@ -478,6 +557,13 @@ async function checkIfAppIsReleased(missingApps: any[], tag?: string, envs?: str
} }
} }
/**
* Deploy with a payload
*
* @param currentAbsentApp current application
* @param projectRelease project release
* @param envId environment id
*/
async function deployWithPayload(currentAbsentApp: any, projectRelease: any, envId?: string) { async function deployWithPayload(currentAbsentApp: any, projectRelease: any, envId?: string) {
const deployPayload = { const deployPayload = {
name: currentAbsentApp.name, name: currentAbsentApp.name,
@@ -493,6 +579,11 @@ async function deployWithPayload(currentAbsentApp: any, projectRelease: any, env
logger.info(`Deployed ${currentAbsentApp.name} ${envId ? 'on env: ' + envId : ''}`); logger.info(`Deployed ${currentAbsentApp.name} ${envId ? 'on env: ' + envId : ''}`);
} }
/**
* Check if descriptor exists
*
* @param name descriptor name
*/
async function checkDescriptorExist(name: string): Promise<boolean> { async function checkDescriptorExist(name: string): Promise<boolean> {
logger.info(`Check descriptor ${name} exist in the list `); logger.info(`Check descriptor ${name} exist in the list `);
const descriptorList = await getDescriptors(); const descriptorList = await getDescriptors();
@@ -509,6 +600,12 @@ async function checkDescriptorExist(name: string): Promise<boolean> {
return false; return false;
} }
/**
* Import and release project
*
* @param app application
* @param tag tag
*/
async function importProjectAndRelease(app: any, tag?: string) { async function importProjectAndRelease(app: any, tag?: string) {
const appLocationReplaced = app.file_location(tag); const appLocationReplaced = app.file_location(tag);
logger.warn('App fileLocation ' + appLocationReplaced); logger.warn('App fileLocation ' + appLocationReplaced);
@@ -519,6 +616,11 @@ async function importProjectAndRelease(app: any, tag?: string) {
return projectRelease; return projectRelease;
} }
/**
* Find missing applications
*
* @param deployedApps applications
*/
function findMissingApps(deployedApps: any[]) { function findMissingApps(deployedApps: any[]) {
Object.keys(ACTIVITI_CLOUD_APPS).forEach((key) => { Object.keys(ACTIVITI_CLOUD_APPS).forEach((key) => {
const isPresent = deployedApps.find((currentApp: any) => ACTIVITI_CLOUD_APPS[key].name === currentApp.entry.name); const isPresent = deployedApps.find((currentApp: any) => ACTIVITI_CLOUD_APPS[key].name === currentApp.entry.name);
@@ -529,6 +631,11 @@ function findMissingApps(deployedApps: any[]) {
}); });
} }
/**
* Find failing applications
*
* @param deployedApps applications
*/
function findFailingApps(deployedApps: any[]) { function findFailingApps(deployedApps: any[]) {
Object.keys(ACTIVITI_CLOUD_APPS).forEach((key) => { Object.keys(ACTIVITI_CLOUD_APPS).forEach((key) => {
const failingApp = deployedApps.filter( const failingApp = deployedApps.filter(
@@ -541,6 +648,12 @@ function findFailingApps(deployedApps: any[]) {
}); });
} }
/**
* Get file from the remote
*
* @param url url to file
* @param name name
*/
async function getFileFromRemote(url: string, name: string) { async function getFileFromRemote(url: string, name: string) {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
https.get(url, (response) => { https.get(url, (response) => {
@@ -568,11 +681,21 @@ async function getFileFromRemote(url: string, name: string) {
}); });
} }
/**
* Deletes local file
*
* @param name file name
*/
async function deleteLocalFile(name: string) { async function deleteLocalFile(name: string) {
logger.info(`Deleting local file ${name}.zip`); logger.info(`Deleting local file ${name}.zip`);
fs.unlinkSync(`${name}.zip`); fs.unlinkSync(`${name}.zip`);
} }
/**
* Perform a timeout
*
* @param time delay in milliseconds
*/
async function sleep(time: number) { async function sleep(time: number) {
logger.info(`Waiting for ${time} sec...`); logger.info(`Waiting for ${time} sec...`);
await new Promise((done) => setTimeout(done, time)); await new Promise((done) => setTimeout(done, time));
@@ -580,12 +703,10 @@ async function sleep(time: number) {
return; return;
} }
// eslint-disable-next-line space-before-function-paren /**
export default async function () { * Init AAE environment command
await main(); */
} export default async function main() {
async function main() {
program program
.version('0.1.0') .version('0.1.0')
.description( .description(
+42 -7
View File
@@ -28,12 +28,10 @@ const ACS_DEFAULT = require('./resources').ACS_DEFAULT;
let alfrescoJsApi: AlfrescoApi; let alfrescoJsApi: AlfrescoApi;
// eslint-disable-next-line space-before-function-paren /**
export default async function () { * Init ACS environment command
await main(); */
} export default async function main() {
async function main() {
program program
.version('0.1.0') .version('0.1.0')
.option('--host [type]', 'Remote environment host') .option('--host [type]', 'Remote environment host')
@@ -48,6 +46,9 @@ async function main() {
await initializeDefaultFiles(); await initializeDefaultFiles();
} }
/**
* Setup default files
*/
async function initializeDefaultFiles() { async function initializeDefaultFiles() {
const e2eFolder = ACS_DEFAULT.e2eFolder; const e2eFolder = ACS_DEFAULT.e2eFolder;
const parentFolder = await createFolder(e2eFolder.name, '-my-'); const parentFolder = await createFolder(e2eFolder.name, '-my-');
@@ -83,6 +84,12 @@ async function initializeDefaultFiles() {
} }
} }
/**
* Create folder
*
* @param folderName folder name
* @param parentId parent folder id
*/
async function createFolder(folderName: string, parentId: string) { async function createFolder(folderName: string, parentId: string) {
let createdFolder: NodeEntry; let createdFolder: NodeEntry;
const body = { const body = {
@@ -102,6 +109,12 @@ async function createFolder(folderName: string, parentId: string) {
return createdFolder; return createdFolder;
} }
/**
* Upload file
*
* @param fileName file name
* @param fileDestination destination path
*/
async function uploadFile(fileName: string, fileDestination: string): Promise<NodeEntry> { async function uploadFile(fileName: string, fileDestination: string): Promise<NodeEntry> {
const filePath = `../resources/content/${fileName}`; const filePath = `../resources/content/${fileName}`;
const file = fs.createReadStream(path.join(__dirname, filePath)); const file = fs.createReadStream(path.join(__dirname, filePath));
@@ -120,6 +133,11 @@ async function uploadFile(fileName: string, fileDestination: string): Promise<No
return uploadedFile; return uploadedFile;
} }
/**
* Lock file node
*
* @param nodeId node id
*/
async function lockFile(nodeId: string): Promise<NodeEntry> { async function lockFile(nodeId: string): Promise<NodeEntry> {
const data = { const data = {
type: 'ALLOW_OWNER_CHANGES' type: 'ALLOW_OWNER_CHANGES'
@@ -133,6 +151,11 @@ async function lockFile(nodeId: string): Promise<NodeEntry> {
} }
} }
/**
* Share file node
*
* @param nodeId node id
*/
async function shareFile(nodeId: string) { async function shareFile(nodeId: string) {
const data = { const data = {
nodeId nodeId
@@ -145,6 +168,11 @@ async function shareFile(nodeId: string) {
} }
} }
/**
* Favorite file node
*
* @param nodeId node id
*/
async function favoriteFile(nodeId: string) { async function favoriteFile(nodeId: string) {
const data = { const data = {
target: { target: {
@@ -161,6 +189,9 @@ async function favoriteFile(nodeId: string) {
} }
} }
/**
* Check environment state
*/
async function checkEnv() { async function checkEnv() {
try { try {
alfrescoJsApi = new AlfrescoApi({ alfrescoJsApi = new AlfrescoApi({
@@ -195,8 +226,12 @@ async function checkEnv() {
} }
} }
/* eslint-enable */
/**
* Perform a delay
*
* @param delay timeout in milliseconds
*/
function sleep(delay: number) { function sleep(delay: number) {
const start = new Date().getTime(); const start = new Date().getTime();
while (new Date().getTime() < start + delay) {} while (new Date().getTime() < start + delay) {}
+91 -9
View File
@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { AdminTenantsApi, AdminUsersApi, AlfrescoApi, TenantRepresentation, AppDefinitionsApi, RuntimeAppDefinitionsApi, UserRepresentation } from '@alfresco/js-api'; import { AdminTenantsApi, AdminUsersApi, AlfrescoApi, TenantRepresentation, AppDefinitionsApi, RuntimeAppDefinitionsApi, UserRepresentation, AppDefinitionUpdateResultRepresentation } from '@alfresco/js-api';
import { argv, exit } from 'node:process'; import { argv, exit } from 'node:process';
import { spawnSync } from 'node:child_process'; import { spawnSync } from 'node:child_process';
import { createReadStream } from 'node:fs'; import { createReadStream } from 'node:fs';
@@ -33,11 +33,10 @@ const ACTIVITI_APPS = require('./resources').ACTIVITI_APPS;
let alfrescoJsApi: AlfrescoApi; let alfrescoJsApi: AlfrescoApi;
export default async function() { /**
await main(); * Init APS command
} */
export default async function main() {
async function main() {
program program
.version('0.1.0') .version('0.1.0')
@@ -114,6 +113,9 @@ async function main() {
} }
/**
* Initialise default applications
*/
async function initializeDefaultApps() { async function initializeDefaultApps() {
for (let x = 0; x < ACTIVITI_APPS.apps.length; x++) { for (let x = 0; x < ACTIVITI_APPS.apps.length; x++) {
const appInfo = ACTIVITI_APPS.apps[x]; const appInfo = ACTIVITI_APPS.apps[x];
@@ -126,6 +128,10 @@ async function initializeDefaultApps() {
} }
} }
} }
/**
* Check environment
*/
async function checkEnv() { async function checkEnv() {
try { try {
alfrescoJsApi = new AlfrescoApi({ alfrescoJsApi = new AlfrescoApi({
@@ -160,7 +166,14 @@ async function checkEnv() {
} }
} }
async function hasDefaultTenant(tenantId: number, tenantName: string) { /**
* Check if the default tenant is present
*
* @param tenantId tenant id
* @param tenantName tenant name
* @returns `true` if tenant is found, otherwise `false`
*/
async function hasDefaultTenant(tenantId: number, tenantName: string): Promise<boolean> {
let tenant: TenantRepresentation; let tenant: TenantRepresentation;
try { try {
@@ -180,6 +193,11 @@ async function hasDefaultTenant(tenantId: number, tenantName: string) {
} }
} }
/**
* Create default tenant
*
* @param tenantName tenant name
*/
async function createDefaultTenant(tenantName: string) { async function createDefaultTenant(tenantName: string) {
const tenantPost = { const tenantPost = {
active: true, active: true,
@@ -197,6 +215,12 @@ async function createDefaultTenant(tenantName: string) {
} }
} }
/**
* Create users
*
* @param tenantId tenant id
* @param user user object
*/
async function createUsers(tenantId: number, user: any) { async function createUsers(tenantId: number, user: any) {
logger.info(`Create user ${user.email} on tenant: ${tenantId}`); logger.info(`Create user ${user.email} on tenant: ${tenantId}`);
const passwordCamelCase = 'Password'; const passwordCamelCase = 'Password';
@@ -220,6 +244,9 @@ async function createUsers(tenantId: number, user: any) {
} }
} }
/**
* Update Activiti license
*/
async function updateLicense() { async function updateLicense() {
const fileContent = createReadStream(path.join(__dirname, '/activiti.lic')); const fileContent = createReadStream(path.join(__dirname, '/activiti.lic'));
@@ -243,7 +270,13 @@ async function updateLicense() {
} }
} }
async function isDefaultAppDeployed(appName: string) { /**
* Check if default application is deployed
*
* @param appName application name
* @returns `true` if application is deployed, otherwise `false`
*/
async function isDefaultAppDeployed(appName: string): Promise<boolean> {
logger.info(`Verify ${appName} already deployed`); logger.info(`Verify ${appName} already deployed`);
try { try {
const runtimeAppDefinitionsApi = new RuntimeAppDefinitionsApi(alfrescoJsApi); const runtimeAppDefinitionsApi = new RuntimeAppDefinitionsApi(alfrescoJsApi);
@@ -255,7 +288,12 @@ async function isDefaultAppDeployed(appName: string) {
} }
} }
async function importPublishApp(appName: string) { /**
* Import and publish the application
*
* @param appName application name
*/
async function importPublishApp(appName: string): Promise<AppDefinitionUpdateResultRepresentation> {
const appNameExtension = `../resources/${appName}.zip`; const appNameExtension = `../resources/${appName}.zip`;
logger.info(`Import app ${appNameExtension}`); logger.info(`Import app ${appNameExtension}`);
const pathFile = path.join(__dirname, appNameExtension); const pathFile = path.join(__dirname, appNameExtension);
@@ -271,6 +309,11 @@ async function importPublishApp(appName: string) {
} }
} }
/**
* Deploy application
*
* @param appDefinitionId app definition id
*/
async function deployApp(appDefinitionId: number) { async function deployApp(appDefinitionId: number) {
logger.info(`Deploy app with id ${appDefinitionId}`); logger.info(`Deploy app with id ${appDefinitionId}`);
const body = { const body = {
@@ -286,6 +329,9 @@ async function deployApp(appDefinitionId: number) {
} }
} }
/**
* Checks if Activiti app has license
*/
async function hasLicense(): Promise<boolean> { async function hasLicense(): Promise<boolean> {
try { try {
const license = await alfrescoJsApi.oauth2Auth.callCustomApi( const license = await alfrescoJsApi.oauth2Auth.callCustomApi(
@@ -310,6 +356,9 @@ async function hasLicense(): Promise<boolean> {
} }
} }
/**
* Get default users from the realm
*/
async function getDefaultApsUsersFromRealm() { async function getDefaultApsUsersFromRealm() {
try { try {
const users: any[] = await alfrescoJsApi.oauth2Auth.callCustomApi( const users: any[] = await alfrescoJsApi.oauth2Auth.callCustomApi(
@@ -332,6 +381,12 @@ async function getDefaultApsUsersFromRealm() {
} }
} }
/**
* Validate that ACS repo for Activiti is present
*
* @param tenantId tenant id
* @param contentName content service name
*/
async function isContentRepoPresent(tenantId: number, contentName: string): Promise<boolean> { async function isContentRepoPresent(tenantId: number, contentName: string): Promise<boolean> {
try { try {
const contentRepos = await alfrescoJsApi.oauth2Auth.callCustomApi( const contentRepos = await alfrescoJsApi.oauth2Auth.callCustomApi(
@@ -351,6 +406,12 @@ async function isContentRepoPresent(tenantId: number, contentName: string): Prom
} }
} }
/**
* Add content service with basic auth
*
* @param tenantId tenant id
* @param name content name
*/
async function addContentRepoWithBasic(tenantId: number, name: string) { async function addContentRepoWithBasic(tenantId: number, name: string) {
logger.info(`Create Content with name ${name} and basic auth`); logger.info(`Create Content with name ${name} and basic auth`);
@@ -384,6 +445,11 @@ async function addContentRepoWithBasic(tenantId: number, name: string) {
} }
} }
/**
* Authorize activiti user to ACS repo
*
* @param user user object
*/
async function authorizeUserToContentRepo(user: any) { async function authorizeUserToContentRepo(user: any) {
logger.info(`Authorize user ${user.email}`); logger.info(`Authorize user ${user.email}`);
try { try {
@@ -412,6 +478,12 @@ async function authorizeUserToContentRepo(user: any) {
} }
} }
/**
* Authorize user with content using basic auth
*
* @param username username
* @param contentId content id
*/
async function authorizeUserToContentWithBasic(username: string, contentId: string) { async function authorizeUserToContentWithBasic(username: string, contentId: string) {
logger.info(`Authorize ${username} on contentId: ${contentId} in basic auth`); logger.info(`Authorize ${username} on contentId: ${contentId} in basic auth`);
try { try {
@@ -434,6 +506,11 @@ async function authorizeUserToContentWithBasic(username: string, contentId: stri
} }
} }
/**
* Download APS license file
*
* @param apsLicensePath path to license file
*/
async function downloadLicenseFile(apsLicensePath: string) { async function downloadLicenseFile(apsLicensePath: string) {
const args = [ const args = [
`s3`, `s3`,
@@ -454,6 +531,11 @@ async function downloadLicenseFile(apsLicensePath: string) {
return true; return true;
} }
/**
* Perform a delay
*
* @param delay timeout in milliseconds
*/
function sleep(delay: number) { function sleep(delay: number) {
const start = new Date().getTime(); const start = new Date().getTime();
while (new Date().getTime() < start + delay) { } while (new Date().getTime() < start + delay) { }
+50 -5
View File
@@ -41,6 +41,12 @@ export interface ConfigArgs {
intervalTime: string; intervalTime: string;
} }
/**
* Get Alfresco Api instance
*
* @param args command parameters
* @returns Alfresco Api instance
*/
function getAlfrescoJsApiInstance(args: ConfigArgs): AlfrescoApi { function getAlfrescoJsApiInstance(args: ConfigArgs): AlfrescoApi {
const config: AlfrescoApiConfig = { const config: AlfrescoApiConfig = {
provider: 'BPM', provider: 'BPM',
@@ -60,6 +66,13 @@ function getAlfrescoJsApiInstance(args: ConfigArgs): AlfrescoApi {
return new AlfrescoApi(config); return new AlfrescoApi(config);
} }
/**
* Perform login
*
* @param username username
* @param password password
* @param alfrescoJsApi api client
*/
async function login(username: string, password: string, alfrescoJsApi: AlfrescoApi) { async function login(username: string, password: string, alfrescoJsApi: AlfrescoApi) {
logger.info(`Perform login...`); logger.info(`Perform login...`);
try { try {
@@ -71,6 +84,13 @@ async function login(username: string, password: string, alfrescoJsApi: Alfresco
logger.info(`Perform done...`); logger.info(`Perform done...`);
} }
/**
* Deletes deployment descriptor
*
* @param args command arguments
* @param apiService api client
* @param name descriptor name
*/
async function deleteDescriptor(args: ConfigArgs, apiService: AlfrescoApi, name: string) { async function deleteDescriptor(args: ConfigArgs, apiService: AlfrescoApi, name: string) {
logger.warn(`Delete the descriptor ${name}`); logger.warn(`Delete the descriptor ${name}`);
@@ -104,6 +124,13 @@ async function deleteDescriptor(args: ConfigArgs, apiService: AlfrescoApi, name:
} }
} }
/**
* Deletes modeling project
*
* @param args arguments
* @param apiService api client
* @param projectId project id
*/
async function deleteProject(args: ConfigArgs, apiService: AlfrescoApi, projectId: string) { async function deleteProject(args: ConfigArgs, apiService: AlfrescoApi, projectId: string) {
logger.warn(`Delete the project ${projectId}`); logger.warn(`Delete the project ${projectId}`);
@@ -137,6 +164,13 @@ async function deleteProject(args: ConfigArgs, apiService: AlfrescoApi, projectI
} }
} }
/**
* Deletes modeling project by name
*
* @param args arguments
* @param apiService api client
* @param name project name
*/
async function deleteProjectByName(args: ConfigArgs, apiService: AlfrescoApi, name: string) { async function deleteProjectByName(args: ConfigArgs, apiService: AlfrescoApi, name: string) {
logger.warn(`Get the project by name ${name}`); logger.warn(`Get the project by name ${name}`);
const url = `${args.host}/modeling-service/v1/projects?name=${name}`; const url = `${args.host}/modeling-service/v1/projects?name=${name}`;
@@ -172,6 +206,13 @@ async function deleteProjectByName(args: ConfigArgs, apiService: AlfrescoApi, na
} }
} }
/**
* Get applications by name
*
* @param args command arguments
* @param apiService api client
* @param name application name
*/
async function getApplicationsByName(args: ConfigArgs, apiService: AlfrescoApi, name: string) { async function getApplicationsByName(args: ConfigArgs, apiService: AlfrescoApi, name: string) {
logger.warn(`Get the applications by name ${name}`); logger.warn(`Get the applications by name ${name}`);
const url = `${args.host}/deployment-service/v1/applications?name=${name}`; const url = `${args.host}/deployment-service/v1/applications?name=${name}`;
@@ -203,6 +244,13 @@ async function getApplicationsByName(args: ConfigArgs, apiService: AlfrescoApi,
} }
} }
/**
* Undeploy applications by name
*
* @param args command arguments
* @param apiService api client
* @param name application name
*/
async function undeployApplication(args: ConfigArgs, apiService: AlfrescoApi, name: string) { async function undeployApplication(args: ConfigArgs, apiService: AlfrescoApi, name: string) {
logger.warn(`Undeploy the application ${name}`); logger.warn(`Undeploy the application ${name}`);
@@ -236,11 +284,6 @@ async function undeployApplication(args: ConfigArgs, apiService: AlfrescoApi, na
} }
} }
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions,space-before-function-paren
export default async function (args: ConfigArgs) {
await main(args);
}
const main = async (args: ConfigArgs) => { const main = async (args: ConfigArgs) => {
program program
.version('0.1.0') .version('0.1.0')
@@ -330,3 +373,5 @@ const main = async (args: ConfigArgs) => {
} }
} }
}; };
export default main;
+19
View File
@@ -49,6 +49,12 @@ const missingRepositories = {
'rxjs-compat': 'https://github.com/ReactiveX/rxjs/tree/master/compat' 'rxjs-compat': 'https://github.com/ReactiveX/rxjs/tree/master/compat'
}; };
/**
* Get a license with MD link
*
* @param licenseExp license expression
* @returns license
*/
function licenseWithMDLinks(licenseExp: string): string { function licenseWithMDLinks(licenseExp: string): string {
let licenseUrl = ''; let licenseUrl = '';
@@ -69,6 +75,12 @@ function licenseWithMDLinks(licenseExp: string): string {
} }
} }
/**
* Get package file
*
* @param packagePath package.json path
* @returns package model
*/
function getPackageFile(packagePath: string): PackageInfo { function getPackageFile(packagePath: string): PackageInfo {
try { try {
return JSON.parse(fs.readFileSync(packagePath).toString()); return JSON.parse(fs.readFileSync(packagePath).toString());
@@ -78,6 +90,13 @@ function getPackageFile(packagePath: string): PackageInfo {
} }
} }
/**
* Licenses command
*
* @param _args (not used)
* @param workingDir working directory
* @returns void function
*/
export default function main(_args: string[], workingDir: string) { export default function main(_args: string[], workingDir: string) {
program program
.description('Generate a licences report') .description('Generate a licences report')
+36 -1
View File
@@ -34,6 +34,12 @@ export interface PublishArgs {
const projects = ['cli', 'core', 'insights', 'testing', 'content-services', 'process-services', 'process-services-cloud', 'extensions']; const projects = ['cli', 'core', 'insights', 'testing', 'content-services', 'process-services', 'process-services-cloud', 'extensions'];
/**
* Publish to NPM command
*
* @param args command arguments
* @param project project name
*/
async function npmPublish(args: PublishArgs, project: string) { async function npmPublish(args: PublishArgs, project: string) {
if (args.dryrun) { if (args.dryrun) {
logger.info(`Dry run mode, no publish will be done`); logger.info(`Dry run mode, no publish will be done`);
@@ -70,7 +76,14 @@ async function npmPublish(args: PublishArgs, project: string) {
} }
} }
function npmCheckExist(project: string, version: string) { /**
* Checks the library exists on npm already
*
* @param project project name
* @param version project version
* @returns `true` if given project exists on NPM, otherwise `false`
*/
function npmCheckExist(project: string, version: string): boolean {
logger.info(`Check if lib ${project} is already in npm with version ${version}`); logger.info(`Check if lib ${project} is already in npm with version ${version}`);
let exist = ''; let exist = '';
try { try {
@@ -82,6 +95,12 @@ function npmCheckExist(project: string, version: string) {
return exist !== ''; return exist !== '';
} }
/**
* Change NPM registry
*
* @param args command parameters
* @param project project name
*/
function changeRegistry(args: PublishArgs, project: string) { function changeRegistry(args: PublishArgs, project: string) {
logger.info(`Change registry... to ${args.npmRegistry} `); logger.info(`Change registry... to ${args.npmRegistry} `);
const folder = `${args.pathProject}/dist/libs/${project}`; const folder = `${args.pathProject}/dist/libs/${project}`;
@@ -98,6 +117,12 @@ always-auth=true
} }
} }
/**
* Removes custom `.npmrc` configuration file
*
* @param args command arguments
* @param project project name
*/
function removeNpmConfig(args: PublishArgs, project: string) { function removeNpmConfig(args: PublishArgs, project: string) {
logger.info(`Removing file from ${project}`); logger.info(`Removing file from ${project}`);
try { try {
@@ -108,6 +133,11 @@ function removeNpmConfig(args: PublishArgs, project: string) {
} }
} }
/**
* Publish to NPM command
*
* @param args command arguments
*/
export default async function main(args: PublishArgs) { export default async function main(args: PublishArgs) {
program program
.version('0.1.0') .version('0.1.0')
@@ -132,6 +162,11 @@ export default async function main(args: PublishArgs) {
} }
} }
/**
* Perform a timeout
*
* @param ms timeout in milliseconds
*/
async function sleep(ms: number) { async function sleep(ms: number) {
logger.info(`Waiting for ${ms} milliseconds...`); logger.info(`Waiting for ${ms} milliseconds...`);
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
+54 -2
View File
@@ -45,7 +45,10 @@ const green = '\x1b[32m';
let alfrescoApi: AlfrescoApi; let alfrescoApi: AlfrescoApi;
let loginAttempts: number = 0; let loginAttempts: number = 0;
export default async function main(_args: string[]) { /**
* Scan environment command
*/
export default async function main() {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log = () => {}; console.log = () => {};
@@ -72,6 +75,12 @@ export default async function main(_args: string[]) {
logger.info(generateTable(rowsToPrint)); logger.info(generateTable(rowsToPrint));
} }
/**
* Generate table
*
* @param rowsToPrint list of table rows to print
* @returns table as a string
*/
function generateTable(rowsToPrint: Array<RowToPrint>) { function generateTable(rowsToPrint: Array<RowToPrint>) {
const columnWidths = rowsToPrint.reduce( const columnWidths = rowsToPrint.reduce(
(maxWidths, row: RowToPrint) => ({ (maxWidths, row: RowToPrint) => ({
@@ -99,6 +108,9 @@ ${grey}╞${horizontalLine}╡${reset}`;
return tableString; return tableString;
} }
/**
* Attempt to login
*/
async function attemptLogin() { async function attemptLogin() {
logger.info(` Logging into ${yellow}${program.host}${reset} with user ${yellow}${program.username}${reset}`); logger.info(` Logging into ${yellow}${program.host}${reset} with user ${yellow}${program.username}${reset}`);
try { try {
@@ -123,6 +135,11 @@ async function attemptLogin() {
} }
} }
/**
* Handles login error
*
* @param loginError error object
*/
async function handleLoginError(loginError) { async function handleLoginError(loginError) {
if (loginAttempts === 0) { if (loginAttempts === 0) {
logger.error(` ${red}Login SSO error${reset}`); logger.error(` ${red}Login SSO error${reset}`);
@@ -150,6 +167,11 @@ async function handleLoginError(loginError) {
} }
} }
/**
* Check environment is reachable
*
* @param loginError error object
*/
function checkEnvReachable(loginError) { function checkEnvReachable(loginError) {
const failingErrorCodes = ['ENOTFOUND', 'ETIMEDOUT', 'ECONNREFUSED']; const failingErrorCodes = ['ENOTFOUND', 'ETIMEDOUT', 'ECONNREFUSED'];
if (typeof loginError === 'object' && failingErrorCodes.indexOf(loginError.code) > -1) { if (typeof loginError === 'object' && failingErrorCodes.indexOf(loginError.code) > -1) {
@@ -158,6 +180,11 @@ function checkEnvReachable(loginError) {
} }
} }
/**
* Get people count
*
* @param skipCount skip count
*/
async function getPeopleCount(skipCount: number = 0): Promise<PeopleTally> { async function getPeopleCount(skipCount: number = 0): Promise<PeopleTally> {
if (skipCount === 0) { if (skipCount === 0) {
logger.info(` Fetching number of users`); logger.info(` Fetching number of users`);
@@ -191,6 +218,9 @@ async function getPeopleCount(skipCount: number = 0): Promise<PeopleTally> {
} }
} }
/**
* Count the amount of Home folders
*/
async function getHomeFoldersCount(): Promise<number> { async function getHomeFoldersCount(): Promise<number> {
logger.info(` Fetching number of home folders`); logger.info(` Fetching number of home folders`);
try { try {
@@ -205,6 +235,9 @@ async function getHomeFoldersCount(): Promise<number> {
} }
} }
/**
* Count the amount of groups
*/
async function getGroupsCount(): Promise<number> { async function getGroupsCount(): Promise<number> {
logger.info(` Fetching number of groups`); logger.info(` Fetching number of groups`);
try { try {
@@ -216,6 +249,9 @@ async function getGroupsCount(): Promise<number> {
} }
} }
/**
* Count the amount of sites
*/
async function getSitesCount(): Promise<number> { async function getSitesCount(): Promise<number> {
logger.info(` Fetching number of sites`); logger.info(` Fetching number of sites`);
try { try {
@@ -227,6 +263,9 @@ async function getSitesCount(): Promise<number> {
} }
} }
/**
* Count the amount of files
*/
async function getFilesCount(): Promise<number> { async function getFilesCount(): Promise<number> {
logger.info(` Fetching number of files`); logger.info(` Fetching number of files`);
try { try {
@@ -246,9 +285,14 @@ async function getFilesCount(): Promise<number> {
} }
} }
/**
* Handle error
*
* @param error error object
*/
function handleError(error) { function handleError(error) {
logger.error(` ${red}Error encountered${reset}`); logger.error(` ${red}Error encountered${reset}`);
if (error && error.response && error?.response?.text) { if (error?.response && error?.response?.text) {
try { try {
const parsedJson = JSON.parse(error?.response?.text); const parsedJson = JSON.parse(error?.response?.text);
if (typeof parsedJson === 'object' && parsedJson.error) { if (typeof parsedJson === 'object' && parsedJson.error) {
@@ -262,11 +306,19 @@ function handleError(error) {
failScript(); failScript();
} }
/**
* Log the error and exit
*/
function failScript() { function failScript() {
logger.error(`${red}${bright}Environment scan failed. Exiting${reset}`); logger.error(`${red}${bright}Environment scan failed. Exiting${reset}`);
exit(0); exit(0);
} }
/**
* Wait with a certain period
*
* @param ms timeout in milliseconds
*/
async function wait(ms: number) { async function wait(ms: number) {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(resolve, ms); setTimeout(resolve, ms);
+19 -2
View File
@@ -28,6 +28,12 @@ export interface CommitArgs {
skipGnu: boolean; skipGnu: boolean;
} }
/**
* Get commit SHA
*
* @param args command arguments
* @returns commit SHA value
*/
function getSha(args: CommitArgs): string { function getSha(args: CommitArgs): string {
logger.info('Check commit sha...'); logger.info('Check commit sha...');
@@ -36,7 +42,13 @@ function getSha(args: CommitArgs): string {
return exec('git', [`rev-parse`, `${gitPointer}`], {}).trim(); return exec('git', [`rev-parse`, `${gitPointer}`], {}).trim();
} }
function replacePerform(args: CommitArgs, sha: string) { /**
* Performs the sha replacement
*
* @param args command parameters
* @param sha value to use
*/
function performReplace(args: CommitArgs, sha: string) {
logger.info(`Replace commit ${sha} in package...`); logger.info(`Replace commit ${sha} in package...`);
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
@@ -49,6 +61,11 @@ function replacePerform(args: CommitArgs, sha: string) {
} }
} }
/**
* Update commit SHA command
*
* @param args command arguments
*/
export default function main(args: CommitArgs) { export default function main(args: CommitArgs) {
program program
.version('0.1.0') .version('0.1.0')
@@ -70,5 +87,5 @@ export default function main(args: CommitArgs) {
const sha = getSha(args); const sha = getSha(args);
replacePerform(args, sha); performReplace(args, sha);
} }
+38
View File
@@ -37,6 +37,12 @@ export interface PackageInfo {
devDependencies?: string[]; devDependencies?: string[];
} }
/**
* Parse alfresco libraries in package.json file
*
* @param workingDir working directory
* @returns package info model
*/
function parseAlfrescoLibs(workingDir: string): PackageInfo { function parseAlfrescoLibs(workingDir: string): PackageInfo {
const packagePath = path.resolve(path.join(workingDir, 'package.json')); const packagePath = path.resolve(path.join(workingDir, 'package.json'));
@@ -57,10 +63,23 @@ function parseAlfrescoLibs(workingDir: string): PackageInfo {
}; };
} }
/**
* Format npm command
*
* @param deps dependencies
* @param tag tag
* @returns npm command to execute
*/
function formatNpmCommand(deps: string[], tag: string): string { function formatNpmCommand(deps: string[], tag: string): string {
return ['npm i -E', deps.map((name) => `${name}@${tag}`).join(' ')].join(' '); return ['npm i -E', deps.map((name) => `${name}@${tag}`).join(' ')].join(' ');
} }
/**
* Run npm command
*
* @param command command to execute
* @param workingDir working directory
*/
function runNpmCommand(command: string, workingDir: string) { function runNpmCommand(command: string, workingDir: string) {
if (shell.exec(command, { cwd: workingDir }).code !== 0) { if (shell.exec(command, { cwd: workingDir }).code !== 0) {
shell.echo('Error running NPM command'); shell.echo('Error running NPM command');
@@ -68,6 +87,13 @@ function runNpmCommand(command: string, workingDir: string) {
} }
} }
/**
* Update libraries
*
* @param pkg package info model
* @param tag tag name
* @param workingDir working directory
*/
function updateLibs(pkg: PackageInfo, tag: string, workingDir: string) { function updateLibs(pkg: PackageInfo, tag: string, workingDir: string) {
if (pkg.dependencies && pkg.dependencies.length > 0) { if (pkg.dependencies && pkg.dependencies.length > 0) {
runNpmCommand(formatNpmCommand(pkg.dependencies, tag), workingDir); runNpmCommand(formatNpmCommand(pkg.dependencies, tag), workingDir);
@@ -78,6 +104,12 @@ function updateLibs(pkg: PackageInfo, tag: string, workingDir: string) {
} }
} }
/**
* Parse tag
*
* @param args update arguments
* @returns tag value
*/
function parseTag(args: UpdateArgs): string { function parseTag(args: UpdateArgs): string {
if (args.alpha) { if (args.alpha) {
return 'alpha'; return 'alpha';
@@ -90,6 +122,12 @@ function parseTag(args: UpdateArgs): string {
return args.version || 'latest'; return args.version || 'latest';
} }
/**
* update version command
*
* @param args arguments
* @param workingDir working directory
*/
export default function main(args: UpdateArgs, workingDir: string) { export default function main(args: UpdateArgs, workingDir: string) {
program program
.description( .description(
@@ -68,7 +68,7 @@ export class AuditService {
* @param auditApplicationId The identifier of an audit application. * @param auditApplicationId The identifier of an audit application.
* @param auditAppBodyUpdate The audit application to update. * @param auditAppBodyUpdate The audit application to update.
* @param opts Options. * @param opts Options.
* @returns * @returns audit application model
*/ */
updateAuditApp(auditApplicationId: string, auditAppBodyUpdate: boolean, opts?: any): Observable<AuditApp | any> { updateAuditApp(auditApplicationId: string, auditAppBodyUpdate: boolean, opts?: any): Observable<AuditApp | any> {
const defaultOptions = {}; const defaultOptions = {};
@@ -117,7 +117,7 @@ export class AuditService {
* *
* @param nodeId The identifier of a node. * @param nodeId The identifier of a node.
* @param opts Options. * @param opts Options.
* @returns * @returns audit entry list
*/ */
getAuditEntriesForNode(nodeId: string, opts?: any): Observable<AuditEntryPaging> { getAuditEntriesForNode(nodeId: string, opts?: any): Observable<AuditEntryPaging> {
const defaultOptions = { const defaultOptions = {
@@ -132,7 +132,7 @@ export class AuditService {
* *
* @param auditApplicationId The identifier of an audit application. * @param auditApplicationId The identifier of an audit application.
* @param where Audit entries to permanently delete for an audit application, given an inclusive time period or range of ids. * @param where Audit entries to permanently delete for an audit application, given an inclusive time period or range of ids.
* @returns * @returns void operation
*/ */
deleteAuditEntries(auditApplicationId: string, where: string): Observable<any> { deleteAuditEntries(auditApplicationId: string, where: string): Observable<any> {
return from(this.auditApi.deleteAuditEntriesForAuditApp(auditApplicationId, where)).pipe(catchError((err: any) => this.handleError(err))); return from(this.auditApi.deleteAuditEntriesForAuditApp(auditApplicationId, where)).pipe(catchError((err: any) => this.handleError(err)));
@@ -143,7 +143,7 @@ export class AuditService {
* *
* @param auditApplicationId The identifier of an audit application. * @param auditApplicationId The identifier of an audit application.
* @param auditEntryId The identifier of an audit entry. * @param auditEntryId The identifier of an audit entry.
* @returns * @returns void operation
*/ */
deleteAuditEntry(auditApplicationId: string, auditEntryId: string): Observable<any> { deleteAuditEntry(auditApplicationId: string, auditEntryId: string): Observable<any> {
return from(this.auditApi.deleteAuditEntry(auditApplicationId, auditEntryId)).pipe(catchError((err: any) => this.handleError(err))); return from(this.auditApi.deleteAuditEntry(auditApplicationId, auditEntryId)).pipe(catchError((err: any) => this.handleError(err)));
@@ -34,26 +34,30 @@ export class BreadcrumbComponent implements OnInit, OnChanges, OnDestroy {
@Input() @Input()
folderNode: Node = null; folderNode: Node = null;
/** (optional) Name of the root element of the breadcrumb. You can use /**
* Name of the root element of the breadcrumb. You can use
* this property to rename "Company Home" to "Personal Files" for * this property to rename "Company Home" to "Personal Files" for
* example. You can use an i18n resource key for the property value. * example. You can use an i18n resource key for the property value.
*/ */
@Input() @Input()
root: string = null; root?: string = null;
/** (optional) The id of the root element. You can use this property /**
* The id of the root element. You can use this property
* to set a custom element the breadcrumb should start with. * to set a custom element the breadcrumb should start with.
*/ */
@Input() @Input()
rootId: string = null; rootId?: string = null;
/** (optional) Document List component to operate with. The list will /**
* Document List component to operate with. The list will
* update when the breadcrumb is clicked. * update when the breadcrumb is clicked.
*/ */
@Input() @Input()
target: DocumentListComponent; target?: DocumentListComponent;
/** Transformation to be performed on the chosen/folder node before building /**
* Transformation to be performed on the chosen/folder node before building
* the breadcrumb UI. Can be useful when custom formatting is needed for the * the breadcrumb UI. Can be useful when custom formatting is needed for the
* breadcrumb. You can change the path elements from the node that are used to * breadcrumb. You can change the path elements from the node that are used to
* build the breadcrumb using this function. * build the breadcrumb using this function.
@@ -56,7 +56,9 @@ export class DropdownBreadcrumbComponent extends BreadcrumbComponent implements
} }
/** /**
* Return if route has more than one element (means: we are not in the root directory) * Check if route has more than one element (means: we are not in the root directory)
*
* @returns `true` if there are previous nodes, otherwise `false`
*/ */
hasPreviousNodes(): boolean { hasPreviousNodes(): boolean {
return this.previousNodes.length > 0; return this.previousNodes.length > 0;
@@ -67,18 +67,40 @@ describe('CategoriesManagementComponent', () => {
categoryService = TestBed.inject(CategoryService); categoryService = TestBed.inject(CategoryService);
}); });
/**
* Get no categories message
*
* @returns message text
*/
function getNoCategoriesMessage(): string { function getNoCategoriesMessage(): string {
return fixture.debugElement.query(By.css(`.adf-no-categories-message`))?.nativeElement.textContent.trim(); return fixture.debugElement.query(By.css(`.adf-no-categories-message`))?.nativeElement.textContent.trim();
} }
/**
* Get assigned categories list
*
* @returns list of native elements
*/
function getAssignedCategoriesList(): HTMLSpanElement[] { function getAssignedCategoriesList(): HTMLSpanElement[] {
return fixture.debugElement.queryAll(By.css('.adf-assigned-categories'))?.map((debugElem) => debugElem.nativeElement); return fixture.debugElement.queryAll(By.css('.adf-assigned-categories'))?.map((debugElem) => debugElem.nativeElement);
} }
/**
* Get the exiting categories list
*
* @returns list of material option element
*/
function getExistingCategoriesList(): MatListOption[] { function getExistingCategoriesList(): MatListOption[] {
return fixture.debugElement.queryAll(By.directive(MatListOption))?.map((debugElem) => debugElem.componentInstance); return fixture.debugElement.queryAll(By.directive(MatListOption))?.map((debugElem) => debugElem.componentInstance);
} }
/**
* Create new category
*
* @param name name of the category
* @param addUsingEnter use Enter key
* @param typingTimeout typing timeout in milliseconds (default 300)
*/
function createCategory(name: string, addUsingEnter?: boolean, typingTimeout = 300): void { function createCategory(name: string, addUsingEnter?: boolean, typingTimeout = 300): void {
typeCategory(name, typingTimeout); typeCategory(name, typingTimeout);
@@ -92,26 +114,57 @@ describe('CategoriesManagementComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Get first error
*
* @returns error text
*/
function getFirstError(): string { function getFirstError(): string {
return fixture.debugElement.query(By.directive(MatError)).nativeElement.textContent; return fixture.debugElement.query(By.directive(MatError)).nativeElement.textContent;
} }
/**
* Get selection list
*
* @returns material selection list
*/
function getSelectionList(): MatSelectionList { function getSelectionList(): MatSelectionList {
return fixture.debugElement.query(By.directive(MatSelectionList)).componentInstance; return fixture.debugElement.query(By.directive(MatSelectionList)).componentInstance;
} }
/**
* Get remove category buttons
*
* @returns list of native elements
*/
function getRemoveCategoryButtons(): HTMLButtonElement[] { function getRemoveCategoryButtons(): HTMLButtonElement[] {
return fixture.debugElement.queryAll(By.css(`[data-automation-id="categories-remove-category-button"]`)).map((debugElem) => debugElem.nativeElement); return fixture.debugElement.queryAll(By.css(`[data-automation-id="categories-remove-category-button"]`)).map((debugElem) => debugElem.nativeElement);
} }
/**
* Get category control input
*
* @returns native input element
*/
function getCategoryControlInput(): HTMLInputElement { function getCategoryControlInput(): HTMLInputElement {
return fixture.debugElement.query(By.css('.adf-category-name-field input'))?.nativeElement; return fixture.debugElement.query(By.css('.adf-category-name-field input'))?.nativeElement;
} }
/**
* Get create category label
*
* @returns native element
*/
function getCreateCategoryLabel(): HTMLSpanElement { function getCreateCategoryLabel(): HTMLSpanElement {
return fixture.debugElement.query(By.css('.adf-existing-categories-panel span'))?.nativeElement; return fixture.debugElement.query(By.css('.adf-existing-categories-panel span'))?.nativeElement;
} }
/**
* Type new category
*
* @param name name of the category
* @param timeout typing timeout in milliseconds (default 300)
*/
function typeCategory(name: string, timeout = 300): void { function typeCategory(name: string, timeout = 300): void {
component.categoryNameControlVisible = true; component.categoryNameControlVisible = true;
fixture.detectChanges(); fixture.detectChanges();
@@ -208,6 +261,11 @@ describe('CategoriesManagementComponent', () => {
}); });
describe('Spinner', () => { describe('Spinner', () => {
/**
* Get the spinner element
*
* @returns debug element
*/
function getSpinner(): DebugElement { function getSpinner(): DebugElement {
return fixture.debugElement.query(By.css(`.mat-progress-spinner`)); return fixture.debugElement.query(By.css(`.mat-progress-spinner`));
} }
@@ -52,7 +52,7 @@ export class CategoryService {
* @param parentCategoryId The identifier of a parent category. * @param parentCategoryId The identifier of a parent category.
* @param skipCount Number of top categories to skip. * @param skipCount Number of top categories to skip.
* @param maxItems Maximum number of subcategories returned from Observable. * @param maxItems Maximum number of subcategories returned from Observable.
* @return Observable<CategoryPaging> * @returns Observable<CategoryPaging>
*/ */
getSubcategories(parentCategoryId: string, skipCount?: number, maxItems?: number): Observable<CategoryPaging> { getSubcategories(parentCategoryId: string, skipCount?: number, maxItems?: number): Observable<CategoryPaging> {
return from(this.categoriesApi.getSubcategories(parentCategoryId ?? '-root-', {skipCount, maxItems})); return from(this.categoriesApi.getSubcategories(parentCategoryId ?? '-root-', {skipCount, maxItems}));
@@ -67,7 +67,7 @@ export class CategoryService {
* @param opts.include Returns additional information about the category. The following optional fields can be requested: * @param opts.include Returns additional information about the category. The following optional fields can be requested:
* count * count
* path * path
* @return Observable<CategoryEntry> * @returns Observable<CategoryEntry>
*/ */
getCategory(categoryId: string, opts?: any): Observable<CategoryEntry> { getCategory(categoryId: string, opts?: any): Observable<CategoryEntry> {
return from(this.categoriesApi.getCategory(categoryId, opts)); return from(this.categoriesApi.getCategory(categoryId, opts));
@@ -78,7 +78,7 @@ export class CategoryService {
* *
* @param parentCategoryId The identifier of a parent category. * @param parentCategoryId The identifier of a parent category.
* @param payload List of categories to be created. * @param payload List of categories to be created.
* @return Observable<CategoryPaging | CategoryEntry> * @returns Observable<CategoryPaging | CategoryEntry>
*/ */
createSubcategories(parentCategoryId: string, payload: CategoryBody[]): Observable<CategoryPaging | CategoryEntry> { createSubcategories(parentCategoryId: string, payload: CategoryBody[]): Observable<CategoryPaging | CategoryEntry> {
return from(this.categoriesApi.createSubcategories(parentCategoryId, payload, {})); return from(this.categoriesApi.createSubcategories(parentCategoryId, payload, {}));
@@ -89,7 +89,7 @@ export class CategoryService {
* *
* @param categoryId The identifier of a category. * @param categoryId The identifier of a category.
* @param payload Updated category body * @param payload Updated category body
* @return Observable<CategoryEntry> * @returns Observable<CategoryEntry>
*/ */
updateCategory(categoryId: string, payload: CategoryBody): Observable<CategoryEntry> { updateCategory(categoryId: string, payload: CategoryBody): Observable<CategoryEntry> {
return from(this.categoriesApi.updateCategory(categoryId, payload, {})); return from(this.categoriesApi.updateCategory(categoryId, payload, {}));
@@ -99,7 +99,7 @@ export class CategoryService {
* Deletes category * Deletes category
* *
* @param categoryId The identifier of a category. * @param categoryId The identifier of a category.
* @return Observable<void> * @returns Observable<void>
*/ */
deleteCategory(categoryId: string): Observable<void> { deleteCategory(categoryId: string): Observable<void> {
return from(this.categoriesApi.deleteCategory(categoryId)); return from(this.categoriesApi.deleteCategory(categoryId));
@@ -111,7 +111,7 @@ export class CategoryService {
* @param name Value for name which should be used during searching categories. * @param name Value for name which should be used during searching categories.
* @param skipCount Specify how many first results should be skipped. Default 0. * @param skipCount Specify how many first results should be skipped. Default 0.
* @param maxItems Specify max number of returned categories. Default is specified by UserPreferencesService. * @param maxItems Specify max number of returned categories. Default is specified by UserPreferencesService.
* @return Observable<ResultSetPaging> Found categories which name contains searched name. * @returns Observable<ResultSetPaging> Found categories which name contains searched name.
*/ */
searchCategories(name: string, skipCount = 0, maxItems?: number): Observable<ResultSetPaging> { searchCategories(name: string, skipCount = 0, maxItems?: number): Observable<ResultSetPaging> {
maxItems = maxItems || this.userPreferencesService.paginationSize; maxItems = maxItems || this.userPreferencesService.paginationSize;
@@ -132,7 +132,7 @@ export class CategoryService {
* List of categories that node is assigned to * List of categories that node is assigned to
* *
* @param nodeId The identifier of a node. * @param nodeId The identifier of a node.
* @return Observable<CategoryPaging> Categories that node is assigned to * @returns Observable<CategoryPaging> Categories that node is assigned to
*/ */
getCategoryLinksForNode(nodeId: string): Observable<CategoryPaging> { getCategoryLinksForNode(nodeId: string): Observable<CategoryPaging> {
return from(this.categoriesApi.getCategoryLinksForNode(nodeId, {include: ['path']})); return from(this.categoriesApi.getCategoryLinksForNode(nodeId, {include: ['path']}));
@@ -143,7 +143,7 @@ export class CategoryService {
* *
* @param nodeId The identifier of a node. * @param nodeId The identifier of a node.
* @param categoryId The identifier of a category. * @param categoryId The identifier of a category.
* @return Observable<void> * @returns Observable<void>
*/ */
unlinkNodeFromCategory(nodeId: string, categoryId: string): Observable<void> { unlinkNodeFromCategory(nodeId: string, categoryId: string): Observable<void> {
return from(this.categoriesApi.unlinkNodeFromCategory(nodeId, categoryId)); return from(this.categoriesApi.unlinkNodeFromCategory(nodeId, categoryId));
@@ -154,7 +154,7 @@ export class CategoryService {
* *
* @param nodeId The identifier of a node. * @param nodeId The identifier of a node.
* @param categoryLinkBodyCreate Array of a categories that node will be linked to. * @param categoryLinkBodyCreate Array of a categories that node will be linked to.
* @return Observable<CategoryEntry> * @returns Observable<CategoryEntry>
*/ */
linkNodeToCategory(nodeId: string, categoryLinkBodyCreate: CategoryLinkBody[]): Observable<CategoryPaging | CategoryEntry> { linkNodeToCategory(nodeId: string, categoryLinkBodyCreate: CategoryLinkBody[]): Observable<CategoryPaging | CategoryEntry> {
return from(this.categoriesApi.linkNodeToCategory(nodeId, categoryLinkBodyCreate)); return from(this.categoriesApi.linkNodeToCategory(nodeId, categoryLinkBodyCreate));
@@ -171,11 +171,11 @@ export class NodesApiService {
/** /**
* Create a new Node from form metadata. * Create a new Node from form metadata.
* *
* @param path Path to the node
* @param nodeType Node type * @param nodeType Node type
* @param name Node name
* @param nameSpace Namespace for properties * @param nameSpace Namespace for properties
* @param data Property data to store in the node under namespace * @param data Property data to store in the node under namespace
* @param path Path to the node
* @param name Node name
* @returns The created node * @returns The created node
*/ */
public createNodeMetadata(nodeType: string, nameSpace: any, data: any, path: string, name?: string): Observable<NodeEntry> { public createNodeMetadata(nodeType: string, nameSpace: any, data: any, path: string, name?: string): Observable<NodeEntry> {
@@ -259,6 +259,9 @@ export class RenditionService {
* This method takes a url to trigger the print dialog against, and the type of artifact that it * This method takes a url to trigger the print dialog against, and the type of artifact that it
* is. * is.
* This URL should be one that can be rendered in the browser, for example PDF, Image, or Text * This URL should be one that can be rendered in the browser, for example PDF, Image, or Text
*
* @param url url to print
* @param type type of the rendition
*/ */
printFile(url: string, type: string): void { printFile(url: string, type: string): void {
const pwa = window.open(url, RenditionService.TARGET); const pwa = window.open(url, RenditionService.TARGET);
@@ -284,6 +287,8 @@ export class RenditionService {
* These are: images, PDF files, or PDF rendition of files. * These are: images, PDF files, or PDF rendition of files.
* We also force PDF rendition for TEXT type objects, otherwise the default URL is to download. * We also force PDF rendition for TEXT type objects, otherwise the default URL is to download.
* TODO there are different TEXT type objects, (HTML, plaintext, xml, etc. we should determine how these are handled) * TODO there are different TEXT type objects, (HTML, plaintext, xml, etc. we should determine how these are handled)
* @param objectId object it
* @param mimeType mime type
*/ */
printFileGeneric(objectId: string, mimeType: string): void { printFileGeneric(objectId: string, mimeType: string): void {
const nodeId = objectId; const nodeId = objectId;
@@ -158,7 +158,7 @@ export class SitesService {
* @param siteId The identifier of a site * @param siteId The identifier of a site
* @param siteMembershipBodyCreate The person to add and their role * @param siteMembershipBodyCreate The person to add and their role
* @param opts Optional parameters * @param opts Optional parameters
* @return Observable<SiteMemberEntry> * @returns Observable<SiteMemberEntry>
*/ */
createSiteMembership(siteId: string, siteMembershipBodyCreate: SiteMembershipBodyCreate, opts?: any): Observable<SiteMemberEntry> { createSiteMembership(siteId: string, siteMembershipBodyCreate: SiteMembershipBodyCreate, opts?: any): Observable<SiteMemberEntry> {
return from(this.sitesApi.createSiteMembership(siteId, siteMembershipBodyCreate, opts)).pipe(catchError((err: any) => this.handleError(err))); return from(this.sitesApi.createSiteMembership(siteId, siteMembershipBodyCreate, opts)).pipe(catchError((err: any) => this.handleError(err)));
@@ -171,7 +171,7 @@ export class SitesService {
* @param personId The identifier of a person. * @param personId The identifier of a person.
* @param siteMembershipBodyUpdate The persons new role * @param siteMembershipBodyUpdate The persons new role
* @param opts Optional parameters * @param opts Optional parameters
* @return Observable<SiteMemberEntry> * @returns Observable<SiteMemberEntry>
*/ */
updateSiteMembership( updateSiteMembership(
siteId: string, siteId: string,
@@ -189,7 +189,7 @@ export class SitesService {
* *
* @param siteId The identifier of a site. * @param siteId The identifier of a site.
* @param personId The identifier of a person. * @param personId The identifier of a person.
* @return Null response notifying when the operation is complete * @returns Null response notifying when the operation is complete
*/ */
deleteSiteMembership(siteId: string, personId: string): Observable<void> { deleteSiteMembership(siteId: string, personId: string): Observable<void> {
return from(this.sitesApi.deleteSiteMembership(siteId, personId)).pipe(catchError((err: any) => this.handleError(err))); return from(this.sitesApi.deleteSiteMembership(siteId, personId)).pipe(catchError((err: any) => this.handleError(err)));
@@ -246,7 +246,7 @@ export class SitesService {
* *
* @param siteId The identifier of a site. * @param siteId The identifier of a site.
* @param groupId The authorityId of a group. * @param groupId The authorityId of a group.
* @return Observable<SiteGroupEntry> * @returns Observable<SiteGroupEntry>
*/ */
getSiteGroupMembership(siteId: string, groupId: string): Observable<SiteGroupEntry> { getSiteGroupMembership(siteId: string, groupId: string): Observable<SiteGroupEntry> {
return from(this.sitesApi.getSiteGroupMembership(siteId, groupId)).pipe(catchError((err: any) => this.handleError(err))); return from(this.sitesApi.getSiteGroupMembership(siteId, groupId)).pipe(catchError((err: any) => this.handleError(err)));
@@ -258,7 +258,7 @@ export class SitesService {
* @param siteId The identifier of a site. * @param siteId The identifier of a site.
* @param groupId The authorityId of a group. * @param groupId The authorityId of a group.
* @param siteMembershipBodyUpdate The group new role * @param siteMembershipBodyUpdate The group new role
* @return Observable<SiteGroupEntry> * @returns Observable<SiteGroupEntry>
*/ */
updateSiteGroupMembership(siteId: string, groupId: string, siteMembershipBodyUpdate: SiteMembershipBodyUpdate): Observable<SiteGroupEntry> { updateSiteGroupMembership(siteId: string, groupId: string, siteMembershipBodyUpdate: SiteMembershipBodyUpdate): Observable<SiteGroupEntry> {
return from(this.sitesApi.updateSiteGroupMembership(siteId, groupId, siteMembershipBodyUpdate)).pipe( return from(this.sitesApi.updateSiteGroupMembership(siteId, groupId, siteMembershipBodyUpdate)).pipe(
@@ -271,7 +271,7 @@ export class SitesService {
* *
* @param siteId The identifier of a site. * @param siteId The identifier of a site.
* @param groupId The authorityId of a group. * @param groupId The authorityId of a group.
* @return Observable<void> * @returns Observable<void>
*/ */
deleteSiteGroupMembership(siteId: string, groupId: string): Observable<void> { deleteSiteGroupMembership(siteId: string, groupId: string): Observable<void> {
return from(this.sitesApi.deleteSiteGroupMembership(siteId, groupId)).pipe(catchError((err: any) => this.handleError(err))); return from(this.sitesApi.deleteSiteGroupMembership(siteId, groupId)).pipe(catchError((err: any) => this.handleError(err)));
@@ -35,56 +35,59 @@ export class ContentMetadataCardComponent implements OnChanges {
@Input() @Input()
node: Node; node: Node;
/** (optional) This flag displays/hides empty metadata /**
* This flag displays/hides empty metadata
* fields. * fields.
*/ */
@Input() @Input()
displayEmpty: boolean = false; displayEmpty?: boolean = false;
/** (optional) This flag displays desired aspect when open for the first time /**
* fields. * This flag displays desired aspect when open for the first time fields.
*/ */
@Input() @Input()
displayAspect: string = null; displayAspect?: string = null;
/** Display tags in the card **/ /** Display tags in the card */
@Input() @Input()
displayTags = true; displayTags = true;
/** Display categories in the card **/ /** Display categories in the card */
@Input() @Input()
displayCategories = true; displayCategories = true;
/** (required) Name or configuration of the metadata preset, which defines aspects /**
* Name or configuration of the metadata preset, which defines aspects
* and their properties. * and their properties.
*/ */
@Input() @Input()
preset: string | PresetConfig; preset: string | PresetConfig;
/** (optional) This flag sets the metadata in read only mode /**
* preventing changes. * This flag sets the metadata in read only mode preventing changes.
*/ */
@Input() @Input()
readOnly = false; readOnly? = false;
/** (optional) This flag allows the component to display more /**
* This flag allows the component to display more
* than one accordion at a time. * than one accordion at a time.
*/ */
@Input() @Input()
multi = false; multi? = false;
/** (optional) This flag toggles editable of content. **/ /** This flag toggles editable of content. */
@Input() @Input()
editable = false; editable? = false;
/** Emitted when content's editable state is changed. **/ /** Emitted when content's editable state is changed. */
@Output() @Output()
editableChange = new EventEmitter<boolean>(); editableChange = new EventEmitter<boolean>();
private _displayDefaultProperties: boolean = true; private _displayDefaultProperties: boolean = true;
/** (optional) This flag displays/hides the metadata /**
* properties. * This flag displays/hides the metadata properties.
*/ */
@Input() @Input()
set displayDefaultProperties(value: boolean) { set displayDefaultProperties(value: boolean) {
@@ -92,18 +92,38 @@ describe('ContentMetadataComponent', () => {
const findShowingTagInputButton = (): HTMLButtonElement => const findShowingTagInputButton = (): HTMLButtonElement =>
fixture.debugElement.query(By.css('[data-automation-id=showing-tag-input-button]')).nativeElement; fixture.debugElement.query(By.css('[data-automation-id=showing-tag-input-button]')).nativeElement;
/**
* Get metadata categories
*
* @returns list of native elements
*/
function getCategories(): HTMLParagraphElement[] { function getCategories(): HTMLParagraphElement[] {
return fixture.debugElement.queryAll(By.css('.adf-metadata-categories'))?.map((debugElem) => debugElem.nativeElement); return fixture.debugElement.queryAll(By.css('.adf-metadata-categories'))?.map((debugElem) => debugElem.nativeElement);
} }
/**
* Get a categories management component
*
* @returns angular component
*/
function getCategoriesManagementComponent(): CategoriesManagementComponent { function getCategoriesManagementComponent(): CategoriesManagementComponent {
return fixture.debugElement.query(By.directive(CategoriesManagementComponent))?.componentInstance; return fixture.debugElement.query(By.directive(CategoriesManagementComponent))?.componentInstance;
} }
/**
* Get categories title button
*
* @returns native element
*/
function getAssignCategoriesBtn(): HTMLButtonElement { function getAssignCategoriesBtn(): HTMLButtonElement {
return fixture.debugElement.query(By.css('.adf-metadata-categories-title button')).nativeElement; return fixture.debugElement.query(By.css('.adf-metadata-categories-title button')).nativeElement;
} }
/**
* Update aspect property
*
* @param newValue value to set
*/
async function updateAspectProperty(newValue: string): Promise<void> { async function updateAspectProperty(newValue: string): Promise<void> {
component.editable = true; component.editable = true;
const property = { key: 'properties.property-key', value: 'original-value' } as CardViewBaseItemModel; const property = { key: 'properties.property-key', value: 'original-value' } as CardViewBaseItemModel;
@@ -76,7 +76,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
@Input() @Input()
displayEmpty: boolean = false; displayEmpty: boolean = false;
/** Toggles between expanded (ie, full information) and collapsed /**
* Toggles between expanded (ie, full information) and collapsed
* (ie, reduced information) in the display * (ie, reduced information) in the display
*/ */
@Input() @Input()
@@ -81,14 +81,16 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
@Input() @Input()
currentFolderId: string = null; currentFolderId: string = null;
/** Hide the "My Files" option added to the site list by default. /**
* Hide the "My Files" option added to the site list by default.
* See the [Sites Dropdown component](sites-dropdown.component.md) * See the [Sites Dropdown component](sites-dropdown.component.md)
* for more information. * for more information.
*/ */
@Input() @Input()
dropdownHideMyFiles: boolean = false; dropdownHideMyFiles: boolean = false;
/** Custom site for site dropdown. This is the same as the `siteList`. /**
* Custom site for site dropdown. This is the same as the `siteList`.
* property of the Sites Dropdown component (see its doc page * property of the Sites Dropdown component (see its doc page
* for more information). * for more information).
*/ */
@@ -97,7 +99,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
_rowFilter: RowFilter = defaultValidation; _rowFilter: RowFilter = defaultValidation;
/** Custom *where* filter function. See the /**
* Custom *where* filter function. See the
* Document List component * Document List component
* for more information. * for more information.
*/ */
@@ -120,7 +123,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
_excludeSiteContent: string[] = []; _excludeSiteContent: string[] = [];
/** Custom list of site content componentIds. /**
* Custom list of site content componentIds.
* Used to filter out the corresponding items from the displayed nodes * Used to filter out the corresponding items from the displayed nodes
*/ */
@Input() @Input()
@@ -149,13 +153,15 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
@Input() @Input()
selectionMode: 'single' | 'multiple' = 'single'; selectionMode: 'single' | 'multiple' = 'single';
/** Function used to decide if the selected node has permission to be selected. /**
* Function used to decide if the selected node has permission to be selected.
* Default value is a function that always returns true. * Default value is a function that always returns true.
*/ */
@Input() @Input()
isSelectionValid: ValidationFunction = defaultValidation; isSelectionValid: ValidationFunction = defaultValidation;
/** Transformation to be performed on the chosen/folder node before building the /**
* Transformation to be performed on the chosen/folder node before building the
* breadcrumb UI. Can be useful when custom formatting is needed for the breadcrumb. * breadcrumb UI. Can be useful when custom formatting is needed for the breadcrumb.
* You can change the path elements from the node that are used to build the * You can change the path elements from the node that are used to build the
* breadcrumb using this function. * breadcrumb using this function.
@@ -427,7 +433,9 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
} }
/** /**
* Returns the actually selected|entered folder node or null in case of searching for the breadcrumb * Get current breadcrumb folder node
*
* @returns the actually selected|entered folder node or null in case of searching for the breadcrumb
*/ */
get breadcrumbFolderNode(): Node | null { get breadcrumbFolderNode(): Node | null {
let folderNode: Node; let folderNode: Node;
@@ -443,6 +451,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Prepares the dialog for a new search * Prepares the dialog for a new search
*
* @param searchRequest request options
*/ */
prepareDialogForNewSearch(searchRequest: SearchRequest): void { prepareDialogForNewSearch(searchRequest: SearchRequest): void {
this.target = searchRequest ? null : this.documentList; this.target = searchRequest ? null : this.documentList;
@@ -527,6 +537,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Sets showingSearchResults state to be able to differentiate between search results or folder results * Sets showingSearchResults state to be able to differentiate between search results or folder results
*
* @param $event node event
*/ */
onFolderChange($event: NodeEntryEvent): void { onFolderChange($event: NodeEntryEvent): void {
this.folderIdToShow = $event.value.id; this.folderIdToShow = $event.value.id;
@@ -540,6 +552,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Attempts to set the currently loaded node * Attempts to set the currently loaded node
*
* @param nodePaging pagination model
*/ */
onFolderLoaded(nodePaging: NodePaging): void { onFolderLoaded(nodePaging: NodePaging): void {
setTimeout(() => { setTimeout(() => {
@@ -554,6 +568,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Updates pagination.hasMoreItems to false after filtering only folders during 'COPY' and 'MOVE' action * Updates pagination.hasMoreItems to false after filtering only folders during 'COPY' and 'MOVE' action
*
* @param nodePaging pagination model
*/ */
updatePaginationAfterRowFilter(nodePaging: NodePaging): void { updatePaginationAfterRowFilter(nodePaging: NodePaging): void {
if (this.documentList.data.getRows().length < nodePaging.list.pagination.maxItems) { if (this.documentList.data.getRows().length < nodePaging.list.pagination.maxItems) {
@@ -563,6 +579,8 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Returns whether breadcrumb has to be shown or not * Returns whether breadcrumb has to be shown or not
*
* @returns `true` if needs to show the breadcrumb, otherwise `false`
*/ */
showBreadcrumbs() { showBreadcrumbs() {
return !this.showingSearchResults || this.chosenNode; return !this.showingSearchResults || this.chosenNode;
@@ -586,7 +604,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* Selects node as chosen if it has the right permission, clears the selection otherwise * Selects node as chosen if it has the right permission, clears the selection otherwise
* *
* @param entry * @param entry node entry
*/ */
private attemptNodeSelection(entry: Node): void { private attemptNodeSelection(entry: Node): void {
if (entry && this.isSelectionValid(entry)) { if (entry && this.isSelectionValid(entry)) {
@@ -604,7 +622,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
/** /**
* It filters and emit the selection coming from the document list * It filters and emit the selection coming from the document list
* *
* @param nodesEntries * @param nodesEntries selected nodes
*/ */
onCurrentSelection(nodesEntries: NodeEntry[]): void { onCurrentSelection(nodesEntries: NodeEntry[]): void {
const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry)); const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry));
@@ -68,7 +68,8 @@ export class ContentUserInfoComponent implements OnDestroy {
@Input() @Input()
showName: boolean = true; showName: boolean = true;
/** When the username is shown, this defines its position relative to the user info button. /**
* When the username is shown, this defines its position relative to the user info button.
* Can be `right` or `left`. * Can be `right` or `left`.
*/ */
@Input() @Input()
@@ -39,12 +39,14 @@ export class FolderDialogComponent implements OnInit {
folder: Node = null; folder: Node = null;
/** Emitted when the edit/create folder give error for example a folder with same name already exist /**
* Emitted when the edit/create folder give error for example a folder with same name already exist
*/ */
@Output() @Output()
error: EventEmitter<any> = new EventEmitter<any>(); error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the edit/create folder is successfully created/modified /**
* Emitted when the edit/create folder is successfully created/modified
*/ */
@Output() @Output()
success: EventEmitter<any> = new EventEmitter<Node>(); success: EventEmitter<any> = new EventEmitter<Node>();
@@ -49,7 +49,8 @@ export class LibraryDialogComponent implements OnInit, OnDestroy {
@Output() @Output()
error: EventEmitter<any> = new EventEmitter<any>(); error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the new library is created successfully. The /**
* Emitted when the new library is created successfully. The
* event parameter is a SiteEntry object with the details of the * event parameter is a SiteEntry object with the details of the
* newly-created library. * newly-created library.
*/ */
@@ -28,7 +28,8 @@ import { NodeAllowableOperationSubject } from '../interfaces/node-allowable-oper
}) })
export class CheckAllowableOperationDirective implements OnChanges { export class CheckAllowableOperationDirective implements OnChanges {
/** Node permission to check (create, delete, update, updatePermissions, /**
* Node permission to check (create, delete, update, updatePermissions,
* !create, !delete, !update, !updatePermissions). * !create, !delete, !update, !updatePermissions).
*/ */
@Input('adf-check-allowable-operation') @Input('adf-check-allowable-operation')
@@ -57,7 +58,7 @@ export class CheckAllowableOperationDirective implements OnChanges {
/** /**
* Updates disabled state for the decorated element * Updates disabled state for the decorated element
* *
* @memberof CheckAllowableOperationDirective * @returns the new state
*/ */
updateElement(): boolean { updateElement(): boolean {
const enable = this.hasAllowableOperations(this.nodes, this.permission); const enable = this.hasAllowableOperations(this.nodes, this.permission);
@@ -112,7 +113,7 @@ export class CheckAllowableOperationDirective implements OnChanges {
* *
* @param nodes Node collection to check * @param nodes Node collection to check
* @param permission Permission to check for each node * @param permission Permission to check for each node
* @memberof CheckAllowableOperationDirective * @returns `true` if there are allowable operations, otherwise `false`
*/ */
hasAllowableOperations(nodes: NodeEntry[], permission: string): boolean { hasAllowableOperations(nodes: NodeEntry[], permission: string): boolean {
if (nodes && nodes.length > 0) { if (nodes && nodes.length > 0) {
@@ -35,6 +35,7 @@ export class ContentActionListComponent {
* Registers action handler within the parent document list component. * Registers action handler within the parent document list component.
* *
* @param action Action model to register. * @param action Action model to register.
* @returns `true` if actions was registered, otherwise `false`
*/ */
registerAction(action: ContentActionModel): boolean { registerAction(action: ContentActionModel): boolean {
if (this.documentList && action) { if (this.documentList && action) {
@@ -76,13 +76,15 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy {
@Output() @Output()
permissionEvent = new EventEmitter(); permissionEvent = new EventEmitter();
/** Emitted when an error occurs during the action. /**
* Emitted when an error occurs during the action.
* Applies to copy and move actions. * Applies to copy and move actions.
*/ */
@Output() @Output()
error = new EventEmitter(); error = new EventEmitter();
/** Emitted when the action succeeds with the success string message. /**
* Emitted when the action succeeds with the success string message.
* Applies to copy, move and delete actions. * Applies to copy, move and delete actions.
*/ */
@Output() @Output()
@@ -137,7 +137,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
display: string = DisplayMode.List; display: string = DisplayMode.List;
/** Define a set of CSS styles to apply depending on the permission /**
* Define a set of CSS styles to apply depending on the permission
* of the user on that node. See the Permission Style model * of the user on that node. See the Permission Style model
* page for further details and examples. * page for further details and examples.
*/ */
@@ -156,7 +157,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
showHeader = ShowHeaderMode.Data; showHeader = ShowHeaderMode.Data;
/** User interaction for folder navigation or file preview. /**
* User interaction for folder navigation or file preview.
* Valid values are "click" and "dblclick". Default value: "dblclick" * Valid values are "click" and "dblclick". Default value: "dblclick"
*/ */
@Input() @Input()
@@ -166,7 +168,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
thumbnails: boolean = false; thumbnails: boolean = false;
/** Row selection mode. Can be null, `single` or `multiple`. For `multiple` mode, /**
* Row selection mode. Can be null, `single` or `multiple`. For `multiple` mode,
* you can use Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows. * you can use Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows.
*/ */
@Input() @Input()
@@ -203,21 +206,24 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
allowDropFiles: boolean = false; allowDropFiles: boolean = false;
/** Defines default sorting. The format is an array of 2 strings `[key, direction]` /**
* Defines default sorting. The format is an array of 2 strings `[key, direction]`
* i.e. `['name', 'desc']` or `['name', 'asc']`. Set this value only if you want to * i.e. `['name', 'desc']` or `['name', 'asc']`. Set this value only if you want to
* override the default sorting detected by the component based on columns. * override the default sorting detected by the component based on columns.
*/ */
@Input() @Input()
sorting: string[] | DataSorting = ['name', 'asc']; sorting: string[] | DataSorting = ['name', 'asc'];
/** Defines default sorting. The format is an array of strings `[key direction, otherKey otherDirection]` /**
* Defines default sorting. The format is an array of strings `[key direction, otherKey otherDirection]`
* i.e. `['name desc', 'nodeType asc']` or `['name asc']`. Set this value if you want a base * i.e. `['name desc', 'nodeType asc']` or `['name asc']`. Set this value if you want a base
* rule to be added to the sorting apart from the one driven by the header. * rule to be added to the sorting apart from the one driven by the header.
*/ */
@Input() @Input()
additionalSorting: DataSorting = new DataSorting('isFolder', 'desc'); additionalSorting: DataSorting = new DataSorting('isFolder', 'desc');
/** Defines sorting mode. Can be either `client` (items in the list /**
* Defines sorting mode. Can be either `client` (items in the list
* are sorted client-side) or `server` (the ordering supplied by the * are sorted client-side) or `server` (the ordering supplied by the
* server is used without further client-side sorting). * server is used without further client-side sorting).
* Note that the `server` option *does not* request the server to sort the data * Note that the `server` option *does not* request the server to sort the data
@@ -226,7 +232,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
sortingMode: 'server' | 'client' = 'server'; sortingMode: 'server' | 'client' = 'server';
/** The inline style to apply to every row. See /**
* The inline style to apply to every row. See
* the Angular NgStyle * the Angular NgStyle
* docs for more details and usage examples. * docs for more details and usage examples.
*/ */
@@ -237,14 +244,14 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
rowStyleClass: string; rowStyleClass: string;
/** Toggles the loading state and animated spinners for the component. Used in /**
* Toggles the loading state and animated spinners for the component. Used in
* combination with `navigate=false` to perform custom navigation and loading * combination with `navigate=false` to perform custom navigation and loading
* state indication. * state indication.
*/ */
@Input() @Input()
loading: boolean = false; loading: boolean = false;
/** @hidden */
@Input() @Input()
_rowFilter: RowFilter | null = null; _rowFilter: RowFilter | null = null;
@@ -292,7 +299,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @Input()
currentFolderId: string = null; currentFolderId: string = null;
/** Array of nodes to be pre-selected. All nodes in the /**
* Array of nodes to be pre-selected. All nodes in the
* array are pre-selected in multi selection mode, but only the first node * array are pre-selected in multi selection mode, but only the first node
* is pre-selected in single selection mode. * is pre-selected in single selection mode.
*/ */
@@ -319,7 +327,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Output() @Output()
folderChange = new EventEmitter<NodeEntryEvent>(); folderChange = new EventEmitter<NodeEntryEvent>();
/** Emitted when the user acts upon files with either single or double click /**
* Emitted when the user acts upon files with either single or double click
* (depends on `navigation-mode`). Useful for integration with the * (depends on `navigation-mode`). Useful for integration with the
* Viewer component. * Viewer component.
*/ */
@@ -765,6 +774,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
/** /**
* Creates a set of predefined columns. * Creates a set of predefined columns.
* @param preset preset to use
*/ */
private setupDefaultColumns(preset: string = 'default'): void { private setupDefaultColumns(preset: string = 'default'): void {
if (this.data) { if (this.data) {
@@ -170,7 +170,7 @@ export class DocumentListService implements DocumentListLoader {
* Load a folder by Node Id. * Load a folder by Node Id.
* *
* @param nodeId ID of the folder node * @param nodeId ID of the folder node
* @param pagination * @param pagination pagination model
* @param includeFields List of data field names to include in the results * @param includeFields List of data field names to include in the results
* @param where Optionally filter the list * @param where Optionally filter the list
* @param orderBy order by node property * @param orderBy order by node property
@@ -54,6 +54,7 @@ export class NodeActionsService {
* *
* @param contentEntry node to copy * @param contentEntry node to copy
* @param permission permission which is needed to apply the action * @param permission permission which is needed to apply the action
* @returns operation result
*/ */
copyContent(contentEntry: Node, permission?: string): Subject<string> { copyContent(contentEntry: Node, permission?: string): Subject<string> {
return this.doFileOperation(NodeAction.COPY, 'content', contentEntry, permission); return this.doFileOperation(NodeAction.COPY, 'content', contentEntry, permission);
@@ -64,6 +65,7 @@ export class NodeActionsService {
* *
* @param contentEntry node to copy * @param contentEntry node to copy
* @param permission permission which is needed to apply the action * @param permission permission which is needed to apply the action
* @returns operation result
*/ */
copyFolder(contentEntry: Node, permission?: string): Subject<string> { copyFolder(contentEntry: Node, permission?: string): Subject<string> {
return this.doFileOperation(NodeAction.COPY, 'folder', contentEntry, permission); return this.doFileOperation(NodeAction.COPY, 'folder', contentEntry, permission);
@@ -74,6 +76,7 @@ export class NodeActionsService {
* *
* @param contentEntry node to move * @param contentEntry node to move
* @param permission permission which is needed to apply the action * @param permission permission which is needed to apply the action
* @returns operation result
*/ */
moveContent(contentEntry: Node, permission?: string): Subject<string> { moveContent(contentEntry: Node, permission?: string): Subject<string> {
return this.doFileOperation(NodeAction.MOVE, 'content', contentEntry, permission); return this.doFileOperation(NodeAction.MOVE, 'content', contentEntry, permission);
@@ -84,6 +87,7 @@ export class NodeActionsService {
* *
* @param contentEntry node to move * @param contentEntry node to move
* @param permission permission which is needed to apply the action * @param permission permission which is needed to apply the action
* @returns operation result
*/ */
moveFolder(contentEntry: Node, permission?: string): Subject<string> { moveFolder(contentEntry: Node, permission?: string): Subject<string> {
return this.doFileOperation(NodeAction.MOVE, 'folder', contentEntry, permission); return this.doFileOperation(NodeAction.MOVE, 'folder', contentEntry, permission);
@@ -96,6 +100,7 @@ export class NodeActionsService {
* @param type type of the content (content|folder) * @param type type of the content (content|folder)
* @param contentEntry the contentEntry which has to have the action performed on * @param contentEntry the contentEntry which has to have the action performed on
* @param permission permission which is needed to apply the action * @param permission permission which is needed to apply the action
* @returns operation result
*/ */
private doFileOperation(action: NodeAction.COPY | NodeAction.MOVE, type: 'content' | 'folder', contentEntry: Node, permission?: string): Subject<string> { private doFileOperation(action: NodeAction.COPY | NodeAction.MOVE, type: 'content' | 'folder', contentEntry: Node, permission?: string): Subject<string> {
const observable = new Subject<string>(); const observable = new Subject<string>();
@@ -31,7 +31,7 @@ export class NewVersionUploaderDialogComponent implements OnInit {
/** /**
* Dialog title to show into the header. * Dialog title to show into the header.
* If data.title is not provided, a default title is set * If data.title is not provided, a default title is set
* */ */
title: string; title: string;
/** Emitted when an action is done. */ /** Emitted when an action is done. */
@@ -67,6 +67,7 @@ export class NodePermissionService {
* Get permissions for a given node * Get permissions for a given node
* *
* @param node Node to check permissions for * @param node Node to check permissions for
* @returns list of permission models
*/ */
getNodePermissions(node: Node): PermissionDisplayModel[] { getNodePermissions(node: Node): PermissionDisplayModel[] {
const result: PermissionDisplayModel[] = []; const result: PermissionDisplayModel[] = [];
@@ -45,10 +45,20 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
/**
* Get the input element
*
* @returns native element
*/
function getInput(): HTMLInputElement { function getInput(): HTMLInputElement {
return fixture.debugElement.query(By.css('input')).nativeElement; return fixture.debugElement.query(By.css('input')).nativeElement;
} }
/**
* Enter the new input value
*
* @param value value to input
*/
function enterNewInputValue(value: string) { function enterNewInputValue(value: string) {
const inputElement = getInput(); const inputElement = getInput();
inputElement.dispatchEvent(new Event('focusin')); inputElement.dispatchEvent(new Event('focusin'));
@@ -57,6 +67,11 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Add new option
*
* @param value value to input
*/
function addNewOption(value: string) { function addNewOption(value: string) {
const inputElement = getInput(); const inputElement = getInput();
inputElement.value = value; inputElement.value = value;
@@ -65,18 +80,39 @@ describe('SearchChipAutocompleteInputComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Get material chip list
*
* @returns list of chips
*/
function getChipList(): MatChip[] { function getChipList(): MatChip[] {
return fixture.debugElement.queryAll(By.css('mat-chip')).map((chip) => chip.nativeElement); return fixture.debugElement.queryAll(By.css('mat-chip')).map((chip) => chip.nativeElement);
} }
/**
* Get chip value by specific index
*
* @param index index of the chip
* @returns chip value
*/
function getChipValue(index: number): string { function getChipValue(index: number): string {
return fixture.debugElement.queryAll(By.css('mat-chip span')).map((chip) => chip.nativeElement)[index].innerText; return fixture.debugElement.queryAll(By.css('mat-chip span')).map((chip) => chip.nativeElement)[index].innerText;
} }
/**
* Get material option elements
*
* @returns list of debug elements
*/
function getOptionElements(): DebugElement[] { function getOptionElements(): DebugElement[] {
return fixture.debugElement.queryAll(By.css('mat-option')); return fixture.debugElement.queryAll(By.css('mat-option'));
} }
/**
* Get added options for auto-complete
*
* @returns list of debug elements
*/
function getAddedOptionElements(): DebugElement[] { function getAddedOptionElements(): DebugElement[] {
return fixture.debugElement.queryAll(By.css('.adf-autocomplete-added-option')); return fixture.debugElement.queryAll(By.css('.adf-autocomplete-added-option'));
} }
@@ -31,7 +31,7 @@ export class SearchChipListComponent {
/** /**
* Search filter to supply the data for the chips. * Search filter to supply the data for the chips.
* Not required from 4.5.0 and later versions @deprecated * Not required from 4.5.0 and later versions @deprecated
* */ */
@Input() @Input()
searchFilter: SearchFilterComponent; searchFilter: SearchFilterComponent;
@@ -59,7 +59,8 @@ export class SearchControlComponent implements OnDestroy {
@Input() @Input()
autocomplete: boolean = false; autocomplete: boolean = false;
/** Toggles whether to use an expanding search control. If false /**
* Toggles whether to use an expanding search control. If false
* then a regular input is used. * then a regular input is used.
*/ */
@Input() @Input()
@@ -69,13 +70,15 @@ export class SearchControlComponent implements OnDestroy {
@Input() @Input()
liveSearchMaxResults: number = 5; liveSearchMaxResults: number = 5;
/** Emitted when the search is submitted by pressing the ENTER key. /**
* Emitted when the search is submitted by pressing the ENTER key.
* The search term is provided as the value of the event. * The search term is provided as the value of the event.
*/ */
@Output() @Output()
submit: EventEmitter<any> = new EventEmitter(); submit: EventEmitter<any> = new EventEmitter();
/** Emitted when the search term is changed. The search term is provided /**
* Emitted when the search term is changed. The search term is provided
* in the 'value' property of the returned object. If the term is less * in the 'value' property of the returned object. If the term is less
* than three characters in length then it is truncated to an empty * than three characters in length then it is truncated to an empty
* string. * string.
@@ -57,6 +57,11 @@ describe('SearchFilterAutocompleteChipsComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
/**
* Add new auto-complete input
*
* @param value value to add
*/
function addNewOption(value: string) { function addNewOption(value: string) {
const inputElement = fixture.debugElement.query(By.css('adf-search-chip-autocomplete-input input')).nativeElement; const inputElement = fixture.debugElement.query(By.css('adf-search-chip-autocomplete-input input')).nativeElement;
inputElement.value = value; inputElement.value = value;
@@ -50,16 +50,30 @@ describe('SearchFacetChipTabbedComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
/**
* Open the facet
*/
function openFacet() { function openFacet() {
const chip = fixture.debugElement.query(By.css('mat-chip')); const chip = fixture.debugElement.query(By.css('mat-chip'));
chip.triggerEventHandler('click', {}); chip.triggerEventHandler('click', {});
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Get the filter display value
*
* @returns filter value
*/
function getDisplayValue(): string { function getDisplayValue(): string {
return fixture.debugElement.query(By.css('.adf-search-filter-ellipsis.adf-filter-value')).nativeElement.innerText.trim(); return fixture.debugElement.query(By.css('.adf-search-filter-ellipsis.adf-filter-value')).nativeElement.innerText.trim();
} }
/**
* Emit the event for the tabbed content
*
* @param eventName event name to trigger
* @param event event to trigger
*/
function emitChildEvent(eventName: string, event: any) { function emitChildEvent(eventName: string, event: any) {
const debugElem = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content')); const debugElem = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content'));
debugElem.triggerEventHandler(eventName, event); debugElem.triggerEventHandler(eventName, event);
@@ -98,7 +112,7 @@ describe('SearchFacetChipTabbedComponent', () => {
it('should display adf-search-facet-tabbed-content component', () => { it('should display adf-search-facet-tabbed-content component', () => {
openFacet(); openFacet();
let activeTabLabel = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content')); const activeTabLabel = fixture.debugElement.query(By.css('adf-search-facet-tabbed-content'));
expect(activeTabLabel).toBeTruthy(); expect(activeTabLabel).toBeTruthy();
}); });
@@ -62,15 +62,28 @@ describe('SearchFacetTabbedContentComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
/**
* Get the tab label content
*
* @returns list of native elements
*/
function getTabs(): HTMLDivElement[] { function getTabs(): HTMLDivElement[] {
return fixture.debugElement.queryAll(By.css('.mat-tab-label-content')).map((element) => element.nativeElement); return fixture.debugElement.queryAll(By.css('.mat-tab-label-content')).map((element) => element.nativeElement);
} }
/**
* Set selected tab
*
* @param tabIndex index of the tab
*/
function changeTab(tabIndex: number) { function changeTab(tabIndex: number) {
getTabs()[tabIndex].click(); getTabs()[tabIndex].click();
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Trigger component property change event
*/
function triggerComponentChanges() { function triggerComponentChanges() {
component.ngOnChanges({ component.ngOnChanges({
tabbedFacet: new SimpleChange(null, component.tabbedFacet, false) tabbedFacet: new SimpleChange(null, component.tabbedFacet, false)
@@ -78,6 +91,12 @@ describe('SearchFacetTabbedContentComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Add new item to the bucket
*
* @param field field name
* @param displayValue value to display
*/
function addBucketItem(field: string, displayValue: string) { function addBucketItem(field: string, displayValue: string) {
component.tabbedFacet.facets[field].buckets.items.push({ component.tabbedFacet.facets[field].buckets.items.push({
count: 1, count: 1,
@@ -47,14 +47,30 @@ describe('SearchLogicalFilterComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
/**
* Get search input elements
*
* @returns list of native elements
*/
function getInputs(): HTMLInputElement[] { function getInputs(): HTMLInputElement[] {
return fixture.debugElement.queryAll(By.css('.adf-search-input input')).map((input) => input.nativeElement); return fixture.debugElement.queryAll(By.css('.adf-search-input input')).map((input) => input.nativeElement);
} }
/**
* Get input label elements
*
* @returns list of labels
*/
function getInputsLabels(): string[] { function getInputsLabels(): string[] {
return fixture.debugElement.queryAll(By.css('.adf-search-input mat-label')).map((label) => label.nativeElement.innerText); return fixture.debugElement.queryAll(By.css('.adf-search-input mat-label')).map((label) => label.nativeElement.innerText);
} }
/**
* Enters a new phrase
*
* @param value new value
* @param index value index
*/
function enterNewPhrase(value: string, index: number) { function enterNewPhrase(value: string, index: number) {
const inputs = getInputs(); const inputs = getInputs();
inputs[index].value = value; inputs[index].value = value;
@@ -64,7 +64,8 @@ export class SearchComponent implements SearchComponentInterface, AfterContentIn
@Input() @Input()
skipResults: number = 0; skipResults: number = 0;
/** Search term to use when executing the search. Updating this value will /**
* Search term to use when executing the search. Updating this value will
* run a new search and update the results. * run a new search and update the results.
*/ */
@Input() @Input()
@@ -55,27 +55,47 @@ export class SearchFilterList<T> implements Iterable<T> {
this.currentPageSize = this.pageSize; this.currentPageSize = this.pageSize;
} }
/** Returns visible portion of the items. */ /**
* Returns visible portion of the items.
*
* @returns list of items
*/
get visibleItems(): T[] { get visibleItems(): T[] {
return this.filteredItems.slice(0, this.currentPageSize); return this.filteredItems.slice(0, this.currentPageSize);
} }
/** Returns entire collection length including items not displayed on the page. */ /**
* Get items length
*
* @returns entire collection length including items not displayed on the page
*/
get length(): number { get length(): number {
return this.items.length; return this.items.length;
} }
/** Detects whether more items can be displayed. */ /**
* Detect whether more items can be displayed.
*
* @returns `true` if can show more items, otherwise `false`
*/
get canShowMoreItems(): boolean { get canShowMoreItems(): boolean {
return this.filteredItems.length > this.currentPageSize; return this.filteredItems.length > this.currentPageSize;
} }
/** Detects whether less items can be displayed. */ /**
* Detect whether less items can be displayed.
*
* @returns `true` if can show less items, otherwise `false`
*/
get canShowLessItems(): boolean { get canShowLessItems(): boolean {
return this.currentPageSize > this.pageSize; return this.currentPageSize > this.pageSize;
} }
/** Detects whether content fits single page. */ /**
* Detect whether content fits single page.
*
* @returns `true` if content fits single page, otherwise `false`.
*/
get fitsPage(): boolean { get fitsPage(): boolean {
return this.pageSize >= this.filteredItems.length; return this.pageSize >= this.filteredItems.length;
} }
@@ -285,6 +285,8 @@ export abstract class BaseQueryBuilderService {
/** /**
* Builds the current query and triggers the `updated` event. * Builds the current query and triggers the `updated` event.
*
* @param queryBody query settings
*/ */
update(queryBody?: SearchRequest): void { update(queryBody?: SearchRequest): void {
const query = queryBody ? queryBody : this.buildQuery(); const query = queryBody ? queryBody : this.buildQuery();
@@ -294,7 +296,7 @@ export abstract class BaseQueryBuilderService {
/** /**
* Builds and executes the current query. * Builds and executes the current query.
* *
* @returns Nothing * @param queryBody query settings
*/ */
async execute(queryBody?: SearchRequest) { async execute(queryBody?: SearchRequest) {
try { try {
@@ -40,9 +40,10 @@ const DEFAULT_PAGE_SIZE: number = 5;
providedIn: 'root' providedIn: 'root'
}) })
export class SearchFacetFiltersService implements OnDestroy { export class SearchFacetFiltersService implements OnDestroy {
/** All facet field items to be displayed in the component. These are updated according to the response. /**
* When a new search is performed, the already existing items are updated with the new bucket count values and * All facet field items to be displayed in the component. These are updated according to the response.
* the newly received items are added to the responseFacets. * When a new search is performed, the already existing items are updated with the new bucket count values and
* the newly received items are added to the responseFacets.
*/ */
responseFacets: FacetField[] = null; responseFacets: FacetField[] = null;
/* tabbed facet incorporating creator and modifier facets */ /* tabbed facet incorporating creator and modifier facets */
@@ -80,10 +80,10 @@ export class SecurityControlsService {
/** /**
* Get All security groups * Get All security groups
* *
* @param include Additional information about the security group
* @param skipCount The number of entities that exist in the collection before those included in this list. * @param skipCount The number of entities that exist in the collection before those included in this list.
* @param maxItems The maximum number of items to return in the list. Default is specified by UserPreferencesService. * @param maxItems The maximum number of items to return in the list. Default is specified by UserPreferencesService.
* @return Promise<SecurityControlsGroupResponse> * @param include Additional information about the security group
* @returns Promise<SecurityControlsGroupResponse>
*/ */
getSecurityGroup( getSecurityGroup(
skipCount = DEFAULT_SKIP_COUNT, skipCount = DEFAULT_SKIP_COUNT,
@@ -117,7 +117,7 @@ export class SecurityControlsService {
* Create security group * Create security group
* *
* @param input securityGroupBody. * @param input securityGroupBody.
* @return Observable<SecurityGroupEntry> * @returns Observable<SecurityGroupEntry>
*/ */
createSecurityGroup( createSecurityGroup(
input: SecurityGroupBody input: SecurityGroupBody
@@ -141,7 +141,7 @@ export class SecurityControlsService {
* *
* @param securityGroupId The key for the security group id. * @param securityGroupId The key for the security group id.
* @param input securityMarkBody[]. * @param input securityMarkBody[].
* @return Promise<SecurityMarkPaging | SecurityMarkEntry> * @returns Promise<SecurityMarkPaging | SecurityMarkEntry>
*/ */
createSecurityMarks( createSecurityMarks(
securityGroupId: string, securityGroupId: string,
@@ -170,7 +170,7 @@ export class SecurityControlsService {
* *
* @param securityGroupId The key for the security group id. * @param securityGroupId The key for the security group id.
* @param skipCount The number of entities that exist in the collection before those included in this list. * @param skipCount The number of entities that exist in the collection before those included in this list.
* @return Promise<SecurityControlsMarkResponse> * @returns Promise<SecurityControlsMarkResponse>
*/ */
getSecurityMark( getSecurityMark(
securityGroupId: string, securityGroupId: string,
@@ -203,7 +203,7 @@ export class SecurityControlsService {
* @param securityGroupId The Key of Security Group id for which info is required * @param securityGroupId The Key of Security Group id for which info is required
* @param input SecurityGroupBody * @param input SecurityGroupBody
* @param opts additional information about the security group * @param opts additional information about the security group
* @return Promise<SecurityGroupEntry> * @returns Promise<SecurityGroupEntry>
*/ */
updateSecurityGroup( updateSecurityGroup(
securityGroupId: string, securityGroupId: string,
@@ -242,7 +242,7 @@ export class SecurityControlsService {
* @param securityGroupId The key for the security group id. * @param securityGroupId The key for the security group id.
* @param securityMarkId The key for the security mark is in use or not. * @param securityMarkId The key for the security mark is in use or not.
* @param input securityMarkBody. * @param input securityMarkBody.
* @return Promise<SecurityMarkEntry> * @returns Promise<SecurityMarkEntry>
*/ */
updateSecurityMark( updateSecurityMark(
securityGroupId: string, securityGroupId: string,
@@ -274,7 +274,7 @@ export class SecurityControlsService {
* Delete security group * Delete security group
* *
* @param securityGroupId The key for the security group id. * @param securityGroupId The key for the security group id.
* @return Observable<void> * @returns Observable<void>
*/ */
deleteSecurityGroup( deleteSecurityGroup(
securityGroupId: string securityGroupId: string
@@ -292,7 +292,7 @@ export class SecurityControlsService {
* *
* @param securityGroupId The key for the security group id. * @param securityGroupId The key for the security group id.
* @param securityMarkId The key for the security mark id. * @param securityMarkId The key for the security mark id.
* @return Promise<SecurityMarkEntry> * @returns Promise<SecurityMarkEntry>
*/ */
deleteSecurityMark( deleteSecurityMark(
securityGroupId: string, securityGroupId: string,
@@ -321,7 +321,7 @@ export class SecurityControlsService {
* @param authorityName The name for the authority for which the clearance is to be fetched. Can be left blank in which case it will fetch it for all users with pagination * @param authorityName The name for the authority for which the clearance is to be fetched. Can be left blank in which case it will fetch it for all users with pagination
* @param skipCount The number of entities that exist in the collection before those included in this list. * @param skipCount The number of entities that exist in the collection before those included in this list.
* @param maxItems The maximum number of items to return in the list. Default is specified by UserPreferencesService. * @param maxItems The maximum number of items to return in the list. Default is specified by UserPreferencesService.
* @return Observable<AuthorityClearanceGroupPaging> * @returns Observable<AuthorityClearanceGroupPaging>
*/ */
getClearancesForAuthority( getClearancesForAuthority(
authorityName: string, authorityName: string,
@@ -345,7 +345,7 @@ export class SecurityControlsService {
* *
* @param authorityName The name for the authority for which the clearance is to be updated * @param authorityName The name for the authority for which the clearance is to be updated
* @param securityMarksList NodeSecurityMarkBody[] * @param securityMarksList NodeSecurityMarkBody[]
* @return Observable<SecurityMarkEntry | SecurityMarkPaging> * @returns Observable<SecurityMarkEntry | SecurityMarkPaging>
*/ */
updateClearancesForAuthority(authorityName: string, securityMarksList: NodeSecurityMarkBody[]): Observable<SecurityMarkEntry | SecurityMarkPaging> { updateClearancesForAuthority(authorityName: string, securityMarksList: NodeSecurityMarkBody[]): Observable<SecurityMarkEntry | SecurityMarkPaging> {
this.loadingSource.next(true); this.loadingSource.next(true);
@@ -43,7 +43,8 @@ export class DropdownSitesComponent implements OnInit {
@Input() @Input()
hideMyFiles: boolean = false; hideMyFiles: boolean = false;
/** A custom list of sites to be displayed by the dropdown. If no value /**
* A custom list of sites to be displayed by the dropdown. If no value
* is given, the sites of the current user are displayed by default. A * is given, the sites of the current user are displayed by default. A
* list of objects only with properties 'title' and 'guid' is enough to * list of objects only with properties 'title' and 'guid' is enough to
* be able to display the dropdown. * be able to display the dropdown.
@@ -55,20 +56,23 @@ export class DropdownSitesComponent implements OnInit {
@Input() @Input()
value: string = null; value: string = null;
/** Text or a translation key to act as a placeholder. Default value is the /**
* Text or a translation key to act as a placeholder. Default value is the
* key "DROPDOWN.PLACEHOLDER_LABEL". * key "DROPDOWN.PLACEHOLDER_LABEL".
*/ */
@Input() @Input()
placeholder: string = 'DROPDOWN.PLACEHOLDER_LABEL'; placeholder: string = 'DROPDOWN.PLACEHOLDER_LABEL';
/** Filter for the results of the sites query. Possible values are /**
* Filter for the results of the sites query. Possible values are
* "members" and "containers". When "members" is used, the site list * "members" and "containers". When "members" is used, the site list
* will be restricted to the sites that the user is a member of. * will be restricted to the sites that the user is a member of.
*/ */
@Input() @Input()
relations: string; relations: string;
/** Emitted when the user selects a site. When the default option is selected, /**
* Emitted when the user selects a site. When the default option is selected,
* an empty model is emitted. * an empty model is emitted.
*/ */
@Output() @Output()
@@ -194,8 +194,7 @@ export class TagService {
* *
* @param nodeId Id of node to which tags should be assigned. * @param nodeId Id of node to which tags should be assigned.
* @param tags List of tags to create and assign or just assign if they already exist. * @param tags List of tags to create and assign or just assign if they already exist.
* * @returns Just linked tags to node or single tag if linked only one tag.
* @return Just linked tags to node or single tag if linked only one tag.
*/ */
assignTagsToNode(nodeId: string, tags: TagBody[]): Observable<TagPaging | TagEntry> { assignTagsToNode(nodeId: string, tags: TagBody[]): Observable<TagPaging | TagEntry> {
return from(this.tagsApi.assignTagsToNode(nodeId, tags)).pipe( return from(this.tagsApi.assignTagsToNode(nodeId, tags)).pipe(
@@ -56,11 +56,6 @@ export class TagListComponent implements OnInit, OnDestroy {
private onDestroy$ = new Subject<boolean>(); private onDestroy$ = new Subject<boolean>();
/**
* Constructor
*
* @param tagService
*/
constructor(private tagService: TagService) { constructor(private tagService: TagService) {
this.defaultPagination = { this.defaultPagination = {
@@ -57,10 +57,20 @@ describe('TagNodeList', () => {
let tagService: TagService; let tagService: TagService;
let resizeCallback: ResizeObserverCallback; let resizeCallback: ResizeObserverCallback;
/**
* Find 'More' button
*
* @returns native element
*/
function findViewMoreButton(): HTMLButtonElement { function findViewMoreButton(): HTMLButtonElement {
return element.querySelector('.adf-view-more-button'); return element.querySelector('.adf-view-more-button');
} }
/**
* Get the tag chips
*
* @returns native element list
*/
function findTagChips(): NodeListOf<Element> { function findTagChips(): NodeListOf<Element> {
return element.querySelectorAll('.adf-tag-chips'); return element.querySelectorAll('.adf-tag-chips');
} }
@@ -149,7 +159,12 @@ describe('TagNodeList', () => {
describe('Limit tags display', () => { describe('Limit tags display', () => {
let initialEntries: TagEntry[]; let initialEntries: TagEntry[];
async function renderTags(entries?: TagEntry[]): Promise<any> { /**
* Render tags
*
* @param entries tags to render
*/
async function renderTags(entries?: TagEntry[]) {
dataTag.list.entries = entries || initialEntries; dataTag.list.entries = entries || initialEntries;
component.tagsEntries = dataTag.list.entries; component.tagsEntries = dataTag.list.entries;
fixture.detectChanges(); fixture.detectChanges();
@@ -88,12 +88,6 @@ export class TagNodeListComponent implements OnChanges, OnDestroy, OnInit, After
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
}); });
/**
* Constructor
*
* @param tagService
* @param changeDetectorRef
*/
constructor(private tagService: TagService, private changeDetectorRef: ChangeDetectorRef) { constructor(private tagService: TagService, private changeDetectorRef: ChangeDetectorRef) {
} }
@@ -85,29 +85,59 @@ describe('TagsCreatorComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
/**
* Get name input element
*
* @returns native element
*/
function getNameInput(): HTMLInputElement { function getNameInput(): HTMLInputElement {
return fixture.debugElement.query(By.css(`.adf-tag-name-field input`))?.nativeElement; return fixture.debugElement.query(By.css(`.adf-tag-name-field input`))?.nativeElement;
} }
/**
* Get the create tag label
*
* @returns native element
*/
function getCreateTagLabel(): HTMLSpanElement { function getCreateTagLabel(): HTMLSpanElement {
return fixture.debugElement.query(By.css('.adf-create-tag-label'))?.nativeElement; return fixture.debugElement.query(By.css('.adf-create-tag-label'))?.nativeElement;
} }
/**
* Get remove tag buttons
*
* @returns list of native elements
*/
function getRemoveTagButtons(): HTMLButtonElement[] { function getRemoveTagButtons(): HTMLButtonElement[] {
const elements = fixture.debugElement.queryAll(By.css(`[data-automation-id="remove-tag-button"]`)); const elements = fixture.debugElement.queryAll(By.css(`[data-automation-id="remove-tag-button"]`));
return elements.map(el => el.nativeElement); return elements.map(el => el.nativeElement);
} }
/**
* Click at the hide name input button
*/
function clickAtHideNameInputButton() { function clickAtHideNameInputButton() {
fixture.debugElement.query(By.css(`[data-automation-id="hide-tag-name-input-button"]`)).nativeElement.click(); fixture.debugElement.query(By.css(`[data-automation-id="hide-tag-name-input-button"]`)).nativeElement.click();
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Get newly added tags
*
* @returns list of tags
*/
function getAddedTags(): string[] { function getAddedTags(): string[] {
const tagElements = fixture.debugElement.queryAll(By.css(`.adf-tags-creation .adf-tag`)); const tagElements = fixture.debugElement.queryAll(By.css(`.adf-tags-creation .adf-tag`));
return tagElements.map(el => el.nativeElement.firstChild.nodeValue.trim()); return tagElements.map(el => el.nativeElement.firstChild.nodeValue.trim());
} }
/**
* Adds tag to the added list
*
* @param tagName tag name
* @param addUsingEnter use Enter when adding
* @param typingTimeout typing timeout in milliseconds (default 300)
*/
function addTagToAddedList(tagName: string, addUsingEnter?: boolean, typingTimeout = 300): void { function addTagToAddedList(tagName: string, addUsingEnter?: boolean, typingTimeout = 300): void {
typeTag(tagName, typingTimeout); typeTag(tagName, typingTimeout);
@@ -121,6 +151,12 @@ describe('TagsCreatorComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* type a new tag
*
* @param tagName tag name
* @param timeout typing timeout in milliseconds (default 300)
*/
function typeTag(tagName: string, timeout = 300): void { function typeTag(tagName: string, timeout = 300): void {
component.tagNameControlVisible = true; component.tagNameControlVisible = true;
fixture.detectChanges(); fixture.detectChanges();
@@ -133,10 +169,20 @@ describe('TagsCreatorComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
} }
/**
* Find the selection list
*
* @returns material component
*/
function findSelectionList(): MatSelectionList { function findSelectionList(): MatSelectionList {
return fixture.debugElement.query(By.directive(MatSelectionList)).componentInstance; return fixture.debugElement.query(By.directive(MatSelectionList)).componentInstance;
} }
/**
* Get the existing tags label
*
* @returns label
*/
function getExistingTagsLabel(): string { function getExistingTagsLabel(): string {
return fixture.debugElement.query(By.css('.adf-existing-tags-label')).nativeElement.textContent.trim(); return fixture.debugElement.query(By.css('.adf-existing-tags-label')).nativeElement.textContent.trim();
} }
@@ -323,6 +369,11 @@ describe('TagsCreatorComponent', () => {
})); }));
describe('Errors', () => { describe('Errors', () => {
/**
* Get first error
*
* @returns error text
*/
function getFirstError(): string { function getFirstError(): string {
const error = fixture.debugElement.query(By.directive(MatError)); const error = fixture.debugElement.query(By.directive(MatError));
return error?.nativeElement.textContent; return error?.nativeElement.textContent;
@@ -407,6 +458,11 @@ describe('TagsCreatorComponent', () => {
}); });
describe('Existing tags panel', () => { describe('Existing tags panel', () => {
/**
* Get the existing tags panel
*
* @returns debug element
*/
function getPanel(): DebugElement { function getPanel(): DebugElement {
return fixture.debugElement.query(By.css(`.adf-existing-tags-panel`)); return fixture.debugElement.query(By.css(`.adf-existing-tags-panel`));
} }
@@ -498,6 +554,11 @@ describe('TagsCreatorComponent', () => {
}); });
describe('Existing tags', () => { describe('Existing tags', () => {
/**
* Get the existing tags
*
* @returns list of tags
*/
function getExistingTags(): string[] { function getExistingTags(): string[] {
const tagElements = fixture.debugElement.queryAll(By.css(`.adf-existing-tags-panel .adf-tag .mat-list-text`)); const tagElements = fixture.debugElement.queryAll(By.css(`.adf-existing-tags-panel .adf-tag .mat-list-text`));
return tagElements.map(el => el.nativeElement.firstChild.nodeValue.trim()); return tagElements.map(el => el.nativeElement.firstChild.nodeValue.trim());
@@ -710,6 +771,11 @@ describe('TagsCreatorComponent', () => {
}); });
describe('Spinner', () => { describe('Spinner', () => {
/**
* Get the material progress spinner
*
* @returns debug element
*/
function getSpinner(): DebugElement { function getSpinner(): DebugElement {
return fixture.debugElement.query(By.css(`.mat-progress-spinner`)); return fixture.debugElement.query(By.css(`.mat-progress-spinner`));
} }
@@ -285,7 +285,7 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
/** /**
* Called when user selects any tag from list of existing tags. It moves tag from existing tags list to top list. * Called when user selects any tag from list of existing tags. It moves tag from existing tags list to top list.
* *
* @param change * @param change changes
*/ */
addExistingTagToTagsToAssign(change: MatSelectionListChange): void { addExistingTagToTagsToAssign(change: MatSelectionListChange): void {
const selectedTag: TagEntry = change.options[0].value; const selectedTag: TagEntry = change.options[0].value;
@@ -299,7 +299,7 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
/** /**
* Checks if component is in Create mode. * Checks if component is in Create mode.
* *
* @return true if Create mode, false otherwise. * @returns `true` if `Create` mode, `false` otherwise.
*/ */
isOnlyCreateMode(): boolean { isOnlyCreateMode(): boolean {
return this.mode === TagsCreatorMode.CREATE; return this.mode === TagsCreatorMode.CREATE;
@@ -151,10 +151,11 @@ export class TreeComponent<T extends TreeNode> implements OnInit, OnDestroy {
/** /**
* Checks if node is LoadMoreNode node * Checks if node is LoadMoreNode node
* *
* @param _idx (unused)
* @param node node to be checked * @param node node to be checked
* @returns boolean * @returns `true` if there are more items to load, otherwise `false`
*/ */
public isLoadMoreNode(_: number, node: T): boolean { public isLoadMoreNode(_idx: number, node: T): boolean {
return node.nodeType === TreeNodeType.LoadMoreNode; return node.nodeType === TreeNodeType.LoadMoreNode;
} }
@@ -109,7 +109,6 @@ export abstract class TreeService<T extends TreeNode> extends DataSource<T> {
* Gets children of the node * Gets children of the node
* *
* @param parentNode Parent node * @param parentNode Parent node
*
* @returns children of parent node * @returns children of parent node
*/ */
public getChildren(parentNode: T): T[] { public getChildren(parentNode: T): T[] {
@@ -31,13 +31,15 @@ export abstract class UploadBase implements OnInit, OnDestroy {
protected translationService = inject(TranslationService); protected translationService = inject(TranslationService);
protected ngZone = inject(NgZone); protected ngZone = inject(NgZone);
/** Sets a limit on the maximum size (in bytes) of a file to be uploaded. /**
* Sets a limit on the maximum size (in bytes) of a file to be uploaded.
* Has no effect if undefined. * Has no effect if undefined.
*/ */
@Input() @Input()
maxFilesSize: number; maxFilesSize: number;
/** The ID of the root. Use the nodeId for /**
* The ID of the root. Use the nodeId for
* Content Services or the taskId/processId for Process Services. * Content Services or the taskId/processId for Process Services.
*/ */
@Input() @Input()
@@ -99,7 +101,7 @@ export abstract class UploadBase implements OnInit, OnDestroy {
/** /**
* Upload a list of file in the specified path * Upload a list of file in the specified path
* *
* @param files * @param files files to upload
*/ */
uploadFiles(files: File[]): void { uploadFiles(files: File[]): void {
const filteredFiles: FileModel[] = files const filteredFiles: FileModel[] = files
@@ -142,6 +144,7 @@ export abstract class UploadBase implements OnInit, OnDestroy {
* Checks if the given file is allowed by the extension filters * Checks if the given file is allowed by the extension filters
* *
* @param file FileModel * @param file FileModel
* @returns `true` if file is acceptable, otherwise `false`
*/ */
protected isFileAcceptable(file: FileModel): boolean { protected isFileAcceptable(file: FileModel): boolean {
if (this.acceptedFilesType === '*') { if (this.acceptedFilesType === '*') {
@@ -158,10 +161,11 @@ export abstract class UploadBase implements OnInit, OnDestroy {
/** /**
* Creates FileModel from File * Creates FileModel from File
* *
* @param file * @param file file instance
* @param parentId * @param parentId parent id
* @param path * @param path upload path
* @param id * @param id model id
* @returns file model
*/ */
protected createFileModel(file: File, parentId: string, path: string, id?: string): FileModel { protected createFileModel(file: File, parentId: string, path: string, id?: string): FileModel {
return new FileModel(file, { return new FileModel(file, {
@@ -195,6 +199,7 @@ export abstract class UploadBase implements OnInit, OnDestroy {
* Checks if the given file is an acceptable size * Checks if the given file is an acceptable size
* *
* @param file FileModel * @param file FileModel
* @returns `true` if file size is acceptable, otherwise `false`
*/ */
private isFileSizeAcceptable(file: FileModel): boolean { private isFileSizeAcceptable(file: FileModel): boolean {
let acceptableSize = true; let acceptableSize = true;
@@ -55,8 +55,6 @@ export class FileUploadingListComponent {
* Cancel file upload * Cancel file upload
* *
* @param file File model to cancel upload for. * @param file File model to cancel upload for.
*
* @memberOf FileUploadingListComponent
*/ */
cancelFile(file: FileModel): void { cancelFile(file: FileModel): void {
if (file.status === FileUploadStatus.Pending) { if (file.status === FileUploadStatus.Pending) {
@@ -70,8 +68,6 @@ export class FileUploadingListComponent {
* Remove uploaded file * Remove uploaded file
* *
* @param file File model to remove upload for. * @param file File model to remove upload for.
*
* @memberOf FileUploadingListComponent
*/ */
removeFile(file: FileModel): void { removeFile(file: FileModel): void {
if (file.status === FileUploadStatus.Error) { if (file.status === FileUploadStatus.Error) {
@@ -99,6 +95,8 @@ export class FileUploadingListComponent {
/** /**
* Checks if all the files are uploaded false if there is at least one file in Progress | Starting | Pending * Checks if all the files are uploaded false if there is at least one file in Progress | Starting | Pending
*
* @returns `true` if upload is complete, otherwise `false`
*/ */
isUploadCompleted(): boolean { isUploadCompleted(): boolean {
return ( return (
@@ -115,6 +113,8 @@ export class FileUploadingListComponent {
/** /**
* Check if all the files are Cancelled | Aborted | Error. false if there is at least one file in uploading states * Check if all the files are Cancelled | Aborted | Error. false if there is at least one file in uploading states
*
* @returns `true` if upload is cancelled, otherwise `false`
*/ */
isUploadCancelled(): boolean { isUploadCancelled(): boolean {
return ( return (
@@ -77,7 +77,11 @@ export class UploadDragAreaComponent extends UploadBase implements NodeAllowable
}); });
} }
/** Returns true or false considering the component options and node permissions */ /**
* Check if content is droppable
*
* @returns `true` or `false` considering the component options and node permissions
*/
isDroppable(): boolean { isDroppable(): boolean {
return !this.disabled; return !this.disabled;
} }
@@ -141,7 +141,7 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
/** /**
* Change the style of the drag area when a file is over the drag area. * Change the style of the drag area when a file is over the drag area.
* *
* @param event * @param event drag event
*/ */
onDragOver(event: DragEvent): void { onDragOver(event: DragEvent): void {
if (this.enabled && !event.defaultPrevented) { if (this.enabled && !event.defaultPrevented) {
@@ -158,7 +158,7 @@ export class FileDraggableDirective implements OnInit, OnDestroy {
/** /**
* Prevent default and stop propagation of the DOM event. * Prevent default and stop propagation of the DOM event.
* *
* @param $event - DOM event. * @param event DOM event
*/ */
preventDefault(event: Event): void { preventDefault(event: Event): void {
event.stopPropagation(); event.stopPropagation();
@@ -18,6 +18,12 @@
import { VersionCompatibilityService } from './version-compatibility.service'; import { VersionCompatibilityService } from './version-compatibility.service';
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
/**
* Create a version compatibility factory
*
* @param versionCompatibilityService service dependency
* @returns factory function
*/
export function versionCompatibilityFactory(versionCompatibilityService: VersionCompatibilityService) { export function versionCompatibilityFactory(versionCompatibilityService: VersionCompatibilityService) {
return () => versionCompatibilityService; return () => versionCompatibilityService;
} }
@@ -95,7 +95,8 @@ export class AlfrescoViewerComponent implements OnChanges, OnInit, OnDestroy {
@Input() @Input()
showViewer = true; showViewer = true;
/** Number of times the Viewer will retry fetching content Rendition. /**
* Number of times the Viewer will retry fetching content Rendition.
* There is a delay of at least one second between attempts. * There is a delay of at least one second between attempts.
*/ */
@Input() @Input()
@@ -109,13 +110,15 @@ export class AlfrescoViewerComponent implements OnChanges, OnInit, OnDestroy {
@Input() @Input()
showToolbar = true; showToolbar = true;
/** If `true` then show the Viewer as a full page over the current content. /**
* If `true` then show the Viewer as a full page over the current content.
* Otherwise fit inside the parent div. * Otherwise fit inside the parent div.
*/ */
@Input() @Input()
overlayMode = false; overlayMode = false;
/** Toggles before/next navigation. You can use the arrow buttons to navigate /**
* Toggles before/next navigation. You can use the arrow buttons to navigate
* between documents in the collection. * between documents in the collection.
*/ */
@Input() @Input()
@@ -19,27 +19,6 @@ import { ObjectDataTableAdapter, AlfrescoApiService, LogService } from '@alfresc
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { WebscriptApi } from '@alfresco/js-api'; import { WebscriptApi } from '@alfresco/js-api';
/**
* <adf-webscript-get [scriptPath]="string"
* [scriptArgs]="Object"
* [contextRoot]="string"
* [servicePath]="string"
* [contentType]="JSON|HTML|DATATABLE"
* (success)="customMethod($event)>
* </adf-webscript-get>
*
* This component, provide a get webscript viewer
*
* @InputParam {string} scriptPath path to Web Script (as defined by Web Script)
* @InputParam {Object} scriptArgs arguments to pass to Web Script
* @InputParam {string} contextRoot path where application is deployed default value 'alfresco'
* @InputParam {string} servicePath path where Web Script service is mapped default value 'service'
* @InputParam {string} contentType JSON | HTML | DATATABLE | TEXT
*
* @Output - success - The event is emitted when the data are received
*
*/
/** /**
* @deprecated Webscript component has never been turned into a product and has no UI/UX and no use cases in ACA/ADW/ACC. * @deprecated Webscript component has never been turned into a product and has no UI/UX and no use cases in ACA/ADW/ACC.
*/ */
@@ -75,13 +54,15 @@ export class WebscriptComponent implements OnChanges {
@Input() @Input()
servicePath: string = 'service'; servicePath: string = 'service';
/** Content type to interpret the data received from the webscript. /**
* Content type to interpret the data received from the webscript.
* Can be "JSON" , "HTML" , "DATATABLE" or "TEXT" * Can be "JSON" , "HTML" , "DATATABLE" or "TEXT"
*/ */
@Input() @Input()
contentType: string = 'TEXT'; contentType: string = 'TEXT';
/** Emitted when the operation succeeds. You can get the plain data from /**
* Emitted when the operation succeeds. You can get the plain data from
* the webscript through the **success** event parameter and use it as you * the webscript through the **success** event parameter and use it as you
* need in your application. * need in your application.
*/ */
@@ -124,8 +105,7 @@ export class WebscriptComponent implements OnChanges {
/** /**
* show the data in a ng2-alfresco-datatable * show the data in a ng2-alfresco-datatable
* *
* @param data * @param data data
*
* @returns the data as datatable * @returns the data as datatable
*/ */
showDataAsDataTable(data: any) { showDataAsDataTable(data: any) {
@@ -54,6 +54,7 @@ export class AppExtensionService {
* The result is filtered by the **disabled** state. * The result is filtered by the **disabled** state.
* *
* @param key Preset key. * @param key Preset key.
* @returns list of document list presets
*/ */
getDocumentListPreset(key: string): DocumentListPresetRef[] { getDocumentListPreset(key: string): DocumentListPresetRef[] {
return this.extensionService return this.extensionService
@@ -66,6 +67,8 @@ export class AppExtensionService {
/** /**
* Provides a list of the Viewer content extensions, * Provides a list of the Viewer content extensions,
* filtered by **disabled** state and **rules**. * filtered by **disabled** state and **rules**.
*
* @returns list of viewer extension references
*/ */
getViewerExtensions(): ViewerExtensionRef[] { getViewerExtensions(): ViewerExtensionRef[] {
return this.extensionService return this.extensionService
@@ -84,6 +84,11 @@ export class ExtensionLoaderService {
* Filters element by **enabled** and **order** attributes. * Filters element by **enabled** and **order** attributes.
* Example: * Example:
* `getElements<ViewerExtensionRef>(config, 'features.viewer.content')` * `getElements<ViewerExtensionRef>(config, 'features.viewer.content')`
*
* @param config configuration settings
* @param key element key
* @param fallback fallback array of values
* @returns list of elements
*/ */
getElements<T extends ExtensionElement>( getElements<T extends ExtensionElement>(
config: ExtensionConfig, config: ExtensionConfig,
@@ -28,6 +28,11 @@ import { ExtensionElement } from '../config/extension-element';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
/**
* The default extensions factory
*
* @returns the list of extension json files
*/
export function extensionJsonsFactory() { export function extensionJsonsFactory() {
return []; return [];
}; };
@@ -38,6 +43,12 @@ export const EXTENSION_JSONS = new InjectionToken<string[][]>('extension-jsons',
}); });
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
/**
* Provides the extension json values for the angular modules
*
* @param jsons files to provide
* @returns a provider section
*/
export function provideExtensionConfig(jsons: string[]) { export function provideExtensionConfig(jsons: string[]) {
return { return {
provide: EXTENSION_JSONS, provide: EXTENSION_JSONS,
@@ -80,6 +80,8 @@ export class AnalyticsReportListComponent implements OnInit {
/** /**
* Reload the component * Reload the component
*
* @param reportId report id
*/ */
reload(reportId?: number) { reload(reportId?: number) {
this.reset(); this.reset();
@@ -88,8 +90,11 @@ export class AnalyticsReportListComponent implements OnInit {
/** /**
* Get the report list * Get the report list
*
* @param appId application id
* @param reportId report id
*/ */
getReportList(appId: number, reportId?: number) { getReportList(appId: number, reportId?: number): void {
this.analyticsService.getReportList(appId).subscribe( this.analyticsService.getReportList(appId).subscribe(
(res: ReportParametersModel[]) => { (res: ReportParametersModel[]) => {
if (res && res.length === 0) { if (res && res.length === 0) {
@@ -133,6 +138,8 @@ export class AnalyticsReportListComponent implements OnInit {
/** /**
* Check if the report list is empty * Check if the report list is empty
*
* @returns `true` if report list is empty, otherwise `false`
*/ */
isReportsEmpty(): boolean { isReportsEmpty(): boolean {
return this.reports === undefined || (this.reports && this.reports.length === 0); return this.reports === undefined || (this.reports && this.reports.length === 0);
@@ -141,7 +148,7 @@ export class AnalyticsReportListComponent implements OnInit {
/** /**
* Select the current report * Select the current report
* *
* @param report * @param report report model
*/ */
selectReport(report: any) { selectReport(report: any) {
this.currentReport = report; this.currentReport = report;
@@ -51,6 +51,9 @@ export class AnalyticsService {
/** /**
* Retrieve all the Deployed app * Retrieve all the Deployed app
*
* @param appId application id
* @returns list or report parameter models
*/ */
getReportList(appId: number): Observable<ReportParametersModel[]> { getReportList(appId: number): Observable<ReportParametersModel[]> {
return from(this.reportApi.getReportList()) return from(this.reportApi.getReportList())
@@ -72,7 +75,8 @@ export class AnalyticsService {
/** /**
* Retrieve Report by name * Retrieve Report by name
* *
* @param reportName - string - The name of report * @param reportName - The name of report
* @returns report model
*/ */
getReportByName(reportName: string): Observable<any> { getReportByName(reportName: string): Observable<any> {
return from(this.reportApi.getReportList()) return from(this.reportApi.getReportList())
@@ -46,7 +46,7 @@ export class DocumentListPage {
await this.dataTable.selectRow('Display name', nodeName); await this.dataTable.selectRow('Display name', nodeName);
} }
/** @deprecated Use Playwright API instead */ // @deprecated Use Playwright API instead
async selectRowsWithKeyboard(...contentNames: string[]): Promise<void> { async selectRowsWithKeyboard(...contentNames: string[]): Promise<void> {
let option: any; let option: any;
await browser.actions().sendKeys(protractor.Key.COMMAND).perform(); await browser.actions().sendKeys(protractor.Key.COMMAND).perform();
@@ -21,7 +21,6 @@ import { StringUtil } from '../../../shared/utils/string.util';
* Create tenant JSON Object * Create tenant JSON Object
* *
* @param details - JSON object used to overwrite the default values * @param details - JSON object used to overwrite the default values
* @constructor
*/ */
export class Tenant { export class Tenant {
@@ -132,20 +132,20 @@ export class DataTableComponentPage {
/** /**
* Check the list is sorted. * Check the list is sorted.
* *
* @param sortOrder: 'ASC' if the list is await expected to be sorted ascending and 'DESC' for descending * @param sortOrder 'ASC' if the list is await expected to be sorted ascending and 'DESC' for descending
* @param columnTitle: titleColumn column * @param columnTitle titleColumn column
* @param listType: 'string' for string typed lists and 'number' for number typed (int, float) lists * @param listType 'string' for string typed lists and 'number' for number typed (int, float) lists
* @return 'true' if the list is sorted as await expected and 'false' if it isn't * @returns 'true' if the list is sorted as await expected and 'false' if it isn't
*/ */
async checkListIsSorted(sortOrder: string, columnTitle: string, listType: string = 'STRING'): Promise<any> { async checkListIsSorted(sortOrder: string, columnTitle: string, listType: string = 'STRING'): Promise<any> {
const column = $$(`div.adf-datatable-cell[title='${columnTitle}'] span`); const column = $$(`div.adf-datatable-cell[title='${columnTitle}'] span`);
await BrowserVisibility.waitUntilElementIsVisible(column.first()); await BrowserVisibility.waitUntilElementIsVisible(column.first());
const initialList = []; const initialList: string[] = [];
const length = await column.count(); const length = await column.count();
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
const text = await BrowserActions.getText(column.get(i)); const text: string = await BrowserActions.getText(column.get(i));
if (text.length !== 0) { if (text.length !== 0) {
initialList.push(text.toLowerCase()); initialList.push(text.toLowerCase());
} }
@@ -155,7 +155,7 @@ export class DataTableComponentPage {
if (listType.toLocaleLowerCase() === 'string') { if (listType.toLocaleLowerCase() === 'string') {
sortedList = sortedList.sort(); sortedList = sortedList.sort();
} else if (listType.toLocaleLowerCase() === 'number') { } else if (listType.toLocaleLowerCase() === 'number') {
sortedList = sortedList.sort((a, b) => a - b); sortedList = sortedList.sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
} else if (listType.toLocaleLowerCase() === 'priority') { } else if (listType.toLocaleLowerCase() === 'priority') {
sortedList = sortedList.sort(this.sortPriority); sortedList = sortedList.sort(this.sortPriority);
} }
@@ -259,7 +259,7 @@ export class DataTableComponentPage {
await BrowserVisibility.waitUntilElementIsVisible(this.tableBody); await BrowserVisibility.waitUntilElementIsVisible(this.tableBody);
} }
/** @deprecated Use Playwright API instead */ // @deprecated Use Playwright API instead
async getFirstElementDetail(detail: string): Promise<string> { async getFirstElementDetail(detail: string): Promise<string> {
const firstNode = $$(`adf-datatable div[title="${detail}"] span`).first(); const firstNode = $$(`adf-datatable div[title="${detail}"] span`).first();
return BrowserActions.getText(firstNode); return BrowserActions.getText(firstNode);
@@ -268,7 +268,8 @@ export class DataTableComponentPage {
/** /**
* Sort the list by name column. * Sort the list by name column.
* *
* @param sortOrder : 'ASC' to sort the list ascendant and 'DESC' for descendant * @param sortOrder 'ASC' to sort the list ascendant and 'DESC' for descendant
* @param titleColumn column title
*/ */
async sortByColumn(sortOrder: string, titleColumn: string): Promise<void> { async sortByColumn(sortOrder: string, titleColumn: string): Promise<void> {
const locator = $(`div[data-automation-id="auto_id_${titleColumn}"]`); const locator = $(`div[data-automation-id="auto_id_${titleColumn}"]`);
@@ -327,7 +328,7 @@ export class DataTableComponentPage {
return this.rootElement.all(by.xpath(`//div[starts-with(@title, '${columnName}')]//div[contains(@data-automation-id, '${columnValue}')]//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]`)).first(); return this.rootElement.all(by.xpath(`//div[starts-with(@title, '${columnName}')]//div[contains(@data-automation-id, '${columnValue}')]//ancestor::adf-datatable-row[contains(@class, 'adf-datatable-row')]`)).first();
} }
/** @deprecated use Playwright instead **/ // @deprecated use Playwright instead
getRowByIndex(index: number): ElementFinder { getRowByIndex(index: number): ElementFinder {
return this.rootElement.element(by.xpath(`//div[contains(@class,'adf-datatable-body')]//adf-datatable-row[contains(@class,'adf-datatable-row')][${index}]`)); return this.rootElement.element(by.xpath(`//div[contains(@class,'adf-datatable-body')]//adf-datatable-row[contains(@class,'adf-datatable-row')][${index}]`));
} }
@@ -400,7 +401,7 @@ export class DataTableComponentPage {
} }
} }
/** @deprecated use Playwright instead **/ // @deprecated use Playwright instead
async isColumnDisplayed(columnTitle: string): Promise<boolean> { async isColumnDisplayed(columnTitle: string): Promise<boolean> {
const isColumnDisplayed = (await this.allColumns).some( const isColumnDisplayed = (await this.allColumns).some(
async column => { async column => {
@@ -412,7 +413,7 @@ export class DataTableComponentPage {
return isColumnDisplayed; return isColumnDisplayed;
} }
/** @deprecated use Playwright instead **/ // @deprecated use Playwright instead
async getNumberOfColumns(): Promise<number> { async getNumberOfColumns(): Promise<number> {
return this.allColumns.count(); return this.allColumns.count();
} }
@@ -30,6 +30,7 @@ export class TestElement {
* Create a new instance with the element located by the id * Create a new instance with the element located by the id
* *
* @param id The id of the element * @param id The id of the element
* @returns test element wrapper
*/ */
static byId(id: string): TestElement { static byId(id: string): TestElement {
return new TestElement(element(by.id(id))); return new TestElement(element(by.id(id)));
@@ -39,6 +40,7 @@ export class TestElement {
* Create a new instance with the element located by the CSS class name * Create a new instance with the element located by the CSS class name
* *
* @param selector The CSS class name to lookup * @param selector The CSS class name to lookup
* @returns test element wrapper
*/ */
static byCss(selector: string): TestElement { static byCss(selector: string): TestElement {
return new TestElement($(selector)); return new TestElement($(selector));
@@ -49,6 +51,7 @@ export class TestElement {
* *
* @param selector the CSS selector * @param selector the CSS selector
* @param text the text within the target element * @param text the text within the target element
* @returns test element wrapper
*/ */
static byText(selector: string, text: string): TestElement { static byText(selector: string, text: string): TestElement {
return new TestElement(element(by.cssContainingText(selector, text))); return new TestElement(element(by.cssContainingText(selector, text)));
@@ -58,6 +61,7 @@ export class TestElement {
* Create a new instance with the element with specific HTML tag name * Create a new instance with the element with specific HTML tag name
* *
* @param selector the HTML tag name * @param selector the HTML tag name
* @returns test element wrapper
*/ */
static byTag(selector: string): TestElement { static byTag(selector: string): TestElement {
return new TestElement(element(by.tagName(selector))); return new TestElement(element(by.tagName(selector)));
@@ -186,6 +190,8 @@ export class TestElement {
/** /**
* Gets the `value` attribute for the given input element * Gets the `value` attribute for the given input element
*
* @returns input value
*/ */
getInputValue(): Promise<string> { getInputValue(): Promise<string> {
return BrowserActions.getInputValue(this.elementFinder); return BrowserActions.getInputValue(this.elementFinder);
@@ -20,9 +20,9 @@ export class ArrayUtil {
/** /**
* Returns TRUE if the first array contains all elements from the second one. * Returns TRUE if the first array contains all elements from the second one.
* *
* @param superset * @param superset source array
* @param subset * @param subset target array
* * @returns `true` if array is included, otherwise `false`
*/ */
static arrayContainsArray(superset: any[], subset: any[]): boolean { static arrayContainsArray(superset: any[], subset: any[]): boolean {
if (0 === subset.length) { if (0 === subset.length) {
@@ -22,6 +22,8 @@ import { ElementFinder, browser } from 'protractor';
* *
* @example ```const item = byCss`.adf-breadcrumb-item-current`;``` * @example ```const item = byCss`.adf-breadcrumb-item-current`;```
* @example ```const item = byCss`${variable}`;``` * @example ```const item = byCss`${variable}`;```
* @param literals literals
* @param placeholders placeholders
* @returns Instance of `ElementFinder` type. * @returns Instance of `ElementFinder` type.
*/ */
export const byCss = (literals: TemplateStringsArray, ...placeholders: string[]): ElementFinder => { export const byCss = (literals: TemplateStringsArray, ...placeholders: string[]): ElementFinder => {
@@ -47,6 +47,8 @@ export class ApiService {
/** /**
* Login using one of the account profiles from the `browser.params.testConfig`. * Login using one of the account profiles from the `browser.params.testConfig`.
* Example: loginWithProfile('admin') * Example: loginWithProfile('admin')
*
* @param profileName profile name
*/ */
async loginWithProfile(profileName: string): Promise<void> { async loginWithProfile(profileName: string): Promise<void> {
const profile = this.config.users[profileName]; const profile = this.config.users[profileName];
@@ -64,7 +66,7 @@ export class ApiService {
} }
} }
/** @deprecated */ // @deprecated
async performBpmOperation(path: string, method: string, queryParams: any, postBody: any): Promise<any> { async performBpmOperation(path: string, method: string, queryParams: any, postBody: any): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const uri = this.config.appConfig.hostBpm + path; const uri = this.config.appConfig.hostBpm + path;
@@ -85,7 +87,7 @@ export class ApiService {
}); });
} }
/** @deprecated */ // @deprecated
async performIdentityOperation(path: string, method: string, queryParams: any, postBody: any): Promise<any> { async performIdentityOperation(path: string, method: string, queryParams: any, postBody: any): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const uri = this.config.appConfig.oauth2.host.replace('/realms', '/admin/realms') + path; const uri = this.config.appConfig.oauth2.host.replace('/realms', '/admin/realms') + path;
@@ -106,7 +108,7 @@ export class ApiService {
}); });
} }
/** @deprecated */ // @deprecated
async performECMOperation(path: string, method: string, queryParams: any, postBody: any): Promise<any> { async performECMOperation(path: string, method: string, queryParams: any, postBody: any): Promise<any> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const uri = this.config.appConfig.hostEcm + path; const uri = this.config.appConfig.hostEcm + path;
+20 -10
View File
@@ -30,6 +30,7 @@ export class StringUtil {
* Generates a random string. * Generates a random string.
* *
* @param length If this parameter is not provided the length is set to 8 by default. * @param length If this parameter is not provided the length is set to 8 by default.
* @returns random string
*/ */
static generateRandomString(length: number = 8): string { static generateRandomString(length: number = 8): string {
return StringUtil.generateRandomCharset(length, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'); return StringUtil.generateRandomCharset(length, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
@@ -39,6 +40,7 @@ export class StringUtil {
* Generates a random lowercase string. * Generates a random lowercase string.
* *
* @param length If this parameter is not provided the length is set to 8 by default. * @param length If this parameter is not provided the length is set to 8 by default.
* @returns random string
*/ */
static generateRandomLowercaseString(length: number = 8): string { static generateRandomLowercaseString(length: number = 8): string {
return StringUtil.generateRandomCharset(length, 'abcdefghijklmnopqrstuvwxyz0123456789'); return StringUtil.generateRandomCharset(length, 'abcdefghijklmnopqrstuvwxyz0123456789');
@@ -47,8 +49,9 @@ export class StringUtil {
/** /**
* Generates a random email address following the format: abcdef@activiti.test.com * Generates a random email address following the format: abcdef@activiti.test.com
* *
* @param domain * @param domain email domain
* @param length * @param length email length
* @returns email address
*/ */
static generateRandomEmail(domain: string, length: number = 5): string { static generateRandomEmail(domain: string, length: number = 5): string {
let email = StringUtil.generateRandomCharset(length, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'); let email = StringUtil.generateRandomCharset(length, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');
@@ -59,7 +62,8 @@ export class StringUtil {
/** /**
* Generates a random string - digits only. * Generates a random string - digits only.
* *
* @param length {int} If this parameter is not provided the length is set to 8 by default. * @param length If this parameter is not provided the length is set to 8 by default.
* @returns random string
*/ */
static generateRandomStringDigits(length: number = 8): string { static generateRandomStringDigits(length: number = 8): string {
return StringUtil.generateRandomCharset(length, '0123456789'); return StringUtil.generateRandomCharset(length, '0123456789');
@@ -68,7 +72,8 @@ export class StringUtil {
/** /**
* Generates a random string - non-latin characters only. * Generates a random string - non-latin characters only.
* *
* @param length {int} If this parameter is not provided the length is set to 3 by default. * @param length If this parameter is not provided the length is set to 3 by default.
* @returns random string
*/ */
static generateRandomStringNonLatin(length: number = 3): string { static generateRandomStringNonLatin(length: number = 3): string {
return StringUtil.generateRandomCharset(length, '密码你好𠮷'); return StringUtil.generateRandomCharset(length, '密码你好𠮷');
@@ -79,6 +84,7 @@ export class StringUtil {
* *
* @param length If this parameter is not provided the length is set to 8 by default. * @param length If this parameter is not provided the length is set to 8 by default.
* @param charSet to use * @param charSet to use
* @returns random string
*/ */
static generateRandomCharset(length: number = 8, charSet: string): string { static generateRandomCharset(length: number = 8, charSet: string): string {
let text = ''; let text = '';
@@ -93,11 +99,11 @@ export class StringUtil {
/** /**
* Generates a sequence of files with name: baseName + index + extension (e.g.) baseName1.txt, baseName2.txt, ... * Generates a sequence of files with name: baseName + index + extension (e.g.) baseName1.txt, baseName2.txt, ...
* *
* @param startIndex * @param startIndex start index
* @param endIndex * @param endIndex end index
* @param baseName the base name of all files * @param baseName the base name of all files
* @param extension the extension of the file * @param extension the extension of the file
* @return fileNames * @returns list of file names
*/ */
static generateFilesNames(startIndex: number, endIndex: number, baseName: string, extension: string): string [] { static generateFilesNames(startIndex: number, endIndex: number, baseName: string, extension: string): string [] {
const fileNames: string[] = []; const fileNames: string[] = [];
@@ -107,17 +113,21 @@ export class StringUtil {
return fileNames; return fileNames;
} }
/** Generates a random name for a process /**
* Generates a random name for a process
* *
* @param length {int} If this parameter is not provided the length is set to 5 by default. * @param length {int} If this parameter is not provided the length is set to 5 by default.
* @returns process name
*/ */
static generateProcessName(length: number = 5): string { static generateProcessName(length: number = 5): string {
return 'process_' + StringUtil.generateRandomString(length); return 'process_' + StringUtil.generateRandomString(length);
} }
/** Generates a random name for a process /**
* Generates a random name for a user task
* *
* @param length {int} If this parameter is not provided the length is set to 5 by default. * @param length If this parameter is not provided the length is set to 5 by default.
* @returns task name
*/ */
static generateUserTaskName(length: number = 5): string { static generateUserTaskName(length: number = 5): string {
return 'userTask_' + StringUtil.generateRandomString(length); return 'userTask_' + StringUtil.generateRandomString(length);