Browse Source

Merge pull request #24579 from abpframework/issue-24564

Angular - Applying the latest migrations - Issue 24564
issue-24672
Fahri Gedik 8 months ago
committed by GitHub
parent
commit
bdd621b6bd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 78
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html
  2. 23
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
  3. 240
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html
  4. 7
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts
  5. 65
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.html
  6. 4
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts
  7. 4
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html
  8. 103
      npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.html
  9. 13
      npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts
  10. 26
      npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.html
  11. 8
      npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts
  12. 4
      npm/ng-packs/packages/components/lookup/src/lib/lookup-search.component.ts
  13. 218
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html
  14. 3
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts
  15. 7
      npm/ng-packs/packages/setting-management/config/src/lib/components/email-setting-group/email-setting-group.component.ts
  16. 36
      npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.html
  17. 4
      npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.ts
  18. 102
      npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html
  19. 3
      npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts
  20. 7
      npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts
  21. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/card/card-body.component.ts
  22. 5
      npm/ng-packs/packages/theme-shared/src/lib/components/card/card-footer.component.ts
  23. 5
      npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.component.ts
  24. 5
      npm/ng-packs/packages/theme-shared/src/lib/components/card/card.component.ts
  25. 13
      npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts
  26. 77
      npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.html
  27. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts
  28. 13
      npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts
  29. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts
  30. 7
      npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts
  31. 2
      npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.html
  32. 4
      npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts
  33. 18
      npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.html
  34. 3
      npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts
  35. 74
      templates/app-nolayers/angular/src/app/home/home.component.html
  36. 74
      templates/app/angular/src/app/home/home.component.html

78
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html

@ -5,61 +5,47 @@
<div class="col-12 col-md-3"> <div class="col-12 col-md-3">
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist"> <ul class="nav flex-column nav-pills" id="nav-tab" role="tablist">
@if (!hideChangePasswordTab && (profile$ | async)) { @if (!hideChangePasswordTab && (profile$ | async)) {
<li class="nav-item" (click)="selectedTab = 0"> <li class="nav-item" (click)="selectedTab = 0">
<a <a class="nav-link" [class.active]="selectedTab === 0" role="tab" href="javascript:void(0)">{{
class="nav-link" 'AbpUi::ChangePassword' | abpLocalization }}</a>
[ngClass]="{ active: selectedTab === 0 }" </li>
role="tab"
href="javascript:void(0)"
>{{ 'AbpUi::ChangePassword' | abpLocalization }}</a
>
</li>
} }
<li class="nav-item mb-2" (click)="selectedTab = 1"> <li class="nav-item mb-2" (click)="selectedTab = 1">
<a <a class="nav-link" [class.active]="selectedTab === 1" role="tab" href="javascript:void(0)">{{
class="nav-link" 'AbpAccount::PersonalSettings' | abpLocalization }}</a>
[ngClass]="{ active: selectedTab === 1 }"
role="tab"
href="javascript:void(0)"
>{{ 'AbpAccount::PersonalSettings' | abpLocalization }}</a
>
</li> </li>
</ul> </ul>
</div> </div>
@if (profile$ | async) { @if (profile$ | async) {
<div class="col-12 col-md-9"> <div class="col-12 col-md-9">
@if (selectedTab === 0) { @if (selectedTab === 0) {
<div class="tab-content" [@fadeIn]> <div class="tab-content fade-in">
<div class="tab-pane active" role="tabpanel"> <div class="tab-pane active" role="tabpanel">
<h4> <h4>
{{ 'AbpIdentity::ChangePassword' | abpLocalization }} {{ 'AbpIdentity::ChangePassword' | abpLocalization }}
<hr /> <hr />
</h4> </h4>
<abp-change-password-form <abp-change-password-form *abpReplaceableTemplate="{
*abpReplaceableTemplate="{
componentKey: changePasswordKey componentKey: changePasswordKey
}" }"></abp-change-password-form>
></abp-change-password-form> </div>
</div> </div>
</div> }
} @if (selectedTab === 1) {
@if (selectedTab === 1) { <div class="tab-content fade-in">
<div class="tab-content" [@fadeIn]> <div class="tab-pane active" role="tabpanel">
<div class="tab-pane active" role="tabpanel"> <h4>
<h4> {{ 'AbpIdentity::PersonalSettings' | abpLocalization }}
{{ 'AbpIdentity::PersonalSettings' | abpLocalization }} <hr />
<hr /> </h4>
</h4> <abp-personal-settings-form *abpReplaceableTemplate="{
<abp-personal-settings-form
*abpReplaceableTemplate="{
componentKey: personalSettingsKey componentKey: personalSettingsKey
}" }"></abp-personal-settings-form>
></abp-personal-settings-form> </div>
</div>
</div>
}
</div> </div>
}
</div>
} }
</div> </div>
</div> </div>
</div> </div>

23
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts

@ -1,10 +1,9 @@
import { ProfileService } from '@abp/ng.account.core/proxy'; import { ProfileService } from '@abp/ng.account.core/proxy';
import { fadeIn, LoadingDirective } from '@abp/ng.theme.shared'; import { LoadingDirective } from '@abp/ng.theme.shared';
import { transition, trigger, useAnimation } from '@angular/animations';
import { Component, inject, OnInit } from '@angular/core'; import { Component, inject, OnInit } from '@angular/core';
import { eAccountComponents } from '../../enums/components'; import { eAccountComponents } from '../../enums/components';
import { ManageProfileStateService } from '../../services/manage-profile.state.service'; import { ManageProfileStateService } from '../../services/manage-profile.state.service';
import { NgClass, AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms';
import { LocalizationPipe, ReplaceableTemplateDirective } from '@abp/ng.core'; import { LocalizationPipe, ReplaceableTemplateDirective } from '@abp/ng.core';
import { PersonalSettingsComponent } from '../personal-settings/personal-settings.component'; import { PersonalSettingsComponent } from '../personal-settings/personal-settings.component';
@ -13,24 +12,34 @@ import { ChangePasswordComponent } from '../change-password/change-password.comp
@Component({ @Component({
selector: 'abp-manage-profile', selector: 'abp-manage-profile',
templateUrl: './manage-profile.component.html', templateUrl: './manage-profile.component.html',
animations: [trigger('fadeIn', [transition(':enter', useAnimation(fadeIn))])],
styles: [ styles: [
//TODO: move static styles
` `
.min-h-400 { .min-h-400 {
min-height: 400px; min-height: 400px;
} }
.fade-in {
animation: fadeIn 350ms ease both;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
`, `,
], ],
imports: [ imports: [
NgClass,
AsyncPipe, AsyncPipe,
ReactiveFormsModule, ReactiveFormsModule,
PersonalSettingsComponent, PersonalSettingsComponent,
ChangePasswordComponent, ChangePasswordComponent,
LocalizationPipe, LocalizationPipe,
ReplaceableTemplateDirective, ReplaceableTemplateDirective,
LoadingDirective, LoadingDirective
], ],
}) })
export class ManageProfileComponent implements OnInit { export class ManageProfileComponent implements OnInit {

240
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.html

@ -1,177 +1,113 @@
<ng-container *abpPermission="prop.permission; runChangeDetection: false"> <ng-container *abpPermission="prop.permission; runChangeDetection: false">
@switch (getComponent(prop)) { @switch (getComponent(prop)) {
@case ('template') { @case ('template') {
<ng-container *ngComponentOutlet="prop.template; injector: injectorForCustomComponent" /> <ng-container *ngComponentOutlet="prop.template; injector: injectorForCustomComponent" />
} }
} }
<div [ngClass]="containerClassName" class="mb-2"> <div [class]="containerClassName" class="mb-2">
@switch (getComponent(prop)) { @switch (getComponent(prop)) {
@case ('input') { @case ('input') {
<ng-template [ngTemplateOutlet]="label" /> <ng-template [ngTemplateOutlet]="label" />
<input <input #field [id]="prop.id" [formControlName]="prop.name" [autocomplete]="prop.autocomplete" [type]="getType(prop)"
#field [abpDisabled]="disabled" [readonly]="readonly" class="form-control" />
[id]="prop.id" }
[formControlName]="prop.name" @case ('hidden') {
[autocomplete]="prop.autocomplete" <input [formControlName]="prop.name" type="hidden" />
[type]="getType(prop)" }
[abpDisabled]="disabled" @case ('checkbox') {
[readonly]="readonly" <div class="form-check" validationTarget>
class="form-control" <input #field [id]="prop.id" [formControlName]="prop.name" [abpDisabled]="disabled" type="checkbox"
/> class="form-check-input" />
} <ng-template [ngTemplateOutlet]="label" [ngTemplateOutletContext]="{ $implicit: 'form-check-label' }" />
@case ('hidden') { </div>
<input [formControlName]="prop.name" type="hidden" /> }
} @case ('select') {
@case ('checkbox') { <ng-template [ngTemplateOutlet]="label" />
<div class="form-check" validationTarget> <select #field [id]="prop.id" [formControlName]="prop.name" [abpDisabled]="disabled"
<input class="form-select form-control">
#field @for (option of options$ | async; track option.value) {
[id]="prop.id" <option [ngValue]="option.value">
[formControlName]="prop.name" @if (prop.isExtra) {
[abpDisabled]="disabled" {{ '::' + option.key | abpLocalization }}
type="checkbox" } @else {
class="form-check-input" {{ option.key }}
/> }
<ng-template </option>
[ngTemplateOutlet]="label"
[ngTemplateOutletContext]="{ $implicit: 'form-check-label' }"
/>
</div>
}
@case ('select') {
<ng-template [ngTemplateOutlet]="label" />
<select
#field
[id]="prop.id"
[formControlName]="prop.name"
[abpDisabled]="disabled"
class="form-select form-control"
>
@for (option of options$ | async; track option.value) {
<option [ngValue]="option.value">
@if (prop.isExtra) {
{{ '::' + option.key | abpLocalization }}
} @else {
{{ option.key }}
}
</option>
}
</select>
}
@case ('multiselect') {
<ng-template [ngTemplateOutlet]="label"></ng-template>
<abp-extensible-form-multi-select
[prop]="prop"
[options]="options$ | async"
[formControlName]="prop.name"
[abpDisabled]="disabled"
/>
}
@case ('typeahead') {
<ng-template [ngTemplateOutlet]="label" />
<div #typeahead class="position-relative" validationStyle validationTarget>
<input
#field
[id]="prop.id"
[autocomplete]="prop.autocomplete"
[abpDisabled]="disabled"
[ngbTypeahead]="search"
[editable]="false"
[inputFormatter]="typeaheadFormatter"
[resultFormatter]="typeaheadFormatter"
[ngModelOptions]="{ standalone: true }"
[(ngModel)]="typeaheadModel"
(selectItem)="setTypeaheadValue($event.item)"
(blur)="setTypeaheadValue(typeaheadModel)"
[class.is-invalid]="typeahead.classList.contains('is-invalid')"
class="form-control"
/>
<input [formControlName]="prop.name" type="hidden" />
</div>
}
@case ('date') {
<ng-template [ngTemplateOutlet]="label" />
<input
[id]="prop.id"
[formControlName]="prop.name"
(click)="datepicker.open()"
(keyup.space)="datepicker.open()"
ngbDatepicker
#datepicker="ngbDatepicker"
type="text"
class="form-control"
/>
}
@case ('time') {
<ng-template [ngTemplateOutlet]="label" />
<ngb-timepicker [formControlName]="prop.name" />
}
@case ('dateTime') {
<ng-template [ngTemplateOutlet]="label" />
<abp-extensible-date-time-picker [prop]="prop" [meridian]="meridian$ | async" />
}
@case ('textarea') {
<ng-template [ngTemplateOutlet]="label" />
<textarea
#field
[id]="prop.id"
[formControlName]="prop.name"
[abpDisabled]="disabled"
[readonly]="readonly"
class="form-control"
></textarea>
} }
@case ('passwordinputgroup') { </select>
<ng-template [ngTemplateOutlet]="label" /> }
<div class="input-group form-group" validationTarget> @case ('multiselect') {
<input <ng-template [ngTemplateOutlet]="label"></ng-template>
class="form-control" <abp-extensible-form-multi-select [prop]="prop" [options]="options$ | async" [formControlName]="prop.name"
[id]="prop.id" [abpDisabled]="disabled" />
[formControlName]="prop.name" }
[abpShowPassword]="showPassword" @case ('typeahead') {
/> <ng-template [ngTemplateOutlet]="label" />
<button class="btn btn-secondary" type="button" (click)="showPassword = !showPassword"> <div #typeahead class="position-relative" validationStyle validationTarget>
<i <input #field [id]="prop.id" [autocomplete]="prop.autocomplete" [abpDisabled]="disabled" [ngbTypeahead]="search"
class="fa" [editable]="false" [inputFormatter]="typeaheadFormatter" [resultFormatter]="typeaheadFormatter"
aria-hidden="true" [ngModelOptions]="{ standalone: true }" [(ngModel)]="typeaheadModel"
[ngClass]="{ (selectItem)="setTypeaheadValue($event.item)" (blur)="setTypeaheadValue(typeaheadModel)"
[class.is-invalid]="typeahead.classList.contains('is-invalid')" class="form-control" />
<input [formControlName]="prop.name" type="hidden" />
</div>
}
@case ('date') {
<ng-template [ngTemplateOutlet]="label" />
<input [id]="prop.id" [formControlName]="prop.name" (click)="datepicker.open()" (keyup.space)="datepicker.open()"
ngbDatepicker #datepicker="ngbDatepicker" type="text" class="form-control" />
}
@case ('time') {
<ng-template [ngTemplateOutlet]="label" />
<ngb-timepicker [formControlName]="prop.name" />
}
@case ('dateTime') {
<ng-template [ngTemplateOutlet]="label" />
<abp-extensible-date-time-picker [prop]="prop" [meridian]="meridian$ | async" />
}
@case ('textarea') {
<ng-template [ngTemplateOutlet]="label" />
<textarea #field [id]="prop.id" [formControlName]="prop.name" [abpDisabled]="disabled" [readonly]="readonly"
class="form-control"></textarea>
}
@case ('passwordinputgroup') {
<ng-template [ngTemplateOutlet]="label" />
<div class="input-group form-group" validationTarget>
<input class="form-control" [id]="prop.id" [formControlName]="prop.name" [abpShowPassword]="showPassword" />
<button class="btn btn-secondary" type="button" (click)="showPassword = !showPassword">
<i class="fa" aria-hidden="true" [class]="{
'fa-eye-slash': !showPassword, 'fa-eye-slash': !showPassword,
'fa-eye': showPassword, 'fa-eye': showPassword,
}" }"></i>
></i> </button>
</button> </div>
</div> }
}
} }
@if (prop.formText) { @if (prop.formText) {
<small class="text-muted d-block">{{ prop.formText | abpLocalization }}</small> <small class="text-muted d-block">{{ prop.formText | abpLocalization }}</small>
} }
</div> </div>
</ng-container> </ng-container>
<ng-template #label let-classes> <ng-template #label let-classes>
<label [htmlFor]="prop.id" [ngClass]="classes || 'form-label d-inline-block'"> <label [htmlFor]="prop.id" [class]="classes || 'form-label d-inline-block'">
<span class="d-inline-flex align-items-center gap-1 text-nowrap"> <span class="d-inline-flex align-items-center gap-1 text-nowrap">
@if (prop.displayTextResolver) { @if (prop.displayTextResolver) {
{{ prop.displayTextResolver(data) | abpLocalization }} {{ prop.displayTextResolver(data) | abpLocalization }}
} @else { } @else {
@if (prop.isExtra) { @if (prop.isExtra) {
{{ '::' + prop.displayName | abpLocalization }} {{ '::' + prop.displayName | abpLocalization }}
} @else { } @else {
{{ prop.displayName | abpLocalization }} {{ prop.displayName | abpLocalization }}
} }
} }
{{ asterisk }} {{ asterisk }}
@if (prop.tooltip) { @if (prop.tooltip) {
<i <i [ngbTooltip]="prop.tooltip.text | abpLocalization" [placement]="prop.tooltip.placement || 'auto'"
[ngbTooltip]="prop.tooltip.text | abpLocalization" container="body" class="bi bi-info-circle"></i>
[placement]="prop.tooltip.placement || 'auto'"
container="body"
class="bi bi-info-circle"
></i>
} }
</span> </span>
</label> </label>
</ng-template> </ng-template>

7
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form-prop.component.ts

@ -49,7 +49,7 @@ import { eExtensibleComponents } from '../../enums/components';
import { ExtensibleDateTimePickerComponent } from '../date-time-picker/extensible-date-time-picker.component'; import { ExtensibleDateTimePickerComponent } from '../date-time-picker/extensible-date-time-picker.component';
import { NgxValidateCoreModule } from '@ngx-validate/core'; import { NgxValidateCoreModule } from '@ngx-validate/core';
import { ExtensibleFormPropService } from '../../services/extensible-form-prop.service'; import { ExtensibleFormPropService } from '../../services/extensible-form-prop.service';
import { AsyncPipe, NgClass, NgComponentOutlet, NgTemplateOutlet } from '@angular/common'; import { AsyncPipe, NgComponentOutlet, NgTemplateOutlet } from '@angular/common';
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
import { ExtensibleFormMultiselectComponent } from '../multi-select/extensible-form-multiselect.component'; import { ExtensibleFormMultiselectComponent } from '../multi-select/extensible-form-multiselect.component';
@ -70,11 +70,10 @@ import { ExtensibleFormMultiselectComponent } from '../multi-select/extensible-f
PermissionDirective, PermissionDirective,
LocalizationPipe, LocalizationPipe,
AsyncPipe, AsyncPipe,
NgClass,
NgComponentOutlet, NgComponentOutlet,
NgTemplateOutlet, NgTemplateOutlet,
FormsModule, FormsModule
], ],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ExtensibleFormPropService], providers: [ExtensibleFormPropService],
viewProviders: [ viewProviders: [

65
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.html

@ -1,46 +1,35 @@
@if (form) { @if (form) {
@for (groupedProp of groupedPropList.items; track i; let i = $index; let first = $first) { @for (groupedProp of groupedPropList.items; track i; let i = $index; let first = $first) {
<ng-container *abpPropData="let data; fromList: groupedProp.formPropList; withRecord: record"> <ng-container *abpPropData="let data; fromList: groupedProp.formPropList; withRecord: record">
@if (isAnyGroupMemberVisible(i, data) && groupedProp.group?.className) { @if (isAnyGroupMemberVisible(i, data) && groupedProp.group?.className) {
<div <div [class]="groupedProp.group?.className"
[ngClass]="groupedProp.group?.className" [attr.data-name]="groupedProp.group?.name || groupedProp.group?.className">
[attr.data-name]="groupedProp.group?.name || groupedProp.group?.className" <ng-container [ngTemplateOutlet]="propListTemplate"
> [ngTemplateOutletContext]="{ groupedProp: groupedProp, data: data, isFirstGroup: first}">
<ng-container
[ngTemplateOutlet]="propListTemplate"
[ngTemplateOutletContext]="{ groupedProp: groupedProp, data: data, isFirstGroup: first}"
>
</ng-container>
</div>
} @else {
<ng-container
[ngTemplateOutlet]="propListTemplate"
[ngTemplateOutletContext]="{ groupedProp: groupedProp, data: data, isFirstGroup: first }"
>
</ng-container>
}
</ng-container> </ng-container>
</div>
} @else {
<ng-container [ngTemplateOutlet]="propListTemplate"
[ngTemplateOutletContext]="{ groupedProp: groupedProp, data: data, isFirstGroup: first }">
</ng-container>
} }
</ng-container>
}
} }
<ng-template let-groupedProp="groupedProp" let-data="data" let-isFirstGroup="isFirstGroup" #propListTemplate> <ng-template let-groupedProp="groupedProp" let-data="data" let-isFirstGroup="isFirstGroup" #propListTemplate>
@for (prop of groupedProp.formPropList; let index = $index; let first = $first; track prop.name) { @for (prop of groupedProp.formPropList; let index = $index; let first = $first; track prop.name) {
@if (prop.visible(data)) { @if (prop.visible(data)) {
@if (extraProperties.controls[prop.name]) { @if (extraProperties.controls[prop.name]) {
<ng-container [formGroupName]="extraPropertiesKey"> <ng-container [formGroupName]="extraPropertiesKey">
<abp-extensible-form-prop [prop]="prop" [data]="data" [class]="prop.className" /> <abp-extensible-form-prop [prop]="prop" [data]="data" [class]="prop.className" />
</ng-container> </ng-container>
} @else { } @else {
@if (form.get(prop.name)) { @if (form.get(prop.name)) {
<abp-extensible-form-prop <abp-extensible-form-prop [class]="prop.className" [prop]="prop" [data]="data" [first]="first"
[class]="prop.className" [isFirstGroup]="isFirstGroup" />
[prop]="prop" }
[data]="data" }
[first]="first" }
[isFirstGroup]="isFirstGroup"
/>
}
}
}
} }
</ng-template> </ng-template>

4
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-form/extensible-form.component.ts

@ -17,14 +17,14 @@ import { ExtensionsService } from '../../services/extensions.service';
import { EXTENSIONS_IDENTIFIER } from '../../tokens/extensions.token'; import { EXTENSIONS_IDENTIFIER } from '../../tokens/extensions.token';
import { selfFactory } from '../../utils/factory.util'; import { selfFactory } from '../../utils/factory.util';
import { ExtensibleFormPropComponent } from './extensible-form-prop.component'; import { ExtensibleFormPropComponent } from './extensible-form-prop.component';
import { NgClass, NgTemplateOutlet } from '@angular/common'; import { NgTemplateOutlet } from '@angular/common';
import { PropDataDirective } from '../../directives/prop-data.directive'; import { PropDataDirective } from '../../directives/prop-data.directive';
@Component({ @Component({
exportAs: 'abpExtensibleForm', exportAs: 'abpExtensibleForm',
selector: 'abp-extensible-form', selector: 'abp-extensible-form',
templateUrl: './extensible-form.component.html', templateUrl: './extensible-form.component.html',
imports: [NgClass, NgTemplateOutlet, PropDataDirective, ReactiveFormsModule, ExtensibleFormPropComponent], imports: [NgTemplateOutlet, PropDataDirective, ReactiveFormsModule, ExtensibleFormPropComponent],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
viewProviders: [ viewProviders: [
{ {

4
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html

@ -94,7 +94,7 @@
: ('::' + (row['_' + prop.name]?.value | async | abpUtcToLocal:prop.type) | abpLocalization) : ('::' + (row['_' + prop.name]?.value | async | abpUtcToLocal:prop.type) | abpLocalization)
" (click)=" " (click)="
prop.action && prop.action({ getInjected: getInjected, record: row, index: i }) prop.action && prop.action({ getInjected: getInjected, record: row, index: i })
" [ngClass]="entityPropTypeClasses[prop.type]" [class.pointer]="prop.action"></div> " [class]="entityPropTypeClasses[prop.type]" [class.pointer]="prop.action"></div>
} @else { } @else {
<div [innerHTML]=" <div [innerHTML]="
!prop.isExtra !prop.isExtra
@ -102,7 +102,7 @@
: ('::' + (row['_' + prop.name]?.value | async) | abpLocalization) : ('::' + (row['_' + prop.name]?.value | async) | abpLocalization)
" (click)=" " (click)="
prop.action && prop.action({ getInjected: getInjected, record: row, index: i }) prop.action && prop.action({ getInjected: getInjected, record: row, index: i })
" [ngClass]="entityPropTypeClasses[prop.type]" [class.pointer]="prop.action"></div> " [class]="entityPropTypeClasses[prop.type]" [class.pointer]="prop.action"></div>
} }
} @else { } @else {
<ng-container *ngComponentOutlet=" <ng-container *ngComponentOutlet="

103
npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.html

@ -1,88 +1,55 @@
@if (actionList.length > 1) { @if (actionList.length > 1) {
<div ngbDropdown container="body" class="d-inline-block"> <div ngbDropdown container="body" class="d-inline-block">
<button <button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" ngbDropdownToggle>
class="btn btn-primary btn-sm dropdown-toggle" <i [class]="icon" [class.me-1]="icon"></i>{{ text | abpLocalization }}
data-toggle="dropdown" </button>
aria-haspopup="true" <div ngbDropdownMenu>
ngbDropdownToggle @for (action of actionList; track action.text) {
> <ng-container [ngTemplateOutlet]="dropDownBtnItemTmp" [ngTemplateOutletContext]="{ $implicit: action }">
<i [ngClass]="icon" [class.me-1]="icon"></i>{{ text | abpLocalization }} </ng-container>
</button> }
<div ngbDropdownMenu>
@for (action of actionList; track action.text) {
<ng-container
[ngTemplateOutlet]="dropDownBtnItemTmp"
[ngTemplateOutletContext]="{ $implicit: action }"
>
</ng-container>
}
</div>
</div> </div>
</div>
} }
@if (actionList.length === 1) { @if (actionList.length === 1) {
<ng-container <ng-container [ngTemplateOutlet]="btnTmp"
[ngTemplateOutlet]="btnTmp" [ngTemplateOutletContext]="{ $implicit: actionList.get(0).value }"></ng-container>
[ngTemplateOutletContext]="{ $implicit: actionList.get(0).value }"
></ng-container>
} }
<ng-template #dropDownBtnItemTmp let-action> <ng-template #dropDownBtnItemTmp let-action>
@if (action.visible(data)) { @if (action.visible(data)) {
<button <button ngbDropdownItem *abpPermission="action.permission; runChangeDetection: false" (click)="action.action(data)"
ngbDropdownItem type="button">
*abpPermission="action.permission; runChangeDetection: false" <ng-container *ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"></ng-container>
(click)="action.action(data)" </button>
type="button"
>
<ng-container
*ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"
></ng-container>
</button>
} }
</ng-template> </ng-template>
<ng-template #buttonContentTmp let-action> <ng-template #buttonContentTmp let-action>
<i [ngClass]="action.icon" [class.me-1]="action.icon && !action.showOnlyIcon"></i> <i [class]="action.icon" [class.me-1]="action.icon && !action.showOnlyIcon"></i>
@if (!action.showOnlyIcon) { @if (!action.showOnlyIcon) {
@if (action.icon) { @if (action.icon) {
<span>{{ action.text | abpLocalization }}</span> <span>{{ action.text | abpLocalization }}</span>
} @else { } @else {
<div abpEllipsis>{{ action.text | abpLocalization }}</div> <div abpEllipsis>{{ action.text | abpLocalization }}</div>
} }
} }
</ng-template> </ng-template>
<ng-template #btnTmp let-action> <ng-template #btnTmp let-action>
@if (action.visible(data)) { @if (action.visible(data)) {
@if (action.tooltip) { @if (action.tooltip) {
<button <button *abpPermission="action.permission; runChangeDetection: false" (click)="action.action(data)" type="button"
*abpPermission="action.permission; runChangeDetection: false" [class]="action.btnClass" [style]="action.btnStyle" [ngbTooltip]="action.tooltip.text | abpLocalization"
(click)="action.action(data)" [placement]="action.tooltip.placement || 'auto'" triggers="hover" container="body">
type="button" <ng-container *ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"></ng-container>
[class]="action.btnClass" </button>
[style]="action.btnStyle" } @else {
[ngbTooltip]="action.tooltip.text | abpLocalization" <button *abpPermission="action.permission; runChangeDetection: false" (click)="action.action(data)" type="button"
[placement]="action.tooltip.placement || 'auto'" [class]="action.btnClass" [style]="action.btnStyle">
triggers="hover" <ng-container *ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"></ng-container>
container="body" </button>
>
<ng-container
*ngTemplateOutlet="buttonContentTmp; context: { $implicit: action }"
></ng-container>
</button>
} @else {
<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> }
</ng-template>

13
npm/ng-packs/packages/components/extensible/src/lib/components/grid-actions/grid-actions.component.ts

@ -1,8 +1,8 @@
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
Input, Input,
TrackByFunction, TrackByFunction,
} from '@angular/core'; } from '@angular/core';
import { EntityAction, EntityActionList } from '../../models/entity-actions'; import { EntityAction, EntityActionList } from '../../models/entity-actions';
import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token'; import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token';
@ -10,7 +10,7 @@ import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.c
import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { LocalizationPipe, PermissionDirective } from '@abp/ng.core'; import { LocalizationPipe, PermissionDirective } from '@abp/ng.core';
import { EllipsisDirective } from '@abp/ng.theme.shared'; import { EllipsisDirective } from '@abp/ng.theme.shared';
import { NgClass, NgTemplateOutlet } from '@angular/common'; import { NgTemplateOutlet } from '@angular/common';
@Component({ @Component({
exportAs: 'abpGridActions', exportAs: 'abpGridActions',
@ -18,7 +18,6 @@ import { NgClass, NgTemplateOutlet } from '@angular/common';
NgbDropdownModule, NgbDropdownModule,
EllipsisDirective, EllipsisDirective,
PermissionDirective, PermissionDirective,
NgClass,
LocalizationPipe, LocalizationPipe,
NgTemplateOutlet, NgTemplateOutlet,
NgbTooltipModule, NgbTooltipModule,

26
npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.html

@ -4,26 +4,20 @@
@if (action.visible(data)) { @if (action.visible(data)) {
<ng-container *abpPermission="action.permission; runChangeDetection: false"> <ng-container *abpPermission="action.permission; runChangeDetection: false">
@if (action.component; as component) { @if (action.component; as component) {
<ng-container <ng-container *ngComponentOutlet="component; injector: record | createInjector: action:this"></ng-container>
*ngComponentOutlet="component; injector: record | createInjector: action:this"
></ng-container>
}@else { }@else {
@if (asToolbarAction(action).value; as toolbarAction ) { @if (asToolbarAction(action).value; as toolbarAction ) {
<button <button (click)="action.action(data)" type="button"
(click)="action.action(data)" [class]="toolbarAction?.btnClass ? toolbarAction?.btnClass : defaultBtnClass"
type="button" class="d-inline-flex align-items-center gap-1">
[ngClass]="toolbarAction?.btnClass ? toolbarAction?.btnClass : defaultBtnClass" <i [class]="toolbarAction?.icon" [class.me-1]="toolbarAction?.icon"></i>
class="d-inline-flex align-items-center gap-1" {{ toolbarAction?.text | abpLocalization }}
> </button>
<i [ngClass]="toolbarAction?.icon" [class.me-1]="toolbarAction?.icon"></i> }
{{ toolbarAction?.text | abpLocalization }}
</button>
}
} }
</ng-container> </ng-container>
} }
</div> </div>
} }
</div> </div>

8
npm/ng-packs/packages/components/extensible/src/lib/components/page-toolbar/page-toolbar.component.ts

@ -10,7 +10,7 @@ import { EXTENSIONS_ACTION_TYPE } from '../../tokens/extensions.token';
import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component'; import { AbstractActionsComponent } from '../abstract-actions/abstract-actions.component';
import { CreateInjectorPipe } from '../../pipes/create-injector.pipe'; import { CreateInjectorPipe } from '../../pipes/create-injector.pipe';
import { LocalizationPipe, PermissionDirective } from '@abp/ng.core'; import { LocalizationPipe, PermissionDirective } from '@abp/ng.core';
import { NgClass, NgComponentOutlet } from '@angular/common'; import { NgComponentOutlet } from '@angular/common';
@Component({ @Component({
exportAs: 'abpPageToolbar', exportAs: 'abpPageToolbar',
@ -19,7 +19,6 @@ import { NgClass, NgComponentOutlet } from '@angular/common';
CreateInjectorPipe, CreateInjectorPipe,
PermissionDirective, PermissionDirective,
LocalizationPipe, LocalizationPipe,
NgClass,
NgComponentOutlet, NgComponentOutlet,
], ],
templateUrl: './page-toolbar.component.html', templateUrl: './page-toolbar.component.html',
@ -33,8 +32,7 @@ import { NgClass, NgComponentOutlet } from '@angular/common';
}) })
export class PageToolbarComponent<R = any> export class PageToolbarComponent<R = any>
extends AbstractActionsComponent<ToolbarActionList<R>> extends AbstractActionsComponent<ToolbarActionList<R>>
implements HasCreateInjectorPipe<R> implements HasCreateInjectorPipe<R> {
{
readonly injector: Injector; readonly injector: Injector;
defaultBtnClass = 'btn btn-sm btn-primary'; defaultBtnClass = 'btn btn-sm btn-primary';
@ -48,7 +46,7 @@ export class PageToolbarComponent<R = any>
const injector = inject(Injector); const injector = inject(Injector);
super(); super();
this.injector = injector; this.injector = injector;
} }

4
npm/ng-packs/packages/components/lookup/src/lib/lookup-search.component.ts

@ -12,7 +12,7 @@ import {
inject, inject,
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CommonModule } from '@angular/common'; import { NgTemplateOutlet } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { LocalizationPipe } from '@abp/ng.core'; import { LocalizationPipe } from '@abp/ng.core';
import { Subject, Observable, debounceTime, distinctUntilChanged, of, finalize } from 'rxjs'; import { Subject, Observable, debounceTime, distinctUntilChanged, of, finalize } from 'rxjs';
@ -29,7 +29,7 @@ export type LookupSearchFn<T = LookupItem> = (filter: string) => Observable<T[]>
selector: 'abp-lookup-search', selector: 'abp-lookup-search',
templateUrl: './lookup-search.component.html', templateUrl: './lookup-search.component.html',
styleUrl: './lookup-search.component.scss', styleUrl: './lookup-search.component.scss',
imports: [CommonModule, FormsModule, LocalizationPipe], imports: [FormsModule, LocalizationPipe, NgTemplateOutlet],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class LookupSearchComponent<T extends LookupItem = LookupItem> implements OnInit { export class LookupSearchComponent<T extends LookupItem = LookupItem> implements OnInit {

218
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html

@ -1,13 +1,13 @@
@if (visible) { @if (visible) {
<abp-modal [(visible)]="visible" [busy]="modalBusy" [options]="{ size: 'lg' }"> <abp-modal [(visible)]="visible" [busy]="modalBusy" [options]="{ size: 'lg' }">
<ng-template #abpHeader> <ng-template #abpHeader>
<h3> <h3>
{{ 'AbpFeatureManagement::Features' | abpLocalization }} {{ 'AbpFeatureManagement::Features' | abpLocalization }}
@if (providerTitle) { @if (providerTitle) {
- {{ providerTitle }} - {{ providerTitle }}
} }
</h3> </h3>
</ng-template> </ng-template>
<ng-template #abpBody> <ng-template #abpBody>
<div class="row"> <div class="row">
@ -35,93 +35,72 @@
<h4>{{ selectedGroupDisplayName }}</h4> <h4>{{ selectedGroupDisplayName }}</h4>
<hr class="mt-2 mb-3" /> <hr class="mt-2 mb-3" />
@for (feature of features[group.name]; track feature.id || i; let i = $index) { @for (feature of features[group.name]; track feature.id || i; let i = $index) {
@let provider = feature.provider.name; @let provider = feature.provider.name;
@let isFeatureDisabled = !feature.parentName ? isParentDisabled(feature.name, group.name, provider) : @let isFeatureDisabled = !feature.parentName ? isParentDisabled(feature.name, group.name, provider) :
(provider !== providerName && provider !== defaultProviderName); (provider !== providerName && provider !== defaultProviderName);
<div class="mt-2" [ngStyle]="feature.style" (keyup.enter)="save()"> <div class="mt-2" [style]="feature.style" (keyup.enter)="save()">
@switch (feature.valueType?.name) { @switch (feature.valueType?.name) {
@case (valueTypes.ToggleStringValueType) { @case (valueTypes.ToggleStringValueType) {
<div class="form-check" [class.px-4]="!!feature.parentName"> <div class="form-check" [class.px-4]="!!feature.parentName">
<input <input class="form-check-input" type="checkbox" [id]="feature.name" [(ngModel)]="feature.value"
class="form-check-input" (ngModelChange)="onCheckboxClick($event, feature)" [disabled]="isFeatureDisabled" />
type="checkbox"
[id]="feature.name"
[(ngModel)]="feature.value"
(ngModelChange)="onCheckboxClick($event, feature)"
[disabled]="isFeatureDisabled"
/>
<label class="form-check-label" [htmlFor]="feature.name"> <label class="form-check-label" [htmlFor]="feature.name">
{{ feature.displayName }} {{ feature.displayName }}
@if (isFeatureDisabled) { @if (isFeatureDisabled) {
<span>({{ provider }})</span> <span>({{ provider }})</span>
} }
</label> </label>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
descTmp; descTmp;
context: { $implicit: feature.description } context: { $implicit: feature.description }
" "></ng-container>
></ng-container> </div>
</div> }
} @case (valueTypes.FreeTextStringValueType) {
@case (valueTypes.FreeTextStringValueType) { <div class="mb-3 form-group" [class.px-2]="!!feature.parentName">
<div class="mb-3 form-group" [class.px-2]="!!feature.parentName"> <label [htmlFor]="feature.name" class="form-label">
<label [htmlFor]="feature.name" class="form-label"> {{ feature.displayName }}
{{ feature.displayName }} @if (isFeatureDisabled) {
@if (isFeatureDisabled) { <span>({{ provider }})</span>
<span>({{ provider }})</span> }
} </label>
</label> <input class="form-control" type="text" [id]="feature.name" [(ngModel)]="feature.value"
<input [abpFeatureManagementFreeText]="feature" [disabled]="isFeatureDisabled" />
class="form-control"
type="text"
[id]="feature.name"
[(ngModel)]="feature.value"
[abpFeatureManagementFreeText]="feature"
[disabled]="isFeatureDisabled"
/>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
descTmp; descTmp;
context: { $implicit: feature.description } context: { $implicit: feature.description }
" "></ng-container>
></ng-container> </div>
</div> }
} @case (valueTypes.SelectionStringValueType) {
@case (valueTypes.SelectionStringValueType) { @if (feature.valueType.itemSource?.items?.length) {
@if (feature.valueType.itemSource?.items?.length) { <div class="mb-3 form-group" [class.px-2]="!!feature.parentName">
<div class="mb-3 form-group" [class.px-2]="!!feature.parentName"> <label [htmlFor]="feature.name" class="form-label">
<label [htmlFor]="feature.name" class="form-label"> {{ feature.displayName }}
{{ feature.displayName }} @if (isFeatureDisabled) {
@if (isFeatureDisabled) { <span>({{ provider }})</span>
<span>({{ provider }})</span> }
} </label>
</label> <select class="form-select" [id]="feature.name" [(ngModel)]="feature.value"
<select [disabled]="isFeatureDisabled">
class="form-select" @for (
[id]="feature.name" item of feature.valueType.itemSource?.items;
[(ngModel)]="feature.value" track item.value
[disabled]="isFeatureDisabled" ) {
> <option [ngValue]="item.value">
@for ( {{
item of feature.valueType.itemSource?.items; item.displayText?.resourceName +
track item.value '::' +
) { item.displayText?.name | abpLocalization
<option [ngValue]="item.value"> }}
{{ </option>
item.displayText?.resourceName + }
'::' + </select>
item.displayText?.name | abpLocalization <ng-container *ngTemplateOutlet="
}}
</option>
}
</select>
<ng-container
*ngTemplateOutlet="
descTmp; descTmp;
context: { $implicit: feature.description } context: { $implicit: feature.description }
" "
@ -148,34 +127,43 @@
</div> </div>
} }
</div> </div>
</ng-template>
<ng-template #abpFooter> <ng-template #descTmp let-description>
<button abpClose type="button" class="btn btn-link"> @if (description) {
{{ 'AbpFeatureManagement::Cancel' | abpLocalization }} <small class="d-block form-text text-muted">{{ description }}</small>
</button> }
</ng-template>
@if (groups.length) { <div class="col-md-8">
<abp-button <div class="py-0" [ngbNavOutlet]="nav"></div>
buttonClass="btn btn-outline-primary" </div>
[disabled]="modalBusy"
(click)="resetToDefault()"
aria-hidden="true"
>
{{ 'AbpFeatureManagement::ResetToDefault' | abpLocalization }}
</abp-button>
} }
@if (groups.length) { @if (!groups.length) {
<abp-button <div class="col">
iconClass="fa fa-check" {{ 'AbpFeatureManagement::NoFeatureFoundMessage' | abpLocalization }}
[disabled]="modalBusy" </div>
(click)="save()"
aria-hidden="true"
>
{{ 'AbpFeatureManagement::Save' | abpLocalization }}
</abp-button>
} }
</ng-template> </div>
</abp-modal> </ng-template>
}
<ng-template #abpFooter>
<button abpClose type="button" class="btn btn-link">
{{ 'AbpFeatureManagement::Cancel' | abpLocalization }}
</button>
@if (groups.length) {
<abp-button buttonClass="btn btn-outline-primary" [disabled]="modalBusy" (click)="resetToDefault()"
aria-hidden="true">
{{ 'AbpFeatureManagement::ResetToDefault' | abpLocalization }}
</abp-button>
}
@if (groups.length) {
<abp-button iconClass="fa fa-check" [disabled]="modalBusy" (click)="save()" aria-hidden="true">
{{ 'AbpFeatureManagement::Save' | abpLocalization }}
</abp-button>
}
</ng-template>
</abp-modal>
}

3
npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts

@ -31,7 +31,7 @@ import {
import { concat, of } from 'rxjs'; import { concat, of } from 'rxjs';
import { finalize, switchMap, take, tap } from 'rxjs/operators'; import { finalize, switchMap, take, tap } from 'rxjs/operators';
import { PermissionManagement } from '../models'; import { PermissionManagement } from '../models';
import { NgStyle } from '@angular/common';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs'; import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
@ -97,7 +97,6 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
], ],
imports: [ imports: [
FormsModule, FormsModule,
NgStyle,
ModalComponent, ModalComponent,
LocalizationPipe, LocalizationPipe,
ButtonComponent, ButtonComponent,

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

@ -25,7 +25,7 @@ import {
PermissionDirective PermissionDirective
} from '@abp/ng.core'; } from '@abp/ng.core';
import { NgxValidateCoreModule } from '@ngx-validate/core'; import { NgxValidateCoreModule } from '@ngx-validate/core';
import { CommonModule } from '@angular/common';
const { required, email } = Validators; const { required, email } = Validators;
@ -35,14 +35,13 @@ const { required, email } = Validators;
animations: [collapse], animations: [collapse],
imports: [ imports: [
ReactiveFormsModule, ReactiveFormsModule,
CommonModule,
LocalizationPipe, LocalizationPipe,
ButtonComponent, ButtonComponent,
ModalComponent, ModalComponent,
ModalCloseDirective, ModalCloseDirective,
NgxValidateCoreModule, NgxValidateCoreModule,
PermissionDirective, PermissionDirective
], ],
}) })
export class EmailSettingGroupComponent implements OnInit { export class EmailSettingGroupComponent implements OnInit {
private emailSettingsService = inject(EmailSettingsService); private emailSettingsService = inject(EmailSettingsService);

36
npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.html

@ -1,26 +1,12 @@
@for (alert of service.alerts$ | async; track i; let i = $index) { @for (alert of service.alerts$ | async; track i; let i = $index) {
<div <div class="alert alert-{{ alert.type }} fade show" [class.alert-dismissible]="alert.dismissible" role="alert">
class="alert alert-{{ alert.type }} fade show" @if (alert.title) {
[ngClass]="{ 'alert-dismissible fade show': alert.dismissible }" <h4 class="alert-heading" [innerHTML]="alert.title | abpSafeHtml | abpLocalization: alert.titleLocalizationParams">
role="alert" </h4>
> }
@if (alert.title) { <span [innerHTML]="alert.message | abpSafeHtml | abpLocalization: alert.messageLocalizationParams"></span>
<h4 @if (alert.dismissible) {
class="alert-heading" <button type="button" class="btn-close" data-dismiss="alert" aria-label="Close" (click)="service.remove(i)"></button>
[innerHTML]="alert.title | abpSafeHtml | abpLocalization: alert.titleLocalizationParams" }
></h4> </div>
} }
<span
[innerHTML]="alert.message | abpSafeHtml | abpLocalization: alert.messageLocalizationParams"
></span>
@if (alert.dismissible) {
<button
type="button"
class="btn-close"
data-dismiss="alert"
aria-label="Close"
(click)="service.remove(i)"
></button>
}
</div>
}

4
npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.ts

@ -1,13 +1,13 @@
import { Component, ViewEncapsulation, inject } from '@angular/core'; import { Component, ViewEncapsulation, inject } from '@angular/core';
import { PageAlertService } from '@abp/ng.theme.shared'; import { PageAlertService } from '@abp/ng.theme.shared';
import { NgClass, AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { LocalizationPipe, SafeHtmlPipe } from '@abp/ng.core'; import { LocalizationPipe, SafeHtmlPipe } from '@abp/ng.core';
@Component({ @Component({
selector: 'abp-page-alert-container', selector: 'abp-page-alert-container',
templateUrl: './page-alert-container.component.html', templateUrl: './page-alert-container.component.html',
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
imports: [NgClass, AsyncPipe, LocalizationPipe, SafeHtmlPipe], imports: [AsyncPipe, LocalizationPipe, SafeHtmlPipe],
}) })
export class PageAlertContainerComponent { export class PageAlertContainerComponent {
service = inject(PageAlertService); service = inject(PageAlertService);

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

@ -1,16 +1,14 @@
<ul class="navbar-nav"> <ul class="navbar-nav">
@for (route of routesService.visible$ | async; track $index) { @for (route of routesService.visible$ | async; track $index) {
<ng-container <ng-container [ngTemplateOutlet]="isDropdown(route) ? dropdownLink : defaultLink"
[ngTemplateOutlet]="isDropdown(route) ? dropdownLink : defaultLink" [ngTemplateOutletContext]="{ $implicit: route }" />
[ngTemplateOutletContext]="{ $implicit: route }"
/>
} }
<ng-template #defaultLink let-route> <ng-template #defaultLink let-route>
<li class="nav-item" *abpPermission="route.requiredPolicy"> <li class="nav-item" *abpPermission="route.requiredPolicy">
<a class="nav-link" [routerLink]="[route.path]"> <a class="nav-link" [routerLink]="[route.path]">
@if (route.iconClass) { @if (route.iconClass) {
<i [ngClass]="route.iconClass"></i> <i [class]="route.iconClass"></i>
} }
{{ route.name | abpAsyncLocalization | async }} {{ route.name | abpAsyncLocalization | async }}
</a> </a>
@ -19,91 +17,61 @@
<ng-template #dropdownLink let-route> <ng-template #dropdownLink let-route>
@if (route.children?.length) { @if (route.children?.length) {
<li <li class="nav-item dropdown" display="static" *abpPermission="route.requiredPolicy" (click)="
class="nav-item dropdown"
display="static"
*abpPermission="route.requiredPolicy"
(click)="
rootDropdownExpand[route.name] rootDropdownExpand[route.name]
? (rootDropdownExpand[route.name] = false) ? (rootDropdownExpand[route.name] = false)
: (rootDropdownExpand[route.name] = true) : (rootDropdownExpand[route.name] = true)">
" <a class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
> href="javascript:void(0)">
<a @if (route.iconClass) {
class="nav-link dropdown-toggle" <i [class]="route.iconClass"></i>
data-toggle="dropdown" }
aria-haspopup="true" {{ route.name | abpAsyncLocalization | async }}
aria-expanded="false" </a>
href="javascript:void(0)" <div #routeContainer class="dropdown-menu border-0 shadow-sm"
> (click)="$event.preventDefault(); $event.stopPropagation()"
@if (route.iconClass) { [class.d-block]="smallScreen && rootDropdownExpand[route.name]">
<i [ngClass]="route.iconClass"></i> <ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: route }" />
} </div>
{{ route.name | abpAsyncLocalization | async }} </li>
</a>
<div
#routeContainer
class="dropdown-menu border-0 shadow-sm"
(click)="$event.preventDefault(); $event.stopPropagation()"
[class.d-block]="smallScreen && rootDropdownExpand[route.name]"
>
<ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: route }" />
</div>
</li>
} }
</ng-template> </ng-template>
<ng-template #forTemplate let-route> <ng-template #forTemplate let-route>
@for (child of route.children; track $index) { @for (child of route.children; track $index) {
<ng-template <ng-template [ngTemplateOutlet]="child.children?.length ? dropdownChild : defaultChild"
[ngTemplateOutlet]="child.children?.length ? dropdownChild : defaultChild" [ngTemplateOutletContext]="{ $implicit: child }" />
[ngTemplateOutletContext]="{ $implicit: child }"
/>
} }
</ng-template> </ng-template>
<ng-template #defaultChild let-child> <ng-template #defaultChild let-child>
@if (child.path) { @if (child.path) {
<div class="dropdown-submenu" *abpPermission="child.requiredPolicy"> <div class="dropdown-submenu" *abpPermission="child.requiredPolicy">
<a class="dropdown-item" [routerLink]="[child.path]" (click)="closeDropdown()"> <a class="dropdown-item" [routerLink]="[child.path]" (click)="closeDropdown()">
@if (child.iconClass) { @if (child.iconClass) {
<i [ngClass]="child.iconClass"></i> <i [class]="child.iconClass"></i>
} }
{{ child.name | abpLocalization }}</a {{ child.name | abpLocalization }}</a>
> </div>
</div>
} }
</ng-template> </ng-template>
<ng-template #dropdownChild let-child> <ng-template #dropdownChild let-child>
<div <div class="dropdown-submenu" ngbDropdown #dropdownSubmenu="ngbDropdown" placement="right-top" [autoClose]="true"
class="dropdown-submenu" *abpPermission="child.requiredPolicy">
ngbDropdown
#dropdownSubmenu="ngbDropdown"
placement="right-top"
[autoClose]="true"
*abpPermission="child.requiredPolicy"
>
<div ngbDropdownToggle [class.dropdown-toggle]="false"> <div ngbDropdownToggle [class.dropdown-toggle]="false">
<a <a abpEllipsis="210px" [abpEllipsisEnabled]="!smallScreen" role="button"
abpEllipsis="210px" class="btn d-block text-start dropdown-toggle">
[abpEllipsisEnabled]="!smallScreen"
role="button"
class="btn d-block text-start dropdown-toggle"
>
@if (child.iconClass) { @if (child.iconClass) {
<i [ngClass]="child.iconClass"></i> <i [class]="child.iconClass"></i>
} }
{{ child.name | abpLocalization }} {{ child.name | abpLocalization }}
</a> </a>
</div> </div>
<div <div #childrenContainer class="dropdown-menu dropdown-menu-start border-0 shadow-sm"
#childrenContainer [class.d-block]="smallScreen && dropdownSubmenu.isOpen()">
class="dropdown-menu dropdown-menu-start border-0 shadow-sm"
[class.d-block]="smallScreen && dropdownSubmenu.isOpen()"
>
<ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: child }" /> <ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: child }" />
</div> </div>
</div> </div>
</ng-template> </ng-template>
</ul> </ul>

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

@ -16,7 +16,7 @@ import {
TrackByFunction, TrackByFunction,
ViewChildren, ViewChildren,
} from '@angular/core'; } from '@angular/core';
import { NgTemplateOutlet, NgClass, AsyncPipe } from '@angular/common'; import { NgTemplateOutlet, AsyncPipe } from '@angular/common';
import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { RouterLink } from '@angular/router'; import { RouterLink } from '@angular/router';
import { EllipsisDirective } from '@abp/ng.theme.shared'; import { EllipsisDirective } from '@abp/ng.theme.shared';
@ -26,7 +26,6 @@ import { EllipsisDirective } from '@abp/ng.theme.shared';
templateUrl: 'routes.component.html', templateUrl: 'routes.component.html',
imports: [ imports: [
NgTemplateOutlet, NgTemplateOutlet,
NgClass,
AsyncPipe, AsyncPipe,
RouterLink, RouterLink,
NgbDropdownModule, NgbDropdownModule,

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

@ -10,7 +10,6 @@ import {
ViewChild, ViewChild,
inject, inject,
} from '@angular/core'; } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ABP, StopPropagationDirective } from '@abp/ng.core'; import { ABP, StopPropagationDirective } from '@abp/ng.core';
@Component({ @Component({
@ -21,16 +20,16 @@ import { ABP, StopPropagationDirective } from '@abp/ng.core';
[id]="buttonId" [id]="buttonId"
[attr.type]="buttonType" [attr.type]="buttonType"
[attr.form]="formName" [attr.form]="formName"
[ngClass]="buttonClass" [class]="buttonClass"
[disabled]="loading || disabled" [disabled]="loading || disabled"
(click.stop)="click.next($event); abpClick.next($event)" (click.stop)="click.next($event); abpClick.next($event)"
(focus)="focus.next($event); abpFocus.next($event)" (focus)="focus.next($event); abpFocus.next($event)"
(blur)="blur.next($event); abpBlur.next($event)" (blur)="blur.next($event); abpBlur.next($event)"
> >
<i [ngClass]="icon" class="me-1" aria-hidden="true"></i><ng-content></ng-content> <i [class]="icon" class="me-1" aria-hidden="true"></i><ng-content></ng-content>
</button> </button>
`, `,
imports: [CommonModule, StopPropagationDirective], imports: [StopPropagationDirective],
}) })
export class ButtonComponent implements OnInit { export class ButtonComponent implements OnInit {
private renderer = inject(Renderer2); private renderer = inject(Renderer2);

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

@ -1,12 +1,10 @@
import { Component, HostBinding, Input } from '@angular/core'; import { Component, HostBinding, Input } from '@angular/core';
import { NgClass, NgStyle } from '@angular/common';
@Component({ @Component({
selector: 'abp-card-body', selector: 'abp-card-body',
template: ` <div [ngClass]="cardBodyClass" [ngStyle]="cardBodyStyle"> template: ` <div [class]="cardBodyClass" [style]="cardBodyStyle">
<ng-content></ng-content> <ng-content></ng-content>
</div>`, </div>`,
imports: [NgClass, NgStyle],
}) })
export class CardBodyComponent { export class CardBodyComponent {
@HostBinding('class') componentClass = 'card-body'; @HostBinding('class') componentClass = 'card-body';

5
npm/ng-packs/packages/theme-shared/src/lib/components/card/card-footer.component.ts

@ -1,15 +1,14 @@
import { Component, HostBinding, Input } from '@angular/core'; import { Component, HostBinding, Input } from '@angular/core';
import { NgClass, NgStyle } from '@angular/common';
@Component({ @Component({
selector: 'abp-card-footer', selector: 'abp-card-footer',
template: ` template: `
<div [ngStyle]="cardFooterStyle" [ngClass]="cardFooterClass"> <div [style]="cardFooterStyle" [class]="cardFooterClass">
<ng-content></ng-content> <ng-content></ng-content>
</div> </div>
`, `,
styles: [], styles: [],
imports: [NgClass, NgStyle], imports: [],
}) })
export class CardFooterComponent { export class CardFooterComponent {
@HostBinding('class') componentClass = 'card-footer'; @HostBinding('class') componentClass = 'card-footer';

5
npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.component.ts

@ -1,15 +1,14 @@
import { Component, HostBinding, Input } from '@angular/core'; import { Component, HostBinding, Input } from '@angular/core';
import { NgClass, NgStyle } from '@angular/common';
@Component({ @Component({
selector: 'abp-card-header', selector: 'abp-card-header',
template: ` template: `
<div [ngClass]="cardHeaderClass" [ngStyle]="cardHeaderStyle"> <div [class]="cardHeaderClass" [style]="cardHeaderStyle">
<ng-content></ng-content> <ng-content></ng-content>
</div> </div>
`, `,
styles: [], styles: [],
imports: [NgClass, NgStyle], imports: [],
}) })
export class CardHeaderComponent { export class CardHeaderComponent {
@HostBinding('class') componentClass = 'card-header'; @HostBinding('class') componentClass = 'card-header';

5
npm/ng-packs/packages/theme-shared/src/lib/components/card/card.component.ts

@ -1,12 +1,11 @@
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { NgClass, NgStyle } from '@angular/common';
@Component({ @Component({
selector: 'abp-card', selector: 'abp-card',
template: ` <div class="card" [ngClass]="cardClass" [ngStyle]="cardStyle"> template: ` <div class="card" [class]="cardClass" [style]="cardStyle">
<ng-content></ng-content> <ng-content></ng-content>
</div>`, </div>`,
imports: [NgClass, NgStyle], imports: [],
}) })
export class CardComponent { export class CardComponent {
@Input() cardClass: string; @Input() cardClass: string;

13
npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts

@ -1,6 +1,5 @@
import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core'; import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
import { NgClass, NgStyle } from '@angular/common';
import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core'; import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
@Component({ @Component({
@ -12,13 +11,13 @@ import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
[(ngModel)]="value" [(ngModel)]="value"
[id]="checkboxId" [id]="checkboxId"
[readonly]="checkboxReadonly" [readonly]="checkboxReadonly"
[ngClass]="checkboxClass" [class]="checkboxClass"
[ngStyle]="checkboxStyle" [style]="checkboxStyle"
(blur)="checkboxBlur.next()" (blur)="checkboxBlur.next()"
(focus)="checkboxFocus.next()" (focus)="checkboxFocus.next()"
/> />
@if (label) { @if (label) {
<label [ngClass]="labelClass" [for]="checkboxId"> <label [class]="labelClass" [for]="checkboxId">
{{ label | abpLocalization }} {{ label | abpLocalization }}
</label> </label>
} }
@ -31,7 +30,7 @@ import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
multi: true, multi: true,
}, },
], ],
imports: [NgClass, NgStyle, FormsModule, LocalizationPipe], imports: [FormsModule, LocalizationPipe],
}) })
export class FormCheckboxComponent extends AbstractNgModelComponent { export class FormCheckboxComponent extends AbstractNgModelComponent {
@Input() label?: string; @Input() label?: string;
@ -39,8 +38,8 @@ export class FormCheckboxComponent extends AbstractNgModelComponent {
@Input() checkboxId!: string; @Input() checkboxId!: string;
@Input() checkboxStyle: @Input() checkboxStyle:
| { | {
[klass: string]: any; [klass: string]: any;
} }
| null | null
| undefined; | undefined;
@Input() checkboxClass = 'form-check-input'; @Input() checkboxClass = 'form-check-input';

77
npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.html

@ -1,51 +1,34 @@
@if (confirmation$ | async; as data) { @if (confirmation$ | async; as data) {
<div class="confirmation"> <div class="confirmation">
<div <div class="confirmation-backdrop" (click)="data.options?.dismissible ? close(dismiss) : null"></div>
class="confirmation-backdrop" <div class="confirmation-dialog">
(click)="data.options?.dismissible ? close(dismiss) : null" @if (data.severity || isCustomIconExists(data)) {
></div> <div class="icon-container" [class]="data.severity">
<div class="confirmation-dialog"> @if (isIconTemplateExits(data)) {
@if (data.severity || isCustomIconExists(data)) { <div [outerHTML]="data.options.iconTemplate"></div>
<div class="icon-container" [ngClass]="data.severity"> } @else {
@if (isIconTemplateExits(data)) { <i class="icon" [class]="getIconClass(data)"></i>
<div [outerHTML]="data.options.iconTemplate"></div> }
} @else { </div>
<i class="icon" [ngClass]="getIconClass(data)"></i> }
} <div class="content">
</div> @if (data.title) {
<h1 class="title" [innerHTML]="data.title | abpLocalization: data.options?.titleLocalizationParams"></h1>
}
@if (data.message) {
<p class="message" [innerHTML]="data.message | abpLocalization: data.options?.messageLocalizationParams"></p>
}
</div>
<div class="footer">
@if (!data?.options?.hideCancelBtn) {
<button id="cancel" class="btn btn-outline-primary me-2"
[innerHTML]="data.options?.cancelText || 'AbpUi::Cancel' | abpLocalization" (click)="close(reject)"></button>
}
@if (!data?.options?.hideYesBtn) {
<button id="confirm" class="btn btn-primary" [innerHTML]="data.options?.yesText || 'AbpUi::Yes' | abpLocalization"
(click)="close(confirm)"></button>
} }
<div class="content">
@if (data.title) {
<h1
class="title"
[innerHTML]="data.title | abpLocalization: data.options?.titleLocalizationParams"
></h1>
}
@if (data.message) {
<p
class="message"
[innerHTML]="data.message | abpLocalization: data.options?.messageLocalizationParams"
></p>
}
</div>
<div class="footer">
@if (!data?.options?.hideCancelBtn) {
<button
id="cancel"
class="btn btn-outline-primary me-2"
[innerHTML]="data.options?.cancelText || 'AbpUi::Cancel' | abpLocalization"
(click)="close(reject)"
></button>
}
@if (!data?.options?.hideYesBtn) {
<button
id="confirm"
class="btn btn-primary"
[innerHTML]="data.options?.yesText || 'AbpUi::Yes' | abpLocalization"
(click)="close(confirm)"
></button>
}
</div>
</div> </div>
</div> </div>
} </div>
}

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

@ -1,4 +1,4 @@
import { NgClass, AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { Component, inject } from '@angular/core'; import { Component, inject } from '@angular/core';
import { ReplaySubject } from 'rxjs'; import { ReplaySubject } from 'rxjs';
import { Confirmation } from '../../models/confirmation'; import { Confirmation } from '../../models/confirmation';
@ -9,7 +9,7 @@ import { LocalizationPipe } from '@abp/ng.core';
selector: 'abp-confirmation', selector: 'abp-confirmation',
templateUrl: './confirmation.component.html', templateUrl: './confirmation.component.html',
styleUrls: ['./confirmation.component.scss'], styleUrls: ['./confirmation.component.scss'],
imports: [NgClass, AsyncPipe, LocalizationPipe], imports: [AsyncPipe, LocalizationPipe],
}) })
export class ConfirmationComponent { export class ConfirmationComponent {
private icons = inject<ConfirmationIcons>(CONFIRMATION_ICONS); private icons = inject<ConfirmationIcons>(CONFIRMATION_ICONS);

13
npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts

@ -1,6 +1,5 @@
import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core'; import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NgClass, NgStyle } from '@angular/common';
import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core'; import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
@Component({ @Component({
@ -8,7 +7,7 @@ import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
template: ` template: `
<div class="mb-3"> <div class="mb-3">
@if (label) { @if (label) {
<label [ngClass]="labelClass" [for]="inputId"> <label [class]="labelClass" [for]="inputId">
{{ label | abpLocalization }} {{ label | abpLocalization }}
</label> </label>
} }
@ -17,8 +16,8 @@ import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
[id]="inputId" [id]="inputId"
[placeholder]="inputPlaceholder" [placeholder]="inputPlaceholder"
[readonly]="inputReadonly" [readonly]="inputReadonly"
[ngClass]="inputClass" [class]="inputClass"
[ngStyle]="inputStyle" [style]="inputStyle"
(blur)="formBlur.next()" (blur)="formBlur.next()"
(focus)="formFocus.next()" (focus)="formFocus.next()"
[(ngModel)]="value" [(ngModel)]="value"
@ -32,7 +31,7 @@ import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core';
multi: true, multi: true,
}, },
], ],
imports: [NgClass, NgStyle, LocalizationPipe, FormsModule], imports: [LocalizationPipe, FormsModule],
}) })
export class FormInputComponent extends AbstractNgModelComponent { export class FormInputComponent extends AbstractNgModelComponent {
@Input() inputId!: string; @Input() inputId!: string;
@ -42,8 +41,8 @@ export class FormInputComponent extends AbstractNgModelComponent {
@Input() inputPlaceholder = ''; @Input() inputPlaceholder = '';
@Input() inputStyle: @Input() inputStyle:
| { | {
[klass: string]: any; [klass: string]: any;
} }
| null | null
| undefined; | undefined;
@Input() inputClass = 'form-control'; @Input() inputClass = 'form-control';

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

@ -14,7 +14,7 @@ import {
DestroyRef, DestroyRef,
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CommonModule, DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { fromEvent, Subject } from 'rxjs'; import { fromEvent, Subject } from 'rxjs';
import { debounceTime, filter } from 'rxjs/operators'; import { debounceTime, filter } from 'rxjs/operators';
@ -25,7 +25,7 @@ import { ErrorScreenErrorCodes } from '../../models';
selector: 'abp-http-error-wrapper', selector: 'abp-http-error-wrapper',
templateUrl: './http-error-wrapper.component.html', templateUrl: './http-error-wrapper.component.html',
styleUrls: ['http-error-wrapper.component.scss'], styleUrls: ['http-error-wrapper.component.scss'],
imports: [CommonModule, LocalizationPipe], imports: [LocalizationPipe],
}) })
export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestroy { export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestroy {
protected readonly destroyRef = inject(DestroyRef); protected readonly destroyRef = inject(DestroyRef);

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

@ -1,4 +1,3 @@
import { NgClass, NgStyle } from '@angular/common';
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, inject } from '@angular/core';
import { combineLatest, Subscription, timer } from 'rxjs'; import { combineLatest, Subscription, timer } from 'rxjs';
import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core'; import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core';
@ -6,12 +5,12 @@ import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng
@Component({ @Component({
selector: 'abp-loader-bar', selector: 'abp-loader-bar',
template: ` template: `
<div id="abp-loader-bar" [ngClass]="containerClass" [class.is-loading]="isLoading"> <div id="abp-loader-bar" [class]="containerClass" [class.is-loading]="isLoading">
<div <div
class="abp-progress" class="abp-progress"
[class.progressing]="progressLevel" [class.progressing]="progressLevel"
[style.width.vw]="progressLevel" [style.width.vw]="progressLevel"
[ngStyle]="{ [style]="{
'background-color': color, 'background-color': color,
'box-shadow': boxShadow, 'box-shadow': boxShadow,
}" }"
@ -20,7 +19,7 @@ import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng
`, `,
styleUrls: ['./loader-bar.component.scss'], styleUrls: ['./loader-bar.component.scss'],
providers: [SubscriptionService], providers: [SubscriptionService],
imports: [NgClass, NgStyle], imports: [],
}) })
export class LoaderBarComponent implements OnDestroy, OnInit { export class LoaderBarComponent implements OnDestroy, OnInit {
private cdRef = inject(ChangeDetectorRef); private cdRef = inject(ChangeDetectorRef);

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

@ -10,7 +10,7 @@
<i <i
class="fa" class="fa"
aria-hidden="true" aria-hidden="true"
[ngClass]="{ [class]="{
'fa-eye-slash': !fieldTextType, 'fa-eye-slash': !fieldTextType,
'fa-eye': fieldTextType 'fa-eye': fieldTextType
}" }"

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

@ -1,6 +1,6 @@
import { Component, forwardRef, Input } from '@angular/core'; import { Component, forwardRef, Input } from '@angular/core';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NgClass } from '@angular/common';
import { AbstractNgModelComponent } from '@abp/ng.core'; import { AbstractNgModelComponent } from '@abp/ng.core';
import { NgxValidateCoreModule } from '@ngx-validate/core'; import { NgxValidateCoreModule } from '@ngx-validate/core';
@ -10,7 +10,7 @@ import { NgxValidateCoreModule } from '@ngx-validate/core';
*/ */
@Component({ @Component({
selector: 'abp-password', selector: 'abp-password',
imports: [NgClass, FormsModule, NgxValidateCoreModule], imports: [FormsModule, NgxValidateCoreModule],
templateUrl: `./password.component.html`, templateUrl: `./password.component.html`,
providers: [ providers: [
{ {

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

@ -1,19 +1,17 @@
<div class="abp-toast" [ngClass]="severityClass" (click)="tap()"> <div class="abp-toast" [class]="severityClass" (click)="tap()">
<div class="abp-toast-icon"> <div class="abp-toast-icon">
<i class="bi icon" [ngClass]="iconClass" aria-hidden="true"></i> <i class="bi icon" [class]="iconClass" aria-hidden="true"></i>
</div> </div>
<div class="abp-toast-content"> <div class="abp-toast-content">
@if (toast.options?.closable) { @if (toast.options?.closable) {
<button class="abp-toast-close-button" (click)="close()"> <button class="abp-toast-close-button" (click)="close()">
<i class="bi bi-x fs-4" aria-hidden="true"></i> <i class="bi bi-x fs-4" aria-hidden="true"></i>
</button> </button>
} }
<div class="abp-toast-title"> <div class="abp-toast-title">
{{ toast.title | abpLocalization: toast.options?.titleLocalizationParams }} {{ toast.title | abpLocalization: toast.options?.titleLocalizationParams }}
</div> </div>
<p <p class="abp-toast-message"
class="abp-toast-message" [innerHTML]="toast.message | abpLocalization: toast.options?.messageLocalizationParams"></p>
[innerHTML]="toast.message | abpLocalization: toast.options?.messageLocalizationParams"
></p>
</div> </div>
</div> </div>

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

@ -1,5 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { NgClass } from '@angular/common';
import { Toaster } from '../../models/toaster'; import { Toaster } from '../../models/toaster';
import { LocalizationPipe } from '@abp/ng.core'; import { LocalizationPipe } from '@abp/ng.core';
@ -7,7 +6,7 @@ import { LocalizationPipe } from '@abp/ng.core';
selector: 'abp-toast', selector: 'abp-toast',
templateUrl: './toast.component.html', templateUrl: './toast.component.html',
styleUrls: ['./toast.component.scss'], styleUrls: ['./toast.component.scss'],
imports: [NgClass, LocalizationPipe], imports: [LocalizationPipe],
}) })
export class ToastComponent implements OnInit { export class ToastComponent implements OnInit {
@Input() @Input()

74
templates/app-nolayers/angular/src/app/home/home.component.html

@ -9,14 +9,12 @@
Welcome to the application. This is a startup project based on the ABP framework. For Welcome to the application. This is a startup project based on the ABP framework. For
more information visit abp.io. more information visit abp.io.
</p> </p>
<a (click)="login()" class="px-4 btn btn-primary mb-4" role="button" <a (click)="login()" class="px-4 btn btn-primary mb-4" role="button"><i class="fa fa-sign-in"></i> {{
><i class="fa fa-sign-in"></i> {{ 'AbpAccount::Login' | abpLocalization }}</a 'AbpAccount::Login' | abpLocalization }}</a>
>
} }
<h3>Getting Started</h3> <h3>Getting Started</h3>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
startingContentTemplate; startingContentTemplate;
context: { context: {
$implicit: { $implicit: {
@ -26,12 +24,10 @@
label: 'Getting Started' label: 'Getting Started'
} }
} }
" "></ng-container>
></ng-container>
<h4>Web Application Development Tutorial</h4> <h4>Web Application Development Tutorial</h4>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
startingContentTemplate; startingContentTemplate;
context: { context: {
$implicit: { $implicit: {
@ -41,17 +37,12 @@
label: 'Explore Tutorial' label: 'Explore Tutorial'
} }
} }
" "></ng-container>
></ng-container>
<h4>Customize Lepton Theme</h4> <h4>Customize Lepton Theme</h4>
<p class="text-muted mb-2">Learn how to customize LeptonX Theme as you wish.</p> <p class="text-muted mb-2">Learn how to customize LeptonX Theme as you wish.</p>
<a <a href="https://docs.abp.io/en/abp/latest/UI/Angular/Theming" class="btn btn-primary soft mb-5 mb-xl-0"
href="https://docs.abp.io/en/abp/latest/UI/Angular/Theming" target="_blank">Customize Lepton</a>
class="btn btn-primary soft mb-5 mb-xl-0"
target="_blank"
>Customize Lepton</a
>
</div> </div>
<img class="card-bg-image" src="assets/images/getting-started/bg-01.png" /> <img class="card-bg-image" src="assets/images/getting-started/bg-01.png" />
@ -60,8 +51,7 @@
</div> </div>
<div class="col-xl-3 col-md-6 d-flex"> <div class="col-xl-3 col-md-6 d-flex">
<div class="row"> <div class="row">
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
visitLinkTemplate; visitLinkTemplate;
context: { context: {
$implicit: { $implicit: {
@ -75,10 +65,8 @@
logo: 'abp-support abp-logo mb-2' logo: 'abp-support abp-logo mb-2'
} }
} }
" "></ng-container>
></ng-container> <ng-container *ngTemplateOutlet="
<ng-container
*ngTemplateOutlet="
visitLinkTemplate; visitLinkTemplate;
context: { context: {
$implicit: { $implicit: {
@ -92,8 +80,7 @@
logo: 'abp-blog abp-logo mb-2' logo: 'abp-blog abp-logo mb-2'
} }
} }
" "></ng-container>
></ng-container>
</div> </div>
</div> </div>
<div class="col-xl-3 col-md-6 d-flex"> <div class="col-xl-3 col-md-6 d-flex">
@ -108,17 +95,14 @@
Explore all ABP users' experiences with the ABP Framework, discover articles and videos on Explore all ABP users' experiences with the ABP Framework, discover articles and videos on
how to use ABP, and join raffles for a chance to win surprise gifts! how to use ABP, and join raffles for a chance to win surprise gifts!
</p> </p>
<a class="btn btn-brand soft mb-3" href="https://community.abp.io/" target="_blank" <a class="btn btn-brand soft mb-3" href="https://community.abp.io/" target="_blank">Join ABP Community</a>
>Join ABP Community</a
>
</div> </div>
<img class="mt-3" src="assets/images/getting-started/img-community.png" /> <img class="mt-3" src="assets/images/getting-started/img-community.png" />
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
tableTemplate; tableTemplate;
context: { context: {
$implicit: { $implicit: {
@ -167,8 +151,7 @@
] ]
} }
} }
" "></ng-container>
></ng-container>
<div class="col-xl-6 col-lg-8 d-flex"> <div class="col-xl-6 col-lg-8 d-flex">
<div class="card"> <div class="card">
<div class="card-body d-flex"> <div class="card-body d-flex">
@ -181,18 +164,12 @@
understanding of the framework and modern web application development techniques. understanding of the framework and modern web application development techniques.
</p> </p>
<div class="d-md-flex mb-2 mb-md-0"> <div class="d-md-flex mb-2 mb-md-0">
<a <a href="https://www.amazon.com/gp/product/B097Z2DM8Q" target="_blank"
href="https://www.amazon.com/gp/product/B097Z2DM8Q" class="btn btn-primary soft me-md-2 mb-2 mb-md-0">
target="_blank"
class="btn btn-primary soft me-md-2 mb-2 mb-md-0"
>
Buy on Amazon US Buy on Amazon US
</a> </a>
<a <a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" target="_blank"
href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary soft mb-2 mb-md-0">
target="_blank"
class="btn btn-primary soft mb-2 mb-md-0"
>
Buy on PACKT Buy on PACKT
</a> </a>
</div> </div>
@ -204,8 +181,7 @@
</div> </div>
</div> </div>
</div> </div>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
tableTemplate; tableTemplate;
context: { context: {
$implicit: { $implicit: {
@ -243,8 +219,7 @@
] ]
} }
} }
" "></ng-container>
></ng-container>
</div> </div>
<ng-template #startingContentTemplate let-context> <ng-template #startingContentTemplate let-context>
@ -279,10 +254,7 @@
<tr> <tr>
<td class="ps-0 d-flex" [class.border-bottom-0]="last"> <td class="ps-0 d-flex" [class.border-bottom-0]="last">
@if(item.icon){ @if(item.icon){
<div <div [class]="item.iconClass" [style]="item.style ? 'width: 20px; height: 20px' : ''">
[ngClass]="item.iconClass"
[style]="item.style ? 'width: 20px; height: 20px' : ''"
>
@if(item.iconType === 'image'){ @if(item.iconType === 'image'){
<img [src]="item.icon" class="me-2" /> <img [src]="item.icon" class="me-2" />
}@else if(item.iconType === 'icon'){ }@else if(item.iconType === 'icon'){
@ -307,4 +279,4 @@
</div> </div>
</div> </div>
</div> </div>
</ng-template> </ng-template>

74
templates/app/angular/src/app/home/home.component.html

@ -9,14 +9,12 @@
<p class="lead text-muted mb-2"> <p class="lead text-muted mb-2">
{{ '::LongWelcomeMessage' | abpLocalization }} {{ '::LongWelcomeMessage' | abpLocalization }}
</p> </p>
<a (click)="login()" class="px-4 btn btn-primary mb-4" role="button" <a (click)="login()" class="px-4 btn btn-primary mb-4" role="button"><i class="fa fa-sign-in"></i> {{
><i class="fa fa-sign-in"></i> {{ 'AbpAccount::Login' | abpLocalization }}</a 'AbpAccount::Login' | abpLocalization }}</a>
>
} }
<h3>Getting Started</h3> <h3>Getting Started</h3>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
startingContentTemplate; startingContentTemplate;
context: { context: {
$implicit: { $implicit: {
@ -26,12 +24,10 @@
label: 'Getting Started' label: 'Getting Started'
} }
} }
" "></ng-container>
></ng-container>
<h4>Web Application Development Tutorial</h4> <h4>Web Application Development Tutorial</h4>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
startingContentTemplate; startingContentTemplate;
context: { context: {
$implicit: { $implicit: {
@ -41,17 +37,12 @@
label: 'Explore Tutorial' label: 'Explore Tutorial'
} }
} }
" "></ng-container>
></ng-container>
<h4>Customize Lepton Theme</h4> <h4>Customize Lepton Theme</h4>
<p class="text-muted mb-2">Learn how to customize LeptonX Theme as you wish.</p> <p class="text-muted mb-2">Learn how to customize LeptonX Theme as you wish.</p>
<a <a href="https://abp.io/docs/latest/framework/ui/angular/theming" class="btn btn-primary soft mb-5 mb-xl-0"
href="https://abp.io/docs/latest/framework/ui/angular/theming" target="_blank">Customize Lepton</a>
class="btn btn-primary soft mb-5 mb-xl-0"
target="_blank"
>Customize Lepton</a
>
</div> </div>
<img class="card-bg-image" src="assets/images/getting-started/bg-01.png" /> <img class="card-bg-image" src="assets/images/getting-started/bg-01.png" />
@ -60,8 +51,7 @@
</div> </div>
<div class="col-xl-3 col-md-6 d-flex"> <div class="col-xl-3 col-md-6 d-flex">
<div class="row"> <div class="row">
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
visitLinkTemplate; visitLinkTemplate;
context: { context: {
$implicit: { $implicit: {
@ -75,10 +65,8 @@
logo: 'abp-support abp-logo mb-2' logo: 'abp-support abp-logo mb-2'
} }
} }
" "></ng-container>
></ng-container> <ng-container *ngTemplateOutlet="
<ng-container
*ngTemplateOutlet="
visitLinkTemplate; visitLinkTemplate;
context: { context: {
$implicit: { $implicit: {
@ -92,8 +80,7 @@
logo: 'abp-blog abp-logo mb-2' logo: 'abp-blog abp-logo mb-2'
} }
} }
" "></ng-container>
></ng-container>
</div> </div>
</div> </div>
<div class="col-xl-3 col-md-6 d-flex"> <div class="col-xl-3 col-md-6 d-flex">
@ -108,17 +95,14 @@
Explore all ABP users' experiences with the ABP Framework, discover articles and videos on Explore all ABP users' experiences with the ABP Framework, discover articles and videos on
how to use ABP, and join raffles for a chance to win surprise gifts! how to use ABP, and join raffles for a chance to win surprise gifts!
</p> </p>
<a class="btn btn-brand soft mb-3" href="https://abp.io/community/" target="_blank" <a class="btn btn-brand soft mb-3" href="https://abp.io/community/" target="_blank">Join ABP Community</a>
>Join ABP Community</a
>
</div> </div>
<img class="mt-3" src="assets/images/getting-started/img-community.png" /> <img class="mt-3" src="assets/images/getting-started/img-community.png" />
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
tableTemplate; tableTemplate;
context: { context: {
$implicit: { $implicit: {
@ -167,8 +151,7 @@
] ]
} }
} }
" "></ng-container>
></ng-container>
<div class="col-xl-6 col-lg-8 d-flex"> <div class="col-xl-6 col-lg-8 d-flex">
<div class="card"> <div class="card">
<div class="card-body d-flex"> <div class="card-body d-flex">
@ -181,18 +164,12 @@
understanding of the framework and modern web application development techniques. understanding of the framework and modern web application development techniques.
</p> </p>
<div class="d-md-flex mb-2 mb-md-0"> <div class="d-md-flex mb-2 mb-md-0">
<a <a href="https://www.amazon.com/gp/product/B097Z2DM8Q" target="_blank"
href="https://www.amazon.com/gp/product/B097Z2DM8Q" class="btn btn-primary soft me-md-2 mb-2 mb-md-0">
target="_blank"
class="btn btn-primary soft me-md-2 mb-2 mb-md-0"
>
Buy on Amazon US Buy on Amazon US
</a> </a>
<a <a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" target="_blank"
href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary soft mb-2 mb-md-0">
target="_blank"
class="btn btn-primary soft mb-2 mb-md-0"
>
Buy on PACKT Buy on PACKT
</a> </a>
</div> </div>
@ -204,8 +181,7 @@
</div> </div>
</div> </div>
</div> </div>
<ng-container <ng-container *ngTemplateOutlet="
*ngTemplateOutlet="
tableTemplate; tableTemplate;
context: { context: {
$implicit: { $implicit: {
@ -243,8 +219,7 @@
] ]
} }
} }
" "></ng-container>
></ng-container>
</div> </div>
<ng-template #startingContentTemplate let-context> <ng-template #startingContentTemplate let-context>
@ -279,10 +254,7 @@
<tr> <tr>
<td class="ps-0 d-flex" [class.border-bottom-0]="last"> <td class="ps-0 d-flex" [class.border-bottom-0]="last">
@if(item.icon){ @if(item.icon){
<div <div [class]="item.iconClass" [style]="item.style ? 'width: 20px; height: 20px' : ''">
[ngClass]="item.iconClass"
[style]="item.style ? 'width: 20px; height: 20px' : ''"
>
@if(item.iconType === 'image'){ @if(item.iconType === 'image'){
<img [src]="item.icon" class="me-2" /> <img [src]="item.icon" class="me-2" />
}@else if(item.iconType === 'icon'){ }@else if(item.iconType === 'icon'){
@ -307,4 +279,4 @@
</div> </div>
</div> </div>
</div> </div>
</ng-template> </ng-template>
Loading…
Cancel
Save