[ACS-12441] Migrate ACA to Angular 21

# Conflicts:
#	package-lock.json
#	package.json
This commit is contained in:
Mykyta Maliarchuk
2026-09-11 14:18:27 +02:00
parent b88d47f486
commit 31dc5faff8
91 changed files with 4011 additions and 3315 deletions
+2 -2
View File
@@ -22,7 +22,7 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>. * from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { enableProdMode } from '@angular/core'; import { enableProdMode, provideZoneChangeDetection } from '@angular/core';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
import { bootstrapApplication } from '@angular/platform-browser'; import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.components'; import { AppComponent } from './app/app.components';
@@ -33,5 +33,5 @@ if (environment.production) {
} }
void (async () => { void (async () => {
await bootstrapApplication(AppComponent, AppConfig); await bootstrapApplication(AppComponent, { ...AppConfig, providers: [provideZoneChangeDetection(), ...AppConfig.providers] });
})(); })();
+2682 -2040
View File
File diff suppressed because it is too large Load Diff
+26 -26
View File
@@ -47,24 +47,24 @@
"@alfresco/adf-extensions": "9.2.0-34565123147", "@alfresco/adf-extensions": "9.2.0-34565123147",
"@alfresco/eslint-plugin-eslint-angular": "9.2.0-34565123147", "@alfresco/eslint-plugin-eslint-angular": "9.2.0-34565123147",
"@alfresco/js-api": "10.2.0-34565123147", "@alfresco/js-api": "10.2.0-34565123147",
"@angular/animations": "20.3.27", "@angular/animations": "21.2.9",
"@angular/cdk": "20.2.14", "@angular/cdk": "21.2.9",
"@angular/common": "20.3.27", "@angular/common": "21.2.9",
"@angular/compiler": "20.3.27", "@angular/compiler": "21.2.9",
"@angular/core": "20.3.27", "@angular/core": "21.2.9",
"@angular/forms": "20.3.27", "@angular/forms": "21.2.9",
"@angular/material": "20.2.14", "@angular/material": "21.2.9",
"@angular/material-date-fns-adapter": "20.2.14", "@angular/material-date-fns-adapter": "21.2.9",
"@angular/platform-browser": "20.3.27", "@angular/platform-browser": "21.2.9",
"@angular/platform-browser-dynamic": "20.3.27", "@angular/platform-browser-dynamic": "21.2.9",
"@angular/router": "20.3.27", "@angular/router": "21.2.9",
"@fontsource/open-sans": "^5.1.0", "@fontsource/open-sans": "^5.1.0",
"@mat-datetimepicker/core": "16.0.1", "@mat-datetimepicker/core": "16.0.1",
"@ngrx/effects": "~20.1.0", "@ngrx/effects": "21.1.1",
"@ngrx/operators": "~20.1.0", "@ngrx/operators": "21.1.1",
"@ngrx/router-store": "~20.1.0", "@ngrx/router-store": "21.1.1",
"@ngrx/store": "~20.1.0", "@ngrx/store": "21.1.1",
"@ngrx/store-devtools": "~20.1.0", "@ngrx/store-devtools": "21.1.1",
"@ngx-translate/core": "^17.0.0", "@ngx-translate/core": "^17.0.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"material-icons": "^1.13.12", "material-icons": "^1.13.12",
@@ -80,16 +80,16 @@
}, },
"devDependencies": { "devDependencies": {
"@alfresco/adf-cli": "9.2.0-34565123147", "@alfresco/adf-cli": "9.2.0-34565123147",
"@angular-devkit/build-angular": "20.3.35", "@angular-devkit/build-angular": "21.2.9",
"@angular-devkit/core": "20.3.16", "@angular-devkit/core": "21.2.9",
"@angular-devkit/schematics": "20.3.16", "@angular-devkit/schematics": "21.2.9",
"@angular-eslint/builder": "20.7.0", "@angular-eslint/builder": "21.4.0",
"@angular-eslint/eslint-plugin": "20.7.0", "@angular-eslint/eslint-plugin": "21.4.0",
"@angular-eslint/eslint-plugin-template": "20.7.0", "@angular-eslint/eslint-plugin-template": "21.4.0",
"@angular-eslint/schematics": "20.7.0", "@angular-eslint/schematics": "21.4.0",
"@angular-eslint/template-parser": "20.7.0", "@angular-eslint/template-parser": "21.4.0",
"@angular/compiler-cli": "20.3.27", "@angular/compiler-cli": "21.2.9",
"@angular/language-service": "20.3.27", "@angular/language-service": "21.2.9",
"@cspell/eslint-plugin": "^10.0.1", "@cspell/eslint-plugin": "^10.0.1",
"@nx/angular": "23.1.2", "@nx/angular": "23.1.2",
"@nx/eslint-plugin": "23.1.2", "@nx/eslint-plugin": "23.1.2",
@@ -12,29 +12,37 @@
<div class="aca-page-layout-content aca-scrollable"> <div class="aca-page-layout-content aca-scrollable">
<adf-about> <adf-about>
<adf-about-panel *ngIf="dev" [label]="'ABOUT.SERVER_SETTINGS.TITLE' | translate"> @if (dev) {
<ng-template> <adf-about-panel [label]="'ABOUT.SERVER_SETTINGS.TITLE' | translate">
<ng-template>
<adf-about-server-settings /> <adf-about-server-settings />
</ng-template> </ng-template>
</adf-about-panel> </adf-about-panel>
}
<adf-about-panel [label]="'ABOUT.REPOSITORY' | translate" *ngIf="repository"> @if (repository) {
<ng-template> <adf-about-panel [label]="'ABOUT.REPOSITORY' | translate">
<ng-template>
<adf-about-repository-info [data]="repository" /> <adf-about-repository-info [data]="repository" />
</ng-template> </ng-template>
</adf-about-panel> </adf-about-panel>
}
<adf-about-panel *ngIf="dev" [label]="'ABOUT.PACKAGES.TITLE' | translate"> @if (dev) {
<ng-template> <adf-about-panel [label]="'ABOUT.PACKAGES.TITLE' | translate">
<ng-template>
<adf-about-package-list [dependencies]="packageJson?.dependencies" /> <adf-about-package-list [dependencies]="packageJson?.dependencies" />
</ng-template> </ng-template>
</adf-about-panel> </adf-about-panel>
}
<adf-about-panel *ngIf="extensions$ | async as extensions" [label]="'ABOUT.PLUGINS.TITLE' | translate"> @if (extensions$ | async; as extensions) {
<ng-template> <adf-about-panel [label]="'ABOUT.PLUGINS.TITLE' | translate">
<ng-template>
<adf-about-extension-list [data]="extensions" /> <adf-about-extension-list [data]="extensions" />
</ng-template> </ng-template>
</adf-about-panel> </adf-about-panel>
}
</adf-about> </adf-about>
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -10,19 +10,15 @@
<div class="aca-page-layout-content"> <div class="aca-page-layout-content">
<div class="aca-main-content"> <div class="aca-main-content">
<ng-container *ngIf="((ruleSetsLoading$ | async) && (inheritedRuleSets$ | async).length === 0) || (actionsLoading$ | async); else onLoaded"> @if (((ruleSetsLoading$ | async) && (inheritedRuleSets$ | async).length === 0) || (actionsLoading$ | async)) {
<mat-progress-bar mode="indeterminate" /> <mat-progress-bar mode="indeterminate" />
</ng-container> } @else {
@if (folderInfo$ | async) {
<ng-template #onLoaded>
<ng-container *ngIf="folderInfo$ | async; else genericError">
<mat-toolbar class="aca-manage-rules__toolbar aca-manage-rules__actions-bar"> <mat-toolbar class="aca-manage-rules__toolbar aca-manage-rules__actions-bar">
<span class="aca-manage-rules__actions-bar__title"> <span class="aca-manage-rules__actions-bar__title">
<mat-icon class="icon-aligner">folder</mat-icon> <mat-icon class="icon-aligner">folder</mat-icon>
<span class="aca-page-title">{{ (folderInfo$ | async).name }}:{{'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.BREADCRUMB.RULES' | translate}}</span> <span class="aca-page-title">{{ (folderInfo$ | async).name }}:{{'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.BREADCRUMB.RULES' | translate}}</span>
</span> </span>
<mat-slide-toggle <mat-slide-toggle
data-automation-id="manage-rules-inheritance-toggle-button" data-automation-id="manage-rules-inheritance-toggle-button"
class="aca-manage-rules__actions-bar__toggle" class="aca-manage-rules__actions-bar__toggle"
@@ -32,104 +28,96 @@
[labelPosition]="'before'"> [labelPosition]="'before'">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.INHERIT_RULES' | translate }} {{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.INHERIT_RULES' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-divider vertical class="aca-manage-rules__actions-bar__vertical-divider" aria-hidden="true" /> <mat-divider vertical class="aca-manage-rules__actions-bar__vertical-divider" aria-hidden="true" />
<div class="aca-manage-rules__actions-bar__buttons"> <div class="aca-manage-rules__actions-bar__buttons">
<button @if (!(mainRuleSet$ | async)) {
*ngIf="!(mainRuleSet$ | async)" <button
data-automation-id="manage-rules-link-button" data-automation-id="manage-rules-link-button"
mat-stroked-button mat-stroked-button
(click)="openLinkRulesDialog()"> (click)="openLinkRulesDialog()">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.LINK_RULES' | translate }} {{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.LINK_RULES' | translate }}
</button> </button>
}
<button @if (canEditMainRule) {
*ngIf="canEditMainRule" <button
data-automation-id="manage-rules-create-button" data-automation-id="manage-rules-create-button"
mat-flat-button mat-flat-button
(click)="openCreateUpdateRuleDialog()"> (click)="openCreateUpdateRuleDialog()">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.CREATE_RULE' | translate }} {{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.CREATE_RULE' | translate }}
</button> </button>
}
</div> </div>
</mat-toolbar> </mat-toolbar>
<mat-divider aria-hidden="true" /> <mat-divider aria-hidden="true" />
@if (isMainRuleSetNotEmpty || isInheritedRuleSetsNotEmpty) {
<div class="aca-manage-rules__container" *ngIf="isMainRuleSetNotEmpty || isInheritedRuleSetsNotEmpty; else emptyContent"> <div class="aca-manage-rules__container">
<aca-rule-list <aca-rule-list
[mainRuleSet$]="mainRuleSet$" [mainRuleSet$]="mainRuleSet$"
[folderId]="nodeId" [folderId]="nodeId"
[inheritedRuleSets]="inheritedRuleSets$ | async" [inheritedRuleSets]="inheritedRuleSets$ | async"
[hasMoreRuleSets]="hasMoreRuleSets$ | async" [hasMoreRuleSets]="hasMoreRuleSets$ | async"
[ruleSetsLoading]="ruleSetsLoading$ | async" [ruleSetsLoading]="ruleSetsLoading$ | async"
[selectedRule]="selectedRule$ | async" [selectedRule]="selectedRule$ | async"
(loadMoreRuleSets)="onLoadMoreRuleSets()" (loadMoreRuleSets)="onLoadMoreRuleSets()"
(loadMoreRules)="onLoadMoreRules($event)" (loadMoreRules)="onLoadMoreRules($event)"
(selectRule)="onSelectRule($event)" (selectRule)="onSelectRule($event)"
(ruleEnabledChanged)="onRuleEnabledToggle($event[0], $event[1])" (ruleEnabledChanged)="onRuleEnabledToggle($event[0], $event[1])"
(ruleSetEditLinkClicked)="openLinkRulesDialog($event)" (ruleSetEditLinkClicked)="openLinkRulesDialog($event)"
(ruleSetUnlinkClicked)="onRuleSetUnlinkClicked($event)" /> (ruleSetUnlinkClicked)="onRuleSetUnlinkClicked($event)" />
<div class="aca-manage-rules__container__rule-details">
<div class="aca-manage-rules__container__rule-details"> @if ((selectedRule$ | async); as selectedRule) {
<div class="aca-manage-rules__container__rule-details__header">
<div class="aca-manage-rules__container__rule-details__header" *ngIf="(selectedRule$ | async) as selectedRule"> <div class="aca-manage-rules__container__rule-details__header__title">
<div class="aca-manage-rules__container__rule-details__header__title"> <div class="aca-manage-rules__container__rule-details__header__title__name">
<div class="aca-manage-rules__container__rule-details__header__title__name"> {{ selectedRule.name }}
{{ selectedRule.name }} </div>
<div class="aca-manage-rules__container__rule-details__header__title__description">
{{ selectedRule.description }}
</div>
</div>
<div class="aca-manage-rules__container__rule-details__header__buttons">
@if (canEditSelectedRule) {
<button mat-stroked-button (click)="onRuleDeleteButtonClicked(selectedRule)" id="delete-rule-btn"
[attr.aria-label]="'ACA_FOLDER_RULES.CONFIRMATION_DIALOG.DELETE_RULE.TITLE' | translate">
<mat-icon>delete_outline</mat-icon>
</button>
<button mat-stroked-button (click)="openCreateUpdateRuleDialog(selectedRule)" id="edit-rule-btn">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.EDIT_RULE' | translate }}
</button>
} @else {
<button mat-stroked-button [routerLink]="['/nodes', (selectedRuleSet$ | async).owningFolder.id, 'rules']">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.SEE_IN_FOLDER' | translate }}
</button>
}
</div>
</div> </div>
<div class="aca-manage-rules__container__rule-details__header__title__description"> }
{{ selectedRule.description }} @if ((selectedRule$ | async); as selectedRule) {
<div class="aca-manage-rules__container__rule-details__content">
<aca-rule-details
[actionDefinitions]="actionDefinitions$ | async"
[parameterConstraints]="parameterConstraints$ | async"
[readOnly]="true"
[preview]="true"
[value]="selectedRule"
[nodeId]="nodeId" />
</div> </div>
</div> }
<div class="aca-manage-rules__container__rule-details__header__buttons">
<ng-container *ngIf="canEditSelectedRule; else goToFolderButton">
<button mat-stroked-button (click)="onRuleDeleteButtonClicked(selectedRule)" id="delete-rule-btn"
[attr.aria-label]="'ACA_FOLDER_RULES.CONFIRMATION_DIALOG.DELETE_RULE.TITLE' | translate">
<mat-icon>delete_outline</mat-icon>
</button>
<button mat-stroked-button (click)="openCreateUpdateRuleDialog(selectedRule)" id="edit-rule-btn">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.EDIT_RULE' | translate }}
</button>
</ng-container>
<ng-template #goToFolderButton>
<button mat-stroked-button [routerLink]="['/nodes', (selectedRuleSet$ | async).owningFolder.id, 'rules']">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.SEE_IN_FOLDER' | translate }}
</button>
</ng-template>
</div>
</div>
<div class="aca-manage-rules__container__rule-details__content" *ngIf="(selectedRule$ | async) as selectedRule">
<aca-rule-details
[actionDefinitions]="actionDefinitions$ | async"
[parameterConstraints]="parameterConstraints$ | async"
[readOnly]="true"
[preview]="true"
[value]="selectedRule"
[nodeId]="nodeId" />
</div> </div>
</div> </div>
</div> } @else {
<ng-template #emptyContent>
<adf-empty-content <adf-empty-content
icon="library_books" icon="library_books"
[title]="'ACA_FOLDER_RULES.MANAGE_RULES.EMPTY_RULES_LIST.TITLE' | translate" [title]="'ACA_FOLDER_RULES.MANAGE_RULES.EMPTY_RULES_LIST.TITLE' | translate"
[subtitle]="'ACA_FOLDER_RULES.MANAGE_RULES.EMPTY_RULES_LIST.SUBTITLE' | translate" [subtitle]="'ACA_FOLDER_RULES.MANAGE_RULES.EMPTY_RULES_LIST.SUBTITLE' | translate"
/> />
</ng-template> }
</ng-container> } @else {
<ng-template #genericError>
<div class="aca-page-layout-error"> <div class="aca-page-layout-error">
<aca-generic-error /> <aca-generic-error />
</div> </div>
</ng-template> }
}
</ng-template>
</div> </div>
</div> </div>
@@ -1,33 +1,37 @@
<div class="aca-rule-action-list__item" [attr.aria-labelledby]="'rule-actions-label'" *ngFor="let control of formControls"> @for (control of formControls; track control) {
<aca-rule-action <div class="aca-rule-action-list__item" [attr.aria-labelledby]="'rule-actions-label'">
[actionDefinitions]="actionDefinitions" <aca-rule-action
[parameterConstraints]="parameterConstraints" [actionDefinitions]="actionDefinitions"
[readOnly]="readOnly" [parameterConstraints]="parameterConstraints"
[formControl]="control" [readOnly]="readOnly"
[nodeId]="nodeId" /> [formControl]="control"
[nodeId]="nodeId" />
@if (!readOnly) {
<button
mat-icon-button
data-automation-id="rule-action-list-action-menu"
[attr.aria-label]="'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.OPEN_ACTION_MENU' | translate"
[matMenuTriggerFor]="menu">
<mat-icon>more_vert</mat-icon>
</button>
}
<mat-menu #menu>
<button
mat-menu-item
data-automation-id="rule-action-list-remove-action-button"
[title]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate"
[disabled]="formControls.length <= 1"
(click)="removeAction(control)">
<mat-icon>delete</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate }}</span>
</button>
</mat-menu>
</div>
}
<button @if (!readOnly) {
mat-icon-button <button mat-flat-button class="aca-rule-action-list-add-action-button" data-automation-id="rule-action-list-add-action-button" (click)="addAction()">
data-automation-id="rule-action-list-action-menu" <mat-icon class="aca-rule-action-list-add-action-button-icon">add</mat-icon>
[attr.aria-label]="'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.OPEN_ACTION_MENU' | translate" <span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.ADD_ACTION' | translate }}</span>
*ngIf="!readOnly" [matMenuTriggerFor]="menu">
<mat-icon>more_vert</mat-icon>
</button> </button>
}
<mat-menu #menu>
<button
mat-menu-item
data-automation-id="rule-action-list-remove-action-button"
[title]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate"
[disabled]="formControls.length <= 1"
(click)="removeAction(control)">
<mat-icon>delete</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.REMOVE' | translate }}</span>
</button>
</mat-menu>
</div>
<button mat-flat-button class="aca-rule-action-list-add-action-button" data-automation-id="rule-action-list-add-action-button" (click)="addAction()" *ngIf="!readOnly">
<mat-icon class="aca-rule-action-list-add-action-button-icon">add</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_BUTTONS.ADD_ACTION' | translate }}</span>
</button>
@@ -28,7 +28,6 @@ import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { ruleActionValidator } from '../validators/rule-actions.validator'; import { ruleActionValidator } from '../validators/rule-actions.validator';
import { ActionParameterConstraint } from '../../model/action-parameter-constraint.model'; import { ActionParameterConstraint } from '../../model/action-parameter-constraint.model';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { RuleActionUiComponent } from './rule-action.ui-component'; import { RuleActionUiComponent } from './rule-action.ui-component';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -36,7 +35,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, RuleActionUiComponent, ReactiveFormsModule, MatButtonModule, MatMenuModule, MatIconModule], imports: [TranslatePipe, RuleActionUiComponent, ReactiveFormsModule, MatButtonModule, MatMenuModule, MatIconModule],
selector: 'aca-rule-action-list', selector: 'aca-rule-action-list',
templateUrl: './rule-action-list.ui-component.html', templateUrl: './rule-action-list.ui-component.html',
styleUrls: ['./rule-action-list.ui-component.scss'], styleUrls: ['./rule-action-list.ui-component.scss'],
@@ -5,20 +5,22 @@
formControlName="actionDefinitionId" formControlName="actionDefinitionId"
data-automation-id="rule-action-select" data-automation-id="rule-action-select"
[placeholder]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_SELECT_PLACEHOLDER' | translate"> [placeholder]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_SELECT_PLACEHOLDER' | translate">
<mat-option @for (actionDefinition of actionDefinitions; track actionDefinition) {
*ngFor="let actionDefinition of actionDefinitions" <mat-option
[value]="actionDefinition.id"> [value]="actionDefinition.id">
{{ actionDefinition.title }} {{ actionDefinition.title }}
</mat-option> </mat-option>
}
</mat-select> </mat-select>
<mat-error>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.ACTION_REQUIRED' | translate}}</mat-error> <mat-error>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.ACTION_REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<adf-card-view @if (cardViewItems?.length > 0) {
*ngIf="cardViewItems?.length > 0" <adf-card-view
data-automation-id="rule-action-card-view" data-automation-id="rule-action-card-view"
[properties]="cardViewItems" [properties]="cardViewItems"
class="aca-rule-action-full-width" class="aca-rule-action-full-width"
[editable]="!readOnly" /> [editable]="!readOnly" />
}
</form> </form>
@@ -51,13 +51,12 @@ import {
} from '@alfresco/adf-content-services'; } from '@alfresco/adf-content-services';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, ReactiveFormsModule, MatFormFieldModule, MatSelectModule, CardViewComponent], imports: [TranslatePipe, ReactiveFormsModule, MatFormFieldModule, MatSelectModule, CardViewComponent],
selector: 'aca-rule-action', selector: 'aca-rule-action',
templateUrl: './rule-action.ui-component.html', templateUrl: './rule-action.ui-component.html',
styleUrls: ['./rule-action.ui-component.scss'], styleUrls: ['./rule-action.ui-component.scss'],
@@ -1,72 +1,83 @@
<form class="aca-rule-composite-condition__form" [formGroup]="form"> <form class="aca-rule-composite-condition__form" [formGroup]="form">
<div *ngIf="hasNoConditions" class="aca-rule-composite-condition__form__no-conditions" data-automation-id="no-conditions"> @if (hasNoConditions) {
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.' + (childCondition ? 'NO_CONDITIONS_IN_GROUP' : 'NO_CONDITIONS') | translate }} <div class="aca-rule-composite-condition__form__no-conditions" data-automation-id="no-conditions">
</div> {{ 'ACA_FOLDER_RULES.RULE_DETAILS.' + (childCondition ? 'NO_CONDITIONS_IN_GROUP' : 'NO_CONDITIONS') | translate }}
<div *ngIf="!hasNoConditions" class="aca-rule-composite-condition__form__no-conditions" data-automation-id="label-with-conditions"> </div>
<span id="conditions-group-label-{{ childCondition ? 'nested' : 'main' }}"> }
{{ (childCondition ? 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.GROUP_CONDITIONS' : 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.CONDITIONS') | translate }} @if (!hasNoConditions) {
</span> <div class="aca-rule-composite-condition__form__no-conditions" data-automation-id="label-with-conditions">
</div> <span id="conditions-group-label-{{ childCondition ? 'nested' : 'main' }}">
{{ (childCondition ? 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.GROUP_CONDITIONS' : 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.CONDITIONS') | translate }}
</span>
</div>
}
<fieldset @for (control of conditionFormControls; track control; let i = $index) {
#conditionRow <fieldset
[attr.aria-labelledby]="'conditions-group-label-' + (childCondition ? 'nested' : 'main')" #conditionRow
class="aca-rule-composite-condition__form__row" [attr.aria-labelledby]="'conditions-group-label-' + (childCondition ? 'nested' : 'main')"
*ngFor="let control of conditionFormControls; let i = index"> class="aca-rule-composite-condition__form__row"
<mat-form-field *ngIf="i === 0"> >
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.LOGIC_OPERATOR' | translate }}</mat-label> @if (i === 0) {
<mat-select <mat-form-field>
[formControl]="invertedControl" <mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.LOGIC_OPERATOR' | translate }}</mat-label>
[disabled]="readOnly"> <mat-select
<mat-option [value]="false">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.IF' | translate }}</mat-option> [formControl]="invertedControl"
<mat-option [value]="true">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.NOT_IF' | translate }}</mat-option> [disabled]="readOnly">
</mat-select> <mat-option [value]="false">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.IF' | translate }}</mat-option>
</mat-form-field> <mat-option [value]="true">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.NOT_IF' | translate }}</mat-option>
</mat-select>
</mat-form-field>
}
@if (i > 0) {
<mat-form-field class="aca-rule-composite-condition__boolean-mode-control">
<mat-select
[formControl]="booleanModeControl">
<mat-option value="and">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.AND' | translate }}</mat-option>
<mat-option value="or">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.OR' | translate }}</mat-option>
</mat-select>
</mat-form-field>
}
@if (!isFormControlSimpleCondition(control)) {
<aca-rule-composite-condition
[secondaryBackground]="!secondaryBackground"
[childCondition]="true"
[formControl]="control"
[readOnly]="readOnly" />
}
@if (isFormControlSimpleCondition(control)) {
<aca-rule-simple-condition
[formControl]="control"
[readOnly]="readOnly" />
}
@if (!readOnly) {
<button mat-icon-button [matMenuTriggerFor]="menu" data-automation-id="condition-actions-button"
[attr.aria-label]="'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.OPEN_ACTION_MENU' | translate">
<mat-icon>more_vert</mat-icon>
</button>
}
<mat-menu #menu="matMenu">
<button
mat-menu-item
[title]="'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.REMOVE' | translate"
(click)="removeCondition(control)">
<mat-icon>delete</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.REMOVE' | translate }}</span>
</button>
</mat-menu>
</fieldset>
}
<mat-form-field *ngIf="i > 0" class="aca-rule-composite-condition__boolean-mode-control"> @if (!readOnly) {
<mat-select <div class="aca-rule-composite-condition__form__actions" data-automation-id="add-actions">
[formControl]="booleanModeControl"> <button mat-flat-button (click)="addSimpleCondition()" data-automation-id="add-condition-button">
<mat-option value="and">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.AND' | translate }}</mat-option> <mat-icon class="aca-rule-composite-condition__form__actions-add">add</mat-icon>
<mat-option value="or">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.OR' | translate }}</mat-option> <span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.ADD_CONDITION' | translate }}</span>
</mat-select>
</mat-form-field>
<aca-rule-composite-condition
*ngIf="!isFormControlSimpleCondition(control)"
[secondaryBackground]="!secondaryBackground"
[childCondition]="true"
[formControl]="control"
[readOnly]="readOnly" />
<aca-rule-simple-condition
*ngIf="isFormControlSimpleCondition(control)"
[formControl]="control"
[readOnly]="readOnly" />
<button mat-icon-button [matMenuTriggerFor]="menu" *ngIf="!readOnly" data-automation-id="condition-actions-button"
[attr.aria-label]="'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.OPEN_ACTION_MENU' | translate">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button
mat-menu-item
[title]="'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.REMOVE' | translate"
(click)="removeCondition(control)">
<mat-icon>delete</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.REMOVE' | translate }}</span>
</button> </button>
</mat-menu> <button mat-flat-button (click)="addCompositeCondition()" data-automation-id="add-group-button">
</fieldset> <mat-icon class="aca-rule-composite-condition__form__actions-add">add</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.ADD_GROUP' | translate }}</span>
<div class="aca-rule-composite-condition__form__actions" *ngIf="!readOnly" data-automation-id="add-actions"> </button>
<button mat-flat-button (click)="addSimpleCondition()" data-automation-id="add-condition-button"> </div>
<mat-icon class="aca-rule-composite-condition__form__actions-add">add</mat-icon> }
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.ADD_CONDITION' | translate }}</span>
</button>
<button mat-flat-button (click)="addCompositeCondition()" data-automation-id="add-group-button">
<mat-icon class="aca-rule-composite-condition__form__actions-add">add</mat-icon>
<span>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.CONDITION_BUTTONS.ADD_GROUP' | translate }}</span>
</button>
</div>
</form> </form>
@@ -41,7 +41,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { RuleCompositeCondition } from '../../model/rule-composite-condition.model'; import { RuleCompositeCondition } from '../../model/rule-composite-condition.model';
import { ControlValueAccessor, FormArray, FormControl, FormGroup, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms'; import { ControlValueAccessor, FormArray, FormControl, FormGroup, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model'; import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
@@ -53,7 +52,6 @@ import { FocusTrapFactory } from '@angular/cdk/a11y';
@Component({ @Component({
imports: [ imports: [
CommonModule,
TranslatePipe, TranslatePipe,
ReactiveFormsModule, ReactiveFormsModule,
MatFormFieldModule, MatFormFieldModule,
@@ -3,12 +3,16 @@
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.FIELD' | translate }}</mat-label> <mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.FIELD' | translate }}</mat-label>
<mat-select formControlName="field" data-automation-id="field-select" <mat-select formControlName="field" data-automation-id="field-select"
(selectionChange)="onChangeField()"> (selectionChange)="onChangeField()">
<mat-option *ngIf="!isSelectedFieldKnown" [value]="selectedField.name" data-automation-id="unknown-field-option"> @if (!isSelectedFieldKnown) {
{{ selectedField.label }} <mat-option [value]="selectedField.name" data-automation-id="unknown-field-option">
</mat-option> {{ selectedField.label }}
<mat-option *ngFor="let field of fields" [value]="field.name"> </mat-option>
{{ field.label | translate }} }
</mat-option> @for (field of fields; track field.name) {
<mat-option [value]="field.name">
{{ field.label | translate }}
</mat-option>
}
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
@@ -16,24 +20,27 @@
[class]="{ 'aca-hidden': isComparatorHidden }" data-automation-id="comparator-form-field"> [class]="{ 'aca-hidden': isComparatorHidden }" data-automation-id="comparator-form-field">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.COMPARATOR' | translate }}</mat-label> <mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.COMPARATOR' | translate }}</mat-label>
<mat-select formControlName="comparator" data-automation-id="comparator-select"> <mat-select formControlName="comparator" data-automation-id="comparator-select">
<mat-option @for (comparator of selectedFieldComparators; track comparator.name) {
*ngFor="let comparator of selectedFieldComparators" <mat-option [value]="comparator.name">
[value]="comparator.name"> {{ comparator.labels[this.selectedField?.type || 'equals'] | translate }}
{{ comparator.labels[this.selectedField?.type || 'equals'] | translate }} </mat-option>
</mat-option> }
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="aca-rule-simple-condition__form__field-input aca-rule-simple-condition__form__parameter-input" <mat-form-field class="aca-rule-simple-condition__form__field-input aca-rule-simple-condition__form__parameter-input">
[ngSwitch]="selectedField.type">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.VALUE' | translate }}</mat-label> <mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.VALUE' | translate }}</mat-label>
<mat-select formControlName="parameter" data-automation-id="simple-condition-value-select" *ngSwitchCase="'mimeType'"> @switch (selectedField.type) {
<mat-option *ngFor="let mimeType of mimeTypes" @case ('mimeType') {
[value]="mimeType.value"> <mat-select formControlName="parameter" data-automation-id="simple-condition-value-select">
{{ mimeType.label }} @for (mimeType of mimeTypes; track mimeType.value) {
</mat-option> <mat-option [value]="mimeType.value">
</mat-select> {{ mimeType.label }}
<ng-template [ngSwitchCase]="'auto-complete'"> </mat-option>
}
</mat-select>
}
@case ('auto-complete') {
<input <input
matInput matInput
[matAutocomplete]="auto" [matAutocomplete]="auto"
@@ -47,7 +54,8 @@
[autoActiveFirstOption]="true" [autoActiveFirstOption]="true"
[autoSelectActiveOption]="true" [autoSelectActiveOption]="true"
[displayWith]="autoCompleteDisplayFunction"> [displayWith]="autoCompleteDisplayFunction">
<mat-option disabled *ngIf="showLoadingSpinner; else optionList"> @if (showLoadingSpinner) {
<mat-option disabled>
<span class="aca-rule-simple-condition__auto-complete-loading-spinner"> <span class="aca-rule-simple-condition__auto-complete-loading-spinner">
<mat-progress-spinner <mat-progress-spinner
mode="indeterminate" mode="indeterminate"
@@ -55,24 +63,24 @@
[diameter]="25" /> [diameter]="25" />
</span> </span>
</mat-option> </mat-option>
<ng-template #optionList> } @else {
<ng-container *ngIf="autoCompleteOptions?.length > 0; else noOptionsTemplate"> @if (autoCompleteOptions?.length > 0) {
<mat-option @for (option of autoCompleteOptions; track option.value) {
*ngFor="let option of autoCompleteOptions" <mat-option [value]="option.value">
[value]="option.value"> {{ option.displayLabel }}
{{ option.displayLabel }} </mat-option>
</mat-option> }
</ng-container> } @else {
<ng-template #noOptionsTemplate>
<mat-option disabled> <mat-option disabled>
{{ 'ACA_FOLDER_RULES.AUTOCOMPLETE.NO_OPTIONS_FOUND' | translate }} {{ 'ACA_FOLDER_RULES.AUTOCOMPLETE.NO_OPTIONS_FOUND' | translate }}
</mat-option> </mat-option>
</ng-template> }
</ng-template> }
</mat-autocomplete> </mat-autocomplete>
</ng-template> }
<ng-template ngSwitchDefault> @default {
<input matInput placeholder="{{ 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.VALUE' | translate }}" type="text" formControlName="parameter" data-automation-id="value-input"> <input matInput placeholder="{{ 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.VALUE' | translate }}" type="text" formControlName="parameter" data-automation-id="value-input">
</ng-template> }
}
</mat-form-field> </mat-form-field>
</form> </form>
@@ -27,7 +27,6 @@ import { AbstractControl, ControlValueAccessor, FormControl, FormGroup, NG_VALUE
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model'; import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
import { comparatorHiddenForConditionFieldType, RuleConditionField, ruleConditionFields } from './rule-condition-fields'; import { comparatorHiddenForConditionFieldType, RuleConditionField, ruleConditionFields } from './rule-condition-fields';
import { RuleConditionComparator, ruleConditionComparators } from './rule-condition-comparators'; import { RuleConditionComparator, ruleConditionComparators } from './rule-condition-comparators';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
@@ -51,7 +50,6 @@ const AUTOCOMPLETE_OPTIONS_DEBOUNCE_TIME = 500;
@Component({ @Component({
imports: [ imports: [
CommonModule,
TranslatePipe, TranslatePipe,
ReactiveFormsModule, ReactiveFormsModule,
MatFormFieldModule, MatFormFieldModule,
@@ -1,48 +1,54 @@
<fieldset [formGroup]="form" [attr.aria-labelledby]="ariaLabelledBy"> <fieldset [formGroup]="form" [attr.aria-labelledby]="ariaLabelledBy">
<div class="aca-rule-options__option" *ngIf="!readOnly || isAsynchronousChecked"> @if (!readOnly || isAsynchronousChecked) {
<mat-checkbox <div class="aca-rule-options__option">
formControlName="isAsynchronous" <mat-checkbox
(change)="toggleErrorScriptDropdown($event)" formControlName="isAsynchronous"
class="aca-rule-options__checkbox" (change)="toggleErrorScriptDropdown($event)"
data-automation-id="rule-option-checkbox-asynchronous"> class="aca-rule-options__checkbox"
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_ASYNCHRONOUS' | translate }} data-automation-id="rule-option-checkbox-asynchronous">
</mat-checkbox> {{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_ASYNCHRONOUS' | translate }}
</mat-checkbox>
<mat-form-field <mat-form-field
data-automation-id="rule-option-form-field-errorScript" data-automation-id="rule-option-form-field-errorScript"
class="aca-rule-options__error-script-dropdown" class="aca-rule-options__error-script-dropdown"
[ngClass]="{ 'aca-hide-error-script-dropdown': hideErrorScriptDropdown }"> [ngClass]="{ 'aca-hide-error-script-dropdown': hideErrorScriptDropdown }">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ERROR_SCRIPT' | translate }}</mat-label> <mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ERROR_SCRIPT' | translate }}</mat-label>
<mat-select <mat-select
formControlName="errorScript" formControlName="errorScript"
data-automation-id="rule-option-select-errorScript"> data-automation-id="rule-option-select-errorScript">
<mat-option class="aca-rule-options__error-script-option" value="">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.NO_SCRIPT' | translate }}</mat-option>
<mat-option class="aca-rule-options__error-script-option" value="">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.NO_SCRIPT' | translate }}</mat-option> @for (option of errorScriptOptions; track option) {
<mat-option *ngFor="let option of errorScriptOptions" <mat-option
class="aca-rule-options__error-script-option" class="aca-rule-options__error-script-option"
[value]="option.value"> [value]="option.value">
{{ option.label }} {{ option.label }}
</mat-option> </mat-option>
</mat-select> }
</mat-form-field> </mat-select>
</div> </mat-form-field>
</div>
}
<div class="aca-rule-options__option" *ngIf="!readOnly || isInheritableChecked"> @if (!readOnly || isInheritableChecked) {
<mat-checkbox <div class="aca-rule-options__option">
formControlName="isInheritable" <mat-checkbox
class="aca-rule-options__checkbox" formControlName="isInheritable"
data-automation-id="rule-option-checkbox-inheritable"> class="aca-rule-options__checkbox"
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_INHERITABLE' | translate }} data-automation-id="rule-option-checkbox-inheritable">
</mat-checkbox> {{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_INHERITABLE' | translate }}
</div> </mat-checkbox>
</div>
}
<div class="aca-rule-options__option" *ngIf="!readOnly"> @if (!readOnly) {
<mat-checkbox <div class="aca-rule-options__option">
formControlName="isDisabled" <mat-checkbox
class="aca-rule-options__checkbox" formControlName="isDisabled"
data-automation-id="rule-option-checkbox-disabled"> class="aca-rule-options__checkbox"
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.DISABLE_RULE' | translate }} data-automation-id="rule-option-checkbox-disabled">
</mat-checkbox> {{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.DISABLE_RULE' | translate }}
</div> </mat-checkbox>
</div>
}
</fieldset> </fieldset>
@@ -1,6 +1,6 @@
<form class="aca-rule-details__form" [ngClass]="{ 'aca-read-only': readOnly }" [formGroup]="form"> <form class="aca-rule-details__form" [ngClass]="{ 'aca-read-only': readOnly }" [formGroup]="form">
<ng-container *ngIf="!preview"> @if (!preview) {
<div class="aca-rule-details__form__row"> <div class="aca-rule-details__form__row">
<label class="aca-rule-details__name__label" for="rule-details-name-input">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.NAME' | translate }}</label> <label class="aca-rule-details__name__label" for="rule-details-name-input">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.NAME' | translate }}</label>
<div> <div>
@@ -16,33 +16,36 @@
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<div class="aca-rule-details__form__row aca-rule-details__form__description"> <div class="aca-rule-details__form__row aca-rule-details__form__description">
<label for="rule-details-description-textarea">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.DESCRIPTION' | translate }}</label> <label for="rule-details-description-textarea">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.DESCRIPTION' | translate }}</label>
<div> <div>
<mat-form-field class="aca-rule-details__form__row__field"> <mat-form-field class="aca-rule-details__form__row__field">
<textarea <textarea
class="aca-rule-details__form__row__field__textarea" class="aca-rule-details__form__row__field__textarea"
id="rule-details-description-textarea" id="rule-details-description-textarea"
matInput formControlName="description" data-automation-id="rule-details-description-textarea" matInput formControlName="description" data-automation-id="rule-details-description-textarea"
[placeholder]="descriptionPlaceHolder | translate"> [placeholder]="descriptionPlaceHolder | translate">
</textarea> </textarea>
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
</ng-container> }
<div class="aca-rule-details__form__row aca-rule-details__form__triggers"> <div class="aca-rule-details__form__row aca-rule-details__form__triggers">
<span id="rule-triggers-label" class="aca-label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.WHEN' | translate }}</span> <span id="rule-triggers-label" class="aca-label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.WHEN' | translate }}</span>
<div> <div>
<aca-rule-triggers formControlName="triggers" data-automation-id="rule-details-triggers-component" /> <aca-rule-triggers formControlName="triggers" data-automation-id="rule-details-triggers-component" />
<mat-error class="aca-rule-details-error" *ngIf="triggers.hasError('required')">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.INSUFFICIENT_TRIGGERS_SELECTED' | translate }}</mat-error> @if (triggers.hasError('required')) {
<mat-error class="aca-rule-details-error">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.INSUFFICIENT_TRIGGERS_SELECTED' | translate }}</mat-error>
}
</div> </div>
</div> </div>
<div class="aca-rule-details__form__conditions"> <div class="aca-rule-details__form__conditions">
<aca-rule-composite-condition [readOnly]="readOnly" formControlName="conditions" /> <aca-rule-composite-condition [readOnly]="readOnly" formControlName="conditions" />
<mat-error class="aca-rule-details-error" *ngIf="conditions.hasError('ruleCompositeConditionInvalid')">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.RULE_COMPOSITE_CONDITION_INVALID' | translate }}</mat-error> @if (conditions.hasError('ruleCompositeConditionInvalid')) {
<mat-error class="aca-rule-details-error">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.RULE_COMPOSITE_CONDITION_INVALID' | translate }}</mat-error>
}
</div> </div>
<div class="aca-rule-details__form__row aca-rule-details__form__actions"> <div class="aca-rule-details__form__row aca-rule-details__form__actions">
@@ -55,12 +58,14 @@
[nodeId]="nodeId" /> [nodeId]="nodeId" />
</div> </div>
<div class="aca-rule-details__form__row aca-rule-details__form__others" *ngIf="showOptionsSection"> @if (showOptionsSection) {
<span id="rule-options-label" class="aca-label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.OPTIONS' | translate }}</span> <div class="aca-rule-details__form__row aca-rule-details__form__others">
<aca-rule-options <span id="rule-options-label" class="aca-label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.OPTIONS' | translate }}</span>
formControlName="options" <aca-rule-options
data-automation-id="rule-details-options-component" formControlName="options"
[errorScriptConstraint]="errorScriptConstraint" /> data-automation-id="rule-details-options-component"
</div> [errorScriptConstraint]="errorScriptConstraint" />
</div>
}
</form> </form>
@@ -1,20 +1,21 @@
<fieldset [attr.aria-labelledby]="ariaLabelledBy"> <fieldset [attr.aria-labelledby]="ariaLabelledBy">
<div *ngFor="let trigger of triggerOptions"> @for (trigger of triggerOptions; track trigger) {
<ng-container *ngIf="readOnly; else checkbox"> <div>
<div @if (readOnly) {
*ngIf="selectedTriggers[trigger]" @if (selectedTriggers[trigger]) {
[attr.data-automation-id]="'rule-trigger-value-' + trigger | lowercase"> <div
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }} [attr.data-automation-id]="'rule-trigger-value-' + trigger | lowercase">
</div> {{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
</ng-container> </div>
}
<ng-template #checkbox> } @else {
<mat-checkbox <mat-checkbox
[attr.data-automation-id]="'rule-trigger-checkbox-' + trigger | lowercase" [attr.data-automation-id]="'rule-trigger-checkbox-' + trigger | lowercase"
[checked]="selectedTriggers[trigger]" [checked]="selectedTriggers[trigger]"
(change)="onTriggerChange(trigger, $event.checked)"> (change)="onTriggerChange(trigger, $event.checked)">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }} {{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
</mat-checkbox> </mat-checkbox>
</ng-template> }
</div> </div>
}
</fieldset> </fieldset>
@@ -1,47 +1,42 @@
<ng-container *ngFor="let item of items"> @for (item of items; track item) {
@if (item.type === 'rule') {
<aca-rule-list-item <aca-rule-list-item
*ngIf="item.type === 'rule'; else loadMoreRules"
matRipple matRippleColor="hsla(0,0%,0%,0.05)"
tabindex="0"
[rule]="item.rule"
[isSelected]="item.rule.id === this.selectedRule?.id"
[showEnabledToggle]="showEnabledToggles"
(click)="onRuleClicked(item.rule)"
(enabledChanged)="onEnabledChanged(item.rule, $event)" />
<ng-template #loadMoreRules>
<div
*ngIf="item.type === 'load-more-rules'; else loadMoreRuleSets"
tabindex="0"
class="aca-rule-list-grouping__non-rule-item aca-load-more"
matRipple matRippleColor="hsla(0,0%,0%,0.05)" matRipple matRippleColor="hsla(0,0%,0%,0.05)"
(click)="onClickLoadMoreRules(item.ruleSet)"
(keyup.enter)="onClickLoadMoreRules(item.ruleSet)">
{{ 'ACA_FOLDER_RULES.RULE_LIST.LOAD_MORE_RULES' | translate }}
</div>
</ng-template>
<ng-template #loadMoreRuleSets>
<div
*ngIf="item.type === 'load-more-rule-sets'; else loadingRules"
tabindex="0" tabindex="0"
class="aca-rule-list-grouping__non-rule-item aca-load-more" [rule]="item.rule"
matRipple matRippleColor="hsla(0,0%,0%,0.05)" [isSelected]="item.rule.id === this.selectedRule?.id"
(click)="onClickLoadMoreRuleSets()" [showEnabledToggle]="showEnabledToggles"
(keyup.enter)="onClickLoadMoreRuleSets()"> (click)="onRuleClicked(item.rule)"
{{ 'ACA_FOLDER_RULES.RULE_LIST.LOAD_MORE_RULE_SETS' | translate }} (enabledChanged)="onEnabledChanged(item.rule, $event)" />
</div> } @else {
</ng-template> @if (item.type === 'load-more-rules') {
<div
<ng-template #loadingRules> tabindex="0"
<div class="aca-rule-list-grouping__non-rule-item aca-load-more"
tabindex="0" matRipple matRippleColor="hsla(0,0%,0%,0.05)"
class="aca-rule-list-grouping__non-rule-item" (click)="onClickLoadMoreRules(item.ruleSet)"
matRipple matRippleColor="hsla(0,0%,0%,0.05)"> (keyup.enter)="onClickLoadMoreRules(item.ruleSet)">
<mat-spinner mode="indeterminate" [diameter]="16" class="aca-spinner" /> {{ 'ACA_FOLDER_RULES.RULE_LIST.LOAD_MORE_RULES' | translate }}
{{ 'ACA_FOLDER_RULES.RULE_LIST.LOADING_RULES' | translate }} </div>
</div> } @else {
</ng-template> @if (item.type === 'load-more-rule-sets') {
<div
</ng-container> tabindex="0"
class="aca-rule-list-grouping__non-rule-item aca-load-more"
matRipple matRippleColor="hsla(0,0%,0%,0.05)"
(click)="onClickLoadMoreRuleSets()"
(keyup.enter)="onClickLoadMoreRuleSets()">
{{ 'ACA_FOLDER_RULES.RULE_LIST.LOAD_MORE_RULE_SETS' | translate }}
</div>
} @else {
<div
tabindex="0"
class="aca-rule-list-grouping__non-rule-item"
matRipple matRippleColor="hsla(0,0%,0%,0.05)">
<mat-spinner mode="indeterminate" [diameter]="16" class="aca-spinner" />
{{ 'ACA_FOLDER_RULES.RULE_LIST.LOADING_RULES' | translate }}
</div>
}
}
}
}
@@ -26,14 +26,13 @@ import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angu
import { Rule } from '../../model/rule.model'; import { Rule } from '../../model/rule.model';
import { RuleGroupingItem } from '../../model/rule-grouping-item.model'; import { RuleGroupingItem } from '../../model/rule-grouping-item.model';
import { RuleSet } from '../../model/rule-set.model'; import { RuleSet } from '../../model/rule-set.model';
import { CommonModule } from '@angular/common';
import { RuleListItemUiComponent } from '../rule-list-item/rule-list-item.ui-component'; import { RuleListItemUiComponent } from '../rule-list-item/rule-list-item.ui-component';
import { MatRippleModule } from '@angular/material/core'; import { MatRippleModule } from '@angular/material/core';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, RuleListItemUiComponent, MatRippleModule, MatProgressSpinnerModule], imports: [TranslatePipe, RuleListItemUiComponent, MatRippleModule, MatProgressSpinnerModule],
selector: 'aca-rule-list-grouping', selector: 'aca-rule-list-grouping',
templateUrl: 'rule-list-grouping.ui-component.html', templateUrl: 'rule-list-grouping.ui-component.html',
styleUrls: ['rule-list-grouping.ui-component.scss'], styleUrls: ['rule-list-grouping.ui-component.scss'],
@@ -2,11 +2,12 @@
<span class="aca-rule-list-item__header__name">{{ rule.name }}</span> <span class="aca-rule-list-item__header__name">{{ rule.name }}</span>
<mat-slide-toggle @if (showEnabledToggle) {
*ngIf="showEnabledToggle" <mat-slide-toggle
[checked]="rule.isEnabled" [checked]="rule.isEnabled"
[aria-label]="'ACA_FOLDER_RULES.RULE_LIST.TOGGLE_RULE_STATE' | translate: { name: rule.name }" [aria-label]="'ACA_FOLDER_RULES.RULE_LIST.TOGGLE_RULE_STATE' | translate: { name: rule.name }"
(click)="onToggleClick(!rule.isEnabled, $event)" /> (click)="onToggleClick(!rule.isEnabled, $event)" />
}
</div> </div>
<div class="aca-rule-list-item__description">{{ rule.description }}</div> <div class="aca-rule-list-item__description">{{ rule.description }}</div>
@@ -24,12 +24,11 @@
import { Component, EventEmitter, HostBinding, Input, Output, ViewEncapsulation } from '@angular/core'; import { Component, EventEmitter, HostBinding, Input, Output, ViewEncapsulation } from '@angular/core';
import { Rule } from '../../model/rule.model'; import { Rule } from '../../model/rule.model';
import { CommonModule } from '@angular/common';
import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
@Component({ @Component({
imports: [CommonModule, MatSlideToggleModule, TranslatePipe], imports: [MatSlideToggleModule, TranslatePipe],
selector: 'aca-rule-list-item', selector: 'aca-rule-list-item',
templateUrl: 'rule-list-item.ui-component.html', templateUrl: 'rule-list-item.ui-component.html',
styleUrls: ['rule-list-item.ui-component.scss'], styleUrls: ['rule-list-item.ui-component.scss'],
@@ -27,7 +27,6 @@ import { RuleSet } from '../../model/rule-set.model';
import { Rule } from '../../model/rule.model'; import { Rule } from '../../model/rule.model';
import { RuleGroupingItem } from '../../model/rule-grouping-item.model'; import { RuleGroupingItem } from '../../model/rule-grouping-item.model';
import { FolderRuleSetsService } from '../../services/folder-rule-sets.service'; import { FolderRuleSetsService } from '../../services/folder-rule-sets.service';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatRippleModule } from '@angular/material/core'; import { MatRippleModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -41,7 +40,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [ imports: [
CommonModule,
TranslatePipe, TranslatePipe,
MatRippleModule, MatRippleModule,
MatIconModule, MatIconModule,
@@ -18,28 +18,25 @@
[rowFilter]="rowFilter" /> [rowFilter]="rowFilter" />
<div class="aca-rule-set-picker__content__rule-list" [ngClass]="{ 'aca-justify': rulesLoading$ | async }"> <div class="aca-rule-set-picker__content__rule-list" [ngClass]="{ 'aca-justify': rulesLoading$ | async }">
<ng-container *ngIf="rulesLoading$ | async; else rulesLoaded"> @if (rulesLoading$ | async) {
<mat-progress-spinner mode="indeterminate" /> <mat-progress-spinner mode="indeterminate" />
</ng-container> } @else {
@if (hasOwnedRules) {
<ng-template #rulesLoaded>
<ng-container *ngIf="hasOwnedRules; else noOwnedRules">
<div class="aca-rule-set-picker__content__rule-list__header"> <div class="aca-rule-set-picker__content__rule-list__header">
{{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.LIST_OF_RULES_TO_LINK' | translate }} {{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.LIST_OF_RULES_TO_LINK' | translate }}
</div> </div>
@for (rule of (mainRuleSet$ | async).rules; track rule) {
<aca-rule-list-item <aca-rule-list-item
*ngFor="let rule of (mainRuleSet$ | async).rules" [rule]="rule" />
[rule]="rule" /> }
</ng-container> } @else {
<ng-template #noOwnedRules>
<adf-empty-content <adf-empty-content
icon="library_books" icon="library_books"
[title]="'ACA_FOLDER_RULES.LINK_RULES_DIALOG.EMPTY_RULES_LIST.TITLE' | translate" [title]="'ACA_FOLDER_RULES.LINK_RULES_DIALOG.EMPTY_RULES_LIST.TITLE' | translate"
[subtitle]="'ACA_FOLDER_RULES.LINK_RULES_DIALOG.EMPTY_RULES_LIST.SUBTITLE' | translate" /> [subtitle]="'ACA_FOLDER_RULES.LINK_RULES_DIALOG.EMPTY_RULES_LIST.SUBTITLE' | translate" />
</ng-template> }
</ng-template> }
</div> </div>
</mat-dialog-content> </mat-dialog-content>
@@ -1,50 +1,53 @@
<mat-form-field @if (items?.length) {
*ngIf="items?.length" <mat-form-field
class="aca-bulk-actions-form-field" class="aca-bulk-actions-form-field"
data-automation-id="aca-bulk-actions-form-field" data-automation-id="aca-bulk-actions-form-field"
>
<mat-label>{{ 'SEARCH.BULK_ACTIONS_DROPDOWN.LABEL' | translate }}</mat-label>
<mat-select
[formControl]="bulkSelectControl"
[placeholder]="placeholder"
panelClass="aca-bulk-actions-select"
disableOptionCentering
data-automation-id="aca-bulk-actions-dropdown"
(keydown)="onKeyDown($event)"
>
<mat-select-trigger>
<div class="aca-bulk-actions-option-content">
<adf-icon
*ngIf="bulkSelectControl.value?.icon"
[title]="bulkSelectControl.value?.title | translate"
[value]="bulkSelectControl.value?.icon"
class="aca-bulk-actions-icon"
aria-hidden="true"
[attr.data-automation-id]="'aca-bulk-action-icon-' + bulkSelectControl.value?.id"
/>
{{ bulkSelectControl.value?.title | translate }}
</div>
</mat-select-trigger>
<mat-option
*ngFor="let option of items"
[value]="option"
[title]="option.tooltip | translate"
[attr.data-automation-id]="option.id"
(keyup.enter)="runAction(option)"
(click)="runAction(option)"
> >
<div class="aca-bulk-actions-option-content"> <mat-label>{{ 'SEARCH.BULK_ACTIONS_DROPDOWN.LABEL' | translate }}</mat-label>
<adf-icon <mat-select
*ngIf="option.icon" [formControl]="bulkSelectControl"
[title]="option.title | translate" [placeholder]="placeholder"
[value]="option.icon" panelClass="aca-bulk-actions-select"
class="aca-bulk-actions-icon" disableOptionCentering
aria-hidden="true" data-automation-id="aca-bulk-actions-dropdown"
[attr.data-automation-id]="'aca-bulk-action-icon-' + option.id" (keydown)="onKeyDown($event)"
/> >
{{ option.title | translate }} <mat-select-trigger>
</div> <div class="aca-bulk-actions-option-content">
</mat-option> @if (bulkSelectControl.value?.icon) {
</mat-select> <adf-icon
</mat-form-field> [title]="bulkSelectControl.value?.title | translate"
[value]="bulkSelectControl.value?.icon"
class="aca-bulk-actions-icon"
aria-hidden="true"
[attr.data-automation-id]="'aca-bulk-action-icon-' + bulkSelectControl.value?.id"
/>
}
{{ bulkSelectControl.value?.title | translate }}
</div>
</mat-select-trigger>
@for (option of items; track option) {
<mat-option
[value]="option"
[title]="option.tooltip | translate"
[attr.data-automation-id]="option.id"
(keyup.enter)="runAction(option)"
(click)="runAction(option)"
>
<div class="aca-bulk-actions-option-content">
@if (option.icon) {
<adf-icon
[title]="option.title | translate"
[value]="option.icon"
class="aca-bulk-actions-icon"
aria-hidden="true"
[attr.data-automation-id]="'aca-bulk-action-icon-' + option.id"
/>
}
{{ option.title | translate }}
</div>
</mat-option>
}
</mat-select>
</mat-form-field>
}
@@ -24,7 +24,6 @@
import { ContentActionRef } from '@alfresco/adf-extensions'; import { ContentActionRef } from '@alfresco/adf-extensions';
import { AppStore, getSearchItemsTotalCount } from '@alfresco/aca-shared/store'; import { AppStore, getSearchItemsTotalCount } from '@alfresco/aca-shared/store';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@@ -40,7 +39,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
selector: 'aca-bulk-actions-dropdown', selector: 'aca-bulk-actions-dropdown',
templateUrl: './bulk-actions-dropdown.component.html', templateUrl: './bulk-actions-dropdown.component.html',
styleUrls: ['./bulk-actions-dropdown.component.scss'], styleUrls: ['./bulk-actions-dropdown.component.scss'],
imports: [CommonModule, TranslatePipe, MatSelectModule, IconComponent, ReactiveFormsModule], imports: [TranslatePipe, MatSelectModule, IconComponent, ReactiveFormsModule],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class BulkActionsDropdownComponent implements OnInit { export class BulkActionsDropdownComponent implements OnInit {
@@ -1,12 +1,11 @@
<ng-container *ngIf="selectionState"> @if (selectionState) {
<ng-container *ngIf="!data.iconButton"> @if (!data.iconButton) {
<button mat-menu-item data-automation-id="share-action-button" (click)="editSharedNode(selectionState, '.adf-context-menu-source')"> <button mat-menu-item data-automation-id="share-action-button" (click)="editSharedNode(selectionState, '.adf-context-menu-source')">
<mat-icon>link</mat-icon> <mat-icon>link</mat-icon>
<span>{{ (isShared ? 'APP.ACTIONS.SHARE_EDIT' : 'APP.ACTIONS.SHARE') | translate }}</span> <span>{{ (isShared ? 'APP.ACTIONS.SHARE_EDIT' : 'APP.ACTIONS.SHARE') | translate }}</span>
</button> </button>
</ng-container> }
@if (data.iconButton) {
<ng-container *ngIf="data.iconButton">
<button <button
mat-icon-button mat-icon-button
data-automation-id="share-action-button" data-automation-id="share-action-button"
@@ -14,8 +13,8 @@
[attr.aria-label]="selectionLabel | translate" [attr.aria-label]="selectionLabel | translate"
[attr.title]="selectionLabel | translate" [attr.title]="selectionLabel | translate"
id="share-action-button" id="share-action-button"
> >
<mat-icon>link</mat-icon> <mat-icon>link</mat-icon>
</button> </button>
</ng-container> }
</ng-container> }
@@ -27,7 +27,6 @@ import { Observable } from 'rxjs';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { SelectionState } from '@alfresco/adf-extensions'; import { SelectionState } from '@alfresco/adf-extensions';
import { AppStore, getAppSelection, ShareNodeAction } from '@alfresco/aca-shared/store'; import { AppStore, getAppSelection, ShareNodeAction } from '@alfresco/aca-shared/store';
import { CommonModule } from '@angular/common';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu'; import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
@@ -35,7 +34,7 @@ import { MatButtonModule } from '@angular/material/button';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [CommonModule, MatMenuModule, MatIconModule, TranslatePipe, MatButtonModule], imports: [MatMenuModule, MatIconModule, TranslatePipe, MatButtonModule],
selector: 'app-toggle-shared', selector: 'app-toggle-shared',
templateUrl: './toggle-shared.component.html', templateUrl: './toggle-shared.component.html',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -1,5 +1,5 @@
<button mat-menu-item class="aca-user-info" [routerLink]="['/profile']" title="{{ 'APP.TOOLTIPS.MY_PROFILE' | translate }}"> <button mat-menu-item class="aca-user-info" [routerLink]="['/profile']" title="{{ 'APP.TOOLTIPS.MY_PROFILE' | translate }}">
<ng-container *ngIf="user$ | async as user"> @if (user$ | async; as user) {
<div class="aca-user-info-content"> <div class="aca-user-info-content">
<button class="aca-user-info-button"> <button class="aca-user-info-button">
<div>{{ user.initials || 'U' }}</div> <div>{{ user.initials || 'U' }}</div>
@@ -9,5 +9,5 @@
<div>{{ user.email }}</div> <div>{{ user.email }}</div>
</div> </div>
</div> </div>
</ng-container> }
</button> </button>
@@ -1,31 +1,27 @@
<div class="aca-context-menu"> <div class="aca-context-menu">
<ng-container [ngSwitch]="actionRef.type"> @switch (actionRef.type) {
<ng-container *ngSwitchCase="'menu'"> @case ('menu') {
<button mat-menu-item [id]="actionRef.id" [matMenuTriggerFor]="childMenu"> <button mat-menu-item [id]="actionRef.id" [matMenuTriggerFor]="childMenu">
<adf-icon [value]="actionRef.icon" class="app-context-menu-item--icon" /> <adf-icon [value]="actionRef.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="actionRef.id + '-label'">{{ actionRef.title | translate }}</span> <span [attr.data-automation-id]="actionRef.id + '-label'">{{ actionRef.title | translate }}</span>
</button> </button>
<mat-menu #childMenu="matMenu"> <mat-menu #childMenu="matMenu">
<ng-container *ngFor="let child of actionRef.children; trackBy: trackByActionId"> @for (child of actionRef.children; track trackByActionId($index, child)) {
<app-context-menu-item [actionRef]="child" /> <app-context-menu-item [actionRef]="child" />
</ng-container> }
</mat-menu> </mat-menu>
</ng-container> }
@case ('separator') {
<ng-container *ngSwitchCase="'separator'">
<mat-divider aria-hidden="true" /> <mat-divider aria-hidden="true" />
</ng-container> }
@case ('custom') {
<ng-container *ngSwitchCase="'custom'">
<adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" /> <adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" />
</ng-container> }
@default {
<ng-container *ngSwitchDefault>
<button mat-menu-item [id]="actionRef.id" (click)="runAction()"> <button mat-menu-item [id]="actionRef.id" (click)="runAction()">
<adf-icon [value]="actionRef.icon" class="app-context-menu-item--icon" /> <adf-icon [value]="actionRef.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="actionRef.id + '-label'">{{ actionRef.title | translate }}</span> <span [attr.data-automation-id]="actionRef.id + '-label'">{{ actionRef.title | translate }}</span>
</button> </button>
</ng-container> }
</ng-container> }
</div> </div>
@@ -25,14 +25,13 @@
import { Component, Input, ViewEncapsulation, inject } from '@angular/core'; import { Component, Input, ViewEncapsulation, inject } from '@angular/core';
import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions'; import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { AppExtensionService } from '@alfresco/aca-shared'; import { AppExtensionService } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
import { IconComponent } from '@alfresco/adf-core'; import { IconComponent } from '@alfresco/adf-core';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent], imports: [TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent],
selector: 'app-context-menu-item', selector: 'app-context-menu-item',
templateUrl: './context-menu-item.component.html', templateUrl: './context-menu-item.component.html',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -2,34 +2,32 @@
<div style="visibility: hidden;" [matMenuTriggerFor]="rootMenu"></div> <div style="visibility: hidden;" [matMenuTriggerFor]="rootMenu"></div>
<mat-menu #rootMenu="matMenu" class="aca-context-menu" hasBackdrop="false" acaContextMenuOutsideEvent (clickOutside)="onClickOutsideEvent()"> <mat-menu #rootMenu="matMenu" class="aca-context-menu" hasBackdrop="false" acaContextMenuOutsideEvent (clickOutside)="onClickOutsideEvent()">
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId" [ngSwitch]="entry.type"> @for (entry of actions; track trackByActionId($index, entry)) {
<ng-container *ngSwitchDefault> @switch (entry.type) {
<button mat-menu-item [id]="entry.id" (click)="runAction(entry)"> @default {
<adf-icon [value]="entry.icon" class="app-context-menu-item--icon" /> <button mat-menu-item [id]="entry.id" (click)="runAction(entry)">
<span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span> <adf-icon [value]="entry.icon" class="app-context-menu-item--icon" />
</button> <span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span>
</ng-container> </button>
}
<ng-container *ngSwitchCase="'separator'"> @case ('separator') {
<mat-divider aria-hidden="true" /> <mat-divider aria-hidden="true" />
</ng-container> }
@case ('menu') {
<ng-container *ngSwitchCase="'menu'"> <button mat-menu-item [id]="entry.id" [matMenuTriggerFor]="childMenu">
<button mat-menu-item [id]="entry.id" [matMenuTriggerFor]="childMenu"> <adf-icon [value]="entry.icon" class="app-context-menu-item--icon" />
<adf-icon [value]="entry.icon" class="app-context-menu-item--icon" /> <span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span>
<span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span> </button>
</button> <mat-menu #childMenu="matMenu">
@for (child of entry.children; track trackByActionId($index, child)) {
<mat-menu #childMenu="matMenu"> <app-context-menu-item [actionRef]="child" />
<ng-container *ngFor="let child of entry.children; trackBy: trackByActionId"> }
<app-context-menu-item [actionRef]="child" /> </mat-menu>
</ng-container> }
</mat-menu> @case ('custom') {
</ng-container> <adf-dynamic-component [data]="entry.data" [id]="entry.component" />
}
<ng-container *ngSwitchCase="'custom'"> }
<adf-dynamic-component [data]="entry.data" [id]="entry.component" /> }
</ng-container>
</ng-container>
</mat-menu> </mat-menu>
</div> </div>
@@ -25,7 +25,6 @@
import { AfterViewInit, Component, DestroyRef, inject, OnInit, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core'; import { AfterViewInit, Component, DestroyRef, inject, OnInit, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
import { MatMenu, MatMenuItem, MatMenuModule } from '@angular/material/menu'; import { MatMenu, MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { ContentActionType, DynamicExtensionComponent } from '@alfresco/adf-extensions'; import { ContentActionType, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
import { IconComponent } from '@alfresco/adf-core'; import { IconComponent } from '@alfresco/adf-core';
@@ -36,7 +35,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [ imports: [
CommonModule,
TranslatePipe, TranslatePipe,
MatMenuModule, MatMenuModule,
MatDividerModule, MatDividerModule,
@@ -7,20 +7,22 @@
<div class="aca-page-layout-content"> <div class="aca-page-layout-content">
<div class="aca-details-container"> <div class="aca-details-container">
<div class="aca-details-title"> <div class="aca-details-title">
<div class="aca-details-breadcrumb" role="heading" aria-level="2" *ngIf="node"> @if (node) {
<span class="aca-details-breadcrumb-library"> <div class="aca-details-breadcrumb" role="heading" aria-level="2">
<img class="aca-details-breadcrumb-icon" alt="{{ 'APP.INFO_DRAWER.ICON' | translate }}" src="{{ nodeIcon }}"> <span class="aca-details-breadcrumb-library">
<img class="aca-details-breadcrumb-icon" alt="{{ 'APP.INFO_DRAWER.ICON' | translate }}" src="{{ nodeIcon }}">
{{ node.name }} </span> {{ node.name }} </span>
</div> </div>
}
<div class="aca-details-buttons"> <div class="aca-details-buttons">
<aca-toolbar [items]="aspectActions" info-drawer-buttons /> <aca-toolbar [items]="aspectActions" info-drawer-buttons />
<button <button
class="aca-close-details-button" class="aca-close-details-button"
mat-icon-button mat-icon-button
data-automation-id="close-library" data-automation-id="close-library"
title="{{ 'APP.INFO_DRAWER.REDUCE_PANEL' | translate }}" title="{{ 'APP.INFO_DRAWER.REDUCE_PANEL' | translate }}"
(click)="goBack()"> (click)="goBack()">
<mat-icon>fullscreen_exit</mat-icon> <mat-icon>fullscreen_exit</mat-icon>
</button> </button>
</div> </div>
</div> </div>
@@ -28,17 +30,29 @@
<mat-tab-group [selectedIndex]="activeTab" class="aca-details-tabs" animationDuration="0" mat-stretch-tabs="false" mat-align-tabs="start"> <mat-tab-group [selectedIndex]="activeTab" class="aca-details-tabs" animationDuration="0" mat-stretch-tabs="false" mat-align-tabs="start">
<mat-tab label="{{ 'APP.INFO_DRAWER.TABS.PROPERTIES' | translate }}"> <mat-tab label="{{ 'APP.INFO_DRAWER.TABS.PROPERTIES' | translate }}">
<ng-template matTabContent> <ng-template matTabContent>
<app-metadata-tab *ngIf="node && !isLoading; else loading" [node]="node" /> @if (node && !isLoading) {
<app-metadata-tab [node]="node" />
} @else {
<mat-progress-bar mode="indeterminate" />
}
</ng-template> </ng-template>
</mat-tab> </mat-tab>
<mat-tab label="{{ 'APP.INFO_DRAWER.TABS.COMMENTS' | translate }}"> <mat-tab label="{{ 'APP.INFO_DRAWER.TABS.COMMENTS' | translate }}">
<ng-template matTabContent> <ng-template matTabContent>
<app-comments-tab *ngIf="node && !isLoading; else loading" [node]="node" /> @if (node && !isLoading) {
<app-comments-tab [node]="node" />
} @else {
<mat-progress-bar mode="indeterminate" />
}
</ng-template> </ng-template>
</mat-tab> </mat-tab>
<mat-tab [disabled]="!canManagePermissions" label="{{ 'APP.INFO_DRAWER.TABS.PERMISSIONS' | translate }}"> <mat-tab [disabled]="!canManagePermissions" label="{{ 'APP.INFO_DRAWER.TABS.PERMISSIONS' | translate }}">
<ng-template matTabContent> <ng-template matTabContent>
<adf-permission-list *ngIf="node && !isLoading; else loading" [nodeId]="node.id" /> @if (node && !isLoading) {
<adf-permission-list [nodeId]="node.id" />
} @else {
<mat-progress-bar mode="indeterminate" />
}
</ng-template> </ng-template>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
@@ -46,6 +60,3 @@
</div> </div>
</aca-page-layout> </aca-page-layout>
<ng-template #loading>
<mat-progress-bar mode="indeterminate" />
</ng-template>
@@ -27,7 +27,7 @@ import { ActivatedRoute, NavigationEnd } from '@angular/router';
import { AppHookService, ContentApiService, PageComponent, PageLayoutComponent, ToolbarComponent } from '@alfresco/aca-shared'; import { AppHookService, ContentApiService, PageComponent, PageLayoutComponent, ToolbarComponent } from '@alfresco/aca-shared';
import { NavigateToFolder, NavigateToPreviousPage, SetInfoDrawerStateAction, SetSelectedNodesAction } from '@alfresco/aca-shared/store'; import { NavigateToFolder, NavigateToPreviousPage, SetInfoDrawerStateAction, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
import { BreadcrumbComponent, ContentService, NodesApiService, PermissionListComponent } from '@alfresco/adf-content-services'; import { BreadcrumbComponent, ContentService, NodesApiService, PermissionListComponent } from '@alfresco/adf-content-services';
import { CommonModule, Location } from '@angular/common'; import { Location } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatTabsModule } from '@angular/material/tabs'; import { MatTabsModule } from '@angular/material/tabs';
@@ -43,7 +43,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [ imports: [
CommonModule,
TranslatePipe, TranslatePipe,
MatIconModule, MatIconModule,
MatTabsModule, MatTabsModule,
@@ -1,19 +1,19 @@
<div class="aca-datatable-cell-badges-container"> <div class="aca-datatable-cell-badges-container">
<ng-container *ngFor="let badge of badges"> @for (badge of badges; track badge) {
@if (badge.component) {
<adf-dynamic-component <adf-dynamic-component
*ngIf="badge.component; else iconBadge"
[id]="badge.component" [id]="badge.component"
[data]="{ node }" [data]="{ node }"
/>
<ng-template #iconBadge>
<adf-icon
class="adf-datatable-cell-badge"
[title]="badge.tooltip | translate"
[value]="badge.icon"
(click)="onBadgeClick(badge)"
(keypress.enter)="onKeyPress(badge)"
tabindex="0"
/> />
</ng-template> } @else {
</ng-container> <adf-icon
class="adf-datatable-cell-badge"
[title]="badge.tooltip | translate"
[value]="badge.icon"
(click)="onBadgeClick(badge)"
(keypress.enter)="onKeyPress(badge)"
tabindex="0"
/>
}
}
</div> </div>
@@ -26,7 +26,6 @@ import { AppExtensionService, Badge } from '@alfresco/aca-shared';
import { IconComponent } from '@alfresco/adf-core'; import { IconComponent } from '@alfresco/adf-core';
import { DynamicExtensionComponent } from '@alfresco/adf-extensions'; import { DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { NodeEntry } from '@alfresco/js-api'; import { NodeEntry } from '@alfresco/js-api';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -37,7 +36,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
styleUrls: ['./datatable-cell-badges.component.scss'], styleUrls: ['./datatable-cell-badges.component.scss'],
host: { class: 'aca-datatable-cell-badges' }, host: { class: 'aca-datatable-cell-badges' },
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
imports: [CommonModule, TranslatePipe, DynamicExtensionComponent, IconComponent] imports: [TranslatePipe, DynamicExtensionComponent, IconComponent]
}) })
export class DatatableCellBadgesComponent implements OnInit { export class DatatableCellBadgesComponent implements OnInit {
private readonly appExtensionService = inject(AppExtensionService); private readonly appExtensionService = inject(AppExtensionService);
@@ -2,8 +2,8 @@
<div class="aca-page-layout-header"> <div class="aca-page-layout-header">
<div class="aca-header-container"> <div class="aca-header-container">
<h1 class="aca-page-title"> <h1 class="aca-page-title">
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.FAVORITES.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }} {{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.FAVORITES.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1> </h1>
<aca-toolbar [items]="actions" /> <aca-toolbar [items]="actions" />
</div> </div>
</div> </div>
@@ -28,14 +28,14 @@
[blurOnResize]="false" [blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)" (node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)" (name-click)="handleNodeClick($event)"
> >
<adf-custom-empty-content-template> <adf-custom-empty-content-template>
<adf-empty-content icon="star_rate" [title]="'APP.BROWSE.FAVORITES.EMPTY_STATE.TITLE'" subtitle="APP.BROWSE.FAVORITES.EMPTY_STATE.TEXT" /> <adf-empty-content icon="star_rate" [title]="'APP.BROWSE.FAVORITES.EMPTY_STATE.TITLE'" subtitle="APP.BROWSE.FAVORITES.EMPTY_STATE.TEXT" />
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
<data-columns> <data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> @for (column of columns; track trackByColumnId($index, column)) {
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -48,14 +48,13 @@
[sortable]="column.sortable" [sortable]="column.sortable"
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
> >
<ng-template let-context> <ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" /> <adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template> </ng-template>
</data-column> </data-column>
</ng-container> }
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -68,17 +67,19 @@
[sortable]="column.sortable" [sortable]="column.sortable"
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
/> />
</ng-container> }
</ng-container> }
</data-columns> </data-columns>
</adf-document-list> </adf-document-list>
<adf-pagination acaPagination [target]="documentList" /> <adf-pagination acaPagination [target]="documentList" />
</div> </div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async"> @if (infoDrawerOpened$ | async) {
<aca-info-drawer [node]="selection.last" /> <div class="aca-sidebar">
</div> <aca-info-drawer [node]="selection.last" />
</div>
}
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -15,99 +15,104 @@
</div> </div>
<div class="aca-page-layout-content"> <div class="aca-page-layout-content">
<div class="aca-main-content" *ngIf="!(showLoader$ | async)"> @if (!(showLoader$ | async)) {
<adf-upload-drag-area [rootFolderId]="node?.id" [disabled]="!canUpload" (updateFileVersion)="onUploadNewVersion($event)"> <div class="aca-main-content">
<adf-document-list <adf-upload-drag-area [rootFolderId]="node?.id" [disabled]="!canUpload" (updateFileVersion)="onUploadNewVersion($event)">
#documentList <adf-document-list
acaDocumentList #documentList
acaContextActions acaDocumentList
[selectionMode]="'multiple'" acaContextActions
[multiselect]="true" [selectionMode]="'multiple'"
[currentFolderId]="node?.id" [multiselect]="true"
[loading]="true" [currentFolderId]="node?.id"
[showHeader]="showHeader" [loading]="true"
[node]="nodeResult" [showHeader]="showHeader"
[allowDropFiles]="true" [node]="nodeResult"
[displayCheckboxesOnHover]="true" [allowDropFiles]="true"
[preselectNodes]="selectedNodesState?.nodes" [displayCheckboxesOnHover]="true"
[navigate]="false" [preselectNodes]="selectedNodesState?.nodes"
[sorting]="['name', 'asc']" [navigate]="false"
[imageResolver]="imageResolver" [sorting]="['name', 'asc']"
[headerFilters]="true" [imageResolver]="imageResolver"
[filterValue]="queryParams" [headerFilters]="true"
[isDataProvidedExternally]="!!queryParams" [filterValue]="queryParams"
[isResizingEnabled]="true" [isDataProvidedExternally]="!!queryParams"
[blurOnResize]="false" [isResizingEnabled]="true"
[displayDragAndDropHint]="canUpload" [blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)" [displayDragAndDropHint]="canUpload"
(name-click)="handleNodeClick($event)" (node-dblclick)="handleNodeClick($event)"
(selectedItemsCountChanged)="onSelectedItemsCountChanged($event)" (name-click)="handleNodeClick($event)"
(filterSelection)="onFilterSelected($event)" (selectedItemsCountChanged)="onSelectedItemsCountChanged($event)"
(error)="onError($event)" (filterSelection)="onFilterSelected($event)"
> (error)="onError($event)"
<data-columns> >
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> <data-columns>
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @for (column of columns; track trackByColumnId($index, column)) {
<data-column @if (column.template && !(column.desktopOnly && isSmallScreen)) {
[id]="column.id" <data-column
[key]="column.key" [id]="column.id"
[title]="column.title" [key]="column.key"
[type]="column.type" [title]="column.title"
[format]="column.format" [type]="column.type"
[class]="column.class" [format]="column.format"
[sortable]="column.sortable" [class]="column.class"
[sortingKey]="column.sortingKey || column.key" [sortable]="column.sortable"
[isHidden]="column.isHidden" [sortingKey]="column.sortingKey || column.key"
[draggable]="column.draggable" [isHidden]="column.isHidden"
[resizable]="column.resizable" [draggable]="column.draggable"
> [resizable]="column.resizable"
<ng-template let-context> >
<adf-dynamic-column [id]="column.template" [context]="context" /> <ng-template let-context>
</ng-template> <adf-dynamic-column [id]="column.template" [context]="context" />
</data-column> </ng-template>
</ng-container> </data-column>
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
[title]="column.title"
[type]="column.type"
[format]="column.format"
[class]="column.class"
[sortable]="column.sortable"
[sortingKey]="column.sortingKey || column.key"
[isHidden]="column.isHidden"
[draggable]="column.draggable"
[resizable]="column.resizable"
/>
}
}
</data-columns>
@if (isFilterHeaderActive) {
<adf-custom-empty-content-template>
<ng-container>
<div class="empty-search__block" aria-live="polite">
<p class="empty-search__text">
{{ 'APP.BROWSE.SEARCH.NO_FILTER_RESULTS' | translate }}
</p>
</div>
</ng-container>
</adf-custom-empty-content-template>
}
</adf-document-list>
<adf-pagination acaPagination [target]="documentList" />
</adf-upload-drag-area>
</div>
}
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)"> @if (showLoader$ | async) {
<data-column <mat-progress-spinner
[id]="column.id" id="adf-document-list-loading"
[key]="column.key" class="adf-document-list-loading-margin"
[title]="column.title" [color]="'primary'"
[type]="column.type" [mode]="'indeterminate'" />
[format]="column.format" }
[class]="column.class"
[sortable]="column.sortable"
[sortingKey]="column.sortingKey || column.key"
[isHidden]="column.isHidden"
[draggable]="column.draggable"
[resizable]="column.resizable"
/>
</ng-container>
</ng-container>
</data-columns>
<adf-custom-empty-content-template *ngIf="isFilterHeaderActive"> @if (infoDrawerOpened$ | async) {
<ng-container> <div class="aca-sidebar">
<div class="empty-search__block" aria-live="polite"> <aca-info-drawer [node]="selection.last" />
<p class="empty-search__text"> </div>
{{ 'APP.BROWSE.SEARCH.NO_FILTER_RESULTS' | translate }} }
</p>
</div>
</ng-container>
</adf-custom-empty-content-template>
</adf-document-list>
<adf-pagination acaPagination [target]="documentList" />
</adf-upload-drag-area>
</div>
<mat-progress-spinner *ngIf="showLoader$ | async"
id="adf-document-list-loading"
class="adf-document-list-loading-margin"
[color]="'primary'"
[mode]="'indeterminate'" />
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async">
<aca-info-drawer [node]="selection.last" />
</div>
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -1,78 +1,80 @@
@if (node) { @if (node) {
<mat-card appearance="raised"> <mat-card appearance="raised">
<mat-card-content> <mat-card-content>
<form [formGroup]="form" autocomplete="off"> <form [formGroup]="form" autocomplete="off">
<mat-form-field data-automation-id="library-name-properties-wrapper" class="app-library-metadata-form-field"> <mat-form-field data-automation-id="library-name-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}</mat-label> <mat-label>{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}</mat-label>
<input <input
#libraryNameInput #libraryNameInput
data-automation-id="app-library-metadata-form-name-input" data-automation-id="app-library-metadata-form-name-input"
matInput matInput
required required
placeholder="{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}" placeholder="{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}"
formControlName="title" formControlName="title"
[errorStateMatcher]="matcher" [errorStateMatcher]="matcher"
/> />
@if (libraryTitleExists) { @if (libraryTitleExists) {
<mat-hint data-automation-id="app-library-metadata-form-name-hint">{{ 'LIBRARY.HINTS.SITE_TITLE_EXISTS' | translate }}</mat-hint> <mat-hint data-automation-id="app-library-metadata-form-name-hint">{{ 'LIBRARY.HINTS.SITE_TITLE_EXISTS' | translate }}</mat-hint>
}
<mat-error data-automation-id="app-library-metadata-form-name-error">
{{ titleErrorTranslationKey | translate }}
</mat-error>
</mat-form-field>
<mat-form-field data-automation-id="library-id-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.SITE_ID' | translate }}</mat-label>
<input matInput placeholder="{{ 'LIBRARY.DIALOG.FORM.SITE_ID' | translate }}" formControlName="id" />
</mat-form-field>
<mat-form-field data-automation-id="library-visibility-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.VISIBILITY' | translate }}</mat-label>
<mat-select placeholder="{{ 'LIBRARY.DIALOG.FORM.VISIBILITY' | translate }}" formControlName="visibility">
@for (type of libraryType; track type) {
<mat-option [value]="type.value" [attr.data-automation-id]="'library-visibility-option-' + type.value">
{{ type.label | translate }}
</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field data-automation-id="library-description-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.DESCRIPTION' | translate }}</mat-label>
<textarea
matInput
placeholder="{{ 'LIBRARY.DIALOG.FORM.DESCRIPTION' | translate }}"
rows="3"
formControlName="description"
[errorStateMatcher]="matcher"
></textarea>
<mat-error>
{{ 'LIBRARY.ERRORS.DESCRIPTION_TOO_LONG' | translate }}
</mat-error>
</mat-form-field>
</form>
</mat-card-content>
@if (canUpdateLibrary) {
<mat-card-actions align="end">
@if (form.enabled) {
<button
data-automation-id="app-library-metadata-form-cancel-button"
mat-button
(click)="cancel()">
{{ 'LIBRARY.DIALOG.CANCEL' | translate }}
</button>
<button mat-button class="app-library-metadata-form__primary-action" [disabled]="form.invalid || form.pristine" (click)="update()">
{{ 'LIBRARY.DIALOG.UPDATE' | translate }}
</button>
} @else {
<button
mat-button
class="app-library-metadata-form__primary-action"
(click)="toggleEdit()"
data-automation-id="app-library-metadata-form-edit-button">
{{ 'LIBRARY.DIALOG.EDIT' | translate }}
</button>
} }
<mat-error data-automation-id="app-library-metadata-form-name-error"> </mat-card-actions>
{{ titleErrorTranslationKey | translate }}
</mat-error>
</mat-form-field>
<mat-form-field data-automation-id="library-id-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.SITE_ID' | translate }}</mat-label>
<input matInput placeholder="{{ 'LIBRARY.DIALOG.FORM.SITE_ID' | translate }}" formControlName="id" />
</mat-form-field>
<mat-form-field data-automation-id="library-visibility-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.VISIBILITY' | translate }}</mat-label>
<mat-select placeholder="{{ 'LIBRARY.DIALOG.FORM.VISIBILITY' | translate }}" formControlName="visibility">
<mat-option [value]="type.value" [attr.data-automation-id]="'library-visibility-option-' + type.value" *ngFor="let type of libraryType">
{{ type.label | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field data-automation-id="library-description-properties-wrapper" class="app-library-metadata-form-field">
<mat-label>{{ 'LIBRARY.DIALOG.FORM.DESCRIPTION' | translate }}</mat-label>
<textarea
matInput
placeholder="{{ 'LIBRARY.DIALOG.FORM.DESCRIPTION' | translate }}"
rows="3"
formControlName="description"
[errorStateMatcher]="matcher"
></textarea>
<mat-error>
{{ 'LIBRARY.ERRORS.DESCRIPTION_TOO_LONG' | translate }}
</mat-error>
</mat-form-field>
</form>
</mat-card-content>
@if (canUpdateLibrary) {
<mat-card-actions align="end">
@if (form.enabled) {
<button
data-automation-id="app-library-metadata-form-cancel-button"
mat-button
(click)="cancel()">
{{ 'LIBRARY.DIALOG.CANCEL' | translate }}
</button>
<button mat-button class="app-library-metadata-form__primary-action" [disabled]="form.invalid || form.pristine" (click)="update()">
{{ 'LIBRARY.DIALOG.UPDATE' | translate }}
</button>
} @else {
<button
mat-button
class="app-library-metadata-form__primary-action"
(click)="toggleEdit()"
data-automation-id="app-library-metadata-form-edit-button">
{{ 'LIBRARY.DIALOG.EDIT' | translate }}
</button>
} }
</mat-card-actions> </mat-card>
}
</mat-card>
} }
@@ -49,7 +49,6 @@ import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgForOf } from '@angular/common';
export class InstantErrorStateMatcher implements ErrorStateMatcher { export class InstantErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean { isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {
@@ -68,8 +67,7 @@ export class InstantErrorStateMatcher implements ErrorStateMatcher {
MatSelectModule, MatSelectModule,
MatOptionModule, MatOptionModule,
MatInputModule, MatInputModule,
MatButtonModule, MatButtonModule
NgForOf
], ],
selector: 'app-library-metadata-form', selector: 'app-library-metadata-form',
templateUrl: './library-metadata-form.component.html', templateUrl: './library-metadata-form.component.html',
@@ -2,8 +2,8 @@
<div class="aca-page-layout-header"> <div class="aca-page-layout-header">
<div class="aca-header-container"> <div class="aca-header-container">
<h1 class="aca-page-title"> <h1 class="aca-page-title">
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.RECENT.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }} {{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.RECENT.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1> </h1>
<aca-toolbar [items]="actions" /> <aca-toolbar [items]="actions" />
</div> </div>
</div> </div>
@@ -28,14 +28,14 @@
[blurOnResize]="false" [blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)" (node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)" (name-click)="handleNodeClick($event)"
> >
<adf-custom-empty-content-template> <adf-custom-empty-content-template>
<adf-empty-content icon="access_time" [title]="'APP.BROWSE.RECENT.EMPTY_STATE.TITLE'" subtitle="APP.BROWSE.RECENT.EMPTY_STATE.TEXT" /> <adf-empty-content icon="access_time" [title]="'APP.BROWSE.RECENT.EMPTY_STATE.TITLE'" subtitle="APP.BROWSE.RECENT.EMPTY_STATE.TEXT" />
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
<data-columns> <data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> @for (column of columns; track trackByColumnId($index, column)) {
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -48,14 +48,13 @@
[resizable]="column.resizable" [resizable]="column.resizable"
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
> >
<ng-template let-context> <ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" /> <adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template> </ng-template>
</data-column> </data-column>
</ng-container> }
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -68,17 +67,19 @@
[draggable]="column.draggable" [draggable]="column.draggable"
[resizable]="column.resizable" [resizable]="column.resizable"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
/> />
</ng-container> }
</ng-container> }
</data-columns> </data-columns>
</adf-document-list> </adf-document-list>
<adf-pagination acaPagination [target]="documentList" /> <adf-pagination acaPagination [target]="documentList" />
</div> </div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async"> @if (infoDrawerOpened$ | async) {
<aca-info-drawer [node]="selection.last" /> <div class="aca-sidebar">
</div> <aca-info-drawer [node]="selection.last" />
</div>
}
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -8,15 +8,16 @@
<mat-menu #sorting="matMenu"> <mat-menu #sorting="matMenu">
<ng-template matMenuContent> <ng-template matMenuContent>
<button @for (option of options; track option) {
mat-menu-item <button
*ngFor="let option of options" mat-menu-item
[id]="option.key + '-sorting-option'" [id]="option.key + '-sorting-option'"
[matMenuTriggerFor]="direction" [matMenuTriggerFor]="direction"
[matMenuTriggerData]="{ option: option }" [matMenuTriggerData]="{ option: option }"
> >
{{ option.label | translate }} {{ option.label | translate }}
</button> </button>
}
</ng-template> </ng-template>
</mat-menu> </mat-menu>
@@ -24,14 +24,13 @@
import { SearchQueryBuilderService, SearchSortingDefinition } from '@alfresco/adf-content-services'; import { SearchQueryBuilderService, SearchSortingDefinition } from '@alfresco/adf-content-services';
import { Component, EventEmitter, OnInit, Output, ViewEncapsulation, inject } from '@angular/core'; import { Component, EventEmitter, OnInit, Output, ViewEncapsulation, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatIconModule, MatButtonModule], imports: [TranslatePipe, MatMenuModule, MatIconModule, MatButtonModule],
selector: 'aca-search-action-menu', selector: 'aca-search-action-menu',
templateUrl: './search-action-menu.component.html', templateUrl: './search-action-menu.component.html',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -23,7 +23,6 @@
*/ */
import { Component, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { OverlayModule } from '@angular/cdk/overlay'; import { OverlayModule } from '@angular/cdk/overlay';
@@ -39,17 +38,7 @@ import { ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cd
@Component({ @Component({
selector: 'aca-search-in-menu', selector: 'aca-search-in-menu',
standalone: true, standalone: true,
imports: [ imports: [FormsModule, TranslatePipe, OverlayModule, MatButtonModule, MatIconModule, MatCheckboxModule, MatRadioModule, MatDividerModule],
CommonModule,
FormsModule,
TranslatePipe,
OverlayModule,
MatButtonModule,
MatIconModule,
MatCheckboxModule,
MatRadioModule,
MatDividerModule
],
templateUrl: './search-in-menu.component.html', templateUrl: './search-in-menu.component.html',
styleUrls: ['./search-in-menu.component.scss'], styleUrls: ['./search-in-menu.component.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -28,7 +28,6 @@ import { ActivatedRoute, NavigationSkipped, Params, Router } from '@angular/rout
import { SearchNavigationService } from '../search-navigation.service'; import { SearchNavigationService } from '../search-navigation.service';
import { SearchFilterService } from '../search-filter.service'; import { SearchFilterService } from '../search-filter.service';
import { SearchExecutionService } from '../search-execution.service'; import { SearchExecutionService } from '../search-execution.service';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -45,7 +44,6 @@ import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
@Component({ @Component({
imports: [ imports: [
CommonModule,
TranslatePipe, TranslatePipe,
MatButtonModule, MatButtonModule,
MatIconModule, MatIconModule,
@@ -8,17 +8,25 @@
<div class="aca-main-content"> <div class="aca-main-content">
<div class="adf-search-results"> <div class="adf-search-results">
<div class="adf-search-results__content"> <div class="adf-search-results__content">
<mat-progress-bar *ngIf="isLoading" mode="indeterminate" /> @if (isLoading) {
<div class="adf-search-results__content-header aca-content-lib" *ngIf="data?.list.entries.length"> <mat-progress-bar mode="indeterminate" />
<div class="aca-content__side--left"> }
<div class="adf-search-results--info-text" *ngIf="totalResults !== 1"> @if (data?.list.entries.length) {
{{ 'APP.BROWSE.SEARCH_LIBRARIES.FOUND_RESULTS' | translate: { number: totalResults } }} <div class="adf-search-results__content-header aca-content-lib">
</div> <div class="aca-content__side--left">
<div class="adf-search-results--info-text" *ngIf="totalResults === 1"> @if (totalResults !== 1) {
{{ 'APP.BROWSE.SEARCH_LIBRARIES.FOUND_ONE_RESULT' | translate: { number: totalResults } }} <div class="adf-search-results--info-text">
{{ 'APP.BROWSE.SEARCH_LIBRARIES.FOUND_RESULTS' | translate: { number: totalResults } }}
</div>
}
@if (totalResults === 1) {
<div class="adf-search-results--info-text">
{{ 'APP.BROWSE.SEARCH_LIBRARIES.FOUND_ONE_RESULT' | translate: { number: totalResults } }}
</div>
}
</div> </div>
</div> </div>
</div> }
<adf-document-list <adf-document-list
#documentList #documentList
@@ -35,10 +43,10 @@
[blurOnResize]="false" [blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)" (node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)" (name-click)="handleNodeClick($event)"
> >
<data-columns> <data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> @for (column of columns; track trackByColumnId($index, column)) {
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -49,14 +57,13 @@
[sortable]="column.sortable" [sortable]="column.sortable"
[draggable]="column.draggable" [draggable]="column.draggable"
[resizable]="column.resizable" [resizable]="column.resizable"
> >
<ng-template let-context> <ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" /> <adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template> </ng-template>
</data-column> </data-column>
</ng-container> }
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -67,28 +74,32 @@
[sortable]="column.sortable" [sortable]="column.sortable"
[draggable]="column.draggable" [draggable]="column.draggable"
[resizable]="column.resizable" [resizable]="column.resizable"
/> />
</ng-container> }
</ng-container> }
</data-columns> </data-columns>
<adf-custom-empty-content-template> <adf-custom-empty-content-template>
<ng-container *ngIf="data"> @if (data) {
<div class="empty-search__block" aria-live="polite"> <div class="empty-search__block" aria-live="polite">
<p class="empty-search__text"> <p class="empty-search__text">
{{ 'APP.BROWSE.SEARCH.NO_RESULTS' | translate }} {{ 'APP.BROWSE.SEARCH.NO_RESULTS' | translate }}
</p> </p>
</div> </div>
</ng-container> }
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
</adf-document-list> </adf-document-list>
<adf-pagination *ngIf="totalResults > 0" acaPagination [target]="documentList" (change)="onPaginationChanged($event)" /> @if (totalResults > 0) {
<adf-pagination acaPagination [target]="documentList" (change)="onPaginationChanged($event)" />
}
</div> </div>
</div> </div>
</div> </div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async"> @if (infoDrawerOpened$ | async) {
<aca-info-drawer [node]="selection.last" /> <div class="aca-sidebar">
</div> <aca-info-drawer [node]="selection.last" />
</div>
}
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -1,25 +1,27 @@
<div class="aca-search-results-text"> <div class="aca-search-results-text">
<div class="search-file-name"> <div class="search-file-name">
<span @if (isFile) {
tabindex="0" <span
role="link" tabindex="0"
*ngIf="isFile" role="link"
(click)="showPreview($event)" (click)="showPreview($event)"
(keyup.enter)="showPreview($event)" (keyup.enter)="showPreview($event)"
class="aca-link aca-crop-text" class="aca-link aca-crop-text"
[title]="nameStripped" [title]="nameStripped"
[innerHTML]="name$ | async" [innerHTML]="name$ | async"
></span> ></span>
<span }
tabindex="0" @if (!isFile) {
role="link" <span
*ngIf="!isFile" tabindex="0"
(click)="navigate($event)" role="link"
(keyup.enter)="navigate($event)" (click)="navigate($event)"
class="bold aca-link aca-crop-text" (keyup.enter)="navigate($event)"
[title]="nameStripped" class="bold aca-link aca-crop-text"
[innerHTML]="name$ | async" [title]="nameStripped"
></span> [innerHTML]="name$ | async"
></span>
}
<span <span
data-automation-id="search-results-entry-title" data-automation-id="search-results-entry-title"
class="aca-crop-text" class="aca-crop-text"
@@ -2,7 +2,9 @@
<div class="aca-page-layout-header"> <div class="aca-page-layout-header">
<div class="aca-header-container"> <div class="aca-header-container">
<aca-search-input /> <aca-search-input />
<aca-bulk-actions-dropdown *ngIf="bulkActions && ('isBulkActionsAvailable' | isFeatureSupportedInCurrentAcs | async)" [items]="bulkActions" /> @if (bulkActions && ('isBulkActionsAvailable' | isFeatureSupportedInCurrentAcs | async)) {
<aca-bulk-actions-dropdown [items]="bulkActions" />
}
<aca-toolbar class="aca-search-results__toolbar-actions" [items]="actions" /> <aca-toolbar class="aca-search-results__toolbar-actions" [items]="actions" />
</div> </div>
</div> </div>
@@ -38,38 +40,19 @@
<div class="aca-content__advanced-filters--header"> <div class="aca-content__advanced-filters--header">
<p>{{ 'APP.BROWSE.SEARCH.ADVANCED_FILTERS' | translate }}</p> <p>{{ 'APP.BROWSE.SEARCH.ADVANCED_FILTERS' | translate }}</p>
<div class="aca-content__advanced-filters--header--action-buttons"> <div class="aca-content__advanced-filters--header--action-buttons">
<button @if (initialSavedSearch !== undefined) {
*ngIf="initialSavedSearch !== undefined; else saveSearchButton"
mat-button
[disabled]="!encodedQuery"
class="aca-content__save-search-action"
title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate"
[matMenuTriggerFor]="saveSearchOptionsMenu"
>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}
<mat-icon iconPositionEnd>keyboard_arrow_down</mat-icon>
</button>
<mat-menu #saveSearchOptionsMenu="matMenu">
<button <button
mat-menu-item mat-button
(click)="editSavedSearch(initialSavedSearch)" [disabled]="!encodedQuery"
title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_CHANGES' | translate }}" class="aca-content__save-search-action"
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_CHANGES' | translate" title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}"
> [attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate"
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_CHANGES' | translate }} [matMenuTriggerFor]="saveSearchOptionsMenu"
>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}
<mat-icon iconPositionEnd>keyboard_arrow_down</mat-icon>
</button> </button>
<button } @else {
mat-menu-item
acaSaveSearch
[acaSaveSearchQuery]="encodedQuery"
title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_AS_NEW' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_AS_NEW' | translate"
>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_AS_NEW' | translate }}
</button>
</mat-menu>
<ng-template #saveSearchButton>
<button <button
mat-button mat-button
acaSaveSearch acaSaveSearch
@@ -79,10 +62,29 @@
class="aca-content__save-search-action" class="aca-content__save-search-action"
title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}" title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate" [attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate"
> >
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }} {{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}
</button> </button>
</ng-template> }
<mat-menu #saveSearchOptionsMenu="matMenu">
<button
mat-menu-item
(click)="editSavedSearch(initialSavedSearch)"
title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_CHANGES' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_CHANGES' | translate"
>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_CHANGES' | translate }}
</button>
<button
mat-menu-item
acaSaveSearch
[acaSaveSearchQuery]="encodedQuery"
title="{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_AS_NEW' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_AS_NEW' | translate"
>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.SAVE_AS_NEW' | translate }}
</button>
</mat-menu>
<button <button
[disabled]="!(areFiltersActive$ | async)" [disabled]="!(areFiltersActive$ | async)"
mat-button mat-button
@@ -90,7 +92,7 @@
class="aca-content__reset-action" class="aca-content__reset-action"
title="{{ 'APP.BROWSE.SEARCH.RESET_ACTION' | translate }}" title="{{ 'APP.BROWSE.SEARCH.RESET_ACTION' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.RESET_ACTION' | translate" [attr.aria-label]="'APP.BROWSE.SEARCH.RESET_ACTION' | translate"
> >
{{ 'APP.BROWSE.SEARCH.RESET' | translate }} {{ 'APP.BROWSE.SEARCH.RESET' | translate }}
</button> </button>
</div> </div>
@@ -114,7 +116,7 @@
[blurOnResize]="false" [blurOnResize]="false"
[node]="$any(data)" [node]="$any(data)"
(node-dblclick)="handleNodeClick($event)" (node-dblclick)="handleNodeClick($event)"
> >
<data-columns> <data-columns>
<data-column <data-column
id="app.search.thumbnail" id="app.search.thumbnail"
@@ -122,15 +124,15 @@
type="image" type="image"
[sr-title]="'ADF-DOCUMENT-LIST.LAYOUT.THUMBNAIL'" [sr-title]="'ADF-DOCUMENT-LIST.LAYOUT.THUMBNAIL'"
[sortable]="false" [sortable]="false"
> >
<adf-data-column-header> <adf-data-column-header>
<ng-template> <ng-template>
<aca-search-action-menu (sortingSelected)="onSearchSortingUpdate($event)" /> <aca-search-action-menu (sortingSelected)="onSearchSortingUpdate($event)" />
</ng-template> </ng-template>
</adf-data-column-header> </adf-data-column-header>
</data-column> </data-column>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> @for (column of columns; track trackByColumnId($index, column)) {
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -143,14 +145,13 @@
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[draggable]="column.draggable" [draggable]="column.draggable"
[resizable]="column.resizable" [resizable]="column.resizable"
> >
<ng-template let-context> <ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" /> <adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template> </ng-template>
</data-column> </data-column>
</ng-container> }
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -163,57 +164,60 @@
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[draggable]="column.draggable" [draggable]="column.draggable"
[resizable]="column.resizable" [resizable]="column.resizable"
/> />
</ng-container> }
</ng-container> }
</data-columns> </data-columns>
<adf-custom-empty-content-template> <adf-custom-empty-content-template>
<ng-container *ngIf="data"> @if (data) {
<div class="empty-search__block" aria-live="polite"> <div class="empty-search__block" aria-live="polite">
<p class="empty-search__text"> <p class="empty-search__text">
{{ 'APP.BROWSE.SEARCH.NO_RESULTS' | translate }} {{ 'APP.BROWSE.SEARCH.NO_RESULTS' | translate }}
</p> </p>
</div> </div>
</ng-container> }
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
</adf-document-list> </adf-document-list>
<adf-pagination *ngIf="totalResults > 0" acaPagination [target]="documentList" (change)="onPaginationChanged($event)" /> @if (totalResults > 0) {
<adf-pagination acaPagination [target]="documentList" (change)="onPaginationChanged($event)" />
}
</div> </div>
</div> </div>
</div> </div>
<div @if (infoDrawerOpened$ | async) {
<div
[ngClass]=" [ngClass]="
(infoDrawerPreview$ | async) === true ? 'adf-search-results--right_panel_section-extended' : 'adf-search-results--right_panel_section' (infoDrawerPreview$ | async) === true ? 'adf-search-results--right_panel_section-extended' : 'adf-search-results--right_panel_section'
" "
*ngIf="infoDrawerOpened$ | async" >
> @if (infoDrawerPreview$ | async) {
<adf-alfresco-viewer <adf-alfresco-viewer
class="adf-search-results--embedded_viewer" class="adf-search-results--embedded_viewer"
[nodeId]="selection.last.entry.id" [nodeId]="selection.last.entry.id"
*ngIf="infoDrawerPreview$ | async; else infoDrawerPanel" >
> <adf-viewer-toolbar>
<adf-viewer-toolbar> <div class="adf-search-results--preview-toolbar">
<div class="adf-search-results--preview-toolbar"> <div>
<div> <button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}" (click)="onDrawerClosed()">
<button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}" (click)="onDrawerClosed()"> <mat-icon>close</mat-icon>
<mat-icon>close</mat-icon> </button>
</button> </div>
</div> <div>
<div> <button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.INFO' | translate }}" (click)="onPreviewClosed()">
<button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.INFO' | translate }}" (click)="onPreviewClosed()"> <mat-icon>info_outline</mat-icon>
<mat-icon>info_outline</mat-icon> </button>
</button> </div>
</div> </div>
</adf-viewer-toolbar>
</adf-alfresco-viewer>
} @else {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div> </div>
</adf-viewer-toolbar> }
</adf-alfresco-viewer> </div>
<ng-template #infoDrawerPanel> }
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
</ng-template>
</div>
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -1,16 +1,16 @@
<div class="aca-save-search-dialog__header"> <div class="aca-save-search-dialog__header">
<h2 <h2
id="aca-save-search-dialog-title" id="aca-save-search-dialog-title"
class="aca-save-search-dialog__title"> class="aca-save-search-dialog__title">
{{"APP.BROWSE.SEARCH.SAVE_SEARCH.MODAL_HEADER" | translate}} {{"APP.BROWSE.SEARCH.SAVE_SEARCH.MODAL_HEADER" | translate}}
</h2> </h2>
<button <button
mat-icon-button mat-icon-button
mat-dialog-close mat-dialog-close
[attr.aria-label]="'CLOSE' | translate | titlecase" [attr.aria-label]="'CLOSE' | translate | titlecase"
[attr.title]="'CLOSE' | translate | titlecase"> [attr.title]="'CLOSE' | translate | titlecase">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
@@ -24,16 +24,22 @@
matInput matInput
required required
[formControlName]="'name'" [formControlName]="'name'"
/> />
<mat-error *ngIf="form.controls['name'].touched"> @if (form.controls['name'].touched) {
<span *ngIf="form.controls['name'].errors?.required"> <mat-error>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.NAME_REQUIRED_ERROR' | translate }} @if (form.controls['name'].errors?.required) {
</span> <span>
<span *ngIf="!form.controls['name'].errors?.required && form.controls['name'].errors?.message"> {{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.NAME_REQUIRED_ERROR' | translate }}
{{ form.controls['name'].errors?.message | translate : { name: form.controls.name.value } }} </span>
</span> }
</mat-error> @if (!form.controls['name'].errors?.required && form.controls['name'].errors?.message) {
<span>
{{ form.controls['name'].errors?.message | translate : { name: form.controls.name.value } }}
</span>
}
</mat-error>
}
</mat-form-field> </mat-form-field>
<mat-form-field class="aca-save-search-dialog__form-field"> <mat-form-field class="aca-save-search-dialog__form-field">
@@ -43,7 +49,7 @@
matInput matInput
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.DESCRIPTION_LABEL' | translate" [attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.DESCRIPTION_LABEL' | translate"
rows="4" rows="4"
[formControlName]="'description'"></textarea> [formControlName]="'description'"></textarea>
</mat-form-field> </mat-form-field>
</form> </form>
</mat-dialog-content> </mat-dialog-content>
@@ -57,10 +63,10 @@
</button> </button>
<button id="aca-save-search-dialog-save-button" <button id="aca-save-search-dialog-save-button"
mat-flat-button mat-flat-button
class="aca-save-search-dialog__save-button" class="aca-save-search-dialog__save-button"
(click)="submit()" (click)="submit()"
[disabled]="!form.valid || disableSubmitButton"> [disabled]="!form.valid || disableSubmitButton">
{{ 'SAVE' | titlecase | translate}} {{ 'SAVE' | titlecase | translate}}
</button> </button>
</mat-dialog-actions> </mat-dialog-actions>
@@ -4,27 +4,29 @@
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.LIST.TITLE' | translate }} {{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.LIST.TITLE' | translate }}
</h1> </h1>
</div> </div>
<div *ngIf="savedSearches$ | async as savedSearches else spinner" @if (savedSearches$ | async; as savedSearches) {
class="aca-page-layout-content"> <div
<div class="aca-main-content" > class="aca-page-layout-content">
<aca-saved-searches-ui-list *ngIf="savedSearches.length else emptyList" <div class="aca-main-content" >
[savedSearches]="savedSearches" @if (savedSearches.length) {
(savedSearchOrderChanged)="onOrderChanged($event)"/> <aca-saved-searches-ui-list
</div> [savedSearches]="savedSearches"
</div> (savedSearchOrderChanged)="onOrderChanged($event)"/>
<ng-template #emptyList> } @else {
<adf-empty-content <adf-empty-content
class="aca-page-layout-content" class="aca-page-layout-content"
data-automation-id="'saved-search-list-empty-content'" data-automation-id="'saved-search-list-empty-content'"
icon="library_books" icon="library_books"
title="APP.BROWSE.SEARCH.SAVE_SEARCH.LIST.EMPTY_LIST" /> title="APP.BROWSE.SEARCH.SAVE_SEARCH.LIST.EMPTY_LIST" />
</ng-template> }
</div>
</div>
} @else {
<mat-progress-spinner
class="aca-page-layout-spinner"
data-automation-id="'saved-search-list-spinner'"
[color]="'primary'"
[mode]="'indeterminate'" />
}
</aca-page-layout> </aca-page-layout>
<ng-template #spinner>
<mat-progress-spinner
class="aca-page-layout-spinner"
data-automation-id="'saved-search-list-spinner'"
[color]="'primary'"
[mode]="'indeterminate'" />
</ng-template>
@@ -44,7 +44,6 @@ import {
TEMPLATE_DIRECTIVES TEMPLATE_DIRECTIVES
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { CommonModule } from '@angular/common';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { SavedSearchesListUiService } from '../saved-searches-list-ui.service'; import { SavedSearchesListUiService } from '../saved-searches-list-ui.service';
import { savedSearchesListSchema } from '../smart-list/saved-searches-list-schema'; import { savedSearchesListSchema } from '../smart-list/saved-searches-list-schema';
@@ -54,7 +53,7 @@ import { Router } from '@angular/router';
@Component({ @Component({
selector: 'aca-saved-searches-ui-list', selector: 'aca-saved-searches-ui-list',
imports: [CommonModule, DATATABLE_DIRECTIVES, TEMPLATE_DIRECTIVES, DataTableComponent], imports: [DATATABLE_DIRECTIVES, TEMPLATE_DIRECTIVES, DataTableComponent],
templateUrl: './saved-searches-list.ui-component.html', templateUrl: './saved-searches-list.ui-component.html',
styleUrls: ['./saved-searches-list.ui-component.scss'], styleUrls: ['./saved-searches-list.ui-component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -2,8 +2,8 @@
<div class="aca-page-layout-header"> <div class="aca-page-layout-header">
<div class="aca-header-container"> <div class="aca-header-container">
<h1 class="aca-page-title"> <h1 class="aca-page-title">
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.SHARED.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }} {{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.SHARED.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1> </h1>
<aca-toolbar [items]="actions" /> <aca-toolbar [items]="actions" />
</div> </div>
@@ -28,14 +28,14 @@
[blurOnResize]="false" [blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)" (node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)" (name-click)="handleNodeClick($event)"
> >
<adf-custom-empty-content-template> <adf-custom-empty-content-template>
<adf-empty-content icon="people" [title]="'APP.BROWSE.SHARED.EMPTY_STATE.TITLE'" subtitle="APP.BROWSE.SHARED.EMPTY_STATE.TEXT" /> <adf-empty-content icon="people" [title]="'APP.BROWSE.SHARED.EMPTY_STATE.TITLE'" subtitle="APP.BROWSE.SHARED.EMPTY_STATE.TEXT" />
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
<data-columns> <data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> @for (column of columns; track trackByColumnId($index, column)) {
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -48,14 +48,13 @@
[draggable]="column.draggable" [draggable]="column.draggable"
[resizable]="column.resizable" [resizable]="column.resizable"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
> >
<ng-template let-context> <ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" /> <adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template> </ng-template>
</data-column> </data-column>
</ng-container> }
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
<data-column <data-column
[id]="column.id" [id]="column.id"
[draggable]="column.draggable" [draggable]="column.draggable"
@@ -68,17 +67,19 @@
[sortable]="column.sortable" [sortable]="column.sortable"
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
/> />
</ng-container> }
</ng-container> }
</data-columns> </data-columns>
</adf-document-list> </adf-document-list>
<adf-pagination acaPagination [target]="documentList" /> <adf-pagination acaPagination [target]="documentList" />
</div> </div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async"> @if (infoDrawerOpened$ | async) {
<aca-info-drawer [node]="selection.last" /> <div class="aca-sidebar">
</div> <aca-info-drawer [node]="selection.last" />
</div>
}
</div> </div>
</aca-page-layout> </aca-page-layout>
@@ -1,7 +1,7 @@
<ng-container *ngIf="sharedLinkId"> @if (sharedLinkId) {
<adf-alfresco-viewer [allowPrint]="false" [allowDownload]="false" [allowFullScreen]="false" [sharedLinkId]="sharedLinkId" [allowGoBack]="false"> <adf-alfresco-viewer [allowPrint]="false" [allowDownload]="false" [allowFullScreen]="false" [sharedLinkId]="sharedLinkId" [allowGoBack]="false">
<adf-viewer-toolbar-actions> <adf-viewer-toolbar-actions>
<aca-toolbar [items]="viewerToolbarActions" /> <aca-toolbar [items]="viewerToolbarActions" />
</adf-viewer-toolbar-actions> </adf-viewer-toolbar-actions>
</adf-alfresco-viewer> </adf-alfresco-viewer>
</ng-container> }
@@ -32,12 +32,11 @@ import { Store } from '@ngrx/store';
import { forkJoin, from, of } from 'rxjs'; import { forkJoin, from, of } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators'; import { catchError, mergeMap } from 'rxjs/operators';
import { AppExtensionService, AppService, ToolbarComponent } from '@alfresco/aca-shared'; import { AppExtensionService, AppService, ToolbarComponent } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { AlfrescoApiService, AlfrescoViewerModule } from '@alfresco/adf-content-services'; import { AlfrescoApiService, AlfrescoViewerModule } from '@alfresco/adf-content-services';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [CommonModule, ViewerModule, AlfrescoViewerModule, ToolbarComponent], imports: [ViewerModule, AlfrescoViewerModule, ToolbarComponent],
selector: 'app-shared-link-view', selector: 'app-shared-link-view',
templateUrl: './shared-link-view.component.html', templateUrl: './shared-link-view.component.html',
styleUrls: ['shared-link-view.component.scss'], styleUrls: ['shared-link-view.component.scss'],
@@ -1,4 +1,4 @@
<ng-container *ngIf="!item.children"> @if (!item.children) {
<button <button
class="action-button" class="action-button"
mat-icon-button mat-icon-button
@@ -8,12 +8,12 @@
[attr.aria-label]="item.title | translate" [attr.aria-label]="item.title | translate"
[attr.title]="item.description | translate" [attr.title]="item.description | translate"
[attr.data-automation-id]="item.id" [attr.data-automation-id]="item.id"
> >
<adf-icon [value]="item.icon" /> <adf-icon [value]="item.icon" />
</button> </button>
</ng-container> }
<ng-container *ngIf="item.children && item.children.length"> @if (item.children && item.children.length) {
<button <button
[matMenuTriggerFor]="menu" [matMenuTriggerFor]="menu"
[acaMenuPanel]="item" [acaMenuPanel]="item"
@@ -27,24 +27,26 @@
[ngClass]="{ [ngClass]="{
'action-button--active': acaMenuPanel.hasActiveChildren 'action-button--active': acaMenuPanel.hasActiveChildren
}" }"
> >
<adf-icon [value]="item.icon" /> <adf-icon [value]="item.icon" />
</button> </button>
<mat-menu #menu="matMenu" [overlapTrigger]="false"> <mat-menu #menu="matMenu" [overlapTrigger]="false">
<button @for (child of item.children; track trackById($index, child)) {
*ngFor="let child of item.children; trackBy: trackById" <button
acaActiveLink="action-button--active" acaActiveLink="action-button--active"
[action]="child" [action]="child"
[attr.aria-label]="child.title | translate" [attr.aria-label]="child.title | translate"
[id]="child.id" [id]="child.id"
[attr.title]="child.description | translate" [attr.title]="child.description | translate"
[attr.data-automation-id]="child.id" [attr.data-automation-id]="child.id"
mat-menu-item mat-menu-item
class="action-button" class="action-button"
> >
<adf-icon *ngIf="child.icon" [value]="child.icon" /> @if (child.icon) {
<span class="action-button__label">{{ child.title | translate }}</span> <adf-icon [value]="child.icon" />
</button> }
<span class="action-button__label">{{ child.title | translate }}</span>
</button>
}
</mat-menu> </mat-menu>
</ng-container> }
@@ -1,4 +1,4 @@
<ng-container *ngIf="!item.children"> @if (!item.children) {
<div class="aca-expansion-panel-item"> <div class="aca-expansion-panel-item">
<button <button
acaActiveLink="aca-action-button--active" acaActiveLink="aca-action-button--active"
@@ -9,19 +9,21 @@
[attr.title]="item.description | translate" [attr.title]="item.description | translate"
mat-button mat-button
class="aca-action-button aca-full-width" class="aca-action-button aca-full-width"
> >
<adf-icon *ngIf="item.icon" [value]="item.icon" /> @if (item.icon) {
<adf-icon [value]="item.icon" />
}
<span class="action-button__label">{{ item.title | translate }}</span> <span class="action-button__label">{{ item.title | translate }}</span>
</button> </button>
</div> </div>
</ng-container> }
<ng-container *ngIf="item.children && item.children.length"> @if (item.children && item.children.length) {
<mat-expansion-panel <mat-expansion-panel
class="aca-expansion-panel" class="aca-expansion-panel"
[expanded]="true" [expanded]="true"
[@.disabled]="true" [@.disabled]="true"
> >
<mat-expansion-panel-header expandedHeight="32px" collapsedHeight="32px" class="aca-expansion-panel-header"> <mat-expansion-panel-header expandedHeight="32px" collapsedHeight="32px" class="aca-expansion-panel-header">
<mat-panel-title class="aca-expansion-panel-header-title"> <mat-panel-title class="aca-expansion-panel-header-title">
<div class="aca-expansion-panel-item"> <div class="aca-expansion-panel-item">
@@ -31,30 +33,36 @@
[attr.title]="item.description | translate" [attr.title]="item.description | translate"
[attr.data-automation-id]="item.id" [attr.data-automation-id]="item.id"
class="aca-action-button aca-full-width" class="aca-action-button aca-full-width"
> >
<adf-icon *ngIf="item.icon" [value]="item.icon" /> @if (item.icon) {
<adf-icon [value]="item.icon" />
}
<span class="aca-action-button__label">{{ item.title | translate }}</span> <span class="aca-action-button__label">{{ item.title | translate }}</span>
</span> </span>
</div> </div>
</mat-panel-title> </mat-panel-title>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ul class="aca-expansion-panel-body" [attr.aria-label]="item.title | translate"> <ul class="aca-expansion-panel-body" [attr.aria-label]="item.title | translate">
<li *ngFor="let child of item.children; trackBy: trackById" class="aca-expansion-panel-item"> @for (child of item.children; track trackById($index, child)) {
<button <li class="aca-expansion-panel-item">
acaActiveLink="aca-action-button--active" <button
[action]="child" acaActiveLink="aca-action-button--active"
(actionClicked)="actionClicked.emit($event)" [action]="child"
[attr.aria-label]="child.title | translate" (actionClicked)="actionClicked.emit($event)"
[id]="child.id" [attr.aria-label]="child.title | translate"
[attr.data-automation-id]="child.id" [id]="child.id"
[attr.title]="child.description | translate" [attr.data-automation-id]="child.id"
mat-button [attr.title]="child.description | translate"
class="aca-action-button aca-full-width" mat-button
> class="aca-action-button aca-full-width"
<adf-icon *ngIf="child.icon" [value]="child.icon" /> >
<span class="aca-action-button__label">{{ child.title | translate }}</span> @if (child.icon) {
</button> <adf-icon [value]="child.icon" />
</li> }
<span class="aca-action-button__label">{{ child.title | translate }}</span>
</button>
</li>
}
</ul> </ul>
</mat-expansion-panel> </mat-expansion-panel>
</ng-container> }
@@ -24,7 +24,6 @@
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, inject } from '@angular/core'; import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, inject } from '@angular/core';
import { NavBarLinkRef } from '@alfresco/adf-extensions'; import { NavBarLinkRef } from '@alfresco/adf-extensions';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { IconComponent } from '@alfresco/adf-core'; import { IconComponent } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@@ -33,7 +32,7 @@ import { ActionDirective } from '../directives/action.directive';
import { MatExpansionModule } from '@angular/material/expansion'; import { MatExpansionModule } from '@angular/material/expansion';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, IconComponent, MatButtonModule, ActiveLinkDirective, ActionDirective, MatExpansionModule], imports: [TranslatePipe, IconComponent, MatButtonModule, ActiveLinkDirective, ActionDirective, MatExpansionModule],
selector: 'app-expand-menu', selector: 'app-expand-menu',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
templateUrl: './expand-menu.component.html', templateUrl: './expand-menu.component.html',
@@ -25,13 +25,12 @@
import { Component, DestroyRef, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, DestroyRef, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { ContentActionRef } from '@alfresco/adf-extensions'; import { ContentActionRef } from '@alfresco/adf-extensions';
import { AppExtensionService, AppService, AppSettingsService, ToolbarComponent } from '@alfresco/aca-shared'; import { AppExtensionService, AppService, AppSettingsService, ToolbarComponent } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, RouterModule, ToolbarComponent], imports: [TranslatePipe, RouterModule, ToolbarComponent],
selector: 'app-sidenav-header', selector: 'app-sidenav-header',
templateUrl: `./sidenav-header.component.html`, templateUrl: `./sidenav-header.component.html`,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -2,19 +2,22 @@
<app-sidenav-header (toggleNavBar)="toggleClick()" /> <app-sidenav-header (toggleNavBar)="toggleClick()" />
<div class="aca-sidenav__section"> <div class="aca-sidenav__section">
<div *ngFor="let group of groups; trackBy: trackByGroupId" class="aca-sidenav__section__actions"> @for (group of groups; track trackByGroupId($index, group)) {
<nav <div class="aca-sidenav__section__actions">
[attr.aria-label]="item.title | translate" @for (item of group.items; track trackByLinkId($index, item)) {
class="aca-sidenav__section__actions__item" <nav
*ngFor="let item of group.items; trackBy: trackByLinkId" [attr.aria-label]="item.title | translate"
> class="aca-sidenav__section__actions__item"
<ng-container *ngIf="!item.component"> >
<app-expand-menu [item]="item" /> @if (!item.component) {
</ng-container> <app-expand-menu [item]="item" />
<ng-container *ngIf="item.component"> }
<adf-dynamic-component [data]="{ item: item, state: 'expanded' }" [id]="item.component" /> @if (item.component) {
</ng-container> <adf-dynamic-component [data]="{ item: item, state: 'expanded' }" [id]="item.component" />
</nav> }
</div> </nav>
}
</div>
}
</div> </div>
</div> </div>
@@ -29,7 +29,6 @@ import { AppStore, getSideNavState } from '@alfresco/aca-shared/store';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { AppExtensionService, AppService, NavigationHistoryService } from '@alfresco/aca-shared'; import { AppExtensionService, AppService, NavigationHistoryService } from '@alfresco/aca-shared';
import { SidenavLayoutComponent } from '@alfresco/adf-core'; import { SidenavLayoutComponent } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { SidenavHeaderComponent } from './components/sidenav-header.component'; import { SidenavHeaderComponent } from './components/sidenav-header.component';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import { ExpandMenuComponent } from './components/expand-menu.component'; import { ExpandMenuComponent } from './components/expand-menu.component';
@@ -38,7 +37,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
@Component({ @Component({
imports: [CommonModule, SidenavHeaderComponent, MatListModule, ExpandMenuComponent, DynamicExtensionComponent, TranslatePipe], imports: [SidenavHeaderComponent, MatListModule, ExpandMenuComponent, DynamicExtensionComponent, TranslatePipe],
selector: 'app-sidenav', selector: 'app-sidenav',
templateUrl: './sidenav.component.html', templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss'], styleUrls: ['./sidenav.component.scss'],
@@ -3,12 +3,12 @@
data-automation-id="app-user-menu-button" data-automation-id="app-user-menu-button"
[matMenuTriggerFor]="menu" [matMenuTriggerFor]="menu"
title="{{'APP.TOOLTIPS.OPTIONS_SETTINGS' | translate}}" title="{{'APP.TOOLTIPS.OPTIONS_SETTINGS' | translate}}"
> >
<div>{{ (user$ | async)?.initials }}</div> <div>{{ (user$ | async)?.initials }}</div>
</button> </button>
<mat-menu #menu="matMenu" xPosition="before"> <mat-menu #menu="matMenu" xPosition="before">
<ng-container *ngFor="let item of data.items"> @for (item of data.items; track item) {
<app-toolbar-menu-item [actionRef]="item" /> <app-toolbar-menu-item [actionRef]="item" />
</ng-container> }
</mat-menu> </mat-menu>
@@ -27,13 +27,12 @@ import { NodeEntry } from '@alfresco/js-api';
import { Component, inject, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, inject, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppExtensionService, isLocked } from '@alfresco/aca-shared'; import { AppExtensionService, isLocked } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu'; import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatIconModule], imports: [TranslatePipe, MatMenuModule, MatIconModule],
selector: 'app-toggle-edit-offline', selector: 'app-toggle-edit-offline',
template: ` template: `
<button mat-menu-item [attr.title]="nodeTitle | translate" (click)="onClick()"> <button mat-menu-item [attr.title]="nodeTitle | translate" (click)="onClick()">
@@ -29,7 +29,6 @@ import { AppStore, getAppSelection } from '@alfresco/aca-shared/store';
import { SelectionState } from '@alfresco/adf-extensions'; import { SelectionState } from '@alfresco/adf-extensions';
import { distinctUntilChanged } from 'rxjs/operators'; import { distinctUntilChanged } from 'rxjs/operators';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { LibraryFavoriteDirective } from '@alfresco/adf-content-services'; import { LibraryFavoriteDirective } from '@alfresco/adf-content-services';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -37,7 +36,7 @@ import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatIconModule, MatMenuModule, LibraryFavoriteDirective], imports: [TranslatePipe, MatIconModule, MatMenuModule, LibraryFavoriteDirective],
selector: 'app-toggle-favorite-library', selector: 'app-toggle-favorite-library',
template: ` template: `
<button <button
@@ -50,8 +50,11 @@ import { MatMenuItem } from '@angular/material/menu';
[isAdmin]="(profile$ | async).isAdmin" [isAdmin]="(profile$ | async).isAdmin"
[attr.title]="(membership.isJoinRequested | async) ? ('APP.ACTIONS.CANCEL_JOIN' | translate) : ('APP.ACTIONS.JOIN' | translate)" [attr.title]="(membership.isJoinRequested | async) ? ('APP.ACTIONS.CANCEL_JOIN' | translate) : ('APP.ACTIONS.JOIN' | translate)"
> >
<mat-icon *ngIf="membership.isJoinRequested | async">cancel</mat-icon> @if (membership.isJoinRequested | async) {
<mat-icon *ngIf="!(membership.isJoinRequested | async)">library_add</mat-icon> <mat-icon>cancel</mat-icon>
} @else {
<mat-icon>library_add</mat-icon>
}
</button> </button>
`, `,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -29,7 +29,6 @@ import { ActivatedRoute, Router } from '@angular/router';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
import { SharedLinkEntry } from '@alfresco/js-api'; import { SharedLinkEntry } from '@alfresco/js-api';
import { AppSettingsService, AutoDownloadService } from '@alfresco/aca-shared'; import { AppSettingsService, AutoDownloadService } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -37,23 +36,21 @@ import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule, MatMenuModule, MatDialogModule], imports: [TranslatePipe, MatButtonModule, MatIconModule, MatMenuModule, MatDialogModule],
selector: 'app-view-node', selector: 'app-view-node',
template: ` template: `
<button @if (data.iconButton) {
*ngIf="data.iconButton" <button mat-icon-button [attr.aria-label]="data.title | translate" [attr.title]="data.title | translate" (click)="onClick()">
mat-icon-button <mat-icon>visibility</mat-icon>
[attr.aria-label]="data.title | translate" </button>
[attr.title]="data.title | translate" }
(click)="onClick()"
>
<mat-icon>visibility</mat-icon>
</button>
<button *ngIf="data.menuButton" mat-menu-item (click)="onClick()"> @if (data.menuButton) {
<mat-icon>visibility</mat-icon> <button mat-menu-item (click)="onClick()">
<span>{{ data.title | translate }}</span> <mat-icon>visibility</mat-icon>
</button> <span>{{ data.title | translate }}</span>
</button>
}
`, `,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
host: { class: 'app-view-node' } host: { class: 'app-view-node' }
@@ -25,7 +25,7 @@
[sorting]="['archivedAt', 'desc']" [sorting]="['archivedAt', 'desc']"
[isResizingEnabled]="true" [isResizingEnabled]="true"
[blurOnResize]="false" [blurOnResize]="false"
> >
<adf-custom-empty-content-template> <adf-custom-empty-content-template>
<adf-empty-content icon="delete" [title]="'APP.BROWSE.TRASHCAN.EMPTY_STATE.TITLE'"> <adf-empty-content icon="delete" [title]="'APP.BROWSE.TRASHCAN.EMPTY_STATE.TITLE'">
<p class="adf-empty-content__text"> <p class="adf-empty-content__text">
@@ -38,8 +38,8 @@
</adf-custom-empty-content-template> </adf-custom-empty-content-template>
<data-columns> <data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId"> @for (column of columns; track trackByColumnId($index, column)) {
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)"> @if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -52,14 +52,13 @@
[sortable]="column.sortable" [sortable]="column.sortable"
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
> >
<ng-template let-context> <ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" /> <adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template> </ng-template>
</data-column> </data-column>
</ng-container> }
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
<data-column <data-column
[id]="column.id" [id]="column.id"
[key]="column.key" [key]="column.key"
@@ -72,16 +71,17 @@
[resizable]="column.resizable" [resizable]="column.resizable"
[isHidden]="column.isHidden" [isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key" [sortingKey]="column.sortingKey || column.key"
/> />
</ng-container> }
</ng-container> }
<data-column @if (!isSmallScreen && (user$ | async)?.isAdmin) {
*ngIf="!isSmallScreen && (user$ | async)?.isAdmin" <data-column
class="adf-ellipsis-cell" class="adf-ellipsis-cell"
key="archivedByUser.displayName" key="archivedByUser.displayName"
title="APP.DOCUMENT_LIST.COLUMNS.DELETED_BY" title="APP.DOCUMENT_LIST.COLUMNS.DELETED_BY"
/> />
}
</data-columns> </data-columns>
</adf-document-list> </adf-document-list>
@@ -1 +1 @@
<adf-file-uploading-dialog *ngIf="showFileUploadingDialog$ | async" position="left" /> @if (showFileUploadingDialog$ | async) {<adf-file-uploading-dialog position="left" />}
@@ -23,7 +23,6 @@
*/ */
import { Component, inject, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, inject, OnInit, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NodesApiService } from '@alfresco/adf-content-services'; import { NodesApiService } from '@alfresco/adf-content-services';
import { DIALOG_COMPONENT_DATA, IconComponent } from '@alfresco/adf-core'; import { DIALOG_COMPONENT_DATA, IconComponent } from '@alfresco/adf-core';
import { Node, NodeAssociation } from '@alfresco/js-api'; import { Node, NodeAssociation } from '@alfresco/js-api';
@@ -33,7 +32,7 @@ import { TranslatePipe } from '@ngx-translate/core';
@Component({ @Component({
selector: 'app-node-location-references', selector: 'app-node-location-references',
imports: [CommonModule, IconComponent, TranslatePipe], imports: [IconComponent, TranslatePipe],
templateUrl: './node-location-references.component.html', templateUrl: './node-location-references.component.html',
styleUrls: ['./node-location-references.component.scss'], styleUrls: ['./node-location-references.component.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -8,11 +8,13 @@
matInput matInput
formControlName="name" formControlName="name"
required required
/> />
<mat-error *ngIf="form.controls['name'].errors?.message" data-automation-id="create-from-template-field-error"> @if (form.controls['name'].errors?.message) {
{{ form.controls['name'].errors?.message | translate }} <mat-error data-automation-id="create-from-template-field-error">
</mat-error> {{ form.controls['name'].errors?.message | translate }}
</mat-error>
}
</mat-form-field> </mat-form-field>
<mat-form-field class="app-create-from-template-field"> <mat-form-field class="app-create-from-template-field">
@@ -20,11 +22,13 @@
<input <input
matInput matInput
formControlName="title" formControlName="title"
/> />
<mat-error *ngIf="form.controls['title'].hasError('maxlength')" data-automation-id="create-from-template-field-error"> @if (form.controls['title'].hasError('maxlength')) {
{{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.TITLE_TOO_LONG' | translate }} <mat-error data-automation-id="create-from-template-field-error">
</mat-error> {{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.TITLE_TOO_LONG' | translate }}
</mat-error>
}
</mat-form-field> </mat-form-field>
<mat-form-field class="app-create-from-template-field app-create-from-template-field-description"> <mat-form-field class="app-create-from-template-field app-create-from-template-field-description">
@@ -35,9 +39,11 @@
formControlName="description" formControlName="description"
></textarea> ></textarea>
<mat-error *ngIf="form.controls['description'].hasError('maxlength')" data-automation-id="create-from-template-field-error"> @if (form.controls['description'].hasError('maxlength')) {
{{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.DESCRIPTION_TOO_LONG' | translate }} <mat-error data-automation-id="create-from-template-field-error">
</mat-error> {{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.DESCRIPTION_TOO_LONG' | translate }}
</mat-error>
}
</mat-form-field> </mat-form-field>
</form> </form>
</div> </div>
@@ -55,7 +61,7 @@
mat-button mat-button
(click)="onSubmit()" (click)="onSubmit()"
data-automation-id="create-from-template-dialog-create-button" data-automation-id="create-from-template-dialog-create-button"
> >
{{ 'NODE_FROM_TEMPLATE.CREATE' | translate }} {{ 'NODE_FROM_TEMPLATE.CREATE' | translate }}
</button> </button>
</div> </div>
@@ -29,14 +29,13 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators, UntypedFormControl, V
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppStore, CreateFromTemplate } from '@alfresco/aca-shared/store'; import { AppStore, CreateFromTemplate } from '@alfresco/aca-shared/store';
import { TranslationService } from '@alfresco/adf-core'; import { TranslationService } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatDialogModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule], imports: [TranslatePipe, MatDialogModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule],
templateUrl: './create-from-template.dialog.html', templateUrl: './create-from-template.dialog.html',
styleUrls: ['./create-from-template.dialog.scss'], styleUrls: ['./create-from-template.dialog.scss'],
selector: 'app-create-from-template-dialog', selector: 'app-create-from-template-dialog',
-1
View File
@@ -4,7 +4,6 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../../out-tsc/lib", "outDir": "../../out-tsc/lib",
"target": "es2020", "target": "es2020",
"moduleResolution": "node",
"sourceMap": true, "sourceMap": true,
"declaration": true, "declaration": true,
"declarationMap": true, "declarationMap": true,
@@ -1,4 +1,4 @@
<ng-container *ngIf="nodeId"> @if (nodeId) {
<adf-alfresco-viewer <adf-alfresco-viewer
[ngClass]="{ [ngClass]="{
'aca-right_side--hide': !showRightSide 'aca-right_side--hide': !showRightSide
@@ -16,19 +16,23 @@
(showViewerChange)="onVisibilityChanged($event)" (showViewerChange)="onVisibilityChanged($event)"
(navigateBefore)="onNavigateBefore($event)" (navigateBefore)="onNavigateBefore($event)"
(navigateNext)="onNavigateNext($event)" (navigateNext)="onNavigateNext($event)"
> >
<adf-viewer-sidebar *ngIf="infoDrawerOpened$ | async"> @if (infoDrawerOpened$ | async) {
<aca-info-drawer [node]="selection.file" /> <adf-viewer-sidebar>
</adf-viewer-sidebar> <aca-info-drawer [node]="selection.file" />
</adf-viewer-sidebar>
<adf-viewer-open-with *ngIf="openWith.length"> }
<ng-container *ngFor="let action of openWith; trackBy: trackByActionId"> @if (openWith.length) {
<app-toolbar-menu-item [actionRef]="action" /> <adf-viewer-open-with>
</ng-container> @for (action of openWith; track trackByActionId($index, action)) {
</adf-viewer-open-with> <app-toolbar-menu-item [actionRef]="action" />
}
<adf-viewer-toolbar-actions *ngIf="!simplestMode"> </adf-viewer-open-with>
<aca-toolbar [items]="viewerToolbarActions" /> }
</adf-viewer-toolbar-actions> @if (!simplestMode) {
<adf-viewer-toolbar-actions>
<aca-toolbar [items]="viewerToolbarActions" />
</adf-viewer-toolbar-actions>
}
</adf-alfresco-viewer> </adf-alfresco-viewer>
</ng-container> }
@@ -1,4 +1,4 @@
<ng-container *ngIf="nodeId"> @if (nodeId) {
<adf-alfresco-viewer <adf-alfresco-viewer
[ngClass]="{ [ngClass]="{
'aca-right_side--hide': !showRightSide 'aca-right_side--hide': !showRightSide
@@ -21,19 +21,21 @@
[canNavigateNext]="!!nextNodeId" [canNavigateNext]="!!nextNodeId"
(navigateBefore)="onNavigateBefore($event)" (navigateBefore)="onNavigateBefore($event)"
(navigateNext)="onNavigateNext($event)" (navigateNext)="onNavigateNext($event)"
> >
<adf-viewer-sidebar *ngIf="infoDrawerOpened$ | async"> @if (infoDrawerOpened$ | async) {
<aca-info-drawer [node]="selection.file" /> <adf-viewer-sidebar>
</adf-viewer-sidebar> <aca-info-drawer [node]="selection.file" />
</adf-viewer-sidebar>
<adf-viewer-open-with *ngIf="openWith.length"> }
<ng-container *ngFor="let action of openWith; trackBy: trackByActionId"> @if (openWith.length) {
<app-toolbar-menu-item [actionRef]="action" /> <adf-viewer-open-with>
</ng-container> @for (action of openWith; track trackByActionId($index, action)) {
</adf-viewer-open-with> <app-toolbar-menu-item [actionRef]="action" />
}
</adf-viewer-open-with>
}
<adf-viewer-toolbar-actions> <adf-viewer-toolbar-actions>
<aca-toolbar [items]="toolbarActions" /> <aca-toolbar [items]="toolbarActions" />
</adf-viewer-toolbar-actions> </adf-viewer-toolbar-actions>
</adf-alfresco-viewer> </adf-alfresco-viewer>
</ng-container> }
@@ -5,7 +5,7 @@
"declarationMap": true, "declarationMap": true,
"target": "es2020", "target": "es2020",
"module": "es2015", "module": "es2015",
"moduleResolution": "node", "moduleResolution": "bundler",
"declaration": true, "declaration": true,
"sourceMap": true, "sourceMap": true,
"inlineSources": true, "inlineSources": true,
@@ -1,12 +1,15 @@
<div *ngIf="isLoading"> @if (isLoading) {
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'APP.INFO_DRAWER.DATA_LOADING' | translate" /> <div>
</div> <mat-progress-bar mode="indeterminate" [attr.aria-label]="'APP.INFO_DRAWER.DATA_LOADING' | translate" />
<ng-container *ngIf="!isLoading && !!displayNode"> </div>
}
@if (!isLoading && !!displayNode) {
<adf-info-drawer class="aca-info-drawer" [icon]="icon" [title]="node?.entry?.name || 'APP.INFO_DRAWER.TITLE'" cdkTrapFocusAutoCapture> <adf-info-drawer class="aca-info-drawer" [icon]="icon" [title]="node?.entry?.name || 'APP.INFO_DRAWER.TITLE'" cdkTrapFocusAutoCapture>
<aca-toolbar [items]="actions" info-drawer-buttons /> <aca-toolbar [items]="actions" info-drawer-buttons />
@for (tab of tabs; track tab) {
<adf-info-drawer-tab *ngFor="let tab of tabs" [icon]="tab.icon" [label]="tab.title"> <adf-info-drawer-tab [icon]="tab.icon" [label]="tab.title">
<adf-dynamic-tab [node]="$any(displayNode)" [id]="tab.component" [attr.data-automation-id]="tab.component" /> <adf-dynamic-tab [node]="$any(displayNode)" [id]="tab.component" [attr.data-automation-id]="tab.component" />
</adf-info-drawer-tab> </adf-info-drawer-tab>
}
</adf-info-drawer> </adf-info-drawer>
</ng-container> }
@@ -29,7 +29,6 @@ import { Store } from '@ngrx/store';
import { infoDrawerPreview, SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store'; import { infoDrawerPreview, SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store';
import { AppExtensionService } from '../../services/app.extension.service'; import { AppExtensionService } from '../../services/app.extension.service';
import { ContentApiService } from '../../services/content-api.service'; import { ContentApiService } from '../../services/content-api.service';
import { CommonModule } from '@angular/common';
import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar';
import { InfoDrawerComponent as AdfInfoDrawerComponent, InfoDrawerTabComponent } from '@alfresco/adf-core'; import { InfoDrawerComponent as AdfInfoDrawerComponent, InfoDrawerTabComponent } from '@alfresco/adf-core';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
@@ -39,16 +38,7 @@ import { ContentService, NodesApiService } from '@alfresco/adf-content-services'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
imports: [ imports: [TranslatePipe, MatProgressBarModule, AdfInfoDrawerComponent, A11yModule, ToolbarComponent, DynamicTabComponent, InfoDrawerTabComponent],
CommonModule,
TranslatePipe,
MatProgressBarModule,
AdfInfoDrawerComponent,
A11yModule,
ToolbarComponent,
DynamicTabComponent,
InfoDrawerTabComponent
],
selector: 'aca-info-drawer', selector: 'aca-info-drawer',
templateUrl: './info-drawer.component.html', templateUrl: './info-drawer.component.html',
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
@@ -8,15 +8,17 @@
<div class="aca-open-in-app-button-container"> <div class="aca-open-in-app-button-container">
<button mat-button (click)="openInApp()" <button mat-button (click)="openInApp()"
data-automation-id="open-in-app-button" data-automation-id="open-in-app-button"
class="aca-open-in-app-button-container" cdkFocusInitial> class="aca-open-in-app-button-container" cdkFocusInitial>
<span>{{ 'APP.DIALOGS.MOBILE_APP.MOBILE_APP_BUTTON_LABEL' | translate }}</span> <span>{{ 'APP.DIALOGS.MOBILE_APP.MOBILE_APP_BUTTON_LABEL' | translate }}</span>
</button> </button>
</div> </div>
<div class="aca-download-app-container" *ngIf="appStoreUrl"> @if (appStoreUrl) {
<button mat-button data-automation-id="download-app-button" class="aca-download-app-container-button" (click)="downloadIosApp()"> <div class="aca-download-app-container">
<span>{{ 'APP.DIALOGS.MOBILE_APP.DOWNLOAD_APP_BUTTON_LABEL' | translate }}</span> <button mat-button data-automation-id="download-app-button" class="aca-download-app-container-button" (click)="downloadIosApp()">
</button> <span>{{ 'APP.DIALOGS.MOBILE_APP.DOWNLOAD_APP_BUTTON_LABEL' | translate }}</span>
</div> </button>
</div>
}
</div> </div>
@@ -24,7 +24,6 @@
import { Component, ViewEncapsulation, inject } from '@angular/core'; import { Component, ViewEncapsulation, inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -35,7 +34,7 @@ export interface OpenInAppDialogOptions {
appStoreUrl: string; appStoreUrl: string;
} }
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule, A11yModule, MatDialogModule], imports: [TranslatePipe, MatButtonModule, MatIconModule, A11yModule, MatDialogModule],
selector: 'aca-open-in-app', selector: 'aca-open-in-app',
templateUrl: './open-in-app.component.html', templateUrl: './open-in-app.component.html',
styleUrls: ['./open-in-app.component.scss'], styleUrls: ['./open-in-app.component.scss'],
@@ -1,5 +1,6 @@
<div class="aca-content-header"> <div class="aca-content-header">
<button *ngIf="(appNavNarMode$ | async) === 'collapsed'" @if ((appNavNarMode$ | async) === 'collapsed') {
<button
mat-icon-button mat-icon-button
class="aca-content-header-button" class="aca-content-header-button"
(click)="toggleClick()" (click)="toggleClick()"
@@ -8,13 +9,14 @@
adf-auto-focus> adf-auto-focus>
<mat-icon>keyboard_double_arrow_right</mat-icon> <mat-icon>keyboard_double_arrow_right</mat-icon>
</button> </button>
<ng-content select=".aca-page-layout-header, aca-page-layout-header" /> }
<ng-content select=".aca-page-layout-header, aca-page-layout-header" />
</div> </div>
<ng-container *ngIf="hasError"> @if (hasError) {
<ng-content select=".aca-page-layout-error, aca-page-layout-error" /> <ng-content select=".aca-page-layout-error, aca-page-layout-error" />
</ng-container> }
<ng-container *ngIf="!hasError"> @if (!hasError) {
<ng-content select=".aca-page-layout-content, aca-page-layout-content" /> <ng-content select=".aca-page-layout-content, aca-page-layout-content" />
</ng-container> }
@@ -1,19 +1,24 @@
<ng-container [ngSwitch]="actionRef.type">
<div *ngSwitchCase="'default'">
<app-toolbar-button [type]="type" [actionRef]="actionRef" [color]="color" />
</div>
<div *ngSwitchCase="'button'"> @switch (actionRef.type) {
<app-toolbar-button [type]="data?.buttonType || type" [actionRef]="actionRef" [color]="color" [data]="actionRef.data" /> @case ('default') {
</div> <div>
<app-toolbar-button [type]="type" [actionRef]="actionRef" [color]="color" />
<div *ngSwitchCase="'separator'" [id]="actionRef.id" class="aca-toolbar-divider"></div> </div>
}
<ng-container *ngSwitchCase="'menu'"> @case ('button') {
<div>
<app-toolbar-button [type]="data?.buttonType || type" [actionRef]="actionRef" [color]="color" [data]="actionRef.data" />
</div>
}
@case ('separator') {
<div [id]="actionRef.id" class="aca-toolbar-divider"></div>
}
@case ('menu') {
<app-toolbar-menu [actionRef]="actionRef" [color]="color" [data]="actionRef.data" /> <app-toolbar-menu [actionRef]="actionRef" [color]="color" [data]="actionRef.data" />
</ng-container> }
@case ('custom') {
<div *ngSwitchCase="'custom'"> <div>
<adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" /> <adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" />
</div> </div>
</ng-container> }
}
@@ -26,11 +26,10 @@ import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input, DoCheck,
import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions'; import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { ToolbarButtonComponent, ToolbarButtonType } from '../toolbar-button/toolbar-button.component'; import { ToolbarButtonComponent, ToolbarButtonType } from '../toolbar-button/toolbar-button.component';
import { ThemePalette } from '@angular/material/core'; import { ThemePalette } from '@angular/material/core';
import { CommonModule } from '@angular/common';
import { ToolbarMenuComponent } from '../toolbar-menu/toolbar-menu.component'; import { ToolbarMenuComponent } from '../toolbar-menu/toolbar-menu.component';
@Component({ @Component({
imports: [CommonModule, ToolbarButtonComponent, ToolbarMenuComponent, DynamicExtensionComponent], imports: [ToolbarButtonComponent, ToolbarMenuComponent, DynamicExtensionComponent],
selector: 'aca-toolbar-action', selector: 'aca-toolbar-action',
templateUrl: './toolbar-action.component.html', templateUrl: './toolbar-action.component.html',
styleUrl: './toolbar-action.component.scss', styleUrl: './toolbar-action.component.scss',
@@ -1,5 +1,6 @@
<ng-container [ngSwitch]="data?.buttonType || type">
<ng-container *ngSwitchCase="'icon-button'"> @switch (data?.buttonType || type) {
@case ('icon-button') {
<button <button
[id]="actionRef.id" [id]="actionRef.id"
mat-icon-button mat-icon-button
@@ -8,12 +9,11 @@
[attr.title]="actionRef.description || actionRef.title | translate" [attr.title]="actionRef.description || actionRef.title | translate"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
(click)="runAction()" (click)="runAction()"
> >
<adf-icon [value]="actionRef.icon" /> <adf-icon [value]="actionRef.icon" />
</button> </button>
</ng-container> }
@case ('flat-button') {
<ng-container *ngSwitchCase="'flat-button'">
<button <button
[id]="actionRef.id" [id]="actionRef.id"
[color]="data?.color || color" [color]="data?.color || color"
@@ -22,12 +22,13 @@
[attr.title]="actionRef.description || actionRef.title | translate" [attr.title]="actionRef.description || actionRef.title | translate"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
(click)="runAction()" (click)="runAction()"
> >
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span> @if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button> </button>
</ng-container> }
@case ('stroked-button') {
<ng-container *ngSwitchCase="'stroked-button'">
<button <button
[id]="actionRef.id" [id]="actionRef.id"
[color]="data?.color || color" [color]="data?.color || color"
@@ -36,12 +37,13 @@
[attr.title]="actionRef.description || actionRef.title | translate" [attr.title]="actionRef.description || actionRef.title | translate"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
(click)="runAction()" (click)="runAction()"
> >
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span> @if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button> </button>
</ng-container> }
@case ('menu-item') {
<ng-container *ngSwitchCase="'menu-item'">
<app-toolbar-menu-item [actionRef]="actionRef" /> <app-toolbar-menu-item [actionRef]="actionRef" />
</ng-container> }
</ng-container> }
@@ -26,7 +26,6 @@ import { Component, Input, ViewEncapsulation, inject } from '@angular/core';
import { ContentActionRef } from '@alfresco/adf-extensions'; import { ContentActionRef } from '@alfresco/adf-extensions';
import { AppExtensionService } from '../../../services/app.extension.service'; import { AppExtensionService } from '../../../services/app.extension.service';
import { ThemePalette } from '@angular/material/core'; import { ThemePalette } from '@angular/material/core';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item.component'; import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item.component';
@@ -40,7 +39,7 @@ export enum ToolbarButtonType {
} }
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, ToolbarMenuItemComponent, IconComponent], imports: [TranslatePipe, MatButtonModule, ToolbarMenuItemComponent, IconComponent],
selector: 'app-toolbar-button', selector: 'app-toolbar-button',
templateUrl: './toolbar-button.component.html', templateUrl: './toolbar-button.component.html',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -1,26 +1,23 @@
<ng-container [ngSwitch]="actionRef.type">
<ng-container *ngSwitchCase="'menu'"> @switch (actionRef.type) {
@case ('menu') {
<button [id]="actionRef.id" mat-menu-item role="menuitem" tabindex="0" [disabled]="actionRef.disabled" [matMenuTriggerFor]="childMenu"> <button [id]="actionRef.id" mat-menu-item role="menuitem" tabindex="0" [disabled]="actionRef.disabled" [matMenuTriggerFor]="childMenu">
<adf-icon [value]="actionRef.icon" /> <adf-icon [value]="actionRef.icon" />
<span data-automation-id="menu-item-title">{{ actionRef.title | translate }}</span> <span data-automation-id="menu-item-title">{{ actionRef.title | translate }}</span>
</button> </button>
<mat-menu #childMenu="matMenu" class="app-create-menu__sub-menu"> <mat-menu #childMenu="matMenu" class="app-create-menu__sub-menu">
<ng-container *ngFor="let child of actionRef.children; trackBy: trackByActionId"> @for (child of actionRef.children; track trackByActionId($index, child)) {
<app-toolbar-menu-item [actionRef]="child" /> <app-toolbar-menu-item [actionRef]="child" />
</ng-container> }
</mat-menu> </mat-menu>
</ng-container> }
@case ('separator') {
<ng-container *ngSwitchCase="'separator'">
<mat-divider aria-hidden="true" /> <mat-divider aria-hidden="true" />
</ng-container> }
@case ('custom') {
<ng-container *ngSwitchCase="'custom'">
<adf-dynamic-component [id]="actionRef.component" /> <adf-dynamic-component [id]="actionRef.component" />
</ng-container> }
@default {
<ng-container *ngSwitchDefault>
<button <button
[id]="actionRef.id" [id]="actionRef.id"
role="menuitem" role="menuitem"
@@ -30,9 +27,9 @@
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
[attr.title]="(actionRef.disabled ? actionRef['description-disabled'] : actionRef.description || actionRef.title) | translate" [attr.title]="(actionRef.disabled ? actionRef['description-disabled'] : actionRef.description || actionRef.title) | translate"
(click)="runAction()" (click)="runAction()"
> >
<adf-icon [value]="actionRef.icon" class="app-toolbar-menu-item--icon" /> <adf-icon [value]="actionRef.icon" class="app-toolbar-menu-item--icon" />
<span data-automation-id="menu-item-title">{{ actionRef.title | translate }}</span> <span data-automation-id="menu-item-title">{{ actionRef.title | translate }}</span>
</button> </button>
</ng-container> }
</ng-container> }
@@ -26,13 +26,12 @@ import { AfterViewInit, Component, Input, ViewChild, ViewEncapsulation, inject }
import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions'; import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { AppExtensionService } from '../../../services/app.extension.service'; import { AppExtensionService } from '../../../services/app.extension.service';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu'; import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
import { IconComponent } from '@alfresco/adf-core'; import { IconComponent } from '@alfresco/adf-core';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent], imports: [TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent],
selector: 'app-toolbar-menu-item', selector: 'app-toolbar-menu-item',
templateUrl: './toolbar-menu-item.component.html', templateUrl: './toolbar-menu-item.component.html',
styleUrls: ['./toolbar-menu-item.component.scss'], styleUrls: ['./toolbar-menu-item.component.scss'],
@@ -1,5 +1,6 @@
<ng-container [ngSwitch]="type">
<ng-container *ngSwitchCase="'button'"> @switch (type) {
@case ('button') {
<button <button
[id]="actionRef.id" [id]="actionRef.id"
[color]="data?.color || color" [color]="data?.color || color"
@@ -9,12 +10,13 @@
[matMenuTriggerFor]="menu" [matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger" #matTrigger="matMenuTrigger"
> >
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span> @if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button> </button>
</ng-container> }
@case ('flat-button') {
<ng-container *ngSwitchCase="'flat-button'">
<button <button
[id]="actionRef.id" [id]="actionRef.id"
[color]="data?.color || color" [color]="data?.color || color"
@@ -24,12 +26,13 @@
[matMenuTriggerFor]="menu" [matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger" #matTrigger="matMenuTrigger"
> >
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span> @if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button> </button>
</ng-container> }
@case ('stroked-button') {
<ng-container *ngSwitchCase="'stroked-button'">
<button <button
[id]="actionRef.id" [id]="actionRef.id"
[color]="data?.color || color" [color]="data?.color || color"
@@ -39,12 +42,13 @@
[matMenuTriggerFor]="menu" [matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger" #matTrigger="matMenuTrigger"
> >
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span> @if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button> </button>
</ng-container> }
@default {
<ng-container *ngSwitchDefault>
<button <button
[id]="actionRef.id" [id]="actionRef.id"
[color]="data?.color || color" [color]="data?.color || color"
@@ -54,21 +58,23 @@
[matMenuTriggerFor]="menu" [matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled" [disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger" #matTrigger="matMenuTrigger"
> >
<adf-icon *ngIf="actionRef.icon" [value]="actionRef.icon" /> @if (actionRef.icon) {
<adf-icon [value]="actionRef.icon" />
}
</button> </button>
</ng-container> }
</ng-container> }
<mat-menu #menu="matMenu" [overlapTrigger]="false" [xPosition]="'before'"> <mat-menu #menu="matMenu" [overlapTrigger]="false" [xPosition]="'before'">
<ng-container *ngFor="let child of actionRef.children; trackBy: trackByActionId"> @for (child of actionRef.children; track trackByActionId($index, child)) {
<ng-container [ngSwitch]="child.type"> @switch (child.type) {
<ng-container *ngSwitchCase="'custom'"> @case ('custom') {
<adf-dynamic-component [id]="child.component" [data]="child.data" /> <adf-dynamic-component [id]="child.component" [data]="child.data" />
</ng-container> }
<ng-container *ngSwitchDefault> @default {
<app-toolbar-menu-item [actionRef]="child" [menuId]="actionRef.id" /> <app-toolbar-menu-item [actionRef]="child" [menuId]="actionRef.id" />
</ng-container> }
</ng-container> }
</ng-container> }
</mat-menu> </mat-menu>
@@ -27,13 +27,12 @@ import { ContentActionRef, ContentActionType, DynamicExtensionComponent } from '
import { MatMenu, MatMenuItem, MatMenuModule, MatMenuTrigger } from '@angular/material/menu'; import { MatMenu, MatMenuItem, MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
import { ThemePalette } from '@angular/material/core'; import { ThemePalette } from '@angular/material/core';
import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item.component'; import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item.component';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { TranslatePipe } from '@ngx-translate/core'; import { TranslatePipe } from '@ngx-translate/core';
import { IconComponent } from '@alfresco/adf-core'; import { IconComponent } from '@alfresco/adf-core';
@Component({ @Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, MatMenuModule, ToolbarMenuItemComponent, IconComponent, DynamicExtensionComponent], imports: [TranslatePipe, MatButtonModule, MatMenuModule, ToolbarMenuItemComponent, IconComponent, DynamicExtensionComponent],
selector: 'app-toolbar-menu', selector: 'app-toolbar-menu',
templateUrl: './toolbar-menu.component.html', templateUrl: './toolbar-menu.component.html',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@@ -1,5 +1,5 @@
<mat-toolbar class="aca-toolbar"> <mat-toolbar class="aca-toolbar">
<ng-container *ngFor="let item of items; trackBy: trackByActionId"> @for (item of items; track trackByActionId($index, item)) {
<aca-toolbar-action [actionRef]="item" /> <aca-toolbar-action [actionRef]="item" />
</ng-container> }
</mat-toolbar> </mat-toolbar>
@@ -23,14 +23,13 @@
*/ */
import { Component, Input, ViewEncapsulation } from '@angular/core'; import { Component, Input, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ContentActionRef } from '@alfresco/adf-extensions'; import { ContentActionRef } from '@alfresco/adf-extensions';
import { ToolbarActionComponent } from './toolbar-action/toolbar-action.component'; import { ToolbarActionComponent } from './toolbar-action/toolbar-action.component';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
@Component({ @Component({
selector: 'aca-toolbar', selector: 'aca-toolbar',
imports: [CommonModule, ToolbarActionComponent, MatToolbarModule], imports: [ToolbarActionComponent, MatToolbarModule],
templateUrl: './toolbar.component.html', templateUrl: './toolbar.component.html',
styleUrls: ['./toolbar.component.scss'], styleUrls: ['./toolbar.component.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
+1 -1
View File
@@ -5,7 +5,7 @@
"declarationMap": true, "declarationMap": true,
"target": "es2020", "target": "es2020",
"module": "es2015", "module": "es2015",
"moduleResolution": "node", "moduleResolution": "bundler",
"declaration": true, "declaration": true,
"sourceMap": true, "sourceMap": true,
"inlineSources": true, "inlineSources": true,
+2 -1
View File
@@ -8,7 +8,7 @@
"sourceMap": true, "sourceMap": true,
"declaration": false, "declaration": false,
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "bundler",
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"skipLibCheck": true, "skipLibCheck": true,
@@ -55,6 +55,7 @@
"preserveWhitespaces": false, "preserveWhitespaces": false,
"fullTemplateTypeCheck": true, "fullTemplateTypeCheck": true,
"strictInjectionParameters": true, "strictInjectionParameters": true,
"typeCheckHostBindings": false,
"strictTemplates": true "strictTemplates": true
} }
} }
+2 -1
View File
@@ -8,7 +8,7 @@
"sourceMap": true, "sourceMap": true,
"declaration": false, "declaration": false,
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "bundler",
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"skipLibCheck": true, "skipLibCheck": true,
@@ -41,6 +41,7 @@
"preserveWhitespaces": false, "preserveWhitespaces": false,
"fullTemplateTypeCheck": true, "fullTemplateTypeCheck": true,
"strictInjectionParameters": true, "strictInjectionParameters": true,
"typeCheckHostBindings": false,
"strictTemplates": true "strictTemplates": true
} }
} }