mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-5991] ESLint fixes and code quality improvements (#8893)
* prefer-optional-chain: core * prefer-optional-chain: content, fix typings * prefer-optional-chain: process, fix typings * prefer-optional-chain: process-cloud, fix typings, fix ts configs and eslint * [ci: force] sonar errors fixes, insights lib * [ci:force] fix security issues * [ci:force] fix metadata e2e bug, js assignment bugs * [ci:force] fix lint issue * [ci:force] fix tests
This commit is contained in:
@@ -63,10 +63,6 @@
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
"@typescript-eslint/no-require-imports": "off",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"brace-style": [
|
||||
"error",
|
||||
"1tbs"
|
||||
],
|
||||
"comma-dangle": "error",
|
||||
"default-case": "error",
|
||||
"import/order": "off",
|
||||
|
@@ -15,14 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Router,
|
||||
CanActivate,
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot,
|
||||
CanActivateChild,
|
||||
UrlTree
|
||||
} from '@angular/router';
|
||||
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivateChild, UrlTree } from '@angular/router';
|
||||
import { AuthenticationService } from '../services/authentication.service';
|
||||
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||
import { OauthConfigModel } from '../models/oauth-config.model';
|
||||
@@ -39,10 +32,7 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
||||
private storageService = inject(StorageService);
|
||||
|
||||
protected get withCredentials(): boolean {
|
||||
return this.appConfigService.get<boolean>(
|
||||
'auth.withCredentials',
|
||||
false
|
||||
);
|
||||
return this.appConfigService.get<boolean>('auth.withCredentials', false);
|
||||
}
|
||||
|
||||
abstract checkLogin(
|
||||
@@ -54,7 +44,6 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
|
||||
|
||||
if (this.authenticationService.isLoggedIn() && this.authenticationService.isOauth() && this.isLoginFragmentPresent()) {
|
||||
return this.redirectSSOSuccessURL();
|
||||
}
|
||||
@@ -116,23 +105,11 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
||||
}
|
||||
|
||||
protected getLoginRoute(): string {
|
||||
return (
|
||||
this.appConfigService &&
|
||||
this.appConfigService.get<string>(
|
||||
AppConfigValues.LOGIN_ROUTE,
|
||||
'login'
|
||||
)
|
||||
);
|
||||
return this.appConfigService.get<string>(AppConfigValues.LOGIN_ROUTE, 'login');
|
||||
}
|
||||
|
||||
protected getProvider(): string {
|
||||
return (
|
||||
this.appConfigService &&
|
||||
this.appConfigService.get<string>(
|
||||
AppConfigValues.PROVIDERS,
|
||||
'ALL'
|
||||
)
|
||||
);
|
||||
return this.appConfigService.get<string>(AppConfigValues.PROVIDERS, 'ALL');
|
||||
}
|
||||
|
||||
protected isOAuthWithoutSilentLogin(): boolean {
|
||||
@@ -141,8 +118,7 @@ export abstract class AuthGuardBase implements CanActivate, CanActivateChild {
|
||||
}
|
||||
|
||||
protected isSilentLogin(): boolean {
|
||||
const oauth = this.appConfigService.oauth2;;
|
||||
const oauth = this.appConfigService.oauth2;
|
||||
return this.authenticationService.isOauth() && oauth && oauth.silentLogin;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -42,7 +42,6 @@ const templateTypes = {
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemModel> implements OnChanges, OnDestroy {
|
||||
|
||||
@Input()
|
||||
editable: boolean = false;
|
||||
|
||||
@@ -69,21 +68,19 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private clipboardService: ClipboardService,
|
||||
private translateService: TranslationService,
|
||||
private cd: ChangeDetectorRef) {
|
||||
constructor(private clipboardService: ClipboardService, private translateService: TranslationService, private cd: ChangeDetectorRef) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.property && changes.property.firstChange) {
|
||||
if (changes.property?.firstChange) {
|
||||
this.textInput.valueChanges
|
||||
.pipe(
|
||||
filter(textInputValue => textInputValue !== this.editedValue && textInputValue !== null),
|
||||
filter((textInputValue) => textInputValue !== this.editedValue && textInputValue !== null),
|
||||
debounceTime(50),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(textInputValue => {
|
||||
.subscribe((textInputValue) => {
|
||||
this.editedValue = textInputValue;
|
||||
this.update();
|
||||
});
|
||||
@@ -143,8 +140,7 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
||||
|
||||
prepareValueForUpload(property: CardViewTextItemModel, value: string | string[]): string | string[] {
|
||||
if (property.multivalued && typeof value === 'string') {
|
||||
const listOfValues = value.split(this.multiValueSeparator.trim()).map((item) => item.trim());
|
||||
return listOfValues;
|
||||
return value.split(this.multiValueSeparator.trim()).map((item) => item.trim());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -196,7 +192,7 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
||||
|
||||
undoText(event: KeyboardEvent) {
|
||||
if ((event.ctrlKey || event.metaKey) && event.code === 'KeyZ' && this.textInput.value) {
|
||||
this.textInput.setValue('');
|
||||
this.textInput.setValue('');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +222,7 @@ export class CardViewTextItemComponent extends BaseCardView<CardViewTextItemMode
|
||||
}
|
||||
|
||||
get hasErrors(): boolean {
|
||||
return (!!this.errors?.length) ?? false;
|
||||
return !!this.errors?.length;
|
||||
}
|
||||
|
||||
get isChipViewEnabled(): boolean {
|
||||
|
@@ -34,7 +34,7 @@ export abstract class CardViewBaseItemModel {
|
||||
|
||||
constructor(cardViewItemProperties: CardViewItemProperties) {
|
||||
this.label = cardViewItemProperties.label || '';
|
||||
this.value = cardViewItemProperties.value && cardViewItemProperties.value.displayName || cardViewItemProperties.value;
|
||||
this.value = cardViewItemProperties.value?.displayName || cardViewItemProperties.value;
|
||||
this.key = cardViewItemProperties.key;
|
||||
this.default = cardViewItemProperties.default;
|
||||
this.editable = !!cardViewItemProperties.editable;
|
||||
@@ -63,9 +63,7 @@ export abstract class CardViewBaseItemModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.validators
|
||||
.map((validator) => validator.isValid(newValue))
|
||||
.reduce((isValidUntilNow, isValid) => isValidUntilNow && isValid, true);
|
||||
return this.validators.map((validator) => validator.isValid(newValue)).reduce((isValidUntilNow, isValid) => isValidUntilNow && isValid, true);
|
||||
}
|
||||
|
||||
getValidationErrors(value): CardViewItemValidator[] {
|
||||
|
@@ -19,7 +19,10 @@ import { Type } from '@angular/core';
|
||||
|
||||
const getType = (type: any): any => () => type;
|
||||
|
||||
export interface DynamicComponentModel { type: string }
|
||||
export interface DynamicComponentModel {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export type DynamicComponentResolveFunction = (model: DynamicComponentModel) => Type<any>;
|
||||
export class DynamicComponentResolver {
|
||||
static fromType(type: Type<any>): DynamicComponentResolveFunction {
|
||||
|
@@ -21,7 +21,6 @@ import moment, { isMoment, Moment } from 'moment';
|
||||
|
||||
@Injectable()
|
||||
export class MomentDateAdapter extends DateAdapter<Moment> {
|
||||
|
||||
private localeData: any = moment.localeData();
|
||||
|
||||
overrideDisplayFormat: string;
|
||||
@@ -50,7 +49,7 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
|
||||
return this.localeData.monthsShort();
|
||||
case 'narrow':
|
||||
return this.localeData.monthsShort().map((month) => month[0]);
|
||||
default :
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -72,7 +71,7 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
|
||||
return this.localeData.weekdaysShort();
|
||||
case 'narrow':
|
||||
return this.localeData.weekdaysShort();
|
||||
default :
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -134,7 +133,7 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
|
||||
date = this.clone(date);
|
||||
displayFormat = this.overrideDisplayFormat ? this.overrideDisplayFormat : displayFormat;
|
||||
|
||||
if (date && date.format) {
|
||||
if (date?.format) {
|
||||
return date.utc().local().format(displayFormat);
|
||||
} else {
|
||||
return '';
|
||||
|
@@ -15,10 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component, ViewEncapsulation, HostListener, AfterViewInit,
|
||||
Optional, Inject, QueryList, ViewChildren
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, HostListener, AfterViewInit, Optional, Inject, QueryList, ViewChildren } from '@angular/core';
|
||||
import { trigger } from '@angular/animations';
|
||||
import { DOWN_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
|
||||
import { FocusKeyManager } from '@angular/cdk/a11y';
|
||||
@@ -33,13 +30,15 @@ import { CONTEXT_MENU_DATA } from './context-menu.tokens';
|
||||
<div mat-menu class="mat-menu-panel" @panelAnimation>
|
||||
<div id="adf-context-menu-content" class="mat-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"
|
||||
(click)="onMenuItemClick($event, link)">
|
||||
<button
|
||||
*ngIf="link.model?.visible"
|
||||
[attr.data-automation-id]="'context-' + (link.title || link.model?.title | translate)"
|
||||
mat-menu-item
|
||||
[disabled]="link.model?.disabled"
|
||||
(click)="onMenuItemClick($event, link)"
|
||||
>
|
||||
<mat-icon *ngIf="link.model?.icon">{{ link.model.icon }}</mat-icon>
|
||||
<span>{{ (link.title || link.model?.title) | translate }}</span>
|
||||
<span>{{ link.title || link.model?.title | translate }}</span>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
@@ -50,9 +49,7 @@ import { CONTEXT_MENU_DATA } from './context-menu.tokens';
|
||||
class: 'adf-context-menu'
|
||||
},
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
animations: [
|
||||
trigger('panelAnimation', contextMenuAnimation)
|
||||
]
|
||||
animations: [trigger('panelAnimation', contextMenuAnimation)]
|
||||
})
|
||||
export class ContextMenuListComponent implements AfterViewInit {
|
||||
private keyManager: FocusKeyManager<MatMenuItem>;
|
||||
@@ -84,7 +81,7 @@ export class ContextMenuListComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
onMenuItemClick(event: Event, menuItem: any) {
|
||||
if (menuItem && menuItem.model && menuItem.model.disabled) {
|
||||
if (menuItem?.model?.disabled) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
return;
|
||||
|
@@ -15,14 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
ViewEncapsulation,
|
||||
OnDestroy, Optional
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation, OnDestroy, Optional } from '@angular/core';
|
||||
import { DataColumn } from '../../data/data-column.model';
|
||||
import { DataRow } from '../../data/data-row.model';
|
||||
import { DataTableAdapter } from '../../data/datatable-adapter';
|
||||
@@ -35,23 +28,22 @@ import { DataTableService } from '../../services/datatable.service';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<ng-container>
|
||||
<span *ngIf="copyContent; else defaultCell"
|
||||
adf-clipboard="CLIPBOARD.CLICK_TO_COPY"
|
||||
[clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"
|
||||
[attr.aria-label]="value$ | async"
|
||||
[title]="tooltip"
|
||||
class="adf-datatable-cell-value"
|
||||
>{{ value$ | async }}</span>
|
||||
</ng-container>
|
||||
<ng-template #defaultCell>
|
||||
<span
|
||||
*ngIf="copyContent; else defaultCell"
|
||||
adf-clipboard="CLIPBOARD.CLICK_TO_COPY"
|
||||
[clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"
|
||||
[attr.aria-label]="value$ | async"
|
||||
[title]="tooltip"
|
||||
class="adf-datatable-cell-value"
|
||||
>{{ value$ | async }}</span>
|
||||
>{{ value$ | async }}</span
|
||||
>
|
||||
</ng-container>
|
||||
<ng-template #defaultCell>
|
||||
<span [title]="tooltip" class="adf-datatable-cell-value">{{ value$ | async }}</span>
|
||||
</ng-template>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {class: 'adf-datatable-content-cell'}
|
||||
host: { class: 'adf-datatable-content-cell' }
|
||||
})
|
||||
export class DataTableCellComponent implements OnInit, OnDestroy {
|
||||
/** Data table adapter instance. */
|
||||
@@ -82,31 +74,30 @@ export class DataTableCellComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(@Optional() protected dataTableService: DataTableService) {
|
||||
}
|
||||
constructor(@Optional() protected dataTableService: DataTableService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.updateValue();
|
||||
if(this.dataTableService) {
|
||||
this.dataTableService.rowUpdate
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(data => {
|
||||
if (data && data.id) {
|
||||
if (this.row.id === data.id) {
|
||||
if (this.row.obj && data.obj) {
|
||||
this.row.obj = data.obj;
|
||||
this.row['cache'][this.column.key] = this.column.key.split('.').reduce((source, key) => source ? source[key] : '', data.obj);
|
||||
if (this.dataTableService) {
|
||||
this.dataTableService.rowUpdate.pipe(takeUntil(this.onDestroy$)).subscribe((data) => {
|
||||
if (data?.id) {
|
||||
if (this.row.id === data.id) {
|
||||
if (this.row.obj && data.obj) {
|
||||
this.row.obj = data.obj;
|
||||
this.row['cache'][this.column.key] = this.column.key
|
||||
.split('.')
|
||||
.reduce((source, key) => (source ? source[key] : ''), data.obj);
|
||||
|
||||
this.updateValue();
|
||||
}
|
||||
this.updateValue();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected updateValue() {
|
||||
if (this.column && this.column.key && this.row && this.data) {
|
||||
if (this.column?.key && this.row && this.data) {
|
||||
const value = this.data.getValue(this.row, this.column, this.resolverFn);
|
||||
|
||||
this.value$.next(value);
|
||||
|
@@ -269,16 +269,12 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
this.keyManager.onKeydown(event);
|
||||
}
|
||||
|
||||
constructor(private elementRef: ElementRef,
|
||||
differs: IterableDiffers,
|
||||
private matIconRegistry: MatIconRegistry,
|
||||
private sanitizer: DomSanitizer) {
|
||||
constructor(private elementRef: ElementRef, differs: IterableDiffers, private matIconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) {
|
||||
if (differs) {
|
||||
this.differ = differs.find([]).create(null);
|
||||
}
|
||||
|
||||
this.click$ = new Observable<DataRowEvent>((observer) => this.clickObserver = observer)
|
||||
.pipe(share());
|
||||
this.click$ = new Observable<DataRowEvent>((observer) => (this.clickObserver = observer)).pipe(share());
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -298,14 +294,12 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.keyManager = new FocusKeyManager(this.rowsList)
|
||||
.withWrap()
|
||||
.skipPredicate(item => item.disabled);
|
||||
this.keyManager = new FocusKeyManager(this.rowsList).withWrap().skipPredicate((item) => item.disabled);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
this.initAndSubscribeClickStream();
|
||||
if(this.selectedRowId) {
|
||||
if (this.selectedRowId) {
|
||||
this.setRowAsContextSource();
|
||||
}
|
||||
|
||||
@@ -358,8 +352,8 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
|
||||
onDropHeaderColumn(event: CdkDragDrop<unknown>): void {
|
||||
const allColumns = this.data.getColumns();
|
||||
const shownColumns = allColumns.filter(column => !column.isHidden);
|
||||
const hiddenColumns = allColumns.filter(column => column.isHidden);
|
||||
const shownColumns = allColumns.filter((column) => !column.isHidden);
|
||||
const hiddenColumns = allColumns.filter((column) => column.isHidden);
|
||||
|
||||
moveItemInArray(shownColumns, event.previousIndex, event.currentIndex);
|
||||
const allColumnsWithNewOrder = [...shownColumns, ...hiddenColumns];
|
||||
@@ -378,14 +372,14 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
}
|
||||
|
||||
isPropertyChanged(property: SimpleChange): boolean {
|
||||
return !!(property && property.currentValue);
|
||||
return !!property?.currentValue;
|
||||
}
|
||||
|
||||
convertToRowsData(rows: any []): ObjectDataRow[] {
|
||||
convertToRowsData(rows: any[]): ObjectDataRow[] {
|
||||
return rows.map((row) => new ObjectDataRow(row, row.isSelected));
|
||||
}
|
||||
|
||||
convertToColumnsData(columns: any []): ObjectDataColumn[] {
|
||||
convertToColumnsData(columns: any[]): ObjectDataColumn[] {
|
||||
return columns.map((column) => new ObjectDataColumn(column));
|
||||
}
|
||||
|
||||
@@ -398,16 +392,11 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
|
||||
private initAndSubscribeClickStream() {
|
||||
this.unsubscribeClickStream();
|
||||
const singleClickStream = this.click$
|
||||
.pipe(
|
||||
buffer(
|
||||
this.click$.pipe(
|
||||
debounceTime(250)
|
||||
)
|
||||
),
|
||||
map((list) => list),
|
||||
filter((x) => x.length === 1)
|
||||
);
|
||||
const singleClickStream = this.click$.pipe(
|
||||
buffer(this.click$.pipe(debounceTime(250))),
|
||||
map((list) => list),
|
||||
filter((x) => x.length === 1)
|
||||
);
|
||||
|
||||
this.singleClickStreamSub = singleClickStream.subscribe((dataRowEvents: DataRowEvent[]) => {
|
||||
const event: DataRowEvent = dataRowEvents[0];
|
||||
@@ -423,16 +412,11 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
}
|
||||
});
|
||||
|
||||
const multiClickStream = this.click$
|
||||
.pipe(
|
||||
buffer(
|
||||
this.click$.pipe(
|
||||
debounceTime(250)
|
||||
)
|
||||
),
|
||||
map((list) => list),
|
||||
filter((x) => x.length >= 2)
|
||||
);
|
||||
const multiClickStream = this.click$.pipe(
|
||||
buffer(this.click$.pipe(debounceTime(250))),
|
||||
map((list) => list),
|
||||
filter((x) => x.length >= 2)
|
||||
);
|
||||
|
||||
this.multiClickStreamSub = multiClickStream.subscribe((dataRowEvents: DataRowEvent[]) => {
|
||||
const event: DataRowEvent = dataRowEvents[0];
|
||||
@@ -489,10 +473,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
}
|
||||
|
||||
private getRuntimeColumns(): any[] {
|
||||
return [
|
||||
...(this.columns || []),
|
||||
...this.getSchemaFromHtml()
|
||||
];
|
||||
return [...(this.columns || []), ...this.getSchemaFromHtml()];
|
||||
}
|
||||
|
||||
private setTableSchema() {
|
||||
@@ -511,7 +492,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
|
||||
public getSchemaFromHtml(): any {
|
||||
let schema = [];
|
||||
if (this.columnList && this.columnList.columns && this.columnList.columns.length > 0) {
|
||||
if (this.columnList?.columns?.length > 0) {
|
||||
schema = this.columnList.columns.map((c) => c as DataColumn);
|
||||
}
|
||||
return schema;
|
||||
@@ -577,7 +558,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
if (this.data) {
|
||||
const rows = this.data.getRows();
|
||||
if (rows && rows.length > 0) {
|
||||
rows.forEach((r) => r.isSelected = false);
|
||||
rows.forEach((r) => (r.isSelected = false));
|
||||
}
|
||||
this.selection = [];
|
||||
}
|
||||
@@ -722,7 +703,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
isIconValue(row: DataRow, col: DataColumn): boolean {
|
||||
if (row && col) {
|
||||
const value = row.getValue(col.key);
|
||||
return value && value.startsWith('material-icons://');
|
||||
return value?.startsWith('material-icons://');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -809,13 +790,13 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
|
||||
markRowAsContextMenuSource(selectedRow: DataRow): void {
|
||||
this.selectedRowId = selectedRow.id ? selectedRow.id : '';
|
||||
this.data.getRows().forEach((row) => row.isContextMenuSource = false);
|
||||
this.data.getRows().forEach((row) => (row.isContextMenuSource = false));
|
||||
selectedRow.isContextMenuSource = true;
|
||||
}
|
||||
|
||||
private setRowAsContextSource(): void {
|
||||
const selectedRow = this.data.getRows().find((row) => this.selectedRowId === row.id);
|
||||
if(selectedRow) {
|
||||
if (selectedRow) {
|
||||
selectedRow.isContextMenuSource = true;
|
||||
}
|
||||
}
|
||||
@@ -845,7 +826,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
}
|
||||
|
||||
findSelectionById(id: string): number {
|
||||
return this.selection.findIndex(selection => selection?.id === id);
|
||||
return this.selection.findIndex((selection) => selection?.id === id);
|
||||
}
|
||||
|
||||
getCellTooltip(row: DataRow, col: DataColumn): string {
|
||||
@@ -923,7 +904,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
|
||||
if (this.display === 'gallery') {
|
||||
for (let i = 0; i < maxGalleryRows; i++) {
|
||||
this.fakeRows.push('');
|
||||
this.fakeRows.push('');
|
||||
}
|
||||
} else {
|
||||
this.fakeRows = [];
|
||||
@@ -931,7 +912,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
}
|
||||
|
||||
getNameColumnValue() {
|
||||
return this.data.getColumns().find( (el: any) => el.key.includes('name'));
|
||||
return this.data.getColumns().find((el: any) => el.key.includes('name'));
|
||||
}
|
||||
|
||||
getAutomationValue(row: DataRow): any {
|
||||
@@ -944,35 +925,27 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
return 'ADF-DATATABLE.ACCESSIBILITY.SORT_NONE';
|
||||
}
|
||||
|
||||
return this.isColumnSorted(column, 'asc') ?
|
||||
'ADF-DATATABLE.ACCESSIBILITY.SORT_ASCENDING' :
|
||||
'ADF-DATATABLE.ACCESSIBILITY.SORT_DESCENDING';
|
||||
return this.isColumnSorted(column, 'asc') ? 'ADF-DATATABLE.ACCESSIBILITY.SORT_ASCENDING' : 'ADF-DATATABLE.ACCESSIBILITY.SORT_DESCENDING';
|
||||
}
|
||||
|
||||
getSortLiveAnnouncement(column: DataColumn): string {
|
||||
if (!this.isColumnSortActive(column)) {
|
||||
return 'ADF-DATATABLE.ACCESSIBILITY.SORT_DEFAULT' ;
|
||||
return 'ADF-DATATABLE.ACCESSIBILITY.SORT_DEFAULT';
|
||||
}
|
||||
return this.isColumnSorted(column, 'asc') ?
|
||||
'ADF-DATATABLE.ACCESSIBILITY.SORT_ASCENDING_BY' :
|
||||
'ADF-DATATABLE.ACCESSIBILITY.SORT_DESCENDING_BY';
|
||||
return this.isColumnSorted(column, 'asc')
|
||||
? 'ADF-DATATABLE.ACCESSIBILITY.SORT_ASCENDING_BY'
|
||||
: 'ADF-DATATABLE.ACCESSIBILITY.SORT_DESCENDING_BY';
|
||||
}
|
||||
|
||||
private registerDragHandleIcon(): void {
|
||||
const iconUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
|
||||
'./assets/images/drag_indicator_24px.svg'
|
||||
);
|
||||
const iconUrl = this.sanitizer.bypassSecurityTrustResourceUrl('./assets/images/drag_indicator_24px.svg');
|
||||
|
||||
this.matIconRegistry.addSvgIconInNamespace(
|
||||
'adf',
|
||||
'drag_indicator',
|
||||
iconUrl
|
||||
);
|
||||
this.matIconRegistry.addSvgIconInNamespace('adf', 'drag_indicator', iconUrl);
|
||||
}
|
||||
|
||||
onResizing({ rectangle: { width } }: ResizeEvent, colIndex: number): void {
|
||||
const timeoutId = setTimeout(() => {
|
||||
const allColumns = this.data.getColumns().filter(column => !column.isHidden);
|
||||
const allColumns = this.data.getColumns().filter((column) => !column.isHidden);
|
||||
allColumns[colIndex].width = width;
|
||||
this.data.setColumns(allColumns);
|
||||
|
||||
@@ -1003,11 +976,9 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
||||
headerContainerColumns.forEach((column: HTMLElement, index: number): void => {
|
||||
if (allColumns[index]) {
|
||||
if (index === 0) {
|
||||
allColumns[index].width =
|
||||
column.clientWidth - parseInt(window.getComputedStyle(column).paddingLeft, 10);
|
||||
} else if ( index === headerContainerColumns.length - 1) {
|
||||
allColumns[index].width =
|
||||
column.clientWidth - parseInt(window.getComputedStyle(column).paddingRight, 10);
|
||||
allColumns[index].width = column.clientWidth - parseInt(window.getComputedStyle(column).paddingLeft, 10);
|
||||
} else if (index === headerContainerColumns.length - 1) {
|
||||
allColumns[index].width = column.clientWidth - parseInt(window.getComputedStyle(column).paddingRight, 10);
|
||||
} else {
|
||||
allColumns[index].width = column.clientWidth;
|
||||
}
|
||||
|
@@ -38,29 +38,23 @@ import { DataTableService } from '../../services/datatable.service';
|
||||
host: { class: 'adf-datatable-content-cell' }
|
||||
})
|
||||
export class JsonCellComponent extends DataTableCellComponent implements OnInit {
|
||||
|
||||
/** Editable JSON. */
|
||||
@Input()
|
||||
editable: boolean = false;
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
@Optional() dataTableService: DataTableService
|
||||
) {
|
||||
constructor(private dialog: MatDialog, @Optional() dataTableService: DataTableService) {
|
||||
super(dataTableService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.column && this.column.key && this.row && this.data) {
|
||||
if (this.column?.key && this.row && this.data) {
|
||||
this.value$.next(this.data.getValue(this.row, this.column, this.resolverFn));
|
||||
}
|
||||
}
|
||||
|
||||
view() {
|
||||
const rawValue: string | any = this.data.getValue(this.row, this.column, this.resolverFn);
|
||||
const value = typeof rawValue === 'object'
|
||||
? JSON.stringify(rawValue || {}, null, 2)
|
||||
: rawValue;
|
||||
const value = typeof rawValue === 'object' ? JSON.stringify(rawValue || {}, null, 2) : rawValue;
|
||||
|
||||
const settings: EditJsonDialogSettings = {
|
||||
title: this.column.title,
|
||||
@@ -68,16 +62,19 @@ export class JsonCellComponent extends DataTableCellComponent implements OnInit
|
||||
value
|
||||
};
|
||||
|
||||
this.dialog.open(EditJsonDialogComponent, {
|
||||
data: settings,
|
||||
minWidth: '50%',
|
||||
minHeight: '50%'
|
||||
}).afterClosed().subscribe((/*result: string*/) => {
|
||||
if (typeof rawValue === 'object') {
|
||||
// todo: update cell value as object
|
||||
} else {
|
||||
// todo: update cell value as string
|
||||
}
|
||||
});
|
||||
this.dialog
|
||||
.open(EditJsonDialogComponent, {
|
||||
data: settings,
|
||||
minWidth: '50%',
|
||||
minHeight: '50%'
|
||||
})
|
||||
.afterClosed()
|
||||
.subscribe((/*result: string*/) => {
|
||||
if (typeof rawValue === 'object') {
|
||||
// todo: update cell value as object
|
||||
} else {
|
||||
// todo: update cell value as string
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -15,13 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
OnInit, Optional,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, Optional, ViewEncapsulation } from '@angular/core';
|
||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||
import { DataTableService } from '../../services/datatable.service';
|
||||
|
||||
@@ -48,14 +42,10 @@ export class LocationCellComponent extends DataTableCellComponent implements OnI
|
||||
|
||||
/** @override */
|
||||
ngOnInit() {
|
||||
if (this.column && this.column.key && this.row && this.data) {
|
||||
const path: any = this.data.getValue(
|
||||
this.row,
|
||||
this.column,
|
||||
this.resolverFn
|
||||
);
|
||||
if (this.column?.key && this.row && this.data) {
|
||||
const path: any = this.data.getValue(this.row, this.column, this.resolverFn);
|
||||
|
||||
if (path && path.name && path.elements) {
|
||||
if (path?.name && path.elements) {
|
||||
this.value$.next(path.name.split('/').pop());
|
||||
|
||||
if (!this.tooltip) {
|
||||
|
@@ -25,7 +25,6 @@ import { ObjectDataColumn } from './object-datacolumn.model';
|
||||
@Directive()
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export abstract class DataTableSchema<T = unknown> {
|
||||
|
||||
@ContentChild(DataColumnListComponent)
|
||||
columnList: DataColumnListComponent;
|
||||
|
||||
@@ -39,16 +38,14 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
protected columnsOrderedByKey: string = 'id';
|
||||
|
||||
protected columnsVisibility: { [columnId: string]: boolean } | undefined;
|
||||
protected columnsWidths: { [columnId: string]: number} | undefined;
|
||||
protected columnsWidths: { [columnId: string]: number } | undefined;
|
||||
|
||||
private layoutPresets = {};
|
||||
|
||||
private columnsSchemaSubject$ = new ReplaySubject<boolean>();
|
||||
isColumnSchemaCreated$ = this.columnsSchemaSubject$.asObservable();
|
||||
|
||||
constructor(private appConfigService: AppConfigService,
|
||||
protected presetKey: string,
|
||||
protected presetsModel: any) { }
|
||||
constructor(private appConfigService: AppConfigService, protected presetKey: string, protected presetsModel: any) {}
|
||||
|
||||
public createDatatableSchema(): void {
|
||||
this.loadLayoutPresets();
|
||||
@@ -81,10 +78,7 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
const configSchemaColumns = this.getSchemaFromConfig(this.presetColumn);
|
||||
const htmlSchemaColumns = this.getSchemaFromHtml(this.columnList);
|
||||
|
||||
let customSchemaColumns = [
|
||||
...configSchemaColumns,
|
||||
...htmlSchemaColumns
|
||||
];
|
||||
let customSchemaColumns = [...configSchemaColumns, ...htmlSchemaColumns];
|
||||
|
||||
if (customSchemaColumns.length === 0) {
|
||||
customSchemaColumns = this.getDefaultLayoutPreset();
|
||||
@@ -95,18 +89,18 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
|
||||
public getSchemaFromHtml(columnList: DataColumnListComponent): DataColumn[] {
|
||||
let schema = [];
|
||||
if (columnList && columnList.columns && columnList.columns.length > 0) {
|
||||
if (columnList?.columns?.length > 0) {
|
||||
schema = columnList.columns.map((c) => c as DataColumn);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
public getSchemaFromConfig(presetColumn: string): DataColumn[] {
|
||||
return presetColumn ? (this.layoutPresets[presetColumn]).map((col) => new ObjectDataColumn(col)) : [];
|
||||
public getSchemaFromConfig(presetColumn: string): DataColumn[] {
|
||||
return presetColumn ? this.layoutPresets[presetColumn].map((col) => new ObjectDataColumn(col)) : [];
|
||||
}
|
||||
|
||||
private getDefaultLayoutPreset(): DataColumn[] {
|
||||
return (this.layoutPresets['default']).map((col) => new ObjectDataColumn(col));
|
||||
return this.layoutPresets['default'].map((col) => new ObjectDataColumn(col));
|
||||
}
|
||||
|
||||
public setPresetKey(presetKey: string) {
|
||||
@@ -117,12 +111,12 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
this.presetsModel = presetsModel;
|
||||
}
|
||||
|
||||
private sortColumnsByKey(columns: any[]): any[] {
|
||||
private sortColumnsByKey(columns: any[]): any[] {
|
||||
const defaultColumns = [...columns];
|
||||
const columnsWithProperOrder = [];
|
||||
|
||||
(this.columnsOrder ?? []).forEach(columnKey => {
|
||||
const originalColumnIndex = defaultColumns.findIndex(defaultColumn => defaultColumn[this.columnsOrderedByKey] === columnKey);
|
||||
(this.columnsOrder ?? []).forEach((columnKey) => {
|
||||
const originalColumnIndex = defaultColumns.findIndex((defaultColumn) => defaultColumn[this.columnsOrderedByKey] === columnKey);
|
||||
|
||||
if (originalColumnIndex > -1) {
|
||||
columnsWithProperOrder.push(defaultColumns[originalColumnIndex]);
|
||||
@@ -135,12 +129,10 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
|
||||
private setHiddenColumns(columns: DataColumn[]): DataColumn[] {
|
||||
if (this.columnsVisibility) {
|
||||
return columns.map(column => {
|
||||
return columns.map((column) => {
|
||||
const isColumnVisible = this.columnsVisibility[column.id];
|
||||
|
||||
return isColumnVisible === undefined ?
|
||||
column :
|
||||
{ ...column, isHidden: !isColumnVisible };
|
||||
return isColumnVisible === undefined ? column : { ...column, isHidden: !isColumnVisible };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,10 +140,10 @@ export abstract class DataTableSchema<T = unknown> {
|
||||
}
|
||||
|
||||
private setColumnsWidth(columns: DataColumn[]): DataColumn[] {
|
||||
if(this.columnsWidths) {
|
||||
return columns.map(column => {
|
||||
if (this.columnsWidths) {
|
||||
return columns.map((column) => {
|
||||
const columnWidth = this.columnsWidths[column.id];
|
||||
return columnWidth === undefined ? column : {...column, width:columnWidth};
|
||||
return columnWidth === undefined ? column : { ...column, width: columnWidth };
|
||||
});
|
||||
}
|
||||
return columns;
|
||||
|
@@ -25,7 +25,6 @@ import { Subject } from 'rxjs';
|
||||
|
||||
// Simple implementation of the DataTableAdapter interface.
|
||||
export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
|
||||
private _sorting: DataSorting;
|
||||
private _rows: DataRow[];
|
||||
private _columns: DataColumn[];
|
||||
@@ -36,12 +35,12 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
static generateSchema(data: any[]) {
|
||||
const schema = [];
|
||||
|
||||
if (data && data.length) {
|
||||
const rowToExaminate = data[0];
|
||||
if (data?.length) {
|
||||
const rowToExamine = data[0];
|
||||
|
||||
if (typeof rowToExaminate === 'object') {
|
||||
for (const key in rowToExaminate) {
|
||||
if (rowToExaminate.hasOwnProperty(key)) {
|
||||
if (typeof rowToExamine === 'object') {
|
||||
for (const key in rowToExamine) {
|
||||
if (rowToExamine.hasOwnProperty(key)) {
|
||||
schema.push({
|
||||
type: 'text',
|
||||
key,
|
||||
@@ -51,7 +50,6 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
@@ -99,7 +97,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
this._columns = columns || [];
|
||||
}
|
||||
|
||||
getValue(row: DataRow, col: DataColumn, resolver?: (_row: DataRow, _col: DataColumn) => any ): any {
|
||||
getValue(row: DataRow, col: DataColumn, resolver?: (_row: DataRow, _col: DataColumn) => any): any {
|
||||
if (!row) {
|
||||
throw new Error('Row not found');
|
||||
}
|
||||
@@ -111,14 +109,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
return resolver(row, col);
|
||||
}
|
||||
|
||||
const value = row.getValue(col.key);
|
||||
|
||||
if (col.type === 'icon') {
|
||||
const icon = row.getValue(col.key);
|
||||
return icon;
|
||||
}
|
||||
|
||||
return value;
|
||||
return row.getValue(col.key);
|
||||
}
|
||||
|
||||
getSorting(): DataSorting {
|
||||
@@ -128,7 +119,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
setSorting(sorting: DataSorting): void {
|
||||
this._sorting = sorting;
|
||||
|
||||
if (sorting && sorting.key) {
|
||||
if (sorting?.key) {
|
||||
this._rows.sort((a: DataRow, b: DataRow) => {
|
||||
let left = a.getValue(sorting.key);
|
||||
let right = b.getValue(sorting.key);
|
||||
@@ -137,20 +128,18 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
return sorting.direction === 'asc' ? left - right : right - left;
|
||||
} else {
|
||||
if (left) {
|
||||
left = (left instanceof Date) ? left.valueOf().toString() : left.toString();
|
||||
left = left instanceof Date ? left.valueOf().toString() : left.toString();
|
||||
} else {
|
||||
left = '';
|
||||
}
|
||||
|
||||
if (right) {
|
||||
right = (right instanceof Date) ? right.valueOf().toString() : right.toString();
|
||||
right = right instanceof Date ? right.valueOf().toString() : right.toString();
|
||||
} else {
|
||||
right = '';
|
||||
}
|
||||
|
||||
return sorting.direction === 'asc'
|
||||
? left.localeCompare(right)
|
||||
: right.localeCompare(left);
|
||||
return sorting.direction === 'asc' ? left.localeCompare(right) : right.localeCompare(left);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -21,223 +21,185 @@ import { map, take, share, filter, pairwise, mergeMap, takeUntil } from 'rxjs/op
|
||||
import { OnInit, Output, NgZone, OnDestroy, Directive, Renderer2, ElementRef, EventEmitter, Input } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[adf-resizable]',
|
||||
exportAs: 'adf-resizable'
|
||||
selector: '[adf-resizable]',
|
||||
exportAs: 'adf-resizable'
|
||||
})
|
||||
export class ResizableDirective implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Emitted when the mouse is pressed and a resize event is about to begin.
|
||||
*/
|
||||
@Output() resizeStart = new EventEmitter<ResizeEvent>();
|
||||
/**
|
||||
* Emitted when the mouse is pressed and a resize event is about to begin.
|
||||
*/
|
||||
@Output() resizeStart = new EventEmitter<ResizeEvent>();
|
||||
|
||||
/**
|
||||
* Emitted when the mouse is dragged after a resize event has started.
|
||||
*/
|
||||
@Output() resizing = new EventEmitter<ResizeEvent>();
|
||||
/**
|
||||
* Emitted when the mouse is dragged after a resize event has started.
|
||||
*/
|
||||
@Output() resizing = new EventEmitter<ResizeEvent>();
|
||||
|
||||
/**
|
||||
* Emitted when the mouse is released after a resize event.
|
||||
*/
|
||||
@Output() resizeEnd = new EventEmitter<ResizeEvent>();
|
||||
/**
|
||||
* Emitted when the mouse is released after a resize event.
|
||||
*/
|
||||
@Output() resizeEnd = new EventEmitter<ResizeEvent>();
|
||||
|
||||
/**
|
||||
* This is to cover sum of the left and right padding between resize handler and its parent.
|
||||
*/
|
||||
@Input() coverPadding = 0;
|
||||
/**
|
||||
* This is to cover sum of the left and right padding between resize handler and its parent.
|
||||
*/
|
||||
@Input() coverPadding = 0;
|
||||
|
||||
mouseup = new Subject<IResizeMouseEvent>();
|
||||
mouseup = new Subject<IResizeMouseEvent>();
|
||||
|
||||
mousedown = new Subject<IResizeMouseEvent>();
|
||||
mousedown = new Subject<IResizeMouseEvent>();
|
||||
|
||||
mousemove = new Subject<IResizeMouseEvent>();
|
||||
mousemove = new Subject<IResizeMouseEvent>();
|
||||
|
||||
private pointerDown: Observable<IResizeMouseEvent>;
|
||||
private pointerDown: Observable<IResizeMouseEvent>;
|
||||
|
||||
private pointerMove: Observable<IResizeMouseEvent>;
|
||||
private pointerMove: Observable<IResizeMouseEvent>;
|
||||
|
||||
private pointerUp: Observable<IResizeMouseEvent>;
|
||||
private pointerUp: Observable<IResizeMouseEvent>;
|
||||
|
||||
private startingRect: BoundingRectangle;
|
||||
private startingRect: BoundingRectangle;
|
||||
|
||||
private currentRect: BoundingRectangle;
|
||||
private currentRect: BoundingRectangle;
|
||||
|
||||
private unlistenMouseDown: () => void;
|
||||
private unlistenMouseDown?: () => void;
|
||||
private unlistenMouseMove?: () => void;
|
||||
private unlistenMouseUp?: () => void;
|
||||
|
||||
private unlistenMouseMove: () => void;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
private unlistenMouseUp: () => void;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private readonly renderer: Renderer2,
|
||||
private readonly element: ElementRef<HTMLElement>,
|
||||
private readonly zone: NgZone
|
||||
) {
|
||||
|
||||
this.pointerDown = new Observable(
|
||||
(observer: Observer<IResizeMouseEvent>) => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseDown = renderer.listen(
|
||||
'document',
|
||||
'mousedown',
|
||||
(event: MouseEvent) => {
|
||||
observer.next(event);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
).pipe(share());
|
||||
|
||||
this.pointerMove = new Observable(
|
||||
(observer: Observer<IResizeMouseEvent>) => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseMove = renderer.listen(
|
||||
'document',
|
||||
'mousemove',
|
||||
(event: MouseEvent) => {
|
||||
observer.next(event);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
).pipe(share());
|
||||
|
||||
this.pointerUp = new Observable(
|
||||
(observer: Observer<IResizeMouseEvent>) => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseUp = renderer.listen(
|
||||
'document',
|
||||
'mouseup',
|
||||
(event: MouseEvent) => {
|
||||
observer.next(event);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
).pipe(share());
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
const mousedown$: Observable<IResizeMouseEvent> = merge(this.pointerDown, this.mousedown);
|
||||
|
||||
const mousemove$: Observable<IResizeMouseEvent> = merge(this.pointerMove, this.mousemove);
|
||||
|
||||
const mouseup$: Observable<IResizeMouseEvent> = merge(this.pointerUp, this.mouseup);
|
||||
|
||||
const mousedrag: Observable<IResizeMouseEvent | ICoordinateX> = mousedown$
|
||||
.pipe(
|
||||
mergeMap(({ clientX = 0 }) => merge(
|
||||
mousemove$.pipe(take(1)).pipe(map((coords) => [, coords])),
|
||||
mousemove$.pipe(pairwise())
|
||||
)
|
||||
.pipe(
|
||||
map(([previousCoords = {}, newCoords = {}]) =>
|
||||
[
|
||||
{ clientX: previousCoords.clientX - clientX },
|
||||
{ clientX: newCoords.clientX - clientX }
|
||||
]
|
||||
)
|
||||
)
|
||||
.pipe(
|
||||
filter(([previousCoords = {}, newCoords = {}]) =>
|
||||
Math.ceil(previousCoords.clientX) !== Math.ceil(newCoords.clientX))
|
||||
)
|
||||
.pipe(
|
||||
map(([, newCoords]) =>
|
||||
({
|
||||
clientX: Math.round(newCoords.clientX)
|
||||
}))
|
||||
)
|
||||
.pipe(takeUntil(merge(mouseup$, mousedown$)))
|
||||
)
|
||||
)
|
||||
.pipe(filter(() => !!this.currentRect));
|
||||
|
||||
mousedrag
|
||||
.pipe(
|
||||
map(({ clientX }) => this.getNewBoundingRectangle(this.startingRect, clientX + this.coverPadding))
|
||||
)
|
||||
.subscribe((rectangle: BoundingRectangle) => {
|
||||
if (this.resizing.observers.length > 0) {
|
||||
this.zone.run(() => {
|
||||
this.resizing.emit({ rectangle });
|
||||
});
|
||||
}
|
||||
this.currentRect = rectangle;
|
||||
});
|
||||
|
||||
mousedown$
|
||||
.pipe(
|
||||
map(({ resize = false }) => resize),
|
||||
filter((resize) => resize),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe(() => {
|
||||
const startingRect: BoundingRectangle = this.getElementRect(this.element);
|
||||
|
||||
this.startingRect = startingRect;
|
||||
this.currentRect = startingRect;
|
||||
|
||||
this.renderer.setStyle(document.body, 'cursor', 'col-resize');
|
||||
if (this.resizeStart.observers.length > 0) {
|
||||
this.zone.run(() => {
|
||||
this.resizeStart.emit({
|
||||
rectangle: this.getNewBoundingRectangle(this.startingRect, 0)
|
||||
constructor(private readonly renderer: Renderer2, private readonly element: ElementRef<HTMLElement>, private readonly zone: NgZone) {
|
||||
this.pointerDown = new Observable((observer: Observer<IResizeMouseEvent>) => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseDown = renderer.listen('document', 'mousedown', (event: MouseEvent) => {
|
||||
observer.next(event);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}).pipe(share());
|
||||
|
||||
mouseup$.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
||||
if (this.currentRect) {
|
||||
this.renderer.setStyle(document.body, 'cursor', '');
|
||||
if (this.resizeEnd.observers.length > 0) {
|
||||
this.zone.run(() => {
|
||||
this.resizeEnd.emit({ rectangle: this.currentRect });
|
||||
});
|
||||
}
|
||||
this.startingRect = null;
|
||||
this.currentRect = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.pointerMove = new Observable((observer: Observer<IResizeMouseEvent>) => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseMove = renderer.listen('document', 'mousemove', (event: MouseEvent) => {
|
||||
observer.next(event);
|
||||
});
|
||||
});
|
||||
}).pipe(share());
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.mousedown.complete();
|
||||
this.mousemove.complete();
|
||||
this.mouseup.complete();
|
||||
this.unlistenMouseDown && this.unlistenMouseDown();
|
||||
this.unlistenMouseMove && this.unlistenMouseMove();
|
||||
this.unlistenMouseUp && this.unlistenMouseUp();
|
||||
this.destroy$.next();
|
||||
}
|
||||
this.pointerUp = new Observable((observer: Observer<IResizeMouseEvent>) => {
|
||||
zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseUp = renderer.listen('document', 'mouseup', (event: MouseEvent) => {
|
||||
observer.next(event);
|
||||
});
|
||||
});
|
||||
}).pipe(share());
|
||||
}
|
||||
|
||||
private getNewBoundingRectangle({ top, bottom, left, right }: BoundingRectangle, clientX: number): BoundingRectangle {
|
||||
const updatedRight = Math.round(right + clientX);
|
||||
ngOnInit(): void {
|
||||
const mousedown$ = merge(this.pointerDown, this.mousedown);
|
||||
const mousemove$ = merge(this.pointerMove, this.mousemove);
|
||||
const mouseup$ = merge(this.pointerUp, this.mouseup);
|
||||
|
||||
return {
|
||||
top,
|
||||
left,
|
||||
bottom,
|
||||
right: updatedRight,
|
||||
width: updatedRight - left
|
||||
};
|
||||
}
|
||||
const mouseDrag: Observable<IResizeMouseEvent | ICoordinateX> = mousedown$
|
||||
.pipe(
|
||||
mergeMap(({ clientX = 0 }) =>
|
||||
merge(mousemove$.pipe(take(1)).pipe(map((coords) => [, coords])), mousemove$.pipe(pairwise()))
|
||||
.pipe(
|
||||
map(([previousCoords = {}, newCoords = {}]) => [
|
||||
{ clientX: previousCoords.clientX - clientX },
|
||||
{ clientX: newCoords.clientX - clientX }
|
||||
])
|
||||
)
|
||||
.pipe(filter(([previousCoords = {}, newCoords = {}]) => Math.ceil(previousCoords.clientX) !== Math.ceil(newCoords.clientX)))
|
||||
.pipe(
|
||||
map(([, newCoords]) => ({
|
||||
clientX: Math.round(newCoords.clientX)
|
||||
}))
|
||||
)
|
||||
.pipe(takeUntil(merge(mouseup$, mousedown$)))
|
||||
)
|
||||
)
|
||||
.pipe(filter(() => !!this.currentRect));
|
||||
|
||||
private getElementRect({ nativeElement }: ElementRef): BoundingRectangle {
|
||||
mouseDrag
|
||||
.pipe(map(({ clientX }) => this.getNewBoundingRectangle(this.startingRect, clientX + this.coverPadding)))
|
||||
.subscribe((rectangle: BoundingRectangle) => {
|
||||
if (this.resizing.observers.length > 0) {
|
||||
this.zone.run(() => {
|
||||
this.resizing.emit({ rectangle });
|
||||
});
|
||||
}
|
||||
this.currentRect = rectangle;
|
||||
});
|
||||
|
||||
const { height = 0, width = 0, top = 0, bottom = 0, right = 0, left = 0 }: BoundingRectangle = nativeElement.getBoundingClientRect();
|
||||
mousedown$
|
||||
.pipe(
|
||||
map(({ resize = false }) => resize),
|
||||
filter((resize) => resize),
|
||||
takeUntil(this.destroy$)
|
||||
)
|
||||
.subscribe(() => {
|
||||
const startingRect: BoundingRectangle = this.getElementRect(this.element);
|
||||
|
||||
return {
|
||||
top,
|
||||
left,
|
||||
right,
|
||||
width,
|
||||
height,
|
||||
bottom,
|
||||
scrollTop: nativeElement.scrollTop,
|
||||
scrollLeft: nativeElement.scrollLeft
|
||||
};
|
||||
}
|
||||
this.startingRect = startingRect;
|
||||
this.currentRect = startingRect;
|
||||
|
||||
this.renderer.setStyle(document.body, 'cursor', 'col-resize');
|
||||
if (this.resizeStart.observers.length > 0) {
|
||||
this.zone.run(() => {
|
||||
this.resizeStart.emit({
|
||||
rectangle: this.getNewBoundingRectangle(this.startingRect, 0)
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
mouseup$.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
||||
if (this.currentRect) {
|
||||
this.renderer.setStyle(document.body, 'cursor', '');
|
||||
if (this.resizeEnd.observers.length > 0) {
|
||||
this.zone.run(() => {
|
||||
this.resizeEnd.emit({ rectangle: this.currentRect });
|
||||
});
|
||||
}
|
||||
this.startingRect = null;
|
||||
this.currentRect = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.mousedown.complete();
|
||||
this.mousemove.complete();
|
||||
this.mouseup.complete();
|
||||
this.unlistenMouseDown?.();
|
||||
this.unlistenMouseMove?.();
|
||||
this.unlistenMouseUp?.();
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
private getNewBoundingRectangle({ top, bottom, left, right }: BoundingRectangle, clientX: number): BoundingRectangle {
|
||||
const updatedRight = Math.round(right + clientX);
|
||||
|
||||
return {
|
||||
top,
|
||||
left,
|
||||
bottom,
|
||||
right: updatedRight,
|
||||
width: updatedRight - left
|
||||
};
|
||||
}
|
||||
|
||||
private getElementRect({ nativeElement }: ElementRef): BoundingRectangle {
|
||||
const { height = 0, width = 0, top = 0, bottom = 0, right = 0, left = 0 }: BoundingRectangle = nativeElement.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
top,
|
||||
left,
|
||||
right,
|
||||
width,
|
||||
height,
|
||||
bottom,
|
||||
scrollTop: nativeElement.scrollTop,
|
||||
scrollLeft: nativeElement.scrollLeft
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -20,80 +20,62 @@ import { ResizableDirective } from './resizable.directive';
|
||||
import { Input, OnInit, Directive, Renderer2, ElementRef, OnDestroy, NgZone } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[adf-resize-handle]'
|
||||
selector: '[adf-resize-handle]'
|
||||
})
|
||||
export class ResizeHandleDirective implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Reference to ResizableDirective
|
||||
*/
|
||||
@Input() resizableContainer: ResizableDirective;
|
||||
/**
|
||||
* Reference to ResizableDirective
|
||||
*/
|
||||
@Input() resizableContainer: ResizableDirective;
|
||||
|
||||
private unlistenMouseDown: () => void;
|
||||
private unlistenMouseDown?: () => void;
|
||||
private unlistenMouseMove?: () => void;
|
||||
private unlistenMouseUp?: () => void;
|
||||
|
||||
private unlistenMouseMove: () => void;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
private unlistenMouseUp: () => void;
|
||||
constructor(private readonly renderer: Renderer2, private readonly element: ElementRef, private readonly zone: NgZone) {}
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private readonly renderer: Renderer2,
|
||||
private readonly element: ElementRef,
|
||||
private readonly zone: NgZone
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseDown = this.renderer.listen(
|
||||
this.element.nativeElement,
|
||||
'mousedown',
|
||||
(mouseDownEvent: MouseEvent) => {
|
||||
this.onMousedown(mouseDownEvent);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.unlistenMouseDown && this.unlistenMouseDown();
|
||||
this.unlistenMouseMove && this.unlistenMouseMove();
|
||||
this.unlistenMouseUp && this.unlistenMouseUp();
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
private onMousedown(event: MouseEvent): void {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
ngOnInit(): void {
|
||||
this.zone.runOutsideAngular(() => {
|
||||
this.unlistenMouseDown = this.renderer.listen(this.element.nativeElement, 'mousedown', (mouseDownEvent: MouseEvent) => {
|
||||
this.onMousedown(mouseDownEvent);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.unlistenMouseMove) {
|
||||
this.unlistenMouseMove = this.renderer.listen(
|
||||
this.element.nativeElement,
|
||||
'mousemove',
|
||||
(mouseMoveEvent: MouseEvent) => {
|
||||
this.onMousemove(mouseMoveEvent);
|
||||
}
|
||||
);
|
||||
ngOnDestroy(): void {
|
||||
this.unlistenMouseDown?.();
|
||||
this.unlistenMouseMove?.();
|
||||
this.unlistenMouseUp?.();
|
||||
this.destroy$.next();
|
||||
}
|
||||
|
||||
this.unlistenMouseUp = this.renderer.listen(
|
||||
'document',
|
||||
'mouseup',
|
||||
(mouseUpEvent: MouseEvent) => {
|
||||
this.onMouseup(mouseUpEvent);
|
||||
}
|
||||
);
|
||||
private onMousedown(event: MouseEvent): void {
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this.resizableContainer.mousedown.next({ ...event, resize: true });
|
||||
}
|
||||
if (!this.unlistenMouseMove) {
|
||||
this.unlistenMouseMove = this.renderer.listen(this.element.nativeElement, 'mousemove', (mouseMoveEvent: MouseEvent) => {
|
||||
this.onMousemove(mouseMoveEvent);
|
||||
});
|
||||
}
|
||||
|
||||
private onMouseup(event: MouseEvent): void {
|
||||
this.unlistenMouseMove && this.unlistenMouseMove();
|
||||
this.unlistenMouseUp();
|
||||
this.resizableContainer.mouseup.next(event);
|
||||
}
|
||||
this.unlistenMouseUp = this.renderer.listen('document', 'mouseup', (mouseUpEvent: MouseEvent) => {
|
||||
this.onMouseup(mouseUpEvent);
|
||||
});
|
||||
|
||||
private onMousemove(event: MouseEvent): void {
|
||||
this.resizableContainer.mousemove.next(event);
|
||||
}
|
||||
this.resizableContainer.mousedown.next({ ...event, resize: true });
|
||||
}
|
||||
|
||||
private onMouseup(event: MouseEvent): void {
|
||||
this.unlistenMouseMove?.();
|
||||
this.unlistenMouseUp();
|
||||
this.resizableContainer.mouseup.next(event);
|
||||
}
|
||||
|
||||
private onMousemove(event: MouseEvent): void {
|
||||
this.resizableContainer.mousemove.next(event);
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@ import { FileInfo, FileUtils } from '../common/utils/file-utils';
|
||||
selector: '[adf-upload]'
|
||||
})
|
||||
export class UploadDirective implements OnInit, OnDestroy {
|
||||
|
||||
/** Enables/disables uploading. */
|
||||
@Input('adf-upload')
|
||||
enabled: boolean = true;
|
||||
@@ -135,7 +134,6 @@ export class UploadDirective implements OnInit, OnDestroy {
|
||||
|
||||
onDrop(event: Event) {
|
||||
if (this.isDropMode()) {
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
@@ -147,7 +145,6 @@ export class UploadDirective implements OnInit, OnDestroy {
|
||||
this.getFilesDropped(dataTransfer).then((files) => {
|
||||
this.onUploadFiles(files);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -181,10 +178,10 @@ export class UploadDirective implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
getDataTransfer(event: Event | any): DataTransfer {
|
||||
if (event && event.dataTransfer) {
|
||||
if (event?.dataTransfer) {
|
||||
return event.dataTransfer;
|
||||
}
|
||||
if (event && event.originalEvent && event.originalEvent.dataTransfer) {
|
||||
if (event?.originalEvent?.dataTransfer) {
|
||||
return event.originalEvent.dataTransfer;
|
||||
}
|
||||
return null;
|
||||
@@ -207,34 +204,38 @@ export class UploadDirective implements OnInit, OnDestroy {
|
||||
const item = items[i].webkitGetAsEntry();
|
||||
if (item) {
|
||||
if (item.isFile) {
|
||||
iterations.push(Promise.resolve({
|
||||
entry: item,
|
||||
file: items[i].getAsFile(),
|
||||
relativeFolder: '/'
|
||||
}));
|
||||
iterations.push(
|
||||
Promise.resolve({
|
||||
entry: item,
|
||||
file: items[i].getAsFile(),
|
||||
relativeFolder: '/'
|
||||
})
|
||||
);
|
||||
} else if (item.isDirectory) {
|
||||
iterations.push(new Promise((resolveFolder) => {
|
||||
FileUtils.flatten(item).then((files) => resolveFolder(files));
|
||||
}));
|
||||
iterations.push(
|
||||
new Promise((resolveFolder) => {
|
||||
FileUtils.flatten(item).then((files) => resolveFolder(files));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iterations.push(Promise.resolve({
|
||||
entry: null,
|
||||
file: items[i].getAsFile(),
|
||||
relativeFolder: '/'
|
||||
}));
|
||||
iterations.push(
|
||||
Promise.resolve({
|
||||
entry: null,
|
||||
file: items[i].getAsFile(),
|
||||
relativeFolder: '/'
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// safari or FF
|
||||
const files = FileUtils
|
||||
.toFileArray(dataTransfer.files)
|
||||
.map((file) => ({
|
||||
entry: null,
|
||||
file,
|
||||
relativeFolder: '/'
|
||||
}));
|
||||
const files = FileUtils.toFileArray(dataTransfer.files).map((file) => ({
|
||||
entry: null,
|
||||
file,
|
||||
relativeFolder: '/'
|
||||
}));
|
||||
|
||||
iterations.push(Promise.resolve(files));
|
||||
}
|
||||
@@ -255,11 +256,13 @@ export class UploadDirective implements OnInit, OnDestroy {
|
||||
if (this.isClickMode()) {
|
||||
const input = event.currentTarget;
|
||||
const files = FileUtils.toFileArray(input.files);
|
||||
this.onUploadFiles(files.map((file) => ({
|
||||
entry: null,
|
||||
file,
|
||||
relativeFolder: '/'
|
||||
})));
|
||||
this.onUploadFiles(
|
||||
files.map((file) => ({
|
||||
entry: null,
|
||||
file,
|
||||
relativeFolder: '/'
|
||||
}))
|
||||
);
|
||||
event.target.value = '';
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@ import { ThemePalette } from '@angular/material/core';
|
||||
@Directive()
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export abstract class FormBaseComponent {
|
||||
|
||||
static SAVE_OUTCOME_ID: string = '$save';
|
||||
static COMPLETE_OUTCOME_ID: string = '$complete';
|
||||
static START_PROCESS_OUTCOME_ID: string = '$startProcess';
|
||||
@@ -137,7 +136,7 @@ export abstract class FormBaseComponent {
|
||||
}
|
||||
|
||||
isOutcomeButtonVisible(outcome: FormOutcomeModel, isFormReadOnly: boolean): boolean {
|
||||
if (outcome && outcome.name) {
|
||||
if (outcome?.name) {
|
||||
if (outcome.name === FormOutcomeModel.COMPLETE_ACTION) {
|
||||
return this.showCompleteButton;
|
||||
}
|
||||
@@ -162,7 +161,6 @@ export abstract class FormBaseComponent {
|
||||
*/
|
||||
onOutcomeClicked(outcome: FormOutcomeModel): boolean {
|
||||
if (!this.readOnly && outcome && this.form) {
|
||||
|
||||
if (!this.onExecuteOutcome(outcome)) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -17,7 +17,8 @@
|
||||
|
||||
import {
|
||||
Compiler,
|
||||
Component, ComponentFactory,
|
||||
Component,
|
||||
ComponentFactory,
|
||||
ComponentFactoryResolver,
|
||||
ComponentRef,
|
||||
Input,
|
||||
@@ -39,19 +40,20 @@ declare const adf: any;
|
||||
@Component({
|
||||
selector: 'adf-form-field',
|
||||
template: `
|
||||
<div [id]="'field-'+field?.id+'-container'"
|
||||
<div
|
||||
[id]="'field-' + field?.id + '-container'"
|
||||
[style.visibility]="!field?.isVisible ? 'hidden' : 'visible'"
|
||||
[style.display]="!field?.isVisible ? 'none' : 'block'"
|
||||
[class.adf-focus]="focus"
|
||||
(focusin)="focusToggle()"
|
||||
(focusout)="focusToggle()">
|
||||
(focusout)="focusToggle()"
|
||||
>
|
||||
<div #container></div>
|
||||
</div>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FormFieldComponent implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild('container', { read: ViewContainerRef, static: true })
|
||||
container: ViewContainerRef;
|
||||
|
||||
@@ -67,11 +69,12 @@ export class FormFieldComponent implements OnInit, OnDestroy {
|
||||
|
||||
focus: boolean = false;
|
||||
|
||||
constructor(private formRenderingService: FormRenderingService,
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private compiler: Compiler) {
|
||||
}
|
||||
constructor(
|
||||
private formRenderingService: FormRenderingService,
|
||||
private componentFactoryResolver: ComponentFactoryResolver,
|
||||
private visibilityService: WidgetVisibilityService,
|
||||
private compiler: Compiler
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
const w: any = window;
|
||||
@@ -114,9 +117,9 @@ export class FormFieldComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private getField(): FormFieldModel {
|
||||
if (this.field && this.field.params) {
|
||||
if (this.field?.params) {
|
||||
const wrappedField = this.field.params.field;
|
||||
if (wrappedField && wrappedField.type) {
|
||||
if (wrappedField?.type) {
|
||||
return wrappedField as FormFieldModel;
|
||||
}
|
||||
}
|
||||
@@ -124,7 +127,7 @@ export class FormFieldComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private hasController(type: string): boolean {
|
||||
return (adf && adf.components && adf.components[type]);
|
||||
return adf?.components?.[type];
|
||||
}
|
||||
|
||||
private getComponentFactorySync(type: string, template: string): ComponentFactory<any> {
|
||||
|
@@ -35,7 +35,6 @@ import { FormService } from '../services/form.service';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
|
||||
/** Toggle debug options. */
|
||||
@Input()
|
||||
showDebugButton: boolean = false;
|
||||
@@ -47,8 +46,7 @@ export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
|
||||
fields: FormFieldModel[];
|
||||
|
||||
constructor(public formService: FormService, private formRulesManager: FormRulesManager<T>) {
|
||||
}
|
||||
constructor(public formService: FormService, private formRulesManager: FormRulesManager<T>) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.formRulesManager.initialize(this.formDefinition);
|
||||
@@ -67,15 +65,15 @@ export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
onExpanderClicked(content: ContainerModel) {
|
||||
if (content && content.isCollapsible()) {
|
||||
if (content?.isCollapsible()) {
|
||||
content.isExpanded = !content.isExpanded;
|
||||
}
|
||||
}
|
||||
|
||||
getNumberOfColumns(content: ContainerModel): number {
|
||||
return (content.json?.numberOfColumns || 1) > (content.columns?.length || 1) ?
|
||||
(content.json?.numberOfColumns || 1) :
|
||||
(content.columns?.length || 1);
|
||||
return (content.json?.numberOfColumns || 1) > (content.columns?.length || 1)
|
||||
? content.json?.numberOfColumns || 1
|
||||
: content.columns?.length || 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +104,8 @@ export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
let maxFieldSize = 0;
|
||||
if (content?.columns?.length > 0) {
|
||||
maxFieldSize = content?.columns?.reduce((prevColumn, currentColumn) =>
|
||||
currentColumn.fields.length > prevColumn?.fields?.length ? currentColumn : prevColumn)?.fields?.length;
|
||||
currentColumn.fields.length > prevColumn?.fields?.length ? currentColumn : prevColumn
|
||||
)?.fields?.length;
|
||||
}
|
||||
return maxFieldSize;
|
||||
}
|
||||
@@ -120,5 +119,4 @@ export class FormRendererComponent<T> implements OnChanges, OnDestroy {
|
||||
const colspan = container ? container.field.colspan : 1;
|
||||
return (100 / container.field.numberOfColumns) * colspan + '';
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation, InjectionToken, Inject, Optional } from '@angular/core';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
@@ -45,7 +45,6 @@ export const ADF_AMOUNT_SETTINGS = new InjectionToken<AmountWidgetSettings>('adf
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class AmountWidgetComponent extends WidgetComponent implements OnInit {
|
||||
|
||||
static DEFAULT_CURRENCY: string = '$';
|
||||
private showPlaceholder = true;
|
||||
|
||||
@@ -71,9 +70,8 @@ export class AmountWidgetComponent extends WidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (this.field.readOnly) {
|
||||
this.showPlaceholder = this.settings && this.settings.showReadonlyPlaceholder;
|
||||
this.showPlaceholder = this.settings?.showReadonlyPlaceholder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,10 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
export class ContentLinkModel {
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
export class ContentLinkModel {
|
||||
contentAvailable: boolean;
|
||||
created: Date;
|
||||
createdBy: any;
|
||||
@@ -36,18 +35,18 @@
|
||||
thumbnailStatus: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.contentAvailable = obj && obj.contentAvailable;
|
||||
this.created = obj && obj.created;
|
||||
this.createdBy = obj && obj.createdBy || {};
|
||||
this.id = obj && obj.id;
|
||||
this.link = obj && obj.link;
|
||||
this.mimeType = obj && obj.mimeType;
|
||||
this.name = obj && obj.name;
|
||||
this.previewStatus = obj && obj.previewStatus;
|
||||
this.relatedContent = obj && obj.relatedContent;
|
||||
this.simpleType = obj && obj.simpleType;
|
||||
this.thumbnailStatus = obj && obj.thumbnailStatus;
|
||||
this.nodeId = obj && obj.nodeId;
|
||||
this.contentAvailable = obj?.contentAvailable;
|
||||
this.created = obj?.created;
|
||||
this.createdBy = obj?.createdBy || {};
|
||||
this.id = obj?.id;
|
||||
this.link = obj?.link;
|
||||
this.mimeType = obj?.mimeType;
|
||||
this.name = obj?.name;
|
||||
this.previewStatus = obj?.previewStatus;
|
||||
this.relatedContent = obj?.relatedContent;
|
||||
this.simpleType = obj?.simpleType;
|
||||
this.thumbnailStatus = obj?.thumbnailStatus;
|
||||
this.nodeId = obj?.nodeId;
|
||||
}
|
||||
|
||||
hasPreviewStatus(): boolean {
|
||||
|
@@ -18,12 +18,11 @@
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
export class ErrorMessageModel {
|
||||
|
||||
message: string = '';
|
||||
attributes: Map<string, string> = null;
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.message = obj && obj.message ? obj.message : '';
|
||||
this.message = obj?.message || '';
|
||||
this.attributes = new Map();
|
||||
}
|
||||
|
||||
|
@@ -32,7 +32,6 @@ import { DataColumn } from '../../../../datatable/data/data-column.model';
|
||||
|
||||
// Maps to FormFieldRepresentation
|
||||
export class FormFieldModel extends FormWidgetModel {
|
||||
|
||||
private _value: string;
|
||||
private _readOnly: boolean = false;
|
||||
private _isValid: boolean = true;
|
||||
@@ -105,7 +104,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
}
|
||||
|
||||
get readOnly(): boolean {
|
||||
if (this.form && this.form.readOnly) {
|
||||
if (this.form?.readOnly) {
|
||||
return true;
|
||||
}
|
||||
return this._readOnly;
|
||||
@@ -206,7 +205,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
}
|
||||
|
||||
if (FormFieldTypes.isReadOnlyType(this.type)) {
|
||||
if (this.params && this.params.field) {
|
||||
if (this.params?.field) {
|
||||
this.setValueForReadonlyType(form);
|
||||
}
|
||||
}
|
||||
@@ -241,9 +240,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
|
||||
private getDefaultDateFormat(jsonField: any): string {
|
||||
let originalType = jsonField.type;
|
||||
if (FormFieldTypes.isReadOnlyType(jsonField.type) &&
|
||||
jsonField.params &&
|
||||
jsonField.params.field) {
|
||||
if (FormFieldTypes.isReadOnlyType(jsonField.type) && jsonField.params && jsonField.params.field) {
|
||||
originalType = jsonField.params.field.type;
|
||||
}
|
||||
return originalType === FormFieldTypes.DATETIME ? this.defaultDateTimeFormat : this.defaultDateFormat;
|
||||
@@ -301,7 +298,6 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
but saving back as object: { id: <id>, name: <name> }
|
||||
*/
|
||||
if (json.type === FormFieldTypes.DROPDOWN) {
|
||||
|
||||
if (json.options) {
|
||||
if (json.hasEmptyValue) {
|
||||
const emptyOption = json.options[0];
|
||||
@@ -328,8 +324,9 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
// Activiti has a bug with default radio button value where initial selection passed as `name` value
|
||||
// so try resolving current one with a fallback to first entry via name or id
|
||||
// TODO: needs to be reported and fixed at Activiti side
|
||||
const entry: FormFieldOption[] = this.options.filter((opt) =>
|
||||
opt.id === value || opt.name === value || (value && (opt.id === value.id || opt.name === value.name)));
|
||||
const entry: FormFieldOption[] = this.options.filter(
|
||||
(opt) => opt.id === value || opt.name === value || (value && (opt.id === value.id || opt.name === value.name))
|
||||
);
|
||||
if (entry.length > 0) {
|
||||
value = entry[0].id;
|
||||
}
|
||||
@@ -347,7 +344,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
} else {
|
||||
dateValue = this.isDateTimeField(json) ? moment.utc(value, 'YYYY-MM-DD hh:mm A') : moment.utc(value.split('T')[0], 'YYYY-M-D');
|
||||
}
|
||||
if (dateValue && dateValue.isValid()) {
|
||||
if (dateValue?.isValid()) {
|
||||
value = dateValue.utc().format(this.dateDisplayFormat);
|
||||
}
|
||||
}
|
||||
@@ -367,7 +364,6 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
|
||||
switch (this.type) {
|
||||
case FormFieldTypes.DROPDOWN:
|
||||
|
||||
if (!this.value) {
|
||||
this.form.values[this.id] = null;
|
||||
break;
|
||||
@@ -422,7 +418,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
}
|
||||
|
||||
const dateValue = moment(this.value, this.dateDisplayFormat, true);
|
||||
if (dateValue && dateValue.isValid()) {
|
||||
if (dateValue?.isValid()) {
|
||||
this.form.values[this.id] = `${dateValue.format('YYYY-MM-DD')}T00:00:00.000Z`;
|
||||
} else {
|
||||
this.form.values[this.id] = null;
|
||||
@@ -435,7 +431,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
}
|
||||
|
||||
const dateTimeValue = moment.utc(this.value, this.dateDisplayFormat, true);
|
||||
if (dateTimeValue && dateTimeValue.isValid()) {
|
||||
if (dateTimeValue?.isValid()) {
|
||||
/* cspell:disable-next-line */
|
||||
this.form.values[this.id] = `${dateTimeValue.utc().format('YYYY-MM-DDTHH:mm:ss')}.000Z`;
|
||||
} else {
|
||||
@@ -450,7 +446,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
this.form.values[this.id] = this.enableFractions ? parseFloat(this.value) : parseInt(this.value, 10);
|
||||
break;
|
||||
case FormFieldTypes.BOOLEAN:
|
||||
this.form.values[this.id] = (this.value !== null && this.value !== undefined) ? this.value : false;
|
||||
this.form.values[this.id] = this.value !== null && this.value !== undefined ? this.value : false;
|
||||
break;
|
||||
case FormFieldTypes.PEOPLE:
|
||||
this.form.values[this.id] = this.value ? this.value : null;
|
||||
@@ -482,28 +478,18 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
}
|
||||
|
||||
hasOptions() {
|
||||
return this.options && this.options.length > 0;
|
||||
return this.options?.length > 0;
|
||||
}
|
||||
|
||||
private isDateField(json: any) {
|
||||
return (json.params &&
|
||||
json.params.field &&
|
||||
json.params.field.type === FormFieldTypes.DATE) ||
|
||||
json.type === FormFieldTypes.DATE;
|
||||
return json.params?.field?.type === FormFieldTypes.DATE || json.type === FormFieldTypes.DATE;
|
||||
}
|
||||
|
||||
private isDateTimeField(json: any): boolean {
|
||||
return (json.params &&
|
||||
json.params.field &&
|
||||
json.params.field.type === FormFieldTypes.DATETIME) ||
|
||||
json.type === FormFieldTypes.DATETIME;
|
||||
return json.params?.field?.type === FormFieldTypes.DATETIME || json.type === FormFieldTypes.DATETIME;
|
||||
}
|
||||
|
||||
private isCheckboxField(json: any): boolean {
|
||||
return (json.params &&
|
||||
json.params.field &&
|
||||
json.params.field.type === FormFieldTypes.BOOLEAN) ||
|
||||
json.type === FormFieldTypes.BOOLEAN;
|
||||
return json.params?.field?.type === FormFieldTypes.BOOLEAN || json.type === FormFieldTypes.BOOLEAN;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -59,7 +59,6 @@ export interface FormRepresentationModel {
|
||||
};
|
||||
}
|
||||
export class FormModel implements ProcessFormModel {
|
||||
|
||||
static UNSET_TASK_NAME: string = 'Nameless task';
|
||||
static SAVE_OUTCOME: string = '$save';
|
||||
static COMPLETE_OUTCOME: string = '$complete';
|
||||
@@ -112,7 +111,7 @@ export class FormModel implements ProcessFormModel {
|
||||
this.className = json.className || '';
|
||||
this.variables = json.variables || json.formDefinition?.variables || [];
|
||||
this.processVariables = json.processVariables || [];
|
||||
this.enableFixedSpace = enableFixedSpace ? true : false;
|
||||
this.enableFixedSpace = enableFixedSpace;
|
||||
this.confirmMessage = json.confirmMessage || {};
|
||||
|
||||
this.tabs = (json.tabs || []).map((tabJson) => new TabModel(this, tabJson));
|
||||
@@ -161,7 +160,6 @@ export class FormModel implements ProcessFormModel {
|
||||
validateFormEvent.errorsField = errorsField;
|
||||
this.formService.validateForm.next(validateFormEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,7 +201,7 @@ export class FormModel implements ProcessFormModel {
|
||||
|
||||
if (json.fields) {
|
||||
fields = json.fields;
|
||||
} else if (json.formDefinition && json.formDefinition.fields) {
|
||||
} else if (json.formDefinition?.fields) {
|
||||
fields = json.formDefinition.fields;
|
||||
}
|
||||
|
||||
@@ -253,11 +251,7 @@ export class FormModel implements ProcessFormModel {
|
||||
*/
|
||||
getFormVariable(identifier: string): FormVariableModel {
|
||||
if (identifier) {
|
||||
return this.variables.find(
|
||||
variable =>
|
||||
variable.name === identifier ||
|
||||
variable.id === identifier
|
||||
);
|
||||
return this.variables.find((variable) => variable.name === identifier || variable.id === identifier);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -271,7 +265,7 @@ export class FormModel implements ProcessFormModel {
|
||||
getDefaultFormVariableValue(identifier: string): any {
|
||||
const variable = this.getFormVariable(identifier);
|
||||
|
||||
if (variable && variable.hasOwnProperty('value')) {
|
||||
if (variable?.hasOwnProperty('value')) {
|
||||
return this.parseValue(variable.type, variable.value);
|
||||
}
|
||||
|
||||
@@ -288,11 +282,9 @@ export class FormModel implements ProcessFormModel {
|
||||
getProcessVariableValue(name: string): any {
|
||||
let value;
|
||||
if (this.processVariables?.length) {
|
||||
const names = [`variables.${ name }`, name];
|
||||
const names = [`variables.${name}`, name];
|
||||
|
||||
const processVariable = this.processVariables.find(
|
||||
entry => names.includes(entry.name)
|
||||
);
|
||||
const processVariable = this.processVariables.find((entry) => names.includes(entry.name));
|
||||
|
||||
if (processVariable) {
|
||||
value = this.parseValue(processVariable.type, processVariable.value);
|
||||
@@ -310,13 +302,9 @@ export class FormModel implements ProcessFormModel {
|
||||
if (type && value) {
|
||||
switch (type) {
|
||||
case 'date':
|
||||
return value
|
||||
? `${value}T00:00:00.000Z`
|
||||
: undefined;
|
||||
return value ? `${value}T00:00:00.000Z` : undefined;
|
||||
case 'boolean':
|
||||
return typeof value === 'string'
|
||||
? JSON.parse(value)
|
||||
: value;
|
||||
return typeof value === 'string' ? JSON.parse(value) : value;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
@@ -356,7 +344,7 @@ export class FormModel implements ProcessFormModel {
|
||||
field.field.columns.forEach((column) => {
|
||||
formFieldModel.push(...column.fields);
|
||||
});
|
||||
}else{
|
||||
} else {
|
||||
formFieldModel.push(field);
|
||||
}
|
||||
}
|
||||
@@ -387,20 +375,14 @@ export class FormModel implements ProcessFormModel {
|
||||
isSystem: true
|
||||
});
|
||||
|
||||
const customOutcomes = (this.json.outcomes || []).map(
|
||||
(obj) => new FormOutcomeModel(this, obj)
|
||||
);
|
||||
const customOutcomes = (this.json.outcomes || []).map((obj) => new FormOutcomeModel(this, obj));
|
||||
|
||||
this.outcomes = [saveOutcome].concat(
|
||||
customOutcomes.length > 0
|
||||
? customOutcomes
|
||||
: [completeOutcome, startProcessOutcome]
|
||||
);
|
||||
this.outcomes = [saveOutcome].concat(customOutcomes.length > 0 ? customOutcomes : [completeOutcome, startProcessOutcome]);
|
||||
}
|
||||
}
|
||||
|
||||
addValuesNotPresent(valuesToSetIfNotPresent: FormValues) {
|
||||
this.fieldsCache.forEach(field => {
|
||||
this.fieldsCache.forEach((field) => {
|
||||
if (valuesToSetIfNotPresent[field.id] && (!this.values[field.id] || this.isValidDropDown(field.id))) {
|
||||
this.values[field.id] = valuesToSetIfNotPresent[field.id];
|
||||
field.json.value = this.values[field.id];
|
||||
@@ -423,11 +405,11 @@ export class FormModel implements ProcessFormModel {
|
||||
setNodeIdValueForViewersLinkedToUploadWidget(linkedUploadWidgetContentSelected: UploadWidgetContentLinkModel) {
|
||||
const linkedWidgetType = linkedUploadWidgetContentSelected?.options?.linkedWidgetType ?? 'uploadWidget';
|
||||
|
||||
const subscribedViewers = this.fieldsCache.filter(field =>
|
||||
linkedUploadWidgetContentSelected.uploadWidgetId === field.params[linkedWidgetType]
|
||||
const subscribedViewers = this.fieldsCache.filter(
|
||||
(field) => linkedUploadWidgetContentSelected.uploadWidgetId === field.params[linkedWidgetType]
|
||||
);
|
||||
|
||||
subscribedViewers.forEach(viewer => {
|
||||
subscribedViewers.forEach((viewer) => {
|
||||
this.values[viewer.id] = linkedUploadWidgetContentSelected.id;
|
||||
viewer.json.value = this.values[viewer.id];
|
||||
viewer.value = viewer.parseValue(viewer.json);
|
||||
|
@@ -29,11 +29,8 @@ import { WidgetComponent } from '../widget.component';
|
||||
styleUrls: ['./error.component.scss'],
|
||||
animations: [
|
||||
trigger('transitionMessages', [
|
||||
state('enter', style({opacity: 1, transform: 'translateY(0%)'})),
|
||||
transition('void => enter', [
|
||||
style({opacity: 0, transform: 'translateY(-100%)'}),
|
||||
animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')
|
||||
])
|
||||
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
|
||||
transition('void => enter', [style({ opacity: 0, transform: 'translateY(-100%)' }), animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')])
|
||||
])
|
||||
],
|
||||
host: {
|
||||
@@ -50,7 +47,6 @@ import { WidgetComponent } from '../widget.component';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ErrorWidgetComponent extends WidgetComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
error: ErrorMessageModel;
|
||||
|
||||
@@ -70,7 +66,7 @@ export class ErrorWidgetComponent extends WidgetComponent implements OnChanges {
|
||||
this.required = changes.required.currentValue;
|
||||
this.subscriptAnimationState = 'enter';
|
||||
}
|
||||
if (changes['error'] && changes['error'].currentValue) {
|
||||
if (changes['error']?.currentValue) {
|
||||
if (changes.error.currentValue.isActive()) {
|
||||
this.error = changes.error.currentValue;
|
||||
this.translateParameters = this.error.getAttributesAsJsonObj();
|
||||
|
@@ -15,18 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector, @typescript-eslint/no-use-before-define, @angular-eslint/no-input-rename */
|
||||
/* eslint-disable @angular-eslint/component-selector, @typescript-eslint/no-use-before-define, @angular-eslint/no-input-rename */
|
||||
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
forwardRef,
|
||||
HostListener,
|
||||
Input,
|
||||
OnChanges,
|
||||
Renderer2,
|
||||
SimpleChanges
|
||||
} from '@angular/core';
|
||||
import { Directive, ElementRef, forwardRef, HostListener, Input, OnChanges, Renderer2, SimpleChanges } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
|
||||
@@ -43,7 +34,6 @@ export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
|
||||
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
|
||||
})
|
||||
export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
|
||||
/** Object defining mask and "reversed" status. */
|
||||
@Input('textMask') inputMask: {
|
||||
mask: string;
|
||||
@@ -62,27 +52,30 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
private value;
|
||||
private invalidCharacters = [];
|
||||
|
||||
constructor(private el: ElementRef, private render: Renderer2) {
|
||||
}
|
||||
constructor(private el: ElementRef, private render: Renderer2) {}
|
||||
|
||||
_onChange = (_: any) => {
|
||||
};
|
||||
_onChange = (_: any) => {};
|
||||
|
||||
_onTouched = () => {
|
||||
};
|
||||
_onTouched = () => {};
|
||||
|
||||
@HostListener('input', ['$event'])
|
||||
@HostListener('keyup', ['$event']) onTextInput(event: KeyboardEvent) {
|
||||
if (this.inputMask && this.inputMask.mask) {
|
||||
this.maskValue(this.el.nativeElement.value, this.el.nativeElement.selectionStart,
|
||||
this.inputMask.mask, this.inputMask.isReversed, event.keyCode);
|
||||
@HostListener('keyup', ['$event'])
|
||||
onTextInput(event: KeyboardEvent) {
|
||||
if (this.inputMask?.mask) {
|
||||
this.maskValue(
|
||||
this.el.nativeElement.value,
|
||||
this.el.nativeElement.selectionStart,
|
||||
this.inputMask.mask,
|
||||
this.inputMask.isReversed,
|
||||
event.keyCode
|
||||
);
|
||||
} else {
|
||||
this._onChange(this.el.nativeElement.value);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['inputMask'] && changes['inputMask'].currentValue['mask']) {
|
||||
if (changes['inputMask']?.currentValue['mask']) {
|
||||
this.inputMask = changes['inputMask'].currentValue;
|
||||
}
|
||||
}
|
||||
@@ -99,7 +92,7 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
this._onTouched = fn;
|
||||
}
|
||||
|
||||
private maskValue(actualValue, startCaret, maskToApply, isMaskReversed, keyCode) {
|
||||
private maskValue(actualValue: string, startCaret: number, maskToApply: string, isMaskReversed: boolean, keyCode: number) {
|
||||
if (this.byPassKeys.indexOf(keyCode) === -1) {
|
||||
const value = this.getMasked(false, actualValue, maskToApply, isMaskReversed);
|
||||
const calculatedCaret = this.calculateCaretPosition(startCaret, actualValue, keyCode);
|
||||
@@ -111,12 +104,12 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
private setCaretPosition(caretPosition) {
|
||||
private setCaretPosition(caretPosition: number) {
|
||||
this.el.nativeElement.moveStart = caretPosition;
|
||||
this.el.nativeElement.moveEnd = caretPosition;
|
||||
}
|
||||
|
||||
calculateCaretPosition(caretPosition, newValue, keyCode) {
|
||||
calculateCaretPosition(caretPosition: number, newValue: string, keyCode: number): number {
|
||||
const newValueLength = newValue.length;
|
||||
const oldValue = this.getValue() || '';
|
||||
const oldValueLength = oldValue.length;
|
||||
@@ -133,7 +126,7 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
return caretPosition;
|
||||
}
|
||||
|
||||
getMasked(skipMaskChars, val, mask, isReversed = false) {
|
||||
getMasked(skipMaskChars: boolean, val: string, mask: string, isReversed = false) {
|
||||
const buf = [];
|
||||
const value = val;
|
||||
let maskIndex = 0;
|
||||
@@ -143,9 +136,9 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
let offset = 1;
|
||||
let addMethod = 'push';
|
||||
let resetPos = -1;
|
||||
let lastMaskChar;
|
||||
let lastUntranslatedMaskChar;
|
||||
let check;
|
||||
let lastMaskChar: number;
|
||||
let lastUntranslatedMaskChar: string;
|
||||
let check: boolean;
|
||||
|
||||
if (isReversed) {
|
||||
addMethod = 'unshift';
|
||||
@@ -159,8 +152,8 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
check = this.isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength);
|
||||
while (check) {
|
||||
const maskDigit = mask.charAt(maskIndex);
|
||||
const valDigit = value.charAt(valueIndex);
|
||||
const translation = this.translationMask[maskDigit];
|
||||
const valDigit = value.charAt(valueIndex);
|
||||
const translation = this.translationMask[maskDigit];
|
||||
|
||||
if (translation) {
|
||||
if (valDigit.match(translation.pattern)) {
|
||||
@@ -211,12 +204,12 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
return buf.join('');
|
||||
}
|
||||
|
||||
private isToCheck(isReversed, maskIndex, maskLen, valueIndex, valueLength) {
|
||||
private isToCheck(isReversed: boolean, maskIndex: number, maskLen: number, valueIndex: number, valueLength: number): boolean {
|
||||
let check = false;
|
||||
if (isReversed) {
|
||||
check = (maskIndex > -1) && (valueIndex > -1);
|
||||
check = maskIndex > -1 && valueIndex > -1;
|
||||
} else {
|
||||
check = (maskIndex < maskLen) && (valueIndex < valueLength);
|
||||
check = maskIndex < maskLen && valueIndex < valueLength;
|
||||
}
|
||||
return check;
|
||||
}
|
||||
|
@@ -43,7 +43,6 @@ import { FormFieldModel } from './core';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class WidgetComponent implements AfterViewInit {
|
||||
|
||||
/** Does the widget show a read-only value? (ie, can't be edited) */
|
||||
@Input()
|
||||
readOnly: boolean = false;
|
||||
@@ -60,8 +59,7 @@ export class WidgetComponent implements AfterViewInit {
|
||||
|
||||
touched: boolean = false;
|
||||
|
||||
constructor(public formService?: FormService) {
|
||||
}
|
||||
constructor(public formService?: FormService) {}
|
||||
|
||||
hasField(): boolean {
|
||||
return !!this.field;
|
||||
@@ -70,7 +68,7 @@ export class WidgetComponent implements AfterViewInit {
|
||||
// Note for developers:
|
||||
// returns <any> object to be able binding it to the <element required="required"> attribute
|
||||
isRequired(): any {
|
||||
if (this.field && this.field.required) {
|
||||
if (this.field?.required) {
|
||||
return true;
|
||||
}
|
||||
return null;
|
||||
@@ -85,9 +83,7 @@ export class WidgetComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
hasValue(): boolean {
|
||||
return this.field &&
|
||||
this.field.value !== null &&
|
||||
this.field.value !== undefined;
|
||||
return this.field?.value !== null && this.field?.value !== undefined;
|
||||
}
|
||||
|
||||
isInvalidFieldRequired() {
|
||||
|
@@ -18,13 +18,7 @@
|
||||
import { LogService } from '../../common/services/log.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
FormFieldModel,
|
||||
FormModel,
|
||||
TabModel,
|
||||
ContainerModel,
|
||||
FormOutcomeModel
|
||||
} from '../components/widgets/core';
|
||||
import { FormFieldModel, FormModel, TabModel, ContainerModel, FormOutcomeModel } from '../components/widgets/core';
|
||||
import { TaskProcessVariableModel } from '../models/task-process-variable.model';
|
||||
import { WidgetVisibilityModel, WidgetTypeEnum } from '../models/widget-visibility.model';
|
||||
|
||||
@@ -32,27 +26,27 @@ import { WidgetVisibilityModel, WidgetTypeEnum } from '../models/widget-visibili
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class WidgetVisibilityService {
|
||||
|
||||
private processVarList: TaskProcessVariableModel[];
|
||||
private form: FormModel;
|
||||
|
||||
constructor(private logService: LogService) {
|
||||
}
|
||||
constructor(private logService: LogService) {}
|
||||
|
||||
public refreshVisibility(form: FormModel, processVarList?: TaskProcessVariableModel[]) {
|
||||
this.form = form;
|
||||
|
||||
if (processVarList) {
|
||||
this.processVarList = processVarList;
|
||||
}
|
||||
if (form && form.tabs && form.tabs.length > 0) {
|
||||
form.tabs.map((tabModel) => this.refreshEntityVisibility(tabModel));
|
||||
}
|
||||
|
||||
if (form && form.outcomes && form.outcomes.length > 0) {
|
||||
form.outcomes.map((outcomeModel) => this.refreshOutcomeVisibility(outcomeModel));
|
||||
}
|
||||
|
||||
if (form) {
|
||||
if (form.tabs?.length > 0) {
|
||||
form.tabs.map((tabModel) => this.refreshEntityVisibility(tabModel));
|
||||
}
|
||||
|
||||
if (form.outcomes?.length > 0) {
|
||||
form.outcomes.map((outcomeModel) => this.refreshOutcomeVisibility(outcomeModel));
|
||||
}
|
||||
|
||||
form.getFormFields().map((field) => this.refreshEntityVisibility(field));
|
||||
}
|
||||
}
|
||||
@@ -79,14 +73,14 @@ export class WidgetVisibilityService {
|
||||
const rightValue = this.getRightValue(form, visibilityObj);
|
||||
const actualResult = this.evaluateCondition(leftValue, rightValue, visibilityObj.operator);
|
||||
|
||||
accumulator.push({value: actualResult, operator: visibilityObj.nextConditionOperator});
|
||||
accumulator.push({ value: actualResult, operator: visibilityObj.nextConditionOperator });
|
||||
|
||||
if (this.isValidCondition(visibilityObj.nextCondition)) {
|
||||
result = this.isFieldVisible(form, visibilityObj.nextCondition, accumulator);
|
||||
} else if (accumulator[0] !== undefined) {
|
||||
result = Function('"use strict";return (' +
|
||||
accumulator.map((expression) => this.transformToLiteralExpression(expression)).join('') +
|
||||
')')();
|
||||
result = Function(
|
||||
'"use strict";return (' + accumulator.map((expression) => this.transformToLiteralExpression(expression)).join('') + ')'
|
||||
)();
|
||||
} else {
|
||||
result = actualResult;
|
||||
}
|
||||
@@ -102,7 +96,7 @@ export class WidgetVisibilityService {
|
||||
switch (currentOperator) {
|
||||
case 'and':
|
||||
return '&&';
|
||||
case 'or' :
|
||||
case 'or':
|
||||
return '||';
|
||||
case 'and-not':
|
||||
return '&& !';
|
||||
@@ -158,25 +152,25 @@ export class WidgetVisibilityService {
|
||||
}
|
||||
|
||||
public isFormFieldValid(formField: FormFieldModel): boolean {
|
||||
return formField && formField.isValid;
|
||||
return formField?.isValid;
|
||||
}
|
||||
|
||||
public getFieldValue(valueList: any, fieldId: string): any {
|
||||
let labelFilterByName;
|
||||
let valueFound;
|
||||
let labelFilterByName: string;
|
||||
let valueFound: any;
|
||||
if (fieldId && fieldId.indexOf('_LABEL') > 0) {
|
||||
labelFilterByName = fieldId.substring(0, fieldId.length - 6);
|
||||
if (valueList[labelFilterByName]) {
|
||||
if (Array.isArray(valueList[labelFilterByName])) {
|
||||
valueFound = valueList[labelFilterByName].map(({name}) => name);
|
||||
valueFound = valueList[labelFilterByName].map(({ name }) => name);
|
||||
} else {
|
||||
valueFound = valueList[labelFilterByName].name;
|
||||
}
|
||||
}
|
||||
} else if (valueList[fieldId] && valueList[fieldId].id) {
|
||||
} else if (valueList[fieldId]?.id) {
|
||||
valueFound = valueList[fieldId].id;
|
||||
} else if (valueList[fieldId] && Array.isArray(valueList[fieldId])) {
|
||||
valueFound = valueList[fieldId].map(({id}) => id);
|
||||
valueFound = valueList[fieldId].map(({ id }) => id);
|
||||
} else {
|
||||
valueFound = valueList[fieldId];
|
||||
}
|
||||
@@ -198,7 +192,7 @@ export class WidgetVisibilityService {
|
||||
fieldValue = this.getObjectValue(formField, fieldId);
|
||||
|
||||
if (!fieldValue) {
|
||||
if (formField.value && formField.value.id) {
|
||||
if (formField.value?.id) {
|
||||
fieldValue = formField.value.id;
|
||||
} else if (!this.isInvalidValue(formField.value)) {
|
||||
fieldValue = formField.value;
|
||||
@@ -223,7 +217,7 @@ export class WidgetVisibilityService {
|
||||
}
|
||||
|
||||
private getCurrentFieldFromTabById(container: ContainerModel, fieldId: string): FormFieldModel {
|
||||
const tabFields: FormFieldModel[][] = Object.keys(container.field.fields).map(key => container.field.fields[key]);
|
||||
const tabFields: FormFieldModel[][] = Object.keys(container.field.fields).map((key) => container.field.fields[key]);
|
||||
let currentField: FormFieldModel;
|
||||
|
||||
for (const tabField of tabFields) {
|
||||
@@ -237,14 +231,14 @@ export class WidgetVisibilityService {
|
||||
|
||||
private getFormTabContainers(form: FormModel): ContainerModel[] {
|
||||
if (!!form) {
|
||||
return form.fields.filter(field => field.type === 'container' && field.tab) as ContainerModel[];
|
||||
return form.fields.filter((field) => field.type === 'container' && field.tab) as ContainerModel[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private getObjectValue(field: FormFieldModel, fieldId: string): string {
|
||||
let value = '';
|
||||
if (field.value && field.value.name) {
|
||||
if (field.value?.name) {
|
||||
value = field.value.name;
|
||||
} else if (field.options) {
|
||||
const option = field.options.find((opt) => opt.id === field.value);
|
||||
@@ -267,23 +261,19 @@ export class WidgetVisibilityService {
|
||||
|
||||
private isSearchedField(field: FormFieldModel, fieldId: string): boolean {
|
||||
const fieldToFind = fieldId?.indexOf('_LABEL') > 0 ? fieldId.replace('_LABEL', '') : fieldId;
|
||||
return (field.id && fieldToFind) ? field.id.toUpperCase() === fieldToFind.toUpperCase() : false;
|
||||
return field.id && fieldToFind ? field.id.toUpperCase() === fieldToFind.toUpperCase() : false;
|
||||
}
|
||||
|
||||
public getVariableValue(form: FormModel, name: string, processVarList: TaskProcessVariableModel[]): string {
|
||||
const processVariableValue = this.getProcessVariableValue(name, processVarList);
|
||||
const variableDefaultValue = form.getDefaultFormVariableValue(name);
|
||||
|
||||
return (processVariableValue === undefined) ? variableDefaultValue : processVariableValue;
|
||||
return processVariableValue === undefined ? variableDefaultValue : processVariableValue;
|
||||
}
|
||||
|
||||
private getProcessVariableValue(name: string, processVarList: TaskProcessVariableModel[]): string {
|
||||
if (processVarList) {
|
||||
const processVariable = processVarList.find(
|
||||
variable =>
|
||||
variable.id === name ||
|
||||
variable.id === `variables.${name}`
|
||||
);
|
||||
const processVariable = processVarList.find((variable) => variable.id === name || variable.id === `variables.${name}`);
|
||||
|
||||
if (processVariable) {
|
||||
return processVariable.value;
|
||||
@@ -329,6 +319,6 @@ export class WidgetVisibilityService {
|
||||
}
|
||||
|
||||
private isValidCondition(condition: WidgetVisibilityModel): boolean {
|
||||
return !!(condition && condition.operator);
|
||||
return !!condition?.operator;
|
||||
}
|
||||
}
|
||||
|
@@ -81,7 +81,7 @@ export class LayoutContainerComponent implements OnInit, OnDestroy, OnChanges {
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes && changes.direction) {
|
||||
if (changes?.direction) {
|
||||
this.contentAnimationState = this.toggledContentAnimation;
|
||||
}
|
||||
}
|
||||
@@ -104,9 +104,7 @@ export class LayoutContainerComponent implements OnInit, OnDestroy, OnChanges {
|
||||
}
|
||||
|
||||
private get toggledSidenavAnimation(): any {
|
||||
return this.sidenavAnimationState === this.SIDENAV_STATES.EXPANDED
|
||||
? this.SIDENAV_STATES.COMPACT
|
||||
: this.SIDENAV_STATES.EXPANDED;
|
||||
return this.sidenavAnimationState === this.SIDENAV_STATES.EXPANDED ? this.SIDENAV_STATES.COMPACT : this.SIDENAV_STATES.EXPANDED;
|
||||
}
|
||||
|
||||
private get toggledContentAnimation(): any {
|
||||
@@ -130,7 +128,6 @@ export class LayoutContainerComponent implements OnInit, OnDestroy, OnChanges {
|
||||
if (this.position === 'end' && this.direction === 'rtl') {
|
||||
return { value: 'compact', params: { 'margin-left': this.sidenavMax } };
|
||||
}
|
||||
|
||||
} else {
|
||||
if (this.position === 'start' && this.direction === 'ltr') {
|
||||
return { value: 'expanded', params: { 'margin-left': this.sidenavMin } };
|
||||
|
@@ -42,6 +42,6 @@ export class LoginDialogPanelComponent {
|
||||
}
|
||||
|
||||
isValid() {
|
||||
return this.login && this.login.form ? this.login.form.valid : false;
|
||||
return this.login?.form ? this.login.form.valid : false;
|
||||
}
|
||||
}
|
||||
|
@@ -15,10 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component, EventEmitter,
|
||||
Input, OnInit, Output, TemplateRef, ViewEncapsulation, OnDestroy
|
||||
} from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||
import { AuthenticationService } from '../../auth/services/authentication.service';
|
||||
@@ -28,10 +25,7 @@ import { UserPreferencesService } from '../../common/services/user-preferences.s
|
||||
import { LoginErrorEvent } from '../models/login-error.event';
|
||||
import { LoginSubmitEvent } from '../models/login-submit.event';
|
||||
import { LoginSuccessEvent } from '../models/login-success.event';
|
||||
import {
|
||||
AppConfigService,
|
||||
AppConfigValues
|
||||
} from '../../app-config/app-config.service';
|
||||
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
@@ -136,8 +130,7 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
private userPreferences: UserPreferencesService,
|
||||
private route: ActivatedRoute,
|
||||
private sanitizer: DomSanitizer
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.initFormError();
|
||||
@@ -149,12 +142,11 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
if (this.authService.isLoggedIn()) {
|
||||
this.router.navigate([this.successRoute]);
|
||||
} else {
|
||||
|
||||
if (this.authService.isOauth()) {
|
||||
const oauth = this.appConfig.oauth2;
|
||||
if (oauth && oauth.silentLogin) {
|
||||
if (oauth?.silentLogin) {
|
||||
this.redirectToImplicitLogin();
|
||||
} else if (oauth && oauth.implicitFlow) {
|
||||
} else if (oauth?.implicitFlow) {
|
||||
this.implicitFlow = true;
|
||||
}
|
||||
}
|
||||
@@ -171,9 +163,7 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
this.form = this._fb.group(this.fieldsValidation);
|
||||
}
|
||||
|
||||
this.form.valueChanges
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(data => this.onValueChanged(data));
|
||||
this.form.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe((data) => this.onValueChanged(data));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@@ -193,7 +183,6 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
* Method called on submit form
|
||||
*
|
||||
* @param values
|
||||
* @param event
|
||||
*/
|
||||
onSubmit(values: any): void {
|
||||
this.disableError();
|
||||
@@ -227,14 +216,12 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
if (field) {
|
||||
this.formError[field] = '';
|
||||
const hasError =
|
||||
(this.form.controls[field].errors && data[field] !== '') ||
|
||||
(this.form.controls[field].dirty &&
|
||||
!this.form.controls[field].valid);
|
||||
(this.form.controls[field].errors && data[field] !== '') || (this.form.controls[field].dirty && !this.form.controls[field].valid);
|
||||
if (hasError) {
|
||||
for (const key in this.form.controls[field].errors) {
|
||||
if (key) {
|
||||
const message = this._message[field][key];
|
||||
if (message && message.value) {
|
||||
if (message?.value) {
|
||||
const translated = this.translateService.instant(message.value, message.params);
|
||||
this.formError[field] += translated;
|
||||
}
|
||||
@@ -246,55 +233,40 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
performLogin(values: { username: string; password: string }) {
|
||||
this.authService
|
||||
.login(values.username, values.password, this.rememberMe)
|
||||
.subscribe(
|
||||
(token: any) => {
|
||||
const redirectUrl = this.authService.getRedirect();
|
||||
this.authService.login(values.username, values.password, this.rememberMe).subscribe(
|
||||
(token) => {
|
||||
const redirectUrl = this.authService.getRedirect();
|
||||
|
||||
this.actualLoginStep = LoginSteps.Welcome;
|
||||
this.userPreferences.setStoragePrefix(values.username);
|
||||
values.password = null;
|
||||
this.success.emit(
|
||||
new LoginSuccessEvent(token, values.username, null)
|
||||
);
|
||||
this.actualLoginStep = LoginSteps.Welcome;
|
||||
this.userPreferences.setStoragePrefix(values.username);
|
||||
values.password = null;
|
||||
this.success.emit(new LoginSuccessEvent(token, values.username, null));
|
||||
|
||||
if (redirectUrl) {
|
||||
this.authService.setRedirect(null);
|
||||
this.router.navigateByUrl(redirectUrl);
|
||||
} else if (this.successRoute) {
|
||||
this.router.navigate([this.successRoute]);
|
||||
}
|
||||
},
|
||||
(err: any) => {
|
||||
this.actualLoginStep = LoginSteps.Landing;
|
||||
this.displayErrorMessage(err);
|
||||
this.isError = true;
|
||||
this.error.emit(new LoginErrorEvent(err));
|
||||
if (redirectUrl) {
|
||||
this.authService.setRedirect(null);
|
||||
this.router.navigateByUrl(redirectUrl);
|
||||
} else if (this.successRoute) {
|
||||
this.router.navigate([this.successRoute]);
|
||||
}
|
||||
);
|
||||
},
|
||||
(err: any) => {
|
||||
this.actualLoginStep = LoginSteps.Landing;
|
||||
this.displayErrorMessage(err);
|
||||
this.isError = true;
|
||||
this.error.emit(new LoginErrorEvent(err));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and display the right error message in the UI
|
||||
*/
|
||||
private displayErrorMessage(err: any): void {
|
||||
if (
|
||||
err.error &&
|
||||
err.error.crossDomain &&
|
||||
err.error.message.indexOf('Access-Control-Allow-Origin') !== -1
|
||||
) {
|
||||
if (err.error?.crossDomain && err.error.message.indexOf('Access-Control-Allow-Origin') !== -1) {
|
||||
this.errorMsg = err.error.message;
|
||||
} else if (
|
||||
err.status === 403 &&
|
||||
err.message.indexOf('Invalid CSRF-token') !== -1
|
||||
) {
|
||||
} else if (err.status === 403 && err.message.indexOf('Invalid CSRF-token') !== -1) {
|
||||
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ERROR-CSRF';
|
||||
} else if (
|
||||
err.status === 403 &&
|
||||
err.message.indexOf('The system is currently in read-only mode') !==
|
||||
-1
|
||||
) {
|
||||
} else if (err.status === 403 && err.message.indexOf('The system is currently in read-only mode') !== -1) {
|
||||
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ECM-LICENSE';
|
||||
} else {
|
||||
this.errorMsg = 'LOGIN.MESSAGES.LOGIN-ERROR-CREDENTIALS';
|
||||
@@ -317,13 +289,9 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
* @param field
|
||||
* @param ruleId - i.e. required | minlength | maxlength
|
||||
* @param msg
|
||||
* @param params
|
||||
*/
|
||||
addCustomValidationError(
|
||||
field: string,
|
||||
ruleId: string,
|
||||
msg: string,
|
||||
params?: any
|
||||
) {
|
||||
addCustomValidationError(field: string, ruleId: string, msg: string, params?: any) {
|
||||
if (field !== '__proto__' && field !== 'constructor' && field !== 'prototype') {
|
||||
this._message[field][ruleId] = {
|
||||
value: msg,
|
||||
@@ -385,7 +353,6 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
minLength: this.minLength
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
password: {
|
||||
required: {
|
||||
|
@@ -20,7 +20,6 @@ import { CookieService } from '../common/services/cookie.service';
|
||||
|
||||
@Injectable()
|
||||
export class CookieServiceMock extends CookieService {
|
||||
|
||||
/** @override */
|
||||
isEnabled(): boolean {
|
||||
return true;
|
||||
@@ -28,18 +27,18 @@ export class CookieServiceMock extends CookieService {
|
||||
|
||||
/** @override */
|
||||
getItem(key: string): string | null {
|
||||
return this[key] && this[key].data || null;
|
||||
return this[key]?.data || null;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
setItem(key: string, data: string, expiration: Date | null, path: string | null): void {
|
||||
this[key] = {data, expiration, path};
|
||||
this[key] = { data, expiration, path };
|
||||
}
|
||||
|
||||
/** @override */
|
||||
clear() {
|
||||
Object.keys(this).forEach((key) => {
|
||||
if (this.hasOwnProperty(key) && typeof(this[key]) !== 'function') {
|
||||
if (this.hasOwnProperty(key) && typeof this[key] !== 'function') {
|
||||
this[key] = undefined;
|
||||
}
|
||||
});
|
||||
|
@@ -18,11 +18,11 @@
|
||||
export class ComponentTranslationModel {
|
||||
name: string;
|
||||
path: string;
|
||||
json: string [];
|
||||
json: string[];
|
||||
|
||||
constructor(obj?: any) {
|
||||
this.name = obj && obj.name;
|
||||
this.path = obj && obj.path;
|
||||
this.json = obj && obj.json || [];
|
||||
this.name = obj?.name;
|
||||
this.path = obj?.path;
|
||||
this.json = obj?.json || [];
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@ import { takeUntil } from 'rxjs/operators';
|
||||
pure: false
|
||||
})
|
||||
export class DecimalNumberPipe implements PipeTransform, OnDestroy {
|
||||
|
||||
static DEFAULT_LOCALE = 'en-US';
|
||||
static DEFAULT_MIN_INTEGER_DIGITS = 1;
|
||||
static DEFAULT_MIN_FRACTION_DIGITS = 0;
|
||||
@@ -41,14 +40,11 @@ export class DecimalNumberPipe implements PipeTransform, OnDestroy {
|
||||
|
||||
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||
|
||||
constructor(public userPreferenceService?: UserPreferencesService,
|
||||
public appConfig?: AppConfigService) {
|
||||
|
||||
constructor(public userPreferenceService?: UserPreferencesService, public appConfig?: AppConfigService) {
|
||||
if (this.userPreferenceService) {
|
||||
this.userPreferenceService.select(UserPreferenceValues.Locale)
|
||||
.pipe(
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
this.userPreferenceService
|
||||
.select(UserPreferenceValues.Locale)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((locale) => {
|
||||
if (locale) {
|
||||
this.defaultLocale = locale;
|
||||
@@ -58,15 +54,21 @@ export class DecimalNumberPipe implements PipeTransform, OnDestroy {
|
||||
|
||||
if (this.appConfig) {
|
||||
this.defaultMinIntegerDigits = this.appConfig.get<number>('decimalValues.minIntegerDigits', DecimalNumberPipe.DEFAULT_MIN_INTEGER_DIGITS);
|
||||
this.defaultMinFractionDigits = this.appConfig.get<number>('decimalValues.minFractionDigits', DecimalNumberPipe.DEFAULT_MIN_FRACTION_DIGITS);
|
||||
this.defaultMaxFractionDigits = this.appConfig.get<number>('decimalValues.maxFractionDigits', DecimalNumberPipe.DEFAULT_MAX_FRACTION_DIGITS);
|
||||
this.defaultMinFractionDigits = this.appConfig.get<number>(
|
||||
'decimalValues.minFractionDigits',
|
||||
DecimalNumberPipe.DEFAULT_MIN_FRACTION_DIGITS
|
||||
);
|
||||
this.defaultMaxFractionDigits = this.appConfig.get<number>(
|
||||
'decimalValues.maxFractionDigits',
|
||||
DecimalNumberPipe.DEFAULT_MAX_FRACTION_DIGITS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
transform(value: any, digitsInfo?: DecimalNumberModel, locale?: string): any {
|
||||
const actualMinIntegerDigits: number = digitsInfo && digitsInfo.minIntegerDigits ? digitsInfo.minIntegerDigits : this.defaultMinIntegerDigits;
|
||||
const actualMinFractionDigits: number = digitsInfo && digitsInfo.minFractionDigits ? digitsInfo.minFractionDigits : this.defaultMinFractionDigits;
|
||||
const actualMaxFractionDigits: number = digitsInfo && digitsInfo.maxFractionDigits ? digitsInfo.maxFractionDigits : this.defaultMaxFractionDigits;
|
||||
const actualMinIntegerDigits: number = digitsInfo?.minIntegerDigits ? digitsInfo.minIntegerDigits : this.defaultMinIntegerDigits;
|
||||
const actualMinFractionDigits: number = digitsInfo?.minFractionDigits ? digitsInfo.minFractionDigits : this.defaultMinFractionDigits;
|
||||
const actualMaxFractionDigits: number = digitsInfo?.maxFractionDigits ? digitsInfo.maxFractionDigits : this.defaultMaxFractionDigits;
|
||||
|
||||
const actualDigitsInfo = `${actualMinIntegerDigits}.${actualMinFractionDigits}-${actualMaxFractionDigits}`;
|
||||
const actualLocale = locale || this.defaultLocale;
|
||||
|
@@ -18,17 +18,7 @@
|
||||
/* eslint-disable @angular-eslint/no-input-rename, @typescript-eslint/no-use-before-define, @angular-eslint/no-input-rename */
|
||||
|
||||
import { ENTER, ESCAPE } from '@angular/cdk/keycodes';
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Directive,
|
||||
ElementRef,
|
||||
forwardRef,
|
||||
Inject,
|
||||
Input,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
Optional
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectorRef, Directive, ElementRef, forwardRef, Inject, Input, NgZone, OnDestroy, Optional } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Observable, Subject, Subscription, merge, of, fromEvent } from 'rxjs';
|
||||
@@ -71,14 +61,16 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
private closingActionsSubscription: Subscription;
|
||||
private escapeEventStream = new Subject<void>();
|
||||
|
||||
onChange: (value: any) => void = () => { };
|
||||
onChange: (value: any) => void = () => {};
|
||||
|
||||
onTouched = () => { };
|
||||
onTouched = () => {};
|
||||
|
||||
constructor(private element: ElementRef,
|
||||
private ngZone: NgZone,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() @Inject(DOCUMENT) private document: any) { }
|
||||
constructor(
|
||||
private element: ElementRef,
|
||||
private ngZone: NgZone,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() @Inject(DOCUMENT) private document: any
|
||||
) {}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
@@ -87,7 +79,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
if (this.escapeEventStream) {
|
||||
this.escapeEventStream = null;
|
||||
}
|
||||
if ( this.closingActionsSubscription ) {
|
||||
if (this.closingActionsSubscription) {
|
||||
this.closingActionsSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -112,10 +104,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
}
|
||||
|
||||
get panelClosingActions(): Observable<any> {
|
||||
return merge(
|
||||
this.escapeEventStream,
|
||||
this.outsideClickStream
|
||||
);
|
||||
return merge(this.escapeEventStream, this.outsideClickStream);
|
||||
}
|
||||
|
||||
private get outsideClickStream(): Observable<any> {
|
||||
@@ -123,10 +112,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
return of(null);
|
||||
}
|
||||
|
||||
return merge(
|
||||
fromEvent(this.document, 'click'),
|
||||
fromEvent(this.document, 'touchend')
|
||||
).pipe(
|
||||
return merge(fromEvent(this.document, 'click'), fromEvent(this.document, 'touchend')).pipe(
|
||||
filter((event: MouseEvent | TouchEvent) => {
|
||||
const clickTarget = event.target as HTMLElement;
|
||||
return this._panelOpen && clickTarget !== this.element.nativeElement;
|
||||
@@ -157,11 +143,10 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
this.escapeEventStream.next();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleInput(event: KeyboardEvent): void {
|
||||
if (document.activeElement === event.target ) {
|
||||
if (document.activeElement === event.target) {
|
||||
const inputValue: string = (event.target as HTMLInputElement).value;
|
||||
this.onChange(inputValue);
|
||||
if (inputValue && this.searchPanel) {
|
||||
@@ -176,17 +161,15 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
|
||||
private isPanelOptionClicked(event: MouseEvent) {
|
||||
let isPanelOption: boolean = false;
|
||||
if ( event && this.searchPanel ) {
|
||||
if (event && this.searchPanel) {
|
||||
const clickTarget = event.target as HTMLElement;
|
||||
isPanelOption = !this.isNoResultOption() &&
|
||||
!!this.searchPanel.panel &&
|
||||
!!this.searchPanel.panel.nativeElement.contains(clickTarget);
|
||||
isPanelOption = !this.isNoResultOption() && !!this.searchPanel.panel && !!this.searchPanel.panel.nativeElement.contains(clickTarget);
|
||||
}
|
||||
return isPanelOption;
|
||||
}
|
||||
|
||||
private isNoResultOption(): boolean {
|
||||
return this.searchPanel && this.searchPanel.results.list ? this.searchPanel.results.list.entries.length === 0 : true;
|
||||
return this.searchPanel?.results?.list ? this.searchPanel.results.list.entries.length === 0 : true;
|
||||
}
|
||||
|
||||
private subscribeToClosingActions(): Subscription {
|
||||
@@ -205,8 +188,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
|
||||
}
|
||||
|
||||
private setTriggerValue(value: any): void {
|
||||
const toDisplay = this.searchPanel && this.searchPanel.displayWith ?
|
||||
this.searchPanel.displayWith(value) : value;
|
||||
const toDisplay = this.searchPanel?.displayWith ? this.searchPanel.displayWith(value) : value;
|
||||
const inputValue = toDisplay != null ? toDisplay : '';
|
||||
this.element.nativeElement.value = inputValue;
|
||||
}
|
||||
|
@@ -27,15 +27,13 @@ import { map, catchError, retry } from 'rxjs/operators';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TranslateLoaderService implements TranslateLoader {
|
||||
|
||||
private prefix: string = 'i18n';
|
||||
private suffix: string = '.json';
|
||||
private providers: ComponentTranslationModel[] = [];
|
||||
private queue: string [][] = [];
|
||||
private queue: string[][] = [];
|
||||
private defaultLang: string = 'en';
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
}
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
setDefaultLang(value: string) {
|
||||
this.defaultLang = value || 'en';
|
||||
@@ -51,7 +49,7 @@ export class TranslateLoaderService implements TranslateLoader {
|
||||
}
|
||||
|
||||
providerRegistered(name: string): boolean {
|
||||
return this.providers.find((x) => x.name === name) ? true : false;
|
||||
return !!this.providers.find((x) => x.name === name);
|
||||
}
|
||||
|
||||
fetchLanguageFile(lang: string, component: ComponentTranslationModel, fallbackUrl?: string): Observable<void> {
|
||||
@@ -86,9 +84,7 @@ export class TranslateLoaderService implements TranslateLoader {
|
||||
if (!this.isComponentInQueue(lang, component.name)) {
|
||||
this.queue[lang].push(component.name);
|
||||
|
||||
observableBatch.push(
|
||||
this.fetchLanguageFile(lang, component)
|
||||
);
|
||||
observableBatch.push(this.fetchLanguageFile(lang, component));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -102,7 +98,7 @@ export class TranslateLoaderService implements TranslateLoader {
|
||||
}
|
||||
|
||||
isComponentInQueue(lang: string, name: string) {
|
||||
return (this.queue[lang] || []).find((x) => x === name) ? true : false;
|
||||
return !!(this.queue[lang] || []).find((x) => x === name);
|
||||
}
|
||||
|
||||
getFullTranslationJSON(lang: string): any {
|
||||
@@ -120,7 +116,7 @@ export class TranslateLoaderService implements TranslateLoader {
|
||||
return a.name.localeCompare(b.name);
|
||||
})
|
||||
.forEach((model) => {
|
||||
if (model.json && model.json[lang]) {
|
||||
if (model.json?.[lang]) {
|
||||
result = ObjectUtils.merge(result, model.json[lang]);
|
||||
}
|
||||
});
|
||||
@@ -131,16 +127,17 @@ export class TranslateLoaderService implements TranslateLoader {
|
||||
getTranslation(lang: string): Observable<any> {
|
||||
let hasFailures = false;
|
||||
const batch = [
|
||||
...this.getComponentToFetch(lang).map((observable) => observable.pipe(
|
||||
catchError((error) => {
|
||||
hasFailures = true;
|
||||
return of(error);
|
||||
})
|
||||
))
|
||||
...this.getComponentToFetch(lang).map((observable) =>
|
||||
observable.pipe(
|
||||
catchError((error) => {
|
||||
hasFailures = true;
|
||||
return of(error);
|
||||
})
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
return new Observable((observer) => {
|
||||
|
||||
if (batch.length > 0) {
|
||||
forkJoin(batch).subscribe(
|
||||
() => {
|
||||
@@ -156,7 +153,8 @@ export class TranslateLoaderService implements TranslateLoader {
|
||||
},
|
||||
() => {
|
||||
observer.error('Failed to load some resources');
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
const fullTranslation = this.getFullTranslationJSON(lang);
|
||||
if (fullTranslation) {
|
||||
|
@@ -23,7 +23,11 @@ import {
|
||||
ViewEncapsulation,
|
||||
ElementRef,
|
||||
Output,
|
||||
EventEmitter, AfterViewInit, ViewChild, HostListener, OnDestroy
|
||||
EventEmitter,
|
||||
AfterViewInit,
|
||||
ViewChild,
|
||||
HostListener,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { UrlService } from '../../common/services/url.service';
|
||||
@@ -37,7 +41,6 @@ import Cropper from 'cropperjs';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
|
||||
@Input()
|
||||
showToolbar = true;
|
||||
|
||||
@@ -64,7 +67,7 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
@Output()
|
||||
isSaving = new EventEmitter<boolean>();
|
||||
|
||||
@ViewChild('image', { static: false})
|
||||
@ViewChild('image', { static: false })
|
||||
public imageElement: ElementRef;
|
||||
|
||||
public scale: number = 1.0;
|
||||
@@ -75,10 +78,7 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
return Math.round(this.scale * 100) + '%';
|
||||
}
|
||||
|
||||
constructor(
|
||||
private appConfigService: AppConfigService,
|
||||
private urlService: UrlService
|
||||
) {
|
||||
constructor(private appConfigService: AppConfigService, private urlService: UrlService) {
|
||||
this.initializeScaling();
|
||||
}
|
||||
|
||||
@@ -143,14 +143,14 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
|
||||
@HostListener('document:fullscreenchange')
|
||||
fullScreenChangeHandler() {
|
||||
if(document.fullscreenElement) {
|
||||
if (document.fullscreenElement) {
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const blobFile = changes['blobFile'];
|
||||
if (blobFile && blobFile.currentValue) {
|
||||
if (blobFile?.currentValue) {
|
||||
this.urlFile = this.urlService.createTrustedUrl(this.blobFile);
|
||||
return;
|
||||
}
|
||||
@@ -167,20 +167,20 @@ export class ImgViewerComponent implements AfterViewInit, OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
zoomIn() {
|
||||
this.cropper.zoom( 0.2);
|
||||
this.scale = +((this.scale + 0.2).toFixed(1));
|
||||
this.cropper.zoom(0.2);
|
||||
this.scale = +(this.scale + 0.2).toFixed(1);
|
||||
}
|
||||
|
||||
zoomOut() {
|
||||
if (this.scale > 0.2) {
|
||||
this.cropper.zoom( -0.2 );
|
||||
this.scale = +((this.scale - 0.2).toFixed(1));
|
||||
this.cropper.zoom(-0.2);
|
||||
this.scale = +(this.scale - 0.2).toFixed(1);
|
||||
}
|
||||
}
|
||||
|
||||
rotateImage() {
|
||||
this.isEditing = true;
|
||||
this.cropper.rotate( -90);
|
||||
this.cropper.rotate(-90);
|
||||
}
|
||||
|
||||
cropImage() {
|
||||
|
@@ -23,11 +23,10 @@ import { UrlService } from '../../common/services/url.service';
|
||||
selector: 'adf-media-player',
|
||||
templateUrl: './media-player.component.html',
|
||||
styleUrls: ['./media-player.component.scss'],
|
||||
host: {class: 'adf-media-player'},
|
||||
host: { class: 'adf-media-player' },
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class MediaPlayerComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
urlFile: string;
|
||||
|
||||
@@ -47,13 +46,12 @@ export class MediaPlayerComponent implements OnChanges {
|
||||
@Output()
|
||||
error = new EventEmitter<any>();
|
||||
|
||||
constructor(private urlService: UrlService) {
|
||||
}
|
||||
constructor(private urlService: UrlService) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const blobFile = changes['blobFile'];
|
||||
|
||||
if (blobFile && blobFile.currentValue) {
|
||||
if (blobFile?.currentValue) {
|
||||
this.urlFile = this.urlService.createTrustedUrl(this.blobFile);
|
||||
return;
|
||||
}
|
||||
|
@@ -48,11 +48,10 @@ declare const pdfjsViewer: any;
|
||||
templateUrl: './pdf-viewer.component.html',
|
||||
styleUrls: ['./pdf-viewer-host.component.scss', './pdf-viewer.component.scss'],
|
||||
providers: [RenderingQueueServices],
|
||||
host: {class: 'adf-pdf-viewer'},
|
||||
host: { class: 'adf-pdf-viewer' },
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
|
||||
@Input()
|
||||
urlFile: string;
|
||||
|
||||
@@ -98,7 +97,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
loadingTask: any;
|
||||
isPanelDisabled = true;
|
||||
showThumbnails: boolean = false;
|
||||
pdfThumbnailsContext: { viewer: any } = {viewer: null};
|
||||
pdfThumbnailsContext: { viewer: any } = { viewer: null };
|
||||
randomPdfId: string;
|
||||
|
||||
get currentScaleText(): string {
|
||||
@@ -119,13 +118,19 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
private dialog: MatDialog,
|
||||
private renderingQueueServices: RenderingQueueServices,
|
||||
private logService: LogService,
|
||||
private appConfigService: AppConfigService) {
|
||||
private appConfigService: AppConfigService
|
||||
) {
|
||||
// needed to preserve "this" context
|
||||
this.onPageChange = this.onPageChange.bind(this);
|
||||
this.onPagesLoaded = this.onPagesLoaded.bind(this);
|
||||
this.onPageRendered = this.onPageRendered.bind(this);
|
||||
this.randomPdfId = this.generateUuid();
|
||||
this.pdfjsWorkerDestroy$.pipe(catchError(() => null), delay(700)).subscribe(() => this.destroyPdJsWorker());
|
||||
this.randomPdfId = window.crypto.randomUUID();
|
||||
this.pdfjsWorkerDestroy$
|
||||
.pipe(
|
||||
catchError(() => null),
|
||||
delay(700)
|
||||
)
|
||||
.subscribe(() => this.destroyPdJsWorker());
|
||||
}
|
||||
|
||||
getUserScaling(): number {
|
||||
@@ -152,7 +157,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const blobFile = changes['blobFile'];
|
||||
|
||||
if (blobFile && blobFile.currentValue) {
|
||||
if (blobFile?.currentValue) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
const pdfOptions = {
|
||||
@@ -166,7 +171,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
const urlFile = changes['urlFile'];
|
||||
if (urlFile && urlFile.currentValue) {
|
||||
if (urlFile?.currentValue) {
|
||||
const pdfOptions = {
|
||||
...this.pdfjsDefaultOptions,
|
||||
url: urlFile.currentValue,
|
||||
@@ -200,14 +205,15 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
this.loadingPercent = Math.round(level * 100);
|
||||
};
|
||||
|
||||
this.loadingTask.promise.then((pdfDocument: PDFDocumentProxy) => {
|
||||
this.totalPages = pdfDocument.numPages;
|
||||
this.page = 1;
|
||||
this.displayPage = 1;
|
||||
this.initPDFViewer(pdfDocument);
|
||||
this.loadingTask.promise
|
||||
.then((pdfDocument: PDFDocumentProxy) => {
|
||||
this.totalPages = pdfDocument.numPages;
|
||||
this.page = 1;
|
||||
this.displayPage = 1;
|
||||
this.initPDFViewer(pdfDocument);
|
||||
|
||||
return pdfDocument.getPage(1);
|
||||
})
|
||||
return pdfDocument.getPage(1);
|
||||
})
|
||||
.then(() => this.scalePage('init'))
|
||||
.catch(() => this.error.emit());
|
||||
}
|
||||
@@ -276,9 +282,8 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
const documentContainer = this.getDocumentContainer();
|
||||
|
||||
if (this.pdfViewer && documentContainer) {
|
||||
|
||||
let widthContainer;
|
||||
let heightContainer;
|
||||
let widthContainer: number;
|
||||
let heightContainer: number;
|
||||
|
||||
if (viewerContainer && viewerContainer.clientWidth <= documentContainer.clientWidth) {
|
||||
widthContainer = viewerContainer.clientWidth;
|
||||
@@ -291,10 +296,10 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
const currentPage = this.pdfViewer._pages[this.pdfViewer._currentPageNumber - 1];
|
||||
|
||||
const padding = 20;
|
||||
const pageWidthScale = (widthContainer - padding) / currentPage.width * currentPage.scale;
|
||||
const pageHeightScale = (heightContainer - padding) / currentPage.width * currentPage.scale;
|
||||
const pageWidthScale = ((widthContainer - padding) / currentPage.width) * currentPage.scale;
|
||||
const pageHeightScale = ((heightContainer - padding) / currentPage.width) * currentPage.scale;
|
||||
|
||||
let scale;
|
||||
let scale: number;
|
||||
switch (this.currentScaleMode) {
|
||||
case 'init':
|
||||
scale = this.getUserScaling();
|
||||
@@ -322,7 +327,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
|
||||
break;
|
||||
default:
|
||||
this.logService.error('pdfViewSetScale: \'' + scaleMode + '\' is an unknown zoom value.');
|
||||
this.logService.error(`pdfViewSetScale: '${scaleMode}' is an unknown zoom value.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -331,7 +336,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
private autoScaling(pageHeightScale: number, pageWidthScale: number) {
|
||||
let horizontalScale;
|
||||
let horizontalScale: number;
|
||||
if (this.isLandscape) {
|
||||
horizontalScale = Math.min(pageHeightScale, pageWidthScale);
|
||||
} else {
|
||||
@@ -387,7 +392,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
*
|
||||
*/
|
||||
isSameScale(oldScale: number, newScale: number): boolean {
|
||||
return (newScale === oldScale);
|
||||
return newScale === oldScale;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,7 +402,7 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
* @param height
|
||||
*/
|
||||
isLandscape(width: number, height: number): boolean {
|
||||
return (width > height);
|
||||
return width > height;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,15 +512,16 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
this.dialog
|
||||
.open(PdfPasswordDialogComponent, {
|
||||
width: '400px',
|
||||
data: {reason}
|
||||
data: { reason }
|
||||
})
|
||||
.afterClosed().subscribe((password) => {
|
||||
if (password) {
|
||||
callback(password);
|
||||
} else {
|
||||
this.close.emit();
|
||||
}
|
||||
});
|
||||
.afterClosed()
|
||||
.subscribe((password) => {
|
||||
if (password) {
|
||||
callback(password);
|
||||
} else {
|
||||
this.close.emit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -528,7 +534,6 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
/**
|
||||
* Pages Loaded Event
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
onPagesLoaded() {
|
||||
this.isPanelDisabled = false;
|
||||
@@ -537,23 +542,17 @@ export class PdfViewerComponent implements OnChanges, OnDestroy {
|
||||
/**
|
||||
* Keyboard Event Listener
|
||||
*
|
||||
* @param KeyboardEvent event
|
||||
* @param event KeyboardEvent
|
||||
*/
|
||||
@HostListener('document:keydown', ['$event'])
|
||||
handleKeyboardEvent(event: KeyboardEvent) {
|
||||
const key = event.keyCode;
|
||||
if (key === 39) { // right arrow
|
||||
if (key === 39) {
|
||||
// right arrow
|
||||
this.nextPage();
|
||||
} else if (key === 37) {// left arrow
|
||||
} else if (key === 37) {
|
||||
// left arrow
|
||||
this.previousPage();
|
||||
}
|
||||
}
|
||||
|
||||
private generateUuid() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,6 @@ import { AppConfigService } from '../../app-config/app-config.service';
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class TxtViewerComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
urlFile: any;
|
||||
|
||||
@@ -36,18 +35,16 @@ export class TxtViewerComponent implements OnChanges {
|
||||
|
||||
content: string | ArrayBuffer;
|
||||
|
||||
constructor(private http: HttpClient, private appConfigService: AppConfigService) {
|
||||
}
|
||||
constructor(private http: HttpClient, private appConfigService: AppConfigService) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): Promise<void> {
|
||||
|
||||
const blobFile = changes['blobFile'];
|
||||
if (blobFile && blobFile.currentValue) {
|
||||
if (blobFile?.currentValue) {
|
||||
return this.readBlob(blobFile.currentValue);
|
||||
}
|
||||
|
||||
const urlFile = changes['urlFile'];
|
||||
if (urlFile && urlFile.currentValue) {
|
||||
if (urlFile?.currentValue) {
|
||||
return this.getUrlContent(urlFile.currentValue);
|
||||
}
|
||||
|
||||
@@ -62,12 +59,15 @@ export class TxtViewerComponent implements OnChanges {
|
||||
const withCredentialsMode = this.appConfigService.get<boolean>('auth.withCredentials', false);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.http.get(url, { responseType: 'text', withCredentials: withCredentialsMode }).subscribe((res) => {
|
||||
this.content = res;
|
||||
resolve();
|
||||
}, (event) => {
|
||||
reject(event);
|
||||
});
|
||||
this.http.get(url, { responseType: 'text', withCredentials: withCredentialsMode }).subscribe(
|
||||
(res) => {
|
||||
this.content = res;
|
||||
resolve();
|
||||
},
|
||||
(event) => {
|
||||
reject(event);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -54,12 +54,11 @@ const DEFAULT_NON_PREVIEW_CONFIG = {
|
||||
selector: 'adf-viewer',
|
||||
templateUrl: './viewer.component.html',
|
||||
styleUrls: ['./viewer.component.scss'],
|
||||
host: {class: 'adf-viewer'},
|
||||
host: { class: 'adf-viewer' },
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
providers: [ViewUtilService]
|
||||
})
|
||||
export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
||||
|
||||
@ContentChild(ViewerToolbarComponent)
|
||||
toolbar: ViewerToolbarComponent;
|
||||
|
||||
@@ -220,24 +219,23 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
||||
public downloadPromptTimer: number;
|
||||
public downloadPromptReminderTimer: number;
|
||||
|
||||
constructor(private el: ElementRef,
|
||||
public dialog: MatDialog,
|
||||
private viewUtilsService: ViewUtilService,
|
||||
private appConfigService: AppConfigService
|
||||
) {
|
||||
}
|
||||
constructor(
|
||||
private el: ElementRef,
|
||||
public dialog: MatDialog,
|
||||
private viewUtilsService: ViewUtilService,
|
||||
private appConfigService: AppConfigService
|
||||
) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges){
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const { blobFile, urlFile } = changes;
|
||||
|
||||
if(blobFile?.currentValue){
|
||||
if (blobFile?.currentValue) {
|
||||
this.mimeType = blobFile.currentValue.type;
|
||||
}
|
||||
|
||||
if(urlFile?.currentValue){
|
||||
if (urlFile?.currentValue) {
|
||||
this.fileName = this.fileName ? this.fileName : this.viewUtilsService.getFilenameFromUrl(urlFile.currentValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -246,27 +244,33 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
||||
}
|
||||
|
||||
private closeOverlayManager() {
|
||||
this.dialog.afterOpened.pipe(
|
||||
skipWhile(() => !this.overlayMode),
|
||||
takeUntil(this.onDestroy$)
|
||||
).subscribe(() => this.closeViewer = false);
|
||||
this.dialog.afterOpened
|
||||
.pipe(
|
||||
skipWhile(() => !this.overlayMode),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(() => (this.closeViewer = false));
|
||||
|
||||
this.dialog.afterAllClosed.pipe(
|
||||
skipWhile(() => !this.overlayMode),
|
||||
takeUntil(this.onDestroy$)
|
||||
).subscribe(() => this.closeViewer = true);
|
||||
this.dialog.afterAllClosed
|
||||
.pipe(
|
||||
skipWhile(() => !this.overlayMode),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe(() => (this.closeViewer = true));
|
||||
|
||||
this.keyDown$.pipe(
|
||||
skipWhile(() => !this.overlayMode),
|
||||
filter((e: KeyboardEvent) => e.keyCode === 27),
|
||||
takeUntil(this.onDestroy$)
|
||||
).subscribe((event: KeyboardEvent) => {
|
||||
event.preventDefault();
|
||||
this.keyDown$
|
||||
.pipe(
|
||||
skipWhile(() => !this.overlayMode),
|
||||
filter((e: KeyboardEvent) => e.keyCode === 27),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe((event: KeyboardEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.closeViewer) {
|
||||
this.onClose();
|
||||
}
|
||||
});
|
||||
if (this.closeViewer) {
|
||||
this.onClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onNavigateBeforeClick(event: MouseEvent | KeyboardEvent) {
|
||||
@@ -295,7 +299,7 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
||||
|
||||
@HostListener('document:keyup', ['$event'])
|
||||
handleKeyboardEvent(event: KeyboardEvent) {
|
||||
if (event && event.defaultPrevented) {
|
||||
if (event?.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -392,20 +396,24 @@ export class ViewerComponent<T> implements OnDestroy, OnInit, OnChanges {
|
||||
private showDownloadPrompt() {
|
||||
if (!this.isDialogVisible) {
|
||||
this.isDialogVisible = true;
|
||||
this.dialog.open(DownloadPromptDialogComponent, { disableClose: true }).afterClosed().pipe(first()).subscribe((result: DownloadPromptActions) => {
|
||||
this.isDialogVisible = false;
|
||||
if (result === DownloadPromptActions.DOWNLOAD) {
|
||||
this.downloadFile.emit();
|
||||
this.onClose();
|
||||
} else if (result === DownloadPromptActions.WAIT) {
|
||||
if (this.enableDownloadPromptReminder) {
|
||||
this.clearDownloadPromptTimeouts();
|
||||
this.downloadPromptReminderTimer = window.setTimeout(() => {
|
||||
this.showOrClearDownloadPrompt();
|
||||
}, this.downloadPromptReminderDelay * 1000);
|
||||
this.dialog
|
||||
.open(DownloadPromptDialogComponent, { disableClose: true })
|
||||
.afterClosed()
|
||||
.pipe(first())
|
||||
.subscribe((result: DownloadPromptActions) => {
|
||||
this.isDialogVisible = false;
|
||||
if (result === DownloadPromptActions.DOWNLOAD) {
|
||||
this.downloadFile.emit();
|
||||
this.onClose();
|
||||
} else if (result === DownloadPromptActions.WAIT) {
|
||||
if (this.enableDownloadPromptReminder) {
|
||||
this.clearDownloadPromptTimeouts();
|
||||
this.downloadPromptReminderTimer = window.setTimeout(() => {
|
||||
this.showOrClearDownloadPrompt();
|
||||
}, this.downloadPromptReminderDelay * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"paths": {
|
||||
"@alfresco/adf-extensions": ["../../../dist/libs/extensions"],
|
||||
|
Reference in New Issue
Block a user