Merge pull request #18364 from abpframework/auto-merge/rel-8-0/2316

Merge branch dev with rel-8.0
pull/18380/head
maliming 1 year ago committed by GitHub
commit ba8ba8fac6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -52,12 +52,13 @@
[abpDisabled]="disabled"
class="form-select form-control"
>
<option
*ngFor="let option of options$ | async; trackBy: track.by('value')"
[ngValue]="option.value"
>
{{ option.key }}
</option>
@for (option of options$ | async; track option.value) {
<option
[ngValue]="option.value"
>
{{ option.key }}
</option>
}
</select>
</ng-template>
@ -161,18 +162,21 @@
</div>
</ng-template>
<small *ngIf="prop.formText" class="text-muted d-block">{{
@if (prop.formText) {
<small class="text-muted d-block">{{
prop.formText | abpLocalization
}}</small>
}
</div>
</ng-container>
<ng-template #label let-classes>
<label [htmlFor]="prop.id" [ngClass]="classes || 'form-label'">
<ng-container *ngIf="prop.displayTextResolver; else displayNameTemplate">
@if (prop.displayTextResolver) {
{{ prop.displayTextResolver(data) | abpLocalization }}
</ng-container>
<ng-template #displayNameTemplate> {{ prop.displayName | abpLocalization }}</ng-template>
}@else{
{{ prop.displayName | abpLocalization }}
}
{{ asterisk }}
</label>
</ng-template>

@ -1,5 +1,5 @@
import { EXTENSIONS_FORM_PROP, EXTENSIONS_FORM_PROP_DATA } from './../../tokens/extensions.token';
import { ABP, CoreModule, ShowPasswordDirective, TrackByService } from '@abp/ng.core';
import { ABP, LocalizationModule, PermissionDirective, ShowPasswordDirective, TrackByService } from '@abp/ng.core';
import {
AfterViewInit,
ChangeDetectionStrategy,
@ -30,11 +30,7 @@ import {
} from '@ng-bootstrap/ng-bootstrap';
import { Observable, of } from 'rxjs';
import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import {
DateAdapter,
DisabledDirective,
TimeAdapter,
} from '@abp/ng.theme.shared';
import { DateAdapter, DisabledDirective, TimeAdapter } from '@abp/ng.theme.shared';
import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties';
import { FormProp } from '../../models/form-props';
import { PropData } from '../../models/props';
@ -44,14 +40,14 @@ import { eThemeSharedComponents } from '../../enums/components';
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";
import { CreateInjectorPipe } from '../../pipes/create-injector.pipe';
import { AsyncPipe, NgClass, NgSwitch, NgSwitchCase, NgTemplateOutlet } from '@angular/common';
@Component({
selector: 'abp-extensible-form-prop',
templateUrl: './extensible-form-prop.component.html',
standalone: true,
imports: [
CoreModule,
ExtensibleDateTimePickerComponent,
NgbDatepickerModule,
NgbTimepickerModule,
@ -60,7 +56,14 @@ import {CreateInjectorPipe} from "../../pipes/create-injector.pipe";
NgxValidateCoreModule,
NgbTypeaheadModule,
CreateInjectorPipe,
ShowPasswordDirective
ShowPasswordDirective,
PermissionDirective,
LocalizationModule,
AsyncPipe,
NgSwitch,
NgSwitchCase,
NgClass,
NgTemplateOutlet,
],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ExtensibleFormPropService],

@ -5,8 +5,8 @@
[list]="list"
(activate)="tableActivate.emit($event)"
>
@if (actionsTemplate || (actionList.length && hasAtLeastOnePermittedAction)) {
<ngx-datatable-column
*ngIf="actionsTemplate || (actionList.length && hasAtLeastOnePermittedAction)"
[name]="actionsText | abpLocalization"
[maxWidth]="columnWidths[0]"
[width]="columnWidths[0]"
@ -21,50 +21,46 @@
</ng-template>
</ng-template>
</ngx-datatable-column>
<ng-container *ngFor="let prop of propList; let i = index; trackBy: trackByFn">
<ngx-datatable-column
*abpVisible="prop.columnVisible(getInjected)"
[width]="columnWidths[i + 1] || 200"
[name]="prop.displayName | abpLocalization"
[prop]="prop.name"
[sortable]="prop.sortable"
>
<ng-template ngx-datatable-header-template let-column="column">
<span
*ngIf="prop.tooltip; else elseBlock"
[ngbTooltip]="prop.tooltip | abpLocalization"
container="body"
>
{{ column.name }} <i class="fa fa-info-circle" aria-hidden="true"></i>
</span>
<ng-template #elseBlock>
{{ column.name }}
</ng-template>
</ng-template>
<ng-template let-row="row" let-i="index" ngx-datatable-cell-template>
<ng-container *abpPermission="prop.permission; runChangeDetection: false">
<ng-container *abpVisible="row['_' + prop.name]?.visible">
<div
*ngIf="!row['_' + prop.name].component; else component"
[innerHTML]="row['_' + prop.name]?.value | async"
(click)="
prop.action && prop.action({ getInjected: getInjected, record: row, index: i })
"
[ngClass]="entityPropTypeClasses[prop.type]"
[class.pointer]="prop.action"
></div>
</ng-container>
<ng-template #component>
<ng-container
*ngComponentOutlet="
row['_' + prop.name].component;
injector: row['_' + prop.name].injector
"
></ng-container>
</ng-template>
} @for (prop of propList; track prop.name; let i = $index) {
<ngx-datatable-column
*abpVisible="prop.columnVisible(getInjected)"
[width]="columnWidths[i + 1] || 200"
[name]="prop.displayName | abpLocalization"
[prop]="prop.name"
[sortable]="prop.sortable"
>
<ng-template ngx-datatable-header-template let-column="column">
@if (prop.tooltip) {
<span [ngbTooltip]="prop.tooltip | abpLocalization" container="body">
{{ column.name }} <i class="fa fa-info-circle" aria-hidden="true"></i>
</span>
}@else{
{{ column.name }}
}
</ng-template>
<ng-template let-row="row" let-i="index" ngx-datatable-cell-template>
<ng-container *abpPermission="prop.permission; runChangeDetection: false">
<ng-container *abpVisible="row['_' + prop.name]?.visible">
@if (!row['_' + prop.name].component) {
<div
[innerHTML]="row['_' + prop.name]?.value | async"
(click)="
prop.action && prop.action({ getInjected: getInjected, record: row, index: i })
"
[ngClass]="entityPropTypeClasses[prop.type]"
[class.pointer]="prop.action"
></div>
}@else{
<ng-container
*ngComponentOutlet="
row['_' + prop.name].component;
injector: row['_' + prop.name].injector
"
></ng-container>
}
</ng-container>
</ng-template>
</ngx-datatable-column>
</ng-container>
</ng-container>
</ng-template>
</ngx-datatable-column>
}
</ngx-datatable>

@ -6,9 +6,18 @@ import {
getShortDateShortTimeFormat,
getShortTimeFormat,
ListService,
LocalizationModule,
PermissionDirective,
PermissionService,
} from '@abp/ng.core';
import { formatDate } from '@angular/common';
import {
AsyncPipe,
formatDate,
NgComponentOutlet,
NgFor,
NgIf,
NgTemplateOutlet,
} from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
@ -51,13 +60,17 @@ const DEFAULT_ACTIONS_COLUMN_WIDTH = 150;
selector: 'abp-extensible-table',
standalone: true,
imports: [
CoreModule,
AbpVisibleDirective,
NgxDatatableModule,
GridActionsComponent,
NgbTooltip,
NgxDatatableDefaultDirective,
NgxDatatableListDirective,
PermissionDirective,
LocalizationModule,
AsyncPipe,
NgTemplateOutlet,
NgComponentOutlet,
],
templateUrl: './extensible-table.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,

@ -1,4 +1,5 @@
<div *ngIf="actionList.length > 1" ngbDropdown container="body" class="d-inline-block">
@if (actionList.length > 1) {
<div ngbDropdown container="body" class="d-inline-block">
<button
class="btn btn-primary btn-sm dropdown-toggle"
data-toggle="dropdown"
@ -8,56 +9,58 @@
<i [ngClass]="icon" [class.me-1]="icon"></i>{{ text | abpLocalization }}
</button>
<div ngbDropdownMenu>
<ng-container
*ngFor="let action of actionList; trackBy: trackByFn"
[ngTemplateOutlet]="dropDownBtnItemTmp"
[ngTemplateOutletContext]="{ $implicit: action }"
>
</ng-container>
@for (action of actionList; track action.text) {
<ng-container
[ngTemplateOutlet]="dropDownBtnItemTmp"
[ngTemplateOutletContext]="{ $implicit: action }"
>
</ng-container>
}
</div>
</div>
} @if (actionList.length === 1) {
<ng-container
*ngIf="actionList.length === 1"
[ngTemplateOutlet]="btnTmp"
[ngTemplateOutletContext]="{ $implicit: actionList.get(0).value }"
></ng-container>
}
<ng-template #dropDownBtnItemTmp let-action>
<ng-container *ngIf="action.visible(data)">
<button
ngbDropdownItem
*abpPermission="action.permission; runChangeDetection: false"
(click)="action.action(data)"
type="button"
>
<ng-container
*ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"
></ng-container>
</button>
</ng-container>
@if (action.visible(data)) {
<button
ngbDropdownItem
*abpPermission="action.permission; runChangeDetection: false"
(click)="action.action(data)"
type="button"
>
<ng-container
*ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"
></ng-container>
</button>
}
</ng-template>
<ng-template #buttonContentTmp let-action>
<i [ngClass]="action.icon" [class.me-1]="action.icon"></i>
<span *ngIf="action.icon; else ellipsis">{{ action.text | abpLocalization }}</span>
<ng-template #ellipsis>
<div abpEllipsis>{{ action.text | abpLocalization }}</div>
</ng-template>
@if (action.icon) {
<span>{{ action.text | abpLocalization }}</span>
}@else {
<div abpEllipsis>{{ action.text | abpLocalization }}</div>
}
</ng-template>
<ng-template #btnTmp let-action>
<ng-container *ngIf="action.visible(data)">
<button
*abpPermission="action.permission; runChangeDetection: false"
(click)="action.action(data)"
type="button"
[class]="action.btnClass"
[style]="action.btnStyle"
>
<ng-container
*ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"
></ng-container>
</button>
</ng-container>
@if (action.visible(data)) {
<button
*abpPermission="action.permission; runChangeDetection: false"
(click)="action.action(data)"
type="button"
[class]="action.btnClass"
[style]="action.btnStyle"
>
<ng-container
*ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"
></ng-container>
</button>
}
</ng-template>

@ -9,13 +9,21 @@ import { EntityAction, EntityActionList } from '../../models/entity-actions';
import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token';
import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { CoreModule } from '@abp/ng.core';
import {EllipsisDirective} from "@abp/ng.theme.shared";
import { LocalizationModule, PermissionDirective } from '@abp/ng.core';
import { EllipsisDirective } from '@abp/ng.theme.shared';
import { NgClass, NgTemplateOutlet } from '@angular/common';
@Component({
exportAs: 'abpGridActions',
standalone: true,
imports: [ CoreModule, NgbDropdownModule, EllipsisDirective],
imports: [
NgbDropdownModule,
EllipsisDirective,
PermissionDirective,
NgClass,
LocalizationModule,
NgTemplateOutlet,
],
selector: 'abp-grid-actions',
templateUrl: './grid-actions.component.html',
providers: [

@ -1,31 +1,29 @@
<div class="row justify-content-end mx-0 gap-2" id="AbpContentToolbar">
<div
class="col-auto px-0 pt-0 "
[class.pe-0]="last"
*ngFor="let action of actionList; trackBy: trackByFn; let last = last"
>
<ng-container *ngIf="action.visible(data)">
<ng-container *abpPermission="action.permission;runChangeDetection: false">
<ng-container *ngIf="action.component as component; else button">
<ng-container
*ngComponentOutlet="component; injector: record | createInjector: action:this"
></ng-container>
</ng-container>
@for (action of actionList; track action.component || action.action; let last = $last) {
<div class="col-auto px-0 pt-0" [class.pe-0]="last">
@if (action.visible(data)) {
<ng-container *abpPermission="action.permission; runChangeDetection: false">
@if (action.component; as component) {
<ng-container
*ngComponentOutlet="component; injector: record | createInjector: action:this"
></ng-container>
<ng-template #button>
<ng-container *ngIf="asToolbarAction(action).value as toolbarAction">
<button
(click)="action.action(data)"
type="button"
[ngClass]="toolbarAction.btnClass ? toolbarAction.btnClass : defaultBtnClass"
class="d-inline-flex align-items-center gap-1"
>
<i [ngClass]="toolbarAction.icon" [class.me-1]="toolbarAction.icon"></i>
{{ toolbarAction.text | abpLocalization }}
</button>
</ng-container>
</ng-template>
</ng-container>
}@else {
@if (asToolbarAction(action).value; as toolbarAction ) {
<button
(click)="action.action(data)"
type="button"
[ngClass]="toolbarAction?.btnClass ? toolbarAction?.btnClass : defaultBtnClass"
class="d-inline-flex align-items-center gap-1"
>
<i [ngClass]="toolbarAction?.icon" [class.me-1]="toolbarAction?.icon"></i>
{{ toolbarAction?.text | abpLocalization }}
</button>
}
}
</ng-container>
}
</div>
}
</div>

@ -9,13 +9,20 @@ import {
import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token';
import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component';
import { CreateInjectorPipe } from '../../pipes/create-injector.pipe';
import { CoreModule } from '@abp/ng.core';
import { LocalizationModule, PermissionDirective } from '@abp/ng.core';
import { NgClass, NgComponentOutlet } from '@angular/common';
@Component({
exportAs: 'abpPageToolbar',
selector: 'abp-page-toolbar',
standalone: true,
imports: [ CoreModule, CreateInjectorPipe],
imports: [
CreateInjectorPipe,
PermissionDirective,
LocalizationModule,
NgClass,
NgComponentOutlet,
],
templateUrl: './page-toolbar.component.html',
providers: [
{

@ -40,6 +40,16 @@ import { DefaultQueueManager } from './utils/queue';
import { IncludeLocalizationResourcesProvider } from './providers/include-localization-resources.provider';
import { SORT_COMPARE_FUNC, compareFuncFactory } from './tokens/compare-func.token';
const standaloneDirectives = [
AutofocusDirective,
InputEventDebounceDirective,
ForDirective,
FormSubmitDirective,
InitDirective,
PermissionDirective,
ReplaceableTemplateDirective,
StopPropagationDirective,
];
/**
* BaseCoreModule is the module that holds
* all imports, declarations, exports, and entryComponents
@ -55,23 +65,16 @@ import { SORT_COMPARE_FUNC, compareFuncFactory } from './tokens/compare-func.tok
RouterModule,
LocalizationModule,
AbstractNgModelComponent,
AutofocusDirective,
DynamicLayoutComponent,
ForDirective,
FormSubmitDirective,
InitDirective,
InputEventDebounceDirective,
PermissionDirective,
ReplaceableRouteContainerComponent,
ReplaceableTemplateDirective,
RouterOutletComponent,
SortPipe,
SafeHtmlPipe,
StopPropagationDirective,
ToInjectorPipe,
ShortDateTimePipe,
ShortTimePipe,
ShortDatePipe,
...standaloneDirectives,
],
imports: [
CommonModule,
@ -80,22 +83,15 @@ import { SORT_COMPARE_FUNC, compareFuncFactory } from './tokens/compare-func.tok
ReactiveFormsModule,
RouterModule,
LocalizationModule,
...standaloneDirectives,
],
declarations: [
AbstractNgModelComponent,
AutofocusDirective,
DynamicLayoutComponent,
ForDirective,
FormSubmitDirective,
InitDirective,
InputEventDebounceDirective,
PermissionDirective,
ReplaceableRouteContainerComponent,
ReplaceableTemplateDirective,
RouterOutletComponent,
SortPipe,
SafeHtmlPipe,
StopPropagationDirective,
ToInjectorPipe,
ShortDateTimePipe,
ShortTimePipe,
@ -179,7 +175,7 @@ export class CoreModule {
},
{
provide: SORT_COMPARE_FUNC,
useFactory: compareFuncFactory
useFactory: compareFuncFactory,
},
{
provide: QUEUE_MANAGER,

@ -1,7 +1,7 @@
import { AfterViewInit, Directive, ElementRef, Input } from '@angular/core';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
standalone: true,
selector: '[autofocus]',
})
export class AutofocusDirective implements AfterViewInit {

@ -4,7 +4,7 @@ import { debounceTime } from 'rxjs/operators';
import { SubscriptionService } from '../services/subscription.service';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
standalone: true,
selector: '[input.debounce]',
providers: [SubscriptionService],
})

@ -33,6 +33,7 @@ class RecordView {
}
@Directive({
standalone: true,
selector: '[abpFor]',
})
export class ForDirective implements OnChanges {

@ -18,7 +18,7 @@ type Controls = { [key: string]: UntypedFormControl } | UntypedFormGroup[];
* @deprecated FormSubmitDirective will be removed in V7.0.0. Use `ngSubmit` instead.
*/
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
standalone: true,
selector: 'form[ngSubmit][formGroup]',
providers: [SubscriptionService],
})

@ -1,6 +1,9 @@
import { Directive, Output, EventEmitter, ElementRef, AfterViewInit } from '@angular/core';
@Directive({ selector: '[abpInit]' })
@Directive({
standalone: true,
selector: '[abpInit]',
})
export class InitDirective implements AfterViewInit {
@Output('abpInit') readonly init = new EventEmitter<ElementRef<any>>();

@ -17,6 +17,7 @@ import { QUEUE_MANAGER } from '../tokens/queue.token';
import { QueueManager } from '../utils/queue';
@Directive({
standalone: true,
selector: '[abpPermission]',
})
export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit {

@ -18,6 +18,7 @@ import { ReplaceableComponentsService } from '../services/replaceable-components
import { SubscriptionService } from '../services/subscription.service';
@Directive({
standalone: true,
selector: '[abpReplaceableTemplate]',
providers: [SubscriptionService],
})

@ -3,7 +3,7 @@ import { fromEvent } from 'rxjs';
import { SubscriptionService } from '../services/subscription.service';
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
standalone: true,
selector: '[click.stop]',
providers: [SubscriptionService],
})

Loading…
Cancel
Save