[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
@@ -12,29 +12,37 @@
<div class="aca-page-layout-content aca-scrollable">
<adf-about>
<adf-about-panel *ngIf="dev" [label]="'ABOUT.SERVER_SETTINGS.TITLE' | translate">
<ng-template>
@if (dev) {
<adf-about-panel [label]="'ABOUT.SERVER_SETTINGS.TITLE' | translate">
<ng-template>
<adf-about-server-settings />
</ng-template>
</adf-about-panel>
</ng-template>
</adf-about-panel>
}
<adf-about-panel [label]="'ABOUT.REPOSITORY' | translate" *ngIf="repository">
<ng-template>
@if (repository) {
<adf-about-panel [label]="'ABOUT.REPOSITORY' | translate">
<ng-template>
<adf-about-repository-info [data]="repository" />
</ng-template>
</adf-about-panel>
</ng-template>
</adf-about-panel>
}
<adf-about-panel *ngIf="dev" [label]="'ABOUT.PACKAGES.TITLE' | translate">
<ng-template>
@if (dev) {
<adf-about-panel [label]="'ABOUT.PACKAGES.TITLE' | translate">
<ng-template>
<adf-about-package-list [dependencies]="packageJson?.dependencies" />
</ng-template>
</adf-about-panel>
</ng-template>
</adf-about-panel>
}
<adf-about-panel *ngIf="extensions$ | async as extensions" [label]="'ABOUT.PLUGINS.TITLE' | translate">
<ng-template>
@if (extensions$ | async; as extensions) {
<adf-about-panel [label]="'ABOUT.PLUGINS.TITLE' | translate">
<ng-template>
<adf-about-extension-list [data]="extensions" />
</ng-template>
</adf-about-panel>
</ng-template>
</adf-about-panel>
}
</adf-about>
</div>
</aca-page-layout>
@@ -10,19 +10,15 @@
<div class="aca-page-layout-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" />
</ng-container>
<ng-template #onLoaded>
<ng-container *ngIf="folderInfo$ | async; else genericError">
} @else {
@if (folderInfo$ | async) {
<mat-toolbar class="aca-manage-rules__toolbar aca-manage-rules__actions-bar">
<span class="aca-manage-rules__actions-bar__title">
<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>
<mat-slide-toggle
data-automation-id="manage-rules-inheritance-toggle-button"
class="aca-manage-rules__actions-bar__toggle"
@@ -32,104 +28,96 @@
[labelPosition]="'before'">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.INHERIT_RULES' | translate }}
</mat-slide-toggle>
<mat-divider vertical class="aca-manage-rules__actions-bar__vertical-divider" aria-hidden="true" />
<div class="aca-manage-rules__actions-bar__buttons">
<button
*ngIf="!(mainRuleSet$ | async)"
data-automation-id="manage-rules-link-button"
mat-stroked-button
(click)="openLinkRulesDialog()">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.LINK_RULES' | translate }}
</button>
<button
*ngIf="canEditMainRule"
data-automation-id="manage-rules-create-button"
mat-flat-button
(click)="openCreateUpdateRuleDialog()">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.CREATE_RULE' | translate }}
</button>
@if (!(mainRuleSet$ | async)) {
<button
data-automation-id="manage-rules-link-button"
mat-stroked-button
(click)="openLinkRulesDialog()">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.LINK_RULES' | translate }}
</button>
}
@if (canEditMainRule) {
<button
data-automation-id="manage-rules-create-button"
mat-flat-button
(click)="openCreateUpdateRuleDialog()">
{{ 'ACA_FOLDER_RULES.MANAGE_RULES.TOOLBAR.ACTIONS.CREATE_RULE' | translate }}
</button>
}
</div>
</mat-toolbar>
<mat-divider aria-hidden="true" />
<div class="aca-manage-rules__container" *ngIf="isMainRuleSetNotEmpty || isInheritedRuleSetsNotEmpty; else emptyContent">
<aca-rule-list
[mainRuleSet$]="mainRuleSet$"
[folderId]="nodeId"
[inheritedRuleSets]="inheritedRuleSets$ | async"
[hasMoreRuleSets]="hasMoreRuleSets$ | async"
[ruleSetsLoading]="ruleSetsLoading$ | async"
[selectedRule]="selectedRule$ | async"
(loadMoreRuleSets)="onLoadMoreRuleSets()"
(loadMoreRules)="onLoadMoreRules($event)"
(selectRule)="onSelectRule($event)"
(ruleEnabledChanged)="onRuleEnabledToggle($event[0], $event[1])"
(ruleSetEditLinkClicked)="openLinkRulesDialog($event)"
(ruleSetUnlinkClicked)="onRuleSetUnlinkClicked($event)" />
<div class="aca-manage-rules__container__rule-details">
<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__name">
{{ selectedRule.name }}
@if (isMainRuleSetNotEmpty || isInheritedRuleSetsNotEmpty) {
<div class="aca-manage-rules__container">
<aca-rule-list
[mainRuleSet$]="mainRuleSet$"
[folderId]="nodeId"
[inheritedRuleSets]="inheritedRuleSets$ | async"
[hasMoreRuleSets]="hasMoreRuleSets$ | async"
[ruleSetsLoading]="ruleSetsLoading$ | async"
[selectedRule]="selectedRule$ | async"
(loadMoreRuleSets)="onLoadMoreRuleSets()"
(loadMoreRules)="onLoadMoreRules($event)"
(selectRule)="onSelectRule($event)"
(ruleEnabledChanged)="onRuleEnabledToggle($event[0], $event[1])"
(ruleSetEditLinkClicked)="openLinkRulesDialog($event)"
(ruleSetUnlinkClicked)="onRuleSetUnlinkClicked($event)" />
<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__title">
<div class="aca-manage-rules__container__rule-details__header__title__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 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 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>
<ng-template #emptyContent>
} @else {
<adf-empty-content
icon="library_books"
[title]="'ACA_FOLDER_RULES.MANAGE_RULES.EMPTY_RULES_LIST.TITLE' | translate"
[subtitle]="'ACA_FOLDER_RULES.MANAGE_RULES.EMPTY_RULES_LIST.SUBTITLE' | translate"
/>
</ng-template>
</ng-container>
<ng-template #genericError>
/>
}
} @else {
<div class="aca-page-layout-error">
<aca-generic-error />
</div>
</ng-template>
</ng-template>
}
}
</div>
</div>
@@ -1,33 +1,37 @@
<div class="aca-rule-action-list__item" [attr.aria-labelledby]="'rule-actions-label'" *ngFor="let control of formControls">
<aca-rule-action
[actionDefinitions]="actionDefinitions"
[parameterConstraints]="parameterConstraints"
[readOnly]="readOnly"
[formControl]="control"
[nodeId]="nodeId" />
@for (control of formControls; track control) {
<div class="aca-rule-action-list__item" [attr.aria-labelledby]="'rule-actions-label'">
<aca-rule-action
[actionDefinitions]="actionDefinitions"
[parameterConstraints]="parameterConstraints"
[readOnly]="readOnly"
[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
mat-icon-button
data-automation-id="rule-action-list-action-menu"
[attr.aria-label]="'ACA_FOLDER_RULES.EDIT_RULE_DIALOG.OPEN_ACTION_MENU' | translate"
*ngIf="!readOnly" [matMenuTriggerFor]="menu">
<mat-icon>more_vert</mat-icon>
@if (!readOnly) {
<button mat-flat-button class="aca-rule-action-list-add-action-button" data-automation-id="rule-action-list-add-action-button" (click)="addAction()">
<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>
<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 { ruleActionValidator } from '../validators/rule-actions.validator';
import { ActionParameterConstraint } from '../../model/action-parameter-constraint.model';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { RuleActionUiComponent } from './rule-action.ui-component';
import { MatButtonModule } from '@angular/material/button';
@@ -36,7 +35,7 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
@Component({
imports: [CommonModule, TranslatePipe, RuleActionUiComponent, ReactiveFormsModule, MatButtonModule, MatMenuModule, MatIconModule],
imports: [TranslatePipe, RuleActionUiComponent, ReactiveFormsModule, MatButtonModule, MatMenuModule, MatIconModule],
selector: 'aca-rule-action-list',
templateUrl: './rule-action-list.ui-component.html',
styleUrls: ['./rule-action-list.ui-component.scss'],
@@ -5,20 +5,22 @@
formControlName="actionDefinitionId"
data-automation-id="rule-action-select"
[placeholder]="'ACA_FOLDER_RULES.RULE_DETAILS.ACTION_SELECT_PLACEHOLDER' | translate">
<mat-option
*ngFor="let actionDefinition of actionDefinitions"
[value]="actionDefinition.id">
{{ actionDefinition.title }}
</mat-option>
@for (actionDefinition of actionDefinitions; track actionDefinition) {
<mat-option
[value]="actionDefinition.id">
{{ actionDefinition.title }}
</mat-option>
}
</mat-select>
<mat-error>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.ERROR.ACTION_REQUIRED' | translate}}</mat-error>
</mat-form-field>
<adf-card-view
*ngIf="cardViewItems?.length > 0"
data-automation-id="rule-action-card-view"
[properties]="cardViewItems"
class="aca-rule-action-full-width"
[editable]="!readOnly" />
@if (cardViewItems?.length > 0) {
<adf-card-view
data-automation-id="rule-action-card-view"
[properties]="cardViewItems"
class="aca-rule-action-full-width"
[editable]="!readOnly" />
}
</form>
@@ -51,13 +51,12 @@ import {
} from '@alfresco/adf-content-services';
import { MatDialog } from '@angular/material/dialog';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { CommonModule } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [CommonModule, TranslatePipe, ReactiveFormsModule, MatFormFieldModule, MatSelectModule, CardViewComponent],
imports: [TranslatePipe, ReactiveFormsModule, MatFormFieldModule, MatSelectModule, CardViewComponent],
selector: 'aca-rule-action',
templateUrl: './rule-action.ui-component.html',
styleUrls: ['./rule-action.ui-component.scss'],
@@ -1,72 +1,83 @@
<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">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.' + (childCondition ? 'NO_CONDITIONS_IN_GROUP' : 'NO_CONDITIONS') | translate }}
</div>
<div *ngIf="!hasNoConditions" class="aca-rule-composite-condition__form__no-conditions" data-automation-id="label-with-conditions">
<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>
@if (hasNoConditions) {
<div class="aca-rule-composite-condition__form__no-conditions" data-automation-id="no-conditions">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.' + (childCondition ? 'NO_CONDITIONS_IN_GROUP' : 'NO_CONDITIONS') | translate }}
</div>
}
@if (!hasNoConditions) {
<div class="aca-rule-composite-condition__form__no-conditions" data-automation-id="label-with-conditions">
<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
#conditionRow
[attr.aria-labelledby]="'conditions-group-label-' + (childCondition ? 'nested' : 'main')"
class="aca-rule-composite-condition__form__row"
*ngFor="let control of conditionFormControls; let i = index">
<mat-form-field *ngIf="i === 0">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.LOGIC_OPERATOR' | translate }}</mat-label>
<mat-select
[formControl]="invertedControl"
[disabled]="readOnly">
<mat-option [value]="false">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.IF' | translate }}</mat-option>
<mat-option [value]="true">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.NOT_IF' | translate }}</mat-option>
</mat-select>
</mat-form-field>
@for (control of conditionFormControls; track control; let i = $index) {
<fieldset
#conditionRow
[attr.aria-labelledby]="'conditions-group-label-' + (childCondition ? 'nested' : 'main')"
class="aca-rule-composite-condition__form__row"
>
@if (i === 0) {
<mat-form-field>
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.LOGIC_OPERATOR' | translate }}</mat-label>
<mat-select
[formControl]="invertedControl"
[disabled]="readOnly">
<mat-option [value]="false">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LOGIC_OPERATORS.IF' | translate }}</mat-option>
<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">
<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>
<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>
@if (!readOnly) {
<div class="aca-rule-composite-condition__form__actions" data-automation-id="add-actions">
<button mat-flat-button (click)="addSimpleCondition()" data-automation-id="add-condition-button">
<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>
</mat-menu>
</fieldset>
<div class="aca-rule-composite-condition__form__actions" *ngIf="!readOnly" data-automation-id="add-actions">
<button mat-flat-button (click)="addSimpleCondition()" data-automation-id="add-condition-button">
<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>
<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>
@@ -41,7 +41,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { RuleCompositeCondition } from '../../model/rule-composite-condition.model';
import { ControlValueAccessor, FormArray, FormControl, FormGroup, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
@@ -53,7 +52,6 @@ import { FocusTrapFactory } from '@angular/cdk/a11y';
@Component({
imports: [
CommonModule,
TranslatePipe,
ReactiveFormsModule,
MatFormFieldModule,
@@ -3,12 +3,16 @@
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.FIELD' | translate }}</mat-label>
<mat-select formControlName="field" data-automation-id="field-select"
(selectionChange)="onChangeField()">
<mat-option *ngIf="!isSelectedFieldKnown" [value]="selectedField.name" data-automation-id="unknown-field-option">
{{ selectedField.label }}
</mat-option>
<mat-option *ngFor="let field of fields" [value]="field.name">
{{ field.label | translate }}
</mat-option>
@if (!isSelectedFieldKnown) {
<mat-option [value]="selectedField.name" data-automation-id="unknown-field-option">
{{ selectedField.label }}
</mat-option>
}
@for (field of fields; track field.name) {
<mat-option [value]="field.name">
{{ field.label | translate }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -16,24 +20,27 @@
[class]="{ 'aca-hidden': isComparatorHidden }" data-automation-id="comparator-form-field">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.COMPARATOR' | translate }}</mat-label>
<mat-select formControlName="comparator" data-automation-id="comparator-select">
<mat-option
*ngFor="let comparator of selectedFieldComparators"
[value]="comparator.name">
{{ comparator.labels[this.selectedField?.type || 'equals'] | translate }}
</mat-option>
@for (comparator of selectedFieldComparators; track comparator.name) {
<mat-option [value]="comparator.name">
{{ comparator.labels[this.selectedField?.type || 'equals'] | translate }}
</mat-option>
}
</mat-select>
</mat-form-field>
<mat-form-field class="aca-rule-simple-condition__form__field-input aca-rule-simple-condition__form__parameter-input"
[ngSwitch]="selectedField.type">
<mat-form-field class="aca-rule-simple-condition__form__field-input aca-rule-simple-condition__form__parameter-input">
<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'">
<mat-option *ngFor="let mimeType of mimeTypes"
[value]="mimeType.value">
{{ mimeType.label }}
</mat-option>
</mat-select>
<ng-template [ngSwitchCase]="'auto-complete'">
@switch (selectedField.type) {
@case ('mimeType') {
<mat-select formControlName="parameter" data-automation-id="simple-condition-value-select">
@for (mimeType of mimeTypes; track mimeType.value) {
<mat-option [value]="mimeType.value">
{{ mimeType.label }}
</mat-option>
}
</mat-select>
}
@case ('auto-complete') {
<input
matInput
[matAutocomplete]="auto"
@@ -47,7 +54,8 @@
[autoActiveFirstOption]="true"
[autoSelectActiveOption]="true"
[displayWith]="autoCompleteDisplayFunction">
<mat-option disabled *ngIf="showLoadingSpinner; else optionList">
@if (showLoadingSpinner) {
<mat-option disabled>
<span class="aca-rule-simple-condition__auto-complete-loading-spinner">
<mat-progress-spinner
mode="indeterminate"
@@ -55,24 +63,24 @@
[diameter]="25" />
</span>
</mat-option>
<ng-template #optionList>
<ng-container *ngIf="autoCompleteOptions?.length > 0; else noOptionsTemplate">
<mat-option
*ngFor="let option of autoCompleteOptions"
[value]="option.value">
{{ option.displayLabel }}
</mat-option>
</ng-container>
<ng-template #noOptionsTemplate>
} @else {
@if (autoCompleteOptions?.length > 0) {
@for (option of autoCompleteOptions; track option.value) {
<mat-option [value]="option.value">
{{ option.displayLabel }}
</mat-option>
}
} @else {
<mat-option disabled>
{{ 'ACA_FOLDER_RULES.AUTOCOMPLETE.NO_OPTIONS_FOUND' | translate }}
</mat-option>
</ng-template>
</ng-template>
}
}
</mat-autocomplete>
</ng-template>
<ng-template ngSwitchDefault>
<input matInput placeholder="{{ 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.VALUE' | translate }}" type="text" formControlName="parameter" data-automation-id="value-input">
</ng-template>
}
@default {
<input matInput placeholder="{{ 'ACA_FOLDER_RULES.RULE_DETAILS.PLACEHOLDER.VALUE' | translate }}" type="text" formControlName="parameter" data-automation-id="value-input">
}
}
</mat-form-field>
</form>
@@ -27,7 +27,6 @@ import { AbstractControl, ControlValueAccessor, FormControl, FormGroup, NG_VALUE
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
import { comparatorHiddenForConditionFieldType, RuleConditionField, ruleConditionFields } from './rule-condition-fields';
import { RuleConditionComparator, ruleConditionComparators } from './rule-condition-comparators';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
@@ -51,7 +50,6 @@ const AUTOCOMPLETE_OPTIONS_DEBOUNCE_TIME = 500;
@Component({
imports: [
CommonModule,
TranslatePipe,
ReactiveFormsModule,
MatFormFieldModule,
@@ -1,48 +1,54 @@
<fieldset [formGroup]="form" [attr.aria-labelledby]="ariaLabelledBy">
<div class="aca-rule-options__option" *ngIf="!readOnly || isAsynchronousChecked">
<mat-checkbox
formControlName="isAsynchronous"
(change)="toggleErrorScriptDropdown($event)"
class="aca-rule-options__checkbox"
data-automation-id="rule-option-checkbox-asynchronous">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_ASYNCHRONOUS' | translate }}
</mat-checkbox>
<mat-form-field
data-automation-id="rule-option-form-field-errorScript"
class="aca-rule-options__error-script-dropdown"
[ngClass]="{ 'aca-hide-error-script-dropdown': hideErrorScriptDropdown }">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ERROR_SCRIPT' | translate }}</mat-label>
<mat-select
formControlName="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 *ngFor="let option of errorScriptOptions"
class="aca-rule-options__error-script-option"
[value]="option.value">
{{ option.label }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
@if (!readOnly || isAsynchronousChecked) {
<div class="aca-rule-options__option">
<mat-checkbox
formControlName="isAsynchronous"
(change)="toggleErrorScriptDropdown($event)"
class="aca-rule-options__checkbox"
data-automation-id="rule-option-checkbox-asynchronous">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_ASYNCHRONOUS' | translate }}
</mat-checkbox>
<mat-form-field
data-automation-id="rule-option-form-field-errorScript"
class="aca-rule-options__error-script-dropdown"
[ngClass]="{ 'aca-hide-error-script-dropdown': hideErrorScriptDropdown }">
<mat-label>{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.ERROR_SCRIPT' | translate }}</mat-label>
<mat-select
formControlName="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>
@for (option of errorScriptOptions; track option) {
<mat-option
class="aca-rule-options__error-script-option"
[value]="option.value">
{{ option.label }}
</mat-option>
}
</mat-select>
</mat-form-field>
</div>
}
<div class="aca-rule-options__option" *ngIf="!readOnly || isInheritableChecked">
<mat-checkbox
formControlName="isInheritable"
class="aca-rule-options__checkbox"
data-automation-id="rule-option-checkbox-inheritable">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_INHERITABLE' | translate }}
</mat-checkbox>
</div>
@if (!readOnly || isInheritableChecked) {
<div class="aca-rule-options__option">
<mat-checkbox
formControlName="isInheritable"
class="aca-rule-options__checkbox"
data-automation-id="rule-option-checkbox-inheritable">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.IS_INHERITABLE' | translate }}
</mat-checkbox>
</div>
}
<div class="aca-rule-options__option" *ngIf="!readOnly">
<mat-checkbox
formControlName="isDisabled"
class="aca-rule-options__checkbox"
data-automation-id="rule-option-checkbox-disabled">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.DISABLE_RULE' | translate }}
</mat-checkbox>
</div>
@if (!readOnly) {
<div class="aca-rule-options__option">
<mat-checkbox
formControlName="isDisabled"
class="aca-rule-options__checkbox"
data-automation-id="rule-option-checkbox-disabled">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.DISABLE_RULE' | translate }}
</mat-checkbox>
</div>
}
</fieldset>
@@ -1,6 +1,6 @@
<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">
<label class="aca-rule-details__name__label" for="rule-details-name-input">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.NAME' | translate }}</label>
<div>
@@ -16,33 +16,36 @@
</mat-form-field>
</div>
</div>
<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>
<div>
<mat-form-field class="aca-rule-details__form__row__field">
<textarea
class="aca-rule-details__form__row__field__textarea"
id="rule-details-description-textarea"
matInput formControlName="description" data-automation-id="rule-details-description-textarea"
[placeholder]="descriptionPlaceHolder | translate">
</textarea>
<textarea
class="aca-rule-details__form__row__field__textarea"
id="rule-details-description-textarea"
matInput formControlName="description" data-automation-id="rule-details-description-textarea"
[placeholder]="descriptionPlaceHolder | translate">
</textarea>
</mat-form-field>
</div>
</div>
</ng-container>
}
<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>
<div>
<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 class="aca-rule-details__form__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 class="aca-rule-details__form__row aca-rule-details__form__actions">
@@ -55,12 +58,14 @@
[nodeId]="nodeId" />
</div>
<div class="aca-rule-details__form__row aca-rule-details__form__others" *ngIf="showOptionsSection">
<span id="rule-options-label" class="aca-label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.OPTIONS' | translate }}</span>
<aca-rule-options
formControlName="options"
data-automation-id="rule-details-options-component"
[errorScriptConstraint]="errorScriptConstraint" />
</div>
@if (showOptionsSection) {
<div class="aca-rule-details__form__row aca-rule-details__form__others">
<span id="rule-options-label" class="aca-label">{{ 'ACA_FOLDER_RULES.RULE_DETAILS.LABEL.OPTIONS' | translate }}</span>
<aca-rule-options
formControlName="options"
data-automation-id="rule-details-options-component"
[errorScriptConstraint]="errorScriptConstraint" />
</div>
}
</form>
@@ -1,20 +1,21 @@
<fieldset [attr.aria-labelledby]="ariaLabelledBy">
<div *ngFor="let trigger of triggerOptions">
<ng-container *ngIf="readOnly; else checkbox">
<div
*ngIf="selectedTriggers[trigger]"
[attr.data-automation-id]="'rule-trigger-value-' + trigger | lowercase">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
</div>
</ng-container>
<ng-template #checkbox>
<mat-checkbox
[attr.data-automation-id]="'rule-trigger-checkbox-' + trigger | lowercase"
[checked]="selectedTriggers[trigger]"
(change)="onTriggerChange(trigger, $event.checked)">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
</mat-checkbox>
</ng-template>
</div>
@for (trigger of triggerOptions; track trigger) {
<div>
@if (readOnly) {
@if (selectedTriggers[trigger]) {
<div
[attr.data-automation-id]="'rule-trigger-value-' + trigger | lowercase">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
</div>
}
} @else {
<mat-checkbox
[attr.data-automation-id]="'rule-trigger-checkbox-' + trigger | lowercase"
[checked]="selectedTriggers[trigger]"
(change)="onTriggerChange(trigger, $event.checked)">
{{ 'ACA_FOLDER_RULES.RULE_DETAILS.TRIGGERS.' + trigger | uppercase | translate }}
</mat-checkbox>
}
</div>
}
</fieldset>
@@ -1,47 +1,42 @@
<ng-container *ngFor="let item of items">
<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"
@for (item of items; track item) {
@if (item.type === 'rule') {
<aca-rule-list-item
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"
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>
</ng-template>
<ng-template #loadingRules>
<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>
</ng-template>
</ng-container>
[rule]="item.rule"
[isSelected]="item.rule.id === this.selectedRule?.id"
[showEnabledToggle]="showEnabledToggles"
(click)="onRuleClicked(item.rule)"
(enabledChanged)="onEnabledChanged(item.rule, $event)" />
} @else {
@if (item.type === 'load-more-rules') {
<div
tabindex="0"
class="aca-rule-list-grouping__non-rule-item aca-load-more"
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>
} @else {
@if (item.type === 'load-more-rule-sets') {
<div
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 { RuleGroupingItem } from '../../model/rule-grouping-item.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 { MatRippleModule } from '@angular/material/core';
import { TranslatePipe } from '@ngx-translate/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@Component({
imports: [CommonModule, TranslatePipe, RuleListItemUiComponent, MatRippleModule, MatProgressSpinnerModule],
imports: [TranslatePipe, RuleListItemUiComponent, MatRippleModule, MatProgressSpinnerModule],
selector: 'aca-rule-list-grouping',
templateUrl: 'rule-list-grouping.ui-component.html',
styleUrls: ['rule-list-grouping.ui-component.scss'],
@@ -2,11 +2,12 @@
<span class="aca-rule-list-item__header__name">{{ rule.name }}</span>
<mat-slide-toggle
*ngIf="showEnabledToggle"
[checked]="rule.isEnabled"
[aria-label]="'ACA_FOLDER_RULES.RULE_LIST.TOGGLE_RULE_STATE' | translate: { name: rule.name }"
(click)="onToggleClick(!rule.isEnabled, $event)" />
@if (showEnabledToggle) {
<mat-slide-toggle
[checked]="rule.isEnabled"
[aria-label]="'ACA_FOLDER_RULES.RULE_LIST.TOGGLE_RULE_STATE' | translate: { name: rule.name }"
(click)="onToggleClick(!rule.isEnabled, $event)" />
}
</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 { Rule } from '../../model/rule.model';
import { CommonModule } from '@angular/common';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { TranslatePipe } from '@ngx-translate/core';
@Component({
imports: [CommonModule, MatSlideToggleModule, TranslatePipe],
imports: [MatSlideToggleModule, TranslatePipe],
selector: 'aca-rule-list-item',
templateUrl: 'rule-list-item.ui-component.html',
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 { RuleGroupingItem } from '../../model/rule-grouping-item.model';
import { FolderRuleSetsService } from '../../services/folder-rule-sets.service';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatRippleModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
@@ -41,7 +40,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [
CommonModule,
TranslatePipe,
MatRippleModule,
MatIconModule,
@@ -18,28 +18,25 @@
[rowFilter]="rowFilter" />
<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" />
</ng-container>
<ng-template #rulesLoaded>
<ng-container *ngIf="hasOwnedRules; else noOwnedRules">
} @else {
@if (hasOwnedRules) {
<div class="aca-rule-set-picker__content__rule-list__header">
{{ 'ACA_FOLDER_RULES.LINK_RULES_DIALOG.LIST_OF_RULES_TO_LINK' | translate }}
</div>
<aca-rule-list-item
*ngFor="let rule of (mainRuleSet$ | async).rules"
[rule]="rule" />
</ng-container>
<ng-template #noOwnedRules>
@for (rule of (mainRuleSet$ | async).rules; track rule) {
<aca-rule-list-item
[rule]="rule" />
}
} @else {
<adf-empty-content
icon="library_books"
[title]="'ACA_FOLDER_RULES.LINK_RULES_DIALOG.EMPTY_RULES_LIST.TITLE' | translate"
[subtitle]="'ACA_FOLDER_RULES.LINK_RULES_DIALOG.EMPTY_RULES_LIST.SUBTITLE' | translate" />
</ng-template>
</ng-template>
}
}
</div>
</mat-dialog-content>
@@ -1,50 +1,53 @@
<mat-form-field
*ngIf="items?.length"
class="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)"
@if (items?.length) {
<mat-form-field
class="aca-bulk-actions-form-field"
data-automation-id="aca-bulk-actions-form-field"
>
<div class="aca-bulk-actions-option-content">
<adf-icon
*ngIf="option.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>
<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">
@if (bulkSelectControl.value?.icon) {
<adf-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>
@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 { AppStore, getSearchItemsTotalCount } from '@alfresco/aca-shared/store';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { MatSelectModule } from '@angular/material/select';
import { Store } from '@ngrx/store';
@@ -40,7 +39,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
selector: 'aca-bulk-actions-dropdown',
templateUrl: './bulk-actions-dropdown.component.html',
styleUrls: ['./bulk-actions-dropdown.component.scss'],
imports: [CommonModule, TranslatePipe, MatSelectModule, IconComponent, ReactiveFormsModule],
imports: [TranslatePipe, MatSelectModule, IconComponent, ReactiveFormsModule],
encapsulation: ViewEncapsulation.None
})
export class BulkActionsDropdownComponent implements OnInit {
@@ -1,12 +1,11 @@
<ng-container *ngIf="selectionState">
<ng-container *ngIf="!data.iconButton">
@if (selectionState) {
@if (!data.iconButton) {
<button mat-menu-item data-automation-id="share-action-button" (click)="editSharedNode(selectionState, '.adf-context-menu-source')">
<mat-icon>link</mat-icon>
<span>{{ (isShared ? 'APP.ACTIONS.SHARE_EDIT' : 'APP.ACTIONS.SHARE') | translate }}</span>
</button>
</ng-container>
<ng-container *ngIf="data.iconButton">
}
@if (data.iconButton) {
<button
mat-icon-button
data-automation-id="share-action-button"
@@ -14,8 +13,8 @@
[attr.aria-label]="selectionLabel | translate"
[attr.title]="selectionLabel | translate"
id="share-action-button"
>
>
<mat-icon>link</mat-icon>
</button>
</ng-container>
</ng-container>
}
}
@@ -27,7 +27,6 @@ import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';
import { SelectionState } from '@alfresco/adf-extensions';
import { AppStore, getAppSelection, ShareNodeAction } from '@alfresco/aca-shared/store';
import { CommonModule } from '@angular/common';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
import { TranslatePipe } from '@ngx-translate/core';
@@ -35,7 +34,7 @@ import { MatButtonModule } from '@angular/material/button';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [CommonModule, MatMenuModule, MatIconModule, TranslatePipe, MatButtonModule],
imports: [MatMenuModule, MatIconModule, TranslatePipe, MatButtonModule],
selector: 'app-toggle-shared',
templateUrl: './toggle-shared.component.html',
encapsulation: ViewEncapsulation.None
@@ -1,5 +1,5 @@
<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">
<button class="aca-user-info-button">
<div>{{ user.initials || 'U' }}</div>
@@ -9,5 +9,5 @@
<div>{{ user.email }}</div>
</div>
</div>
</ng-container>
}
</button>
@@ -1,31 +1,27 @@
<div class="aca-context-menu">
<ng-container [ngSwitch]="actionRef.type">
<ng-container *ngSwitchCase="'menu'">
@switch (actionRef.type) {
@case ('menu') {
<button mat-menu-item [id]="actionRef.id" [matMenuTriggerFor]="childMenu">
<adf-icon [value]="actionRef.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="actionRef.id + '-label'">{{ actionRef.title | translate }}</span>
</button>
<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" />
</ng-container>
}
</mat-menu>
</ng-container>
<ng-container *ngSwitchCase="'separator'">
}
@case ('separator') {
<mat-divider aria-hidden="true" />
</ng-container>
<ng-container *ngSwitchCase="'custom'">
}
@case ('custom') {
<adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" />
</ng-container>
<ng-container *ngSwitchDefault>
}
@default {
<button mat-menu-item [id]="actionRef.id" (click)="runAction()">
<adf-icon [value]="actionRef.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="actionRef.id + '-label'">{{ actionRef.title | translate }}</span>
</button>
</ng-container>
</ng-container>
}
}
</div>
@@ -25,14 +25,13 @@
import { Component, Input, ViewEncapsulation, inject } from '@angular/core';
import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { AppExtensionService } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { MatMenuModule } from '@angular/material/menu';
import { TranslatePipe } from '@ngx-translate/core';
import { MatDividerModule } from '@angular/material/divider';
import { IconComponent } from '@alfresco/adf-core';
@Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent],
imports: [TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent],
selector: 'app-context-menu-item',
templateUrl: './context-menu-item.component.html',
encapsulation: ViewEncapsulation.None,
@@ -2,34 +2,32 @@
<div style="visibility: hidden;" [matMenuTriggerFor]="rootMenu"></div>
<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">
<ng-container *ngSwitchDefault>
<button mat-menu-item [id]="entry.id" (click)="runAction(entry)">
<adf-icon [value]="entry.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span>
</button>
</ng-container>
<ng-container *ngSwitchCase="'separator'">
<mat-divider aria-hidden="true" />
</ng-container>
<ng-container *ngSwitchCase="'menu'">
<button mat-menu-item [id]="entry.id" [matMenuTriggerFor]="childMenu">
<adf-icon [value]="entry.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span>
</button>
<mat-menu #childMenu="matMenu">
<ng-container *ngFor="let child of entry.children; trackBy: trackByActionId">
<app-context-menu-item [actionRef]="child" />
</ng-container>
</mat-menu>
</ng-container>
<ng-container *ngSwitchCase="'custom'">
<adf-dynamic-component [data]="entry.data" [id]="entry.component" />
</ng-container>
</ng-container>
@for (entry of actions; track trackByActionId($index, entry)) {
@switch (entry.type) {
@default {
<button mat-menu-item [id]="entry.id" (click)="runAction(entry)">
<adf-icon [value]="entry.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span>
</button>
}
@case ('separator') {
<mat-divider aria-hidden="true" />
}
@case ('menu') {
<button mat-menu-item [id]="entry.id" [matMenuTriggerFor]="childMenu">
<adf-icon [value]="entry.icon" class="app-context-menu-item--icon" />
<span [attr.data-automation-id]="entry.id + '-label'">{{ entry.title | translate }}</span>
</button>
<mat-menu #childMenu="matMenu">
@for (child of entry.children; track trackByActionId($index, child)) {
<app-context-menu-item [actionRef]="child" />
}
</mat-menu>
}
@case ('custom') {
<adf-dynamic-component [data]="entry.data" [id]="entry.component" />
}
}
}
</mat-menu>
</div>
@@ -25,7 +25,6 @@
import { AfterViewInit, Component, DestroyRef, inject, OnInit, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
import { MatMenu, MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { ContentActionType, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatDividerModule } from '@angular/material/divider';
import { IconComponent } from '@alfresco/adf-core';
@@ -36,7 +35,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [
CommonModule,
TranslatePipe,
MatMenuModule,
MatDividerModule,
@@ -7,20 +7,22 @@
<div class="aca-page-layout-content">
<div class="aca-details-container">
<div class="aca-details-title">
<div class="aca-details-breadcrumb" role="heading" aria-level="2" *ngIf="node">
<span class="aca-details-breadcrumb-library">
<img class="aca-details-breadcrumb-icon" alt="{{ 'APP.INFO_DRAWER.ICON' | translate }}" src="{{ nodeIcon }}">
@if (node) {
<div class="aca-details-breadcrumb" role="heading" aria-level="2">
<span class="aca-details-breadcrumb-library">
<img class="aca-details-breadcrumb-icon" alt="{{ 'APP.INFO_DRAWER.ICON' | translate }}" src="{{ nodeIcon }}">
{{ node.name }} </span>
</div>
</div>
}
<div class="aca-details-buttons">
<aca-toolbar [items]="aspectActions" info-drawer-buttons />
<button
class="aca-close-details-button"
mat-icon-button
data-automation-id="close-library"
title="{{ 'APP.INFO_DRAWER.REDUCE_PANEL' | translate }}"
(click)="goBack()">
<mat-icon>fullscreen_exit</mat-icon>
class="aca-close-details-button"
mat-icon-button
data-automation-id="close-library"
title="{{ 'APP.INFO_DRAWER.REDUCE_PANEL' | translate }}"
(click)="goBack()">
<mat-icon>fullscreen_exit</mat-icon>
</button>
</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 label="{{ 'APP.INFO_DRAWER.TABS.PROPERTIES' | translate }}">
<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>
</mat-tab>
<mat-tab label="{{ 'APP.INFO_DRAWER.TABS.COMMENTS' | translate }}">
<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>
</mat-tab>
<mat-tab [disabled]="!canManagePermissions" label="{{ 'APP.INFO_DRAWER.TABS.PERMISSIONS' | translate }}">
<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>
</mat-tab>
</mat-tab-group>
@@ -46,6 +60,3 @@
</div>
</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 { NavigateToFolder, NavigateToPreviousPage, SetInfoDrawerStateAction, SetSelectedNodesAction } from '@alfresco/aca-shared/store';
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 { MatIconModule } from '@angular/material/icon';
import { MatTabsModule } from '@angular/material/tabs';
@@ -43,7 +43,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [
CommonModule,
TranslatePipe,
MatIconModule,
MatTabsModule,
@@ -1,19 +1,19 @@
<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
*ngIf="badge.component; else iconBadge"
[id]="badge.component"
[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>
</ng-container>
} @else {
<adf-icon
class="adf-datatable-cell-badge"
[title]="badge.tooltip | translate"
[value]="badge.icon"
(click)="onBadgeClick(badge)"
(keypress.enter)="onKeyPress(badge)"
tabindex="0"
/>
}
}
</div>
@@ -26,7 +26,6 @@ import { AppExtensionService, Badge } from '@alfresco/aca-shared';
import { IconComponent } from '@alfresco/adf-core';
import { DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { NodeEntry } from '@alfresco/js-api';
import { CommonModule } from '@angular/common';
import { Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { TranslatePipe } from '@ngx-translate/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -37,7 +36,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
styleUrls: ['./datatable-cell-badges.component.scss'],
host: { class: 'aca-datatable-cell-badges' },
encapsulation: ViewEncapsulation.None,
imports: [CommonModule, TranslatePipe, DynamicExtensionComponent, IconComponent]
imports: [TranslatePipe, DynamicExtensionComponent, IconComponent]
})
export class DatatableCellBadgesComponent implements OnInit {
private readonly appExtensionService = inject(AppExtensionService);
@@ -2,8 +2,8 @@
<div class="aca-page-layout-header">
<div class="aca-header-container">
<h1 class="aca-page-title">
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.FAVORITES.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1>
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.FAVORITES.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1>
<aca-toolbar [items]="actions" />
</div>
</div>
@@ -28,14 +28,14 @@
[blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)"
>
>
<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-custom-empty-content-template>
<data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)">
@for (column of columns; track trackByColumnId($index, column)) {
@if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -48,14 +48,13 @@
[sortable]="column.sortable"
[isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key"
>
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -68,17 +67,19 @@
[sortable]="column.sortable"
[isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key"
/>
</ng-container>
</ng-container>
/>
}
}
</data-columns>
</adf-document-list>
<adf-pagination acaPagination [target]="documentList" />
</div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async">
<aca-info-drawer [node]="selection.last" />
</div>
@if (infoDrawerOpened$ | async) {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
}
</div>
</aca-page-layout>
@@ -15,99 +15,104 @@
</div>
<div class="aca-page-layout-content">
<div class="aca-main-content" *ngIf="!(showLoader$ | async)">
<adf-upload-drag-area [rootFolderId]="node?.id" [disabled]="!canUpload" (updateFileVersion)="onUploadNewVersion($event)">
<adf-document-list
#documentList
acaDocumentList
acaContextActions
[selectionMode]="'multiple'"
[multiselect]="true"
[currentFolderId]="node?.id"
[loading]="true"
[showHeader]="showHeader"
[node]="nodeResult"
[allowDropFiles]="true"
[displayCheckboxesOnHover]="true"
[preselectNodes]="selectedNodesState?.nodes"
[navigate]="false"
[sorting]="['name', 'asc']"
[imageResolver]="imageResolver"
[headerFilters]="true"
[filterValue]="queryParams"
[isDataProvidedExternally]="!!queryParams"
[isResizingEnabled]="true"
[blurOnResize]="false"
[displayDragAndDropHint]="canUpload"
(node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)"
(selectedItemsCountChanged)="onSelectedItemsCountChanged($event)"
(filterSelection)="onFilterSelected($event)"
(error)="onError($event)"
>
<data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="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"
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
@if (!(showLoader$ | async)) {
<div class="aca-main-content">
<adf-upload-drag-area [rootFolderId]="node?.id" [disabled]="!canUpload" (updateFileVersion)="onUploadNewVersion($event)">
<adf-document-list
#documentList
acaDocumentList
acaContextActions
[selectionMode]="'multiple'"
[multiselect]="true"
[currentFolderId]="node?.id"
[loading]="true"
[showHeader]="showHeader"
[node]="nodeResult"
[allowDropFiles]="true"
[displayCheckboxesOnHover]="true"
[preselectNodes]="selectedNodesState?.nodes"
[navigate]="false"
[sorting]="['name', 'asc']"
[imageResolver]="imageResolver"
[headerFilters]="true"
[filterValue]="queryParams"
[isDataProvidedExternally]="!!queryParams"
[isResizingEnabled]="true"
[blurOnResize]="false"
[displayDragAndDropHint]="canUpload"
(node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)"
(selectedItemsCountChanged)="onSelectedItemsCountChanged($event)"
(filterSelection)="onFilterSelected($event)"
(error)="onError($event)"
>
<data-columns>
@for (column of columns; track trackByColumnId($index, 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"
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</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)">
<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"
/>
</ng-container>
</ng-container>
</data-columns>
@if (showLoader$ | async) {
<mat-progress-spinner
id="adf-document-list-loading"
class="adf-document-list-loading-margin"
[color]="'primary'"
[mode]="'indeterminate'" />
}
<adf-custom-empty-content-template *ngIf="isFilterHeaderActive">
<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>
<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>
@if (infoDrawerOpened$ | async) {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
}
</div>
</aca-page-layout>
@@ -1,78 +1,80 @@
@if (node) {
<mat-card appearance="raised">
<mat-card-content>
<form [formGroup]="form" autocomplete="off">
<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>
<input
#libraryNameInput
data-automation-id="app-library-metadata-form-name-input"
matInput
required
placeholder="{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}"
formControlName="title"
[errorStateMatcher]="matcher"
/>
@if (libraryTitleExists) {
<mat-hint data-automation-id="app-library-metadata-form-name-hint">{{ 'LIBRARY.HINTS.SITE_TITLE_EXISTS' | translate }}</mat-hint>
<mat-card appearance="raised">
<mat-card-content>
<form [formGroup]="form" autocomplete="off">
<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>
<input
#libraryNameInput
data-automation-id="app-library-metadata-form-name-input"
matInput
required
placeholder="{{ 'LIBRARY.DIALOG.FORM.NAME' | translate }}"
formControlName="title"
[errorStateMatcher]="matcher"
/>
@if (libraryTitleExists) {
<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">
{{ 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-actions>
}
</mat-card>
</mat-card>
}
@@ -49,7 +49,6 @@ import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgForOf } from '@angular/common';
export class InstantErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {
@@ -68,8 +67,7 @@ export class InstantErrorStateMatcher implements ErrorStateMatcher {
MatSelectModule,
MatOptionModule,
MatInputModule,
MatButtonModule,
NgForOf
MatButtonModule
],
selector: 'app-library-metadata-form',
templateUrl: './library-metadata-form.component.html',
@@ -2,8 +2,8 @@
<div class="aca-page-layout-header">
<div class="aca-header-container">
<h1 class="aca-page-title">
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.RECENT.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1>
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.RECENT.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1>
<aca-toolbar [items]="actions" />
</div>
</div>
@@ -28,14 +28,14 @@
[blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)"
>
>
<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-custom-empty-content-template>
<data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)">
@for (column of columns; track trackByColumnId($index, column)) {
@if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -48,14 +48,13 @@
[resizable]="column.resizable"
[isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key"
>
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -68,17 +67,19 @@
[draggable]="column.draggable"
[resizable]="column.resizable"
[sortingKey]="column.sortingKey || column.key"
/>
</ng-container>
</ng-container>
/>
}
}
</data-columns>
</adf-document-list>
<adf-pagination acaPagination [target]="documentList" />
</div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async">
<aca-info-drawer [node]="selection.last" />
</div>
@if (infoDrawerOpened$ | async) {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
}
</div>
</aca-page-layout>
@@ -8,15 +8,16 @@
<mat-menu #sorting="matMenu">
<ng-template matMenuContent>
<button
mat-menu-item
*ngFor="let option of options"
[id]="option.key + '-sorting-option'"
[matMenuTriggerFor]="direction"
[matMenuTriggerData]="{ option: option }"
>
{{ option.label | translate }}
</button>
@for (option of options; track option) {
<button
mat-menu-item
[id]="option.key + '-sorting-option'"
[matMenuTriggerFor]="direction"
[matMenuTriggerData]="{ option: option }"
>
{{ option.label | translate }}
</button>
}
</ng-template>
</mat-menu>
@@ -24,14 +24,13 @@
import { SearchQueryBuilderService, SearchSortingDefinition } from '@alfresco/adf-content-services';
import { Component, EventEmitter, OnInit, Output, ViewEncapsulation, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
@Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatIconModule, MatButtonModule],
imports: [TranslatePipe, MatMenuModule, MatIconModule, MatButtonModule],
selector: 'aca-search-action-menu',
templateUrl: './search-action-menu.component.html',
encapsulation: ViewEncapsulation.None
@@ -23,7 +23,6 @@
*/
import { Component, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TranslatePipe } from '@ngx-translate/core';
import { OverlayModule } from '@angular/cdk/overlay';
@@ -39,17 +38,7 @@ import { ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from '@angular/cd
@Component({
selector: 'aca-search-in-menu',
standalone: true,
imports: [
CommonModule,
FormsModule,
TranslatePipe,
OverlayModule,
MatButtonModule,
MatIconModule,
MatCheckboxModule,
MatRadioModule,
MatDividerModule
],
imports: [FormsModule, TranslatePipe, OverlayModule, MatButtonModule, MatIconModule, MatCheckboxModule, MatRadioModule, MatDividerModule],
templateUrl: './search-in-menu.component.html',
styleUrls: ['./search-in-menu.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -28,7 +28,6 @@ import { ActivatedRoute, NavigationSkipped, Params, Router } from '@angular/rout
import { SearchNavigationService } from '../search-navigation.service';
import { SearchFilterService } from '../search-filter.service';
import { SearchExecutionService } from '../search-execution.service';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
@@ -45,7 +44,6 @@ import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
@Component({
imports: [
CommonModule,
TranslatePipe,
MatButtonModule,
MatIconModule,
@@ -8,17 +8,25 @@
<div class="aca-main-content">
<div class="adf-search-results">
<div class="adf-search-results__content">
<mat-progress-bar *ngIf="isLoading" mode="indeterminate" />
<div class="adf-search-results__content-header aca-content-lib" *ngIf="data?.list.entries.length">
<div class="aca-content__side--left">
<div class="adf-search-results--info-text" *ngIf="totalResults !== 1">
{{ 'APP.BROWSE.SEARCH_LIBRARIES.FOUND_RESULTS' | translate: { number: totalResults } }}
</div>
<div class="adf-search-results--info-text" *ngIf="totalResults === 1">
{{ 'APP.BROWSE.SEARCH_LIBRARIES.FOUND_ONE_RESULT' | translate: { number: totalResults } }}
@if (isLoading) {
<mat-progress-bar mode="indeterminate" />
}
@if (data?.list.entries.length) {
<div class="adf-search-results__content-header aca-content-lib">
<div class="aca-content__side--left">
@if (totalResults !== 1) {
<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>
}
<adf-document-list
#documentList
@@ -35,10 +43,10 @@
[blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)"
>
>
<data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)">
@for (column of columns; track trackByColumnId($index, column)) {
@if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -49,14 +57,13 @@
[sortable]="column.sortable"
[draggable]="column.draggable"
[resizable]="column.resizable"
>
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -67,28 +74,32 @@
[sortable]="column.sortable"
[draggable]="column.draggable"
[resizable]="column.resizable"
/>
</ng-container>
</ng-container>
/>
}
}
</data-columns>
<adf-custom-empty-content-template>
<ng-container *ngIf="data">
@if (data) {
<div class="empty-search__block" aria-live="polite">
<p class="empty-search__text">
{{ 'APP.BROWSE.SEARCH.NO_RESULTS' | translate }}
</p>
</div>
</ng-container>
}
</adf-custom-empty-content-template>
</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 class="aca-sidebar" *ngIf="infoDrawerOpened$ | async">
<aca-info-drawer [node]="selection.last" />
</div>
@if (infoDrawerOpened$ | async) {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
}
</div>
</aca-page-layout>
@@ -1,25 +1,27 @@
<div class="aca-search-results-text">
<div class="search-file-name">
<span
tabindex="0"
role="link"
*ngIf="isFile"
(click)="showPreview($event)"
(keyup.enter)="showPreview($event)"
class="aca-link aca-crop-text"
[title]="nameStripped"
[innerHTML]="name$ | async"
></span>
<span
tabindex="0"
role="link"
*ngIf="!isFile"
(click)="navigate($event)"
(keyup.enter)="navigate($event)"
class="bold aca-link aca-crop-text"
[title]="nameStripped"
[innerHTML]="name$ | async"
></span>
@if (isFile) {
<span
tabindex="0"
role="link"
(click)="showPreview($event)"
(keyup.enter)="showPreview($event)"
class="aca-link aca-crop-text"
[title]="nameStripped"
[innerHTML]="name$ | async"
></span>
}
@if (!isFile) {
<span
tabindex="0"
role="link"
(click)="navigate($event)"
(keyup.enter)="navigate($event)"
class="bold aca-link aca-crop-text"
[title]="nameStripped"
[innerHTML]="name$ | async"
></span>
}
<span
data-automation-id="search-results-entry-title"
class="aca-crop-text"
@@ -2,7 +2,9 @@
<div class="aca-page-layout-header">
<div class="aca-header-container">
<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" />
</div>
</div>
@@ -38,38 +40,19 @@
<div class="aca-content__advanced-filters--header">
<p>{{ 'APP.BROWSE.SEARCH.ADVANCED_FILTERS' | translate }}</p>
<div class="aca-content__advanced-filters--header--action-buttons">
<button
*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">
@if (initialSavedSearch !== undefined) {
<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 }}
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>
<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>
<ng-template #saveSearchButton>
} @else {
<button
mat-button
acaSaveSearch
@@ -79,10 +62,29 @@
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"
>
>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.ACTION_BUTTON' | translate }}
</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
[disabled]="!(areFiltersActive$ | async)"
mat-button
@@ -90,7 +92,7 @@
class="aca-content__reset-action"
title="{{ 'APP.BROWSE.SEARCH.RESET_ACTION' | translate }}"
[attr.aria-label]="'APP.BROWSE.SEARCH.RESET_ACTION' | translate"
>
>
{{ 'APP.BROWSE.SEARCH.RESET' | translate }}
</button>
</div>
@@ -114,7 +116,7 @@
[blurOnResize]="false"
[node]="$any(data)"
(node-dblclick)="handleNodeClick($event)"
>
>
<data-columns>
<data-column
id="app.search.thumbnail"
@@ -122,15 +124,15 @@
type="image"
[sr-title]="'ADF-DOCUMENT-LIST.LAYOUT.THUMBNAIL'"
[sortable]="false"
>
>
<adf-data-column-header>
<ng-template>
<aca-search-action-menu (sortingSelected)="onSearchSortingUpdate($event)" />
</ng-template>
</adf-data-column-header>
</data-column>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)">
@for (column of columns; track trackByColumnId($index, column)) {
@if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -143,14 +145,13 @@
[isHidden]="column.isHidden"
[draggable]="column.draggable"
[resizable]="column.resizable"
>
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -163,57 +164,60 @@
[isHidden]="column.isHidden"
[draggable]="column.draggable"
[resizable]="column.resizable"
/>
</ng-container>
</ng-container>
/>
}
}
</data-columns>
<adf-custom-empty-content-template>
<ng-container *ngIf="data">
@if (data) {
<div class="empty-search__block" aria-live="polite">
<p class="empty-search__text">
{{ 'APP.BROWSE.SEARCH.NO_RESULTS' | translate }}
</p>
</div>
</ng-container>
}
</adf-custom-empty-content-template>
</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
@if (infoDrawerOpened$ | async) {
<div
[ngClass]="
(infoDrawerPreview$ | async) === true ? 'adf-search-results--right_panel_section-extended' : 'adf-search-results--right_panel_section'
"
*ngIf="infoDrawerOpened$ | async"
>
<adf-alfresco-viewer
class="adf-search-results--embedded_viewer"
[nodeId]="selection.last.entry.id"
*ngIf="infoDrawerPreview$ | async; else infoDrawerPanel"
>
<adf-viewer-toolbar>
<div class="adf-search-results--preview-toolbar">
<div>
<button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}" (click)="onDrawerClosed()">
<mat-icon>close</mat-icon>
</button>
</div>
<div>
<button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.INFO' | translate }}" (click)="onPreviewClosed()">
<mat-icon>info_outline</mat-icon>
</button>
</div>
>
@if (infoDrawerPreview$ | async) {
<adf-alfresco-viewer
class="adf-search-results--embedded_viewer"
[nodeId]="selection.last.entry.id"
>
<adf-viewer-toolbar>
<div class="adf-search-results--preview-toolbar">
<div>
<button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}" (click)="onDrawerClosed()">
<mat-icon>close</mat-icon>
</button>
</div>
<div>
<button mat-icon-button title="{{ 'ADF_VIEWER.ACTIONS.INFO' | translate }}" (click)="onPreviewClosed()">
<mat-icon>info_outline</mat-icon>
</button>
</div>
</div>
</adf-viewer-toolbar>
</adf-alfresco-viewer>
} @else {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
</adf-viewer-toolbar>
</adf-alfresco-viewer>
<ng-template #infoDrawerPanel>
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
</ng-template>
</div>
}
</div>
}
</div>
</aca-page-layout>
@@ -1,16 +1,16 @@
<div class="aca-save-search-dialog__header">
<h2
id="aca-save-search-dialog-title"
class="aca-save-search-dialog__title">
{{"APP.BROWSE.SEARCH.SAVE_SEARCH.MODAL_HEADER" | translate}}
</h2>
<button
mat-icon-button
mat-dialog-close
[attr.aria-label]="'CLOSE' | translate | titlecase"
[attr.title]="'CLOSE' | translate | titlecase">
<mat-icon>close</mat-icon>
</button>
<h2
id="aca-save-search-dialog-title"
class="aca-save-search-dialog__title">
{{"APP.BROWSE.SEARCH.SAVE_SEARCH.MODAL_HEADER" | translate}}
</h2>
<button
mat-icon-button
mat-dialog-close
[attr.aria-label]="'CLOSE' | translate | titlecase"
[attr.title]="'CLOSE' | translate | titlecase">
<mat-icon>close</mat-icon>
</button>
</div>
@@ -24,16 +24,22 @@
matInput
required
[formControlName]="'name'"
/>
/>
<mat-error *ngIf="form.controls['name'].touched">
<span *ngIf="form.controls['name'].errors?.required">
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.NAME_REQUIRED_ERROR' | translate }}
</span>
<span *ngIf="!form.controls['name'].errors?.required && form.controls['name'].errors?.message">
{{ form.controls['name'].errors?.message | translate : { name: form.controls.name.value } }}
</span>
</mat-error>
@if (form.controls['name'].touched) {
<mat-error>
@if (form.controls['name'].errors?.required) {
<span>
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.NAME_REQUIRED_ERROR' | translate }}
</span>
}
@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 class="aca-save-search-dialog__form-field">
@@ -43,7 +49,7 @@
matInput
[attr.aria-label]="'APP.BROWSE.SEARCH.SAVE_SEARCH.DESCRIPTION_LABEL' | translate"
rows="4"
[formControlName]="'description'"></textarea>
[formControlName]="'description'"></textarea>
</mat-form-field>
</form>
</mat-dialog-content>
@@ -57,10 +63,10 @@
</button>
<button id="aca-save-search-dialog-save-button"
mat-flat-button
class="aca-save-search-dialog__save-button"
(click)="submit()"
[disabled]="!form.valid || disableSubmitButton">
mat-flat-button
class="aca-save-search-dialog__save-button"
(click)="submit()"
[disabled]="!form.valid || disableSubmitButton">
{{ 'SAVE' | titlecase | translate}}
</button>
</mat-dialog-actions>
@@ -4,27 +4,29 @@
{{ 'APP.BROWSE.SEARCH.SAVE_SEARCH.LIST.TITLE' | translate }}
</h1>
</div>
<div *ngIf="savedSearches$ | async as savedSearches else spinner"
class="aca-page-layout-content">
<div class="aca-main-content" >
<aca-saved-searches-ui-list *ngIf="savedSearches.length else emptyList"
[savedSearches]="savedSearches"
(savedSearchOrderChanged)="onOrderChanged($event)"/>
</div>
</div>
<ng-template #emptyList>
<adf-empty-content
@if (savedSearches$ | async; as savedSearches) {
<div
class="aca-page-layout-content">
<div class="aca-main-content" >
@if (savedSearches.length) {
<aca-saved-searches-ui-list
[savedSearches]="savedSearches"
(savedSearchOrderChanged)="onOrderChanged($event)"/>
} @else {
<adf-empty-content
class="aca-page-layout-content"
data-automation-id="'saved-search-list-empty-content'"
icon="library_books"
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>
<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
} from '@alfresco/adf-core';
import { Subject } from 'rxjs';
import { CommonModule } from '@angular/common';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { SavedSearchesListUiService } from '../saved-searches-list-ui.service';
import { savedSearchesListSchema } from '../smart-list/saved-searches-list-schema';
@@ -54,7 +53,7 @@ import { Router } from '@angular/router';
@Component({
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',
styleUrls: ['./saved-searches-list.ui-component.scss'],
encapsulation: ViewEncapsulation.None,
@@ -2,8 +2,8 @@
<div class="aca-page-layout-header">
<div class="aca-header-container">
<h1 class="aca-page-title">
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.SHARED.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1>
{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.SHARED.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}
</h1>
<aca-toolbar [items]="actions" />
</div>
@@ -28,14 +28,14 @@
[blurOnResize]="false"
(node-dblclick)="handleNodeClick($event)"
(name-click)="handleNodeClick($event)"
>
>
<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-custom-empty-content-template>
<data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)">
@for (column of columns; track trackByColumnId($index, column)) {
@if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -48,14 +48,13 @@
[draggable]="column.draggable"
[resizable]="column.resizable"
[sortingKey]="column.sortingKey || column.key"
>
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[draggable]="column.draggable"
@@ -68,17 +67,19 @@
[sortable]="column.sortable"
[isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key"
/>
</ng-container>
</ng-container>
/>
}
}
</data-columns>
</adf-document-list>
<adf-pagination acaPagination [target]="documentList" />
</div>
<div class="aca-sidebar" *ngIf="infoDrawerOpened$ | async">
<aca-info-drawer [node]="selection.last" />
</div>
@if (infoDrawerOpened$ | async) {
<div class="aca-sidebar">
<aca-info-drawer [node]="selection.last" />
</div>
}
</div>
</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-viewer-toolbar-actions>
<aca-toolbar [items]="viewerToolbarActions" />
</adf-viewer-toolbar-actions>
</adf-alfresco-viewer>
</ng-container>
}
@@ -32,12 +32,11 @@ import { Store } from '@ngrx/store';
import { forkJoin, from, of } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators';
import { AppExtensionService, AppService, ToolbarComponent } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { AlfrescoApiService, AlfrescoViewerModule } from '@alfresco/adf-content-services';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [CommonModule, ViewerModule, AlfrescoViewerModule, ToolbarComponent],
imports: [ViewerModule, AlfrescoViewerModule, ToolbarComponent],
selector: 'app-shared-link-view',
templateUrl: './shared-link-view.component.html',
styleUrls: ['shared-link-view.component.scss'],
@@ -1,4 +1,4 @@
<ng-container *ngIf="!item.children">
@if (!item.children) {
<button
class="action-button"
mat-icon-button
@@ -8,12 +8,12 @@
[attr.aria-label]="item.title | translate"
[attr.title]="item.description | translate"
[attr.data-automation-id]="item.id"
>
>
<adf-icon [value]="item.icon" />
</button>
</ng-container>
}
<ng-container *ngIf="item.children && item.children.length">
@if (item.children && item.children.length) {
<button
[matMenuTriggerFor]="menu"
[acaMenuPanel]="item"
@@ -27,24 +27,26 @@
[ngClass]="{
'action-button--active': acaMenuPanel.hasActiveChildren
}"
>
>
<adf-icon [value]="item.icon" />
</button>
<mat-menu #menu="matMenu" [overlapTrigger]="false">
<button
*ngFor="let child of item.children; trackBy: trackById"
acaActiveLink="action-button--active"
[action]="child"
[attr.aria-label]="child.title | translate"
[id]="child.id"
[attr.title]="child.description | translate"
[attr.data-automation-id]="child.id"
mat-menu-item
class="action-button"
>
<adf-icon *ngIf="child.icon" [value]="child.icon" />
<span class="action-button__label">{{ child.title | translate }}</span>
</button>
@for (child of item.children; track trackById($index, child)) {
<button
acaActiveLink="action-button--active"
[action]="child"
[attr.aria-label]="child.title | translate"
[id]="child.id"
[attr.title]="child.description | translate"
[attr.data-automation-id]="child.id"
mat-menu-item
class="action-button"
>
@if (child.icon) {
<adf-icon [value]="child.icon" />
}
<span class="action-button__label">{{ child.title | translate }}</span>
</button>
}
</mat-menu>
</ng-container>
}
@@ -1,4 +1,4 @@
<ng-container *ngIf="!item.children">
@if (!item.children) {
<div class="aca-expansion-panel-item">
<button
acaActiveLink="aca-action-button--active"
@@ -9,19 +9,21 @@
[attr.title]="item.description | translate"
mat-button
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>
</button>
</div>
</ng-container>
}
<ng-container *ngIf="item.children && item.children.length">
@if (item.children && item.children.length) {
<mat-expansion-panel
class="aca-expansion-panel"
[expanded]="true"
[@.disabled]="true"
>
>
<mat-expansion-panel-header expandedHeight="32px" collapsedHeight="32px" class="aca-expansion-panel-header">
<mat-panel-title class="aca-expansion-panel-header-title">
<div class="aca-expansion-panel-item">
@@ -31,30 +33,36 @@
[attr.title]="item.description | translate"
[attr.data-automation-id]="item.id"
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>
</div>
</mat-panel-title>
</mat-expansion-panel-header>
<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">
<button
acaActiveLink="aca-action-button--active"
[action]="child"
(actionClicked)="actionClicked.emit($event)"
[attr.aria-label]="child.title | translate"
[id]="child.id"
[attr.data-automation-id]="child.id"
[attr.title]="child.description | translate"
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>
</button>
</li>
@for (child of item.children; track trackById($index, child)) {
<li class="aca-expansion-panel-item">
<button
acaActiveLink="aca-action-button--active"
[action]="child"
(actionClicked)="actionClicked.emit($event)"
[attr.aria-label]="child.title | translate"
[id]="child.id"
[attr.data-automation-id]="child.id"
[attr.title]="child.description | translate"
mat-button
class="aca-action-button aca-full-width"
>
@if (child.icon) {
<adf-icon [value]="child.icon" />
}
<span class="aca-action-button__label">{{ child.title | translate }}</span>
</button>
</li>
}
</ul>
</mat-expansion-panel>
</ng-container>
}
@@ -24,7 +24,6 @@
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, inject } from '@angular/core';
import { NavBarLinkRef } from '@alfresco/adf-extensions';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { IconComponent } from '@alfresco/adf-core';
import { MatButtonModule } from '@angular/material/button';
@@ -33,7 +32,7 @@ import { ActionDirective } from '../directives/action.directive';
import { MatExpansionModule } from '@angular/material/expansion';
@Component({
imports: [CommonModule, TranslatePipe, IconComponent, MatButtonModule, ActiveLinkDirective, ActionDirective, MatExpansionModule],
imports: [TranslatePipe, IconComponent, MatButtonModule, ActiveLinkDirective, ActionDirective, MatExpansionModule],
selector: 'app-expand-menu',
encapsulation: ViewEncapsulation.None,
templateUrl: './expand-menu.component.html',
@@ -25,13 +25,12 @@
import { Component, DestroyRef, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { ContentActionRef } from '@alfresco/adf-extensions';
import { AppExtensionService, AppService, AppSettingsService, ToolbarComponent } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { RouterModule } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [CommonModule, TranslatePipe, RouterModule, ToolbarComponent],
imports: [TranslatePipe, RouterModule, ToolbarComponent],
selector: 'app-sidenav-header',
templateUrl: `./sidenav-header.component.html`,
encapsulation: ViewEncapsulation.None,
@@ -2,19 +2,22 @@
<app-sidenav-header (toggleNavBar)="toggleClick()" />
<div class="aca-sidenav__section">
<div *ngFor="let group of groups; trackBy: trackByGroupId" class="aca-sidenav__section__actions">
<nav
[attr.aria-label]="item.title | translate"
class="aca-sidenav__section__actions__item"
*ngFor="let item of group.items; trackBy: trackByLinkId"
>
<ng-container *ngIf="!item.component">
<app-expand-menu [item]="item" />
</ng-container>
<ng-container *ngIf="item.component">
<adf-dynamic-component [data]="{ item: item, state: 'expanded' }" [id]="item.component" />
</ng-container>
</nav>
</div>
@for (group of groups; track trackByGroupId($index, group)) {
<div class="aca-sidenav__section__actions">
@for (item of group.items; track trackByLinkId($index, item)) {
<nav
[attr.aria-label]="item.title | translate"
class="aca-sidenav__section__actions__item"
>
@if (!item.component) {
<app-expand-menu [item]="item" />
}
@if (item.component) {
<adf-dynamic-component [data]="{ item: item, state: 'expanded' }" [id]="item.component" />
}
</nav>
}
</div>
}
</div>
</div>
@@ -29,7 +29,6 @@ import { AppStore, getSideNavState } from '@alfresco/aca-shared/store';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { AppExtensionService, AppService, NavigationHistoryService } from '@alfresco/aca-shared';
import { SidenavLayoutComponent } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { SidenavHeaderComponent } from './components/sidenav-header.component';
import { MatListModule } from '@angular/material/list';
import { ExpandMenuComponent } from './components/expand-menu.component';
@@ -38,7 +37,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TranslatePipe } from '@ngx-translate/core';
@Component({
imports: [CommonModule, SidenavHeaderComponent, MatListModule, ExpandMenuComponent, DynamicExtensionComponent, TranslatePipe],
imports: [SidenavHeaderComponent, MatListModule, ExpandMenuComponent, DynamicExtensionComponent, TranslatePipe],
selector: 'app-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss'],
@@ -3,12 +3,12 @@
data-automation-id="app-user-menu-button"
[matMenuTriggerFor]="menu"
title="{{'APP.TOOLTIPS.OPTIONS_SETTINGS' | translate}}"
>
>
<div>{{ (user$ | async)?.initials }}</div>
</button>
<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" />
</ng-container>
}
</mat-menu>
@@ -27,13 +27,12 @@ import { NodeEntry } from '@alfresco/js-api';
import { Component, inject, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppExtensionService, isLocked } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
@Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatIconModule],
imports: [TranslatePipe, MatMenuModule, MatIconModule],
selector: 'app-toggle-edit-offline',
template: `
<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 { distinctUntilChanged } from 'rxjs/operators';
import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { LibraryFavoriteDirective } from '@alfresco/adf-content-services';
import { MatIconModule } from '@angular/material/icon';
@@ -37,7 +36,7 @@ import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
imports: [CommonModule, TranslatePipe, MatIconModule, MatMenuModule, LibraryFavoriteDirective],
imports: [TranslatePipe, MatIconModule, MatMenuModule, LibraryFavoriteDirective],
selector: 'app-toggle-favorite-library',
template: `
<button
@@ -50,8 +50,11 @@ import { MatMenuItem } from '@angular/material/menu';
[isAdmin]="(profile$ | async).isAdmin"
[attr.title]="(membership.isJoinRequested | async) ? ('APP.ACTIONS.CANCEL_JOIN' | translate) : ('APP.ACTIONS.JOIN' | translate)"
>
<mat-icon *ngIf="membership.isJoinRequested | async">cancel</mat-icon>
<mat-icon *ngIf="!(membership.isJoinRequested | async)">library_add</mat-icon>
@if (membership.isJoinRequested | async) {
<mat-icon>cancel</mat-icon>
} @else {
<mat-icon>library_add</mat-icon>
}
</button>
`,
encapsulation: ViewEncapsulation.None,
@@ -29,7 +29,6 @@ import { ActivatedRoute, Router } from '@angular/router';
import { take } from 'rxjs/operators';
import { SharedLinkEntry } from '@alfresco/js-api';
import { AppSettingsService, AutoDownloadService } from '@alfresco/aca-shared';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
@@ -37,23 +36,21 @@ import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { MatDialogModule } from '@angular/material/dialog';
@Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule, MatMenuModule, MatDialogModule],
imports: [TranslatePipe, MatButtonModule, MatIconModule, MatMenuModule, MatDialogModule],
selector: 'app-view-node',
template: `
<button
*ngIf="data.iconButton"
mat-icon-button
[attr.aria-label]="data.title | translate"
[attr.title]="data.title | translate"
(click)="onClick()"
>
<mat-icon>visibility</mat-icon>
</button>
@if (data.iconButton) {
<button mat-icon-button [attr.aria-label]="data.title | translate" [attr.title]="data.title | translate" (click)="onClick()">
<mat-icon>visibility</mat-icon>
</button>
}
<button *ngIf="data.menuButton" mat-menu-item (click)="onClick()">
<mat-icon>visibility</mat-icon>
<span>{{ data.title | translate }}</span>
</button>
@if (data.menuButton) {
<button mat-menu-item (click)="onClick()">
<mat-icon>visibility</mat-icon>
<span>{{ data.title | translate }}</span>
</button>
}
`,
encapsulation: ViewEncapsulation.None,
host: { class: 'app-view-node' }
@@ -25,7 +25,7 @@
[sorting]="['archivedAt', 'desc']"
[isResizingEnabled]="true"
[blurOnResize]="false"
>
>
<adf-custom-empty-content-template>
<adf-empty-content icon="delete" [title]="'APP.BROWSE.TRASHCAN.EMPTY_STATE.TITLE'">
<p class="adf-empty-content__text">
@@ -38,8 +38,8 @@
</adf-custom-empty-content-template>
<data-columns>
<ng-container *ngFor="let column of columns; trackBy: trackByColumnId">
<ng-container *ngIf="column.template && !(column.desktopOnly && isSmallScreen)">
@for (column of columns; track trackByColumnId($index, column)) {
@if (column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -52,14 +52,13 @@
[sortable]="column.sortable"
[isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key"
>
>
<ng-template let-context>
<adf-dynamic-column [id]="column.template" [context]="context" />
</ng-template>
</data-column>
</ng-container>
<ng-container *ngIf="!column.template && !(column.desktopOnly && isSmallScreen)">
}
@if (!column.template && !(column.desktopOnly && isSmallScreen)) {
<data-column
[id]="column.id"
[key]="column.key"
@@ -72,16 +71,17 @@
[resizable]="column.resizable"
[isHidden]="column.isHidden"
[sortingKey]="column.sortingKey || column.key"
/>
</ng-container>
</ng-container>
/>
}
}
<data-column
*ngIf="!isSmallScreen && (user$ | async)?.isAdmin"
class="adf-ellipsis-cell"
key="archivedByUser.displayName"
title="APP.DOCUMENT_LIST.COLUMNS.DELETED_BY"
/>
@if (!isSmallScreen && (user$ | async)?.isAdmin) {
<data-column
class="adf-ellipsis-cell"
key="archivedByUser.displayName"
title="APP.DOCUMENT_LIST.COLUMNS.DELETED_BY"
/>
}
</data-columns>
</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 { CommonModule } from '@angular/common';
import { NodesApiService } from '@alfresco/adf-content-services';
import { DIALOG_COMPONENT_DATA, IconComponent } from '@alfresco/adf-core';
import { Node, NodeAssociation } from '@alfresco/js-api';
@@ -33,7 +32,7 @@ import { TranslatePipe } from '@ngx-translate/core';
@Component({
selector: 'app-node-location-references',
imports: [CommonModule, IconComponent, TranslatePipe],
imports: [IconComponent, TranslatePipe],
templateUrl: './node-location-references.component.html',
styleUrls: ['./node-location-references.component.scss'],
encapsulation: ViewEncapsulation.None
@@ -8,11 +8,13 @@
matInput
formControlName="name"
required
/>
/>
<mat-error *ngIf="form.controls['name'].errors?.message" data-automation-id="create-from-template-field-error">
{{ form.controls['name'].errors?.message | translate }}
</mat-error>
@if (form.controls['name'].errors?.message) {
<mat-error data-automation-id="create-from-template-field-error">
{{ form.controls['name'].errors?.message | translate }}
</mat-error>
}
</mat-form-field>
<mat-form-field class="app-create-from-template-field">
@@ -20,11 +22,13 @@
<input
matInput
formControlName="title"
/>
/>
<mat-error *ngIf="form.controls['title'].hasError('maxlength')" data-automation-id="create-from-template-field-error">
{{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.TITLE_TOO_LONG' | translate }}
</mat-error>
@if (form.controls['title'].hasError('maxlength')) {
<mat-error data-automation-id="create-from-template-field-error">
{{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.TITLE_TOO_LONG' | translate }}
</mat-error>
}
</mat-form-field>
<mat-form-field class="app-create-from-template-field app-create-from-template-field-description">
@@ -35,9 +39,11 @@
formControlName="description"
></textarea>
<mat-error *ngIf="form.controls['description'].hasError('maxlength')" data-automation-id="create-from-template-field-error">
{{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.DESCRIPTION_TOO_LONG' | translate }}
</mat-error>
@if (form.controls['description'].hasError('maxlength')) {
<mat-error data-automation-id="create-from-template-field-error">
{{ 'NODE_FROM_TEMPLATE.FORM.ERRORS.DESCRIPTION_TOO_LONG' | translate }}
</mat-error>
}
</mat-form-field>
</form>
</div>
@@ -55,7 +61,7 @@
mat-button
(click)="onSubmit()"
data-automation-id="create-from-template-dialog-create-button"
>
>
{{ 'NODE_FROM_TEMPLATE.CREATE' | translate }}
</button>
</div>
@@ -29,14 +29,13 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators, UntypedFormControl, V
import { Store } from '@ngrx/store';
import { AppStore, CreateFromTemplate } from '@alfresco/aca-shared/store';
import { TranslationService } from '@alfresco/adf-core';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
@Component({
imports: [CommonModule, TranslatePipe, MatDialogModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule],
imports: [TranslatePipe, MatDialogModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule],
templateUrl: './create-from-template.dialog.html',
styleUrls: ['./create-from-template.dialog.scss'],
selector: 'app-create-from-template-dialog',
-1
View File
@@ -4,7 +4,6 @@
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2020",
"moduleResolution": "node",
"sourceMap": true,
"declaration": true,
"declarationMap": true,
@@ -1,4 +1,4 @@
<ng-container *ngIf="nodeId">
@if (nodeId) {
<adf-alfresco-viewer
[ngClass]="{
'aca-right_side--hide': !showRightSide
@@ -16,19 +16,23 @@
(showViewerChange)="onVisibilityChanged($event)"
(navigateBefore)="onNavigateBefore($event)"
(navigateNext)="onNavigateNext($event)"
>
<adf-viewer-sidebar *ngIf="infoDrawerOpened$ | async">
<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">
<app-toolbar-menu-item [actionRef]="action" />
</ng-container>
</adf-viewer-open-with>
<adf-viewer-toolbar-actions *ngIf="!simplestMode">
<aca-toolbar [items]="viewerToolbarActions" />
</adf-viewer-toolbar-actions>
>
@if (infoDrawerOpened$ | async) {
<adf-viewer-sidebar>
<aca-info-drawer [node]="selection.file" />
</adf-viewer-sidebar>
}
@if (openWith.length) {
<adf-viewer-open-with>
@for (action of openWith; track trackByActionId($index, action)) {
<app-toolbar-menu-item [actionRef]="action" />
}
</adf-viewer-open-with>
}
@if (!simplestMode) {
<adf-viewer-toolbar-actions>
<aca-toolbar [items]="viewerToolbarActions" />
</adf-viewer-toolbar-actions>
}
</adf-alfresco-viewer>
</ng-container>
}
@@ -1,4 +1,4 @@
<ng-container *ngIf="nodeId">
@if (nodeId) {
<adf-alfresco-viewer
[ngClass]="{
'aca-right_side--hide': !showRightSide
@@ -21,19 +21,21 @@
[canNavigateNext]="!!nextNodeId"
(navigateBefore)="onNavigateBefore($event)"
(navigateNext)="onNavigateNext($event)"
>
<adf-viewer-sidebar *ngIf="infoDrawerOpened$ | async">
<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">
<app-toolbar-menu-item [actionRef]="action" />
</ng-container>
</adf-viewer-open-with>
>
@if (infoDrawerOpened$ | async) {
<adf-viewer-sidebar>
<aca-info-drawer [node]="selection.file" />
</adf-viewer-sidebar>
}
@if (openWith.length) {
<adf-viewer-open-with>
@for (action of openWith; track trackByActionId($index, action)) {
<app-toolbar-menu-item [actionRef]="action" />
}
</adf-viewer-open-with>
}
<adf-viewer-toolbar-actions>
<aca-toolbar [items]="toolbarActions" />
</adf-viewer-toolbar-actions>
</adf-alfresco-viewer>
</ng-container>
}
@@ -5,7 +5,7 @@
"declarationMap": true,
"target": "es2020",
"module": "es2015",
"moduleResolution": "node",
"moduleResolution": "bundler",
"declaration": true,
"sourceMap": true,
"inlineSources": true,
@@ -1,12 +1,15 @@
<div *ngIf="isLoading">
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'APP.INFO_DRAWER.DATA_LOADING' | translate" />
</div>
<ng-container *ngIf="!isLoading && !!displayNode">
@if (isLoading) {
<div>
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'APP.INFO_DRAWER.DATA_LOADING' | translate" />
</div>
}
@if (!isLoading && !!displayNode) {
<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 />
<adf-info-drawer-tab *ngFor="let tab of tabs" [icon]="tab.icon" [label]="tab.title">
<adf-dynamic-tab [node]="$any(displayNode)" [id]="tab.component" [attr.data-automation-id]="tab.component" />
</adf-info-drawer-tab>
@for (tab of tabs; track tab) {
<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-info-drawer-tab>
}
</adf-info-drawer>
</ng-container>
}
@@ -29,7 +29,6 @@ import { Store } from '@ngrx/store';
import { infoDrawerPreview, SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store';
import { AppExtensionService } from '../../services/app.extension.service';
import { ContentApiService } from '../../services/content-api.service';
import { CommonModule } from '@angular/common';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { InfoDrawerComponent as AdfInfoDrawerComponent, InfoDrawerTabComponent } from '@alfresco/adf-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';
@Component({
imports: [
CommonModule,
TranslatePipe,
MatProgressBarModule,
AdfInfoDrawerComponent,
A11yModule,
ToolbarComponent,
DynamicTabComponent,
InfoDrawerTabComponent
],
imports: [TranslatePipe, MatProgressBarModule, AdfInfoDrawerComponent, A11yModule, ToolbarComponent, DynamicTabComponent, InfoDrawerTabComponent],
selector: 'aca-info-drawer',
templateUrl: './info-drawer.component.html',
encapsulation: ViewEncapsulation.None
@@ -8,15 +8,17 @@
<div class="aca-open-in-app-button-container">
<button mat-button (click)="openInApp()"
data-automation-id="open-in-app-button"
class="aca-open-in-app-button-container" cdkFocusInitial>
data-automation-id="open-in-app-button"
class="aca-open-in-app-button-container" cdkFocusInitial>
<span>{{ 'APP.DIALOGS.MOBILE_APP.MOBILE_APP_BUTTON_LABEL' | translate }}</span>
</button>
</div>
<div class="aca-download-app-container" *ngIf="appStoreUrl">
<button mat-button data-automation-id="download-app-button" class="aca-download-app-container-button" (click)="downloadIosApp()">
<span>{{ 'APP.DIALOGS.MOBILE_APP.DOWNLOAD_APP_BUTTON_LABEL' | translate }}</span>
</button>
</div>
@if (appStoreUrl) {
<div class="aca-download-app-container">
<button mat-button data-automation-id="download-app-button" class="aca-download-app-container-button" (click)="downloadIosApp()">
<span>{{ 'APP.DIALOGS.MOBILE_APP.DOWNLOAD_APP_BUTTON_LABEL' | translate }}</span>
</button>
</div>
}
</div>
@@ -24,7 +24,6 @@
import { Component, ViewEncapsulation, inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
@@ -35,7 +34,7 @@ export interface OpenInAppDialogOptions {
appStoreUrl: string;
}
@Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, MatIconModule, A11yModule, MatDialogModule],
imports: [TranslatePipe, MatButtonModule, MatIconModule, A11yModule, MatDialogModule],
selector: 'aca-open-in-app',
templateUrl: './open-in-app.component.html',
styleUrls: ['./open-in-app.component.scss'],
@@ -1,5 +1,6 @@
<div class="aca-content-header">
<button *ngIf="(appNavNarMode$ | async) === 'collapsed'"
@if ((appNavNarMode$ | async) === 'collapsed') {
<button
mat-icon-button
class="aca-content-header-button"
(click)="toggleClick()"
@@ -8,13 +9,14 @@
adf-auto-focus>
<mat-icon>keyboard_double_arrow_right</mat-icon>
</button>
<ng-content select=".aca-page-layout-header, aca-page-layout-header" />
}
<ng-content select=".aca-page-layout-header, aca-page-layout-header" />
</div>
<ng-container *ngIf="hasError">
@if (hasError) {
<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-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'">
<app-toolbar-button [type]="data?.buttonType || type" [actionRef]="actionRef" [color]="color" [data]="actionRef.data" />
</div>
<div *ngSwitchCase="'separator'" [id]="actionRef.id" class="aca-toolbar-divider"></div>
<ng-container *ngSwitchCase="'menu'">
@switch (actionRef.type) {
@case ('default') {
<div>
<app-toolbar-button [type]="type" [actionRef]="actionRef" [color]="color" />
</div>
}
@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" />
</ng-container>
<div *ngSwitchCase="'custom'">
<adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" />
</div>
</ng-container>
}
@case ('custom') {
<div>
<adf-dynamic-component [data]="actionRef.data" [id]="actionRef.component" />
</div>
}
}
@@ -26,11 +26,10 @@ import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input, DoCheck,
import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { ToolbarButtonComponent, ToolbarButtonType } from '../toolbar-button/toolbar-button.component';
import { ThemePalette } from '@angular/material/core';
import { CommonModule } from '@angular/common';
import { ToolbarMenuComponent } from '../toolbar-menu/toolbar-menu.component';
@Component({
imports: [CommonModule, ToolbarButtonComponent, ToolbarMenuComponent, DynamicExtensionComponent],
imports: [ToolbarButtonComponent, ToolbarMenuComponent, DynamicExtensionComponent],
selector: 'aca-toolbar-action',
templateUrl: './toolbar-action.component.html',
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
[id]="actionRef.id"
mat-icon-button
@@ -8,12 +9,11 @@
[attr.title]="actionRef.description || actionRef.title | translate"
[disabled]="actionRef.disabled"
(click)="runAction()"
>
>
<adf-icon [value]="actionRef.icon" />
</button>
</ng-container>
<ng-container *ngSwitchCase="'flat-button'">
}
@case ('flat-button') {
<button
[id]="actionRef.id"
[color]="data?.color || color"
@@ -22,12 +22,13 @@
[attr.title]="actionRef.description || actionRef.title | translate"
[disabled]="actionRef.disabled"
(click)="runAction()"
>
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span>
>
@if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button>
</ng-container>
<ng-container *ngSwitchCase="'stroked-button'">
}
@case ('stroked-button') {
<button
[id]="actionRef.id"
[color]="data?.color || color"
@@ -36,12 +37,13 @@
[attr.title]="actionRef.description || actionRef.title | translate"
[disabled]="actionRef.disabled"
(click)="runAction()"
>
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span>
>
@if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button>
</ng-container>
<ng-container *ngSwitchCase="'menu-item'">
}
@case ('menu-item') {
<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 { AppExtensionService } from '../../../services/app.extension.service';
import { ThemePalette } from '@angular/material/core';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { TranslatePipe } from '@ngx-translate/core';
import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item.component';
@@ -40,7 +39,7 @@ export enum ToolbarButtonType {
}
@Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, ToolbarMenuItemComponent, IconComponent],
imports: [TranslatePipe, MatButtonModule, ToolbarMenuItemComponent, IconComponent],
selector: 'app-toolbar-button',
templateUrl: './toolbar-button.component.html',
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">
<adf-icon [value]="actionRef.icon" />
<span data-automation-id="menu-item-title">{{ actionRef.title | translate }}</span>
</button>
<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" />
</ng-container>
}
</mat-menu>
</ng-container>
<ng-container *ngSwitchCase="'separator'">
}
@case ('separator') {
<mat-divider aria-hidden="true" />
</ng-container>
<ng-container *ngSwitchCase="'custom'">
}
@case ('custom') {
<adf-dynamic-component [id]="actionRef.component" />
</ng-container>
<ng-container *ngSwitchDefault>
}
@default {
<button
[id]="actionRef.id"
role="menuitem"
@@ -30,9 +27,9 @@
[disabled]="actionRef.disabled"
[attr.title]="(actionRef.disabled ? actionRef['description-disabled'] : actionRef.description || actionRef.title) | translate"
(click)="runAction()"
>
>
<adf-icon [value]="actionRef.icon" class="app-toolbar-menu-item--icon" />
<span data-automation-id="menu-item-title">{{ actionRef.title | translate }}</span>
</button>
</ng-container>
</ng-container>
}
}
@@ -26,13 +26,12 @@ import { AfterViewInit, Component, Input, ViewChild, ViewEncapsulation, inject }
import { ContentActionRef, DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { AppExtensionService } from '../../../services/app.extension.service';
import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
import { CommonModule } from '@angular/common';
import { TranslatePipe } from '@ngx-translate/core';
import { MatDividerModule } from '@angular/material/divider';
import { IconComponent } from '@alfresco/adf-core';
@Component({
imports: [CommonModule, TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent],
imports: [TranslatePipe, MatMenuModule, MatDividerModule, IconComponent, DynamicExtensionComponent],
selector: 'app-toolbar-menu-item',
templateUrl: './toolbar-menu-item.component.html',
styleUrls: ['./toolbar-menu-item.component.scss'],
@@ -1,5 +1,6 @@
<ng-container [ngSwitch]="type">
<ng-container *ngSwitchCase="'button'">
@switch (type) {
@case ('button') {
<button
[id]="actionRef.id"
[color]="data?.color || color"
@@ -9,12 +10,13 @@
[matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger"
>
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span>
>
@if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button>
</ng-container>
<ng-container *ngSwitchCase="'flat-button'">
}
@case ('flat-button') {
<button
[id]="actionRef.id"
[color]="data?.color || color"
@@ -24,12 +26,13 @@
[matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger"
>
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span>
>
@if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button>
</ng-container>
<ng-container *ngSwitchCase="'stroked-button'">
}
@case ('stroked-button') {
<button
[id]="actionRef.id"
[color]="data?.color || color"
@@ -39,12 +42,13 @@
[matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger"
>
<span *ngIf="actionRef.title">{{ actionRef.title | translate }}</span>
>
@if (actionRef.title) {
<span>{{ actionRef.title | translate }}</span>
}
</button>
</ng-container>
<ng-container *ngSwitchDefault>
}
@default {
<button
[id]="actionRef.id"
[color]="data?.color || color"
@@ -54,21 +58,23 @@
[matMenuTriggerFor]="menu"
[disabled]="actionRef.disabled"
#matTrigger="matMenuTrigger"
>
<adf-icon *ngIf="actionRef.icon" [value]="actionRef.icon" />
>
@if (actionRef.icon) {
<adf-icon [value]="actionRef.icon" />
}
</button>
</ng-container>
</ng-container>
}
}
<mat-menu #menu="matMenu" [overlapTrigger]="false" [xPosition]="'before'">
<ng-container *ngFor="let child of actionRef.children; trackBy: trackByActionId">
<ng-container [ngSwitch]="child.type">
<ng-container *ngSwitchCase="'custom'">
@for (child of actionRef.children; track trackByActionId($index, child)) {
@switch (child.type) {
@case ('custom') {
<adf-dynamic-component [id]="child.component" [data]="child.data" />
</ng-container>
<ng-container *ngSwitchDefault>
}
@default {
<app-toolbar-menu-item [actionRef]="child" [menuId]="actionRef.id" />
</ng-container>
</ng-container>
</ng-container>
}
}
}
</mat-menu>
@@ -27,13 +27,12 @@ import { ContentActionRef, ContentActionType, DynamicExtensionComponent } from '
import { MatMenu, MatMenuItem, MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
import { ThemePalette } from '@angular/material/core';
import { ToolbarMenuItemComponent } from '../toolbar-menu-item/toolbar-menu-item.component';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { TranslatePipe } from '@ngx-translate/core';
import { IconComponent } from '@alfresco/adf-core';
@Component({
imports: [CommonModule, TranslatePipe, MatButtonModule, MatMenuModule, ToolbarMenuItemComponent, IconComponent, DynamicExtensionComponent],
imports: [TranslatePipe, MatButtonModule, MatMenuModule, ToolbarMenuItemComponent, IconComponent, DynamicExtensionComponent],
selector: 'app-toolbar-menu',
templateUrl: './toolbar-menu.component.html',
encapsulation: ViewEncapsulation.None,
@@ -1,5 +1,5 @@
<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" />
</ng-container>
}
</mat-toolbar>
@@ -23,14 +23,13 @@
*/
import { Component, Input, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ContentActionRef } from '@alfresco/adf-extensions';
import { ToolbarActionComponent } from './toolbar-action/toolbar-action.component';
import { MatToolbarModule } from '@angular/material/toolbar';
@Component({
selector: 'aca-toolbar',
imports: [CommonModule, ToolbarActionComponent, MatToolbarModule],
imports: [ToolbarActionComponent, MatToolbarModule],
templateUrl: './toolbar.component.html',
styleUrls: ['./toolbar.component.scss'],
encapsulation: ViewEncapsulation.None
+1 -1
View File
@@ -5,7 +5,7 @@
"declarationMap": true,
"target": "es2020",
"module": "es2015",
"moduleResolution": "node",
"moduleResolution": "bundler",
"declaration": true,
"sourceMap": true,
"inlineSources": true,