Browse Source

Merge pull request #10581 from abpframework/angular/strict-mode

Angular UI: Fixed some errors due to ts strict mode
pull/10601/head
Bunyamin Coskuner 5 years ago
committed by GitHub
parent
commit
6e848aa262
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts
  2. 10
      npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts
  3. 16
      npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts
  4. 2
      npm/ng-packs/packages/core/src/lib/models/common.ts
  5. 4
      npm/ng-packs/packages/core/src/lib/models/replaceable-components.ts
  6. 23
      npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts
  7. 8
      npm/ng-packs/packages/core/src/lib/services/config-state.service.ts
  8. 4
      npm/ng-packs/packages/core/src/lib/services/environment.service.ts
  9. 2
      npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts
  10. 2
      npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
  11. 4
      npm/ng-packs/packages/core/src/lib/services/list.service.ts
  12. 4
      npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts
  13. 4
      npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html
  14. 2
      npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.ts
  15. 2
      npm/ng-packs/packages/setting-management/config/src/providers/features.token.ts
  16. 4
      npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts
  17. 8
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html
  18. 12
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts
  19. 2
      npm/ng-packs/packages/tenant-management/src/lib/defaults/default-tenants-toolbar-actions.ts
  20. 2
      npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html
  21. 2
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
  22. 6
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts
  23. 2
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html
  24. 9
      npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html
  25. 6
      npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts
  26. 2
      npm/ng-packs/packages/theme-basic/src/lib/components/validation-error/validation-error.component.ts
  27. 8
      npm/ng-packs/packages/theme-basic/src/lib/handlers/lazy-style.handler.ts
  28. 6
      npm/ng-packs/packages/theme-basic/src/lib/services/layout.service.ts
  29. 9
      npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date-time.adapter.ts
  30. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date.adapter.ts
  31. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/time.adapter.ts
  32. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/abstract-actions/abstract-actions.component.ts
  33. 6
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/date-time-picker/date-time-picker.component.ts
  34. 18
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.ts
  35. 6
      npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form.component.ts
  36. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/directives/disabled.directive.ts
  37. 6
      npm/ng-packs/packages/theme-shared/extensions/src/lib/directives/prop-data.directive.ts
  38. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/models/actions.ts
  39. 2
      npm/ng-packs/packages/theme-shared/extensions/src/lib/models/props.ts
  40. 4
      npm/ng-packs/packages/theme-shared/extensions/src/lib/models/toolbar-actions.ts
  41. 10
      npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/enum.util.ts
  42. 10
      npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/localization.util.ts
  43. 9
      npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts
  44. 16
      npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/typeahead.util.ts
  45. 5
      npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/validation.util.ts
  46. 3
      npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb-items/breadcrumb-items.component.ts
  47. 12
      npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts
  48. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts
  49. 24
      npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts
  50. 2
      npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts
  51. 2
      npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-ref.service.ts
  52. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html
  53. 38
      npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
  54. 14
      npm/ng-packs/packages/theme-shared/src/lib/components/toast-container/toast-container.component.ts
  55. 2
      npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.html
  56. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts
  57. 4
      npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts
  58. 12
      npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts
  59. 2
      npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts
  60. 74
      npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts
  61. 2
      npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts
  62. 6
      npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts
  63. 4
      npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts
  64. 7
      npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts
  65. 1
      npm/ng-packs/tsconfig.json
  66. 3113
      npm/ng-packs/yarn.lock

12
npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts

@ -5,12 +5,20 @@ import { AfterViewInit, Directive, ElementRef, Input } from '@angular/core';
selector: '[autofocus]', selector: '[autofocus]',
}) })
export class AutofocusDirective implements AfterViewInit { export class AutofocusDirective implements AfterViewInit {
private _delay = 0;
@Input('autofocus') @Input('autofocus')
delay = 0; set delay(val: number | string | undefined) {
this._delay = Number(val) || 0;
}
get delay() {
return this._delay;
}
constructor(private elRef: ElementRef) {} constructor(private elRef: ElementRef) {}
ngAfterViewInit(): void { ngAfterViewInit(): void {
setTimeout(() => this.elRef.nativeElement.focus(), this.delay); setTimeout(() => this.elRef.nativeElement.focus(), this.delay as number);
} }
} }

10
npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts

@ -1,12 +1,10 @@
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Directive, Directive,
ElementRef,
Input, Input,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
Optional, Optional,
Renderer2,
TemplateRef, TemplateRef,
ViewContainerRef, ViewContainerRef,
} from '@angular/core'; } from '@angular/core';
@ -18,13 +16,11 @@ import { PermissionService } from '../services/permission.service';
selector: '[abpPermission]', selector: '[abpPermission]',
}) })
export class PermissionDirective implements OnDestroy, OnChanges { export class PermissionDirective implements OnDestroy, OnChanges {
@Input('abpPermission') condition: string; @Input('abpPermission') condition: string | undefined;
subscription: Subscription; subscription!: Subscription;
constructor( constructor(
private elRef: ElementRef<HTMLElement>,
private renderer: Renderer2,
@Optional() private templateRef: TemplateRef<any>, @Optional() private templateRef: TemplateRef<any>,
private vcRef: ViewContainerRef, private vcRef: ViewContainerRef,
private permissionService: PermissionService, private permissionService: PermissionService,
@ -37,7 +33,7 @@ export class PermissionDirective implements OnDestroy, OnChanges {
} }
this.subscription = this.permissionService this.subscription = this.permissionService
.getGrantedPolicy$(this.condition) .getGrantedPolicy$(this.condition || '')
.pipe(distinctUntilChanged()) .pipe(distinctUntilChanged())
.subscribe(isGranted => { .subscribe(isGranted => {
this.vcRef.clear(); this.vcRef.clear();

16
npm/ng-packs/packages/core/src/lib/directives/replaceable-template.directive.ts

@ -33,7 +33,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
context = {} as any; context = {} as any;
externalComponent: Type<any>; externalComponent!: Type<any>;
defaultComponentRef: any; defaultComponentRef: any;
@ -50,7 +50,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
private subscription: SubscriptionService, private subscription: SubscriptionService,
) { ) {
this.context = { this.context = {
initTemplate: ref => { initTemplate: (ref: any) => {
this.resetDefaultComponent(); this.resetDefaultComponent();
this.defaultComponentRef = ref; this.defaultComponentRef = ref;
this.setDefaultComponentInputs(); this.setDefaultComponentInputs();
@ -121,8 +121,8 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
if (Object.prototype.hasOwnProperty.call(this.data.outputs, key)) { if (Object.prototype.hasOwnProperty.call(this.data.outputs, key)) {
if (!this.defaultComponentSubscriptions[key]) { if (!this.defaultComponentSubscriptions[key]) {
this.defaultComponentSubscriptions[key] = this.defaultComponentRef[key].subscribe( this.defaultComponentSubscriptions[key] = this.defaultComponentRef[key].subscribe(
value => { (value: any) => {
this.data.outputs[key](value); this.data.outputs?.[key](value);
}, },
); );
} }
@ -132,7 +132,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
} }
setProvidedData() { setProvidedData() {
this.providedData = { ...this.data, inputs: {} }; this.providedData = { ...this.data, inputs: {}, outputs: {} };
if (!this.data.inputs) return; if (!this.data.inputs) return;
Object.defineProperties(this.providedData.inputs, { Object.defineProperties(this.providedData.inputs, {
@ -142,9 +142,9 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
[key]: { [key]: {
enumerable: true, enumerable: true,
configurable: true, configurable: true,
get: () => this.data.inputs[key].value, get: () => this.data.inputs[key]?.value,
...(this.data.inputs[key].twoWay && { ...(this.data.inputs[key]?.twoWay && {
set: newValue => { set: (newValue: any) => {
this.data.inputs[key].value = newValue; this.data.inputs[key].value = newValue;
this.data.outputs[`${key}Change`](newValue); this.data.outputs[`${key}Change`](newValue);
}, },

2
npm/ng-packs/packages/core/src/lib/models/common.ts

@ -52,7 +52,7 @@ export namespace ABP {
} }
export interface Route extends Nav { export interface Route extends Nav {
path: string; path?: string;
layout?: eLayoutType; layout?: eLayoutType;
iconClass?: string; iconClass?: string;
} }

4
npm/ng-packs/packages/core/src/lib/models/replaceable-components.ts

@ -16,8 +16,8 @@ export namespace ReplaceableComponents {
I, I,
O extends { [K in keyof O]: EventEmitter<any> | Subject<any> }, O extends { [K in keyof O]: EventEmitter<any> | Subject<any> },
> { > {
inputs: { -readonly [K in keyof I]: { value: I[K]; twoWay?: boolean } }; inputs?: { -readonly [K in keyof I]: { value: I[K]; twoWay?: boolean } };
outputs: { -readonly [K in keyof O]: (value: ABP.ExtractFromOutput<O[K]>) => void }; outputs?: { -readonly [K in keyof O]: (value: ABP.ExtractFromOutput<O[K]>) => void };
componentKey: string; componentKey: string;
} }

23
npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts

@ -9,13 +9,20 @@ import { LocalizationService } from '../services/localization.service';
export class LocalizationPipe implements PipeTransform { export class LocalizationPipe implements PipeTransform {
constructor(private localization: LocalizationService) {} constructor(private localization: LocalizationService) {}
transform(value: string | LocalizationWithDefault = '', ...interpolateParams: string[]): string { transform(
return this.localization.instant( value: string | LocalizationWithDefault = '',
value, ...interpolateParams: (string | string[] | undefined)[]
...interpolateParams.reduce( ): string {
(acc, val) => (Array.isArray(val) ? [...acc, ...val] : [...acc, val]), const params =
[], interpolateParams.reduce((acc, val) => {
), if (!acc) {
); return val;
}
if (!val) {
return acc;
}
return Array.isArray(val) ? [...acc, ...val] : [...acc, val];
}, []) || [];
return this.localization.instant(value, ...params);
} }
} }

8
npm/ng-packs/packages/core/src/lib/services/config-state.service.ts

@ -48,14 +48,14 @@ export class ConfigStateService {
return this.store.state; return this.store.state;
} }
getDeep$(keys: string[] | string) { getDeep$(keys: string[] | string): Observable<any> {
keys = splitKeys(keys); keys = splitKeys(keys);
return this.store return this.store
.sliceState(state => state) .sliceState(state => state)
.pipe( .pipe(
map(state => { map(state => {
return (keys as string[]).reduce((acc, val) => { return (keys as string[]).reduce((acc: any, val) => {
if (acc) { if (acc) {
return acc[val]; return acc[val];
} }
@ -66,10 +66,10 @@ export class ConfigStateService {
); );
} }
getDeep(keys: string[] | string) { getDeep(keys: string[] | string): any {
keys = splitKeys(keys); keys = splitKeys(keys);
return (keys as string[]).reduce((acc, val) => { return (keys as string[]).reduce((acc: any, val) => {
if (acc) { if (acc) {
return acc[val]; return acc[val];
} }

4
npm/ng-packs/packages/core/src/lib/services/environment.service.ts

@ -23,11 +23,11 @@ export class EnvironmentService {
return this.store.state; return this.store.state;
} }
getApiUrl(key?: string) { getApiUrl(key: string) {
return mapToApiUrl(key)(this.store.state.apis); return mapToApiUrl(key)(this.store.state.apis);
} }
getApiUrl$(key?: string) { getApiUrl$(key: string) {
return this.store.sliceState(state => state.apis).pipe(map(mapToApiUrl(key))); return this.store.sliceState(state => state.apis).pipe(map(mapToApiUrl(key)));
} }

2
npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts

@ -4,7 +4,7 @@ import { BehaviorSubject, Subject } from 'rxjs';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class HttpErrorReporterService { export class HttpErrorReporterService {
private _reporter$ = new Subject(); private _reporter$ = new Subject<HttpErrorResponse>();
private _errors$ = new BehaviorSubject<HttpErrorResponse[]>([]); private _errors$ = new BehaviorSubject<HttpErrorResponse[]>([]);
get reporter$() { get reporter$() {

2
npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts

@ -8,7 +8,7 @@ import { ResourceWaitService } from './resource-wait.service';
providedIn: 'root', providedIn: 'root',
}) })
export class LazyLoadService { export class LazyLoadService {
readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement>(); readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement | null>();
constructor(private resourceWaitService: ResourceWaitService) {} constructor(private resourceWaitService: ResourceWaitService) {}

4
npm/ng-packs/packages/core/src/lib/services/list.service.ts

@ -21,7 +21,7 @@ import { PagedResultDto } from '../models/dtos';
import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token'; import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token';
@Injectable() @Injectable()
export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDestroy { export class ListService<QueryParamsType = ABP.PageQueryParams | any> implements OnDestroy {
private _filter = ''; private _filter = '';
set filter(value: string) { set filter(value: string) {
this._filter = value; this._filter = value;
@ -112,7 +112,7 @@ export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDes
switchMap(query => streamCreatorCallback(query).pipe(catchError(() => of(null)))), switchMap(query => streamCreatorCallback(query).pipe(catchError(() => of(null)))),
filter(Boolean), filter(Boolean),
tap(() => this._isLoading$.next(false)), tap(() => this._isLoading$.next(false)),
shareReplay({ bufferSize: 1, refCount: true }), shareReplay<any>({ bufferSize: 1, refCount: true }),
takeUntil(this.destroy$), takeUntil(this.destroy$),
); );
} }

4
npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts

@ -35,7 +35,7 @@ export function createLocalizationPipeKeyGenerator(
) { ) {
const findLocalization = createLocalizationFinder(localization); const findLocalization = createLocalizationFinder(localization);
return (resourceNames: string[], keys: string[], defaultKey: string) => { return (resourceNames: string[], keys: string[], defaultKey: string | undefined) => {
const { resourceName, key } = findLocalization(resourceNames, keys); const { resourceName, key } = findLocalization(resourceNames, keys);
return !resourceName ? defaultKey : resourceName === '_' ? key : `${resourceName}::${key}`; return !resourceName ? defaultKey : resourceName === '_' ? key : `${resourceName}::${key}`;
}; };
@ -45,7 +45,7 @@ function createLocalizationFinder(localization: ApplicationLocalizationConfigura
const localize = createLocalizer(localization); const localize = createLocalizer(localization);
return (resourceNames: string[], keys: string[]) => { return (resourceNames: string[], keys: string[]) => {
resourceNames = resourceNames.concat(localization.defaultResourceName).filter(Boolean); resourceNames = resourceNames.concat(localization.defaultResourceName || '').filter(Boolean);
const resourceCount = resourceNames.length; const resourceCount = resourceNames.length;
const keyCount = keys.length; const keyCount = keys.length;

4
npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.html

@ -2,7 +2,7 @@
<hr class="my-3" /> <hr class="my-3" />
<form *ngIf="form" [formGroup]="form" (ngSubmit)="submit()" validateOnSubmit> <form *ngIf="form" [formGroup]="form" (ngSubmit)="submit()" [validateOnSubmit]="true">
<div class="mb-3 form-group"> <div class="mb-3 form-group">
<label class="form-label">{{ <label class="form-label">{{
'AbpSettingManagement::DefaultFromDisplayName' | abpLocalization 'AbpSettingManagement::DefaultFromDisplayName' | abpLocalization
@ -49,7 +49,7 @@
<div <div
[@collapse]="{ [@collapse]="{
value: form.get('smtpUseDefaultCredentials').value ? 'collapsed' : 'expanded', value: form.get('smtpUseDefaultCredentials')?.value ? 'collapsed' : 'expanded',
params: { time: '200ms', easing: 'linear' } params: { time: '200ms', easing: 'linear' }
}" }"
> >

2
npm/ng-packs/packages/setting-management/config/src/components/email-setting-group/email-setting-group.component.ts

@ -11,7 +11,7 @@ import { EmailSettingsDto } from '../../proxy/models';
animations: [collapse], animations: [collapse],
}) })
export class EmailSettingGroupComponent implements OnInit { export class EmailSettingGroupComponent implements OnInit {
form: FormGroup; form!: FormGroup;
saving = false; saving = false;

2
npm/ng-packs/packages/setting-management/config/src/providers/features.token.ts

@ -10,7 +10,7 @@ export const SETTING_MANAGEMENT_FEATURES = new InjectionToken<Observable<{ enabl
factory: () => { factory: () => {
const configState = inject(ConfigStateService); const configState = inject(ConfigStateService);
const featureKey = 'SettingManagement.Enable'; const featureKey = 'SettingManagement.Enable';
const mapFn = features => ({ const mapFn = (features: Record<string, string>) => ({
enable: features[featureKey].toLowerCase() !== 'false', enable: features[featureKey].toLowerCase() !== 'false',
}); });
return featuresFactory(configState, [featureKey], mapFn); return featuresFactory(configState, [featureKey], mapFn);

4
npm/ng-packs/packages/setting-management/src/lib/components/setting-management.component.ts

@ -1,6 +1,6 @@
import { ABP } from '@abp/ng.core'; import { ABP } from '@abp/ng.core';
import { Component, OnDestroy, OnInit, TrackByFunction } from '@angular/core';
import { SettingTabsService } from '@abp/ng.setting-management/config'; import { SettingTabsService } from '@abp/ng.setting-management/config';
import { Component, OnDestroy, OnInit, TrackByFunction } from '@angular/core';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
@Component({ @Component({
@ -11,7 +11,7 @@ export class SettingManagementComponent implements OnDestroy, OnInit {
private subscription = new Subscription(); private subscription = new Subscription();
settings: ABP.Tab[] = []; settings: ABP.Tab[] = [];
selected: ABP.Tab; selected!: ABP.Tab;
trackByFn: TrackByFunction<ABP.Tab> = (_, item) => item.name; trackByFn: TrackByFunction<ABP.Tab> = (_, item) => item.name;

8
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html

@ -23,8 +23,8 @@
</div> </div>
<abp-extensible-table <abp-extensible-table
[data]="data.items" [data]="data.items || []"
[recordsTotal]="data.totalCount" [recordsTotal]="data.totalCount || 0"
[list]="list" [list]="list"
></abp-extensible-table> ></abp-extensible-table>
</div> </div>
@ -41,7 +41,7 @@
</ng-template> </ng-template>
<ng-template #abpBody> <ng-template #abpBody>
<form [formGroup]="tenantForm" (ngSubmit)="save()" validateOnSubmit> <form [formGroup]="tenantForm" (ngSubmit)="save()" [validateOnSubmit]="true">
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> <abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form> </form>
</ng-template> </ng-template>
@ -63,7 +63,7 @@
providerKey: { value: providerKey }, providerKey: { value: providerKey },
visible: { value: visibleFeatures, twoWay: true } visible: { value: visibleFeatures, twoWay: true }
}, },
outputs: { visibleChange: onVisibleFeaturesChange }, outputs: { visibleChange: $any(onVisibleFeaturesChange) },
componentKey: featureManagementKey componentKey: featureManagementKey
}" }"
[(visible)]="visibleFeatures" [(visible)]="visibleFeatures"

12
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts

@ -26,17 +26,15 @@ import { eTenantManagementComponents } from '../../enums/components';
export class TenantsComponent implements OnInit { export class TenantsComponent implements OnInit {
data: PagedResultDto<TenantDto> = { items: [], totalCount: 0 }; data: PagedResultDto<TenantDto> = { items: [], totalCount: 0 };
selected: TenantDto; selected!: TenantDto;
tenantForm: FormGroup; tenantForm!: FormGroup;
isModalVisible: boolean; isModalVisible!: boolean;
visibleFeatures = false; visibleFeatures = false;
providerKey: string; providerKey!: string;
_useSharedDatabase: boolean;
modalBusy = false; modalBusy = false;
@ -142,7 +140,7 @@ export class TenantsComponent implements OnInit {
}, 0); }, 0);
} }
sort(data) { sort(data: any) {
const { prop, dir } = data.sorts[0]; const { prop, dir } = data.sorts[0];
this.list.sortKey = prop; this.list.sortKey = prop;
this.list.sortOrder = dir; this.list.sortOrder = dir;

2
npm/ng-packs/packages/tenant-management/src/lib/defaults/default-tenants-toolbar-actions.ts

@ -7,7 +7,7 @@ export const DEFAULT_TENANTS_TOOLBAR_ACTIONS = ToolbarAction.createMany<TenantDt
text: 'AbpTenantManagement::ManageHostFeatures', text: 'AbpTenantManagement::ManageHostFeatures',
action: data => { action: data => {
const component = data.getInjected(TenantsComponent); const component = data.getInjected(TenantsComponent);
component.openFeaturesModal(null); component.openFeaturesModal('');
}, },
permission: 'FeatureManagement.ManageHostFeatures', permission: 'FeatureManagement.ManageHostFeatures',
icon: 'fa fa-cog', icon: 'fa fa-cog',

2
npm/ng-packs/packages/theme-basic/src/lib/components/account-layout/tenant-box/tenant-box.component.html

@ -1,4 +1,4 @@
<ng-container *ngIf="(service.currentTenant$ | async) || {} as currentTenant"> <ng-container *ngIf="(service.currentTenant$ | async) || { name: '' } as currentTenant">
<div class="card shadow-sm rounded mb-3"> <div class="card shadow-sm rounded mb-3">
<div class="card-body px-5"> <div class="card-body px-5">
<div class="row"> <div class="row">

2
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts

@ -21,7 +21,7 @@ export class CurrentUserComponent {
} }
constructor( constructor(
@Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile, @Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile: () => void,
private authService: AuthService, private authService: AuthService,
private configState: ConfigStateService, private configState: ConfigStateService,
private sessionState: SessionStateService, private sessionState: SessionStateService,

6
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts

@ -7,7 +7,7 @@ import { map } from 'rxjs/operators';
selector: 'abp-languages', selector: 'abp-languages',
template: ` template: `
<div <div
*ngIf="(dropdownLanguages$ | async)?.length > 0" *ngIf="((dropdownLanguages$ | async)?.length || 0) > 0"
class="dropdown" class="dropdown"
ngbDropdown ngbDropdown
#languageDropdown="ngbDropdown" #languageDropdown="ngbDropdown"
@ -34,7 +34,7 @@ import { map } from 'rxjs/operators';
*ngFor="let lang of dropdownLanguages$ | async" *ngFor="let lang of dropdownLanguages$ | async"
href="javascript:void(0)" href="javascript:void(0)"
class="dropdown-item" class="dropdown-item"
(click)="onChangeLang(lang.cultureName)" (click)="onChangeLang(lang.cultureName || '')"
>{{ lang?.displayName }}</a >{{ lang?.displayName }}</a
> >
</div> </div>
@ -52,7 +52,7 @@ export class LanguagesComponent {
return this.languages$.pipe( return this.languages$.pipe(
map( map(
languages => languages =>
languages?.find(lang => lang.cultureName === this.selectedLangCulture).displayName || '', languages?.find(lang => lang.cultureName === this.selectedLangCulture)?.displayName || '',
), ),
); );
} }

2
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html

@ -1,6 +1,6 @@
<ul class="navbar-nav"> <ul class="navbar-nav">
<ng-container *ngFor="let item of navItems.items$ | async; trackBy: trackByFn"> <ng-container *ngFor="let item of navItems.items$ | async; trackBy: trackByFn">
<ng-container *ngIf="item.visible()"> <ng-container *ngIf="item.visible && item.visible()">
<li class="nav-item d-flex align-items-center" *abpPermission="item.requiredPolicy"> <li class="nav-item d-flex align-items-center" *abpPermission="item.requiredPolicy">
<ng-container <ng-container
*ngIf="item.component; else htmlTemplate" *ngIf="item.component; else htmlTemplate"

9
npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html

@ -18,14 +18,13 @@
<ng-template #dropdownLink let-route> <ng-template #dropdownLink let-route>
<ng-container *ngIf="route.children?.length"> <ng-container *ngIf="route.children?.length">
<li <li
#navbarRootDropdown
class="nav-item dropdown" class="nav-item dropdown"
display="static" display="static"
*abpPermission="route.requiredPolicy" *abpPermission="route.requiredPolicy"
(click)=" (click)="
navbarRootDropdown.expand rootDropdownExpand[route.name]
? (navbarRootDropdown.expand = false) ? (rootDropdownExpand[route.name] = false)
: (navbarRootDropdown.expand = true) : (rootDropdownExpand[route.name] = true)
" "
> >
<a <a
@ -42,7 +41,7 @@
#routeContainer #routeContainer
class="dropdown-menu border-0 shadow-sm" class="dropdown-menu border-0 shadow-sm"
(click)="$event.preventDefault(); $event.stopPropagation()" (click)="$event.preventDefault(); $event.stopPropagation()"
[class.d-block]="smallScreen && navbarRootDropdown.expand" [class.d-block]="smallScreen && rootDropdownExpand[route.name]"
> >
<ng-container <ng-container
*ngTemplateOutlet="forTemplate; context: { $implicit: route }" *ngTemplateOutlet="forTemplate; context: { $implicit: route }"

6
npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts

@ -14,9 +14,11 @@ import {
templateUrl: 'routes.component.html', templateUrl: 'routes.component.html',
}) })
export class RoutesComponent { export class RoutesComponent {
@Input() smallScreen: boolean; @Input() smallScreen?: boolean;
@ViewChildren('childrenContainer') childrenContainers: QueryList<ElementRef<HTMLDivElement>>; @ViewChildren('childrenContainer') childrenContainers!: QueryList<ElementRef<HTMLDivElement>>;
rootDropdownExpand = {} as { [key: string]: boolean };
trackByFn: TrackByFunction<TreeNode<ABP.Route>> = (_, item) => item.name; trackByFn: TrackByFunction<TreeNode<ABP.Route>> = (_, item) => item.name;

2
npm/ng-packs/packages/theme-basic/src/lib/components/validation-error/validation-error.component.ts

@ -12,7 +12,7 @@ import { Validation, ValidationErrorComponent as ErrorComponent } from '@ngx-val
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
}) })
export class ValidationErrorComponent extends ErrorComponent { export class ValidationErrorComponent extends ErrorComponent {
get abpErrors(): Validation.Error[] & { interpoliteParams?: string[] } { get abpErrors(): (Validation.Error & { interpoliteParams?: string[] })[] {
if (!this.errors || !this.errors.length) return []; if (!this.errors || !this.errors.length) return [];
return this.errors.map(error => { return this.errors.map(error => {

8
npm/ng-packs/packages/theme-basic/src/lib/handlers/lazy-style.handler.ts

@ -6,8 +6,8 @@ export const BOOTSTRAP = 'bootstrap-{{dir}}.min.css';
@Injectable() @Injectable()
export class LazyStyleHandler { export class LazyStyleHandler {
private lazyLoad: LazyLoadService; private lazyLoad!: LazyLoadService;
private styles: string[]; private styles!: string[];
private _dir: LocaleDirection = 'ltr'; private _dir: LocaleDirection = 'ltr';
readonly loaded = new Map<string, HTMLLinkElement>(); readonly loaded = new Map<string, HTMLLinkElement>();
@ -29,7 +29,7 @@ export class LazyStyleHandler {
this.listenToDirectionChanges(injector); this.listenToDirectionChanges(injector);
} }
private getHrefFromLink(link: HTMLLinkElement | null): string { private getHrefFromLink(link: HTMLLinkElement | null | undefined): string {
if (!link) return ''; if (!link) return '';
const a = document.createElement('a'); const a = document.createElement('a');
@ -94,5 +94,5 @@ export function initLazyStyleHandler(injector: Injector) {
interface LoadedStyle { interface LoadedStyle {
href: string; href: string;
link: HTMLLinkElement; link: HTMLLinkElement | null;
} }

6
npm/ng-packs/packages/theme-basic/src/lib/services/layout.service.ts

@ -1,14 +1,14 @@
import { ChangeDetectorRef, Injectable } from '@angular/core';
import { eThemeBasicComponents } from '../enums';
import { SubscriptionService } from '@abp/ng.core'; import { SubscriptionService } from '@abp/ng.core';
import { ChangeDetectorRef, Injectable } from '@angular/core';
import { fromEvent } from 'rxjs'; import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators'; import { debounceTime } from 'rxjs/operators';
import { eThemeBasicComponents } from '../enums';
@Injectable() @Injectable()
export class LayoutService { export class LayoutService {
isCollapsed = true; isCollapsed = true;
smallScreen: boolean; // do not set true or false smallScreen!: boolean; // do not set true or false
logoComponentKey = eThemeBasicComponents.Logo; logoComponentKey = eThemeBasicComponents.Logo;

9
npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date-time.adapter.ts

@ -3,7 +3,7 @@ import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
@Injectable() @Injectable()
export class DateTimeAdapter { export class DateTimeAdapter {
value: NgbDateTimeStruct; value!: NgbDateTimeStruct;
fromModel(value: string | Date): NgbDateTimeStruct | null { fromModel(value: string | Date): NgbDateTimeStruct | null {
if (!value) return null; if (!value) return null;
@ -27,15 +27,16 @@ export class DateTimeAdapter {
toModel(value: NgbDateTimeStruct | null): string { toModel(value: NgbDateTimeStruct | null): string {
if (!value) return ''; if (!value) return '';
const now = new Date(); //const now = new Date();
value = { value = {
year: now.getUTCFullYear(), // TODO
/* year: now.getUTCFullYear(),
month: now.getMonth() + 1, month: now.getMonth() + 1,
day: now.getDate(), day: now.getDate(),
hour: 0, hour: 0,
minute: 0, minute: 0,
second: 0, second: 0, */
...this.value, ...this.value,
...value, ...value,
}; };

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date.adapter.ts

@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap'; import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
@Injectable() @Injectable()
export class DateAdapter extends NgbDateAdapter<string> { export class DateAdapter extends NgbDateAdapter<string | Date> {
fromModel(value: string | Date): NgbDateStruct | null { fromModel(value: string | Date): NgbDateStruct | null {
if (!value) return null; if (!value) return null;

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/time.adapter.ts

@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
import { NgbTimeAdapter, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap'; import { NgbTimeAdapter, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
@Injectable() @Injectable()
export class TimeAdapter extends NgbTimeAdapter<string> { export class TimeAdapter extends NgbTimeAdapter<string | Date> {
fromModel(value: string | Date): NgbTimeStruct | null { fromModel(value: string | Date): NgbTimeStruct | null {
if (!value) return null; if (!value) return null;

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/abstract-actions/abstract-actions.component.ts

@ -13,7 +13,7 @@ export abstract class AbstractActionsComponent<L extends ActionList<any>> extend
readonly getInjected: InferredData<L>['getInjected']; readonly getInjected: InferredData<L>['getInjected'];
@Input() readonly record: InferredData<L>['record']; @Input() record!: InferredData<L>['record'];
constructor(injector: Injector) { constructor(injector: Injector) {
super(); super();

6
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/date-time-picker/date-time-picker.component.ts

@ -58,11 +58,11 @@ import { selfFactory } from '../../utils/factory.util';
], ],
}) })
export class DateTimePickerComponent { export class DateTimePickerComponent {
@Input() prop: FormProp; @Input() prop!: FormProp;
@Input() meridian = false; @Input() meridian = false;
@ViewChild(NgbInputDatepicker) date: NgbInputDatepicker; @ViewChild(NgbInputDatepicker) date!: NgbInputDatepicker;
@ViewChild(NgbTimepicker) time: NgbTimepicker; @ViewChild(NgbTimepicker) time!: NgbTimepicker;
constructor(public readonly cdRef: ChangeDetectorRef) {} constructor(public readonly cdRef: ChangeDetectorRef) {}

18
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.ts

@ -46,13 +46,13 @@ import { addTypeaheadTextSuffix } from '../../utils/typeahead.util';
], ],
}) })
export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit {
@Input() data: PropData; @Input() data!: PropData;
@Input() prop: FormProp; @Input() prop!: FormProp;
@Input() first: boolean; @Input() first?: boolean;
@ViewChild('field') private fieldRef: ElementRef<HTMLElement>; @ViewChild('field') private fieldRef!: ElementRef<HTMLElement>;
asterisk = ''; asterisk = '';
@ -60,9 +60,9 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit {
validators: ValidatorFn[] = []; validators: ValidatorFn[] = [];
readonly: boolean; readonly!: boolean;
disabled: boolean; disabled!: boolean;
private readonly form: FormGroup; private readonly form: FormGroup;
@ -72,9 +72,9 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit {
this.typeaheadModel = selectedOption || { key: null, value: null }; this.typeaheadModel = selectedOption || { key: null, value: null };
const { key, value } = this.typeaheadModel; const { key, value } = this.typeaheadModel;
const [keyControl, valueControl] = this.getTypeaheadControls(); const [keyControl, valueControl] = this.getTypeaheadControls();
if (valueControl.value && !value) valueControl.markAsDirty(); if (valueControl?.value && !value) valueControl.markAsDirty();
keyControl.setValue(key); keyControl?.setValue(key);
valueControl.setValue(value); valueControl?.setValue(value);
} }
search = (text$: Observable<string>) => search = (text$: Observable<string>) =>

6
npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form.component.ts

@ -33,7 +33,7 @@ import { ExtensibleFormPropComponent } from './extensible-form-prop.component';
}) })
export class ExtensibleFormComponent<R = any> { export class ExtensibleFormComponent<R = any> {
@ViewChildren(ExtensibleFormPropComponent) @ViewChildren(ExtensibleFormPropComponent)
formProps: QueryList<ExtensibleFormPropComponent>; formProps!: QueryList<ExtensibleFormPropComponent>;
@Input() @Input()
set selectedRecord(record: R) { set selectedRecord(record: R) {
@ -43,8 +43,8 @@ export class ExtensibleFormComponent<R = any> {
} }
extraPropertiesKey = EXTRA_PROPERTIES_KEY; extraPropertiesKey = EXTRA_PROPERTIES_KEY;
propList: FormPropList<R>; propList!: FormPropList<R>;
record: R; record!: R;
get form(): FormGroup { get form(): FormGroup {
return (this.container ? this.container.control : { controls: {} }) as FormGroup; return (this.container ? this.container.control : { controls: {} }) as FormGroup;

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/directives/disabled.directive.ts

@ -6,7 +6,7 @@ import { NgControl } from '@angular/forms';
}) })
export class DisabledDirective implements OnChanges { export class DisabledDirective implements OnChanges {
@Input() @Input()
abpDisabled: boolean; abpDisabled = false;
constructor(@Host() private ngControl: NgControl) {} constructor(@Host() private ngControl: NgControl) {}

6
npm/ng-packs/packages/theme-shared/extensions/src/lib/directives/prop-data.directive.ts

@ -18,11 +18,11 @@ export class PropDataDirective<L extends PropList<any>>
extends PropData<InferredData<L>> extends PropData<InferredData<L>>
implements OnChanges, OnDestroy implements OnChanges, OnDestroy
{ {
@Input('abpPropDataFromList') readonly propList: L; @Input('abpPropDataFromList') propList?: L;
@Input('abpPropDataWithRecord') readonly record: InferredData<L>['record']; @Input('abpPropDataWithRecord') record!: InferredData<L>['record'];
@Input('abpPropDataAtIndex') readonly index: number; @Input('abpPropDataAtIndex') index?: number;
readonly getInjected: InferredData<L>['getInjected']; readonly getInjected: InferredData<L>['getInjected'];

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/models/actions.ts

@ -32,7 +32,7 @@ export abstract class Action<R = any> {
) {} ) {}
} }
export type ActionCallback<T, R = any> = (data?: Omit<ActionData<T>, 'data'>) => R; export type ActionCallback<T, R = any> = (data: Omit<ActionData<T>, 'data'>) => R;
export type ActionPredicate<T> = (data?: Omit<ActionData<T>, 'data'>) => boolean; export type ActionPredicate<T> = (data?: Omit<ActionData<T>, 'data'>) => boolean;
export abstract class ActionsFactory<C extends Actions<any>> { export abstract class ActionsFactory<C extends Actions<any>> {

2
npm/ng-packs/packages/theme-shared/extensions/src/lib/models/props.ts

@ -38,7 +38,7 @@ export abstract class Prop<R = any> {
} }
} }
export type PropCallback<T, R = any> = (data?: Omit<PropData<T>, 'data'>, auxData?: any) => R; export type PropCallback<T, R = any> = (data: Omit<PropData<T>, 'data'>, auxData?: any) => R;
export type PropPredicate<T> = (data?: Omit<PropData<T>, 'data'>, auxData?: any) => boolean; export type PropPredicate<T> = (data?: Omit<PropData<T>, 'data'>, auxData?: any) => boolean;
export abstract class PropsFactory<C extends Props<any>> { export abstract class PropsFactory<C extends Props<any>> {

4
npm/ng-packs/packages/theme-shared/extensions/src/lib/models/toolbar-actions.ts

@ -27,7 +27,7 @@ export class ToolbarAction<R = any> extends Action<R> {
readonly icon: string; readonly icon: string;
constructor(options: ToolbarActionOptions<R>) { constructor(options: ToolbarActionOptions<R>) {
super(options.permission, options.visible, options.action); super(options.permission || '', options.visible, options.action);
this.text = options.text; this.text = options.text;
this.icon = options.icon || ''; this.icon = options.icon || '';
} }
@ -45,7 +45,7 @@ export class ToolbarComponent<R = any> extends Action<R> {
readonly component: Type<any>; readonly component: Type<any>;
constructor(options: ToolbarComponentOptions<R>) { constructor(options: ToolbarComponentOptions<R>) {
super(options.permission, options.visible, options.action); super(options.permission || '', options.visible, options.action);
this.component = options.component; this.component = options.component;
} }

10
npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/enum.util.ts

@ -8,7 +8,7 @@ import { PropCallback } from '../models/props';
export function createEnum(members: ObjectExtensions.ExtensionEnumFieldDto[]) { export function createEnum(members: ObjectExtensions.ExtensionEnumFieldDto[]) {
const enumObject: any = {}; const enumObject: any = {};
members.forEach(({ name, value }) => { members.forEach(({ name = '', value }) => {
enumObject[(enumObject[name] = value as any)] = name; enumObject[(enumObject[name] = value as any)] = name;
}); });
@ -21,7 +21,7 @@ export function createEnumValueResolver<T = any>(
propName: string, propName: string,
): PropCallback<T, Observable<string>> { ): PropCallback<T, Observable<string>> {
return data => { return data => {
const value = data.record[EXTRA_PROPERTIES_KEY][propName]; const value = (data.record as any)[EXTRA_PROPERTIES_KEY][propName];
const key = lookupEnum.transformed[value]; const key = lookupEnum.transformed[value];
const l10n = data.getInjected(LocalizationService); const l10n = data.getInjected(LocalizationService);
const localizeEnum = createEnumLocalizer(l10n, enumType, lookupEnum); const localizeEnum = createEnumLocalizer(l10n, enumType, lookupEnum);
@ -40,7 +40,7 @@ export function createEnumOptions<T = any>(
return createLocalizationStream( return createLocalizationStream(
l10n, l10n,
lookupEnum.fields.map(({ name, value }) => ({ lookupEnum.fields.map(({ name = '', value }) => ({
key: localizeEnum(name), key: localizeEnum(name),
value, value,
})), })),
@ -62,12 +62,12 @@ function createEnumLocalizer(
return key => return key =>
l10n.localizeWithFallbackSync( l10n.localizeWithFallbackSync(
[resource], [resource || ''],
['Enum:' + shortType + '.' + key, shortType + '.' + key, key], ['Enum:' + shortType + '.' + key, shortType + '.' + key, key],
key, key,
); );
} }
function getShortEnumType(enumType: string): string { function getShortEnumType(enumType: string) {
return enumType.split('.').pop(); return enumType.split('.').pop();
} }

10
npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/localization.util.ts

@ -15,19 +15,23 @@ export function createDisplayNameLocalizationPipeKeyGenerator(
) => { ) => {
if (displayName && displayName.name) if (displayName && displayName.name)
return generateLocalizationPipeKey( return generateLocalizationPipeKey(
[displayName.resource], [displayName.resource || ''],
[displayName.name], [displayName.name],
displayName.name, displayName.name,
); );
const key = generateLocalizationPipeKey( const key = generateLocalizationPipeKey(
[fallback.resource], [fallback.resource || ''],
['DisplayName:' + fallback.name], ['DisplayName:' + fallback.name],
undefined, undefined,
); );
if (key) return key; if (key) return key;
return generateLocalizationPipeKey([fallback.resource], [fallback.name], fallback.name); return generateLocalizationPipeKey(
[fallback.resource || ''],
[fallback.name || ''],
fallback.name,
);
}; };
} }

9
npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts

@ -74,7 +74,7 @@ export function mapEntitiesToContributors<T = any>(
resource: string, resource: string,
) { ) {
return pipe( return pipe(
switchMap(entities => switchMap((entities: any) =>
zip(selectLocalization(configState), selectEnums(configState)).pipe( zip(selectLocalization(configState), selectEnums(configState)).pipe(
map(([localization, enums]) => { map(([localization, enums]) => {
const generateDisplayName = createDisplayNameLocalizationPipeKeyGenerator(localization); const generateDisplayName = createDisplayNameLocalizationPipeKeyGenerator(localization);
@ -166,8 +166,9 @@ function createPropertiesToContributorsMapper<T = any>(
if (isOnCreateForm || isOnEditForm) { if (isOnCreateForm || isOnEditForm) {
const defaultValue = property.defaultValue; const defaultValue = property.defaultValue;
const validators = () => getValidatorsFromProperty(property); const validators = () => getValidatorsFromProperty(property);
let options: PropCallback<any, Observable<ABP.Option<any>[]>>; let options: PropCallback<any, Observable<ABP.Option<any>[]>> | undefined;
if (type === ePropType.Enum) options = createEnumOptions(propName, enums[property.type]); if (type === ePropType.Enum)
options = createEnumOptions(propName, enums[property.type || '']);
else if (type === ePropType.Typeahead) options = createTypeaheadOptions(lookup); else if (type === ePropType.Typeahead) options = createTypeaheadOptions(lookup);
const formProp = new FormProp({ const formProp = new FormProp({
@ -192,7 +193,7 @@ function createPropertiesToContributorsMapper<T = any>(
} }
function getTypeFromProperty(property: ObjectExtensions.ExtensionPropertyDto): ePropType { function getTypeFromProperty(property: ObjectExtensions.ExtensionPropertyDto): ePropType {
return property.typeSimple.replace(/\?$/, '') as string as ePropType; return property?.typeSimple?.replace(/\?$/, '') as string as ePropType;
} }
function isUndefined(obj: any): obj is undefined { function isUndefined(obj: any): obj is undefined {

16
npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/typeahead.util.ts

@ -12,25 +12,25 @@ export function createTypeaheadOptions(
lookup: ExtensionPropertyUiLookupDto, lookup: ExtensionPropertyUiLookupDto,
): PropCallback<any, Observable<ABP.Option<any>[]>> { ): PropCallback<any, Observable<ABP.Option<any>[]>> {
return (data, searchText) => return (data, searchText) =>
searchText searchText && data
? data ? data
.getInjected(RestService) .getInjected(RestService)
.request( .request(
{ {
method: 'GET', method: 'GET',
url: lookup.url, url: lookup.url || '',
params: { params: {
[lookup.filterParamName]: searchText, [lookup.filterParamName || '']: searchText,
}, },
}, },
{ apiName: 'Default' }, { apiName: 'Default' },
) )
.pipe( .pipe(
map(response => { map((response: any) => {
const list = response[lookup.resultListPropertyName]; const list = response[lookup.resultListPropertyName || ''];
const mapToOption = (item: any) => ({ const mapToOption = (item: any) => ({
key: item[lookup.displayPropertyName], key: item[lookup.displayPropertyName || ''],
value: item[lookup.valuePropertyName], value: item[lookup.valuePropertyName || ''],
}); });
return list.map(mapToOption); return list.map(mapToOption);
}), }),
@ -51,7 +51,7 @@ export function createTypeaheadDisplayNameGenerator(
properties: ObjectExtensions.EntityExtensionProperties, properties: ObjectExtensions.EntityExtensionProperties,
): ObjectExtensions.DisplayNameGeneratorFn { ): ObjectExtensions.DisplayNameGeneratorFn {
return (displayName, fallback) => { return (displayName, fallback) => {
const name = removeTypeaheadTextSuffix(fallback.name); const name = removeTypeaheadTextSuffix(fallback.name || '');
return displayNameGeneratorFn(displayName || properties[name].displayName, { return displayNameGeneratorFn(displayName || properties[name].displayName, {
name, name,
resource: fallback.resource, resource: fallback.resource,

5
npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/validation.util.ts

@ -8,8 +8,9 @@ export function getValidatorsFromProperty(
const validators: ValidatorFn[] = []; const validators: ValidatorFn[] = [];
property.attributes.forEach(attr => { property.attributes.forEach(attr => {
if (attr.typeSimple in AbpValidators) if (attr.typeSimple && attr.typeSimple in AbpValidators) {
validators.push(AbpValidators[attr.typeSimple](attr.config)); validators.push((AbpValidators as any)[attr.typeSimple](attr.config));
}
}); });
return validators; return validators;

3
npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb-items/breadcrumb-items.component.ts

@ -1,3 +1,4 @@
import { ABP } from '@abp/ng.core';
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
@Component({ @Component({
@ -5,5 +6,5 @@ import { Component, Input } from '@angular/core';
templateUrl: './breadcrumb-items.component.html', templateUrl: './breadcrumb-items.component.html',
}) })
export class BreadcrumbItemsComponent { export class BreadcrumbItemsComponent {
@Input() items = []; @Input() items: Partial<ABP.Route>[] = [];
} }

12
npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts

@ -39,16 +39,16 @@ export class ButtonComponent implements OnInit {
buttonType = 'button'; buttonType = 'button';
@Input() @Input()
iconClass: string; iconClass?: string;
@Input() @Input()
loading = false; loading = false;
@Input() @Input()
disabled = false; disabled: boolean | undefined = false;
@Input() @Input()
attributes: ABP.Dictionary<string>; attributes?: ABP.Dictionary<string>;
@Output() readonly click = new EventEmitter<MouseEvent>(); @Output() readonly click = new EventEmitter<MouseEvent>();
@ -63,7 +63,7 @@ export class ButtonComponent implements OnInit {
@Output() readonly abpBlur = new EventEmitter<FocusEvent>(); @Output() readonly abpBlur = new EventEmitter<FocusEvent>();
@ViewChild('button', { static: true }) @ViewChild('button', { static: true })
buttonRef: ElementRef<HTMLButtonElement>; buttonRef!: ElementRef<HTMLButtonElement>;
get icon(): string { get icon(): string {
return `${this.loading ? 'fa fa-spinner fa-spin' : this.iconClass || 'd-none'}`; return `${this.loading ? 'fa fa-spinner fa-spin' : this.iconClass || 'd-none'}`;
@ -74,7 +74,9 @@ export class ButtonComponent implements OnInit {
ngOnInit() { ngOnInit() {
if (this.attributes) { if (this.attributes) {
Object.keys(this.attributes).forEach(key => { Object.keys(this.attributes).forEach(key => {
this.renderer.setAttribute(this.buttonRef.nativeElement, key, this.attributes[key]); if (this.attributes?.[key]) {
this.renderer.setAttribute(this.buttonRef.nativeElement, key, this.attributes[key]);
}
}); });
} }
} }

4
npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts

@ -12,9 +12,9 @@ export class ConfirmationComponent {
reject = Confirmation.Status.reject; reject = Confirmation.Status.reject;
dismiss = Confirmation.Status.dismiss; dismiss = Confirmation.Status.dismiss;
confirmation$: ReplaySubject<Confirmation.DialogData>; confirmation$!: ReplaySubject<Confirmation.DialogData>;
clear: (status: Confirmation.Status) => void; clear!: (status: Confirmation.Status) => void;
close(status: Confirmation.Status) { close(status: Confirmation.Status) {
this.clear(status); this.clear(status);

24
npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts

@ -22,11 +22,11 @@ import { debounceTime, filter } from 'rxjs/operators';
providers: [SubscriptionService], providers: [SubscriptionService],
}) })
export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnInit { export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnInit {
appRef: ApplicationRef; appRef!: ApplicationRef;
cfRes: ComponentFactoryResolver; cfRes!: ComponentFactoryResolver;
injector: Injector; injector!: Injector;
status = 0; status = 0;
@ -34,18 +34,18 @@ export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnIn
details: LocalizationParam = 'Sorry, an error has occured.'; details: LocalizationParam = 'Sorry, an error has occured.';
customComponent: Type<any> = null; customComponent: Type<any> | undefined = undefined;
destroy$: Subject<void>; destroy$!: Subject<void>;
hideCloseIcon = false; hideCloseIcon = false;
backgroundColor: string; backgroundColor!: string;
isHomeShow = true; isHomeShow = true;
@ViewChild('container', { static: false }) @ViewChild('container', { static: false })
containerRef: ElementRef<HTMLDivElement>; containerRef?: ElementRef<HTMLDivElement>;
get statusText(): string { get statusText(): string {
return this.status ? `[${this.status}]` : ''; return this.status ? `[${this.status}]` : '';
@ -66,13 +66,15 @@ export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnIn
customComponentRef.instance.errorStatus = this.status; customComponentRef.instance.errorStatus = this.status;
customComponentRef.instance.destroy$ = this.destroy$; customComponentRef.instance.destroy$ = this.destroy$;
this.appRef.attachView(customComponentRef.hostView); this.appRef.attachView(customComponentRef.hostView);
this.containerRef.nativeElement.appendChild( if (this.containerRef) {
(customComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0], this.containerRef.nativeElement.appendChild(
); (customComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0],
);
}
customComponentRef.changeDetectorRef.detectChanges(); customComponentRef.changeDetectorRef.detectChanges();
} }
const keyup$ = fromEvent(document, 'keyup').pipe( const keyup$ = fromEvent<KeyboardEvent>(document, 'keyup').pipe(
debounceTime(150), debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'), filter((key: KeyboardEvent) => key && key.key === 'Escape'),
); );

2
npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts

@ -22,7 +22,7 @@ import { combineLatest, Subscription, timer } from 'rxjs';
providers: [SubscriptionService], providers: [SubscriptionService],
}) })
export class LoaderBarComponent implements OnDestroy, OnInit { export class LoaderBarComponent implements OnDestroy, OnInit {
protected _isLoading: boolean; protected _isLoading!: boolean;
@Input() @Input()
set isLoading(value: boolean) { set isLoading(value: boolean) {

2
npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-ref.service.ts

@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
export type ModalDismissMode = 'hard' | 'soft'; export type ModalDismissMode = 'hard' | 'soft';
export interface DismissableModal { export interface DismissableModal {
dismiss(mode: ModalDismissMode); dismiss(mode: ModalDismissMode): void;
} }
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })

4
npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html

@ -1,7 +1,7 @@
<ng-content></ng-content> <ng-content></ng-content>
<ng-template #modalContent let-modal> <ng-template #modalContent let-modal>
<div id="abp-modal-header" class="modal-header"> <div *ngIf="abpHeader" id="abp-modal-header" class="modal-header">
<ng-container *ngTemplateOutlet="abpHeader"></ng-container> <ng-container *ngTemplateOutlet="abpHeader"></ng-container>
​ ​
<button <button
@ -12,7 +12,7 @@
(click)="modal.dismiss()" (click)="modal.dismiss()"
></button> ></button>
</div> </div>
<div id="abp-modal-body" class="modal-body"> <div *ngIf="abpBody" id="abp-modal-body" class="modal-body">
<ng-container *ngTemplateOutlet="abpBody"></ng-container> <ng-container *ngTemplateOutlet="abpBody"></ng-container>
</div> </div>
<div *ngIf="abpFooter" id="abp-modal-footer" class="modal-footer"> <div *ngIf="abpFooter" id="abp-modal-footer" class="modal-footer">

38
npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts

@ -55,16 +55,16 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
@Input() suppressUnsavedChangesWarning = this.suppressUnsavedChangesWarningToken; @Input() suppressUnsavedChangesWarning = this.suppressUnsavedChangesWarningToken;
@ViewChild('modalContent') modalContent: TemplateRef<any>; @ViewChild('modalContent') modalContent?: TemplateRef<any>;
@ContentChild('abpHeader', { static: false }) abpHeader: TemplateRef<any>; @ContentChild('abpHeader', { static: false }) abpHeader?: TemplateRef<any>;
@ContentChild('abpBody', { static: false }) abpBody: TemplateRef<any>; @ContentChild('abpBody', { static: false }) abpBody?: TemplateRef<any>;
@ContentChild('abpFooter', { static: false }) abpFooter: TemplateRef<any>; @ContentChild('abpFooter', { static: false }) abpFooter?: TemplateRef<any>;
@ContentChild(ButtonComponent, { static: false, read: ButtonComponent }) @ContentChild(ButtonComponent, { static: false, read: ButtonComponent })
abpSubmit: ButtonComponent; abpSubmit?: ButtonComponent;
@Output() readonly visibleChange = new EventEmitter<boolean>(); @Output() readonly visibleChange = new EventEmitter<boolean>();
@ -78,7 +78,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
_busy = false; _busy = false;
modalRef: NgbModalRef; modalRef!: NgbModalRef;
isConfirmationOpen = false; isConfirmationOpen = false;
@ -93,7 +93,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
} }
get isFormDirty(): boolean { get isFormDirty(): boolean {
return Boolean(this.modalWindowRef.querySelector('.ng-dirty')); return Boolean(this.modalWindowRef?.querySelector('.ng-dirty'));
} }
constructor( constructor(
@ -191,22 +191,22 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
} }
listen() { listen() {
fromEvent(this.modalWindowRef, 'keyup') if (this.modalWindowRef) {
.pipe( fromEvent<KeyboardEvent>(this.modalWindowRef, 'keyup')
takeUntil(this.destroy$), .pipe(
debounceTime(150), takeUntil(this.destroy$),
filter((key: KeyboardEvent) => key && key.key === 'Escape'), debounceTime(150),
) filter((key: KeyboardEvent) => key && key.key === 'Escape'),
.subscribe(() => this.close()); )
.subscribe(() => this.close());
}
fromEvent(window, 'beforeunload') fromEvent(window, 'beforeunload')
.pipe(takeUntil(this.destroy$)) .pipe(takeUntil(this.destroy$))
.subscribe(event => { .subscribe(event => {
event.preventDefault(); // TODO: check this
if (this.isFormDirty && !this.suppressUnsavedChangesWarning) { if (!this.isFormDirty || this.suppressUnsavedChangesWarning) {
event.returnValue = true; event.preventDefault();
} else {
delete event.returnValue;
} }
}); });

14
npm/ng-packs/packages/theme-shared/src/lib/components/toast-container/toast-container.component.ts

@ -10,14 +10,14 @@ import { Toaster } from '../../models/toaster';
animations: [toastInOut], animations: [toastInOut],
}) })
export class ToastContainerComponent implements OnInit { export class ToastContainerComponent implements OnInit {
toasts$: ReplaySubject<Toaster.Toast[]>; toasts$!: ReplaySubject<Toaster.Toast[]>;
remove: (toastId: number) => void; remove!: (toastId: number) => void;
toasts = [] as Toaster.Toast[]; toasts = [] as Toaster.Toast[];
@Input() @Input()
top: string; top?: string;
@Input() @Input()
right = '30px'; right = '30px';
@ -26,10 +26,10 @@ export class ToastContainerComponent implements OnInit {
bottom = '30px'; bottom = '30px';
@Input() @Input()
left: string; left?: string;
@Input() @Input()
toastKey: string; toastKey?: string;
ngOnInit() { ngOnInit() {
this.toasts$.subscribe(toasts => { this.toasts$.subscribe(toasts => {
@ -41,8 +41,8 @@ export class ToastContainerComponent implements OnInit {
}); });
} }
trackByFunc(index, toast) { trackByFunc(index: number, toast: Toaster.Toast) {
if (!toast) return null; if (!toast) return null;
return toast.options.id; return toast.options?.id;
} }
} }

2
npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.html

@ -3,7 +3,7 @@
<i class="fa icon" [ngClass]="iconClass"></i> <i class="fa icon" [ngClass]="iconClass"></i>
</div> </div>
<div class="abp-toast-content"> <div class="abp-toast-content">
<button class="abp-toast-close-button" (click)="close()" *ngIf="toast.options.closable"> <button class="abp-toast-close-button" (click)="close()" *ngIf="toast.options?.closable">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</button> </button>
<div class="abp-toast-title"> <div class="abp-toast-title">

4
npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts

@ -7,7 +7,7 @@ import { Toaster } from '../../models/toaster';
}) })
export class ToastComponent implements OnInit { export class ToastComponent implements OnInit {
@Input() @Input()
toast: Toaster.Toast; toast!: Toaster.Toast;
@Output() remove = new EventEmitter<number>(); @Output() remove = new EventEmitter<number>();
@ -42,7 +42,7 @@ export class ToastComponent implements OnInit {
} }
close() { close() {
this.remove.emit(this.toast.options.id); this.remove.emit(this.toast.options?.id);
} }
tap() { tap() {

4
npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts

@ -13,11 +13,11 @@ import {
}) })
export class EllipsisDirective implements AfterViewInit { export class EllipsisDirective implements AfterViewInit {
@Input('abpEllipsis') @Input('abpEllipsis')
width: string; width?: string;
@HostBinding('title') @HostBinding('title')
@Input() @Input()
title: string; title?: string;
@Input('abpEllipsisEnabled') @Input('abpEllipsisEnabled')
enabled = true; enabled = true;

12
npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts

@ -18,7 +18,7 @@ import { LoadingComponent } from '../components/loading/loading.component';
@Directive({ selector: '[abpLoading]' }) @Directive({ selector: '[abpLoading]' })
export class LoadingDirective implements OnInit, OnDestroy { export class LoadingDirective implements OnInit, OnDestroy {
private _loading: boolean; private _loading!: boolean;
@HostBinding('style.position') @HostBinding('style.position')
position = 'relative'; position = 'relative';
@ -53,7 +53,7 @@ export class LoadingDirective implements OnInit, OnDestroy {
if (newValue && !this.rootNode) { if (newValue && !this.rootNode) {
this.rootNode = (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0]; this.rootNode = (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0];
this.targetElement.appendChild(this.rootNode); this.targetElement?.appendChild(this.rootNode as HTMLDivElement);
} else if (this.rootNode) { } else if (this.rootNode) {
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode); this.renderer.removeChild(this.rootNode.parentElement, this.rootNode);
this.rootNode = null; this.rootNode = null;
@ -66,14 +66,14 @@ export class LoadingDirective implements OnInit, OnDestroy {
} }
@Input('abpLoadingTargetElement') @Input('abpLoadingTargetElement')
targetElement: HTMLElement; targetElement: HTMLElement | undefined;
@Input('abpLoadingDelay') @Input('abpLoadingDelay')
delay = 0; delay = 0;
componentRef: ComponentRef<LoadingComponent>; componentRef!: ComponentRef<LoadingComponent>;
rootNode: HTMLDivElement; rootNode: HTMLDivElement | null = null;
timerSubscription: Subscription; timerSubscription: Subscription | null = null;
constructor( constructor(
private elRef: ElementRef<HTMLElement>, private elRef: ElementRef<HTMLElement>,

2
npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts

@ -27,7 +27,7 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit {
private subscription = new Subscription(); private subscription = new Subscription();
private querySubscription = new Subscription(); private querySubscription = new Subscription();
@Input() list: ListService; @Input() list!: ListService;
constructor( constructor(
private table: DatatableComponent, private table: DatatableComponent,

74
npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts

@ -71,7 +71,7 @@ export const DEFAULT_ERROR_LOCALIZATIONS = {
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ErrorHandler { export class ErrorHandler {
componentRef: ComponentRef<HttpErrorWrapperComponent>; componentRef: ComponentRef<HttpErrorWrapperComponent> | null = null;
protected httpErrorHandler = this.injector.get(HTTP_ERROR_HANDLER, (_, err: HttpErrorResponse) => protected httpErrorHandler = this.injector.get(HTTP_ERROR_HANDLER, (_, err: HttpErrorResponse) =>
throwError(err), throwError(err),
@ -109,7 +109,7 @@ export class ErrorHandler {
.getEvents(ResolveEnd) .getEvents(ResolveEnd)
.pipe(filter(() => !!this.componentRef)) .pipe(filter(() => !!this.componentRef))
.subscribe(() => { .subscribe(() => {
this.componentRef.destroy(); this.componentRef?.destroy();
this.componentRef = null; this.componentRef = null;
}); });
} }
@ -120,7 +120,7 @@ export class ErrorHandler {
.subscribe(); .subscribe();
} }
private executeErrorHandler = error => { private executeErrorHandler = (error: any) => {
const returnValue = this.httpErrorHandler(this.injector, error); const returnValue = this.httpErrorHandler(this.injector, error);
return (returnValue instanceof Observable ? returnValue : of(null)).pipe( return (returnValue instanceof Observable ? returnValue : of(null)).pipe(
@ -138,7 +138,7 @@ export class ErrorHandler {
}; };
if (err instanceof HttpErrorResponse && err.headers.get('_AbpErrorFormat')) { if (err instanceof HttpErrorResponse && err.headers.get('_AbpErrorFormat')) {
const confirmation$ = this.showError(null, null, body); const confirmation$ = this.showErrorWithRequestBody(body);
if (err.status === 401) { if (err.status === 401) {
confirmation$.subscribe(() => { confirmation$.subscribe(() => {
@ -249,29 +249,34 @@ export class ErrorHandler {
}); });
} }
protected showError( protected showErrorWithRequestBody(body: any) {
message?: LocalizationParam, let message: LocalizationParam;
title?: LocalizationParam, let title: LocalizationParam;
body?: any,
): Observable<Confirmation.Status> { if (body.details) {
if (body) { message = body.details;
if (body.details) { title = body.message;
message = body.details; } else if (body.message) {
title = body.message; title = {
} else if (body.message) { key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title,
title = { defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title,
key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title, };
defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title, message = body.message;
}; } else {
message = body.message; message = body.message || {
} else { key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title,
message = body.message || { defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title,
key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title, };
defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title, title = '';
};
}
} }
return this.showError(message, title);
}
protected showError(
message: LocalizationParam,
title: LocalizationParam,
): Observable<Confirmation.Status> {
return this.confirmationService.error(message, title, { return this.confirmationService.error(message, title, {
hideCancelBtn: true, hideCancelBtn: true,
yesText: 'AbpAccount::Close', yesText: 'AbpAccount::Close',
@ -293,18 +298,18 @@ export class ErrorHandler {
for (const key in instance) { for (const key in instance) {
/* istanbul ignore else */ /* istanbul ignore else */
if (Object.prototype.hasOwnProperty.call(this.componentRef.instance, key)) { if (Object.prototype.hasOwnProperty.call(this.componentRef.instance, key)) {
this.componentRef.instance[key] = instance[key]; (this.componentRef.instance as any)[key] = (instance as any)[key];
} }
} }
this.componentRef.instance.hideCloseIcon = this.httpErrorConfig.errorScreen.hideCloseIcon; this.componentRef.instance.hideCloseIcon = !!this.httpErrorConfig.errorScreen?.hideCloseIcon;
const appRef = this.injector.get(ApplicationRef); const appRef = this.injector.get(ApplicationRef);
if (this.canCreateCustomError(instance.status as ErrorScreenErrorCodes)) { if (this.canCreateCustomError(instance.status as ErrorScreenErrorCodes)) {
this.componentRef.instance.cfRes = this.cfRes; this.componentRef.instance.cfRes = this.cfRes;
this.componentRef.instance.appRef = appRef; this.componentRef.instance.appRef = appRef;
this.componentRef.instance.injector = this.injector; this.componentRef.instance.injector = this.injector;
this.componentRef.instance.customComponent = this.httpErrorConfig.errorScreen.component; this.componentRef.instance.customComponent = this.httpErrorConfig.errorScreen?.component;
} }
appRef.attachView(this.componentRef.hostView); appRef.attachView(this.componentRef.hostView);
@ -313,27 +318,32 @@ export class ErrorHandler {
const destroy$ = new Subject<void>(); const destroy$ = new Subject<void>();
this.componentRef.instance.destroy$ = destroy$; this.componentRef.instance.destroy$ = destroy$;
destroy$.subscribe(() => { destroy$.subscribe(() => {
this.componentRef.destroy(); this.componentRef?.destroy();
this.componentRef = null; this.componentRef = null;
}); });
} }
canCreateCustomError(status: ErrorScreenErrorCodes): boolean { canCreateCustomError(status: ErrorScreenErrorCodes): boolean {
return ( return !!(
this.httpErrorConfig?.errorScreen?.component && this.httpErrorConfig?.errorScreen?.component &&
this.httpErrorConfig?.errorScreen?.forWhichErrors?.indexOf(status) > -1 this.httpErrorConfig?.errorScreen?.forWhichErrors &&
this.httpErrorConfig?.errorScreen?.forWhichErrors.indexOf(status) > -1
); );
} }
protected filterRestErrors = ({ status }: HttpErrorResponse): boolean => { protected filterRestErrors = ({ status }: HttpErrorResponse): boolean => {
if (typeof status !== 'number') return false; if (typeof status !== 'number') return false;
return this.httpErrorConfig.skipHandledErrorCodes.findIndex(code => code === status) < 0; return (
!!this.httpErrorConfig.skipHandledErrorCodes &&
this.httpErrorConfig.skipHandledErrorCodes.findIndex(code => code === status) < 0
);
}; };
protected filterRouteErrors = (navigationError: NavigationError): boolean => { protected filterRouteErrors = (navigationError: NavigationError): boolean => {
return ( return (
navigationError.error?.message?.indexOf('Cannot match') > -1 && navigationError.error?.message?.indexOf('Cannot match') > -1 &&
!!this.httpErrorConfig.skipHandledErrorCodes &&
this.httpErrorConfig.skipHandledErrorCodes.findIndex(code => code === 404) < 0 this.httpErrorConfig.skipHandledErrorCodes.findIndex(code => code === 404) < 0
); );
}; };

2
npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts

@ -1,7 +1,7 @@
import { Type } from '@angular/core'; import { Type } from '@angular/core';
export class NavItem { export class NavItem {
id: string | number; id?: string | number;
component?: Type<any>; component?: Type<any>;
html?: string; html?: string;
action?: () => void; action?: () => void;

6
npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts

@ -7,10 +7,10 @@ import { Confirmation } from '../models/confirmation';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ConfirmationService { export class ConfirmationService {
status$: Subject<Confirmation.Status>; status$!: Subject<Confirmation.Status>;
confirmation$ = new ReplaySubject<Confirmation.DialogData>(1); confirmation$ = new ReplaySubject<Confirmation.DialogData>(1);
private containerComponentRef: ComponentRef<ConfirmationComponent>; private containerComponentRef!: ComponentRef<ConfirmationComponent>;
clear = (status: Confirmation.Status = Confirmation.Status.dismiss) => { clear = (status: Confirmation.Status = Confirmation.Status.dismiss) => {
this.confirmation$.next(); this.confirmation$.next();
@ -87,7 +87,7 @@ export class ConfirmationService {
} }
private listenToEscape() { private listenToEscape() {
fromEvent(document, 'keyup') fromEvent<KeyboardEvent>(document, 'keyup')
.pipe( .pipe(
takeUntil(this.status$), takeUntil(this.status$),
debounceTime(150), debounceTime(150),

4
npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts

@ -19,7 +19,7 @@ export class ToasterService implements ToasterContract {
private toasts = [] as Toaster.Toast[]; private toasts = [] as Toaster.Toast[];
private containerComponentRef: ComponentRef<ToastContainerComponent>; private containerComponentRef!: ComponentRef<ToastContainerComponent>;
constructor(private contentProjectionService: ContentProjectionService) {} constructor(private contentProjectionService: ContentProjectionService) {}
@ -100,7 +100,7 @@ export class ToasterService implements ToasterContract {
show( show(
message: LocalizationParam, message: LocalizationParam,
title: LocalizationParam = null, title: LocalizationParam | undefined = undefined,
severity: Toaster.Severity = 'neutral', severity: Toaster.Severity = 'neutral',
options = {} as Partial<Toaster.ToastOptions>, options = {} as Partial<Toaster.ToastOptions>,
): Toaster.ToasterId { ): Toaster.ToasterId {

7
npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts

@ -17,13 +17,14 @@ export class DateParserFormatter extends NgbDateParserFormatter {
super(); super();
} }
parse(value: string): NgbDateStruct { parse(value: string): NgbDateStruct | null {
if (value) { if (value) {
const dateParts = value.trim().split('-'); const dateParts = value.trim().split('-');
// TODO: CHANGED
if (dateParts.length === 1 && isNumber(dateParts[0])) { if (dateParts.length === 1 && isNumber(dateParts[0])) {
return { year: toInteger(dateParts[0]), month: null, day: null }; return { year: toInteger(dateParts[0]), month: -1, day: -1 };
} else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) { } else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
return { year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: null }; return { year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: -1 };
} else if ( } else if (
dateParts.length === 3 && dateParts.length === 3 &&
isNumber(dateParts[0]) && isNumber(dateParts[0]) &&

1
npm/ng-packs/tsconfig.json

@ -1,6 +1,7 @@
{ {
"compileOnSave": false, "compileOnSave": false,
"compilerOptions": { "compilerOptions": {
"strict": false,
"sourceMap": true, "sourceMap": true,
"declaration": false, "declaration": false,
"moduleResolution": "node", "moduleResolution": "node",

3113
npm/ng-packs/yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save