mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
chore: migrate to Angular 20 and Material 20
- Update Angular from 19.2.18 to 20.3.9 - Update Angular Material/CDK from 19.2.19 to 20.2.14 - Update TypeScript from 5.8.3 to 5.9.3 - Update @typescript-eslint from 6.21.0 to 8.18.2 - Update @angular-eslint from 19.8.1 to 20.0.0 - Update ng-packagr from 19.2.2 to 20.3.2 - Update @mat-datetimepicker/core from 15.0.2 to 16.0.1 (Angular 20 compatible) Angular Migrations Applied: - Convert templates to new control flow syntax (@if, @for, @switch) - Migrate DOCUMENT imports from @angular/common to @angular/core - Update Router.getCurrentNavigation() to currentNavigation signal - Replace deprecated InjectFlags enum usage - Replace TestBed.get with TestBed.inject Breaking Changes Fixed: - Remove deprecated Directionality.value setter (read-only in Angular 20) - Update ESLint config: replace @typescript-eslint/no-var-requires with no-require-imports - Remove @typescript-eslint/brace-style rule (deprecated in v8) Configuration: - Add .npmrc with legacy-peer-deps for CI/CD compatibility - Update ESLint rules for @typescript-eslint v8 compatibility BREAKING CHANGE: Requires Angular 20+ and @mat-datetimepicker/core@16.0.1 Note: Nx build system currently has plugin worker issues. TypeScript compilation verified successfully. Full builds and tests pending Nx worker resolution. See MIGRATION_SUMMARY.md for complete details. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,50 +20,51 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { BreadcrumbItemComponent } from '../components/breadcrumb-item/breadcrumb-item.component';
|
||||
import { BreadcrumbComponent } from '../components/breadcrumb/breadcrumb.component';
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { IconModule } from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-demo-breadcrumb',
|
||||
template: `
|
||||
<adf-breadcrumb [compact]="compact">
|
||||
<adf-breadcrumb-item>
|
||||
<a href="/">Home</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com/">Alfresco</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com">External Link 1</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com/">External Link 2</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com/">External Link 3</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item *ngIf="showBreadcrumbItemWithMenu" aria-current="location" aria-haspopup="true">
|
||||
<div>
|
||||
Current Page
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Menu">
|
||||
<mat-icon adf-icon="menu_open" />
|
||||
</button>
|
||||
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item>Menu Item 1</button>
|
||||
<button mat-menu-item>Menu Item 2</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
<adf-breadcrumb-item>
|
||||
<a href="/">Home</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com/">Alfresco</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com">External Link 1</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com/">External Link 2</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
<adf-breadcrumb-item>
|
||||
<a href="https://www.alfresco.com/">External Link 3</a>
|
||||
</adf-breadcrumb-item>
|
||||
|
||||
@if (showBreadcrumbItemWithMenu) {
|
||||
<adf-breadcrumb-item aria-current="location" aria-haspopup="true">
|
||||
<div>
|
||||
Current Page
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Menu">
|
||||
<mat-icon adf-icon="menu_open" />
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item>Menu Item 1</button>
|
||||
<button mat-menu-item>Menu Item 2</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</adf-breadcrumb-item>
|
||||
}
|
||||
</adf-breadcrumb>
|
||||
`,
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [MatButtonModule, MatMenuModule, IconModule, BreadcrumbItemComponent, BreadcrumbComponent, NgIf]
|
||||
imports: [MatButtonModule, MatMenuModule, IconModule, BreadcrumbItemComponent, BreadcrumbComponent]
|
||||
})
|
||||
export class DemoBreadcrumbComponent {
|
||||
compact = false;
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
<ng-container>
|
||||
<nav class="adf-breadcrumb" [class.adf-breadcrumb--compact]="compact" [attr.aria-label]="'CORE.BREADCRUMBS.TITLE' | translate" >
|
||||
<ol>
|
||||
<ng-container *ngFor="let breadcrumbTemplate of selectedBreadcrumbs; last as last">
|
||||
@for (breadcrumbTemplate of selectedBreadcrumbs; track breadcrumbTemplate; let last = $last) {
|
||||
<li adf-breadcrumb-focus class="adf-breadcrumb__item-wrapper">
|
||||
<ng-container *ngTemplateOutlet="breadcrumbTemplate" />
|
||||
<div *ngIf="!last" class="adf-breadcrumb__chevron" [class.adf-breadcrumb__chevron-before--compact]="compact" ></div>
|
||||
@if (!last) {
|
||||
<div class="adf-breadcrumb__chevron" [class.adf-breadcrumb__chevron-before--compact]="compact" ></div>
|
||||
}
|
||||
</li>
|
||||
|
||||
<li *ngIf="!last && compact === true" class="adf-breadcrumb__show-all-button-wrapper">
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleCompact()"
|
||||
color="primary"
|
||||
[title]="'CORE.BREADCRUMBS.SHOWALL' | translate"
|
||||
[attr.aria-label]="'CORE.BREADCRUMBS.SHOWALL' | translate"
|
||||
>
|
||||
<mat-icon class="adf-breadcrumb__show-all-button-icon--rotate" adf-icon="more_vert" />
|
||||
</button>
|
||||
<div class="adf-breadcrumb__chevron" [class.adf-breadcrumb__chevron-after--compact]="compact" ></div>
|
||||
</li>
|
||||
</ng-container>
|
||||
@if (!last && compact === true) {
|
||||
<li class="adf-breadcrumb__show-all-button-wrapper">
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleCompact()"
|
||||
color="primary"
|
||||
[title]="'CORE.BREADCRUMBS.SHOWALL' | translate"
|
||||
[attr.aria-label]="'CORE.BREADCRUMBS.SHOWALL' | translate"
|
||||
>
|
||||
<mat-icon class="adf-breadcrumb__show-all-button-icon--rotate" adf-icon="more_vert" />
|
||||
</button>
|
||||
<div class="adf-breadcrumb__chevron" [class.adf-breadcrumb__chevron-after--compact]="compact" ></div>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ol>
|
||||
</nav>
|
||||
</ng-container>
|
||||
|
||||
@@ -41,9 +41,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
`
|
||||
],
|
||||
template: `
|
||||
<span [ngClass]="['activity-indicator', size]" *ngIf="isEnabled; else inActive">🟢</span>
|
||||
<ng-template #inActive><span [ngClass]="['activity-indicator', size]">🔴</span></ng-template>
|
||||
`,
|
||||
@if (isEnabled) {
|
||||
<span [ngClass]="['activity-indicator', size]">🟢</span>
|
||||
} @else {
|
||||
<span [ngClass]="['activity-indicator', size]">🔴</span>
|
||||
}
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
|
||||
@@ -13,20 +13,23 @@
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
<ng-container *ngIf="flags$ | async as flags">
|
||||
@if (flags$ | async; as flags) {
|
||||
<table mat-table [dataSource]="flags" class="adf-feature-flags-overrides-table mat-elevation-z0">
|
||||
<ng-container matColumnDef="icon">
|
||||
<th mat-header-cell class="adf-icon-col adf-header-cell" *matHeaderCellDef>
|
||||
<mat-icon class="material-icons-outlined adf-search-icon" adf-icon="search" />
|
||||
</th>
|
||||
<td mat-cell class="adf-icon-col" *matCellDef="let element">
|
||||
<button mat-icon-button *ngIf="element.fictive; else flagFromApi" class="adf-fictive-flag-button" (click)="onDelete(element.flag)">
|
||||
<mat-icon class="material-icons-outlined adf-custom-flag-icon" adf-icon="memory" />
|
||||
<mat-icon class="material-icons-outlined adf-trash-icon" adf-icon="delete" />
|
||||
</button>
|
||||
@if (element.fictive) {
|
||||
<button mat-icon-button class="adf-fictive-flag-button" (click)="onDelete(element.flag)">
|
||||
<mat-icon class="material-icons-outlined adf-custom-flag-icon" adf-icon="memory" />
|
||||
<mat-icon class="material-icons-outlined adf-trash-icon" adf-icon="delete" />
|
||||
</button>
|
||||
} @else {
|
||||
<mat-icon class="material-icons-outlined" adf-icon="cloud" />
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="flag">
|
||||
<th mat-header-cell class="flag-col header-cell" *matHeaderCellDef>
|
||||
<mat-form-field class="adf-flag-form-field" appearance="fill" floatLabel="auto">
|
||||
@@ -35,16 +38,19 @@
|
||||
</th>
|
||||
<td mat-cell class="flag-col" *matCellDef="let element">{{ element.flag }}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="value">
|
||||
<th mat-header-cell class="adf-val-col header-cell" *matHeaderCellDef>
|
||||
<div class="adf-input-field-buttons-container">
|
||||
<button *ngIf="showPlusButton$ | async" mat-icon-button title="{{'CORE.FEATURE-FLAGS.ADD_NEW' | translate}}" color="accent" (click)="onAddButtonClick()">
|
||||
<mat-icon class="material-icons-outlined" adf-icon="add_circle" />
|
||||
</button>
|
||||
<button *ngIf="inputValue" matSuffix mat-icon-button aria-label="Clear" (click)="onClearInput()" class="adf-clear-button">
|
||||
<mat-icon adf-icon="cancel" />
|
||||
</button>
|
||||
@if (showPlusButton$ | async) {
|
||||
<button mat-icon-button title="{{'CORE.FEATURE-FLAGS.ADD_NEW' | translate}}" color="accent" (click)="onAddButtonClick()">
|
||||
<mat-icon class="material-icons-outlined" adf-icon="add_circle" />
|
||||
</button>
|
||||
}
|
||||
@if (inputValue) {
|
||||
<button matSuffix mat-icon-button aria-label="Clear" (click)="onClearInput()" class="adf-clear-button">
|
||||
<mat-icon adf-icon="cancel" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</th>
|
||||
<td mat-cell class="adf-val-col" *matCellDef="let element">
|
||||
@@ -54,13 +60,9 @@
|
||||
[disabled]="!isEnabled" />
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<ng-template #flagFromApi>
|
||||
<mat-icon class="material-icons-outlined" adf-icon="cloud" />
|
||||
</ng-template>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { inject, provideAppInitializer } from '@angular/core';
|
||||
import { inject, provideAppInitializer, DOCUMENT } from '@angular/core';
|
||||
import {
|
||||
FlagsOverrideToken,
|
||||
FeaturesServiceToken,
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import { StorageFeaturesService } from '../services/storage-features.service';
|
||||
import { DebugFeaturesService } from '../services/debug-features.service';
|
||||
import { QaFeaturesHelper } from '../services/qa-features.helper';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -104,7 +104,7 @@ export class ShellLayoutComponent implements OnInit {
|
||||
)
|
||||
.subscribe((event: NavigationEnd) => {
|
||||
this.minimizeSidenav = this.shellService.minimizeSidenavConditions.some((el) => {
|
||||
const previousNavigation = this.router.getCurrentNavigation()?.previousNavigation?.finalUrl;
|
||||
const previousNavigation = this.router.currentNavigation()?.previousNavigation?.finalUrl;
|
||||
const previousPath = previousNavigation ? this.router.serializeUrl(previousNavigation) : '';
|
||||
return event.urlAfterRedirects.includes(el) && !previousPath.includes(el);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<mat-table [dataSource]="data">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
@for (column of columns; track column) {
|
||||
<ng-container [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns" />
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { ExtensionRef } from '@alfresco/adf-extensions';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
|
||||
@@ -26,7 +26,7 @@ import { TranslatePipe } from '@ngx-translate/core';
|
||||
templateUrl: './about-extension-list.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, MatTableModule, TranslatePipe]
|
||||
imports: [MatTableModule, TranslatePipe]
|
||||
})
|
||||
export class AboutExtensionListComponent {
|
||||
columns = [
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<mat-table [dataSource]="data">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row"
|
||||
class="adf-about-license-cell"
|
||||
[innerHTML]="column.cell(row)" />
|
||||
</ng-container>
|
||||
@for (column of columns; track column) {
|
||||
<ng-container [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row"
|
||||
class="adf-about-license-cell"
|
||||
[innerHTML]="column.cell(row)" />
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns" />
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { LicenseData } from '../interfaces';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
@@ -27,7 +27,7 @@ import { MatTableModule } from '@angular/material/table';
|
||||
styleUrls: ['./about-license-list.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, TranslatePipe, MatTableModule]
|
||||
imports: [TranslatePipe, MatTableModule]
|
||||
})
|
||||
export class AboutLicenseListComponent {
|
||||
private readonly translateService = inject(TranslateService);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<mat-table [dataSource]="data">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
@for (column of columns; track column) {
|
||||
<ng-container [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns" />
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns" />
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
@@ -30,7 +30,7 @@ interface ModuleInfo {
|
||||
templateUrl: './module-list.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, TranslatePipe, MatTableModule]
|
||||
imports: [TranslatePipe, MatTableModule]
|
||||
})
|
||||
export class ModuleListComponent {
|
||||
columns = [
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<mat-table [dataSource]="data" class="adf-package-list-table">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef class="adf-package-list-table__header-cell">
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="adf-package-list-table__row-cell">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
@for (column of columns; track column) {
|
||||
<ng-container [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef class="adf-package-list-table__header-cell">
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="adf-package-list-table__row-cell">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns" class="adf-package-list-table__header-row" />
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns" class="adf-package-list-table__row" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { PackageInfo } from '../interfaces';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
@@ -26,7 +26,7 @@ import { MatTableModule } from '@angular/material/table';
|
||||
templateUrl: './package-list.component.html',
|
||||
styleUrls: ['./package-list.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, TranslatePipe, MatTableModule]
|
||||
imports: [TranslatePipe, MatTableModule]
|
||||
})
|
||||
export class PackageListComponent implements OnInit {
|
||||
@Input()
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
<div>
|
||||
<article *ngIf="licenseEntries">
|
||||
<header>{{ 'ABOUT.LICENSE.TITLE' | translate }}</header>
|
||||
<adf-about-license-list [data]="licenseEntries" />
|
||||
@if (licenseEntries) {
|
||||
<article>
|
||||
<header>{{ 'ABOUT.LICENSE.TITLE' | translate }}</header>
|
||||
<adf-about-license-list [data]="licenseEntries" />
|
||||
</article>
|
||||
}
|
||||
|
||||
<article *ngIf="statusEntries">
|
||||
<header>{{ 'ABOUT.STATUS.TITLE' | translate }}</header>
|
||||
<adf-about-status-list [data]="statusEntries" />
|
||||
@if (statusEntries) {
|
||||
<article>
|
||||
<header>{{ 'ABOUT.STATUS.TITLE' | translate }}</header>
|
||||
<adf-about-status-list [data]="statusEntries" />
|
||||
</article>
|
||||
}
|
||||
|
||||
<article *ngIf="data?.modules">
|
||||
<header>{{ 'ABOUT.MODULES.TITLE' | translate }}</header>
|
||||
<adf-about-module-list [data]="data.modules" />
|
||||
@if (data?.modules) {
|
||||
<article>
|
||||
<header>{{ 'ABOUT.MODULES.TITLE' | translate }}</header>
|
||||
<adf-about-module-list [data]="data.modules" />
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { ObjectUtils, StringUtils } from '../../common/utils';
|
||||
import { LicenseData, StatusData } from '../interfaces';
|
||||
import { RepositoryInfo } from './repository-info.interface';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { AboutLicenseListComponent } from '../about-license-list/about-license-list.component';
|
||||
import { ModuleListComponent } from '../about-module-list/module-list.component';
|
||||
@@ -30,7 +30,7 @@ import { AboutStatusListComponent } from '../about-status-list/about-status-list
|
||||
templateUrl: './about-repository-info.component.html',
|
||||
styleUrls: ['./about-repository-info.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
imports: [CommonModule, TranslatePipe, AboutLicenseListComponent, ModuleListComponent, AboutStatusListComponent]
|
||||
imports: [TranslatePipe, AboutLicenseListComponent, ModuleListComponent, AboutStatusListComponent]
|
||||
})
|
||||
export class AboutRepositoryInfoComponent implements OnInit {
|
||||
@Input()
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
|
||||
@@ -26,7 +26,7 @@ import { MatCardModule } from '@angular/material/card';
|
||||
templateUrl: './about-server-settings.component.html',
|
||||
styleUrls: ['./about-server-settings.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
imports: [CommonModule, TranslatePipe, MatCardModule]
|
||||
imports: [TranslatePipe, MatCardModule]
|
||||
})
|
||||
export class AboutServerSettingsComponent implements OnInit {
|
||||
private readonly appConfig = inject(AppConfigService);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<mat-table [dataSource]="data">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
@for (column of columns; track column) {
|
||||
<ng-container [matColumnDef]="column.columnDef">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
{{ column.header | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ column.cell(row) }}</mat-cell>
|
||||
</ng-container>
|
||||
}
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns" />
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { StatusData } from '../interfaces';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
@@ -26,7 +26,7 @@ import { MatTableModule } from '@angular/material/table';
|
||||
templateUrl: './about-status-list.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule, TranslatePipe, MatTableModule]
|
||||
imports: [TranslatePipe, MatTableModule]
|
||||
})
|
||||
export class AboutStatusListComponent {
|
||||
columns = [
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<mat-accordion [togglePosition]="'before'" class="adf-about-panel">
|
||||
<ng-container *ngFor="let panel of panels">
|
||||
<mat-expansion-panel [attr.data-automation-id]="panel.automationId">
|
||||
<mat-expansion-panel-header class="adf-about-panel-header">
|
||||
<mat-panel-title class="adf-about-panel-header__title">{{panel.label}}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<ng-container *ngTemplateOutlet="panel.layoutTemplate" />
|
||||
</mat-expansion-panel>
|
||||
</ng-container>
|
||||
@for (panel of panels; track panel) {
|
||||
<mat-expansion-panel [attr.data-automation-id]="panel.automationId">
|
||||
<mat-expansion-panel-header class="adf-about-panel-header">
|
||||
<mat-panel-title class="adf-about-panel-header__title">{{panel.label}}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<ng-container *ngTemplateOutlet="panel.layoutTemplate" />
|
||||
</mat-expansion-panel>
|
||||
}
|
||||
</mat-accordion>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<div class="adf-avatar">
|
||||
<img (error)="src = ''" *ngIf="src; else initialsTemplate" class="adf-avatar__image" [src]="src" [alt]="initials" [title]="tooltip" />
|
||||
@if (src) {
|
||||
<img (error)="src = ''" class="adf-avatar__image" [src]="src" [alt]="initials" [title]="tooltip" />
|
||||
} @else {
|
||||
<div class="adf-avatar__image adf-avatar__initials" [title]="tooltip">{{ initials }}</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<ng-template #initialsTemplate>
|
||||
<div class="adf-avatar__image adf-avatar__initials" [title]="tooltip">{{ initials }}</div>
|
||||
</ng-template>
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { Component, HostBinding, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'adf-avatar',
|
||||
imports: [CommonModule],
|
||||
imports: [],
|
||||
templateUrl: './avatar.component.html',
|
||||
styleUrls: ['./avatar.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
+74
-62
@@ -1,66 +1,78 @@
|
||||
<div [attr.data-automation-id]="'card-array-label-' + property.key" class="adf-property-label">{{ property.label | translate }}</div>
|
||||
<div class="adf-property-value adf-card-view-array-item-container">
|
||||
<ng-container *ngIf="(property.displayValue | async) as items; else elseEmptyValueBlock">
|
||||
<mat-chip-listbox *ngIf="items.length > 0; else elseEmptyValueBlock" data-automation-id="card-arrayitem-chip-list-container">
|
||||
<ng-container *ngIf="displayCount > 0; else withOutDisplayCount" >
|
||||
<mat-chip
|
||||
*ngFor="let item of items.slice(0, displayCount)"
|
||||
(keyup.enter)="clicked()"
|
||||
(click)="clicked()"
|
||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||
<div class="adf-card-view-array-chip-content">
|
||||
<mat-icon *ngIf="item?.icon" class="adf-array-item-icon" [adf-icon]="item.icon" />
|
||||
<span>{{item?.value}}</span>
|
||||
</div>
|
||||
</mat-chip>
|
||||
<mat-chip
|
||||
*ngIf="items.length > displayCount"
|
||||
data-automation-id="card-arrayitem-more-chip"
|
||||
[matMenuTriggerFor]="menu">
|
||||
<span>{{items.length - displayCount}} {{'CORE.CARDVIEW.MORE' | translate}}</span>
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
<ng-template #withOutDisplayCount>
|
||||
<mat-chip
|
||||
*ngFor="let item of items"
|
||||
(keyup.enter)="clicked()"
|
||||
(click)="clicked()"
|
||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||
<div class="adf-card-view-array-chip-content">
|
||||
<mat-icon *ngIf="item?.icon" class="adf-array-item-icon" [adf-icon]="item.icon" />
|
||||
<span>{{item?.value}}</span>
|
||||
</div>
|
||||
</mat-chip>
|
||||
</ng-template>
|
||||
</mat-chip-listbox>
|
||||
<mat-menu #menu="matMenu">
|
||||
<mat-card appearance="outlined" class="adf-array-item-more-chip-container">
|
||||
<mat-card-content>
|
||||
<mat-chip-listbox>
|
||||
<mat-chip (click)="clicked()" (keyup.enter)="clicked()"
|
||||
*ngFor="let item of items.slice(displayCount, items.length)"
|
||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||
<div class="adf-card-view-array-chip-content">
|
||||
<mat-icon *ngIf="item?.icon" class="adf-array-item-icon" [adf-icon]="item.icon" />
|
||||
<span>{{item?.value}}</span>
|
||||
</div>
|
||||
</mat-chip>
|
||||
</mat-chip-listbox>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
<ng-template #elseEmptyValueBlock>
|
||||
<span class="adf-card-array-item-default" data-automation-id="card-arrayitem-default">{{ property?.default | translate }}</span>
|
||||
</ng-template>
|
||||
@if (showClickableIcon) {
|
||||
<button mat-icon-button
|
||||
(click)="clicked()"
|
||||
(keydown.enter)="clicked()"
|
||||
[attr.aria-label]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.data-automation-id]="'card-array-item-clickable-icon-' + property.key">
|
||||
<mat-icon class="adf-array-item-button-icon" [adf-icon]="property.icon" />
|
||||
</button>
|
||||
@if ((property.displayValue | async); as items) {
|
||||
@if (items.length > 0) {
|
||||
<mat-chip-listbox data-automation-id="card-arrayitem-chip-list-container">
|
||||
@if (displayCount > 0) {
|
||||
@for (item of items.slice(0, displayCount); track item) {
|
||||
<mat-chip
|
||||
(keyup.enter)="clicked()"
|
||||
(click)="clicked()"
|
||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||
<div class="adf-card-view-array-chip-content">
|
||||
@if (item?.icon) {
|
||||
<mat-icon class="adf-array-item-icon" [adf-icon]="item.icon" />
|
||||
}
|
||||
<span>{{item?.value}}</span>
|
||||
</div>
|
||||
</mat-chip>
|
||||
}
|
||||
@if (items.length > displayCount) {
|
||||
<mat-chip
|
||||
data-automation-id="card-arrayitem-more-chip"
|
||||
[matMenuTriggerFor]="menu">
|
||||
<span>{{items.length - displayCount}} {{'CORE.CARDVIEW.MORE' | translate}}</span>
|
||||
</mat-chip>
|
||||
}
|
||||
} @else {
|
||||
@for (item of items; track item) {
|
||||
<mat-chip
|
||||
(keyup.enter)="clicked()"
|
||||
(click)="clicked()"
|
||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||
<div class="adf-card-view-array-chip-content">
|
||||
@if (item?.icon) {
|
||||
<mat-icon class="adf-array-item-icon" [adf-icon]="item.icon" />
|
||||
}
|
||||
<span>{{item?.value}}</span>
|
||||
</div>
|
||||
</mat-chip>
|
||||
}
|
||||
}
|
||||
</mat-chip-listbox>
|
||||
} @else {
|
||||
<span class="adf-card-array-item-default" data-automation-id="card-arrayitem-default">{{ property?.default | translate }}</span>
|
||||
}
|
||||
<mat-menu #menu="matMenu">
|
||||
<mat-card appearance="outlined" class="adf-array-item-more-chip-container">
|
||||
<mat-card-content>
|
||||
<mat-chip-listbox>
|
||||
@for (item of items.slice(displayCount, items.length); track item) {
|
||||
<mat-chip (click)="clicked()" (keyup.enter)="clicked()"
|
||||
[attr.data-automation-id]="'card-arrayitem-chip-' + item.value">
|
||||
<div class="adf-card-view-array-chip-content">
|
||||
@if (item?.icon) {
|
||||
<mat-icon class="adf-array-item-icon" [adf-icon]="item.icon" />
|
||||
}
|
||||
<span>{{item?.value}}</span>
|
||||
</div>
|
||||
</mat-chip>
|
||||
}
|
||||
</mat-chip-listbox>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</mat-menu>
|
||||
} @else {
|
||||
<span class="adf-card-array-item-default" data-automation-id="card-arrayitem-default">{{ property?.default | translate }}</span>
|
||||
}
|
||||
@if (showClickableIcon) {
|
||||
<button mat-icon-button
|
||||
(click)="clicked()"
|
||||
(keydown.enter)="clicked()"
|
||||
[attr.aria-label]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.data-automation-id]="'card-array-item-clickable-icon-' + property.key">
|
||||
<mat-icon class="adf-array-item-button-icon" [adf-icon]="property.icon" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
+24
-24
@@ -1,24 +1,24 @@
|
||||
<ng-container *ngIf="!property.isEmpty() || isEditable">
|
||||
<div class="adf-property-value">
|
||||
<mat-checkbox
|
||||
#checkbox="ngModel"
|
||||
adf-card-view-property-validator
|
||||
[attr.data-automation-id]="'card-boolean-' + property.key"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.TOGGLE' | translate"
|
||||
[checked]="property.displayValue"
|
||||
[disabled]="!isEditable"
|
||||
[ngModel]="property.displayValue"
|
||||
[property]="property"
|
||||
(ngModelChange)="changed($event)"
|
||||
(validated)="onValidation($event)"
|
||||
>
|
||||
<div
|
||||
[attr.data-automation-id]="'card-boolean-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
>{{ property.label | translate }}</div>
|
||||
@if(checkbox.touched && error){
|
||||
<mat-error [innerHTML]="error" />
|
||||
}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</ng-container>
|
||||
@if (!property.isEmpty() || isEditable) {
|
||||
<div class="adf-property-value">
|
||||
<mat-checkbox
|
||||
#checkbox="ngModel"
|
||||
adf-card-view-property-validator
|
||||
[attr.data-automation-id]="'card-boolean-' + property.key"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.TOGGLE' | translate"
|
||||
[checked]="property.displayValue"
|
||||
[disabled]="!isEditable"
|
||||
[ngModel]="property.displayValue"
|
||||
[property]="property"
|
||||
(ngModelChange)="changed($event)"
|
||||
(validated)="onValidation($event)"
|
||||
>
|
||||
<div
|
||||
[attr.data-automation-id]="'card-boolean-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
>{{ property.label | translate }}</div>
|
||||
@if(checkbox.touched && error){
|
||||
<mat-error [innerHTML]="error" />
|
||||
}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ import { Component, Input } from '@angular/core';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { CardViewBoolItemModel } from '../../models/card-view-boolitem.model';
|
||||
import { BaseCardView } from '../base-card-view';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { CardViewPropertyValidatorDirective } from '../../directives/card-view-property-validator.directive';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -27,7 +27,7 @@ import { MatError } from '@angular/material/form-field';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-card-view-boolitem',
|
||||
imports: [CommonModule, MatCheckboxModule, TranslatePipe, CardViewPropertyValidatorDirective, FormsModule, MatError],
|
||||
imports: [MatCheckboxModule, TranslatePipe, CardViewPropertyValidatorDirective, FormsModule, MatError],
|
||||
templateUrl: './card-view-boolitem.component.html',
|
||||
styles: [
|
||||
`
|
||||
|
||||
+132
-131
@@ -1,136 +1,137 @@
|
||||
<div class="adf-property-value" [ngClass]="{ 'adf-property-value-editable': editable, 'adf-property-readonly-value': isReadonlyProperty || !editable }">
|
||||
@if (!property.multivalued) {
|
||||
<mat-form-field class="adf-property-field adf-dateitem-editable" [floatLabel]="property.default ? 'always' : null">
|
||||
<mat-label
|
||||
class="adf-property-label"
|
||||
[attr.data-automation-id]="'card-dateitem-label-' + property.key"
|
||||
[attr.for]="'card-view-dateitem-' + property.key"
|
||||
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty || !editable, 'adf-property-value-editable': editable }"
|
||||
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
|
||||
>
|
||||
{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<div class="adf-dateitem-editable-controls">
|
||||
<span
|
||||
class="adf-datepicker-span-button"
|
||||
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
|
||||
(click)="showDatePicker()"
|
||||
(dblclick)="copyToClipboard(property.displayValue)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(keyup.enter)="showDatePicker()"
|
||||
>
|
||||
<span [attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">
|
||||
@if (showProperty) {
|
||||
{{ property.displayValue }}
|
||||
} @else {
|
||||
{{ property.default | translate }}
|
||||
}
|
||||
@if (!property.multivalued) {
|
||||
<mat-form-field class="adf-property-field adf-dateitem-editable" [floatLabel]="property.default ? 'always' : null">
|
||||
<mat-label
|
||||
class="adf-property-label"
|
||||
[attr.data-automation-id]="'card-dateitem-label-' + property.key"
|
||||
[attr.for]="'card-view-dateitem-' + property.key"
|
||||
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty || !editable, 'adf-property-value-editable': editable }"
|
||||
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
|
||||
>
|
||||
{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<div class="adf-dateitem-editable-controls">
|
||||
<span
|
||||
class="adf-datepicker-span-button"
|
||||
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
|
||||
(click)="showDatePicker()"
|
||||
(dblclick)="copyToClipboard(property.displayValue)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(keyup.enter)="showDatePicker()"
|
||||
>
|
||||
<span [attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">
|
||||
@if (showProperty) {
|
||||
{{ property.displayValue }}
|
||||
} @else {
|
||||
{{ property.default | translate }}
|
||||
}
|
||||
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
matInput
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
class="adf-invisible-date-input"
|
||||
[attr.tabIndex]="-1"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[value]="valueDate"
|
||||
(dateChange)="onDateChanged($event)"
|
||||
[attr.id]="'card-view-dateitem-' + property.key"
|
||||
/>
|
||||
@if (showClearAction) {
|
||||
<mat-icon
|
||||
matIconSuffix
|
||||
class="adf-date-reset-icon"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
(click)="onDateClear()"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.CLEAR' | translate"
|
||||
[attr.data-automation-id]="'datepicker-date-clear-' + property.key"
|
||||
adf-icon="clear"
|
||||
/>
|
||||
}
|
||||
<mat-datetimepicker-toggle
|
||||
matIconSuffix
|
||||
[attr.tabindex]="-1"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.data-automation-id]="'datepickertoggle-' + property.key"
|
||||
[for]="datetimePicker"
|
||||
class="adf-dateitem-picker-toggle"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
matInput
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
class="adf-invisible-date-input"
|
||||
[attr.tabIndex]="-1"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[value]="valueDate"
|
||||
(dateChange)="onDateChanged($event)"
|
||||
[attr.id]="'card-view-dateitem-' + property.key"
|
||||
/>
|
||||
@if (showClearAction) {
|
||||
<mat-icon
|
||||
matIconSuffix
|
||||
class="adf-date-reset-icon"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
(click)="onDateClear()"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.CLEAR' | translate"
|
||||
[attr.data-automation-id]="'datepicker-date-clear-' + property.key"
|
||||
adf-icon="clear"
|
||||
/>
|
||||
}
|
||||
<mat-datetimepicker-toggle
|
||||
matIconSuffix
|
||||
[attr.tabindex]="-1"
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.data-automation-id]="'datepickertoggle-' + property.key"
|
||||
[for]="datetimePicker"
|
||||
class="adf-dateitem-picker-toggle"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
|
||||
<mat-datetimepicker
|
||||
#datetimePicker
|
||||
[type]="$any(property).type"
|
||||
[timeInterval]="5"
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
[attr.data-automation-id]="'datepicker-' + property.key"
|
||||
[startAt]="valueDate"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
} @else {
|
||||
<mat-form-field class="adf-property-field adf-dateitem-editable" [floatLabel]="property.default ? 'always' : null">
|
||||
<mat-label
|
||||
class="adf-property-label"
|
||||
[attr.data-automation-id]="'card-dateitem-label-' + property.key"
|
||||
[attr.for]="'card-view-dateitem-' + property.key"
|
||||
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty || !editable, 'adf-property-value-editable': editable }"
|
||||
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
|
||||
<mat-datetimepicker
|
||||
#datetimePicker
|
||||
[type]="$any(property).type"
|
||||
[timeInterval]="5"
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
[attr.data-automation-id]="'datepicker-' + property.key"
|
||||
[startAt]="valueDate"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
} @else {
|
||||
<mat-form-field class="adf-property-field adf-dateitem-editable" [floatLabel]="property.default ? 'always' : null">
|
||||
<mat-label
|
||||
class="adf-property-label"
|
||||
[attr.data-automation-id]="'card-dateitem-label-' + property.key"
|
||||
[attr.for]="'card-view-dateitem-' + property.key"
|
||||
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty || !editable, 'adf-property-value-editable': editable }"
|
||||
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
|
||||
>
|
||||
{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<mat-chip-listbox #chipList class="adf-textitem-chip-list" [disabled]="isReadonlyProperty || !editable">
|
||||
@for (propertyValue of property.displayValue; track propertyValue; let idx = $index) {
|
||||
<mat-chip-option
|
||||
[removable]="isEditable"
|
||||
(removed)="removeValueFromList(idx)"
|
||||
>
|
||||
{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<mat-chip-listbox #chipList class="adf-textitem-chip-list" [disabled]="isReadonlyProperty || !editable">
|
||||
<mat-chip-option
|
||||
*ngFor="let propertyValue of property.displayValue; let idx = index"
|
||||
[removable]="isEditable"
|
||||
(removed)="removeValueFromList(idx)"
|
||||
>
|
||||
{{ propertyValue }}
|
||||
@if (isEditable) {
|
||||
<mat-icon matChipRemove adf-icon="cancel" />
|
||||
}
|
||||
</mat-chip-option>
|
||||
</mat-chip-listbox>
|
||||
<div class="adf-dateitem-editable-controls">
|
||||
<span
|
||||
class="adf-datepicker-span-button"
|
||||
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
|
||||
(click)="showDatePicker()"
|
||||
(dblclick)="copyToClipboard(property.displayValue)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(keyup.enter)="showDatePicker()"
|
||||
></span>
|
||||
</div>
|
||||
<input
|
||||
matInput
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
class="adf-invisible-date-input"
|
||||
[attr.tabIndex]="-1"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
(dateChange)="addDateToList($event)"
|
||||
[attr.id]="'card-view-dateitem-' + property.key"
|
||||
/>
|
||||
<mat-datetimepicker-toggle
|
||||
[attr.tabindex]="-1"
|
||||
matSuffix
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.data-automation-id]="'datepickertoggle-' + property.key"
|
||||
[for]="datetimePicker"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
<mat-datetimepicker
|
||||
#datetimePicker
|
||||
[type]="$any(property).type"
|
||||
[timeInterval]="5"
|
||||
[attr.data-automation-id]="'datepicker-' + property.key"
|
||||
[startAt]="valueDate"
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
}
|
||||
{{ propertyValue }}
|
||||
@if (isEditable) {
|
||||
<mat-icon matChipRemove adf-icon="cancel" />
|
||||
}
|
||||
</mat-chip-option>
|
||||
}
|
||||
</mat-chip-listbox>
|
||||
<div class="adf-dateitem-editable-controls">
|
||||
<span
|
||||
class="adf-datepicker-span-button"
|
||||
[attr.data-automation-id]="'datepicker-label-toggle-' + property.key"
|
||||
(click)="showDatePicker()"
|
||||
(dblclick)="copyToClipboard(property.displayValue)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(keyup.enter)="showDatePicker()"
|
||||
></span>
|
||||
</div>
|
||||
<input
|
||||
matInput
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
class="adf-invisible-date-input"
|
||||
[attr.tabIndex]="-1"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
(dateChange)="addDateToList($event)"
|
||||
[attr.id]="'card-view-dateitem-' + property.key"
|
||||
/>
|
||||
<mat-datetimepicker-toggle
|
||||
[attr.tabindex]="-1"
|
||||
matSuffix
|
||||
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
|
||||
[attr.data-automation-id]="'datepickertoggle-' + property.key"
|
||||
[for]="datetimePicker"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
<mat-datetimepicker
|
||||
#datetimePicker
|
||||
[type]="$any(property).type"
|
||||
[timeInterval]="5"
|
||||
[attr.data-automation-id]="'datepicker-' + property.key"
|
||||
[startAt]="valueDate"
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
[ngClass]="{ 'cdk-visually-hidden': !editable || isReadonlyProperty}"
|
||||
/>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
|
||||
+57
-53
@@ -1,63 +1,67 @@
|
||||
<div [attr.data-automation-id]="'card-key-value-pairs-label-' + property.key"
|
||||
class="adf-property-label">{{ property.label | translate }}</div>
|
||||
class="adf-property-label">{{ property.label | translate }}</div>
|
||||
<div class="adf-property-field">
|
||||
|
||||
<div *ngIf="!isEditable" class="adf-card-view__key-value-pairs__read-only adf-property-value">
|
||||
<mat-table #table [dataSource]="matTableValues" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let item">{{item.name}}</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="value">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let item">{{item.value}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="['name', 'value']" />
|
||||
<mat-row *matRowDef="let row; columns: ['name', 'value'];" />
|
||||
</mat-table>
|
||||
@if (!isEditable) {
|
||||
<div class="adf-card-view__key-value-pairs__read-only adf-property-value">
|
||||
<mat-table #table [dataSource]="matTableValues" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let item">{{item.name}}</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="value">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let item">{{item.value}}</mat-cell>
|
||||
</ng-container>
|
||||
<mat-header-row *matHeaderRowDef="['name', 'value']" />
|
||||
<mat-row *matRowDef="let row; columns: ['name', 'value'];" />
|
||||
</mat-table>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="adf-card-view__key-value-pairs adf-property-value" *ngIf="isEditable && values && values.length">
|
||||
@if (isEditable && values && values.length) {
|
||||
<div class="adf-card-view__key-value-pairs adf-property-value">
|
||||
<div class="adf-card-view__key-value-pairs__row">
|
||||
<div class="adf-property-col-key">{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}</div>
|
||||
<div class="adf-property-col-value">{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}</div>
|
||||
</div>
|
||||
@for (item of values; track item; let i = $index) {
|
||||
<div class="adf-card-view__key-value-pairs__row">
|
||||
<div class="adf-property-col-key">{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}</div>
|
||||
<div class="adf-property-col-value">{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}</div>
|
||||
</div>
|
||||
|
||||
<div class="adf-card-view__key-value-pairs__row" *ngFor="let item of values; let i = index">
|
||||
<input
|
||||
matInput
|
||||
class="adf-property-col-key adf-property-value-input"
|
||||
placeholder="{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}"
|
||||
(blur)="onBlur(item.value)"
|
||||
[attr.data-automation-id]="'card-'+ property.key +'-name-input-' + i"
|
||||
[(ngModel)]="values[i].name">
|
||||
|
||||
<input
|
||||
matInput
|
||||
class="adf-property-col-value adf-property-value-input"
|
||||
placeholder="{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}"
|
||||
(blur)="onBlur(item.value)"
|
||||
[attr.data-automation-id]="'card-'+ property.key +'-value-input-' + i"
|
||||
[(ngModel)]="values[i].value">
|
||||
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="remove(i)"
|
||||
class="adf-property-col-delete">
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
<input
|
||||
matInput
|
||||
class="adf-property-col-key adf-property-value-input"
|
||||
placeholder="{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}"
|
||||
(blur)="onBlur(item.value)"
|
||||
[attr.data-automation-id]="'card-'+ property.key +'-name-input-' + i"
|
||||
[(ngModel)]="values[i].name">
|
||||
<input
|
||||
matInput
|
||||
class="adf-property-col-value adf-property-value-input"
|
||||
placeholder="{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}"
|
||||
(blur)="onBlur(item.value)"
|
||||
[attr.data-automation-id]="'card-'+ property.key +'-value-input-' + i"
|
||||
[(ngModel)]="values[i].value">
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="remove(i)"
|
||||
class="adf-property-col-delete">
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div *ngIf="isEditable" class="adf-property-value adf-card-view__key-value-pairs__add-btn-container">
|
||||
<button (click)="add()"
|
||||
mat-button
|
||||
class="adf-card-view__key-value-pairs__add-btn"
|
||||
[attr.data-automation-id]="'card-key-value-pairs-button-' + property.key">
|
||||
{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.ADD' | translate }}
|
||||
<mat-icon adf-icon="add" />
|
||||
</button>
|
||||
}
|
||||
@if (isEditable) {
|
||||
<div class="adf-property-value adf-card-view__key-value-pairs__add-btn-container">
|
||||
<button (click)="add()"
|
||||
mat-button
|
||||
class="adf-card-view__key-value-pairs__add-btn"
|
||||
[attr.data-automation-id]="'card-key-value-pairs-button-' + property.key">
|
||||
{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.ADD' | translate }}
|
||||
<mat-icon adf-icon="add" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ import { CardViewKeyValuePairsItemModel } from '../../models/card-view.models';
|
||||
import { CardViewKeyValuePairsItemType } from '../../interfaces/card-view.interfaces';
|
||||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
||||
import { BaseCardView } from '../base-card-view';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -29,7 +29,7 @@ import { IconModule } from '../../../icon/icon.module';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-card-view-key-value-pairs-item',
|
||||
imports: [CommonModule, TranslatePipe, MatTableModule, MatInputModule, FormsModule, MatButtonModule, IconModule],
|
||||
imports: [TranslatePipe, MatTableModule, MatInputModule, FormsModule, MatButtonModule, IconModule],
|
||||
templateUrl: './card-view-keyvaluepairsitem.component.html',
|
||||
styleUrls: ['./card-view-keyvaluepairsitem.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
+28
-22
@@ -1,24 +1,30 @@
|
||||
<div [attr.data-automation-id]="'card-mapitem-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
*ngIf="showProperty">{{ property.label | translate }}</div>
|
||||
@if (showProperty) {
|
||||
<div [attr.data-automation-id]="'card-mapitem-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
>{{ property.label | translate }}</div>
|
||||
}
|
||||
<div class="adf-property-value adf-map-item-padding">
|
||||
<div>
|
||||
<span *ngIf="!isClickable; else clickableTemplate"
|
||||
[attr.data-automation-id]="'card-mapitem-value-' + property.key">
|
||||
<span *ngIf="showProperty;">{{ property.displayValue }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<ng-template #clickableTemplate>
|
||||
<span class="adf-mapitem-clickable-value"
|
||||
(click)="clicked()"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(keyup.enter)="clicked()"
|
||||
[attr.data-automation-id]="'card-mapitem-value-' + property.key">
|
||||
<span *ngIf="showProperty; else emptyValueTemplate">{{ property.displayValue }}</span>
|
||||
</span>
|
||||
</ng-template>
|
||||
<ng-template #emptyValueTemplate>
|
||||
{{ property.default | translate }}
|
||||
</ng-template>
|
||||
<div>
|
||||
@if (!isClickable) {
|
||||
<span
|
||||
[attr.data-automation-id]="'card-mapitem-value-' + property.key">
|
||||
@if (showProperty;) {
|
||||
<span>{{ property.displayValue }}</span>
|
||||
}
|
||||
</span>
|
||||
} @else {
|
||||
<span class="adf-mapitem-clickable-value"
|
||||
(click)="clicked()"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
(keyup.enter)="clicked()"
|
||||
[attr.data-automation-id]="'card-mapitem-value-' + property.key">
|
||||
@if (showProperty) {
|
||||
<span>{{ property.displayValue }}</span>
|
||||
} @else {
|
||||
{{ property.default | translate }}
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -18,12 +18,12 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { CardViewMapItemModel } from '../../models/card-view-mapitem.model';
|
||||
import { BaseCardView } from '../base-card-view';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-card-view-mapitem',
|
||||
imports: [CommonModule, TranslatePipe],
|
||||
imports: [TranslatePipe],
|
||||
templateUrl: './card-view-mapitem.component.html',
|
||||
styleUrls: ['./card-view-mapitem.component.scss']
|
||||
})
|
||||
|
||||
+83
-70
@@ -1,80 +1,93 @@
|
||||
<ng-container *ngIf="showProperty || isEditable">
|
||||
<div [ngSwitch]="templateType">
|
||||
<div *ngSwitchDefault>
|
||||
<div class="adf-property-field">
|
||||
<mat-form-field class="adf-property-value">
|
||||
<mat-label
|
||||
[attr.data-automation-id]="'card-select-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
@if (showProperty || isEditable) {
|
||||
<div>
|
||||
@switch (templateType) {
|
||||
@default {
|
||||
<div>
|
||||
<div class="adf-property-field">
|
||||
<mat-form-field class="adf-property-value">
|
||||
<mat-label
|
||||
[attr.data-automation-id]="'card-select-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
[ngClass]="{
|
||||
'adf-property-value-editable': isEditable,
|
||||
'adf-property-readonly-value': isReadonlyProperty
|
||||
}"
|
||||
>{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<mat-select
|
||||
[(ngModel)]="value"
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty || !editable }"
|
||||
panelClass="adf-select-filter"
|
||||
(selectionChange)="onChange($event)"
|
||||
data-automation-id="select-box"
|
||||
[aria-label]="property.label | translate"
|
||||
adf-card-view-property-validator
|
||||
[property]="property"
|
||||
(validated)="onValidation($event)"
|
||||
>
|
||||
<adf-select-filter-input *ngIf="showInputFilter" (change)="onFilterInputChange($event)" />
|
||||
<mat-option *ngIf="displayNoneOption">{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
|
||||
<mat-option *ngFor="let option of list$ | async" [value]="option.key">
|
||||
{{ option.label | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error [innerHTML]="error" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="'autocompleteBased'">
|
||||
<mat-form-field
|
||||
class="adf-property-field adf-card-selectitem-autocomplete "
|
||||
[ngClass]="{ 'adf-property-read-only': isReadonlyProperty || !editable }"
|
||||
[floatLabel]="property.default ? 'always' : null"
|
||||
>
|
||||
<mat-label
|
||||
[attr.data-automation-id]="'card-autocomplete-based-selectitem-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
[ngClass]="{
|
||||
'adf-property-value-editable': isEditable,
|
||||
'adf-property-readonly-value': isReadonlyProperty || !editable
|
||||
}"
|
||||
>{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<mat-select
|
||||
[(ngModel)]="value"
|
||||
[disabled]="isReadonlyProperty || !editable"
|
||||
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty || !editable }"
|
||||
panelClass="adf-select-filter"
|
||||
(selectionChange)="onChange($event)"
|
||||
data-automation-id="select-box"
|
||||
[aria-label]="property.label | translate"
|
||||
adf-card-view-property-validator
|
||||
[property]="property"
|
||||
(validated)="onValidation($event)"
|
||||
>
|
||||
{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[matAutocomplete]="auto"
|
||||
class="adf-property-value"
|
||||
@if (showInputFilter) {
|
||||
<adf-select-filter-input (change)="onFilterInputChange($event)" />
|
||||
}
|
||||
@if (displayNoneOption) {
|
||||
<mat-option>{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
|
||||
}
|
||||
@for (option of list$ | async; track option) {
|
||||
<mat-option [value]="option.key">
|
||||
{{ option.label | translate }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error [innerHTML]="error" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@case ('autocompleteBased') {
|
||||
<div>
|
||||
<mat-form-field
|
||||
class="adf-property-field adf-card-selectitem-autocomplete "
|
||||
[ngClass]="{ 'adf-property-read-only': isReadonlyProperty || !editable }"
|
||||
[floatLabel]="property.default ? 'always' : null"
|
||||
>
|
||||
<mat-label
|
||||
[attr.data-automation-id]="'card-autocomplete-based-selectitem-label-' + property.key"
|
||||
class="adf-property-label"
|
||||
[ngClass]="{
|
||||
'adf-property-value-editable': isEditable,
|
||||
'adf-property-readonly-value': isReadonlyProperty || !editable
|
||||
}"
|
||||
title="{{ property.label | translate }}"
|
||||
[placeholder]="property.default"
|
||||
[attr.aria-label]="property.label | translate"
|
||||
[formControl]="autocompleteControl"
|
||||
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
|
||||
[attr.data-automation-id]="'card-autocomplete-based-selectitem-value-' + property.key"
|
||||
/>
|
||||
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="onOptionSelected($event)">
|
||||
<mat-option
|
||||
*ngFor="let option of property.options$ | async"
|
||||
[value]="option.key"
|
||||
[attr.data-automation-id]="'card-autocomplete-based-selectitem-option-' + property.key"
|
||||
>
|
||||
{{ option.label }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
>
|
||||
{{ property.label | translate }}
|
||||
</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[matAutocomplete]="auto"
|
||||
class="adf-property-value"
|
||||
[ngClass]="{
|
||||
'adf-property-value-editable': isEditable,
|
||||
'adf-property-readonly-value': isReadonlyProperty || !editable
|
||||
}"
|
||||
title="{{ property.label | translate }}"
|
||||
[placeholder]="property.default"
|
||||
[attr.aria-label]="property.label | translate"
|
||||
[formControl]="autocompleteControl"
|
||||
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
|
||||
[attr.data-automation-id]="'card-autocomplete-based-selectitem-value-' + property.key"
|
||||
/>
|
||||
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="onOptionSelected($event)">
|
||||
@for (option of property.options$ | async; track option) {
|
||||
<mat-option
|
||||
[value]="option.key"
|
||||
[attr.data-automation-id]="'card-autocomplete-based-selectitem-option-' + property.key"
|
||||
>
|
||||
{{ option.label }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
+23
-22
@@ -1,26 +1,27 @@
|
||||
|
||||
<div class="adf-select-filter-input-container">
|
||||
<mat-form-field>
|
||||
<input matInput
|
||||
autocomplete="off"
|
||||
(keydown)="handleKeydown($event)"
|
||||
[placeholder]="'SELECT_FILTER.INPUT.PLACEHOLDER' | translate"
|
||||
#selectFilterInput
|
||||
[ngModel]="term"
|
||||
(ngModelChange)="onModelChange($event)"
|
||||
[attr.aria-label]="'SELECT_FILTER.INPUT.ARIA_LABEL' | translate"
|
||||
(change)="$event.stopPropagation()"
|
||||
/>
|
||||
<mat-form-field>
|
||||
<input matInput
|
||||
autocomplete="off"
|
||||
(keydown)="handleKeydown($event)"
|
||||
[placeholder]="'SELECT_FILTER.INPUT.PLACEHOLDER' | translate"
|
||||
#selectFilterInput
|
||||
[ngModel]="term"
|
||||
(ngModelChange)="onModelChange($event)"
|
||||
[attr.aria-label]="'SELECT_FILTER.INPUT.ARIA_LABEL' | translate"
|
||||
(change)="$event.stopPropagation()"
|
||||
/>
|
||||
|
||||
<button
|
||||
matSuffix
|
||||
mat-icon-button
|
||||
class="adf-select-filter-clear-button"
|
||||
[attr.aria-label]="'SELECT_FILTER.BUTTON.ARIA_LABEL' | translate"
|
||||
*ngIf="term"
|
||||
(keydown.enter)="reset($event)"
|
||||
(click)="reset()">
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</mat-form-field>
|
||||
@if (term) {
|
||||
<button
|
||||
matSuffix
|
||||
mat-icon-button
|
||||
class="adf-select-filter-clear-button"
|
||||
[attr.aria-label]="'SELECT_FILTER.BUTTON.ARIA_LABEL' | translate"
|
||||
(keydown.enter)="reset($event)"
|
||||
(click)="reset()">
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Component, DestroyRef, ElementRef, EventEmitter, inject, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { MatSelect } from '@angular/material/select';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -28,7 +28,7 @@ import { IconModule } from '../../../../icon/icon.module';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-select-filter-input',
|
||||
imports: [CommonModule, MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, IconModule, TranslatePipe],
|
||||
imports: [MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, IconModule, TranslatePipe],
|
||||
templateUrl: './select-filter-input.component.html',
|
||||
styleUrls: ['./select-filter-input.component.scss'],
|
||||
host: { class: 'adf-select-filter-input' },
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<div class="adf-property-list">
|
||||
<div *ngFor="let property of properties" class="adf-property-container">
|
||||
<div [attr.data-automation-id]="'header-'+property.key" class="adf-property">
|
||||
<adf-card-view-item-dispatcher
|
||||
[property]="property"
|
||||
[editable]="editable"
|
||||
[displayEmpty]="displayEmpty"
|
||||
[displayNoneOption]="property['displayNoneOption'] !== undefined ? property['displayNoneOption'] : displayNoneOption"
|
||||
[displayClearAction]="displayClearAction"
|
||||
[copyToClipboardAction]="copyToClipboardAction"
|
||||
[useChipsForMultiValueProperty]="useChipsForMultiValueProperty"
|
||||
[multiValueSeparator]="multiValueSeparator" />
|
||||
</div>
|
||||
@for (property of properties; track property) {
|
||||
<div class="adf-property-container">
|
||||
<div [attr.data-automation-id]="'header-'+property.key" class="adf-property">
|
||||
<adf-card-view-item-dispatcher
|
||||
[property]="property"
|
||||
[editable]="editable"
|
||||
[displayEmpty]="displayEmpty"
|
||||
[displayNoneOption]="property['displayNoneOption'] !== undefined ? property['displayNoneOption'] : displayNoneOption"
|
||||
[displayClearAction]="displayClearAction"
|
||||
[copyToClipboardAction]="copyToClipboardAction"
|
||||
[useChipsForMultiValueProperty]="useChipsForMultiValueProperty"
|
||||
[multiValueSeparator]="multiValueSeparator" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { CardViewItem } from '../../interfaces/card-view-item.interface';
|
||||
import { DEFAULT_SEPARATOR } from '../card-view-textitem/card-view-textitem.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { CardViewItemDispatcherComponent } from '../card-view-item-dispatcher/card-view-item-dispatcher.component';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-card-view',
|
||||
imports: [CommonModule, CardViewItemDispatcherComponent],
|
||||
imports: [CardViewItemDispatcherComponent],
|
||||
templateUrl: './card-view.component.html',
|
||||
styleUrls: ['./card-view.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Injectable, inject, DOCUMENT } from '@angular/core';
|
||||
|
||||
import { NotificationService } from '../notifications/services/notification.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
<mat-list class="adf-comment-list">
|
||||
<mat-list-item *ngFor="let comment of comments"
|
||||
(click)="selectComment(comment)"
|
||||
class="adf-comment-list-item">
|
||||
<div class="adf-comment-img-container">
|
||||
<div *ngIf="!comment.hasAvatarPicture" class="adf-comment-user-icon">{{ comment.userInitials }}</div>
|
||||
<img *ngIf="comment.hasAvatarPicture" class="adf-people-img"
|
||||
[alt]="'COMMENTS.PROFILE_IMAGE' | translate"
|
||||
[src]="getUserImage(comment.createdBy.id.toString())" />
|
||||
</div>
|
||||
<div class="adf-comment-contents">
|
||||
<div matLine class="adf-comment-user-name">{{ comment.userDisplayName }}</div>
|
||||
<div matLine class="adf-comment-message">{{ comment.message }}</div>
|
||||
<div matLine class="adf-comment-message-time">{{ comment.created | adfTimeAgo }}</div>
|
||||
</div>
|
||||
<mat-list class="adf-comment-list">
|
||||
@for (comment of comments; track comment) {
|
||||
<mat-list-item
|
||||
(click)="selectComment(comment)"
|
||||
class="adf-comment-list-item">
|
||||
<div class="adf-comment-img-container">
|
||||
@if (!comment.hasAvatarPicture) {
|
||||
<div class="adf-comment-user-icon">{{ comment.userInitials }}</div>
|
||||
}
|
||||
@if (comment.hasAvatarPicture) {
|
||||
<img class="adf-people-img"
|
||||
[alt]="'COMMENTS.PROFILE_IMAGE' | translate"
|
||||
[src]="getUserImage(comment.createdBy.id.toString())" />
|
||||
}
|
||||
</div>
|
||||
<div class="adf-comment-contents">
|
||||
<div matLine class="adf-comment-user-name">{{ comment.userDisplayName }}</div>
|
||||
<div matLine class="adf-comment-message">{{ comment.message }}</div>
|
||||
<div matLine class="adf-comment-message-time">{{ comment.created | adfTimeAgo }}</div>
|
||||
</div>
|
||||
</mat-list-item>
|
||||
}
|
||||
</mat-list>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Component, EventEmitter, inject, Input, Output, ViewEncapsulation } fro
|
||||
import { CommentModel } from '../../models/comment.model';
|
||||
import { CommentsService } from '../interfaces/comments-service.interface';
|
||||
import { ADF_COMMENTS_SERVICE } from '../interfaces/comments.token';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatLineModule } from '@angular/material/core';
|
||||
import { TimeAgoPipe } from '../../pipes';
|
||||
@@ -27,7 +27,7 @@ import { TranslatePipe } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-comment-list',
|
||||
imports: [CommonModule, MatListModule, MatLineModule, TimeAgoPipe, TranslatePipe],
|
||||
imports: [MatListModule, MatLineModule, TimeAgoPipe, TranslatePipe],
|
||||
templateUrl: './comment-list.component.html',
|
||||
styleUrls: ['./comment-list.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
@@ -1,35 +1,40 @@
|
||||
<div class="adf-comments-container">
|
||||
<div id="comment-header" class="adf-comments-header adf-comments-divider">
|
||||
{{'COMMENTS.HEADER' | translate: { count: comments?.length } }}
|
||||
<div id="comment-header" class="adf-comments-header adf-comments-divider">
|
||||
{{'COMMENTS.HEADER' | translate: { count: comments?.length } }}
|
||||
</div>
|
||||
@if (!readOnly) {
|
||||
<div class="adf-comments-input-container adf-comments-divider">
|
||||
<mat-form-field class="adf-comments-input-form-field">
|
||||
<mat-label>{{ 'COMMENTS.ADD' | translate }}</mat-label>
|
||||
<textarea
|
||||
#commentInput
|
||||
matInput
|
||||
id="comment-input"
|
||||
class="adf-text-text-area"
|
||||
[attr.aria-label]='("COMMENTS.ADD" | translate) + "*"'
|
||||
[formControl]="commentControl"
|
||||
(keydown.escape)="clearMessage($event)"
|
||||
>
|
||||
</textarea>
|
||||
@if (commentControl.invalid && commentControl.touched) {
|
||||
<mat-error>{{ 'COMMENTS.EMPTY_ERROR' | translate }}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<div class="adf-comments-input-actions">
|
||||
<button
|
||||
mat-button
|
||||
data-automation-id="comments-input-add"
|
||||
color="primary"
|
||||
(click)="addComment()"
|
||||
[disabled]="commentControl.invalid"
|
||||
>
|
||||
{{ 'COMMENTS.ADD' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!readOnly" class="adf-comments-input-container adf-comments-divider">
|
||||
<mat-form-field class="adf-comments-input-form-field">
|
||||
<mat-label>{{ 'COMMENTS.ADD' | translate }}</mat-label>
|
||||
<textarea
|
||||
#commentInput
|
||||
matInput
|
||||
id="comment-input"
|
||||
class="adf-text-text-area"
|
||||
[attr.aria-label]='("COMMENTS.ADD" | translate) + "*"'
|
||||
[formControl]="commentControl"
|
||||
(keydown.escape)="clearMessage($event)"
|
||||
>
|
||||
</textarea>
|
||||
<mat-error *ngIf="commentControl.invalid && commentControl.touched">{{ 'COMMENTS.EMPTY_ERROR' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<div class="adf-comments-input-actions">
|
||||
<button
|
||||
mat-button
|
||||
data-automation-id="comments-input-add"
|
||||
color="primary"
|
||||
(click)="addComment()"
|
||||
[disabled]="commentControl.invalid"
|
||||
>
|
||||
{{ 'COMMENTS.ADD' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<adf-comment-list *ngIf="comments?.length > 0" [comments]="comments" />
|
||||
@if (comments?.length > 0) {
|
||||
<adf-comment-list [comments]="comments" />
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { CommentModel } from '../models/comment.model';
|
||||
import { Component, ElementRef, EventEmitter, inject, Input, OnChanges, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { ADF_COMMENTS_SERVICE } from './interfaces/comments.token';
|
||||
import { CommentsService } from './interfaces/comments-service.interface';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
@@ -30,15 +30,14 @@ import { CommentListComponent } from './comment-list';
|
||||
@Component({
|
||||
selector: 'adf-comments',
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslatePipe,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
FormsModule,
|
||||
MatButtonModule,
|
||||
CommentListComponent,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
TranslatePipe,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
FormsModule,
|
||||
MatButtonModule,
|
||||
CommentListComponent,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
templateUrl: './comments.component.html',
|
||||
styleUrls: ['./comments.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { inject, Injectable, RendererFactory2, Signal } from '@angular/core';
|
||||
import { inject, Injectable, RendererFactory2, Signal, DOCUMENT } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { LanguageItem } from './language-item.interface';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
|
||||
import { Directionality, Direction } from '@angular/cdk/bidi';
|
||||
import { DEFAULT_LANGUAGE_LIST } from '../models/default-languages.model';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
@@ -46,7 +46,6 @@ export class UserPreferencesService {
|
||||
|
||||
private readonly document = inject(DOCUMENT);
|
||||
private readonly rendererFactory = inject(RendererFactory2);
|
||||
private readonly directionality = inject(Directionality);
|
||||
|
||||
defaults = {
|
||||
paginationSize: 25,
|
||||
@@ -135,7 +134,6 @@ export class UserPreferencesService {
|
||||
|
||||
this.select('textOrientation').subscribe((direction: Direction) => {
|
||||
renderer.setAttribute(this.document.body, 'dir', direction);
|
||||
(this.directionality as any).value = direction;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
<div mat-menu class="mat-mdc-menu-panel mdc-menu-surface mdc-menu-surface--open" @panelAnimation>
|
||||
<div id="adf-context-menu-content" class="mat-mdc-menu-content">
|
||||
<ng-container *ngFor="let link of links">
|
||||
<button *ngIf="link.model?.visible"
|
||||
[attr.data-automation-id]="'context-' + (link.title || link.model?.title | translate)"
|
||||
mat-menu-item
|
||||
[disabled]="link.model?.disabled"
|
||||
[title]="link.model?.tooltip | translate"
|
||||
(click)="onMenuItemClick($event, link)">
|
||||
<mat-icon *ngIf="link.model?.icon" [adf-icon]="link.model.icon" />
|
||||
<span>{{ link.title || link.model?.title | translate }}</span>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div id="adf-context-menu-content" class="mat-mdc-menu-content">
|
||||
@for (link of links; track link) {
|
||||
@if (link.model?.visible) {
|
||||
<button
|
||||
[attr.data-automation-id]="'context-' + (link.title || link.model?.title | translate)"
|
||||
mat-menu-item
|
||||
[disabled]="link.model?.disabled"
|
||||
[title]="link.model?.tooltip | translate"
|
||||
(click)="onMenuItemClick($event, link)">
|
||||
@if (link.model?.icon) {
|
||||
<mat-icon [adf-icon]="link.model.icon" />
|
||||
}
|
||||
<span>{{ link.title || link.model?.title | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ContextMenuOverlayRef } from './context-menu-overlay';
|
||||
import { contextMenuAnimation } from './animations';
|
||||
import { CONTEXT_MENU_DATA } from './context-menu.tokens';
|
||||
import { AfterViewInit, Component, HostListener, QueryList, ViewChildren, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { DOWN_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
|
||||
import { IconModule } from '../icon/icon.module';
|
||||
@@ -37,7 +37,7 @@ import { ContextMenuItem } from './interfaces';
|
||||
class: 'adf-context-menu'
|
||||
},
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
imports: [IconModule, MatMenuModule, NgForOf, NgIf, TranslatePipe],
|
||||
imports: [IconModule, MatMenuModule, TranslatePipe],
|
||||
animations: [trigger('panelAnimation', contextMenuAnimation)]
|
||||
})
|
||||
export class ContextMenuListComponent implements AfterViewInit {
|
||||
|
||||
+68
-65
@@ -1,77 +1,80 @@
|
||||
<div
|
||||
class="adf-columns-selector"
|
||||
role="presentation"
|
||||
data-automation-id="adf-columns-selector"
|
||||
(keyup.enter)="$event.stopPropagation()"
|
||||
(click)="$event.stopPropagation();"
|
||||
>
|
||||
<div class="adf-columns-selector-header">
|
||||
<span class="adf-columns-selector-header-label">
|
||||
{{"ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS" | translate}}
|
||||
</span>
|
||||
class="adf-columns-selector"
|
||||
role="presentation"
|
||||
data-automation-id="adf-columns-selector"
|
||||
(keyup.enter)="$event.stopPropagation()"
|
||||
(click)="$event.stopPropagation();"
|
||||
>
|
||||
<div class="adf-columns-selector-header">
|
||||
<span class="adf-columns-selector-header-label">
|
||||
{{"ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS" | translate}}
|
||||
</span>
|
||||
|
||||
<button
|
||||
data-automation-id="adf-columns-selector-close-button"
|
||||
mat-icon-button
|
||||
[attr.aria-label]="'CLOSE' | translate"
|
||||
(click)="closeMenu()"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
data-automation-id="adf-columns-selector-close-button"
|
||||
mat-icon-button
|
||||
[attr.aria-label]="'CLOSE' | translate"
|
||||
(click)="closeMenu()"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<mat-divider class="adf-columns-selector-divider" aria-hidden="true" />
|
||||
<mat-divider class="adf-columns-selector-divider" aria-hidden="true" />
|
||||
|
||||
<mat-form-field class="adf-columns-selector-search-input-form">
|
||||
<mat-label>{{ 'ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
data-automation-id="adf-columns-selector-search-input"
|
||||
[placeholder]="'ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH' | translate"
|
||||
[formControl]="searchInputControl"/>
|
||||
<mat-icon adf-icon="search" matSuffix />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="adf-columns-selector-search-input-form">
|
||||
<mat-label>{{ 'ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
data-automation-id="adf-columns-selector-search-input"
|
||||
[placeholder]="'ADF-DATATABLE.COLUMNS_SELECTOR.SEARCH' | translate"
|
||||
[formControl]="searchInputControl"/>
|
||||
<mat-icon adf-icon="search" matSuffix />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-selection-list
|
||||
class="adf-columns-selector-list-container"
|
||||
(selectionChange)="changeColumnVisibility($event)"
|
||||
[attr.aria-label]='"ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS_VISIBILITY" | translate'>
|
||||
<div *ngFor="let column of (columnItems | columnsSearchFilter: searchQuery)" class="adf-columns-selector-list-item">
|
||||
<mat-list-option
|
||||
color="primary"
|
||||
class="adf-columns-selector-column-checkbox"
|
||||
[attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title"
|
||||
[selected]="!column.isHidden"
|
||||
[disabled]="isCheckboxDisabled(column)"
|
||||
[value]="column.id">
|
||||
<div class="adf-columns-selector-list-content">
|
||||
{{column.title | translate}}
|
||||
</div>
|
||||
<div
|
||||
*ngIf="column.subtitle"
|
||||
<mat-selection-list
|
||||
class="adf-columns-selector-list-container"
|
||||
(selectionChange)="changeColumnVisibility($event)"
|
||||
[attr.aria-label]='"ADF-DATATABLE.COLUMNS_SELECTOR.COLUMNS_VISIBILITY" | translate'>
|
||||
@for (column of (columnItems | columnsSearchFilter: searchQuery); track column) {
|
||||
<div class="adf-columns-selector-list-item">
|
||||
<mat-list-option
|
||||
color="primary"
|
||||
class="adf-columns-selector-column-checkbox"
|
||||
[attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title"
|
||||
[selected]="!column.isHidden"
|
||||
[disabled]="isCheckboxDisabled(column)"
|
||||
[value]="column.id">
|
||||
<div class="adf-columns-selector-list-content">
|
||||
{{column.title | translate}}
|
||||
</div>
|
||||
@if (column.subtitle) {
|
||||
<div
|
||||
class="
|
||||
adf-columns-selector-list-content
|
||||
adf-columns-selector-subtitle
|
||||
"
|
||||
>
|
||||
<span>
|
||||
{{column.subtitle | translate}}
|
||||
</span>
|
||||
</div>
|
||||
</mat-list-option>
|
||||
</div>
|
||||
</mat-selection-list>
|
||||
>
|
||||
<span>
|
||||
{{column.subtitle | translate}}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</mat-list-option>
|
||||
</div>
|
||||
}
|
||||
</mat-selection-list>
|
||||
|
||||
<mat-divider class="adf-columns-selector-divider" aria-hidden="true" />
|
||||
<mat-divider class="adf-columns-selector-divider" aria-hidden="true" />
|
||||
|
||||
<div class="adf-columns-selector-footer">
|
||||
<button
|
||||
mat-flat-button
|
||||
data-automation-id="adf-columns-selector-apply-button"
|
||||
color="primary"
|
||||
(click)="apply()">
|
||||
{{"ADF-DATATABLE.COLUMNS_SELECTOR.APPLY" | translate}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="adf-columns-selector-footer">
|
||||
<button
|
||||
mat-flat-button
|
||||
data-automation-id="adf-columns-selector-apply-button"
|
||||
color="primary"
|
||||
(click)="apply()">
|
||||
{{"ADF-DATATABLE.COLUMNS_SELECTOR.APPLY" | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+13
-14
@@ -20,7 +20,7 @@ import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { DataColumn } from '../../data/data-column.model';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
@@ -35,19 +35,18 @@ import { IconModule } from '../../../icon/icon.module';
|
||||
@Component({
|
||||
selector: 'adf-datatable-column-selector',
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslatePipe,
|
||||
MatButtonModule,
|
||||
IconModule,
|
||||
MatDividerModule,
|
||||
ReactiveFormsModule,
|
||||
MatCheckboxModule,
|
||||
ColumnsSearchFilterPipe,
|
||||
MatSelectionList,
|
||||
MatListOption,
|
||||
MatFormFieldModule,
|
||||
MatInputModule
|
||||
],
|
||||
TranslatePipe,
|
||||
MatButtonModule,
|
||||
IconModule,
|
||||
MatDividerModule,
|
||||
ReactiveFormsModule,
|
||||
MatCheckboxModule,
|
||||
ColumnsSearchFilterPipe,
|
||||
MatSelectionList,
|
||||
MatListOption,
|
||||
MatFormFieldModule,
|
||||
MatInputModule
|
||||
],
|
||||
templateUrl: './columns-selector.component.html',
|
||||
styleUrls: ['./columns-selector.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
<div
|
||||
@if (data) {
|
||||
<div
|
||||
role="grid"
|
||||
*ngIf="data"
|
||||
class="adf-datatable-list"
|
||||
[class.adf-sticky-header]="isStickyHeaderEnabled()"
|
||||
[class.adf-datatable--empty]="(isEmpty() && !isHeaderVisible()) || loading"
|
||||
[class.adf-datatable--empty--header-visible]="isEmpty() && isHeaderVisible()"
|
||||
>
|
||||
<div *ngIf="isHeaderVisible()" class="adf-datatable-header" role="rowgroup" [ngClass]="{ 'adf-sr-only': !isHeaderVisible() }">
|
||||
>
|
||||
@if (isHeaderVisible()) {
|
||||
<div class="adf-datatable-header" role="rowgroup" [ngClass]="{ 'adf-sr-only': !isHeaderVisible() }">
|
||||
<adf-datatable-row
|
||||
cdkDropList
|
||||
cdkDropListOrientation="horizontal"
|
||||
[cdkDropListSortPredicate]="filterDisabledColumns"
|
||||
data-automation-id="datatable-row-header"
|
||||
class="adf-datatable-row"
|
||||
role="row">
|
||||
|
||||
|
||||
<!-- Drag -->
|
||||
<div *ngIf="enableDragRows" class="adf-datatable-cell-header adf-drag-column">
|
||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.DRAG' | translate }}</span>
|
||||
cdkDropList
|
||||
cdkDropListOrientation="horizontal"
|
||||
[cdkDropListSortPredicate]="filterDisabledColumns"
|
||||
data-automation-id="datatable-row-header"
|
||||
class="adf-datatable-row"
|
||||
role="row">
|
||||
<!-- Drag -->
|
||||
@if (enableDragRows) {
|
||||
<div class="adf-datatable-cell-header adf-drag-column">
|
||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.DRAG' | translate }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Actions (left) -->
|
||||
<div *ngIf="actions && actionsPosition === 'left'" class="adf-actions-column adf-datatable-cell-header">
|
||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
||||
}
|
||||
<!-- Actions (left) -->
|
||||
@if (actions && actionsPosition === 'left') {
|
||||
<div class="adf-actions-column adf-datatable-cell-header">
|
||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Columns -->
|
||||
<div *ngIf="multiselect" class="adf-datatable-cell-header adf-datatable-checkbox">
|
||||
<mat-checkbox
|
||||
[indeterminate]="isSelectAllIndeterminate"
|
||||
[checked]="isSelectAllChecked"
|
||||
(change)="onSelectAllClick($event)"
|
||||
class="adf-checkbox-sr-only"
|
||||
[aria-label]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate"
|
||||
[matTooltip]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate"
|
||||
#tooltip="matTooltip"
|
||||
(focusin)="tooltip.show()"
|
||||
(focusout)="tooltip.hide()"
|
||||
}
|
||||
<!-- Columns -->
|
||||
@if (multiselect) {
|
||||
<div class="adf-datatable-cell-header adf-datatable-checkbox">
|
||||
<mat-checkbox
|
||||
[indeterminate]="isSelectAllIndeterminate"
|
||||
[checked]="isSelectAllChecked"
|
||||
(change)="onSelectAllClick($event)"
|
||||
class="adf-checkbox-sr-only"
|
||||
[aria-label]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate"
|
||||
[matTooltip]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate"
|
||||
#tooltip="matTooltip"
|
||||
(focusin)="tooltip.show()"
|
||||
(focusout)="tooltip.hide()"
|
||||
>
|
||||
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate }}
|
||||
</mat-checkbox>
|
||||
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<ng-container
|
||||
*ngFor="
|
||||
let col of getVisibleColumns();
|
||||
let columnIndex = index
|
||||
let lastColumn = last"
|
||||
>
|
||||
<div
|
||||
}
|
||||
@for (
|
||||
col of getVisibleColumns(); track
|
||||
col; let columnIndex = $index
|
||||
let lastColumn) {
|
||||
@if (col.title || !showProvidedActions) {
|
||||
<div
|
||||
class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header adf-datatable-cell-data"
|
||||
*ngIf="col.title || !showProvidedActions"
|
||||
[attr.data-automation-id]="'auto_id_' + col.key"
|
||||
[ngClass]="{
|
||||
'adf-sortable': col.sortable,
|
||||
@@ -71,13 +71,12 @@
|
||||
(mouseleave)="hoveredHeaderColumnIndex = -1"
|
||||
adf-drop-zone dropTarget="header"
|
||||
[dropColumn]="col"
|
||||
>
|
||||
|
||||
<div
|
||||
adf-resizable
|
||||
#resizableElement="adf-resizable"
|
||||
[attr.tabindex]="col.sortable ? 0 : null"
|
||||
[attr.role]="col.sortable ? 'button' : null"
|
||||
>
|
||||
<div
|
||||
adf-resizable
|
||||
#resizableElement="adf-resizable"
|
||||
[attr.tabindex]="col.sortable ? 0 : null"
|
||||
[attr.role]="col.sortable ? 'button' : null"
|
||||
[attr.aria-description]="
|
||||
isColumnSortActive(col) ? (getSortLiveAnnouncement(col) | translate: { string: col.title | translate }) : null
|
||||
"
|
||||
@@ -89,71 +88,76 @@
|
||||
(col.title | translate) +
|
||||
(col.subtitle ? ' ' + (col.subtitle | translate) : '')
|
||||
"
|
||||
(click)="onColumnHeaderClick(col, $event)"
|
||||
(keyup.enter)="onColumnHeaderClick(col, $event)"
|
||||
[coverPadding]="10"
|
||||
(resizing)="onResizing($event, columnIndex)"
|
||||
(keyboardResizing)="onResizing($event, columnIndex)"
|
||||
(resizeStart)="resizingColumnIndex = columnIndex"
|
||||
(resizeEnd)="onResizingEnd()"
|
||||
[attr.data-automation-id]="'auto_header_content_id_' + col.key"
|
||||
class="adf-datatable-cell-header-content"
|
||||
(click)="onColumnHeaderClick(col, $event)"
|
||||
(keyup.enter)="onColumnHeaderClick(col, $event)"
|
||||
[coverPadding]="10"
|
||||
(resizing)="onResizing($event, columnIndex)"
|
||||
(keyboardResizing)="onResizing($event, columnIndex)"
|
||||
(resizeStart)="resizingColumnIndex = columnIndex"
|
||||
(resizeEnd)="onResizingEnd()"
|
||||
[attr.data-automation-id]="'auto_header_content_id_' + col.key"
|
||||
class="adf-datatable-cell-header-content"
|
||||
[ngClass]="{ 'adf-datatable-cell-header-content--hovered':
|
||||
hoveredHeaderColumnIndex === columnIndex &&
|
||||
!isDraggingHeaderColumn &&
|
||||
!isResizing && col.sortable}"
|
||||
>
|
||||
<ng-container *ngIf="!col.header">
|
||||
<span
|
||||
*ngIf="col.title"
|
||||
>
|
||||
@if (!col.header) {
|
||||
@if (col.title) {
|
||||
<span
|
||||
title="{{col.title | translate}}"
|
||||
class="adf-datatable-cell-value"
|
||||
>
|
||||
>
|
||||
{{col.title | translate}}
|
||||
</span>
|
||||
|
||||
<span
|
||||
*ngIf="col.subtitle"
|
||||
</span>
|
||||
}
|
||||
@if (col.subtitle) {
|
||||
<span
|
||||
title="{{col.subtitle | translate}}"
|
||||
class="adf-datatable-cell-value adf-datatable-cell-header_subtitle"
|
||||
>
|
||||
>
|
||||
({{col.subtitle | translate}})
|
||||
</span>
|
||||
|
||||
<span *ngIf="col.title && col.sortable && isDraggingHeaderColumn" class="adf-sr-only" aria-live="polite">
|
||||
</span>
|
||||
}
|
||||
@if (col.title && col.sortable && isDraggingHeaderColumn) {
|
||||
<span class="adf-sr-only" aria-live="polite">
|
||||
{{ getSortLiveAnnouncement(col) | translate: { string: col.title | translate } }}
|
||||
</span>
|
||||
|
||||
<span *ngIf="!col.title && !col.sortable && !headerFilterTemplate" [attr.title]="'ADF-DATATABLE.ACCESSIBILITY.EMPTY_HEADER' | translate"></span>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="col.header" class="adf-datatable-cell-value">
|
||||
<ng-template [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}" />
|
||||
</div>
|
||||
|
||||
<span
|
||||
</span>
|
||||
}
|
||||
@if (!col.title && !col.sortable && !headerFilterTemplate) {
|
||||
<span [attr.title]="'ADF-DATATABLE.ACCESSIBILITY.EMPTY_HEADER' | translate"></span>
|
||||
}
|
||||
}
|
||||
@if (col.header) {
|
||||
<div class="adf-datatable-cell-value">
|
||||
<ng-template [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}" />
|
||||
</div>
|
||||
}
|
||||
<span
|
||||
[class.adf-datatable__header--sorted-asc]="isColumnSorted(col, 'asc')"
|
||||
[class.adf-datatable__header--sorted-desc]="isColumnSorted(col, 'desc')">
|
||||
</span>
|
||||
|
||||
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}" />
|
||||
|
||||
<span
|
||||
*ngIf="col.draggable"
|
||||
cdkDragHandle
|
||||
[ngClass]="{ 'adf-datatable-cell-header-drag-icon': !isResizing }"
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="hoveredHeaderColumnIndex === columnIndex && !isResizing"
|
||||
svgIcon="adf:drag_indicator"
|
||||
class="adf-datatable-cell-header-drag-icon-visible"
|
||||
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="isResizingEnabled && col.resizable && !lastColumn"
|
||||
</span>
|
||||
@if (allowFiltering) {
|
||||
<ng-template [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}" />
|
||||
}
|
||||
@if (col.draggable) {
|
||||
<span
|
||||
cdkDragHandle
|
||||
[ngClass]="{ 'adf-datatable-cell-header-drag-icon': !isResizing }"
|
||||
>
|
||||
@if (hoveredHeaderColumnIndex === columnIndex && !isResizing) {
|
||||
<mat-icon
|
||||
svgIcon="adf:drag_indicator"
|
||||
class="adf-datatable-cell-header-drag-icon-visible"
|
||||
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
@if (isResizingEnabled && col.resizable && !lastColumn) {
|
||||
<div
|
||||
[ngClass]="hoveredHeaderColumnIndex === columnIndex && !isResizing || resizingColumnIndex === columnIndex ? 'adf-datatable__resize-handle-visible' : 'adf-datatable__resize-handle-hidden'"
|
||||
adf-resize-handle
|
||||
tabindex="0"
|
||||
@@ -167,155 +171,167 @@
|
||||
class="adf-datatable__resize-handle"
|
||||
[resizableContainer]="resizableElement">
|
||||
<div class="adf-datatable__resize-handle--divider"></div>
|
||||
</div>
|
||||
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Header actions (right) -->
|
||||
</div>
|
||||
}
|
||||
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<!-- Header actions (right) -->
|
||||
@if ((actions && actionsPosition === 'right') ||
|
||||
(mainActionTemplate && showMainDatatableActions)) {
|
||||
<div
|
||||
*ngIf="(actions && actionsPosition === 'right') ||
|
||||
(mainActionTemplate && showMainDatatableActions)"
|
||||
class="adf-actions-column adf-datatable-actions-menu adf-datatable-cell-header adf-datatable__actions-cell"
|
||||
[class.adf-datatable-actions-menu-provided]="showProvidedActions"
|
||||
>
|
||||
<ng-container *ngIf="mainActionTemplate">
|
||||
<button
|
||||
data-automation-id="adf-datatable-main-menu-button"
|
||||
title="{{ 'ADF-DATATABLE.CONTENT-ACTIONS.SELECT_COLUMNS' | translate }}"
|
||||
mat-icon-button
|
||||
#mainMenuTrigger="matMenuTrigger"
|
||||
(click)="onMainMenuOpen()"
|
||||
[matMenuTriggerFor]="mainMenu">
|
||||
<mat-icon adf-icon="view_week_outline" />
|
||||
</button>
|
||||
<mat-menu #mainMenu (closed)="onMainMenuClosed()">
|
||||
<div #mainMenuTemplate role="presentation" (keydown.tab)="$event.stopPropagation()">
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="mainActionTemplate"
|
||||
class="adf-actions-column adf-datatable-actions-menu adf-datatable-cell-header adf-datatable__actions-cell"
|
||||
[class.adf-datatable-actions-menu-provided]="showProvidedActions"
|
||||
>
|
||||
@if (mainActionTemplate) {
|
||||
<button
|
||||
data-automation-id="adf-datatable-main-menu-button"
|
||||
title="{{ 'ADF-DATATABLE.CONTENT-ACTIONS.SELECT_COLUMNS' | translate }}"
|
||||
mat-icon-button
|
||||
#mainMenuTrigger="matMenuTrigger"
|
||||
(click)="onMainMenuOpen()"
|
||||
[matMenuTriggerFor]="mainMenu">
|
||||
<mat-icon adf-icon="view_week_outline" />
|
||||
</button>
|
||||
<mat-menu #mainMenu (closed)="onMainMenuClosed()">
|
||||
<div #mainMenuTemplate role="presentation" (keydown.tab)="$event.stopPropagation()">
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="mainActionTemplate"
|
||||
[ngTemplateOutletContext]="{
|
||||
$implicit: mainMenuTrigger
|
||||
}" />
|
||||
</div>
|
||||
</mat-menu>
|
||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
||||
</ng-container>
|
||||
</div>
|
||||
</mat-menu>
|
||||
<span class="adf-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.ACTIONS' | translate }}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
}
|
||||
</adf-datatable-row>
|
||||
</div>
|
||||
|
||||
<div
|
||||
*ngIf="!loading; else loadingRowTemplate"
|
||||
</div>
|
||||
}
|
||||
@if (!loading) {
|
||||
<div
|
||||
class="adf-datatable-body"
|
||||
[ngClass]="{ 'adf-blur-datatable-body': blurOnResize && (isDraggingHeaderColumn || isResizing), 'adf-datatable-body__draggable': enableDragRows && !isDraggingRow, 'adf-datatable-body__dragging': isDraggingRow }"
|
||||
cdkDropList
|
||||
[cdkDropListDisabled]="!enableDragRows"
|
||||
role="rowgroup">
|
||||
<ng-container *ngIf="!noPermission; else noPermissionsRowTemplate">
|
||||
<adf-datatable-row *ngFor="let row of data.getRows(); let idx = index"
|
||||
cdkDrag
|
||||
[cdkDragDisabled]="!enableDragRows"
|
||||
(cdkDragDropped)="onDragDrop($event)"
|
||||
(cdkDragStarted)="onDragStart()"
|
||||
(cdkDragEnded)="onDragEnd()"
|
||||
[cdkDragBoundary]="'.adf-datatable-body'"
|
||||
[row]="row"
|
||||
(select)="onEnterKeyPressed(row, $event)"
|
||||
(keyup)="onRowKeyUp(row, $event)"
|
||||
(keydown)="onRowEnterKeyDown(row, $event)"
|
||||
[adf-upload]="rowAllowsDrop(row)"
|
||||
[adf-upload-data]="row"
|
||||
[ngStyle]="rowStyle"
|
||||
[ngClass]="getRowStyle(row)"
|
||||
[class.adf-datatable-row__dragging]="isDraggingRow"
|
||||
[attr.data-automation-id]="'datatable-row-' + idx"
|
||||
(contextmenu)="markRowAsContextMenuSource(row)"
|
||||
[disabled]="!(data?.allowFocusOnRows ?? true)"
|
||||
>
|
||||
<!-- Drag button -->
|
||||
<div *ngIf="enableDragRows"
|
||||
role="gridcell"
|
||||
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-hover-only">
|
||||
<button mat-icon-button
|
||||
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.DRAG' | translate">
|
||||
<mat-icon adf-icon="drag_indicator" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Actions (left) -->
|
||||
<div *ngIf="actions && actionsPosition === 'left'" role="gridcell" class="adf-datatable-cell">
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
|
||||
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
|
||||
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
|
||||
[attr.id]="'action_menu_left_' + idx"
|
||||
[attr.data-automation-id]="'action_menu_' + idx">
|
||||
<mat-icon adf-icon="more_vert" />
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let action of getRowActions(row)"
|
||||
[attr.data-automation-id]="action.title"
|
||||
[disabled]="action.disabled"
|
||||
(click)="onExecuteRowAction(row, action)">
|
||||
<mat-icon *ngIf="action.icon" [adf-icon]="action.icon" />
|
||||
<span>{{ action.title | translate }}</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
||||
<label *ngIf="multiselect"
|
||||
(keydown.enter)="onEnterKeyPressed(row, $any($event))"
|
||||
(click)="onCheckboxLabelClick(row, $event)"
|
||||
[for]="'select-file-' + idx"
|
||||
class="adf-datatable-cell adf-datatable-checkbox adf-datatable-checkbox-single"
|
||||
[attr.tabindex]="null">
|
||||
<mat-checkbox
|
||||
[id]="'select-file-' + idx"
|
||||
[disabled]="!row?.isSelectable"
|
||||
[class.adf-datatable-checkbox-selected]="row.isSelected"
|
||||
[class.adf-datatable-hover-only]="displayCheckboxesOnHover"
|
||||
[checked]="row.isSelected"
|
||||
[attr.aria-checked]="row.isSelected"
|
||||
[aria-label]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate"
|
||||
data-adf-datatable-row-checkbox
|
||||
(change)="onCheckboxChange(row, $event)"
|
||||
(keydown.enter)="$event.stopPropagation()"
|
||||
class="adf-checkbox-sr-only"
|
||||
>
|
||||
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate }}
|
||||
</mat-checkbox>
|
||||
</label>
|
||||
|
||||
@if (!noPermission) {
|
||||
@for (row of data.getRows(); track row; let idx = $index) {
|
||||
<adf-datatable-row
|
||||
cdkDrag
|
||||
[cdkDragDisabled]="!enableDragRows"
|
||||
(cdkDragDropped)="onDragDrop($event)"
|
||||
(cdkDragStarted)="onDragStart()"
|
||||
(cdkDragEnded)="onDragEnd()"
|
||||
[cdkDragBoundary]="'.adf-datatable-body'"
|
||||
[row]="row"
|
||||
(select)="onEnterKeyPressed(row, $event)"
|
||||
(keyup)="onRowKeyUp(row, $event)"
|
||||
(keydown)="onRowEnterKeyDown(row, $event)"
|
||||
[adf-upload]="rowAllowsDrop(row)"
|
||||
[adf-upload-data]="row"
|
||||
[ngStyle]="rowStyle"
|
||||
[ngClass]="getRowStyle(row)"
|
||||
[class.adf-datatable-row__dragging]="isDraggingRow"
|
||||
[attr.data-automation-id]="'datatable-row-' + idx"
|
||||
(contextmenu)="markRowAsContextMenuSource(row)"
|
||||
[disabled]="!(data?.allowFocusOnRows ?? true)"
|
||||
>
|
||||
<!-- Drag button -->
|
||||
@if (enableDragRows) {
|
||||
<div
|
||||
*ngFor="let col of getVisibleColumns(); let lastColumn = last;"
|
||||
role="gridcell"
|
||||
class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-data adf-datatable-cell--{{getAutomationValue(row)}}"
|
||||
[attr.title]="col.title | translate"
|
||||
[attr.data-automation-id]="getAutomationValue(row)"
|
||||
[attr.aria-selected]="row.isSelected"
|
||||
[attr.aria-label]="col.title ? (col.title | translate) : null"
|
||||
(click)="onRowClick(row, $event)"
|
||||
[attr.tabindex]="null"
|
||||
(keydown.enter)="onEnterKeyPressed(row, $any($event))"
|
||||
[adf-context-menu]="getContextMenuActions(row, col)"
|
||||
[adf-context-menu-enabled]="contextMenu"
|
||||
adf-drop-zone dropTarget="cell" [dropColumn]="col" [dropRow]="row"
|
||||
[ngStyle]="(col.width) && !lastColumn && {'flex': getFlexValue(col)}"
|
||||
>
|
||||
<div *ngIf="!col.template" class="adf-datatable-cell-container">
|
||||
<ng-container [ngSwitch]="data.getColumnType(row, col)">
|
||||
<div *ngSwitchCase="'image'" class="adf-cell-value">
|
||||
<mat-icon
|
||||
[attr.aria-label]="col.srTitle? (col.srTitle | translate) : null"
|
||||
[attr.aria-hidden]="!asIconValue(row, col)"
|
||||
*ngIf="isIconValue(row, col); else no_iconvalue"
|
||||
[adf-icon]="asIconValue(row, col)"
|
||||
role="gridcell"
|
||||
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-hover-only">
|
||||
<button mat-icon-button
|
||||
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.DRAG' | translate">
|
||||
<mat-icon adf-icon="drag_indicator" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
<!-- Actions (left) -->
|
||||
@if (actions && actionsPosition === 'left') {
|
||||
<div role="gridcell" class="adf-datatable-cell">
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
|
||||
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
|
||||
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
|
||||
[attr.id]="'action_menu_left_' + idx"
|
||||
[attr.data-automation-id]="'action_menu_' + idx">
|
||||
<mat-icon adf-icon="more_vert" />
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
@for (action of getRowActions(row); track action) {
|
||||
<button mat-menu-item
|
||||
[attr.data-automation-id]="action.title"
|
||||
[disabled]="action.disabled"
|
||||
(click)="onExecuteRowAction(row, action)">
|
||||
@if (action.icon) {
|
||||
<mat-icon [adf-icon]="action.icon" />
|
||||
}
|
||||
<span>{{ action.title | translate }}</span>
|
||||
</button>
|
||||
}
|
||||
</mat-menu>
|
||||
</div>
|
||||
}
|
||||
@if (multiselect) {
|
||||
<label
|
||||
(keydown.enter)="onEnterKeyPressed(row, $any($event))"
|
||||
(click)="onCheckboxLabelClick(row, $event)"
|
||||
[for]="'select-file-' + idx"
|
||||
class="adf-datatable-cell adf-datatable-checkbox adf-datatable-checkbox-single"
|
||||
[attr.tabindex]="null">
|
||||
<mat-checkbox
|
||||
[id]="'select-file-' + idx"
|
||||
[disabled]="!row?.isSelectable"
|
||||
[class.adf-datatable-checkbox-selected]="row.isSelected"
|
||||
[class.adf-datatable-hover-only]="displayCheckboxesOnHover"
|
||||
[checked]="row.isSelected"
|
||||
[attr.aria-checked]="row.isSelected"
|
||||
[aria-label]="'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate"
|
||||
data-adf-datatable-row-checkbox
|
||||
(change)="onCheckboxChange(row, $event)"
|
||||
(keydown.enter)="$event.stopPropagation()"
|
||||
class="adf-checkbox-sr-only"
|
||||
>
|
||||
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate }}
|
||||
</mat-checkbox>
|
||||
</label>
|
||||
}
|
||||
@for (col of getVisibleColumns(); track col; let lastColumn = $last) {
|
||||
<div
|
||||
role="gridcell"
|
||||
class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-data adf-datatable-cell--{{getAutomationValue(row)}}"
|
||||
[attr.title]="col.title | translate"
|
||||
[attr.data-automation-id]="getAutomationValue(row)"
|
||||
[attr.aria-selected]="row.isSelected"
|
||||
[attr.aria-label]="col.title ? (col.title | translate) : null"
|
||||
(click)="onRowClick(row, $event)"
|
||||
[attr.tabindex]="null"
|
||||
(keydown.enter)="onEnterKeyPressed(row, $any($event))"
|
||||
[adf-context-menu]="getContextMenuActions(row, col)"
|
||||
[adf-context-menu-enabled]="contextMenu"
|
||||
adf-drop-zone dropTarget="cell" [dropColumn]="col" [dropRow]="row"
|
||||
[ngStyle]="(col.width) && !lastColumn && {'flex': getFlexValue(col)}"
|
||||
>
|
||||
@if (!col.template) {
|
||||
<div class="adf-datatable-cell-container">
|
||||
@switch (data.getColumnType(row, col)) {
|
||||
@case ('image') {
|
||||
<div class="adf-cell-value">
|
||||
@if (isIconValue(row, col)) {
|
||||
<mat-icon
|
||||
[attr.aria-label]="col.srTitle? (col.srTitle | translate) : null"
|
||||
[attr.aria-hidden]="!asIconValue(row, col)"
|
||||
[adf-icon]="asIconValue(row, col)"
|
||||
/>
|
||||
<ng-template #no_iconvalue>
|
||||
<mat-icon class="adf-datatable-selected"
|
||||
*ngIf="row.isSelected && !multiselect; else no_selected_row" svgIcon="selected" />
|
||||
<ng-template #no_selected_row>
|
||||
<img class="adf-datatable-center-img-ie"
|
||||
} @else {
|
||||
@if (row.isSelected && !multiselect) {
|
||||
<mat-icon class="adf-datatable-selected"
|
||||
svgIcon="selected" />
|
||||
} @else {
|
||||
<img class="adf-datatable-center-img-ie"
|
||||
[attr.aria-label]="(data.getValue(row, col) | fileType) === 'disable' ?
|
||||
('ADF-DATATABLE.ACCESSIBILITY.ICON_DISABLED' | translate) :
|
||||
'ADF-DATATABLE.ACCESSIBILITY.ICON_TEXT' | translate:{
|
||||
@@ -326,174 +342,213 @@
|
||||
'ADF-DATATABLE.ACCESSIBILITY.ICON_TEXT' | translate:{
|
||||
type: 'ADF-DATATABLE.FILE_TYPE.' + (data.getValue(row, col) | fileType | uppercase) | translate
|
||||
}"
|
||||
src="{{ data.getValue(row, col) }}"
|
||||
(error)="onImageLoadingError($event, row)">
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div *ngSwitchCase="'icon'" class="adf-cell-value">
|
||||
<adf-icon-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
*ngSwitchCase="'date'"
|
||||
class="adf-cell-value adf-cell-date"
|
||||
|
||||
[attr.data-automation-id]="'date_' + (data.getValue(row, col, resolverFn) | adfLocalizedDate: 'medium') ">
|
||||
<adf-date-cell class="adf-datatable-center-date-column-ie"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)"
|
||||
[dateConfig]="col.dateConfig" />
|
||||
</div>
|
||||
|
||||
<div *ngSwitchCase="'location'" class="adf-cell-value"
|
||||
[attr.data-automation-id]="'location' + data.getValue(row, col, resolverFn)">
|
||||
<adf-location-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
<div *ngSwitchCase="'fileSize'" class="adf-cell-value"
|
||||
[attr.data-automation-id]="'fileSize_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-filesize-cell class="adf-datatable-center-size-column-ie"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
<div *ngSwitchCase="'text'" class="adf-cell-value"
|
||||
[attr.data-automation-id]="'text_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-datatable-cell
|
||||
[copyContent]="col.copyContent"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
<div *ngSwitchCase="'boolean'" class="adf-cell-value"
|
||||
[attr.data-automation-id]="'boolean_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-boolean-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
<div *ngSwitchCase="'json'" class="adf-cell-value">
|
||||
<adf-json-cell
|
||||
[editable]="col.editable"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row" />
|
||||
</div>
|
||||
<div *ngSwitchCase="'amount'"
|
||||
class="adf-cell-value"
|
||||
[attr.data-automation-id]="'amount_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-amount-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row"
|
||||
[currencyConfig]="col.currencyConfig" />
|
||||
</div>
|
||||
<div *ngSwitchCase="'number'"
|
||||
class="adf-cell-value"
|
||||
[attr.data-automation-id]="'number_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-number-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row"
|
||||
[decimalConfig]="col.decimalConfig" />
|
||||
</div>
|
||||
<span *ngSwitchDefault class="adf-cell-value">
|
||||
<!-- empty cell for unknown column type -->
|
||||
</span>
|
||||
</ng-container>
|
||||
src="{{ data.getValue(row, col) }}"
|
||||
(error)="onImageLoadingError($event, row)">
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@case ('icon') {
|
||||
<div class="adf-cell-value">
|
||||
<adf-icon-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
@case ('date') {
|
||||
<div
|
||||
class="adf-cell-value adf-cell-date"
|
||||
[attr.data-automation-id]="'date_' + (data.getValue(row, col, resolverFn) | adfLocalizedDate: 'medium') ">
|
||||
<adf-date-cell class="adf-datatable-center-date-column-ie"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)"
|
||||
[dateConfig]="col.dateConfig" />
|
||||
</div>
|
||||
}
|
||||
@case ('location') {
|
||||
<div class="adf-cell-value"
|
||||
[attr.data-automation-id]="'location' + data.getValue(row, col, resolverFn)">
|
||||
<adf-location-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
}
|
||||
@case ('fileSize') {
|
||||
<div class="adf-cell-value"
|
||||
[attr.data-automation-id]="'fileSize_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-filesize-cell class="adf-datatable-center-size-column-ie"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
}
|
||||
@case ('text') {
|
||||
<div class="adf-cell-value"
|
||||
[attr.data-automation-id]="'text_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-datatable-cell
|
||||
[copyContent]="col.copyContent"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
}
|
||||
@case ('boolean') {
|
||||
<div class="adf-cell-value"
|
||||
[attr.data-automation-id]="'boolean_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-boolean-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[row]="row"
|
||||
[resolverFn]="resolverFn"
|
||||
[tooltip]="getCellTooltip(row, col)" />
|
||||
</div>
|
||||
}
|
||||
@case ('json') {
|
||||
<div class="adf-cell-value">
|
||||
<adf-json-cell
|
||||
[editable]="col.editable"
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row" />
|
||||
</div>
|
||||
}
|
||||
@case ('amount') {
|
||||
<div
|
||||
class="adf-cell-value"
|
||||
[attr.data-automation-id]="'amount_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-amount-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row"
|
||||
[currencyConfig]="col.currencyConfig" />
|
||||
</div>
|
||||
}
|
||||
@case ('number') {
|
||||
<div
|
||||
class="adf-cell-value"
|
||||
[attr.data-automation-id]="'number_' + data.getValue(row, col, resolverFn)">
|
||||
<adf-number-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
[resolverFn]="resolverFn"
|
||||
[row]="row"
|
||||
[decimalConfig]="col.decimalConfig" />
|
||||
</div>
|
||||
}
|
||||
@default {
|
||||
<span class="adf-cell-value">
|
||||
<!-- empty cell for unknown column type -->
|
||||
</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div *ngIf="col.template" class="adf-datatable-cell-container">
|
||||
<div class="adf-cell-value">
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="col.template"
|
||||
[ngTemplateOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col, resolverFn) }" />
|
||||
</div>
|
||||
}
|
||||
@if (col.template) {
|
||||
<div class="adf-datatable-cell-container">
|
||||
<div class="adf-cell-value">
|
||||
<ng-container
|
||||
[ngTemplateOutlet]="col.template"
|
||||
[ngTemplateOutletContext]="{ $implicit: { data: data, row: row, col: col }, value: data.getValue(row, col, resolverFn) }" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Row actions (right) -->
|
||||
<div *ngIf="
|
||||
!showProvidedActions &&
|
||||
((actions && actionsPosition === 'right') ||
|
||||
(mainActionTemplate && showMainDatatableActions))"
|
||||
role="gridcell"
|
||||
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie adf-datatable-actions-menu">
|
||||
|
||||
<ng-container *ngIf="(actions && actionsPosition === 'right')">
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
|
||||
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
|
||||
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ROW_OPTION_BUTTON' | translate"
|
||||
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
|
||||
[attr.id]="'action_menu_right_' + idx"
|
||||
[attr.data-automation-id]="'action_menu_' + idx"
|
||||
(keydown.enter)="actionsMenuTrigger.openMenu()">
|
||||
<mat-icon adf-icon="more_vert" />
|
||||
}
|
||||
<!-- Row actions (right) -->
|
||||
@if (
|
||||
!showProvidedActions &&
|
||||
((actions && actionsPosition === 'right') ||
|
||||
(mainActionTemplate && showMainDatatableActions))) {
|
||||
<div
|
||||
role="gridcell"
|
||||
class="adf-datatable-cell adf-datatable__actions-cell adf-datatable-center-actions-column-ie adf-datatable-actions-menu">
|
||||
@if ((actions && actionsPosition === 'right')) {
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu" #actionsMenuTrigger="matMenuTrigger"
|
||||
[ngClass]="getHideActionsWithoutHoverClass(actionsMenuTrigger)"
|
||||
[attr.aria-label]="'ADF-DATATABLE.ACCESSIBILITY.ROW_OPTION_BUTTON' | translate"
|
||||
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
|
||||
[attr.id]="'action_menu_right_' + idx"
|
||||
[attr.data-automation-id]="'action_menu_' + idx"
|
||||
(keydown.enter)="actionsMenuTrigger.openMenu()">
|
||||
<mat-icon adf-icon="more_vert" />
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
@for (action of getRowActions(row); track action) {
|
||||
<button mat-menu-item
|
||||
[attr.data-automation-id]="action.title"
|
||||
[attr.aria-label]="action.title | translate"
|
||||
[disabled]="action.disabled"
|
||||
(click)="onExecuteRowAction(row, action)">
|
||||
@if (action.icon) {
|
||||
<mat-icon [adf-icon]="action.icon" />
|
||||
}
|
||||
<span>{{ action.title | translate }}</span>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let action of getRowActions(row)"
|
||||
[attr.data-automation-id]="action.title"
|
||||
[attr.aria-label]="action.title | translate"
|
||||
[disabled]="action.disabled"
|
||||
(click)="onExecuteRowAction(row, action)">
|
||||
<mat-icon *ngIf="action.icon" [adf-icon]="action.icon" />
|
||||
<span>{{ action.title | translate }}</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
}
|
||||
</mat-menu>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</adf-datatable-row>
|
||||
<div *ngIf="isEmpty()" role="row" class="adf-datatable-row">
|
||||
<div class="adf-no-content-container adf-datatable-cell" role="gridcell">
|
||||
<ng-template *ngIf="noContentTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="noContentTemplate" />
|
||||
<ng-content select="adf-empty-list" />
|
||||
</div>
|
||||
}
|
||||
@if (isEmpty()) {
|
||||
<div role="row" class="adf-datatable-row">
|
||||
<div class="adf-no-content-container adf-datatable-cell" role="gridcell">
|
||||
@if (noContentTemplate) {
|
||||
@for ( of [data]; track ) {
|
||||
<ng-template
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="noContentTemplate" />
|
||||
}
|
||||
}
|
||||
<ng-content select="adf-empty-list" />
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #noPermissionsRowTemplate>
|
||||
<div
|
||||
role="row"
|
||||
class="adf-datatable-row adf-no-permission__row">
|
||||
<div class="adf-no-permission__cell adf-no-content-container adf-datatable-cell">
|
||||
<ng-template *ngIf="noPermissionTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="noPermissionTemplate" />
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<ng-template #loadingRowTemplate>
|
||||
<div class="adf-datatable-row adf-datatable-data-loading">
|
||||
<div class="adf-no-content-container adf-datatable-cell">
|
||||
<ng-template *ngIf="loadingTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="loadingTemplate" />
|
||||
}
|
||||
} @else {
|
||||
<div
|
||||
role="row"
|
||||
class="adf-datatable-row adf-no-permission__row">
|
||||
<div class="adf-no-permission__cell adf-no-content-container adf-datatable-cell">
|
||||
@if (noPermissionTemplate) {
|
||||
@for ( of [data]; track ) {
|
||||
<ng-template
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="noPermissionTemplate" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
} @else {
|
||||
<div class="adf-datatable-row adf-datatable-data-loading">
|
||||
<div class="adf-no-content-container adf-datatable-cell">
|
||||
@if (loadingTemplate) {
|
||||
@for ( of [data]; track ) {
|
||||
<ng-template
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="loadingTemplate" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,42 +1,44 @@
|
||||
<h1 mat-dialog-title data-automation-id="adf-confirm-dialog-title">{{ title | translate }}</h1>
|
||||
<mat-dialog-content>
|
||||
<div class="adf-confirm-dialog-content">
|
||||
<p *ngIf="!htmlContent; else customContent" data-automation-id="adf-confirm-dialog-base-message">{{ message | translate }}</p>
|
||||
<ng-template #customContent>
|
||||
<span [innerHTML]="sanitizedHtmlContent()" data-automation-id="adf-confirm-dialog-custom-content"></span>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="adf-confirm-dialog-content">
|
||||
@if (!htmlContent) {
|
||||
<p data-automation-id="adf-confirm-dialog-base-message">{{ message | translate }}</p>
|
||||
} @else {
|
||||
<span [innerHTML]="sanitizedHtmlContent()" data-automation-id="adf-confirm-dialog-custom-content"></span>
|
||||
}
|
||||
</div>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<span class="adf-dialog-spacer" data-automation-id="adf-confirm-dialog-spacer"></span>
|
||||
<button
|
||||
id="adf-confirm-cancel"
|
||||
class="adf-confirm-dialog-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="false"
|
||||
data-automation-id="adf-confirm-dialog-reject"
|
||||
<span class="adf-dialog-spacer" data-automation-id="adf-confirm-dialog-spacer"></span>
|
||||
<button
|
||||
id="adf-confirm-cancel"
|
||||
class="adf-confirm-dialog-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="false"
|
||||
data-automation-id="adf-confirm-dialog-reject"
|
||||
>
|
||||
{{ noLabel | translate }}
|
||||
</button>
|
||||
{{ noLabel | translate }}
|
||||
</button>
|
||||
@if (thirdOptionLabel) {
|
||||
<button
|
||||
*ngIf="thirdOptionLabel"
|
||||
id="adf-confirm-all"
|
||||
class="adf-confirm-dialog-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="thirdOptionLabel"
|
||||
data-automation-id="adf-confirm-dialog-confirm-all"
|
||||
>
|
||||
{{ thirdOptionLabel | translate }}
|
||||
id="adf-confirm-all"
|
||||
class="adf-confirm-dialog-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="thirdOptionLabel"
|
||||
data-automation-id="adf-confirm-dialog-confirm-all"
|
||||
>
|
||||
{{ thirdOptionLabel | translate }}
|
||||
</button>
|
||||
<button
|
||||
id="adf-confirm-accept"
|
||||
class="adf-confirm-dialog-button"
|
||||
mat-button
|
||||
color="primary"
|
||||
data-automation-id="adf-confirm-dialog-confirmation"
|
||||
[mat-dialog-close]="true"
|
||||
cdkFocusInitial
|
||||
}
|
||||
<button
|
||||
id="adf-confirm-accept"
|
||||
class="adf-confirm-dialog-button"
|
||||
mat-button
|
||||
color="primary"
|
||||
data-automation-id="adf-confirm-dialog-confirmation"
|
||||
[mat-dialog-close]="true"
|
||||
cdkFocusInitial
|
||||
>
|
||||
{{ yesLabel | translate }}
|
||||
</button>
|
||||
{{ yesLabel | translate }}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Component, SecurityContext, ViewEncapsulation, inject } from '@angular/
|
||||
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
|
||||
export interface ConfirmDialogComponentProps {
|
||||
@@ -38,7 +38,7 @@ export interface ConfirmDialogComponentProps {
|
||||
host: { class: 'adf-confirm-dialog' },
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
standalone: true,
|
||||
imports: [TranslatePipe, MatDialogModule, NgIf, MatButtonModule]
|
||||
imports: [TranslatePipe, MatDialogModule, MatButtonModule]
|
||||
})
|
||||
export class ConfirmDialogComponent {
|
||||
private readonly sanitizer = inject(DomSanitizer);
|
||||
|
||||
@@ -1,88 +1,94 @@
|
||||
<div
|
||||
data-automation-id="adf-dialog-container"
|
||||
class="adf-dialog-container {{ dialogSize }}"
|
||||
>
|
||||
<div
|
||||
mat-dialog-title
|
||||
data-automation-id="adf-dialog-header"
|
||||
class="adf-dialog-header"
|
||||
[ngClass]="{ 'adf-centered-header': data.headerIcon }"
|
||||
data-automation-id="adf-dialog-container"
|
||||
class="adf-dialog-container {{ dialogSize }}"
|
||||
>
|
||||
<div
|
||||
mat-dialog-title
|
||||
data-automation-id="adf-dialog-header"
|
||||
class="adf-dialog-header"
|
||||
[ngClass]="{ 'adf-centered-header': data.headerIcon }"
|
||||
>
|
||||
<div class="adf-dialog-title-container" [ngClass]="{ 'adf-centered-title': data.headerIcon }">
|
||||
<mat-icon
|
||||
*ngIf="data.headerIcon"
|
||||
color="primary"
|
||||
class="adf-dialog-header-icon"
|
||||
[adf-icon]="data.headerIcon"
|
||||
/>
|
||||
<h2 class="adf-dialog-title">{{ data.title | translate }}</h2>
|
||||
</div>
|
||||
<button
|
||||
*ngIf="!isCloseButtonHidden"
|
||||
mat-icon-button
|
||||
mat-dialog-close
|
||||
title="{{'CLOSE' | translate }}"
|
||||
data-automation-id="adf-dialog-close-button"
|
||||
<div class="adf-dialog-title-container" [ngClass]="{ 'adf-centered-title': data.headerIcon }">
|
||||
@if (data.headerIcon) {
|
||||
<mat-icon
|
||||
color="primary"
|
||||
class="adf-dialog-header-icon"
|
||||
[adf-icon]="data.headerIcon"
|
||||
/>
|
||||
}
|
||||
<h2 class="adf-dialog-title">{{ data.title | translate }}</h2>
|
||||
</div>
|
||||
@if (!isCloseButtonHidden) {
|
||||
<button
|
||||
mat-icon-button
|
||||
mat-dialog-close
|
||||
title="{{'CLOSE' | translate }}"
|
||||
data-automation-id="adf-dialog-close-button"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</div>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
[ngTemplateOutlet]="data.descriptionTemplate"
|
||||
[ngClass]="{ 'adf-description': data.description || data.descriptionTemplate }"
|
||||
<div
|
||||
[ngTemplateOutlet]="data.descriptionTemplate"
|
||||
[ngClass]="{ 'adf-description': data.description || data.descriptionTemplate }"
|
||||
>
|
||||
<ng-container>{{ data.description | translate }}</ng-container>
|
||||
</div>
|
||||
<ng-container>{{ data.description | translate }}</ng-container>
|
||||
</div>
|
||||
|
||||
<mat-dialog-content *ngIf="data.contentTemplate || data.contentComponent || data.contentText" class="adf-dialog-content">
|
||||
<ng-container [ngTemplateOutlet]="data.contentTemplate" />
|
||||
<ng-container *ngComponentOutlet="data.contentComponent; injector: dataInjector" />
|
||||
<ng-container>{{ data.contentText | translate }}</ng-container>
|
||||
@if (data.contentTemplate || data.contentComponent || data.contentText) {
|
||||
<mat-dialog-content class="adf-dialog-content">
|
||||
<ng-container [ngTemplateOutlet]="data.contentTemplate" />
|
||||
<ng-container *ngComponentOutlet="data.contentComponent; injector: dataInjector" />
|
||||
<ng-container>{{ data.contentText | translate }}</ng-container>
|
||||
</mat-dialog-content>
|
||||
}
|
||||
|
||||
<mat-dialog-actions
|
||||
class="adf-dialog-actions"
|
||||
[ngClass]="{ 'adf-additional-actions': data.actionsTemplate || additionalActionButtons }"
|
||||
<mat-dialog-actions
|
||||
class="adf-dialog-actions"
|
||||
[ngClass]="{ 'adf-additional-actions': data.actionsTemplate || additionalActionButtons }"
|
||||
>
|
||||
<div class="adf-additional-actions-container">
|
||||
<ng-container *ngIf="!additionalActionButtons && data.actionsTemplate">
|
||||
<ng-container [ngTemplateOutlet]="data.actionsTemplate" />
|
||||
</ng-container>
|
||||
<div class="adf-additional-actions-container">
|
||||
@if (!additionalActionButtons && data.actionsTemplate) {
|
||||
<ng-container [ngTemplateOutlet]="data.actionsTemplate" />
|
||||
}
|
||||
|
||||
<ng-container *ngIf="!data.actionsTemplate && additionalActionButtons">
|
||||
<button
|
||||
*ngFor="let additionalButton of additionalActionButtons"
|
||||
mat-button
|
||||
color="primary"
|
||||
class="{{ additionalButton.class }}"
|
||||
(click)="additionalButton.onClick()"
|
||||
>
|
||||
{{ additionalButton.title | translate }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="adf-main-actions-container">
|
||||
<button
|
||||
*ngIf="!isCancelButtonHidden"
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
mat-dialog-close
|
||||
data-automation-id="adf-dialog-actions-cancel"
|
||||
@if (!data.actionsTemplate && additionalActionButtons) {
|
||||
@for (additionalButton of additionalActionButtons; track additionalButton) {
|
||||
<button
|
||||
mat-button
|
||||
color="primary"
|
||||
class="{{ additionalButton.class }}"
|
||||
(click)="additionalButton.onClick()"
|
||||
>
|
||||
{{ cancelButtonTitle | translate }}
|
||||
</button>
|
||||
{{ additionalButton.title | translate }}
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
data-automation-id="adf-dialog-actions-confirm"
|
||||
[disabled]="isConfirmButtonDisabled$ | async"
|
||||
(click)="onConfirm()"
|
||||
>
|
||||
{{ confirmButtonTitle | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-dialog-actions>
|
||||
<div class="adf-main-actions-container">
|
||||
@if (!isCancelButtonHidden) {
|
||||
<button
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
mat-dialog-close
|
||||
data-automation-id="adf-dialog-actions-cancel"
|
||||
>
|
||||
{{ cancelButtonTitle | translate }}
|
||||
</button>
|
||||
}
|
||||
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
data-automation-id="adf-dialog-actions-confirm"
|
||||
[disabled]="isConfirmButtonDisabled$ | async"
|
||||
(click)="onConfirm()"
|
||||
>
|
||||
{{ confirmButtonTitle | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-dialog-actions>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<h1 mat-dialog-title>{{ title | translate }}</h1>
|
||||
<mat-dialog-content class="adf-edit-json-dialog-content">
|
||||
<textarea [(ngModel)]="value" [attr.readonly]="!editable ? true : null"></textarea>
|
||||
<textarea [(ngModel)]="value" [attr.readonly]="!editable ? true : null"></textarea>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button mat-dialog-close cdkFocusInitial>
|
||||
{{ 'CORE.DIALOG.EDIT_JSON.CLOSE' | translate }}
|
||||
</button>
|
||||
<button *ngIf="editable" mat-button [mat-dialog-close]="value">
|
||||
{{ 'CORE.DIALOG.EDIT_JSON.UPDATE' | translate }}
|
||||
<button mat-button mat-dialog-close cdkFocusInitial>
|
||||
{{ 'CORE.DIALOG.EDIT_JSON.CLOSE' | translate }}
|
||||
</button>
|
||||
@if (editable) {
|
||||
<button mat-button [mat-dialog-close]="value">
|
||||
{{ 'CORE.DIALOG.EDIT_JSON.UPDATE' | translate }}
|
||||
</button>
|
||||
}
|
||||
</mat-dialog-actions>
|
||||
|
||||
+30
-28
@@ -1,35 +1,37 @@
|
||||
<h1 mat-dialog-title class="adf-unsaved-changes-dialog-header">
|
||||
{{ dialogData.headerText | translate }}
|
||||
<button
|
||||
data-automation-id="adf-unsaved-changes-dialog-close-button"
|
||||
class="adf-unsaved-changes-dialog-header-close-button"
|
||||
mat-icon-button
|
||||
[title]="'CLOSE' | translate"
|
||||
[mat-dialog-close]="false">
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
{{ dialogData.headerText | translate }}
|
||||
<button
|
||||
data-automation-id="adf-unsaved-changes-dialog-close-button"
|
||||
class="adf-unsaved-changes-dialog-header-close-button"
|
||||
mat-icon-button
|
||||
[title]="'CLOSE' | translate"
|
||||
[mat-dialog-close]="false">
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</h1>
|
||||
<mat-dialog-content class="adf-unsaved-changes-dialog-content">
|
||||
{{ dialogData.descriptionText | translate }}
|
||||
<div class="adf-unsaved-changes-dialog-content-checkbox" *ngIf="dialogData.checkboxText.length">
|
||||
<mat-checkbox data-automation-id="adf-unsaved-changes-dialog-content-checkbox"
|
||||
(change)="onToggleCheckboxPreferences($event)"
|
||||
>{{ dialogData.checkboxText | translate }}</mat-checkbox>
|
||||
{{ dialogData.descriptionText | translate }}
|
||||
@if (dialogData.checkboxText.length) {
|
||||
<div class="adf-unsaved-changes-dialog-content-checkbox">
|
||||
<mat-checkbox data-automation-id="adf-unsaved-changes-dialog-content-checkbox"
|
||||
(change)="onToggleCheckboxPreferences($event)"
|
||||
>{{ dialogData.checkboxText | translate }}</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end" class="adf-unsaved-changes-dialog-actions">
|
||||
<button
|
||||
data-automation-id="adf-unsaved-changes-dialog-cancel-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="false"
|
||||
class="adf-unsaved-changes-dialog-actions-cancel-button">
|
||||
{{ 'CANCEL' | translate | titlecase }}
|
||||
</button>
|
||||
<button
|
||||
data-automation-id="adf-unsaved-changes-dialog-discard-changes-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="true"
|
||||
class="adf-unsaved-changes-dialog-actions-discard-changes-button">
|
||||
{{ dialogData.confirmButtonText | translate }}
|
||||
</button>
|
||||
<button
|
||||
data-automation-id="adf-unsaved-changes-dialog-cancel-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="false"
|
||||
class="adf-unsaved-changes-dialog-actions-cancel-button">
|
||||
{{ 'CANCEL' | translate | titlecase }}
|
||||
</button>
|
||||
<button
|
||||
data-automation-id="adf-unsaved-changes-dialog-discard-changes-button"
|
||||
mat-button
|
||||
[mat-dialog-close]="true"
|
||||
class="adf-unsaved-changes-dialog-actions-discard-changes-button">
|
||||
{{ dialogData.confirmButtonText | translate }}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing';
|
||||
import { InfiniteSelectScrollDirective } from './infinite-select-scroll.directive';
|
||||
import { MatSelect, MatSelectModule } from '@angular/material/select';
|
||||
@@ -26,12 +26,14 @@ import { UnitTestingUtils } from '../testing/unit-testing-utils';
|
||||
|
||||
@Component({
|
||||
template: ` <mat-select adf-infinite-select-scroll (scrollEnd)="load()">
|
||||
<mat-option *ngFor="let option of options; let idx = index">
|
||||
{{ option.text }}
|
||||
</mat-option>
|
||||
</mat-select>`,
|
||||
@for (option of options; track option; let idx = $index) {
|
||||
<mat-option>
|
||||
{{ option.text }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>`,
|
||||
standalone: true,
|
||||
imports: [MatSelectModule, InfiniteSelectScrollDirective, CommonModule]
|
||||
imports: [MatSelectModule, InfiniteSelectScrollDirective]
|
||||
})
|
||||
class TestComponent {
|
||||
options = new Array(50).fill({ text: 'dummy' });
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<div @tooltip class="adf-tooltip-card" [style.width.px]="width">
|
||||
<img *ngIf="image " [src]="image" [width]="width" alt="{{text}}">
|
||||
<hr *ngIf="image" />
|
||||
<p *ngIf="text">{{text}}</p>
|
||||
<div *ngIf="htmlContent" [innerHTML]="sanitizedHtmlContent()" class="adf-tooltip-card-content"></div>
|
||||
@if (image ) {
|
||||
<img [src]="image" [width]="width" alt="{{text}}">
|
||||
}
|
||||
@if (image) {
|
||||
<hr />
|
||||
}
|
||||
@if (text) {
|
||||
<p>{{text}}</p>
|
||||
}
|
||||
@if (htmlContent) {
|
||||
<div [innerHTML]="sanitizedHtmlContent()" class="adf-tooltip-card-content"></div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
import { Component, Input, SecurityContext, inject } from '@angular/core';
|
||||
import { animate, style, transition, trigger } from '@angular/animations';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'adf-tooltip-card-component',
|
||||
imports: [CommonModule],
|
||||
imports: [],
|
||||
templateUrl: './tooltip-card.component.html',
|
||||
styleUrls: ['./tooltip-card.component.scss'],
|
||||
animations: [
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
<div
|
||||
class="adf-dynamic-chip-list-container"
|
||||
[class.adf-dynamic-chip-list-flex-column]="limitChipsDisplayed && (!calculationsDone || columnFlexDirection)"
|
||||
[class.adf-dynamic-chip-list-button-in-next-line]="moveLoadMoreButtonToNextRow"
|
||||
[class.adf-dynamic-chip-list-paginated]="paginationData"
|
||||
#nodeListContainer>
|
||||
<mat-chip-set
|
||||
[class.adf-dynamic-chip-list-full-width]="limitChipsDisplayed && !calculationsDone"
|
||||
role="list"
|
||||
[attr.aria-label]="'METADATA.BASIC.TAGS' | translate">
|
||||
<mat-chip
|
||||
*ngFor="let chip of chipsToDisplay; let idx = index"
|
||||
class="adf-dynamic-chip-list-chip"
|
||||
[style.border-radius]="roundUpChips ? '20px' : '10px'"
|
||||
[style.font-weight]="'bold'"
|
||||
role="listitem"
|
||||
[attr.aria-label]="chip.name"
|
||||
(removed)="removedChip.emit(chip.id)">
|
||||
<span id="adf-dynamic-chip-list-chip-name-{{ idx }}">{{ chip.name }}</span>
|
||||
<mat-icon
|
||||
*ngIf="showDelete"
|
||||
id="adf-dynamic-chip-list-delete-{{ chip.name }}"
|
||||
class="adf-dynamic-chip-list-delete-icon"
|
||||
[disabled]="disableDelete"
|
||||
adf-icon="close"
|
||||
matChipRemove
|
||||
class="adf-dynamic-chip-list-container"
|
||||
[class.adf-dynamic-chip-list-flex-column]="limitChipsDisplayed && (!calculationsDone || columnFlexDirection)"
|
||||
[class.adf-dynamic-chip-list-button-in-next-line]="moveLoadMoreButtonToNextRow"
|
||||
[class.adf-dynamic-chip-list-paginated]="paginationData"
|
||||
#nodeListContainer>
|
||||
<mat-chip-set
|
||||
[class.adf-dynamic-chip-list-full-width]="limitChipsDisplayed && !calculationsDone"
|
||||
role="list"
|
||||
[attr.aria-label]="'METADATA.BASIC.TAGS' | translate">
|
||||
@for (chip of chipsToDisplay; track chip; let idx = $index) {
|
||||
<mat-chip
|
||||
class="adf-dynamic-chip-list-chip"
|
||||
[style.border-radius]="roundUpChips ? '20px' : '10px'"
|
||||
[style.font-weight]="'bold'"
|
||||
role="listitem"
|
||||
[attr.aria-label]="chip.name"
|
||||
(removed)="removedChip.emit(chip.id)">
|
||||
<span id="adf-dynamic-chip-list-chip-name-{{ idx }}">{{ chip.name }}</span>
|
||||
@if (showDelete) {
|
||||
<mat-icon
|
||||
id="adf-dynamic-chip-list-delete-{{ chip.name }}"
|
||||
class="adf-dynamic-chip-list-delete-icon"
|
||||
[disabled]="disableDelete"
|
||||
adf-icon="close"
|
||||
matChipRemove
|
||||
/>
|
||||
</mat-chip>
|
||||
</mat-chip-set>
|
||||
<button
|
||||
data-automation-id="adf-dynamic-chip-list-view-more-button"
|
||||
mat-button
|
||||
[hidden]="chipsToDisplay?.length === 0 || !limitChipsDisplayed"
|
||||
[style.left.px]="viewMoreButtonLeftOffset"
|
||||
[style.top.px]="!!pagination ? viewMoreButtonTop : ''"
|
||||
class="adf-dynamic-chip-list-view-more-button"
|
||||
[class.adf-dynamic-chip-list-hidden-btn]="!calculationsDone"
|
||||
(click)="displayNextChips($event)">
|
||||
{{
|
||||
paginationData ? ('DYNAMIC_CHIP_LIST.LOAD_MORE' | translate) :
|
||||
('TAG_NODE_LIST.VIEW_MORE' | translate: { count: undisplayedChipsCount })
|
||||
}}
|
||||
</button>
|
||||
}
|
||||
</mat-chip>
|
||||
}
|
||||
</mat-chip-set>
|
||||
<button
|
||||
data-automation-id="adf-dynamic-chip-list-view-more-button"
|
||||
mat-button
|
||||
[hidden]="chipsToDisplay?.length === 0 || !limitChipsDisplayed"
|
||||
[style.left.px]="viewMoreButtonLeftOffset"
|
||||
[style.top.px]="!!pagination ? viewMoreButtonTop : ''"
|
||||
class="adf-dynamic-chip-list-view-more-button"
|
||||
[class.adf-dynamic-chip-list-hidden-btn]="!calculationsDone"
|
||||
(click)="displayNextChips($event)">
|
||||
{{
|
||||
paginationData ? ('DYNAMIC_CHIP_LIST.LOAD_MORE' | translate) :
|
||||
('TAG_NODE_LIST.VIEW_MORE' | translate: { count: undisplayedChipsCount })
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Pagination } from '@alfresco/js-api';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
@@ -48,7 +48,7 @@ import { IconModule } from '../icon/icon.module';
|
||||
selector: 'adf-dynamic-chip-list',
|
||||
templateUrl: './dynamic-chip-list.component.html',
|
||||
styleUrls: ['./dynamic-chip-list.component.scss'],
|
||||
imports: [MatChipsModule, TranslatePipe, NgForOf, IconModule, NgIf, MatButtonModule],
|
||||
imports: [MatChipsModule, TranslatePipe, IconModule, MatButtonModule],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DynamicChipListComponent implements OnChanges, OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
@@ -1,135 +1,158 @@
|
||||
<div id="adf-form-renderer" class="{{ formDefinition.className }} adf-form-renderer"
|
||||
[ngClass]="{ 'adf-readonly-form': formDefinition.readOnly }">
|
||||
<div *ngIf="formDefinition.hasTabs()">
|
||||
<div *ngIf="hasTabs()" class="alfresco-tabs-widget">
|
||||
<mat-tab-group [preserveContent]="true">
|
||||
<mat-tab *ngFor="let tab of visibleTabs()" [label]="tab.title | translate ">
|
||||
<ng-template matTabContent>
|
||||
<div class="adf-form-tab-content">
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: tab.fields }" />
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
[ngClass]="{ 'adf-readonly-form': formDefinition.readOnly }">
|
||||
@if (formDefinition.hasTabs()) {
|
||||
<div>
|
||||
@if (hasTabs()) {
|
||||
<div class="alfresco-tabs-widget">
|
||||
<mat-tab-group [preserveContent]="true">
|
||||
@for (tab of visibleTabs(); track tab) {
|
||||
<mat-tab [label]="tab.title | translate ">
|
||||
<ng-template matTabContent>
|
||||
<div class="adf-form-tab-content">
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: tab.fields }" />
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
}
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div *ngIf="!formDefinition.hasTabs() && formDefinition.hasFields()">
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: formDefinition.fields }" />
|
||||
@if (!formDefinition.hasTabs() && formDefinition.hasFields()) {
|
||||
<div>
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: formDefinition.fields }" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<ng-template #render let-fieldToRender="fieldToRender">
|
||||
<div *ngFor="let currentRootElement of fieldToRender">
|
||||
<div *ngIf="currentRootElement.type === 'section'" [id]="'field-' + currentRootElement?.id + '-container'" class="adf-container-widget">
|
||||
<adf-form-section [field]="currentRootElement" />
|
||||
@for (currentRootElement of fieldToRender; track currentRootElement) {
|
||||
<div>
|
||||
@if (currentRootElement.type === 'section') {
|
||||
<div [id]="'field-' + currentRootElement?.id + '-container'" class="adf-container-widget">
|
||||
<adf-form-section [field]="currentRootElement" />
|
||||
</div>
|
||||
|
||||
<div *ngIf="currentRootElement.type === 'container' || currentRootElement.type === 'group'"
|
||||
[id]="'field-' + currentRootElement?.id + '-container'"
|
||||
class="adf-container-widget"
|
||||
[hidden]="!currentRootElement?.isVisible">
|
||||
<adf-header-widget [element]="currentRootElement" />
|
||||
<div *ngIf="currentRootElement?.form?.enableFixedSpace; else fixingTemplate">
|
||||
}
|
||||
@if (currentRootElement.type === 'container' || currentRootElement.type === 'group') {
|
||||
<div
|
||||
[id]="'field-' + currentRootElement?.id + '-container'"
|
||||
class="adf-container-widget"
|
||||
[hidden]="!currentRootElement?.isVisible">
|
||||
<adf-header-widget [element]="currentRootElement" />
|
||||
@if (currentRootElement?.form?.enableFixedSpace) {
|
||||
<div>
|
||||
@if (currentRootElement?.isExpanded) {
|
||||
<div class="adf-grid-list"
|
||||
[ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }"
|
||||
*ngIf="currentRootElement?.isExpanded">
|
||||
[ngStyle]="{ 'grid-template-columns': 'repeat(' + getNumberOfColumns(currentRootElement) + ', 1fr)' }"
|
||||
>
|
||||
@for (field of getContainerFields(currentRootElement); track field) {
|
||||
<div class="adf-grid-list-item"
|
||||
*ngFor="let field of getContainerFields(currentRootElement)"
|
||||
[ngStyle]="{ 'grid-area': 'auto / auto / span ' + (field?.rowspan || 1) + ' / span ' + (field?.colspan || 1) }">
|
||||
<adf-form-field *ngIf="field" [field]="field" />
|
||||
[ngStyle]="{ 'grid-area': 'auto / auto / span ' + (field?.rowspan || 1) + ' / span ' + (field?.colspan || 1) }">
|
||||
@if (field) {
|
||||
<adf-form-field [field]="field" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<ng-template #fixingTemplate>
|
||||
<section class="adf-grid-list-column-view" *ngIf="currentRootElement?.isExpanded">
|
||||
<div class="adf-grid-list-single-column"
|
||||
*ngFor="let column of currentRootElement?.columns"
|
||||
[style.width.%]="getColumnWidth(currentRootElement)"
|
||||
} @else {
|
||||
@if (currentRootElement?.isExpanded) {
|
||||
<section class="adf-grid-list-column-view">
|
||||
@for (column of currentRootElement?.columns; track column) {
|
||||
<div class="adf-grid-list-single-column"
|
||||
[style.width.%]="getColumnWidth(currentRootElement)"
|
||||
>
|
||||
<ng-container *ngFor="let field of column?.fields">
|
||||
<ng-container *ngIf="field.type === 'section'; else formField">
|
||||
<adf-form-section [field]="field"/>
|
||||
</ng-container>
|
||||
<ng-template #formField>
|
||||
<div class="adf-grid-list-column-view-item">
|
||||
<adf-form-field [field]="field"/>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</div>
|
||||
</section>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #columnViewItem let-column="column">
|
||||
<div class="adf-grid-list-column-view-item" *ngFor="let field of column?.fields">
|
||||
<adf-form-field *ngIf="field" [field]="field" />
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@if (currentRootElement.type === 'repeatable-section') {
|
||||
<div
|
||||
[id]="'field-' + currentRootElement?.id + '-container'"
|
||||
class="adf-container-widget"
|
||||
[hidden]="!currentRootElement?.isVisible"
|
||||
>
|
||||
<adf-repeat-widget [element]="currentRootElement" [isEditor]="false">
|
||||
@for (row of currentRootElement.field.rows; track row.id; let rowIndex = $index) {
|
||||
@let hasMultipleRows = currentRootElement.field.rows.length > 1;
|
||||
<div
|
||||
class="adf-grid-list-container"
|
||||
[class.adf-grid-list-container-multiple]="hasMultipleRows"
|
||||
[class.adf-grid-list-container-disabled]="currentRootElement.field.readOnly"
|
||||
>
|
||||
<div class="adf-grid-list-row">
|
||||
<span class="adf-grid-list-row-label">{{ 'FORM.FORM_RENDERER.ROW_LABEL' | translate: {number: rowIndex + 1} }}</span>
|
||||
|
||||
@let shouldDisplayRemoveRowButton = !currentRootElement.field.rows[rowIndex].isInitial || (currentRootElement.field.rows[rowIndex].isInitial && currentRootElement.field.params.allowInitialRowsDelete);
|
||||
@if (shouldDisplayRemoveRowButton) {
|
||||
<button
|
||||
mat-icon-button
|
||||
class="adf-grid-list-row-remove-button"
|
||||
[disabled]="currentRootElement.field.readOnly"
|
||||
[matTooltip]="'FORM.FORM_RENDERER.DELETE_ROW' | translate"
|
||||
(click)="displayDialogToRemoveRow(currentRootElement.field, rowIndex)"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<section class="adf-grid-list-column-view">
|
||||
@for (column of row.columns; track $index) {
|
||||
<div
|
||||
class="adf-grid-list-single-column"
|
||||
[style.width.%]="getColumnWidth(currentRootElement)"
|
||||
>
|
||||
@for (field of column?.fields; track $index) {
|
||||
@if (field.type === 'section') {
|
||||
<adf-form-section [field]="field"/>
|
||||
} @else {
|
||||
<div class="adf-grid-list-column-view-item">
|
||||
<adf-form-field [field]="field"/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
@for (field of column?.fields; track field) {
|
||||
@if (field.type === 'section') {
|
||||
<adf-form-section [field]="field"/>
|
||||
} @else {
|
||||
<div class="adf-grid-list-column-view-item">
|
||||
<adf-form-field [field]="field"/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</adf-repeat-widget>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div *ngIf="currentRootElement.type === 'dynamic-table'" class="adf-container-widget">
|
||||
<adf-form-field [field]="currentRootElement" />
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
}
|
||||
}
|
||||
<ng-template #columnViewItem let-column="column">
|
||||
@for (field of column?.fields; track field) {
|
||||
<div class="adf-grid-list-column-view-item">
|
||||
@if (field) {
|
||||
<adf-form-field [field]="field" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
}
|
||||
@if (currentRootElement.type === 'repeatable-section') {
|
||||
<div
|
||||
[id]="'field-' + currentRootElement?.id + '-container'"
|
||||
class="adf-container-widget"
|
||||
[hidden]="!currentRootElement?.isVisible"
|
||||
>
|
||||
<adf-repeat-widget [element]="currentRootElement" [isEditor]="false">
|
||||
@for (row of currentRootElement.field.rows; track row.id; let rowIndex = $index) {
|
||||
@let hasMultipleRows = currentRootElement.field.rows.length > 1;
|
||||
<div
|
||||
class="adf-grid-list-container"
|
||||
[class.adf-grid-list-container-multiple]="hasMultipleRows"
|
||||
[class.adf-grid-list-container-disabled]="currentRootElement.field.readOnly"
|
||||
>
|
||||
<div class="adf-grid-list-row">
|
||||
<span class="adf-grid-list-row-label">{{ 'FORM.FORM_RENDERER.ROW_LABEL' | translate: {number: rowIndex + 1} }}</span>
|
||||
@let shouldDisplayRemoveRowButton = !currentRootElement.field.rows[rowIndex].isInitial || (currentRootElement.field.rows[rowIndex].isInitial && currentRootElement.field.params.allowInitialRowsDelete);
|
||||
@if (shouldDisplayRemoveRowButton) {
|
||||
<button
|
||||
mat-icon-button
|
||||
class="adf-grid-list-row-remove-button"
|
||||
[disabled]="currentRootElement.field.readOnly"
|
||||
[matTooltip]="'FORM.FORM_RENDERER.DELETE_ROW' | translate"
|
||||
(click)="displayDialogToRemoveRow(currentRootElement.field, rowIndex)"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<section class="adf-grid-list-column-view">
|
||||
@for (column of row.columns; track $index) {
|
||||
<div
|
||||
class="adf-grid-list-single-column"
|
||||
[style.width.%]="getColumnWidth(currentRootElement)"
|
||||
>
|
||||
@for (field of column?.fields; track $index) {
|
||||
@if (field.type === 'section') {
|
||||
<adf-form-section [field]="field"/>
|
||||
} @else {
|
||||
<div class="adf-grid-list-column-view-item">
|
||||
<adf-form-field [field]="field"/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
}
|
||||
</adf-repeat-widget>
|
||||
</div>
|
||||
}
|
||||
@if (currentRootElement.type === 'dynamic-table') {
|
||||
<div class="adf-container-widget">
|
||||
<adf-form-field [field]="currentRootElement" />
|
||||
</div>
|
||||
}
|
||||
@if (currentRootElement.type === 'readonly' && currentRootElement.field.params.field.type === 'dynamic-table') {
|
||||
<div class="adf-container-widget"
|
||||
*ngIf="currentRootElement.type === 'readonly' && currentRootElement.field.params.field.type === 'dynamic-table'">
|
||||
<adf-form-field [field]="currentRootElement.field"/>
|
||||
>
|
||||
<adf-form-field [field]="currentRootElement.field"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</ng-template>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NgClass, NgForOf, NgIf, NgStyle, NgTemplateOutlet } from '@angular/common';
|
||||
import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component, inject, Injector, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
@@ -51,22 +51,20 @@ import { IconModule } from '../../icon/icon.module';
|
||||
}
|
||||
],
|
||||
imports: [
|
||||
NgIf,
|
||||
MatTabsModule,
|
||||
NgForOf,
|
||||
NgTemplateOutlet,
|
||||
TranslatePipe,
|
||||
MatButtonModule,
|
||||
IconModule,
|
||||
NgStyle,
|
||||
FormFieldComponent,
|
||||
FormsModule,
|
||||
NgClass,
|
||||
HeaderWidgetComponent,
|
||||
FormSectionComponent,
|
||||
RepeatWidgetComponent,
|
||||
MatTooltipModule
|
||||
],
|
||||
MatTabsModule,
|
||||
NgTemplateOutlet,
|
||||
TranslatePipe,
|
||||
MatButtonModule,
|
||||
IconModule,
|
||||
NgStyle,
|
||||
FormFieldComponent,
|
||||
FormsModule,
|
||||
NgClass,
|
||||
HeaderWidgetComponent,
|
||||
FormSectionComponent,
|
||||
RepeatWidgetComponent,
|
||||
MatTooltipModule
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FormRendererComponent<T> implements OnInit, OnDestroy {
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<div class="adf-grid-list-section-single-column"
|
||||
[id]="'field-' + field?.id + '-container'"
|
||||
[style.display]="field?.isVisible ? 'flex' : 'none'">
|
||||
<div *ngFor="let sectionColumn of field.columns"
|
||||
[style.width.%]="getSectionColumnWidth(field.numberOfColumns, sectionColumn.fields)"
|
||||
>
|
||||
<div *ngFor="let sectionField of sectionColumn.fields" class="adf-grid-list-section-column-view-item">
|
||||
<adf-form-field [field]="sectionField"/>
|
||||
[id]="'field-' + field?.id + '-container'"
|
||||
[style.display]="field?.isVisible ? 'flex' : 'none'">
|
||||
@for (sectionColumn of field.columns; track sectionColumn) {
|
||||
<div
|
||||
[style.width.%]="getSectionColumnWidth(field.numberOfColumns, sectionColumn.fields)"
|
||||
>
|
||||
@for (sectionField of sectionColumn.fields; track sectionField) {
|
||||
<div class="adf-grid-list-section-column-view-item">
|
||||
<adf-form-field [field]="sectionField"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -19,14 +19,14 @@ import { Component, inject, Input, OnInit, ViewEncapsulation } from '@angular/co
|
||||
import { WidgetVisibilityService } from '../../services/widget-visibility.service';
|
||||
import { FormFieldModel } from '../widgets/core/form-field.model';
|
||||
import { FormFieldComponent } from '../form-field/form-field.component';
|
||||
import { NgFor } from '@angular/common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'adf-form-section',
|
||||
templateUrl: './form-section.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
styleUrls: ['./form-section.component.scss'],
|
||||
imports: [NgFor, FormFieldComponent]
|
||||
imports: [FormFieldComponent]
|
||||
})
|
||||
export class FormSectionComponent implements OnInit {
|
||||
@Input()
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
<div
|
||||
class="adf-amount-widget__container adf-amount-widget {{field.className}}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels"
|
||||
>
|
||||
<div *ngIf="field.leftLabels">
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id"
|
||||
>{{field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span></label
|
||||
class="adf-amount-widget__container adf-amount-widget {{field.className}}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels"
|
||||
>
|
||||
@if (field.leftLabels) {
|
||||
<div>
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id"
|
||||
>{{field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span></label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="adf-amount-widget-container">
|
||||
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
|
||||
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{field.name | translate }}</mat-label> }
|
||||
@if(!enableDisplayBasedOnLocale) {
|
||||
<span matTextPrefix class="adf-amount-widget__prefix-spacing">{{ currency }} </span>
|
||||
}
|
||||
<input
|
||||
matInput
|
||||
[title]="field.tooltip"
|
||||
class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[required]="field.required && field.isVisible"
|
||||
[placeholder]="placeholder"
|
||||
[value]="amountWidgetValue"
|
||||
[(ngModel)]="amountWidgetValue"
|
||||
(ngModelChange)="onFieldChangedAmountWidget()"
|
||||
[disabled]="field.readOnly"
|
||||
(focus)="amountWidgetOnFocus()"
|
||||
(blur)="amountWidgetOnBlur()"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
<error-widget
|
||||
*ngIf="isInvalidFieldRequired() && isTouched()"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
<mat-form-field class="adf-amount-widget__input adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
|
||||
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{field.name | translate }}</mat-label> }
|
||||
@if(!enableDisplayBasedOnLocale) {
|
||||
<span matTextPrefix class="adf-amount-widget__prefix-spacing">{{ currency }} </span>
|
||||
}
|
||||
<input
|
||||
matInput
|
||||
[title]="field.tooltip"
|
||||
class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[required]="field.required && field.isVisible"
|
||||
[placeholder]="placeholder"
|
||||
[value]="amountWidgetValue"
|
||||
[(ngModel)]="amountWidgetValue"
|
||||
(ngModelChange)="onFieldChangedAmountWidget()"
|
||||
[disabled]="field.readOnly"
|
||||
(focus)="amountWidgetOnFocus()"
|
||||
(blur)="amountWidgetOnBlur()"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
@if (isInvalidFieldRequired() && isTouched()) {
|
||||
<error-widget
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { CurrencyPipe, NgIf } from '@angular/common';
|
||||
import { CurrencyPipe } from '@angular/common';
|
||||
import { Component, OnInit, ViewEncapsulation, InjectionToken, inject, DestroyRef } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
@@ -52,7 +52,7 @@ export const ADF_AMOUNT_SETTINGS = new InjectionToken<Observable<AmountWidgetSet
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent, TranslatePipe, NgIf],
|
||||
imports: [MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent, TranslatePipe],
|
||||
providers: [CurrencyPipe],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
<div [ngClass]="field.className"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()" class="adf-checkbox-widget-container"
|
||||
>
|
||||
<mat-checkbox [id]="field.id"
|
||||
color="primary"
|
||||
class="adf-checkbox"
|
||||
[required]="isRequired()"
|
||||
[disabled]="field.readOnly || readOnly"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[title]="field.tooltip"
|
||||
(click)="markAsTouched()"
|
||||
>
|
||||
{{ field.name | translate }}
|
||||
<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</mat-checkbox>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
<error-widget
|
||||
*ngIf="isInvalidFieldRequired() && isTouched()"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()" class="adf-checkbox-widget-container"
|
||||
>
|
||||
<mat-checkbox [id]="field.id"
|
||||
color="primary"
|
||||
class="adf-checkbox"
|
||||
[required]="isRequired()"
|
||||
[disabled]="field.readOnly || readOnly"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[title]="field.tooltip"
|
||||
(click)="markAsTouched()"
|
||||
>
|
||||
{{ field.name | translate }}
|
||||
<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</mat-checkbox>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
@if (isInvalidFieldRequired() && isTouched()) {
|
||||
<error-widget
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
|
||||
|
||||
import { NgClass, NgIf } from '@angular/common';
|
||||
import { NgClass } from '@angular/common';
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
@@ -47,7 +47,7 @@ import { WidgetComponent } from '../widget.component';
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [NgClass, MatCheckboxModule, FormsModule, TranslatePipe, ErrorWidgetComponent, NgIf],
|
||||
imports: [NgClass, MatCheckboxModule, FormsModule, TranslatePipe, ErrorWidgetComponent],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class CheckboxWidgetComponent extends WidgetComponent {}
|
||||
|
||||
@@ -1,44 +1,48 @@
|
||||
<div class="{{ field.className }}"
|
||||
id="data-time-widget"
|
||||
[class.adf-invalid]="datetimeInputControl.invalid && datetimeInputControl.touched"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
<div *ngIf="field.leftLabels">
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }} ({{ field.dateDisplayFormat }})<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
id="data-time-widget"
|
||||
[class.adf-invalid]="datetimeInputControl.invalid && datetimeInputControl.touched"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
@if (field.leftLabels) {
|
||||
<div>
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }} ({{ field.dateDisplayFormat }})<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="adf-date-time-widget-container">
|
||||
<mat-form-field class="adf-date-time-widget adf-form-field-input"
|
||||
[class.adf-left-label-input-datepicker]="field.leftLabels"
|
||||
[floatLabel]="field.placeholder ? 'always' : null">
|
||||
@if( (field.name || field?.required) && !field.leftLabels) {
|
||||
<mat-label class="adf-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
|
||||
</mat-label>
|
||||
}
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[readonly]="field.readOnly"
|
||||
[required]="field.required && field.isVisible"
|
||||
[id]="field.id"
|
||||
[formControl]="datetimeInputControl"
|
||||
(keydown.enter)="datetimePicker.open()"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
[min]="minDate"
|
||||
[max]="maxDate">
|
||||
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker"
|
||||
[disabled]="field.readOnly" />
|
||||
<mat-datetimepicker #datetimePicker
|
||||
data-automation-id="adf-date-time-widget-picker"
|
||||
type="datetime"
|
||||
[touchUi]="true"
|
||||
[timeInterval]="5"
|
||||
[disabled]="field.readOnly" />
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget *ngIf="datetimeInputControl.invalid && datetimeInputControl.touched" [error]="field.validationSummary" />
|
||||
</div>
|
||||
}
|
||||
<div class="adf-date-time-widget-container">
|
||||
<mat-form-field class="adf-date-time-widget adf-form-field-input"
|
||||
[class.adf-left-label-input-datepicker]="field.leftLabels"
|
||||
[floatLabel]="field.placeholder ? 'always' : null">
|
||||
@if( (field.name || field?.required) && !field.leftLabels) {
|
||||
<mat-label class="adf-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
|
||||
</mat-label>
|
||||
}
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[readonly]="field.readOnly"
|
||||
[required]="field.required && field.isVisible"
|
||||
[id]="field.id"
|
||||
[formControl]="datetimeInputControl"
|
||||
(keydown.enter)="datetimePicker.open()"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
[min]="minDate"
|
||||
[max]="maxDate">
|
||||
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker"
|
||||
[disabled]="field.readOnly" />
|
||||
<mat-datetimepicker #datetimePicker
|
||||
data-automation-id="adf-date-time-widget-picker"
|
||||
type="datetime"
|
||||
[touchUi]="true"
|
||||
[timeInterval]="5"
|
||||
[disabled]="field.readOnly" />
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
@if (datetimeInputControl.invalid && datetimeInputControl.touched) {
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { FormControl, ReactiveFormsModule, ValidationErrors, Validators } from '@angular/forms';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
@@ -46,7 +46,7 @@ import { ReactiveFormWidget } from '../reactive-widget.interface';
|
||||
host: {
|
||||
'(click)': 'event($event)'
|
||||
},
|
||||
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, MatDatetimepickerModule, ReactiveFormsModule, ErrorWidgetComponent],
|
||||
imports: [TranslatePipe, MatFormFieldModule, MatInputModule, MatDatetimepickerModule, ReactiveFormsModule, ErrorWidgetComponent],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
<div class="{{ field.className }} date-widget-container" id="data-widget" [class.adf-invalid]="dateInputControl.invalid && dateInputControl.touched">
|
||||
<mat-form-field class="adf-date-widget adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
|
||||
<mat-label class="adf-label"
|
||||
[id]="field.id + '-label'"
|
||||
[attr.for]="field.id">
|
||||
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
|
||||
</mat-label>
|
||||
<input matInput
|
||||
[matDatepicker]="datePicker"
|
||||
[id]="field.id"
|
||||
[formControl]="dateInputControl"
|
||||
[placeholder]="field.placeholder"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[required]="field.required && field.isVisible"
|
||||
[readonly]="field.readOnly"
|
||||
<mat-form-field class="adf-date-widget adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
|
||||
<mat-label class="adf-label"
|
||||
[id]="field.id + '-label'"
|
||||
[attr.for]="field.id">
|
||||
{{ field.name | translate }} ({{ field.dateDisplayFormat }})
|
||||
</mat-label>
|
||||
<input matInput
|
||||
[matDatepicker]="datePicker"
|
||||
[id]="field.id"
|
||||
[formControl]="dateInputControl"
|
||||
[placeholder]="field.placeholder"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[required]="field.required && field.isVisible"
|
||||
[readonly]="field.readOnly"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly" />
|
||||
<mat-datepicker #datePicker
|
||||
[startAt]="startAt"
|
||||
[disabled]="field.readOnly" />
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
@if (dateInputControl.invalid && dateInputControl.touched) {
|
||||
<error-widget
|
||||
[error]="field.validationSummary"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly" />
|
||||
<mat-datepicker #datePicker
|
||||
[startAt]="startAt"
|
||||
[disabled]="field.readOnly" />
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget
|
||||
*ngIf="dateInputControl.invalid && dateInputControl.touched"
|
||||
[error]="field.validationSummary"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { FormControl, ReactiveFormsModule, ValidationErrors, Validators } from '@angular/forms';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
@@ -53,7 +53,7 @@ import { ReactiveFormWidget } from '../reactive-widget.interface';
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [MatFormFieldModule, TranslatePipe, MatInputModule, MatDatepickerModule, ReactiveFormsModule, ErrorWidgetComponent, NgIf],
|
||||
imports: [MatFormFieldModule, TranslatePipe, MatInputModule, MatDatepickerModule, ReactiveFormsModule, ErrorWidgetComponent],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DateWidgetComponent extends WidgetComponent implements OnInit, ReactiveFormWidget {
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
<div class="adf-textfield adf-decimal-widget {{ field.className }}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
<div *ngIf="field.leftLabels">
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
@if (field.leftLabels) {
|
||||
<div>
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="adf-decimal-widget-container">
|
||||
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
|
||||
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{ field.name | translate }}</mat-label> }
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
pattern="-?[0-9]*(\.[0-9]*)?"
|
||||
[id]="field.id"
|
||||
[required]="field.required && field.isVisible"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()" />
|
||||
</mat-form-field>
|
||||
<div class="adf-decimal-widget-container">
|
||||
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
|
||||
@if ( (field.name || field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">{{ field.name | translate }}</mat-label> }
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
pattern="-?[0-9]*(\.[0-9]*)?"
|
||||
[id]="field.id"
|
||||
[required]="field.required && field.isVisible"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()" />
|
||||
</mat-form-field>
|
||||
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
<error-widget
|
||||
*ngIf="isInvalidFieldRequired() && isTouched()"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
@if (isInvalidFieldRequired() && isTouched()) {
|
||||
<error-widget
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
@@ -39,7 +39,7 @@ import { WidgetComponent } from '../widget.component';
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent],
|
||||
imports: [TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DecimalWidgetComponent extends WidgetComponent {}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<div class="adf-error-container adf-error-widget-container">
|
||||
<div *ngIf="error?.isActive()" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ error.message | translate:translateParameters }}</div>
|
||||
@if (error?.isActive()) {
|
||||
<div [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ error.message | translate:translateParameters }}</div>
|
||||
</div>
|
||||
<div *ngIf="required" [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ required }}</div>
|
||||
}
|
||||
@if (required) {
|
||||
<div [@transitionMessages]="subscriptAnimationState" class="adf-error">
|
||||
<mat-icon class="adf-error-icon" adf-icon="error_outline" />
|
||||
<div class="adf-error-text">{{ required }}</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { ErrorMessageModel } from '../core';
|
||||
@@ -52,7 +52,7 @@ import { IconModule } from '../../../../icon/icon.module';
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [NgIf, IconModule, TranslatePipe],
|
||||
imports: [IconModule, TranslatePipe],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ErrorWidgetComponent extends WidgetComponent implements OnChanges {
|
||||
|
||||
+40
-37
@@ -1,42 +1,45 @@
|
||||
<div
|
||||
class="adf-multiline-text-widget {{ field.className }}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
>
|
||||
<mat-form-field
|
||||
floatPlaceholder="never"
|
||||
class="adf-form-field-input"
|
||||
[floatLabel]="field.placeholder ? 'always' : null"
|
||||
class="adf-multiline-text-widget {{ field.className }}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
>
|
||||
<mat-form-field
|
||||
floatPlaceholder="never"
|
||||
class="adf-form-field-input"
|
||||
[floatLabel]="field.placeholder ? 'always' : null"
|
||||
>
|
||||
@if(field.name || field.required) {
|
||||
<mat-label class="adf-label" [attr.for]="field.id"> {{ field.name | translate }} </mat-label>
|
||||
}
|
||||
<textarea
|
||||
matInput
|
||||
class="adf-input"
|
||||
[cdkTextareaAutosize]="true"
|
||||
type="text"
|
||||
rows="3"
|
||||
[id]="field.id"
|
||||
[required]="field.required"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly || readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()"
|
||||
>
|
||||
</textarea>
|
||||
</mat-form-field>
|
||||
<div *ngIf="field.maxLength > 0" class="adf-multiline-word-counter">
|
||||
<span class="adf-multiline-word-counter-value">{{ field?.value?.length || 0 }}/{{ field.maxLength }}</span>
|
||||
@if(field.name || field.required) {
|
||||
<mat-label class="adf-label" [attr.for]="field.id"> {{ field.name | translate }} </mat-label>
|
||||
}
|
||||
<textarea
|
||||
matInput
|
||||
class="adf-input"
|
||||
[cdkTextareaAutosize]="true"
|
||||
type="text"
|
||||
rows="3"
|
||||
[id]="field.id"
|
||||
[required]="field.required"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly || readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()"
|
||||
>
|
||||
</textarea>
|
||||
</mat-form-field>
|
||||
@if (field.maxLength > 0) {
|
||||
<div class="adf-multiline-word-counter">
|
||||
<span class="adf-multiline-word-counter-value">{{ field?.value?.length || 0 }}/{{ field.maxLength }}</span>
|
||||
</div>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
<error-widget
|
||||
*ngIf="isInvalidFieldRequired() && isTouched()"
|
||||
class="adf-multiline-required-message"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
}
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
@if (isInvalidFieldRequired() && isTouched()) {
|
||||
<error-widget
|
||||
class="adf-multiline-required-message"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { Component, DestroyRef, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -44,7 +44,7 @@ import { WidgetComponent } from '../widget.component';
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [MatFormFieldModule, NgIf, TranslatePipe, MatInputModule, FormsModule, ErrorWidgetComponent],
|
||||
imports: [MatFormFieldModule, TranslatePipe, MatInputModule, FormsModule, ErrorWidgetComponent],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class MultilineTextWidgetComponentComponent extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -1,40 +1,43 @@
|
||||
<div class="adf-textfield adf-number-widget {{ field.className }}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
<div *ngIf="field.leftLabels">
|
||||
<label class="adf-label adf-left-label"
|
||||
[attr.for]="field.id">
|
||||
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
@if (field.leftLabels) {
|
||||
<div>
|
||||
<label class="adf-label adf-left-label"
|
||||
[attr.for]="field.id">
|
||||
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="adf-number-widget-container">
|
||||
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
|
||||
@if( (field.name || this.field?.required) && !field.leftLabels) {
|
||||
<mat-label class="adf-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}
|
||||
</mat-label>
|
||||
}
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
pattern="-?[0-9]*(\.[0-9]+)?"
|
||||
[id]="field.id"
|
||||
[required]="field.required"
|
||||
[value]="displayValue"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onNumberChange($event)"
|
||||
[disabled]="field.readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()">
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
<error-widget
|
||||
*ngIf="isInvalidFieldRequired() && isTouched()"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<div class="adf-number-widget-container">
|
||||
<mat-form-field class="adf-form-field-input" [floatLabel]="field.placeholder ? 'always' : null">
|
||||
@if( (field.name || this.field?.required) && !field.leftLabels) {
|
||||
<mat-label class="adf-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}
|
||||
</mat-label>
|
||||
}
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
pattern="-?[0-9]*(\.[0-9]+)?"
|
||||
[id]="field.id"
|
||||
[required]="field.required"
|
||||
[value]="displayValue"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onNumberChange($event)"
|
||||
[disabled]="field.readOnly"
|
||||
[placeholder]="field.placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()">
|
||||
</mat-form-field>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
@if (isInvalidFieldRequired() && isTouched()) {
|
||||
<error-widget
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector, @angular-eslint/no-input-rename */
|
||||
|
||||
import { NgIf } from '@angular/common';
|
||||
|
||||
import { Component, inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
@@ -42,7 +42,7 @@ import { WidgetComponent } from '../widget.component';
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent],
|
||||
imports: [TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent],
|
||||
providers: [DecimalNumberPipe],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
|
||||
@@ -1,39 +1,43 @@
|
||||
<div class="adf-textfield adf-text-widget {{ field.className }}"
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
<div *ngIf="field.leftLabels">
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
[class.adf-invalid]="!field.isValid && isTouched()"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
[class.adf-left-label-input-container]="field.leftLabels">
|
||||
@if (field.leftLabels) {
|
||||
<div>
|
||||
<label class="adf-label adf-left-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}<span class="adf-asterisk" [style.visibility]="isRequired() ? 'visible' : 'hidden'">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="adf-text-widget-container">
|
||||
<mat-form-field class="adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
|
||||
@if ( (field.name || this.field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}
|
||||
</mat-label>
|
||||
}
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[required]="field.required"
|
||||
[value]="field.value"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly || readOnly"
|
||||
[textMask]="{mask: mask, isReversed: isMaskReversed}"
|
||||
[placeholder]="placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()">
|
||||
</mat-form-field>
|
||||
<ng-container *ngTemplateOutlet="fieldStatusTemplate ?? defaultErrorMessageTemplate; context: { $implicit: this }" />
|
||||
<ng-template #defaultErrorMessageTemplate>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()"
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}" />
|
||||
</div>
|
||||
</ng-template>
|
||||
}
|
||||
<div class="adf-text-widget-container">
|
||||
<mat-form-field class="adf-form-field-input" [floatLabel]="placeholder ? 'always' : null">
|
||||
@if ( (field.name || this.field?.required) && !field.leftLabels) { <mat-label class="adf-label" [attr.for]="field.id">
|
||||
{{ field.name | translate }}
|
||||
</mat-label>
|
||||
}
|
||||
<input matInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[required]="field.required"
|
||||
[value]="field.value"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly || readOnly"
|
||||
[textMask]="{mask: mask, isReversed: isMaskReversed}"
|
||||
[placeholder]="placeholder"
|
||||
[title]="field.tooltip"
|
||||
(blur)="markAsTouched()">
|
||||
</mat-form-field>
|
||||
<ng-container *ngTemplateOutlet="fieldStatusTemplate ?? defaultErrorMessageTemplate; context: { $implicit: this }" />
|
||||
<ng-template #defaultErrorMessageTemplate>
|
||||
<div class="adf-error-messages-container">
|
||||
<error-widget [error]="field.validationSummary" />
|
||||
@if (isInvalidFieldRequired() && isTouched()) {
|
||||
<error-widget
|
||||
required="{{ 'FORM.FIELD.REQUIRED' | translate }}" />
|
||||
}
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { NgIf, NgTemplateOutlet } from '@angular/common';
|
||||
import { NgTemplateOutlet } from '@angular/common';
|
||||
import { Component, DestroyRef, Directive, inject, InjectionToken, Input, OnInit, TemplateRef, ViewEncapsulation } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -63,7 +63,7 @@ export class FieldStatusTemplateDirective {
|
||||
'(invalid)': 'event($event)',
|
||||
'(select)': 'event($event)'
|
||||
},
|
||||
imports: [NgIf, TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent, InputMaskDirective, NgTemplateOutlet],
|
||||
imports: [TranslatePipe, MatFormFieldModule, MatInputModule, FormsModule, ErrorWidgetComponent, InputMaskDirective, NgTemplateOutlet],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class TextWidgetComponent extends WidgetComponent implements OnInit {
|
||||
|
||||
@@ -1,43 +1,47 @@
|
||||
<ng-container [ngSwitch]="variant">
|
||||
<ng-container *ngSwitchCase="'minimal'">
|
||||
<adf-toolbar [color]="color">
|
||||
<adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="toolbarTitleContent" />
|
||||
</adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="navbarTemplate" />
|
||||
<div class="adf-toolbar--spacer"></div>
|
||||
<ng-container *ngTemplateOutlet="toolbarActions" />
|
||||
</adf-toolbar>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'extended'">
|
||||
<adf-toolbar [color]="color">
|
||||
<adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="toolbarTitleContent" />
|
||||
</adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="toolbarActions" />
|
||||
</adf-toolbar>
|
||||
<adf-toolbar [color]="color">
|
||||
<ng-container *ngTemplateOutlet="navbarTemplate" />
|
||||
</adf-toolbar>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
@switch (variant) {
|
||||
@case ('minimal') {
|
||||
<adf-toolbar [color]="color">
|
||||
<adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="toolbarTitleContent" />
|
||||
</adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="navbarTemplate" />
|
||||
<div class="adf-toolbar--spacer"></div>
|
||||
<ng-container *ngTemplateOutlet="toolbarActions" />
|
||||
</adf-toolbar>
|
||||
}
|
||||
@case ('extended') {
|
||||
<adf-toolbar [color]="color">
|
||||
<adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="toolbarTitleContent" />
|
||||
</adf-toolbar-title>
|
||||
<ng-container *ngTemplateOutlet="toolbarActions" />
|
||||
</adf-toolbar>
|
||||
<adf-toolbar [color]="color">
|
||||
<ng-container *ngTemplateOutlet="navbarTemplate" />
|
||||
</adf-toolbar>
|
||||
}
|
||||
}
|
||||
|
||||
<ng-template #toolbarTitleContent>
|
||||
<img *ngIf="logoSrc" [src]="logoSrc" [alt]="logoAlt" class="adf-toolbar-logo"/>
|
||||
<span *ngIf="variant==='extended'">{{ title }}</span>
|
||||
@if (logoSrc) {
|
||||
<img [src]="logoSrc" [alt]="logoAlt" class="adf-toolbar-logo"/>
|
||||
}
|
||||
@if (variant==='extended') {
|
||||
<span>{{ title }}</span>
|
||||
}
|
||||
</ng-template>
|
||||
|
||||
<ng-template #toolbarActions>
|
||||
<div class="adf-toolbar-actions">
|
||||
<ng-content select="[adf-toolbar-actions]" />
|
||||
</div>
|
||||
<div class="adf-toolbar-actions">
|
||||
<ng-content select="[adf-toolbar-actions]" />
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #navbarTemplate>
|
||||
<adf-navbar [items]="navbarItems">
|
||||
<ng-content select="adf-navbar-item" />
|
||||
</adf-navbar>
|
||||
<adf-navbar [items]="navbarItems">
|
||||
<ng-content select="adf-navbar-item" />
|
||||
</adf-navbar>
|
||||
</ng-template>
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<button *ngIf="routerLink; else noRouterLink" class="adf-navbar-item-btn"
|
||||
[routerLink]="routerLink"
|
||||
routerLinkActive="adf-navbar-item-active"
|
||||
mat-button>{{ label }}
|
||||
</button>
|
||||
<ng-template #noRouterLink>
|
||||
<button class="adf-navbar-item-btn" mat-button>
|
||||
{{ label }}
|
||||
</button>
|
||||
</ng-template>
|
||||
@if (routerLink) {
|
||||
<button class="adf-navbar-item-btn"
|
||||
[routerLink]="routerLink"
|
||||
routerLinkActive="adf-navbar-item-active"
|
||||
mat-button>{{ label }}
|
||||
</button>
|
||||
} @else {
|
||||
<button class="adf-navbar-item-btn" mat-button>
|
||||
{{ label }}
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
export interface NavbarItem {
|
||||
@@ -30,7 +30,7 @@ export interface NavbarItem {
|
||||
templateUrl: 'navbar-item.component.html',
|
||||
styleUrls: ['./navbar-item.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
imports: [MatButtonModule, CommonModule, RouterModule],
|
||||
imports: [MatButtonModule, RouterModule],
|
||||
host: { class: 'adf-navbar-item' }
|
||||
})
|
||||
export class NavbarItemComponent {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<adf-navbar-item *ngFor="let item of items"
|
||||
[routerLink]="item.routerLink"
|
||||
[label]="item.label" />
|
||||
@for (item of items; track item) {
|
||||
<adf-navbar-item
|
||||
[routerLink]="item.routerLink"
|
||||
[label]="item.label" />
|
||||
}
|
||||
<ng-content />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { NavbarItem, NavbarItemComponent } from './navbar-item.component';
|
||||
|
||||
@Component({
|
||||
@@ -25,7 +25,7 @@ import { NavbarItem, NavbarItemComponent } from './navbar-item.component';
|
||||
templateUrl: './navbar.component.html',
|
||||
styleUrls: ['./navbar.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
imports: [MatToolbarModule, CommonModule, NavbarItemComponent],
|
||||
imports: [MatToolbarModule, NavbarItemComponent],
|
||||
host: { class: 'adf-navbar' }
|
||||
})
|
||||
export class NavbarComponent {
|
||||
|
||||
@@ -1,41 +1,44 @@
|
||||
<div
|
||||
*ngIf="isLoggedIn"
|
||||
@if (isLoggedIn) {
|
||||
<div
|
||||
id="userinfo_container"
|
||||
[class.adf-userinfo-name-right]="showOnRight"
|
||||
(keyup)="onKeyPress($event)"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
class="adf-userinfo-container"
|
||||
>
|
||||
<span *ngIf="showName" id="adf-userinfo-identity-name-display" class="adf-userinfo-name">
|
||||
>
|
||||
@if (showName) {
|
||||
<span id="adf-userinfo-identity-name-display" class="adf-userinfo-name">
|
||||
{{ identityUser | fullName }}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
<button mat-button [matMenuTriggerFor]="menu" class="adf-userinfo-menu_button adf-identity-userinfo-button" data-automation-id="adf-user-profile">
|
||||
<div class="adf-userinfo-button-profile" id="user-profile">
|
||||
<div id="identity-user-image">
|
||||
<div [innerHTML]="identityUser | usernameInitials : 'adf-userinfo-pic'"></div>
|
||||
</div>
|
||||
<div class="adf-userinfo-button-profile" id="user-profile">
|
||||
<div id="identity-user-image">
|
||||
<div [innerHTML]="identityUser | usernameInitials : 'adf-userinfo-pic'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<mat-menu
|
||||
#menu="matMenu"
|
||||
id="user-profile-lists"
|
||||
[xPosition]="menuPositionX"
|
||||
[yPosition]="menuPositionY"
|
||||
[overlapTrigger]="false"
|
||||
class="adf-userinfo-menu adf-identity-userinfo-menu"
|
||||
>
|
||||
<mat-card class="adf-userinfo-card adf-identity-userinfo-card">
|
||||
<mat-card-header class="adf-userinfo-card-header" [style.background-image]="'url(' + bpmBackgroundImage + ')'">
|
||||
<div class="mat-headline-6" id="identity-username">{{ identityUser | fullName }}</div>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="adf-userinfo-supporting-text">
|
||||
<h2 id="identity-full-name" class="adf-userinfo__detail-title">{{ identityUser | fullName }}</h2>
|
||||
<span id="identity-email"> {{ identityUser.email }} </span>
|
||||
<a href="#/profile"> {{ 'USER_PROFILE.LABELS.MY_PROFILE' | translate }}</a>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
#menu="matMenu"
|
||||
id="user-profile-lists"
|
||||
[xPosition]="menuPositionX"
|
||||
[yPosition]="menuPositionY"
|
||||
[overlapTrigger]="false"
|
||||
class="adf-userinfo-menu adf-identity-userinfo-menu"
|
||||
>
|
||||
<mat-card class="adf-userinfo-card adf-identity-userinfo-card">
|
||||
<mat-card-header class="adf-userinfo-card-header" [style.background-image]="'url(' + bpmBackgroundImage + ')'">
|
||||
<div class="mat-headline-6" id="identity-username">{{ identityUser | fullName }}</div>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="adf-userinfo-supporting-text">
|
||||
<h2 id="identity-full-name" class="adf-userinfo__detail-title">{{ identityUser | fullName }}</h2>
|
||||
<span id="identity-email"> {{ identityUser.email }} </span>
|
||||
<a href="#/profile"> {{ 'USER_PROFILE.LABELS.MY_PROFILE' | translate }}</a>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import { Component, Input, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { MatMenuModule, MatMenuTrigger, MenuPositionX, MenuPositionY } from '@angular/material/menu';
|
||||
import { IdentityUserModel } from '../auth/models/identity-user.model';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { FullNamePipe, InitialUsernamePipe } from '../pipes';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
@@ -26,7 +26,7 @@ import { TranslatePipe } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-identity-user-info',
|
||||
imports: [CommonModule, FullNamePipe, MatMenuModule, InitialUsernamePipe, MatButtonModule, MatCardModule, TranslatePipe],
|
||||
imports: [FullNamePipe, MatMenuModule, InitialUsernamePipe, MatButtonModule, MatCardModule, TranslatePipe],
|
||||
templateUrl: './identity-user-info.component.html',
|
||||
styleUrls: ['./identity-user-info.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<div *ngIf="showHeader" class="adf-info-drawer-layout-header">
|
||||
@if (showHeader) {
|
||||
<div class="adf-info-drawer-layout-header">
|
||||
<div class="adf-info-drawer-layout-header-title">
|
||||
<ng-content select="[info-drawer-node-icon]" />
|
||||
<ng-content select="[info-drawer-title]" />
|
||||
<ng-content select="[info-drawer-node-icon]" />
|
||||
<ng-content select="[info-drawer-title]" />
|
||||
</div>
|
||||
<div class="adf-info-drawer-layout-header-buttons">
|
||||
<ng-content select="[info-drawer-buttons]" />
|
||||
<ng-content select="[info-drawer-buttons]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="adf-info-drawer-layout-content">
|
||||
<ng-content select="[info-drawer-content]" />
|
||||
<ng-content select="[info-drawer-content]" />
|
||||
</div>
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
*/
|
||||
|
||||
import { Component, Directive, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'adf-info-drawer-layout',
|
||||
imports: [CommonModule],
|
||||
imports: [],
|
||||
templateUrl: './info-drawer-layout.component.html',
|
||||
styleUrls: ['./info-drawer-layout.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -1,33 +1,41 @@
|
||||
<adf-info-drawer-layout [showHeader]="showHeader">
|
||||
<img *ngIf="icon" class="adf-info-drawer-icon" alt="{{ 'INFO_DRAWER.ICON' | translate }}" src="{{ icon }}" info-drawer-node-icon aria-hidden="true">
|
||||
<div *ngIf="title" role="heading" aria-level="1" title="{{ title | translate }}" info-drawer-title>{{ title | translate }}</div>
|
||||
@if (icon) {
|
||||
<img class="adf-info-drawer-icon" alt="{{ 'INFO_DRAWER.ICON' | translate }}" src="{{ icon }}" info-drawer-node-icon aria-hidden="true">
|
||||
}
|
||||
@if (title) {
|
||||
<div role="heading" aria-level="1" title="{{ title | translate }}" info-drawer-title>{{ title | translate }}</div>
|
||||
}
|
||||
|
||||
<ng-content *ngIf="!title" info-drawer-title select="[info-drawer-title]" />
|
||||
<ng-content info-drawer-buttons select="[info-drawer-buttons]" />
|
||||
<ng-container info-drawer-content *ngIf="showTabLayout(); then tabLayout else singleLayout" />
|
||||
|
||||
<ng-template #tabLayout>
|
||||
<mat-tab-group [(selectedIndex)]="selectedIndex" class="adf-info-drawer-tabs" (selectedTabChange)="onTabChange($event)" [animationDuration]="0">
|
||||
<mat-tab *ngFor="let contentBlock of contentBlocks"
|
||||
#tab
|
||||
@if (!title) {
|
||||
<ng-content info-drawer-title select="[info-drawer-title]" />
|
||||
}
|
||||
<ng-content info-drawer-buttons select="[info-drawer-buttons]" />
|
||||
@if (showTabLayout()) {
|
||||
<mat-tab-group [(selectedIndex)]="selectedIndex" class="adf-info-drawer-tabs" (selectedTabChange)="onTabChange($event)" [animationDuration]="0">
|
||||
@for (contentBlock of contentBlocks; track contentBlock) {
|
||||
<mat-tab
|
||||
#tab
|
||||
[labelClass]="[
|
||||
'adf-info-drawer-tab',
|
||||
tab.isActive ? 'adf-info-drawer-tab--active' : '',
|
||||
]"
|
||||
[label]="contentBlock.label | translate"
|
||||
class="adf-info-drawer-tab">
|
||||
[label]="contentBlock.label | translate"
|
||||
class="adf-info-drawer-tab">
|
||||
<ng-template mat-tab-label>
|
||||
@if (contentBlock.icon) {
|
||||
<mat-icon [adf-icon]="contentBlock.icon" />
|
||||
}
|
||||
@if (contentBlock.label) {
|
||||
<span>{{ contentBlock.label | translate }}</span>
|
||||
}
|
||||
</ng-template>
|
||||
<ng-container *ngTemplateOutlet="contentBlock.content" />
|
||||
</mat-tab>
|
||||
}
|
||||
</mat-tab-group>
|
||||
} @else {
|
||||
<ng-content select="[info-drawer-content]" />
|
||||
}
|
||||
|
||||
<ng-template mat-tab-label>
|
||||
<mat-icon *ngIf="contentBlock.icon" [adf-icon]="contentBlock.icon" />
|
||||
<span *ngIf="contentBlock.label">{{ contentBlock.label | translate }}</span>
|
||||
</ng-template>
|
||||
|
||||
<ng-container *ngTemplateOutlet="contentBlock.content" />
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #singleLayout>
|
||||
<ng-content select="[info-drawer-content]" />
|
||||
</ng-template>
|
||||
</adf-info-drawer-layout>
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { MatTabChangeEvent, MatTabsModule } from '@angular/material/tabs';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
InfoDrawerButtonsDirective,
|
||||
InfoDrawerContentDirective,
|
||||
@@ -59,16 +59,15 @@ export class InfoDrawerTabComponent {
|
||||
@Component({
|
||||
selector: 'adf-info-drawer',
|
||||
imports: [
|
||||
CommonModule,
|
||||
InfoDrawerLayoutComponent,
|
||||
TranslatePipe,
|
||||
MatTabsModule,
|
||||
IconModule,
|
||||
InfoDrawerButtonsDirective,
|
||||
InfoDrawerTitleDirective,
|
||||
InfoDrawerContentDirective,
|
||||
InfoDrawerTabComponent
|
||||
],
|
||||
InfoDrawerLayoutComponent,
|
||||
TranslatePipe,
|
||||
MatTabsModule,
|
||||
IconModule,
|
||||
InfoDrawerButtonsDirective,
|
||||
InfoDrawerTitleDirective,
|
||||
InfoDrawerContentDirective,
|
||||
InfoDrawerTabComponent
|
||||
],
|
||||
templateUrl: './info-drawer.component.html',
|
||||
styleUrls: ['./info-drawer.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -26,10 +26,12 @@ import { MatMenuItem, MatMenuModule } from '@angular/material/menu';
|
||||
selector: 'adf-language-menu',
|
||||
imports: [CommonModule, MatMenuModule],
|
||||
template: `
|
||||
<button mat-menu-item *ngFor="let language of languages$ | async" [attr.lang]="language.key" (click)="changeLanguage(language)">
|
||||
@for (language of languages$ | async; track language) {
|
||||
<button mat-menu-item [attr.lang]="language.key" (click)="changeLanguage(language)">
|
||||
{{ language.label }}
|
||||
</button>
|
||||
`
|
||||
</button>
|
||||
}
|
||||
`
|
||||
})
|
||||
export class LanguageMenuComponent {
|
||||
private readonly languageService = inject(LanguageService);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { AfterViewInit, Component, EventEmitter, Output, QueryList, ViewChild } from '@angular/core';
|
||||
import { LanguageItem } from '../common/services/language-item.interface';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatMenu, MatMenuItem, MatMenuModule } from '@angular/material/menu';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { LanguageMenuComponent } from './language-menu.component';
|
||||
@@ -25,7 +25,7 @@ import { IconModule } from '../icon/icon.module';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-picker-button',
|
||||
imports: [CommonModule, MatMenuModule, TranslatePipe, LanguageMenuComponent, IconModule],
|
||||
imports: [MatMenuModule, TranslatePipe, LanguageMenuComponent, IconModule],
|
||||
template: `
|
||||
<button mat-menu-item [matMenuTriggerFor]="langMenu">
|
||||
<mat-icon adf-icon="language" />
|
||||
|
||||
@@ -1,48 +1,52 @@
|
||||
<mat-toolbar
|
||||
class="adf-toolbar-container-row"
|
||||
[color]="color"
|
||||
[style.background-color]="color"
|
||||
[style.background-image]="backgroundImage ? 'url(' + backgroundImage + ')' : 'none'">
|
||||
class="adf-toolbar-container-row"
|
||||
[color]="color"
|
||||
[style.background-color]="color"
|
||||
[style.background-image]="backgroundImage ? 'url(' + backgroundImage + ')' : 'none'">
|
||||
@if (showSidenavToggle && position === 'start') {
|
||||
<button
|
||||
*ngIf="showSidenavToggle && position === 'start'"
|
||||
id="adf-sidebar-toggle-start"
|
||||
data-automation-id="adf-menu-icon"
|
||||
class="adf-menu-icon adf-header-icon-button"
|
||||
mat-icon-button
|
||||
(click)="toggleMenu()"
|
||||
[attr.aria-expanded]="expandedSidenav"
|
||||
[attr.aria-label]="'CORE.HEADER.ACCESSIBILITY.SIDEBAR_TOGGLE_BUTTON_ARIA_LABEL' | translate">
|
||||
<mat-icon class="adf-menu-icon-header" role="img" aria-hidden="true" [adf-icon]="toggleIcon" />
|
||||
id="adf-sidebar-toggle-start"
|
||||
data-automation-id="adf-menu-icon"
|
||||
class="adf-menu-icon adf-header-icon-button"
|
||||
mat-icon-button
|
||||
(click)="toggleMenu()"
|
||||
[attr.aria-expanded]="expandedSidenav"
|
||||
[attr.aria-label]="'CORE.HEADER.ACCESSIBILITY.SIDEBAR_TOGGLE_BUTTON_ARIA_LABEL' | translate">
|
||||
<mat-icon class="adf-menu-icon-header" role="img" aria-hidden="true" [adf-icon]="toggleIcon" />
|
||||
</button>
|
||||
}
|
||||
|
||||
<a *ngIf="showLogo" [routerLink]="redirectUrl" title="{{ tooltip }}">
|
||||
<img
|
||||
src="{{ logo }}"
|
||||
class="adf-app-logo"
|
||||
alt="{{ 'CORE.HEADER.LOGO_ARIA' | translate }}"
|
||||
@if (showLogo) {
|
||||
<a [routerLink]="redirectUrl" title="{{ tooltip }}">
|
||||
<img
|
||||
src="{{ logo }}"
|
||||
class="adf-app-logo"
|
||||
alt="{{ 'CORE.HEADER.LOGO_ARIA' | translate }}"
|
||||
/>
|
||||
</a>
|
||||
}
|
||||
|
||||
<h1
|
||||
role="link"
|
||||
[attr.aria-label]="title | translate"
|
||||
[routerLink]="redirectUrl"
|
||||
class="adf-app-title"
|
||||
>
|
||||
{{ title }}
|
||||
</h1>
|
||||
<h1
|
||||
role="link"
|
||||
[attr.aria-label]="title | translate"
|
||||
[routerLink]="redirectUrl"
|
||||
class="adf-app-title"
|
||||
>
|
||||
{{ title }}
|
||||
</h1>
|
||||
|
||||
<ng-content />
|
||||
<ng-content />
|
||||
|
||||
@if (showSidenavToggle && position === 'end') {
|
||||
<button
|
||||
*ngIf="showSidenavToggle && position === 'end'"
|
||||
id="adf-sidebar-toggle-end"
|
||||
data-automation-id="adf-menu-icon"
|
||||
class="adf-menu-icon adf-header-icon-button"
|
||||
mat-icon-button
|
||||
(click)="toggleMenu()"
|
||||
[attr.aria-expanded]="expandedSidenav"
|
||||
[attr.aria-label]="'CORE.HEADER.ACCESSIBILITY.SIDEBAR_TOGGLE_BUTTON_ARIA_LABEL' | translate">
|
||||
<mat-icon class="adf-menu-icon-header" role="img" aria-hidden="true" [adf-icon]="toggleIcon" />
|
||||
id="adf-sidebar-toggle-end"
|
||||
data-automation-id="adf-menu-icon"
|
||||
class="adf-menu-icon adf-header-icon-button"
|
||||
mat-icon-button
|
||||
(click)="toggleMenu()"
|
||||
[attr.aria-expanded]="expandedSidenav"
|
||||
[attr.aria-label]="'CORE.HEADER.ACCESSIBILITY.SIDEBAR_TOGGLE_BUTTON_ARIA_LABEL' | translate">
|
||||
<mat-icon class="adf-menu-icon-header" role="img" aria-hidden="true" [adf-icon]="toggleIcon" />
|
||||
</button>
|
||||
}
|
||||
</mat-toolbar>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import { Component, Input, Output, EventEmitter, ViewEncapsulation, OnInit, inject } from '@angular/core';
|
||||
import { ThemePalette } from '@angular/material/core';
|
||||
import { AppConfigService } from '../../../app-config/app-config.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
@@ -27,7 +27,7 @@ import { IconModule } from '../../../icon/icon.module';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-layout-header',
|
||||
imports: [CommonModule, MatToolbarModule, MatButtonModule, IconModule, RouterModule, TranslatePipe],
|
||||
imports: [MatToolbarModule, MatButtonModule, IconModule, RouterModule, TranslatePipe],
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
import { Component, Input, ViewChild, OnInit, OnDestroy, ViewEncapsulation, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { MatSidenav, MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { Direction } from '@angular/cdk/bidi';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-layout-container',
|
||||
imports: [CommonModule, MatSidenavModule],
|
||||
imports: [MatSidenavModule],
|
||||
templateUrl: './layout-container.component.html',
|
||||
styleUrls: ['./layout-container.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
+16
-10
@@ -1,16 +1,22 @@
|
||||
<div class="adf-sidebar-action-menu">
|
||||
<button *ngIf="isExpanded()" mat-raised-button class="adf-sidebar-action-menu-button" data-automation-id="create-button" [matMenuTriggerFor]="adfSidebarMenu">
|
||||
<span *ngIf="title" class="adf-sidebar-action-menu-text">{{ title }}</span>
|
||||
<ng-content select="[adf-sidebar-menu-title-icon], [sidebar-menu-title-icon]" />
|
||||
@if (isExpanded()) {
|
||||
<button mat-raised-button class="adf-sidebar-action-menu-button" data-automation-id="create-button" [matMenuTriggerFor]="adfSidebarMenu">
|
||||
@if (title) {
|
||||
<span class="adf-sidebar-action-menu-text">{{ title }}</span>
|
||||
}
|
||||
<ng-content select="[adf-sidebar-menu-title-icon], [sidebar-menu-title-icon]" />
|
||||
</button>
|
||||
}
|
||||
|
||||
<div *ngIf="!isExpanded()" class="adf-sidebar-action-menu-icon" [matMenuTriggerFor]="adfSidebarMenu">
|
||||
<ng-content select="[adf-sidebar-menu-expand-icon], [sidebar-menu-expand-icon]" />
|
||||
@if (!isExpanded()) {
|
||||
<div class="adf-sidebar-action-menu-icon" [matMenuTriggerFor]="adfSidebarMenu">
|
||||
<ng-content select="[adf-sidebar-menu-expand-icon], [sidebar-menu-expand-icon]" />
|
||||
</div>
|
||||
}
|
||||
|
||||
<mat-menu #adfSidebarMenu="matMenu" class="adf-sidebar-action-menu-panel" [overlapTrigger]="false" yPosition="below">
|
||||
<div class="adf-sidebar-action-menu-options" [style.width.px]="width">
|
||||
<ng-content select="[adf-sidebar-menu-options], [sidebar-menu-options]" />
|
||||
</div>
|
||||
</mat-menu>
|
||||
<mat-menu #adfSidebarMenu="matMenu" class="adf-sidebar-action-menu-panel" [overlapTrigger]="false" yPosition="below">
|
||||
<div class="adf-sidebar-action-menu-options" [style.width.px]="width">
|
||||
<ng-content select="[adf-sidebar-menu-options], [sidebar-menu-options]" />
|
||||
</div>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { SidebarActionMenuComponent } from './sidebar-action-menu.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { UnitTestingUtils } from '../../../testing/unit-testing-utils';
|
||||
import { IconModule } from '../../../icon/icon.module';
|
||||
@@ -52,7 +52,7 @@ describe('SidebarActionMenuComponent', () => {
|
||||
});
|
||||
|
||||
@Component({
|
||||
imports: [CommonModule, SidebarActionMenuComponent, IconModule, MatMenuModule],
|
||||
imports: [SidebarActionMenuComponent, IconModule, MatMenuModule],
|
||||
// eslint-disable-next-line @alfresco/eslint-angular/no-angular-material-selectors
|
||||
template: `
|
||||
<adf-sidebar-action-menu [expanded]="expanded" [title]="title">
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Directive, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-sidebar-action-menu',
|
||||
imports: [CommonModule, MatButtonModule, MatMenuModule],
|
||||
imports: [MatButtonModule, MatMenuModule],
|
||||
templateUrl: './sidebar-action-menu.component.html',
|
||||
styleUrls: ['./sidebar-action-menu.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
<div class="adf-sidenav-layout-full-space">
|
||||
<ng-container *ngIf="!isHeaderInside">
|
||||
<ng-container class="adf-sidenav-layout-outer-header"
|
||||
*ngTemplateOutlet="headerTemplate; context:templateContext" />
|
||||
@if (!isHeaderInside) {
|
||||
<ng-container class="adf-sidenav-layout-outer-header"
|
||||
*ngTemplateOutlet="headerTemplate; context:templateContext" />
|
||||
}
|
||||
|
||||
<adf-layout-container #container
|
||||
[direction]="dir"
|
||||
[position]="position"
|
||||
[sidenavMin]="sidenavMin"
|
||||
[sidenavMax]="sidenavMax"
|
||||
[mediaQueryList]="mediaQueryList"
|
||||
[hideSidenav]="hideSidenav"
|
||||
[expandedSidenav]="expandedSidenav"
|
||||
data-automation-id="adf-layout-container"
|
||||
class="adf-layout__content">
|
||||
|
||||
<ng-container app-layout-navigation
|
||||
*ngTemplateOutlet="navigationTemplate; context:templateContext" />
|
||||
|
||||
<ng-container app-layout-content>
|
||||
@if (isHeaderInside) {
|
||||
<ng-container *ngTemplateOutlet="headerTemplate; context:templateContext" />
|
||||
}
|
||||
<ng-container *ngTemplateOutlet="contentTemplate; context:templateContext" />
|
||||
</ng-container>
|
||||
</adf-layout-container>
|
||||
|
||||
<adf-layout-container #container
|
||||
[direction]="dir"
|
||||
[position]="position"
|
||||
[sidenavMin]="sidenavMin"
|
||||
[sidenavMax]="sidenavMax"
|
||||
[mediaQueryList]="mediaQueryList"
|
||||
[hideSidenav]="hideSidenav"
|
||||
[expandedSidenav]="expandedSidenav"
|
||||
data-automation-id="adf-layout-container"
|
||||
class="adf-layout__content">
|
||||
|
||||
<ng-container app-layout-navigation
|
||||
*ngTemplateOutlet="navigationTemplate; context:templateContext" />
|
||||
|
||||
<ng-container app-layout-content>
|
||||
<ng-container *ngIf="isHeaderInside">
|
||||
<ng-container *ngTemplateOutlet="headerTemplate; context:templateContext" />
|
||||
</ng-container>
|
||||
<ng-container *ngTemplateOutlet="contentTemplate; context:templateContext" />
|
||||
</ng-container>
|
||||
</adf-layout-container>
|
||||
|
||||
<ng-template #emptyTemplate />
|
||||
<ng-template #emptyTemplate />
|
||||
</div>
|
||||
|
||||
@@ -1,200 +1,225 @@
|
||||
<div class="adf-login-content" [style.background-image]="'url(' + backgroundImageUrl + ')'">
|
||||
<div class="adf-ie11FixerParent">
|
||||
<div class="adf-ie11FixerChild">
|
||||
<div class="adf-ie11FixerParent">
|
||||
<div class="adf-ie11FixerChild">
|
||||
|
||||
<mat-card class="adf-login-card-wide">
|
||||
<form id="adf-login-form"
|
||||
[formGroup]="form"
|
||||
autocomplete="off"
|
||||
(submit)="onSubmit(form.value)">
|
||||
<mat-card-header class="adf-login-card-header-text">
|
||||
<mat-card-title>
|
||||
<div class="adf-alfresco-logo">
|
||||
<!--HEADER TEMPLATE-->
|
||||
<ng-template *ngIf="headerTemplate"
|
||||
ngFor
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="headerTemplate" />
|
||||
<img *ngIf="!headerTemplate"
|
||||
id="adf-login-img-logo"
|
||||
class="adf-img-logo"
|
||||
[src]="logoImageUrl"
|
||||
alt="{{ 'LOGIN.LOGO' | translate }}">
|
||||
</div>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card class="adf-login-card-wide">
|
||||
<form id="adf-login-form"
|
||||
[formGroup]="form"
|
||||
autocomplete="off"
|
||||
(submit)="onSubmit(form.value)">
|
||||
<mat-card-header class="adf-login-card-header-text">
|
||||
<mat-card-title>
|
||||
<div class="adf-alfresco-logo">
|
||||
<!--HEADER TEMPLATE-->
|
||||
@if (headerTemplate) {
|
||||
@for ( of [data]; track ) {
|
||||
<ng-template
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="headerTemplate" />
|
||||
}
|
||||
}
|
||||
@if (!headerTemplate) {
|
||||
<img
|
||||
id="adf-login-img-logo"
|
||||
class="adf-img-logo"
|
||||
[src]="logoImageUrl"
|
||||
alt="{{ 'LOGIN.LOGO' | translate }}">
|
||||
}
|
||||
</div>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content class="adf-login-controls">
|
||||
<mat-card-content class="adf-login-controls">
|
||||
|
||||
<!--ERRORS AREA-->
|
||||
<div class="adf-error-container">
|
||||
<div *ngIf="isError"
|
||||
id="login-error"
|
||||
data-automation-id="login-error"
|
||||
class="adf-error adf-error-message">
|
||||
<mat-icon class="adf-error-icon" adf-icon="warning" />
|
||||
<span class="adf-login-error-message">
|
||||
{{ errorMsg | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!ssoLogin">
|
||||
|
||||
<!--USERNAME FIELD-->
|
||||
<div class="adf-login__field adf-login-container"
|
||||
[ngClass]="{'adf-is-invalid': isErrorStyle(form.controls.username)}">
|
||||
<mat-form-field class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<mat-label class="adf-login-form-input-label">
|
||||
{{'LOGIN.LABEL.USERNAME' | translate }}
|
||||
</mat-label>
|
||||
<input matInput
|
||||
type="text"
|
||||
class="adf-login-input"
|
||||
formControlName="username"
|
||||
id="username"
|
||||
data-automation-id="username"
|
||||
autocapitalize="none"
|
||||
(blur)="trimUsername($event)">
|
||||
</mat-form-field>
|
||||
<span *ngIf="formError['username']"
|
||||
class="adf-login-validation"
|
||||
for="username">
|
||||
<span id="username-error"
|
||||
class="adf-login-error"
|
||||
data-automation-id="username-error">
|
||||
{{ formError['username'] | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--PASSWORD FIELD-->
|
||||
<div class="adf-login__field">
|
||||
<mat-form-field class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<mat-label class="adf-login-form-input-label">
|
||||
{{'LOGIN.LABEL.PASSWORD' | translate }}
|
||||
</mat-label>
|
||||
<input matInput
|
||||
[type]="isPasswordShow ? 'text' : 'password'"
|
||||
formControlName="password"
|
||||
class="adf-login-input"
|
||||
id="password"
|
||||
data-automation-id="password">
|
||||
<button matSuffix
|
||||
mat-icon-button
|
||||
type="button"
|
||||
[attr.aria-label]="(isPasswordShow ? 'LOGIN.ARIA-LABEL.HIDE-PASSWORD' : 'LOGIN.ARIA-LABEL.SHOW-PASSWORD') | translate"
|
||||
(click)="toggleShowPassword($event)"
|
||||
(keyup.enter)="toggleShowPassword($event)"
|
||||
[attr.data-automation-id]="isPasswordShow ? 'hide_password' : 'show_password'">
|
||||
<mat-icon class="adf-login-form-password-icon adf-login-password-icon" [adf-icon]="isPasswordShow ? 'visibility' : 'visibility_off'" />
|
||||
</button>
|
||||
</mat-form-field>
|
||||
<span class="adf-login-validation"
|
||||
for="password"
|
||||
*ngIf="formError['password']">
|
||||
<span id="password-required"
|
||||
class="adf-login-error"
|
||||
data-automation-id="password-required">
|
||||
{{ formError['password'] | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--CUSTOM CONTENT-->
|
||||
<ng-content />
|
||||
|
||||
<br>
|
||||
<button type="submit"
|
||||
id="login-button"
|
||||
class="adf-login-button"
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[class.adf-isChecking]="actualLoginStep === LoginSteps.Checking"
|
||||
[class.adf-isWelcome]="actualLoginStep === LoginSteps.Welcome"
|
||||
data-automation-id="login-button"
|
||||
[disabled]="!form.valid"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.LOGIN' | translate">
|
||||
<span *ngIf="actualLoginStep === LoginSteps.Landing"
|
||||
class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.LOGIN' | translate }}
|
||||
</span>
|
||||
<div *ngIf="actualLoginStep === LoginSteps.Checking"
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.CHECKING' | translate }}
|
||||
</span>
|
||||
<div class="adf-login-spinner-container">
|
||||
<mat-spinner id="checking-spinner"
|
||||
class="adf-login-checking-spinner"
|
||||
[strokeWidth]="4"
|
||||
[diameter]="25" />
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="actualLoginStep === LoginSteps.Welcome"
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.WELCOME' | translate }}
|
||||
</span>
|
||||
<mat-icon class="adf-welcome-icon" adf-icon="done" />
|
||||
</div>
|
||||
</button>
|
||||
<div *ngIf="showRememberMe" class="adf-login__remember-me">
|
||||
<mat-checkbox id="adf-login-remember"
|
||||
color="primary"
|
||||
class="adf-login-remember-me"
|
||||
[checked]="rememberMe"
|
||||
(change)="rememberMe = !rememberMe">
|
||||
<div class="adf-login-remember-me-label">
|
||||
{{ 'LOGIN.LABEL.REMEMBER' | translate }}
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="ssoLogin">
|
||||
<button type="button"
|
||||
(click)="implicitLogin()"
|
||||
id="login-button-sso"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.SSO' | translate"
|
||||
class="adf-login-button"
|
||||
mat-raised-button color="primary"
|
||||
data-automation-id="login-button-sso">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.SSO' | translate }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions *ngIf="footerTemplate || showLoginActions">
|
||||
|
||||
<div class="adf-login-action-container">
|
||||
<!--FOOTER TEMPLATE-->
|
||||
<ng-template *ngIf="footerTemplate"
|
||||
ngFor
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="footerTemplate" />
|
||||
<div class="adf-login-action" *ngIf="!footerTemplate && showLoginActions">
|
||||
<div id="adf-login-action-left" class="adf-login-action-left">
|
||||
<a href="{{ needHelpLink }}">{{ 'LOGIN.ACTION.HELP' | translate }}</a>
|
||||
</div>
|
||||
<div id="adf-login-action-right" class="adf-login-action-right">
|
||||
<a href="{{ registerLink }}">{{ 'LOGIN.ACTION.REGISTER' | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
|
||||
<div class="adf-copyright" data-automation-id="login-copyright">
|
||||
{{ copyrightText }}
|
||||
<!--ERRORS AREA-->
|
||||
<div class="adf-error-container">
|
||||
@if (isError) {
|
||||
<div
|
||||
id="login-error"
|
||||
data-automation-id="login-error"
|
||||
class="adf-error adf-error-message">
|
||||
<mat-icon class="adf-error-icon" adf-icon="warning" />
|
||||
<span class="adf-login-error-message">
|
||||
{{ errorMsg | translate }}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (!ssoLogin) {
|
||||
<div>
|
||||
<!--USERNAME FIELD-->
|
||||
<div class="adf-login__field adf-login-container"
|
||||
[ngClass]="{'adf-is-invalid': isErrorStyle(form.controls.username)}">
|
||||
<mat-form-field class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<mat-label class="adf-login-form-input-label">
|
||||
{{'LOGIN.LABEL.USERNAME' | translate }}
|
||||
</mat-label>
|
||||
<input matInput
|
||||
type="text"
|
||||
class="adf-login-input"
|
||||
formControlName="username"
|
||||
id="username"
|
||||
data-automation-id="username"
|
||||
autocapitalize="none"
|
||||
(blur)="trimUsername($event)">
|
||||
</mat-form-field>
|
||||
@if (formError['username']) {
|
||||
<span
|
||||
class="adf-login-validation"
|
||||
for="username">
|
||||
<span id="username-error"
|
||||
class="adf-login-error"
|
||||
data-automation-id="username-error">
|
||||
{{ formError['username'] | translate }}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<!--PASSWORD FIELD-->
|
||||
<div class="adf-login__field">
|
||||
<mat-form-field class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<mat-label class="adf-login-form-input-label">
|
||||
{{'LOGIN.LABEL.PASSWORD' | translate }}
|
||||
</mat-label>
|
||||
<input matInput
|
||||
[type]="isPasswordShow ? 'text' : 'password'"
|
||||
formControlName="password"
|
||||
class="adf-login-input"
|
||||
id="password"
|
||||
data-automation-id="password">
|
||||
<button matSuffix
|
||||
mat-icon-button
|
||||
type="button"
|
||||
[attr.aria-label]="(isPasswordShow ? 'LOGIN.ARIA-LABEL.HIDE-PASSWORD' : 'LOGIN.ARIA-LABEL.SHOW-PASSWORD') | translate"
|
||||
(click)="toggleShowPassword($event)"
|
||||
(keyup.enter)="toggleShowPassword($event)"
|
||||
[attr.data-automation-id]="isPasswordShow ? 'hide_password' : 'show_password'">
|
||||
<mat-icon class="adf-login-form-password-icon adf-login-password-icon" [adf-icon]="isPasswordShow ? 'visibility' : 'visibility_off'" />
|
||||
</button>
|
||||
</mat-form-field>
|
||||
@if (formError['password']) {
|
||||
<span class="adf-login-validation"
|
||||
for="password"
|
||||
>
|
||||
<span id="password-required"
|
||||
class="adf-login-error"
|
||||
data-automation-id="password-required">
|
||||
{{ formError['password'] | translate }}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<!--CUSTOM CONTENT-->
|
||||
<ng-content />
|
||||
<br>
|
||||
<button type="submit"
|
||||
id="login-button"
|
||||
class="adf-login-button"
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[class.adf-isChecking]="actualLoginStep === LoginSteps.Checking"
|
||||
[class.adf-isWelcome]="actualLoginStep === LoginSteps.Welcome"
|
||||
data-automation-id="login-button"
|
||||
[disabled]="!form.valid"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.LOGIN' | translate">
|
||||
@if (actualLoginStep === LoginSteps.Landing) {
|
||||
<span
|
||||
class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.LOGIN' | translate }}
|
||||
</span>
|
||||
}
|
||||
@if (actualLoginStep === LoginSteps.Checking) {
|
||||
<div
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.CHECKING' | translate }}
|
||||
</span>
|
||||
<div class="adf-login-spinner-container">
|
||||
<mat-spinner id="checking-spinner"
|
||||
class="adf-login-checking-spinner"
|
||||
[strokeWidth]="4"
|
||||
[diameter]="25" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (actualLoginStep === LoginSteps.Welcome) {
|
||||
<div
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.WELCOME' | translate }}
|
||||
</span>
|
||||
<mat-icon class="adf-welcome-icon" adf-icon="done" />
|
||||
</div>
|
||||
}
|
||||
</button>
|
||||
@if (showRememberMe) {
|
||||
<div class="adf-login__remember-me">
|
||||
<mat-checkbox id="adf-login-remember"
|
||||
color="primary"
|
||||
class="adf-login-remember-me"
|
||||
[checked]="rememberMe"
|
||||
(change)="rememberMe = !rememberMe">
|
||||
<div class="adf-login-remember-me-label">
|
||||
{{ 'LOGIN.LABEL.REMEMBER' | translate }}
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (ssoLogin) {
|
||||
<div>
|
||||
<button type="button"
|
||||
(click)="implicitLogin()"
|
||||
id="login-button-sso"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.SSO' | translate"
|
||||
class="adf-login-button"
|
||||
mat-raised-button color="primary"
|
||||
data-automation-id="login-button-sso">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.SSO' | translate }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
|
||||
@if (footerTemplate || showLoginActions) {
|
||||
<mat-card-actions>
|
||||
<div class="adf-login-action-container">
|
||||
<!--FOOTER TEMPLATE-->
|
||||
@if (footerTemplate) {
|
||||
@for ( of [data]; track ) {
|
||||
<ng-template
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="footerTemplate" />
|
||||
}
|
||||
}
|
||||
@if (!footerTemplate && showLoginActions) {
|
||||
<div class="adf-login-action">
|
||||
<div id="adf-login-action-left" class="adf-login-action-left">
|
||||
<a href="{{ needHelpLink }}">{{ 'LOGIN.ACTION.HELP' | translate }}</a>
|
||||
</div>
|
||||
<div id="adf-login-action-right" class="adf-login-action-right">
|
||||
<a href="{{ registerLink }}">{{ 'LOGIN.ACTION.REGISTER' | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
}
|
||||
</form>
|
||||
</mat-card>
|
||||
|
||||
<div class="adf-copyright" data-automation-id="login-copyright">
|
||||
{{ copyrightText }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,81 +1,85 @@
|
||||
<button
|
||||
mat-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-hidden="false"
|
||||
[attr.aria-label]="('NOTIFICATIONS.' + (notifications.length ? 'UNREAD_MESSAGES' : 'NO_MESSAGE') | translate) + ' ' + ('NOTIFICATIONS.OPEN_HISTORY' | translate)"
|
||||
title="{{ 'NOTIFICATIONS.OPEN_HISTORY' | translate }}"
|
||||
class="adf-notification-history-menu_button"
|
||||
id="adf-notification-history-open-button"
|
||||
(menuOpened)="onMenuOpened()"
|
||||
>
|
||||
<mat-icon aria-hidden="false" matBadge="⁠" [matBadgeHidden]="!notifications.length" class="adf-notification-history-menu_button-icon" matBadgeColor="accent" matBadgeSize="small" adf-icon="notifications" />
|
||||
mat-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
aria-hidden="false"
|
||||
[attr.aria-label]="('NOTIFICATIONS.' + (notifications.length ? 'UNREAD_MESSAGES' : 'NO_MESSAGE') | translate) + ' ' + ('NOTIFICATIONS.OPEN_HISTORY' | translate)"
|
||||
title="{{ 'NOTIFICATIONS.OPEN_HISTORY' | translate }}"
|
||||
class="adf-notification-history-menu_button"
|
||||
id="adf-notification-history-open-button"
|
||||
(menuOpened)="onMenuOpened()"
|
||||
>
|
||||
<mat-icon aria-hidden="false" matBadge="⁠" [matBadgeHidden]="!notifications.length" class="adf-notification-history-menu_button-icon" matBadgeColor="accent" matBadgeSize="small" adf-icon="notifications" />
|
||||
</button>
|
||||
|
||||
<mat-menu #menu="matMenu"
|
||||
[xPosition]="menuPositionX"
|
||||
[yPosition]="menuPositionY"
|
||||
id="adf-notification-history-menu"
|
||||
class="adf-notification-history-menu adf-notification-history-menu-panel">
|
||||
<div class="adf-notification-history-list-header" aria-hidden="true">
|
||||
<span class="adf-notification-history-menu-title">{{ 'NOTIFICATIONS.TITLE' | translate }}</span>
|
||||
<button mat-icon-button
|
||||
*ngIf="notifications.length"
|
||||
data-automation-id="adf-notification-history-mark-as-read"
|
||||
class="adf-notification-history-mark-as-read"
|
||||
title="{{ 'NOTIFICATIONS.MARK_AS_READ' | translate }}"
|
||||
(click)="markAsRead()"
|
||||
#markAsReadButton
|
||||
(keydown)="manageFocus($event)">
|
||||
<mat-icon class="adf-notification-history-mark-as-read-icon" adf-icon="done_all" />
|
||||
[xPosition]="menuPositionX"
|
||||
[yPosition]="menuPositionY"
|
||||
id="adf-notification-history-menu"
|
||||
class="adf-notification-history-menu adf-notification-history-menu-panel">
|
||||
<div class="adf-notification-history-list-header" aria-hidden="true">
|
||||
<span class="adf-notification-history-menu-title">{{ 'NOTIFICATIONS.TITLE' | translate }}</span>
|
||||
@if (notifications.length) {
|
||||
<button mat-icon-button
|
||||
data-automation-id="adf-notification-history-mark-as-read"
|
||||
class="adf-notification-history-mark-as-read"
|
||||
title="{{ 'NOTIFICATIONS.MARK_AS_READ' | translate }}"
|
||||
(click)="markAsRead()"
|
||||
#markAsReadButton
|
||||
(keydown)="manageFocus($event)">
|
||||
<mat-icon class="adf-notification-history-mark-as-read-icon" adf-icon="done_all" />
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<mat-divider aria-hidden="true" />
|
||||
|
||||
<div class="adf-notification-history-item-list">
|
||||
@if (notifications.length) {
|
||||
@for (notification of paginatedNotifications; track notification) {
|
||||
<button mat-menu-item
|
||||
(click)="onNotificationClick(notification, $event)"
|
||||
class="adf-notification-history-menu-item"
|
||||
(keydown)="manageFocus($event)">
|
||||
<div class="adf-notification-history-menu-item-content">
|
||||
@if (notification.initiator) {
|
||||
<div
|
||||
[outerHTML]="notification.initiator | usernameInitials : 'adf-notification-initiator-pic'"></div>
|
||||
} @else {
|
||||
<mat-icon class="adf-notification-history-menu-initiator" [adf-icon]="notification.icon" />
|
||||
}
|
||||
<div class="adf-notification-history-menu-item-content-message">
|
||||
@for (message of notification.messages; track message) {
|
||||
<p class="adf-notification-history-menu-text adf-notification-history-menu-message"
|
||||
[title]="message">{{ message }}</p>
|
||||
}
|
||||
<p class="adf-notification-history-menu-text adf-notification-history-menu-date"
|
||||
> {{ notification.datetime | adfTimeAgo }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
} @else {
|
||||
<p id="adf-notification-history-component-no-message"
|
||||
class="adf-notification-history-menu-no-message-text">
|
||||
{{ 'NOTIFICATIONS.NO_MESSAGE' | translate }}
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<mat-divider aria-hidden="true" />
|
||||
|
||||
<div class="adf-notification-history-item-list">
|
||||
<ng-container *ngIf="notifications.length; else empty_list_template">
|
||||
<button mat-menu-item
|
||||
*ngFor="let notification of paginatedNotifications"
|
||||
(click)="onNotificationClick(notification, $event)"
|
||||
class="adf-notification-history-menu-item"
|
||||
(keydown)="manageFocus($event)">
|
||||
<div class="adf-notification-history-menu-item-content">
|
||||
<div *ngIf="notification.initiator; else no_avatar"
|
||||
[outerHTML]="notification.initiator | usernameInitials : 'adf-notification-initiator-pic'"></div>
|
||||
<ng-template #no_avatar>
|
||||
<mat-icon class="adf-notification-history-menu-initiator" [adf-icon]="notification.icon" />
|
||||
</ng-template>
|
||||
<div class="adf-notification-history-menu-item-content-message">
|
||||
<p class="adf-notification-history-menu-text adf-notification-history-menu-message"
|
||||
*ngFor="let message of notification.messages"
|
||||
[title]="message">{{ message }}</p>
|
||||
<p class="adf-notification-history-menu-text adf-notification-history-menu-date"
|
||||
> {{ notification.datetime | adfTimeAgo }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</ng-container>
|
||||
<ng-template #empty_list_template>
|
||||
<p id="adf-notification-history-component-no-message"
|
||||
class="adf-notification-history-menu-no-message-text">
|
||||
{{ 'NOTIFICATIONS.NO_MESSAGE' | translate }}
|
||||
</p>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<mat-divider aria-hidden="true" />
|
||||
<mat-divider aria-hidden="true" />
|
||||
|
||||
@if (hasMoreNotifications()) {
|
||||
<div
|
||||
class="adf-notification-history-load-more"
|
||||
*ngIf="hasMoreNotifications()"
|
||||
aria-hidden="true">
|
||||
<button
|
||||
data-automation-id="adf-notification-history-load-more"
|
||||
mat-button
|
||||
(click)="loadMore($event)"
|
||||
#loadMoreButton
|
||||
(keydown)="manageFocus($event)">
|
||||
{{ 'NOTIFICATIONS.LOAD_MORE' | translate }}
|
||||
</button>
|
||||
class="adf-notification-history-load-more"
|
||||
aria-hidden="true">
|
||||
<button
|
||||
data-automation-id="adf-notification-history-load-more"
|
||||
mat-button
|
||||
(click)="loadMore($event)"
|
||||
#loadMoreButton
|
||||
(keydown)="manageFocus($event)">
|
||||
{{ 'NOTIFICATIONS.LOAD_MORE' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</mat-menu>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user