From 207439a4a263fc79f340765e94e06c501a78aae7 Mon Sep 17 00:00:00 2001 From: Mahmut Gundogdu Date: Tue, 7 Nov 2023 20:57:46 +0300 Subject: [PATCH 1/3] Convert moved components and directives Standalone --- .../extensible-date-time-picker.component.ts | 7 +- .../extensible-form-prop.component.html | 2 +- .../extensible-form-prop.component.ts | 135 +++++++----------- .../extensible-form.component.ts | 123 ++++++++-------- .../extensible-table.component.ts | 26 +++- .../grid-actions/grid-actions.component.ts | 6 + .../page-toolbar/page-toolbar.component.ts | 6 + .../src/lib/directives/prop-data.directive.ts | 1 + .../extensible/src/lib/extensible.module.ts | 35 ++--- .../src/lib/pipes/create-injector.pipe.ts | 1 + .../services/extensible-form-prop.service.ts | 77 ++++++++++ .../components/page/src/page.module.ts | 4 +- .../src/lib/abstracts/ng-model.component.ts | 8 +- .../components/checkbox/checkbox.component.ts | 4 - .../form-input/form-input.component.ts | 4 - .../components/password/password.component.ts | 9 +- .../src/lib/directives/ellipsis.directive.ts | 7 +- .../ngx-datatable-default.directive.ts | 1 + .../ngx-datatable-list.directive.ts | 1 + .../src/lib/theme-shared.module.ts | 11 +- 20 files changed, 263 insertions(+), 205 deletions(-) create mode 100644 npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts index 55b73581c9..e6f7881ca2 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/date-time-picker/extensible-date-time-picker.component.ts @@ -7,19 +7,24 @@ import { SkipSelf, ViewChild, } from '@angular/core'; -import { ControlContainer } from '@angular/forms'; +import { ControlContainer, ReactiveFormsModule } from '@angular/forms'; import { NgbDateAdapter, + NgbDatepickerModule, NgbInputDatepicker, NgbTimeAdapter, NgbTimepicker, + NgbTimepickerModule, } from '@ng-bootstrap/ng-bootstrap'; import { FormProp } from '../../models/form-props'; import { selfFactory } from '../../utils/factory.util'; import { DateTimeAdapter } from '@abp/ng.theme.shared'; +import { CommonModule } from '@angular/common'; @Component({ exportAs: 'abpExtensibleDateTimePicker', + standalone: true, + imports: [CommonModule, NgbDatepickerModule, ReactiveFormsModule, NgbTimepickerModule], selector: 'abp-extensible-date-time-picker', template: ` - + diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts index 2689e09a33..0d8c692015 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts @@ -1,11 +1,12 @@ import { EXTENSIONS_FORM_PROP, EXTENSIONS_FORM_PROP_DATA } from './../../tokens/extensions.token'; -import { ABP, AbpValidators, ConfigStateService, TrackByService } from '@abp/ng.core'; +import { ABP, CoreModule, TrackByService } from '@abp/ng.core'; import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, + inject, Injector, Input, OnChanges, @@ -17,26 +18,55 @@ import { import { ControlContainer, FormGroupDirective, - UntypedFormGroup, + ReactiveFormsModule, ValidatorFn, - Validators, } from '@angular/forms'; -import { NgbDateAdapter, NgbTimeAdapter } from '@ng-bootstrap/ng-bootstrap'; +import { + NgbDateAdapter, + NgbDatepickerModule, + NgbTimeAdapter, + NgbTimepickerModule, + NgbTypeaheadModule, +} from '@ng-bootstrap/ng-bootstrap'; import { Observable, of } from 'rxjs'; import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; -import { DateAdapter, TimeAdapter } from '@abp/ng.theme.shared'; +import { + DateAdapter, + DisabledDirective, + PasswordComponent, + TimeAdapter, +} from '@abp/ng.theme.shared'; import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties'; -import { ePropType } from '../../enums/props.enum'; import { FormProp } from '../../models/form-props'; import { PropData } from '../../models/props'; import { selfFactory } from '../../utils/factory.util'; import { addTypeaheadTextSuffix } from '../../utils/typeahead.util'; -import { eThemeSharedComponents } from "../../enums/components"; +import { eThemeSharedComponents } from '../../enums/components'; +import { CommonModule } from '@angular/common'; +import { ExtensibleDateTimePickerComponent } from '../date-time-picker/extensible-date-time-picker.component'; +import { NgxValidateCoreModule } from '@ngx-validate/core'; +import { ExtensibleFormPropService } from '../../services/extensible-form-prop.service'; +import {CreateInjectorPipe} from "../../pipes/create-injector.pipe"; @Component({ selector: 'abp-extensible-form-prop', templateUrl: './extensible-form-prop.component.html', + standalone: true, + imports: [ + CommonModule, + CoreModule, + ExtensibleDateTimePickerComponent, + NgbDatepickerModule, + NgbTimepickerModule, + ReactiveFormsModule, + DisabledDirective, + NgxValidateCoreModule, + NgbTypeaheadModule, + PasswordComponent, + CreateInjectorPipe + ], changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ExtensibleFormPropService], viewProviders: [ { provide: ControlContainer, @@ -48,32 +78,27 @@ import { eThemeSharedComponents } from "../../enums/components"; ], }) export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { - @Input() data!: PropData; + protected service = inject(ExtensibleFormPropService); + public readonly cdRef = inject(ChangeDetectorRef); + public readonly track = inject(TrackByService); + #groupDirective = inject(FormGroupDirective); + private injector = inject(Injector); + private readonly form = this.#groupDirective.form; + @Input() data!: PropData; @Input() prop!: FormProp; - @Input() first?: boolean; - @ViewChild('field') private fieldRef!: ElementRef; - public injectorForCustomComponent?: Injector; - + injectorForCustomComponent?: Injector; asterisk = ''; - containerClassName = 'mb-2'; - options$: Observable[]> = of([]); - validators: ValidatorFn[] = []; - readonly!: boolean; - typeaheadModel: any; - passwordKey = eThemeSharedComponents.PasswordComponent; - private readonly form: UntypedFormGroup; - disabledFn = (data: PropData) => false; get disabled() { @@ -100,27 +125,13 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { typeaheadFormatter = (option: ABP.Option) => option.key; - get meridian() { - return ( - this.configState.getDeep('localization.currentCulture.dateTimeFormat.shortTimePattern') || '' - ).includes('tt'); - } + meridian$ = this.service.meridian$; get isInvalid() { const control = this.form.get(this.prop.name); return control?.touched && control.invalid; } - constructor( - public readonly cdRef: ChangeDetectorRef, - public readonly track: TrackByService, - protected configState: ConfigStateService, - groupDirective: FormGroupDirective, - private injector: Injector, - ) { - this.form = groupDirective.form; - } - private getTypeaheadControls() { const { name } = this.prop; const extraPropName = `${EXTRA_PROPERTIES_KEY}.${name}`; @@ -132,7 +143,7 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { } private setAsterisk() { - this.asterisk = this.validators.some(isRequired) ? '*' : ''; + this.asterisk = this.service.calcAsterisks(this.validators); } ngAfterViewInit() { @@ -143,51 +154,11 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { } getComponent(prop: FormProp): string { - if (prop.template) { - return 'template'; - } - switch (prop.type) { - case ePropType.Boolean: - return 'checkbox'; - case ePropType.Date: - return 'date'; - case ePropType.DateTime: - return 'dateTime'; - case ePropType.Hidden: - return 'hidden'; - case ePropType.MultiSelect: - return 'multiselect'; - case ePropType.Text: - return 'textarea'; - case ePropType.Time: - return 'time'; - case ePropType.Typeahead: - return 'typeahead'; - case ePropType.PasswordInputGroup: - return 'passwordinputgroup'; - default: - return prop.options ? 'select' : 'input'; - } + return this.service.getComponent(prop); } getType(prop: FormProp): string { - switch (prop.type) { - case ePropType.Date: - case ePropType.String: - return 'text'; - case ePropType.Boolean: - return 'checkbox'; - case ePropType.Number: - return 'number'; - case ePropType.Email: - return 'email'; - case ePropType.Password: - return 'password'; - case ePropType.PasswordInputGroup: - return 'passwordinputgroup'; - default: - return 'hidden'; - } + return this.service.getType(prop); } ngOnChanges({ prop, data }: SimpleChanges) { @@ -229,11 +200,3 @@ export class ExtensibleFormPropComponent implements OnChanges, AfterViewInit { this.typeaheadModel = { key: keyControl.value, value: valueControl.value }; } } - -function isRequired(validator: ValidatorFn) { - return ( - validator === Validators.required || - validator === AbpValidators.required || - validator.name === 'required' - ); -} diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts index bd6f23591f..c7436d3374 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts @@ -1,73 +1,76 @@ -import { TrackByService } from '@abp/ng.core'; +import {TrackByService} from '@abp/ng.core'; import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - Inject, - Input, - Optional, - QueryList, - SkipSelf, - ViewChildren, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, inject, + Input, + Optional, + QueryList, + SkipSelf, + ViewChildren, } from '@angular/core'; -import { ControlContainer, UntypedFormGroup } from '@angular/forms'; -import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties'; -import { FormPropList, GroupedFormPropList } from '../../models/form-props'; -import { ExtensionsService } from '../../services/extensions.service'; -import { EXTENSIONS_IDENTIFIER } from '../../tokens/extensions.token'; -import { selfFactory } from '../../utils/factory.util'; -import { ExtensibleFormPropComponent } from './extensible-form-prop.component'; +import {ControlContainer, ReactiveFormsModule, UntypedFormGroup} from '@angular/forms'; +import {EXTRA_PROPERTIES_KEY} from '../../constants/extra-properties'; +import {FormPropList, GroupedFormPropList} from '../../models/form-props'; +import {ExtensionsService} from '../../services/extensions.service'; +import {EXTENSIONS_IDENTIFIER} from '../../tokens/extensions.token'; +import {selfFactory} from '../../utils/factory.util'; +import {ExtensibleFormPropComponent} from './extensible-form-prop.component'; +import {CommonModule} from "@angular/common"; +import {PropDataDirective} from "../../directives/prop-data.directive"; @Component({ - exportAs: 'abpExtensibleForm', - selector: 'abp-extensible-form', - templateUrl: './extensible-form.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, - viewProviders: [ - { - provide: ControlContainer, - useFactory: selfFactory, - deps: [[new Optional(), new SkipSelf(), ControlContainer]], - }, - ], + exportAs: 'abpExtensibleForm', + selector: 'abp-extensible-form', + templateUrl: './extensible-form.component.html', + standalone:true, + imports:[CommonModule, PropDataDirective,ReactiveFormsModule,ExtensibleFormPropComponent], + changeDetection: ChangeDetectionStrategy.OnPush, + viewProviders: [ + { + provide: ControlContainer, + useFactory: selfFactory, + deps: [[new Optional(), new SkipSelf(), ControlContainer]], + }, + ], }) export class ExtensibleFormComponent { - @ViewChildren(ExtensibleFormPropComponent) - formProps!: QueryList; - @Input() - set selectedRecord(record: R) { - const type = !record || JSON.stringify(record) === '{}' ? 'create' : 'edit'; - const propList = this.extensions[`${type}FormProps`].get(this.identifier).props; - this.groupedPropList = this.createGroupedList(propList); - this.record = record; - } + @ViewChildren(ExtensibleFormPropComponent) + formProps!: QueryList; - extraPropertiesKey = EXTRA_PROPERTIES_KEY; - groupedPropList!: GroupedFormPropList; - record!: R; + @Input() + set selectedRecord(record: R) { + const type = !record || JSON.stringify(record) === '{}' ? 'create' : 'edit'; + const propList = this.extensions[`${type}FormProps`].get(this.identifier).props; + this.groupedPropList = this.createGroupedList(propList); + this.record = record; + } - createGroupedList(propList: FormPropList) { - const groupedFormPropList = new GroupedFormPropList(); - propList.forEach(item => { - groupedFormPropList.addItem(item.value); - }); - return groupedFormPropList; - } + extraPropertiesKey = EXTRA_PROPERTIES_KEY; + groupedPropList!: GroupedFormPropList; + record!: R; - get form(): UntypedFormGroup { - return (this.container ? this.container.control : { controls: {} }) as UntypedFormGroup; - } + public readonly cdRef = inject(ChangeDetectorRef) + public readonly track = inject(TrackByService) + private container = inject(ControlContainer) + private extensions = inject(ExtensionsService); + private identifier = inject(EXTENSIONS_IDENTIFIER) - get extraProperties(): UntypedFormGroup { - return (this.form.controls.extraProperties || { controls: {} }) as UntypedFormGroup; - } + createGroupedList(propList: FormPropList) { + const groupedFormPropList = new GroupedFormPropList(); + propList.forEach(item => { + groupedFormPropList.addItem(item.value); + }); + return groupedFormPropList; + } + + get form(): UntypedFormGroup { + return (this.container ? this.container.control : {controls: {}}) as UntypedFormGroup; + } + + get extraProperties(): UntypedFormGroup { + return (this.form.controls.extraProperties || {controls: {}}) as UntypedFormGroup; + } - constructor( - public readonly cdRef: ChangeDetectorRef, - public readonly track: TrackByService, - private container: ControlContainer, - private extensions: ExtensionsService, - @Inject(EXTENSIONS_IDENTIFIER) private identifier: string, - ) {} } diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index af146e2367..79930e418e 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -1,13 +1,14 @@ import { ABP, ConfigStateService, + CoreModule, getShortDateFormat, getShortDateShortTimeFormat, getShortTimeFormat, ListService, PermissionService, } from '@abp/ng.core'; -import { formatDate } from '@angular/common'; +import { CommonModule, formatDate } from '@angular/common'; import { ChangeDetectionStrategy, Component, @@ -35,12 +36,26 @@ import { EXTENSIONS_IDENTIFIER, PROP_DATA_STREAM, } from '../../tokens/extensions.token'; +import { NgxDatatableModule } from '@swimlane/ngx-datatable'; +import { GridActionsComponent } from '../grid-actions/grid-actions.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgxDatatableDefaultDirective, NgxDatatableListDirective } from '@abp/ng.theme.shared'; const DEFAULT_ACTIONS_COLUMN_WIDTH = 150; - @Component({ +@Component({ exportAs: 'abpExtensibleTable', selector: 'abp-extensible-table', + standalone: true, + imports: [ + CommonModule, + CoreModule, + NgxDatatableModule, + GridActionsComponent, + NgbTooltip, + NgxDatatableDefaultDirective, + NgxDatatableListDirective, + ], templateUrl: './extensible-table.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) @@ -50,6 +65,7 @@ export class ExtensibleTableComponent implements OnChanges { set actionsText(value: string) { this._actionsText = value; } + get actionsText(): string { return this._actionsText ?? (this.actionList.length > 1 ? 'AbpUi::Actions' : ''); } @@ -57,14 +73,16 @@ export class ExtensibleTableComponent implements OnChanges { @Input() data!: R[]; @Input() list!: ListService; @Input() recordsTotal!: number; + @Input() set actionsColumnWidth(width: number) { this.setColumnWidths(width ? Number(width) : undefined); } + @Input() actionsTemplate?: TemplateRef; @Output() tableActivate = new EventEmitter(); - getInjected: typeof this.injector.get + getInjected: typeof this.injector.get; hasAtLeastOnePermittedAction: boolean; @@ -149,7 +167,7 @@ export class ExtensibleTableComponent implements OnChanges { if (!data?.currentValue) return; if (data.currentValue.length < 1) { - this.list.totalCount = this.recordsTotal + this.list.totalCount = this.recordsTotal; } this.data = data.currentValue.map((record: any, index: number) => { diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts index 22b5419b55..440c5e9adf 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts @@ -8,9 +8,15 @@ import { import { EntityAction, EntityActionList } from '../../models/entity-actions'; import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token'; import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component'; +import { CommonModule } from '@angular/common'; +import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; +import { CoreModule } from '@abp/ng.core'; +import {EllipsisDirective} from "@abp/ng.theme.shared"; @Component({ exportAs: 'abpGridActions', + standalone: true, + imports: [CommonModule, CoreModule, NgbDropdownModule, EllipsisDirective], selector: 'abp-grid-actions', templateUrl: './grid-actions.component.html', providers: [ diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts index afe421554b..2be1acba02 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts @@ -8,10 +8,15 @@ import { } from '../../models/toolbar-actions'; import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token'; import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component'; +import { CommonModule } from '@angular/common'; +import { CreateInjectorPipe } from '../../pipes/create-injector.pipe'; +import { CoreModule } from '@abp/ng.core'; @Component({ exportAs: 'abpPageToolbar', selector: 'abp-page-toolbar', + standalone: true, + imports: [CommonModule, CoreModule, CreateInjectorPipe], templateUrl: './page-toolbar.component.html', providers: [ { @@ -31,6 +36,7 @@ export class PageToolbarComponent readonly trackByFn: TrackByFunction> = (_, item) => item.action || item.component; + constructor(public readonly injector: Injector) { super(injector); } diff --git a/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts b/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts index 2bba45ff70..52ccd286ad 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/directives/prop-data.directive.ts @@ -13,6 +13,7 @@ import { PropData, PropList } from '../models/props'; @Directive({ exportAs: 'abpPropData', selector: '[abpPropData]', + standalone: true, }) export class PropDataDirective> extends PropData> diff --git a/npm/ng-packs/packages/components/extensible/src/lib/extensible.module.ts b/npm/ng-packs/packages/components/extensible/src/lib/extensible.module.ts index 334909a7e2..99bc25b6f4 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/extensible.module.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/extensible.module.ts @@ -15,23 +15,25 @@ import { ExtensibleTableComponent, GridActionsComponent, PageToolbarComponent, - ExtensibleDateTimePickerComponent + ExtensibleDateTimePickerComponent, } from './components'; import { PropDataDirective } from './directives/prop-data.directive'; import { CreateInjectorPipe } from './pipes/create-injector.pipe'; import { DisabledDirective } from '@abp/ng.theme.shared'; +const importWithExport = [ + DisabledDirective, + ExtensibleDateTimePickerComponent, + ExtensibleFormPropComponent, + GridActionsComponent, + PropDataDirective, + PageToolbarComponent, + CreateInjectorPipe, + ExtensibleFormComponent, + ExtensibleTableComponent, +]; @NgModule({ - declarations: [ - ExtensibleDateTimePickerComponent, - PageToolbarComponent, - GridActionsComponent, - ExtensibleFormPropComponent, - ExtensibleFormComponent, - ExtensibleTableComponent, - PropDataDirective, - CreateInjectorPipe, - ], + declarations: [], imports: [ CoreModule, ThemeSharedModule, @@ -41,15 +43,8 @@ import { DisabledDirective } from '@abp/ng.theme.shared'; NgbTimepickerModule, NgbTypeaheadModule, NgbTooltipModule, - DisabledDirective, - ], - exports: [ - PageToolbarComponent, - GridActionsComponent, - ExtensibleFormComponent, - ExtensibleTableComponent, - PropDataDirective, - CreateInjectorPipe, + ...importWithExport, ], + exports: [...importWithExport], }) export class ExtensibleModule {} diff --git a/npm/ng-packs/packages/components/extensible/src/lib/pipes/create-injector.pipe.ts b/npm/ng-packs/packages/components/extensible/src/lib/pipes/create-injector.pipe.ts index 3536fa4dad..4b410fcea9 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/pipes/create-injector.pipe.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/pipes/create-injector.pipe.ts @@ -12,6 +12,7 @@ import { EXTENSIONS_ACTION_CALLBACK, EXTENSIONS_ACTION_DATA } from '../tokens/ex @Pipe({ name: 'createInjector', + standalone: true, }) export class CreateInjectorPipe implements PipeTransform { public transform( diff --git a/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts b/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts new file mode 100644 index 0000000000..854ae1f9d9 --- /dev/null +++ b/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts @@ -0,0 +1,77 @@ +import { inject, Injectable } from '@angular/core'; + import { ValidatorFn, Validators } from '@angular/forms'; +import { AbpValidators, ConfigStateService } from '@abp/ng.core'; +import { map } from 'rxjs/operators'; +import { FormProp } from '../models/form-props'; +import { ePropType } from '../enums/props.enum'; + +@Injectable() +export class ExtensibleFormPropService { + #configStateService = inject(ConfigStateService); + + meridian$ = this.#configStateService + .getDeep$('localization.currentCulture.dateTimeFormat.shortTimePattern') + .pipe(map((shortTimePattern: string | undefined) => (shortTimePattern || '').includes('tt'))); + + isRequired(validator: ValidatorFn) { + return ( + validator === Validators.required || + validator === AbpValidators.required || + validator.name === 'required' + ); + } + + getComponent(prop: FormProp) { + if (prop.template) { + return 'template'; + } + switch (prop.type) { + case ePropType.Boolean: + return 'checkbox'; + case ePropType.Date: + return 'date'; + case ePropType.DateTime: + return 'dateTime'; + case ePropType.Hidden: + return 'hidden'; + case ePropType.MultiSelect: + return 'multiselect'; + case ePropType.Text: + return 'textarea'; + case ePropType.Time: + return 'time'; + case ePropType.Typeahead: + return 'typeahead'; + case ePropType.PasswordInputGroup: + return 'passwordinputgroup'; + default: + return prop.options ? 'select' : 'input'; + } + } + + getType(prop: FormProp) { + switch (prop.type) { + case ePropType.Date: + case ePropType.String: + return 'text'; + case ePropType.Boolean: + return 'checkbox'; + case ePropType.Number: + return 'number'; + case ePropType.Email: + return 'email'; + case ePropType.Password: + return 'password'; + case ePropType.PasswordInputGroup: + return 'passwordinputgroup'; + default: + return 'hidden'; + } + } + + calcAsterisks(validators: ValidatorFn[]) { + if (!validators) return ''; + const required = validators.find(v => this.isRequired(v)); + return required ? '*' : ''; + } +} diff --git a/npm/ng-packs/packages/components/page/src/page.module.ts b/npm/ng-packs/packages/components/page/src/page.module.ts index 5bb27fbc66..acc397421d 100644 --- a/npm/ng-packs/packages/components/page/src/page.module.ts +++ b/npm/ng-packs/packages/components/page/src/page.module.ts @@ -9,7 +9,7 @@ import { PageToolbarContainerComponent, } from './page-parts.component'; import { PageComponent } from './page.component'; -import {ExtensibleModule} from "@abp/ng.components/extensible"; +import {PageToolbarComponent} from "@abp/ng.components/extensible"; const exportedDeclarations = [ PageComponent, @@ -21,7 +21,7 @@ const exportedDeclarations = [ @NgModule({ declarations: [...exportedDeclarations], - imports: [CommonModule, CoreModule, ThemeSharedModule, ExtensibleModule], + imports: [CommonModule, CoreModule, ThemeSharedModule, PageToolbarComponent], exports: [...exportedDeclarations], }) export class PageModule {} diff --git a/npm/ng-packs/packages/core/src/lib/abstracts/ng-model.component.ts b/npm/ng-packs/packages/core/src/lib/abstracts/ng-model.component.ts index 0f0eaa3722..8cabb30b0d 100644 --- a/npm/ng-packs/packages/core/src/lib/abstracts/ng-model.component.ts +++ b/npm/ng-packs/packages/core/src/lib/abstracts/ng-model.component.ts @@ -1,11 +1,11 @@ -import { ChangeDetectorRef, Component, Injector, Input } from '@angular/core'; +import { ChangeDetectorRef, Component, inject, Input } from '@angular/core'; import { ControlValueAccessor } from '@angular/forms'; // Not an abstract class on purpose. Do not change! @Component({ template: '' }) export class AbstractNgModelComponent implements ControlValueAccessor { protected _value!: T; - protected cdRef: ChangeDetectorRef; + protected cdRef = inject(ChangeDetectorRef); onChange?: (value: T) => void; onTouched?: () => void; @@ -39,10 +39,6 @@ export class AbstractNgModelComponent implements ControlValueAcc return this._value; } - constructor(public injector: Injector) { - this.cdRef = injector.get(ChangeDetectorRef); - } - notifyValueChange(): void { if (this.onChange) { this.onChange(this.value); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts index ee2dd5aeac..89766ce992 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts @@ -43,8 +43,4 @@ export class FormCheckboxComponent extends AbstractNgModelComponent { @Input() checkboxReadonly = false; @Output() checkboxBlur = new EventEmitter(); @Output() checkboxFocus = new EventEmitter(); - - constructor(injector: Injector) { - super(injector); - } } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts index 8aa68a2047..d759163a0d 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts @@ -45,8 +45,4 @@ export class FormInputComponent extends AbstractNgModelComponent { @Input() inputClass = 'form-control'; @Output() formBlur = new EventEmitter(); @Output() formFocus = new EventEmitter(); - - constructor(injector: Injector) { - super(injector); - } } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts index 22fcd6e4f5..44207199ec 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts @@ -1,9 +1,12 @@ import { Component, forwardRef, Injector, Input } from '@angular/core'; import { AbstractNgModelComponent } from '@abp/ng.core'; -import { NG_VALUE_ACCESSOR } from '@angular/forms'; +import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'abp-password', + standalone: true, + imports: [CommonModule, FormsModule], templateUrl: `./password.component.html`, providers: [ { @@ -18,10 +21,6 @@ export class PasswordComponent extends AbstractNgModelComponent { @Input() formControlName!: string; fieldTextType?: boolean; - constructor(injector: Injector) { - super(injector); - } - toggleFieldTextType() { this.fieldTextType = !this.fieldTextType; } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts index d7bfc999ff..2cad957942 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts @@ -10,6 +10,7 @@ import { @Directive({ selector: '[abpEllipsis]', + standalone:true }) export class EllipsisDirective implements AfterViewInit { @Input('abpEllipsis') @@ -44,9 +45,3 @@ export class EllipsisDirective implements AfterViewInit { this.cdRef.detectChanges(); } } - -@NgModule({ - exports: [EllipsisDirective], - declarations: [EllipsisDirective], -}) -export class EllipsisModule {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts index b41be45343..eb781666c1 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts @@ -7,6 +7,7 @@ import { debounceTime } from 'rxjs/operators'; @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector selector: 'ngx-datatable[default]', + standalone:true, exportAs: 'ngxDatatableDefault', }) export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index a179669473..9ce5d1d860 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -21,6 +21,7 @@ import { @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector selector: 'ngx-datatable[list]', + standalone: true, exportAs: 'ngxDatatableList', }) export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 71c081c9b2..44fbc85c0f 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -22,7 +22,7 @@ import { ModalComponent } from './components/modal/modal.component'; import { ToastContainerComponent } from './components/toast-container/toast-container.component'; import { ToastComponent } from './components/toast/toast.component'; import { DEFAULT_VALIDATION_BLUEPRINTS } from './constants/validation'; -import { EllipsisModule } from './directives/ellipsis.directive'; +import { EllipsisDirective } from './directives/ellipsis.directive'; import { LoadingDirective } from './directives/loading.directive'; import { NgxDatatableDefaultDirective } from './directives/ngx-datatable-default.directive'; import { NgxDatatableListDirective } from './directives/ngx-datatable-list.directive'; @@ -52,9 +52,6 @@ const declarationsWithExports = [ ModalComponent, ToastComponent, ToastContainerComponent, - PasswordComponent, - NgxDatatableDefaultDirective, - NgxDatatableListDirective, LoadingDirective, ModalCloseDirective, AbpVisibleDirective, @@ -68,14 +65,16 @@ const declarationsWithExports = [ NgxDatatableModule, NgxValidateCoreModule, NgbPaginationModule, - EllipsisModule, + EllipsisDirective, CardModule, + PasswordComponent, + NgxDatatableDefaultDirective, + NgxDatatableListDirective, DisabledDirective ], declarations: [...declarationsWithExports, HttpErrorWrapperComponent], exports: [ NgxDatatableModule, - EllipsisModule, NgxValidateCoreModule, CardModule, DisabledDirective, From c8e97adb643094031bb1b250df9d1b4660cf49d7 Mon Sep 17 00:00:00 2001 From: Mahmut Gundogdu Date: Tue, 7 Nov 2023 21:08:45 +0300 Subject: [PATCH 2/3] Clean some constructor injection to inject() --- .../extensible-table.component.ts | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index 79930e418e..b04689430b 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -13,6 +13,7 @@ import { ChangeDetectionStrategy, Component, EventEmitter, + inject, Inject, Injector, Input, @@ -82,12 +83,8 @@ export class ExtensibleTableComponent implements OnChanges { @Output() tableActivate = new EventEmitter(); - getInjected: typeof this.injector.get; - hasAtLeastOnePermittedAction: boolean; - entityPropTypeClasses: EntityPropTypeClass; - readonly columnWidths!: number[]; readonly propList: EntityPropList; @@ -96,20 +93,20 @@ export class ExtensibleTableComponent implements OnChanges { readonly trackByFn: TrackByFunction> = (_, item) => item.name; - constructor( - @Inject(LOCALE_ID) private locale: string, - private config: ConfigStateService, - private injector: Injector, - ) { - this.entityPropTypeClasses = injector.get(ENTITY_PROP_TYPE_CLASSES); - this.getInjected = injector.get.bind(injector); - const extensions = injector.get(ExtensionsService); - const name = injector.get(EXTENSIONS_IDENTIFIER); + locale = inject(LOCALE_ID); + private config = inject(ConfigStateService); + entityPropTypeClasses = inject(ENTITY_PROP_TYPE_CLASSES); + #injector = inject(Injector); + getInjected = this.#injector.get.bind(this.#injector); + + constructor() { + const extensions = this.#injector.get(ExtensionsService); + const name = this.#injector.get(EXTENSIONS_IDENTIFIER); this.propList = extensions.entityProps.get(name).props; this.actionList = extensions['entityActions'].get(name) .actions as unknown as EntityActionList; - const permissionService = injector.get(PermissionService); + const permissionService = this.#injector.get(PermissionService); this.hasAtLeastOnePermittedAction = permissionService.filterItemsByPolicy( this.actionList.toArray().map(action => ({ requiredPolicy: action.permission })), @@ -188,7 +185,7 @@ export class ExtensibleTableComponent implements OnChanges { useValue: value, }, ], - parent: this.injector, + parent: this.#injector, }); record[propKey].component = prop.value.component; } From b3d2ac7aaf3730b835e285063aa5c3e036192acf Mon Sep 17 00:00:00 2001 From: Mahmut Gundogdu Date: Mon, 13 Nov 2023 15:42:08 +0300 Subject: [PATCH 3/3] implement comments, fix review issues --- .../extensible-form/extensible-form-prop.component.ts | 2 -- .../components/extensible-table/extensible-table.component.ts | 2 -- .../src/lib/components/grid-actions/grid-actions.component.ts | 3 +-- .../src/lib/components/page-toolbar/page-toolbar.component.ts | 3 +-- .../src/lib/services/extensible-form-prop.service.ts | 2 +- npm/ng-packs/packages/components/page/src/page.module.ts | 3 +-- .../src/lib/components/password/password.component.ts | 2 +- 7 files changed, 5 insertions(+), 12 deletions(-) diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts index 0d8c692015..ca32fd3e7a 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts @@ -42,7 +42,6 @@ import { PropData } from '../../models/props'; import { selfFactory } from '../../utils/factory.util'; import { addTypeaheadTextSuffix } from '../../utils/typeahead.util'; import { eThemeSharedComponents } from '../../enums/components'; -import { CommonModule } from '@angular/common'; import { ExtensibleDateTimePickerComponent } from '../date-time-picker/extensible-date-time-picker.component'; import { NgxValidateCoreModule } from '@ngx-validate/core'; import { ExtensibleFormPropService } from '../../services/extensible-form-prop.service'; @@ -53,7 +52,6 @@ import {CreateInjectorPipe} from "../../pipes/create-injector.pipe"; templateUrl: './extensible-form-prop.component.html', standalone: true, imports: [ - CommonModule, CoreModule, ExtensibleDateTimePickerComponent, NgbDatepickerModule, diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index b04689430b..697f8d36bd 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -33,7 +33,6 @@ import { PropData } from '../../models/props'; import { ExtensionsService } from '../../services/extensions.service'; import { ENTITY_PROP_TYPE_CLASSES, - EntityPropTypeClass, EXTENSIONS_IDENTIFIER, PROP_DATA_STREAM, } from '../../tokens/extensions.token'; @@ -49,7 +48,6 @@ const DEFAULT_ACTIONS_COLUMN_WIDTH = 150; selector: 'abp-extensible-table', standalone: true, imports: [ - CommonModule, CoreModule, NgxDatatableModule, GridActionsComponent, diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts index 440c5e9adf..ebccd6e163 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts @@ -8,7 +8,6 @@ import { import { EntityAction, EntityActionList } from '../../models/entity-actions'; import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token'; import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component'; -import { CommonModule } from '@angular/common'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { CoreModule } from '@abp/ng.core'; import {EllipsisDirective} from "@abp/ng.theme.shared"; @@ -16,7 +15,7 @@ import {EllipsisDirective} from "@abp/ng.theme.shared"; @Component({ exportAs: 'abpGridActions', standalone: true, - imports: [CommonModule, CoreModule, NgbDropdownModule, EllipsisDirective], + imports: [ CoreModule, NgbDropdownModule, EllipsisDirective], selector: 'abp-grid-actions', templateUrl: './grid-actions.component.html', providers: [ diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts index 2be1acba02..85685cdee6 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts @@ -8,7 +8,6 @@ import { } from '../../models/toolbar-actions'; import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token'; import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component'; -import { CommonModule } from '@angular/common'; import { CreateInjectorPipe } from '../../pipes/create-injector.pipe'; import { CoreModule } from '@abp/ng.core'; @@ -16,7 +15,7 @@ import { CoreModule } from '@abp/ng.core'; exportAs: 'abpPageToolbar', selector: 'abp-page-toolbar', standalone: true, - imports: [CommonModule, CoreModule, CreateInjectorPipe], + imports: [ CoreModule, CreateInjectorPipe], templateUrl: './page-toolbar.component.html', providers: [ { diff --git a/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts b/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts index 854ae1f9d9..bf6de7ed05 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/services/extensible-form-prop.service.ts @@ -7,7 +7,7 @@ import { ePropType } from '../enums/props.enum'; @Injectable() export class ExtensibleFormPropService { - #configStateService = inject(ConfigStateService); + readonly #configStateService = inject(ConfigStateService); meridian$ = this.#configStateService .getDeep$('localization.currentCulture.dateTimeFormat.shortTimePattern') diff --git a/npm/ng-packs/packages/components/page/src/page.module.ts b/npm/ng-packs/packages/components/page/src/page.module.ts index acc397421d..77ffca0951 100644 --- a/npm/ng-packs/packages/components/page/src/page.module.ts +++ b/npm/ng-packs/packages/components/page/src/page.module.ts @@ -1,6 +1,5 @@ import { CoreModule } from '@abp/ng.core'; import { ThemeSharedModule } from '@abp/ng.theme.shared'; - import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { PagePartDirective } from './page-part.directive'; import { @@ -21,7 +20,7 @@ const exportedDeclarations = [ @NgModule({ declarations: [...exportedDeclarations], - imports: [CommonModule, CoreModule, ThemeSharedModule, PageToolbarComponent], + imports: [CoreModule, ThemeSharedModule, PageToolbarComponent], exports: [...exportedDeclarations], }) export class PageModule {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts index 44207199ec..4567ef45d6 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts @@ -1,4 +1,4 @@ -import { Component, forwardRef, Injector, Input } from '@angular/core'; +import { Component, forwardRef, Input } from '@angular/core'; import { AbstractNgModelComponent } from '@abp/ng.core'; import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { CommonModule } from '@angular/common';