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]',
})
export class AutofocusDirective implements AfterViewInit {
private _delay = 0;
@Input('autofocus')
delay = 0;
set delay(val: number | string | undefined) {
this._delay = Number(val) || 0;
}
get delay() {
return this._delay;
}
constructor(private elRef: ElementRef) {}
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 {
ChangeDetectorRef,
Directive,
ElementRef,
Input,
OnChanges,
OnDestroy,
Optional,
Renderer2,
TemplateRef,
ViewContainerRef,
} from '@angular/core';
@ -18,13 +16,11 @@ import { PermissionService } from '../services/permission.service';
selector: '[abpPermission]',
})
export class PermissionDirective implements OnDestroy, OnChanges {
@Input('abpPermission') condition: string;
@Input('abpPermission') condition: string | undefined;
subscription: Subscription;
subscription!: Subscription;
constructor(
private elRef: ElementRef<HTMLElement>,
private renderer: Renderer2,
@Optional() private templateRef: TemplateRef<any>,
private vcRef: ViewContainerRef,
private permissionService: PermissionService,
@ -37,7 +33,7 @@ export class PermissionDirective implements OnDestroy, OnChanges {
}
this.subscription = this.permissionService
.getGrantedPolicy$(this.condition)
.getGrantedPolicy$(this.condition || '')
.pipe(distinctUntilChanged())
.subscribe(isGranted => {
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;
externalComponent: Type<any>;
externalComponent!: Type<any>;
defaultComponentRef: any;
@ -50,7 +50,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
private subscription: SubscriptionService,
) {
this.context = {
initTemplate: ref => {
initTemplate: (ref: any) => {
this.resetDefaultComponent();
this.defaultComponentRef = ref;
this.setDefaultComponentInputs();
@ -121,8 +121,8 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
if (Object.prototype.hasOwnProperty.call(this.data.outputs, key)) {
if (!this.defaultComponentSubscriptions[key]) {
this.defaultComponentSubscriptions[key] = this.defaultComponentRef[key].subscribe(
value => {
this.data.outputs[key](value);
(value: any) => {
this.data.outputs?.[key](value);
},
);
}
@ -132,7 +132,7 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
}
setProvidedData() {
this.providedData = { ...this.data, inputs: {} };
this.providedData = { ...this.data, inputs: {}, outputs: {} };
if (!this.data.inputs) return;
Object.defineProperties(this.providedData.inputs, {
@ -142,9 +142,9 @@ export class ReplaceableTemplateDirective implements OnInit, OnChanges {
[key]: {
enumerable: true,
configurable: true,
get: () => this.data.inputs[key].value,
...(this.data.inputs[key].twoWay && {
set: newValue => {
get: () => this.data.inputs[key]?.value,
...(this.data.inputs[key]?.twoWay && {
set: (newValue: any) => {
this.data.inputs[key].value = 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 {
path: string;
path?: string;
layout?: eLayoutType;
iconClass?: string;
}

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

@ -16,8 +16,8 @@ export namespace ReplaceableComponents {
I,
O extends { [K in keyof O]: EventEmitter<any> | Subject<any> },
> {
inputs: { -readonly [K in keyof I]: { value: I[K]; twoWay?: boolean } };
outputs: { -readonly [K in keyof O]: (value: ABP.ExtractFromOutput<O[K]>) => void };
inputs?: { -readonly [K in keyof I]: { value: I[K]; twoWay?: boolean } };
outputs?: { -readonly [K in keyof O]: (value: ABP.ExtractFromOutput<O[K]>) => void };
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 {
constructor(private localization: LocalizationService) {}
transform(value: string | LocalizationWithDefault = '', ...interpolateParams: string[]): string {
return this.localization.instant(
value,
...interpolateParams.reduce(
(acc, val) => (Array.isArray(val) ? [...acc, ...val] : [...acc, val]),
[],
),
);
transform(
value: string | LocalizationWithDefault = '',
...interpolateParams: (string | string[] | undefined)[]
): string {
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;
}
getDeep$(keys: string[] | string) {
getDeep$(keys: string[] | string): Observable<any> {
keys = splitKeys(keys);
return this.store
.sliceState(state => state)
.pipe(
map(state => {
return (keys as string[]).reduce((acc, val) => {
return (keys as string[]).reduce((acc: any, val) => {
if (acc) {
return acc[val];
}
@ -66,10 +66,10 @@ export class ConfigStateService {
);
}
getDeep(keys: string[] | string) {
getDeep(keys: string[] | string): any {
keys = splitKeys(keys);
return (keys as string[]).reduce((acc, val) => {
return (keys as string[]).reduce((acc: any, val) => {
if (acc) {
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;
}
getApiUrl(key?: string) {
getApiUrl(key: string) {
return mapToApiUrl(key)(this.store.state.apis);
}
getApiUrl$(key?: string) {
getApiUrl$(key: string) {
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' })
export class HttpErrorReporterService {
private _reporter$ = new Subject();
private _reporter$ = new Subject<HttpErrorResponse>();
private _errors$ = new BehaviorSubject<HttpErrorResponse[]>([]);
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',
})
export class LazyLoadService {
readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement>();
readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement | null>();
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';
@Injectable()
export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDestroy {
export class ListService<QueryParamsType = ABP.PageQueryParams | any> implements OnDestroy {
private _filter = '';
set filter(value: string) {
this._filter = value;
@ -112,7 +112,7 @@ export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDes
switchMap(query => streamCreatorCallback(query).pipe(catchError(() => of(null)))),
filter(Boolean),
tap(() => this._isLoading$.next(false)),
shareReplay({ bufferSize: 1, refCount: true }),
shareReplay<any>({ bufferSize: 1, refCount: true }),
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);
return (resourceNames: string[], keys: string[], defaultKey: string) => {
return (resourceNames: string[], keys: string[], defaultKey: string | undefined) => {
const { resourceName, key } = findLocalization(resourceNames, keys);
return !resourceName ? defaultKey : resourceName === '_' ? key : `${resourceName}::${key}`;
};
@ -45,7 +45,7 @@ function createLocalizationFinder(localization: ApplicationLocalizationConfigura
const localize = createLocalizer(localization);
return (resourceNames: string[], keys: string[]) => {
resourceNames = resourceNames.concat(localization.defaultResourceName).filter(Boolean);
resourceNames = resourceNames.concat(localization.defaultResourceName || '').filter(Boolean);
const resourceCount = resourceNames.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" />
<form *ngIf="form" [formGroup]="form" (ngSubmit)="submit()" validateOnSubmit>
<form *ngIf="form" [formGroup]="form" (ngSubmit)="submit()" [validateOnSubmit]="true">
<div class="mb-3 form-group">
<label class="form-label">{{
'AbpSettingManagement::DefaultFromDisplayName' | abpLocalization
@ -49,7 +49,7 @@
<div
[@collapse]="{
value: form.get('smtpUseDefaultCredentials').value ? 'collapsed' : 'expanded',
value: form.get('smtpUseDefaultCredentials')?.value ? 'collapsed' : 'expanded',
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],
})
export class EmailSettingGroupComponent implements OnInit {
form: FormGroup;
form!: FormGroup;
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: () => {
const configState = inject(ConfigStateService);
const featureKey = 'SettingManagement.Enable';
const mapFn = features => ({
const mapFn = (features: Record<string, string>) => ({
enable: features[featureKey].toLowerCase() !== 'false',
});
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 { Component, OnDestroy, OnInit, TrackByFunction } from '@angular/core';
import { SettingTabsService } from '@abp/ng.setting-management/config';
import { Component, OnDestroy, OnInit, TrackByFunction } from '@angular/core';
import { Subscription } from 'rxjs';
@Component({
@ -11,7 +11,7 @@ export class SettingManagementComponent implements OnDestroy, OnInit {
private subscription = new Subscription();
settings: ABP.Tab[] = [];
selected: ABP.Tab;
selected!: ABP.Tab;
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>
<abp-extensible-table
[data]="data.items"
[recordsTotal]="data.totalCount"
[data]="data.items || []"
[recordsTotal]="data.totalCount || 0"
[list]="list"
></abp-extensible-table>
</div>
@ -41,7 +41,7 @@
</ng-template>
<ng-template #abpBody>
<form [formGroup]="tenantForm" (ngSubmit)="save()" validateOnSubmit>
<form [formGroup]="tenantForm" (ngSubmit)="save()" [validateOnSubmit]="true">
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form>
</ng-template>
@ -63,7 +63,7 @@
providerKey: { value: providerKey },
visible: { value: visibleFeatures, twoWay: true }
},
outputs: { visibleChange: onVisibleFeaturesChange },
outputs: { visibleChange: $any(onVisibleFeaturesChange) },
componentKey: featureManagementKey
}"
[(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 {
data: PagedResultDto<TenantDto> = { items: [], totalCount: 0 };
selected: TenantDto;
selected!: TenantDto;
tenantForm: FormGroup;
tenantForm!: FormGroup;
isModalVisible: boolean;
isModalVisible!: boolean;
visibleFeatures = false;
providerKey: string;
_useSharedDatabase: boolean;
providerKey!: string;
modalBusy = false;
@ -142,7 +140,7 @@ export class TenantsComponent implements OnInit {
}, 0);
}
sort(data) {
sort(data: any) {
const { prop, dir } = data.sorts[0];
this.list.sortKey = prop;
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',
action: data => {
const component = data.getInjected(TenantsComponent);
component.openFeaturesModal(null);
component.openFeaturesModal('');
},
permission: 'FeatureManagement.ManageHostFeatures',
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-body px-5">
<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(
@Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile,
@Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile: () => void,
private authService: AuthService,
private configState: ConfigStateService,
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',
template: `
<div
*ngIf="(dropdownLanguages$ | async)?.length > 0"
*ngIf="((dropdownLanguages$ | async)?.length || 0) > 0"
class="dropdown"
ngbDropdown
#languageDropdown="ngbDropdown"
@ -34,7 +34,7 @@ import { map } from 'rxjs/operators';
*ngFor="let lang of dropdownLanguages$ | async"
href="javascript:void(0)"
class="dropdown-item"
(click)="onChangeLang(lang.cultureName)"
(click)="onChangeLang(lang.cultureName || '')"
>{{ lang?.displayName }}</a
>
</div>
@ -52,7 +52,7 @@ export class LanguagesComponent {
return this.languages$.pipe(
map(
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">
<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">
<ng-container
*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-container *ngIf="route.children?.length">
<li
#navbarRootDropdown
class="nav-item dropdown"
display="static"
*abpPermission="route.requiredPolicy"
(click)="
navbarRootDropdown.expand
? (navbarRootDropdown.expand = false)
: (navbarRootDropdown.expand = true)
rootDropdownExpand[route.name]
? (rootDropdownExpand[route.name] = false)
: (rootDropdownExpand[route.name] = true)
"
>
<a
@ -42,7 +41,7 @@
#routeContainer
class="dropdown-menu border-0 shadow-sm"
(click)="$event.preventDefault(); $event.stopPropagation()"
[class.d-block]="smallScreen && navbarRootDropdown.expand"
[class.d-block]="smallScreen && rootDropdownExpand[route.name]"
>
<ng-container
*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',
})
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;

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,
})
export class ValidationErrorComponent extends ErrorComponent {
get abpErrors(): Validation.Error[] & { interpoliteParams?: string[] } {
get abpErrors(): (Validation.Error & { interpoliteParams?: string[] })[] {
if (!this.errors || !this.errors.length) return [];
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()
export class LazyStyleHandler {
private lazyLoad: LazyLoadService;
private styles: string[];
private lazyLoad!: LazyLoadService;
private styles!: string[];
private _dir: LocaleDirection = 'ltr';
readonly loaded = new Map<string, HTMLLinkElement>();
@ -29,7 +29,7 @@ export class LazyStyleHandler {
this.listenToDirectionChanges(injector);
}
private getHrefFromLink(link: HTMLLinkElement | null): string {
private getHrefFromLink(link: HTMLLinkElement | null | undefined): string {
if (!link) return '';
const a = document.createElement('a');
@ -94,5 +94,5 @@ export function initLazyStyleHandler(injector: Injector) {
interface LoadedStyle {
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 { ChangeDetectorRef, Injectable } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { eThemeBasicComponents } from '../enums';
@Injectable()
export class LayoutService {
isCollapsed = true;
smallScreen: boolean; // do not set true or false
smallScreen!: boolean; // do not set true or false
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()
export class DateTimeAdapter {
value: NgbDateTimeStruct;
value!: NgbDateTimeStruct;
fromModel(value: string | Date): NgbDateTimeStruct | null {
if (!value) return null;
@ -27,15 +27,16 @@ export class DateTimeAdapter {
toModel(value: NgbDateTimeStruct | null): string {
if (!value) return '';
const now = new Date();
//const now = new Date();
value = {
year: now.getUTCFullYear(),
// TODO
/* year: now.getUTCFullYear(),
month: now.getMonth() + 1,
day: now.getDate(),
hour: 0,
minute: 0,
second: 0,
second: 0, */
...this.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';
@Injectable()
export class DateAdapter extends NgbDateAdapter<string> {
export class DateAdapter extends NgbDateAdapter<string | Date> {
fromModel(value: string | Date): NgbDateStruct | 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';
@Injectable()
export class TimeAdapter extends NgbTimeAdapter<string> {
export class TimeAdapter extends NgbTimeAdapter<string | Date> {
fromModel(value: string | Date): NgbTimeStruct | 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'];
@Input() readonly record: InferredData<L>['record'];
@Input() record!: InferredData<L>['record'];
constructor(injector: Injector) {
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 {
@Input() prop: FormProp;
@Input() prop!: FormProp;
@Input() meridian = false;
@ViewChild(NgbInputDatepicker) date: NgbInputDatepicker;
@ViewChild(NgbTimepicker) time: NgbTimepicker;
@ViewChild(NgbInputDatepicker) date!: NgbInputDatepicker;
@ViewChild(NgbTimepicker) time!: NgbTimepicker;
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 {
@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 = '';
@ -60,9 +60,9 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit {
validators: ValidatorFn[] = [];
readonly: boolean;
readonly!: boolean;
disabled: boolean;
disabled!: boolean;
private readonly form: FormGroup;
@ -72,9 +72,9 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit {
this.typeaheadModel = selectedOption || { key: null, value: null };
const { key, value } = this.typeaheadModel;
const [keyControl, valueControl] = this.getTypeaheadControls();
if (valueControl.value && !value) valueControl.markAsDirty();
keyControl.setValue(key);
valueControl.setValue(value);
if (valueControl?.value && !value) valueControl.markAsDirty();
keyControl?.setValue(key);
valueControl?.setValue(value);
}
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> {
@ViewChildren(ExtensibleFormPropComponent)
formProps: QueryList<ExtensibleFormPropComponent>;
formProps!: QueryList<ExtensibleFormPropComponent>;
@Input()
set selectedRecord(record: R) {
@ -43,8 +43,8 @@ export class ExtensibleFormComponent<R = any> {
}
extraPropertiesKey = EXTRA_PROPERTIES_KEY;
propList: FormPropList<R>;
record: R;
propList!: FormPropList<R>;
record!: R;
get form(): 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 {
@Input()
abpDisabled: boolean;
abpDisabled = false;
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>>
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'];

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 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 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;
constructor(options: ToolbarActionOptions<R>) {
super(options.permission, options.visible, options.action);
super(options.permission || '', options.visible, options.action);
this.text = options.text;
this.icon = options.icon || '';
}
@ -45,7 +45,7 @@ export class ToolbarComponent<R = any> extends Action<R> {
readonly component: Type<any>;
constructor(options: ToolbarComponentOptions<R>) {
super(options.permission, options.visible, options.action);
super(options.permission || '', options.visible, options.action);
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[]) {
const enumObject: any = {};
members.forEach(({ name, value }) => {
members.forEach(({ name = '', value }) => {
enumObject[(enumObject[name] = value as any)] = name;
});
@ -21,7 +21,7 @@ export function createEnumValueResolver<T = any>(
propName: string,
): PropCallback<T, Observable<string>> {
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 l10n = data.getInjected(LocalizationService);
const localizeEnum = createEnumLocalizer(l10n, enumType, lookupEnum);
@ -40,7 +40,7 @@ export function createEnumOptions<T = any>(
return createLocalizationStream(
l10n,
lookupEnum.fields.map(({ name, value }) => ({
lookupEnum.fields.map(({ name = '', value }) => ({
key: localizeEnum(name),
value,
})),
@ -62,12 +62,12 @@ function createEnumLocalizer(
return key =>
l10n.localizeWithFallbackSync(
[resource],
[resource || ''],
['Enum:' + shortType + '.' + key, shortType + '.' + key, key],
key,
);
}
function getShortEnumType(enumType: string): string {
function getShortEnumType(enumType: string) {
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)
return generateLocalizationPipeKey(
[displayName.resource],
[displayName.resource || ''],
[displayName.name],
displayName.name,
);
const key = generateLocalizationPipeKey(
[fallback.resource],
[fallback.resource || ''],
['DisplayName:' + fallback.name],
undefined,
);
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,
) {
return pipe(
switchMap(entities =>
switchMap((entities: any) =>
zip(selectLocalization(configState), selectEnums(configState)).pipe(
map(([localization, enums]) => {
const generateDisplayName = createDisplayNameLocalizationPipeKeyGenerator(localization);
@ -166,8 +166,9 @@ function createPropertiesToContributorsMapper<T = any>(
if (isOnCreateForm || isOnEditForm) {
const defaultValue = property.defaultValue;
const validators = () => getValidatorsFromProperty(property);
let options: PropCallback<any, Observable<ABP.Option<any>[]>>;
if (type === ePropType.Enum) options = createEnumOptions(propName, enums[property.type]);
let options: PropCallback<any, Observable<ABP.Option<any>[]>> | undefined;
if (type === ePropType.Enum)
options = createEnumOptions(propName, enums[property.type || '']);
else if (type === ePropType.Typeahead) options = createTypeaheadOptions(lookup);
const formProp = new FormProp({
@ -192,7 +193,7 @@ function createPropertiesToContributorsMapper<T = any>(
}
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 {

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

@ -12,25 +12,25 @@ export function createTypeaheadOptions(
lookup: ExtensionPropertyUiLookupDto,
): PropCallback<any, Observable<ABP.Option<any>[]>> {
return (data, searchText) =>
searchText
searchText && data
? data
.getInjected(RestService)
.request(
{
method: 'GET',
url: lookup.url,
url: lookup.url || '',
params: {
[lookup.filterParamName]: searchText,
[lookup.filterParamName || '']: searchText,
},
},
{ apiName: 'Default' },
)
.pipe(
map(response => {
const list = response[lookup.resultListPropertyName];
map((response: any) => {
const list = response[lookup.resultListPropertyName || ''];
const mapToOption = (item: any) => ({
key: item[lookup.displayPropertyName],
value: item[lookup.valuePropertyName],
key: item[lookup.displayPropertyName || ''],
value: item[lookup.valuePropertyName || ''],
});
return list.map(mapToOption);
}),
@ -51,7 +51,7 @@ export function createTypeaheadDisplayNameGenerator(
properties: ObjectExtensions.EntityExtensionProperties,
): ObjectExtensions.DisplayNameGeneratorFn {
return (displayName, fallback) => {
const name = removeTypeaheadTextSuffix(fallback.name);
const name = removeTypeaheadTextSuffix(fallback.name || '');
return displayNameGeneratorFn(displayName || properties[name].displayName, {
name,
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[] = [];
property.attributes.forEach(attr => {
if (attr.typeSimple in AbpValidators)
validators.push(AbpValidators[attr.typeSimple](attr.config));
if (attr.typeSimple && attr.typeSimple in AbpValidators) {
validators.push((AbpValidators as any)[attr.typeSimple](attr.config));
}
});
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';
@Component({
@ -5,5 +6,5 @@ import { Component, Input } from '@angular/core';
templateUrl: './breadcrumb-items.component.html',
})
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';
@Input()
iconClass: string;
iconClass?: string;
@Input()
loading = false;
@Input()
disabled = false;
disabled: boolean | undefined = false;
@Input()
attributes: ABP.Dictionary<string>;
attributes?: ABP.Dictionary<string>;
@Output() readonly click = new EventEmitter<MouseEvent>();
@ -63,7 +63,7 @@ export class ButtonComponent implements OnInit {
@Output() readonly abpBlur = new EventEmitter<FocusEvent>();
@ViewChild('button', { static: true })
buttonRef: ElementRef<HTMLButtonElement>;
buttonRef!: ElementRef<HTMLButtonElement>;
get icon(): string {
return `${this.loading ? 'fa fa-spinner fa-spin' : this.iconClass || 'd-none'}`;
@ -74,7 +74,9 @@ export class ButtonComponent implements OnInit {
ngOnInit() {
if (this.attributes) {
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;
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) {
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],
})
export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnInit {
appRef: ApplicationRef;
appRef!: ApplicationRef;
cfRes: ComponentFactoryResolver;
cfRes!: ComponentFactoryResolver;
injector: Injector;
injector!: Injector;
status = 0;
@ -34,18 +34,18 @@ export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnIn
details: LocalizationParam = 'Sorry, an error has occured.';
customComponent: Type<any> = null;
customComponent: Type<any> | undefined = undefined;
destroy$: Subject<void>;
destroy$!: Subject<void>;
hideCloseIcon = false;
backgroundColor: string;
backgroundColor!: string;
isHomeShow = true;
@ViewChild('container', { static: false })
containerRef: ElementRef<HTMLDivElement>;
containerRef?: ElementRef<HTMLDivElement>;
get statusText(): string {
return this.status ? `[${this.status}]` : '';
@ -66,13 +66,15 @@ export class HttpErrorWrapperComponent implements AfterViewInit, OnDestroy, OnIn
customComponentRef.instance.errorStatus = this.status;
customComponentRef.instance.destroy$ = this.destroy$;
this.appRef.attachView(customComponentRef.hostView);
this.containerRef.nativeElement.appendChild(
(customComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0],
);
if (this.containerRef) {
this.containerRef.nativeElement.appendChild(
(customComponentRef.hostView as EmbeddedViewRef<any>).rootNodes[0],
);
}
customComponentRef.changeDetectorRef.detectChanges();
}
const keyup$ = fromEvent(document, 'keyup').pipe(
const keyup$ = fromEvent<KeyboardEvent>(document, 'keyup').pipe(
debounceTime(150),
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],
})
export class LoaderBarComponent implements OnDestroy, OnInit {
protected _isLoading: boolean;
protected _isLoading!: boolean;
@Input()
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 interface DismissableModal {
dismiss(mode: ModalDismissMode);
dismiss(mode: ModalDismissMode): void;
}
@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-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>
<button
@ -12,7 +12,7 @@
(click)="modal.dismiss()"
></button>
</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>
</div>
<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;
@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 })
abpSubmit: ButtonComponent;
abpSubmit?: ButtonComponent;
@Output() readonly visibleChange = new EventEmitter<boolean>();
@ -78,7 +78,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
_busy = false;
modalRef: NgbModalRef;
modalRef!: NgbModalRef;
isConfirmationOpen = false;
@ -93,7 +93,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
}
get isFormDirty(): boolean {
return Boolean(this.modalWindowRef.querySelector('.ng-dirty'));
return Boolean(this.modalWindowRef?.querySelector('.ng-dirty'));
}
constructor(
@ -191,22 +191,22 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
}
listen() {
fromEvent(this.modalWindowRef, 'keyup')
.pipe(
takeUntil(this.destroy$),
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
)
.subscribe(() => this.close());
if (this.modalWindowRef) {
fromEvent<KeyboardEvent>(this.modalWindowRef, 'keyup')
.pipe(
takeUntil(this.destroy$),
debounceTime(150),
filter((key: KeyboardEvent) => key && key.key === 'Escape'),
)
.subscribe(() => this.close());
}
fromEvent(window, 'beforeunload')
.pipe(takeUntil(this.destroy$))
.subscribe(event => {
event.preventDefault();
if (this.isFormDirty && !this.suppressUnsavedChangesWarning) {
event.returnValue = true;
} else {
delete event.returnValue;
// TODO: check this
if (!this.isFormDirty || this.suppressUnsavedChangesWarning) {
event.preventDefault();
}
});

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],
})
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[];
@Input()
top: string;
top?: string;
@Input()
right = '30px';
@ -26,10 +26,10 @@ export class ToastContainerComponent implements OnInit {
bottom = '30px';
@Input()
left: string;
left?: string;
@Input()
toastKey: string;
toastKey?: string;
ngOnInit() {
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;
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>
</div>
<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>
</button>
<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 {
@Input()
toast: Toaster.Toast;
toast!: Toaster.Toast;
@Output() remove = new EventEmitter<number>();
@ -42,7 +42,7 @@ export class ToastComponent implements OnInit {
}
close() {
this.remove.emit(this.toast.options.id);
this.remove.emit(this.toast.options?.id);
}
tap() {

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

@ -13,11 +13,11 @@ import {
})
export class EllipsisDirective implements AfterViewInit {
@Input('abpEllipsis')
width: string;
width?: string;
@HostBinding('title')
@Input()
title: string;
title?: string;
@Input('abpEllipsisEnabled')
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]' })
export class LoadingDirective implements OnInit, OnDestroy {
private _loading: boolean;
private _loading!: boolean;
@HostBinding('style.position')
position = 'relative';
@ -53,7 +53,7 @@ export class LoadingDirective implements OnInit, OnDestroy {
if (newValue && !this.rootNode) {
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) {
this.renderer.removeChild(this.rootNode.parentElement, this.rootNode);
this.rootNode = null;
@ -66,14 +66,14 @@ export class LoadingDirective implements OnInit, OnDestroy {
}
@Input('abpLoadingTargetElement')
targetElement: HTMLElement;
targetElement: HTMLElement | undefined;
@Input('abpLoadingDelay')
delay = 0;
componentRef: ComponentRef<LoadingComponent>;
rootNode: HTMLDivElement;
timerSubscription: Subscription;
componentRef!: ComponentRef<LoadingComponent>;
rootNode: HTMLDivElement | null = null;
timerSubscription: Subscription | null = null;
constructor(
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 querySubscription = new Subscription();
@Input() list: ListService;
@Input() list!: ListService;
constructor(
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' })
export class ErrorHandler {
componentRef: ComponentRef<HttpErrorWrapperComponent>;
componentRef: ComponentRef<HttpErrorWrapperComponent> | null = null;
protected httpErrorHandler = this.injector.get(HTTP_ERROR_HANDLER, (_, err: HttpErrorResponse) =>
throwError(err),
@ -109,7 +109,7 @@ export class ErrorHandler {
.getEvents(ResolveEnd)
.pipe(filter(() => !!this.componentRef))
.subscribe(() => {
this.componentRef.destroy();
this.componentRef?.destroy();
this.componentRef = null;
});
}
@ -120,7 +120,7 @@ export class ErrorHandler {
.subscribe();
}
private executeErrorHandler = error => {
private executeErrorHandler = (error: any) => {
const returnValue = this.httpErrorHandler(this.injector, error);
return (returnValue instanceof Observable ? returnValue : of(null)).pipe(
@ -138,7 +138,7 @@ export class ErrorHandler {
};
if (err instanceof HttpErrorResponse && err.headers.get('_AbpErrorFormat')) {
const confirmation$ = this.showError(null, null, body);
const confirmation$ = this.showErrorWithRequestBody(body);
if (err.status === 401) {
confirmation$.subscribe(() => {
@ -249,29 +249,34 @@ export class ErrorHandler {
});
}
protected showError(
message?: LocalizationParam,
title?: LocalizationParam,
body?: any,
): Observable<Confirmation.Status> {
if (body) {
if (body.details) {
message = body.details;
title = body.message;
} else if (body.message) {
title = {
key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title,
defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title,
};
message = body.message;
} else {
message = body.message || {
key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title,
defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title,
};
}
protected showErrorWithRequestBody(body: any) {
let message: LocalizationParam;
let title: LocalizationParam;
if (body.details) {
message = body.details;
title = body.message;
} else if (body.message) {
title = {
key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title,
defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title,
};
message = body.message;
} else {
message = body.message || {
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, {
hideCancelBtn: true,
yesText: 'AbpAccount::Close',
@ -293,18 +298,18 @@ export class ErrorHandler {
for (const key in instance) {
/* istanbul ignore else */
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);
if (this.canCreateCustomError(instance.status as ErrorScreenErrorCodes)) {
this.componentRef.instance.cfRes = this.cfRes;
this.componentRef.instance.appRef = appRef;
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);
@ -313,27 +318,32 @@ export class ErrorHandler {
const destroy$ = new Subject<void>();
this.componentRef.instance.destroy$ = destroy$;
destroy$.subscribe(() => {
this.componentRef.destroy();
this.componentRef?.destroy();
this.componentRef = null;
});
}
canCreateCustomError(status: ErrorScreenErrorCodes): boolean {
return (
return !!(
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 => {
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 => {
return (
navigationError.error?.message?.indexOf('Cannot match') > -1 &&
!!this.httpErrorConfig.skipHandledErrorCodes &&
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';
export class NavItem {
id: string | number;
id?: string | number;
component?: Type<any>;
html?: string;
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' })
export class ConfirmationService {
status$: Subject<Confirmation.Status>;
status$!: Subject<Confirmation.Status>;
confirmation$ = new ReplaySubject<Confirmation.DialogData>(1);
private containerComponentRef: ComponentRef<ConfirmationComponent>;
private containerComponentRef!: ComponentRef<ConfirmationComponent>;
clear = (status: Confirmation.Status = Confirmation.Status.dismiss) => {
this.confirmation$.next();
@ -87,7 +87,7 @@ export class ConfirmationService {
}
private listenToEscape() {
fromEvent(document, 'keyup')
fromEvent<KeyboardEvent>(document, 'keyup')
.pipe(
takeUntil(this.status$),
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 containerComponentRef: ComponentRef<ToastContainerComponent>;
private containerComponentRef!: ComponentRef<ToastContainerComponent>;
constructor(private contentProjectionService: ContentProjectionService) {}
@ -100,7 +100,7 @@ export class ToasterService implements ToasterContract {
show(
message: LocalizationParam,
title: LocalizationParam = null,
title: LocalizationParam | undefined = undefined,
severity: Toaster.Severity = 'neutral',
options = {} as Partial<Toaster.ToastOptions>,
): 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();
}
parse(value: string): NgbDateStruct {
parse(value: string): NgbDateStruct | null {
if (value) {
const dateParts = value.trim().split('-');
// TODO: CHANGED
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])) {
return { year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: null };
return { year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: -1 };
} else if (
dateParts.length === 3 &&
isNumber(dateParts[0]) &&

1
npm/ng-packs/tsconfig.json

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

3113
npm/ng-packs/yarn.lock

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